import assert from 'node:assert/strict' import crypto from 'node:crypto' import fs from 'node:fs/promises' import path from 'node:path' import React from 'react' import { renderToStaticMarkup } from 'react-dom/server' import { fileURLToPath, pathToFileURL } from 'node:url' const here = path.dirname(fileURLToPath(import.meta.url)) const recoveredDirectory = path.resolve(here, '../../src/renderer/src/workbuddy/artifacts/recovered-pierre') const manifest = JSON.parse(await fs.readFile(path.join(recoveredDirectory, 'manifest.json'), 'utf8')) assert.equal(manifest.target.name, '@genie/workbuddy-desktop') assert.equal(manifest.target.version, '5.8.2') assert.equal(manifest.target.root_sha256, '035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918') assert.ok(!manifest.renderer_source.imports.includes('./src-0FGg1seX.js')) assert.ok(!manifest.renderer_source.imports.includes('./monaco-init-CE4MbM4x.js')) assert.ok(manifest.renderer_source.closure_program_bindings >= 700) assert.equal(manifest.renderer_source.dynamic_import_count, 311) assert.equal(manifest.renderer_source.dynamic_import_files.length, 311) assert.equal(manifest.evidence.dynamic_chunks.length, 20) const availableAssets = new Set(manifest.assets.map((asset) => asset.path)) for (const dynamicPath of manifest.renderer_source.dynamic_import_files) { assert.ok(availableAssets.has(path.basename(dynamicPath)), `missing selected dynamic chunk: ${dynamicPath}`) } for (const output of manifest.outputs) { const bytes = await fs.readFile(path.join(recoveredDirectory, output.path)) assert.equal(bytes.length, output.bytes, `${output.path} byte count`) assert.equal(crypto.createHash('sha256').update(bytes).digest('hex'), output.sha256, `${output.path} SHA-256`) } const { buildFileDiff, parseDiffFromFile, processFile, PierreDiffEditor, getFiletypeFromFileName, } = await import(pathToFileURL(path.join(recoveredDirectory, 'engine.mjs')).href) assert.equal(typeof buildFileDiff, 'function') assert.equal(typeof parseDiffFromFile, 'function') assert.equal(typeof processFile, 'function') assert.ok(PierreDiffEditor) assert.equal(getFiletypeFromFileName('sample.ts'), 'typescript') const oldText = 'const value = 1;\n' const newText = 'const value = 2;\n' const fileDiff = buildFileDiff({ oldFile: { name: 'sample.ts', contents: oldText, lang: 'typescript' }, newFile: { name: 'sample.ts', contents: newText, lang: 'typescript' }, }) assert.equal(fileDiff.type, 'change') assert.equal(fileDiff.hunks.length, 1) assert.deepEqual(fileDiff.deletionLines, ['const value = 1;\n']) assert.deepEqual(fileDiff.additionLines, ['const value = 2;\n']) const unified = '--- a/sample.ts\n+++ b/sample.ts\n@@ -1 +1 @@\n-const value = 1;\n+const value = 2;\n' const parsedUnified = processFile(unified, { oldFile: { name: 'sample.ts', contents: oldText }, newFile: { name: 'sample.ts', contents: newText }, }) assert.equal(parsedUnified?.hunks.length, 1) const parsedFiles = parseDiffFromFile( { name: 'sample.ts', contents: oldText, lang: 'typescript' }, { name: 'sample.ts', contents: newText, lang: 'typescript' }, ) assert.equal(parsedFiles.hunks.length, 1) globalThis.document = { documentElement: {} } globalThis.getComputedStyle = () => ({ getPropertyValue: () => '' }) const markup = renderToStaticMarkup(React.createElement(PierreDiffEditor, { original: oldText, modified: newText, fileName: 'sample.ts', language: 'typescript', currentTheme: 'light', defaultDiffMode: 'split', })) assert.match(markup, /_pierre-diff-editor_4ij9v_5/u) assert.match(markup, /id="diffs-icon-diff-split"/u) assert.match(markup, /id="diffs-icon-diff-unified"/u) const stylesheet = await fs.readFile(path.join(recoveredDirectory, 'engine.css'), 'utf8') assert.match(stylesheet, /_pierre-diff-editor_4ij9v_5/u) assert.match(stylesheet, /_pierre-diff-editor__mode-btn_4ij9v_21/u) const worker = await fs.readFile(path.join(recoveredDirectory, 'worker-portable-D1lwTqsk.js'), 'utf8') assert.match(worker, /createJavaScriptRegexEngine/u) assert.match(worker, /shiki-wasm/u) console.log('Recovered Pierre diff regression passed: REA Evidence locks, complete dynamic chunk closure, YCode React binding, parser fixtures, SSR component shell, exact CSS module rules, and JS worker fallback.')