import { createRequire } from 'node:module'; import { mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, rmSync, writeFileSync, } from 'node:fs'; import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { performance } from 'node:perf_hooks'; import { afterEach, beforeEach, describe, expect, it } from 'vitest'; import { ensureBundledCourseSkills, ensureBundledSuperpowersPlugin, } from '@electron/opencode/superpowers'; const require = createRequire(import.meta.url); const describeWindows = process.platform === 'win32' ? describe : describe.skip; const chineseUsername = '\u5362\u6b22'; function writeFixtureFile(filePath: string, content: string): void { mkdirSync(dirname(filePath), { recursive: true }); writeFileSync(filePath, content, 'utf8'); } function createFixture() { const root = mkdtempSync(join(tmpdir(), 'niancode-electron-unicode-')); const sources = join(root, 'sources'); const superpowers = join(sources, 'superpowers'); const courseSkills = join(sources, 'course-skills'); const managedConfigDir = join( root, chineseUsername, 'AppData', 'Roaming', 'niancode', 'opencode', 'niancode-config', ); writeFixtureFile( join(superpowers, 'package.json'), `${JSON.stringify({ name: 'superpowers', version: '5.0.7' })}\n`, ); writeFixtureFile( join(superpowers, '.opencode', 'plugins', 'superpowers.js'), 'export const SuperpowersPlugin = async () => ({});\n', ); writeFixtureFile( join(superpowers, 'skills', 'using-superpowers', 'SKILL.md'), '---\nname: using-superpowers\n---\n', ); writeFixtureFile( join(courseSkills, 'pm-project-plan', 'SKILL.md'), '---\nname: pm-project-plan\n---\n', ); writeFixtureFile( join(courseSkills, 'pm-project-plan', 'references', 'guide.md'), '# planning guide\n', ); return { root, managedConfigDir, superpowers, courseSkills, rootEntriesBeforeCopy: readdirSync(root).sort(), }; } function expectNoUnexpectedRootEntries(fixture: ReturnType): void { expect(readdirSync(fixture.root).sort()).toEqual([ ...fixture.rootEntriesBeforeCopy, chineseUsername, ].sort()); } function median(values: number[]): number { const sorted = [...values].sort((left, right) => left - right); return sorted[Math.floor(sorted.length / 2)]; } describeWindows('Windows Unicode runtime directory copies', () => { let fixture: ReturnType; beforeEach(() => { fixture = createFixture(); }); afterEach(() => { rmSync(fixture.root, { recursive: true, force: true, maxRetries: 3, retryDelay: 50, }); }); it('runs under this project local Electron runtime', () => { const localElectronExecutable = require('electron'); const localElectronPackage = JSON.parse(readFileSync( require.resolve('electron/package.json'), 'utf8', )); console.info(`[electron-runtime] ${JSON.stringify({ execPath: process.execPath, electron: process.versions.electron, node: process.versions.node, })}`); expect(process.platform).toBe('win32'); expect(process.env.ELECTRON_RUN_AS_NODE).toBe('1'); expect(process.versions.electron).toBeDefined(); expect(realpathSync(process.execPath)).toBe(realpathSync(localElectronExecutable)); expect(process.versions.electron).toBe(localElectronPackage.version); expect(process.versions.electron).toBe(process.env.NIANCODE_LOCAL_ELECTRON_VERSION); if (process.env.NIANCODE_VERIFY_RELEASE_RUNTIME === '1') { expect(process.versions.electron).toBe('40.10.6'); expect(process.versions.node).toBe('24.15.0'); } }); it('installs and reuses Superpowers below a Chinese user path', () => { expect(ensureBundledSuperpowersPlugin({ managedConfigDir: fixture.managedConfigDir, sourceDir: fixture.superpowers, })).toBe(true); const installedSkill = join( fixture.managedConfigDir, 'superpowers-bundles', '5.0.7', 'skills', 'using-superpowers', 'SKILL.md', ); expect(readFileSync(installedSkill, 'utf8')).toBe( readFileSync(join(fixture.superpowers, 'skills', 'using-superpowers', 'SKILL.md'), 'utf8'), ); expect(JSON.parse(readFileSync( join(fixture.managedConfigDir, 'superpowers-active.json'), 'utf8', ))).toEqual({ version: '5.0.7', directory: '5.0.7' }); expect(readFileSync( join(fixture.managedConfigDir, 'plugins', 'superpowers-niancode.js'), 'utf8', )).toContain('../superpowers-bundles/5.0.7/.opencode/plugins/superpowers.js'); expect(readdirSync(join( fixture.managedConfigDir, 'superpowers-bundles', )).sort()).toEqual(['5.0.7']); const reuseMarker = join( fixture.managedConfigDir, 'superpowers-bundles', '5.0.7', 'reuse-marker.txt', ); writeFileSync(reuseMarker, 'preserve-me', 'utf8'); expect(ensureBundledSuperpowersPlugin({ managedConfigDir: fixture.managedConfigDir, sourceDir: fixture.superpowers, })).toBe(true); expect(readFileSync(reuseMarker, 'utf8')).toBe('preserve-me'); expect(readdirSync(join( fixture.managedConfigDir, 'superpowers-bundles', )).sort()).toEqual(['5.0.7']); expectNoUnexpectedRootEntries(fixture); }); it('copies course Skills below a Chinese user path twice', () => { const unrelatedSkill = join( fixture.managedConfigDir, 'skills', 'user-owned-skill', 'SKILL.md', ); writeFixtureFile(unrelatedSkill, 'preserve-user-owned-skill\n'); expect(ensureBundledCourseSkills({ managedConfigDir: fixture.managedConfigDir, sourceDir: fixture.courseSkills, })).toBe(true); writeFixtureFile( join(fixture.courseSkills, 'pm-project-plan', 'references', 'guide.md'), '# updated planning guide\n', ); expect(ensureBundledCourseSkills({ managedConfigDir: fixture.managedConfigDir, sourceDir: fixture.courseSkills, })).toBe(true); expect(readFileSync( join(fixture.managedConfigDir, 'skills', 'pm-project-plan', 'references', 'guide.md'), 'utf8', )).toBe('# updated planning guide\n'); expect(readFileSync(unrelatedSkill, 'utf8')).toBe('preserve-user-owned-skill\n'); expectNoUnexpectedRootEntries(fixture); }); it('reports course copy timing without a brittle CI threshold', () => { const skillTimes: number[] = []; const actualSkills = join(process.cwd(), '.opencode', 'skills'); for (let run = 0; run < 7; run += 1) { const managedConfigDir = join( fixture.root, chineseUsername, 'performance', String(run), 'niancode-config', ); const skillStart = performance.now(); ensureBundledCourseSkills({ managedConfigDir, sourceDir: actualSkills }); skillTimes.push(performance.now() - skillStart); } const evidence = { skills: { medianMs: median(skillTimes), maxMs: Math.max(...skillTimes) }, }; console.info(`[runtime-copy-performance] ${JSON.stringify(evidence)}`); expect(evidence.skills.maxMs).toBeGreaterThanOrEqual(evidence.skills.medianMs); }); });