// A project in its document and back, for every file of the corpus: written // into a document, sent as Yjs sends it (an update into a second document) // and read back, it is the same project — the same snapshot for the core, // the same .fls on export, each folder's files in the same order. import { readdirSync, readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { describe, expect, it } from 'vitest'; import * as Y from 'yjs'; import type { VirtualFileSystem } from '@mdg-filius/core'; import { openProjectArchive, projectSnapshot, saveProjectArchive, type ImportedProject } from '@mdg-filius/fls'; import { docArchive, docSnapshot, readProject, ROOTS, SCHEMA_VERSION, writeProject } from '../src/index.js'; const corpus = join(dirname(fileURLToPath(import.meta.url)), '../../../corpus'); const files = ['java-examples', 'java-tests', 'ipad-fixtures'].flatMap((folder) => readdirSync(join(corpus, folder)) .filter((name) => name.endsWith('.fls')) .map((name) => join(folder, name)), ); /** Ids that fall in the file's reverse order: the document must keep the order itself, not by its ids. */ function opened(file: string): ImportedProject { let counter = 0; return openProjectArchive(new Uint8Array(readFileSync(join(corpus, file))), () => `00000000-0000-0000-0000-${(0xffff_ffff - ++counter).toString(16).padStart(12, '0')}`); } /** The document as another client gets it: its whole state as one update. */ function sent(doc: Y.Doc): Y.Doc { const other = new Y.Doc(); Y.applyUpdate(other, Y.encodeStateAsUpdate(doc)); return other; } /** Every folder's entries in the order they were made. */ function creationOrder(files: VirtualFileSystem): string[] { const paths: string[] = []; const walk = (folder: string): void => { for (const entry of files.entriesInCreationOrder(folder)) { paths.push(entry.path); if (entry.content.kind === 'directory') walk(entry.path); } }; walk('/'); return paths; } describe('a project in its document and back', () => { it('reads the whole corpus', () => { expect(files.length).toBe(23); }); for (const file of files) { it(file, () => { const project = opened(file); const doc = new Y.Doc(); writeProject(doc, project); expect(doc.getMap(ROOTS.meta).get('schema')).toBe(SCHEMA_VERSION); const received = sent(doc); const back = readProject(received); expect({ ...back, warnings: [] }).toEqual({ ...project, warnings: [] }); for (const [nodeId, fileSystem] of project.virtualFileSystems) { expect(creationOrder(back.virtualFileSystems.get(nodeId)!), nodeId).toEqual(creationOrder(fileSystem)); } expect(docSnapshot(received)).toEqual(projectSnapshot(project)); expect(docArchive(received).archive).toEqual(saveProjectArchive(project).archive); }); } });