UNPKG

@timothy-spaceman/multitrack-vcs

Version:

Version Control System for musicians

371 lines (304 loc) 11.1 kB
import path from "node:path" import * as process from "process" import {CONTENT_DIR, FsStorageProvider, Project, PROJECT_DIR, VirtualStorageProvider} from "../src/index.js" let uuidCounter = 0 jest.mock("crypto", () => { const actualCrypto = jest.requireActual("crypto") return { ...actualCrypto, randomUUID: jest.fn(() => `test-uuid-${uuidCounter++}`), } }) const tmp = "tests-tmp" const sp = new FsStorageProvider() VirtualStorageProvider.separator = "\\" const getProjectFile = async () => { const projectFile = await sp.readFile(path.join(PROJECT_DIR, "project.json")) const fileContent = (await projectFile.readData()).toString() return JSON.parse(fileContent) } const getFileContent = async (filePath: string) => { const file = await sp.readFile(filePath) const fileData = await file.readData() return fileData.toString() } const shiftTime = function (ms: number) { const d = new Date() d.setMilliseconds(ms) jest.setSystemTime(d) } const clearTmp = async () => { const files = await sp.readDir(".") for (const file of files) { await sp.deleteFileOrDir(file) } } beforeAll(async () => { jest .useFakeTimers() .setSystemTime(new Date("2025-01-01T00:00:00.000Z")) if (path.basename(process.cwd()) != tmp) { if (!await sp.exists(tmp)) { await sp.createDir(tmp) } process.chdir(tmp) } await clearTmp() }) describe("Commits", () => { let project: Project beforeAll(async () => { uuidCounter = 1 project = await Project.create( sp, ".", "JEST", "JEST_PROJECT", ) }) afterAll(async () => { await clearTmp() }) test("Initial", async () => { const commitId = "test-uuid-4" const contentPath = "test-uuid-3" const itemId = "test-uuid-2" await sp.createFile("file1.txt", Buffer.from("First line ever")) await project.commit( await sp.readDirDeep(".", [".mvcs"]), "JEST", "Initial Commit", "First commit in this project" ) await project.save() expect(project.currentCommitId).toBe(commitId) expect(project.commits.get(commitId)).toMatchObject({ "id": commitId, "children": [], "authorId": "JEST", "title": "Initial Commit", "description": "First commit in this project", "date": "2025-01-01T00:00:00.000Z", "changes": [ { "to": itemId } ] }) expect(project.items.get(itemId)).toMatchObject({ "id": itemId, "content": contentPath, "path": "file1.txt" }) expect(await getFileContent(path.join(PROJECT_DIR, CONTENT_DIR, contentPath))).toBe("First line ever") shiftTime(5000) }) test("Changes", async () => { const previousItemId = "test-uuid-2" const newItemId = "test-uuid-5" const newContentId = "test-uuid-6" const newCommitId = "test-uuid-7" const parentCommitId = "test-uuid-4" const file = await sp.readFile("file1.txt") await file.writeData(Buffer.from("First line ever\nSecond line")) await project.commit( await sp.readDirDeep(".", [".mvcs"]), "JEST", "Modified file1.txt", ) await project.save() expect(project.currentCommitId).toBe(newCommitId) expect(project.commits.get(newCommitId)).toMatchObject({ id: newCommitId, parent: parentCommitId, children: [], authorId: "JEST", title: "Modified file1.txt", description: "", date: "2025-01-01T00:00:05.000Z", changes: [{from: previousItemId, to: newItemId}] }) expect(project.items.get(newItemId)).toMatchObject({ id: newItemId, content: newContentId, path: "file1.txt" }) expect(await getFileContent(path.join(PROJECT_DIR, CONTENT_DIR, newContentId))) .toBe("First line ever\nSecond line") shiftTime(5000) }) test("Subdirs", async () => { const newItemId = "test-uuid-9" const newContentId = "test-uuid-10" const newCommitId = "test-uuid-11" const parentCommitId = "test-uuid-7" await sp.createFile("subdir1/file2.txt", Buffer.from("First file in subdir1")) await project.commit( await sp.readDirDeep(".", [".mvcs"]), "JEST", "Added subdir1" ) await project.save() expect(project.currentCommitId).toBe(newCommitId) expect(project.commits.get(newCommitId)).toMatchObject({ id: newCommitId, parent: parentCommitId, children: [], authorId: "JEST", title: "Added subdir1", description: "", date: "2025-01-01T00:00:10.000Z", changes: [{to: newItemId}] }) expect(project.items.get(newItemId)).toMatchObject({ id: newItemId, content: newContentId, path: "subdir1\\file2.txt" }) expect(await getFileContent(path.join(PROJECT_DIR, CONTENT_DIR, newContentId))) .toBe("First file in subdir1") shiftTime(5000) }) test("Renamed/Moved Files", async () => { const oldItemId = "test-uuid-5" const newItemId = "test-uuid-14" const newContentId = "test-uuid-6" const newCommitId = "test-uuid-15" const parentCommitId = "test-uuid-11" const prevFilesState = await sp.readDirDeep(".", [".mvcs"]) await sp.moveFile("file1.txt", "subdir1/file1.txt") const newFilesState = await sp.readDirDeep(".", [".mvcs"]) await project.commit( [...prevFilesState, ...newFilesState], "JEST", "Moved file1 into subdir1" ) await project.save() expect(project.currentCommitId).toBe(newCommitId) expect(project.commits.get(newCommitId)).toMatchObject({ id: newCommitId, parent: parentCommitId, children: [], authorId: "JEST", title: "Moved file1 into subdir1", description: "", date: "2025-01-01T00:00:15.000Z", changes: [{from: oldItemId}, {to: newItemId}] }) expect(project.items.get(newItemId)).toMatchObject({ id: newItemId, content: newContentId, path: "subdir1\\file1.txt" }) shiftTime(5000) }) test("Copies", async () => { const newItemId = "test-uuid-16" const newContentId = "test-uuid-6" const newCommitId = "test-uuid-19" const parentCommitId = "test-uuid-15" await sp.copyFile("subdir1/file1.txt", "file1-copy.txt") await project.commit( await sp.readDirDeep(".", [".mvcs"]), "JEST", "Copied file1" ) await project.save() expect(project.currentCommitId).toBe(newCommitId) expect(project.commits.get(newCommitId)).toMatchObject({ id: newCommitId, parent: parentCommitId, children: [], authorId: "JEST", title: "Copied file1", description: "", date: "2025-01-01T00:00:20.000Z", changes: [{to: newItemId}] }) expect(project.items.get(newItemId)).toMatchObject({ id: newItemId, content: newContentId, path: "file1-copy.txt" }) shiftTime(5000) }) test("Deletions", async () => { const deletedItem1 = "test-uuid-9" const deletedItem2 = "test-uuid-14" const newCommitId = "test-uuid-21" const parentCommitId = "test-uuid-19" const filesToCommit = await sp.readDirDeep(".", [".mvcs"]) await sp.deleteFileOrDir("subdir1") await project.commit( filesToCommit, "JEST", "Removed subdir1" ) await project.save() expect(project.currentCommitId).toBe(newCommitId) expect(project.commits.get(newCommitId)).toMatchObject({ id: newCommitId, parent: parentCommitId, children: [], authorId: "JEST", title: "Removed subdir1", description: "", date: "2025-01-01T00:00:25.000Z", changes: [ {from: deletedItem1}, {from: deletedItem2} ] }) }) test("Checkout", async () => { interface CheckoutTestCase { id: string, filesList: string[], filesToCheck: { [fileName: string]: string }, } const verifyCheckout = async ({id, filesList, filesToCheck}: CheckoutTestCase) => { await project.checkout(id) expect(await sp.readDirDeep(".")).toEqual(expect.arrayContaining(filesList)) for (const [filePath, content] of Object.entries(filesToCheck)) { expect(await getFileContent(filePath)).toBe(content) } } const testCases: CheckoutTestCase[] = [ { id: "test-uuid-4", filesList: ["file1.txt", ".mvcs"], filesToCheck: { "file1.txt": "First line ever", } }, { id: "test-uuid-11", filesList: ["file1.txt", "subdir1", "subdir1\\file2.txt", ".mvcs"], filesToCheck: { "file1.txt": "First line ever\nSecond line", "subdir1\\file2.txt": "First file in subdir1" } }, { id: "test-uuid-21", filesList: ["file1-copy.txt", "subdir1", ".mvcs"], filesToCheck: { "file1-copy.txt": "First line ever\nSecond line" } }, { id: "test-uuid-15", filesList: ["subdir1", "subdir1\\file1.txt", "subdir1\\file2.txt", ".mvcs"], filesToCheck: { "subdir1\\file1.txt": "First line ever\nSecond line", "subdir1\\file2.txt": "First file in subdir1" } } ] for (const testCase of testCases) { await verifyCheckout(testCase) } }) })