From d62a48d7bd76aa6cef4d9df96ff8efbe774879c3 Mon Sep 17 00:00:00 2001 From: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Date: Fri, 13 Nov 2026 08:35:35 -0800 Subject: [PATCH] test: remove low-value localization and mobile test coverage --- .../scripts/ci/sharding/ci-shard-timings.json | 8 -- ...windows-pty-table-stress-observer.test.mjs | 43 ++---- .../install-electron-package-binary.test.mjs | 115 +-------------- .../shared-electron-dist-cache.test.ts | 131 ------------------ .../locale-brand-prefilter.test.mjs | 55 -------- .../locale-generic-ui-terms.test.mjs | 125 ----------------- ...ale-repair-catalog-missing-leaves.test.mjs | 12 +- .../locale-translation-policy.es-pr.test.mjs | 34 ----- .../locale-translation-policy.test.mjs | 22 --- .../protected-copy-keys.test.mjs | 40 +----- .../verify-localization-catalog.test.mjs | 24 ---- .../verify-localization-catalogs.test.mjs | 50 ------- ...audit-localization-native-dialogs.test.mjs | 27 +--- .../verify-localization-extraction.test.mjs | 55 -------- .../macos-terminal-host-bundle.test.mjs | 81 +---------- .../mobile-web-app-route-manifest.test.mjs | 105 +------------- .../mobile-web-app-route-snapshot.test.mjs | 33 ----- ...obile-web-app-html-preview-render.test.mjs | 13 -- ...bile-web-app-media-preview-render.test.mjs | 20 +-- .../mobile-web-app-mermaid-render.test.mjs | 33 ----- 20 files changed, 21 insertions(+), 1005 deletions(-) delete mode 100644 config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.test.ts delete mode 100644 config/scripts/locale-catalog/locale-brand-prefilter.test.mjs delete mode 100644 config/scripts/locale-catalog/locale-generic-ui-terms.test.mjs delete mode 100644 config/scripts/locale-catalog/locale-translation-policy.es-pr.test.mjs delete mode 100644 config/scripts/locale-catalog/locale-translation-policy.test.mjs delete mode 100644 config/scripts/localization/catalog-validation/verify-localization-catalogs.test.mjs delete mode 100644 config/scripts/localization/source-extraction/verify-localization-extraction.test.mjs delete mode 100644 config/scripts/mobile-web-app/mobile-web-app-route-snapshot.test.mjs diff --git a/config/scripts/ci/sharding/ci-shard-timings.json b/config/scripts/ci/sharding/ci-shard-timings.json index 0ceb948e2b6..ffa0250c9b6 100644 --- a/config/scripts/ci/sharding/ci-shard-timings.json +++ b/config/scripts/ci/sharding/ci-shard-timings.json @@ -94,11 +94,7 @@ "config/scripts/diagnostics/lag-capture/lag-probe-failures.test.mjs": 55, "config/scripts/dependency-security/runtime-resolution/linear-sdk-runtime.test.mjs": 773, "config/scripts/preflight/changed-checks/lint-staged-worktree-backup.test.mjs": 278, - "config/scripts/locale-catalog/locale-brand-prefilter.test.mjs": 246, - "config/scripts/locale-catalog/locale-generic-ui-terms.test.mjs": 102, "config/scripts/locale-catalog/locale-repair-catalog-missing-leaves.test.mjs": 159, - "config/scripts/locale-catalog/locale-translation-policy.es-pr.test.mjs": 91, - "config/scripts/locale-catalog/locale-translation-policy.test.mjs": 189, "config/scripts/localization/source-extraction/localization-extraction-call-syntax.test.mjs": 317, "config/scripts/localization/extraction-policy/localization-extraction-change-scope.test.mjs": 732, "config/scripts/performance/macos-computer-owner/macos-computer-helper-owner-loss-processes.test.mjs": 52, @@ -130,7 +126,6 @@ "config/scripts/mobile-web-app/shell/mobile-web-app-render.test.mjs": 254, "config/scripts/mobile-web-app/session/mobile-web-app-rich-markdown-render.test.mjs": 356, "config/scripts/mobile-web-app/mobile-web-app-route-manifest.test.mjs": 174, - "config/scripts/mobile-web-app/mobile-web-app-route-snapshot.test.mjs": 121, "config/scripts/mobile-web-app/shell/mobile-web-app-safe-area-render.test.mjs": 314, "config/scripts/mobile-web-app/session/mobile-web-app-screencast-lane-grant.test.mjs": 70, "config/scripts/mobile-web-app/session/mobile-web-app-session-dictation-capture.test.mjs": 123, @@ -230,7 +225,6 @@ "config/scripts/tool-invocation/script-entry-detection.test.mjs": 107, "config/scripts/test-fixtures/script-copy-closure/script-module-dependencies.test.mjs": 62, "config/scripts/ci/workflow-contracts/setup-pnpm-action.test.mjs": 421, - "config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.test.ts": 140, "config/scripts/native-build/node-addons/shared-native-build.test.mjs": 127, "config/scripts/artifact-storage/atomic-publication/shared-tree-publish.test.mjs": 63, "config/scripts/desktop-distribution/macos/sign-mac-app.test.mjs": 268, @@ -246,8 +240,6 @@ "config/scripts/desktop-distribution/channel-policy/verify-dev-channel-packaging.test.mjs": 213, "config/scripts/native-build/linux/verify-linux-glibc-floor.test.mjs": 156, "config/scripts/localization/catalog-validation/verify-localization-catalog.test.mjs": 422, - "config/scripts/localization/catalog-validation/verify-localization-catalogs.test.mjs": 1574, - "config/scripts/localization/source-extraction/verify-localization-extraction.test.mjs": 233, "config/scripts/desktop-distribution/runtime-verification/verify-packaged-mobile-web-bundle.test.mjs": 214, "config/scripts/desktop-distribution/runtime-verification/verify-packaged-node-pty-job-ownership.test.mjs": 93, "config/scripts/orcad-distribution/template/verify-packaged-orcad-template.test.mjs": 454, diff --git a/config/scripts/diagnostics/windows-pty/windows-pty-table-stress-observer.test.mjs b/config/scripts/diagnostics/windows-pty/windows-pty-table-stress-observer.test.mjs index b557887dc59..73faeda0e98 100644 --- a/config/scripts/diagnostics/windows-pty/windows-pty-table-stress-observer.test.mjs +++ b/config/scripts/diagnostics/windows-pty/windows-pty-table-stress-observer.test.mjs @@ -1,45 +1,20 @@ -import { rmSync } from 'node:fs' -import { afterEach, describe, expect, it } from 'vitest' +import { describe, expect, it } from 'vitest' import { sanitizeStressText } from './windows-pty-table-stress-observer.mjs' -const directories = [] -afterEach(() => { - for (const directory of directories.splice(0)) { - rmSync(directory, { recursive: true, force: true }) - } -}) - describe('Windows PTY stress observer', () => { - it('preserves OSC boundaries while redacting their title payload and adjacent CSI text', () => { + it('redacts a key interrupted by adjacent controls without moving their bytes', () => { const esc = String.fromCharCode(27) - const raw = `${esc}]0;private@sensitive.test${esc}\\${esc}[31mprivate@sensitive.test` + const before = 'sk-secret01' + const after = '234567890abcdefghijkl' + const controls = `${esc}[31m${esc}[1m` + const raw = `${before}${controls}${after}` const sanitized = sanitizeStressText(raw) - expect(sanitized).not.toContain('private@') - expect(sanitized).not.toContain('sensitive.test') - expect(sanitized).toContain(`${esc}]0;`) - expect(sanitized).toContain(`${esc}\\${esc}[31m`) + expect(sanitized).not.toContain(before) + expect(sanitized).not.toContain(after) + expect(sanitized.slice(before.length, before.length + controls.length)).toBe(controls) expect(sanitized.length).toBe(raw.length) }) - it.each([ - ['email domain', 'private@', 'sensitive.test', ['[31m']], - ['email name', 'pri', 'vate@sensitive.test', ['[31m', '[1m']], - ['vendor key', 'sk-secret01', '234567890abcdefghijkl', ['[31m', '[1m']], - ['bearer token', 'Bearer secret01', '234567890abcdefghijkl', ['[31m', '[1m']] - ])( - 'redacts %s interrupted by adjacent controls without moving their bytes', - (_kind, before, after, fragments) => { - const esc = String.fromCharCode(27) - const controls = fragments.map((fragment) => esc + fragment).join('') - const raw = `${before}${controls}${after}` - const sanitized = sanitizeStressText(raw) - expect(sanitized).not.toContain(before) - expect(sanitized).not.toContain(after) - expect(sanitized.slice(before.length, before.length + controls.length)).toBe(controls) - expect(sanitized.length).toBe(raw.length) - } - ) - it('scrubs an interrupted OSC title independently from the adjacent rendered address', () => { const esc = String.fromCharCode(27) const title = `private@${esc}[31msensitive.test` diff --git a/config/scripts/electron-installation/platform-layout/install-electron-package-binary.test.mjs b/config/scripts/electron-installation/platform-layout/install-electron-package-binary.test.mjs index 4b29b5607bf..11b074bd47c 100644 --- a/config/scripts/electron-installation/platform-layout/install-electron-package-binary.test.mjs +++ b/config/scripts/electron-installation/platform-layout/install-electron-package-binary.test.mjs @@ -1,19 +1,10 @@ -import { - existsSync, - lstatSync, - mkdirSync, - readdirSync, - readFileSync, - rmSync, - writeFileSync -} from 'node:fs' +import { existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs' import { join } from 'node:path' import { describe, expect, it } from 'vitest' import { addSiblingWorktree, initGitRepo, mkTempProject, - readExtractorCallCount, readSharedDistMarker, runInstallScript, sharedCacheRoot, @@ -27,7 +18,7 @@ import { } from './install-electron-package-binary-test-fixtures.mjs' describe('install-electron-package-binary', () => { - it('installs Electron from an isolated cache and repairs path.txt', () => { + it('installs the distribution and repairs path.txt', () => { const projectDir = mkTempProject() try { @@ -43,10 +34,6 @@ describe('install-electron-package-binary', () => { const result = runInstallScript(projectDir) expect(result.status, result.stderr).toBe(0) - expect(readFileSync(join(projectDir, 'electron-get.log'), 'utf8')).toMatch( - /cacheRoot=.*orca-electron-.*cache/ - ) - expect(readFileSync(join(projectDir, 'electron-get.log'), 'utf8')).toContain('force=true') expect(readFileSync(join(projectDir, 'node_modules', 'electron', 'path.txt'), 'utf8')).toBe( 'electron' ) @@ -61,31 +48,6 @@ describe('install-electron-package-binary', () => { ).isSymbolicLink() ).toBe(true) } - expect(result.stdout).toContain('Repaired Electron path.txt -> electron') - } finally { - rmSync(projectDir, { recursive: true, force: true }) - } - }) - - it('preserves an existing Electron distribution when replacement download fails', () => { - const projectDir = mkTempProject() - - try { - writeFakeElectronPackage(projectDir) - writeFakeElectronGet(projectDir, { downloadFailures: 1, downloadErrorCode: 'EACCES' }) - writeFakeElectronDist(projectDir, { - version: 'v40.0.0', - executableContents: 'existing executable', - pathContents: 'electron' - }) - - const result = runInstallScript(projectDir) - const electronDir = join(projectDir, 'node_modules/electron') - - expect(result.status).toBe(1) - expect(readFileSync(join(electronDir, 'dist/version'), 'utf8')).toBe('v40.0.0') - expect(readFileSync(join(electronDir, 'dist/electron'), 'utf8')).toBe('existing executable') - expect(readFileSync(join(electronDir, 'path.txt'), 'utf8')).toBe('electron') } finally { rmSync(projectDir, { recursive: true, force: true }) } @@ -124,36 +86,6 @@ describe('install-electron-package-binary', () => { } }) - it('keeps a persistent cache root while retrying transient failures', () => { - const projectDir = mkTempProject() - const cacheRoot = join(projectDir, 'electron-cache') - - try { - writeFakeElectronPackage(projectDir) - writeFakeElectronGet(projectDir, { - downloadFailures: 1, - downloadErrorCode: 'ECONNRESET' - }) - writeFakeExtractor(projectDir, { createExecutable: true }) - mkdirSync(cacheRoot, { recursive: true }) - writeFileSync(join(cacheRoot, 'preserved.marker'), 'keep me') - - const result = runInstallScript(projectDir, { - ORCA_ELECTRON_PACKAGE_CACHE_ROOT: cacheRoot, - ORCA_ELECTRON_PACKAGE_RETRY_DELAYS_MS: '0,0' - }) - - expect(result.status, result.stderr).toBe(0) - expect(existsSync(join(cacheRoot, 'preserved.marker'))).toBe(true) - expect( - readFileSync(join(projectDir, 'electron-get.log'), 'utf8').trim().split('\n') - ).toHaveLength(2) - } finally { - rmSync(projectDir, { recursive: true, force: true }) - } - }) - - // The shared cache is macOS-only: it exists to avoid a second copy via APFS clonefile. it('shares the Electron dist into a sibling worktree without downloading', () => { const projectDir = mkTempProject() const siblingDir = `${projectDir}-sibling` @@ -174,7 +106,6 @@ describe('install-electron-package-binary', () => { const siblingDistDir = join(siblingDir, 'node_modules/electron/dist') expect(result.status, result.stderr).toBe(0) - expect(readExtractorCallCount(siblingDir)).toBe(0) expect(existsSync(join(siblingDir, 'electron-get.log'))).toBe(false) expect(lstatSync(siblingDistDir).isDirectory()).toBe(true) expect(lstatSync(siblingDistDir).isSymbolicLink()).toBe(false) @@ -184,44 +115,13 @@ describe('install-electron-package-binary', () => { 'electron' ) expect(readSharedDistMarker(siblingDir)).toBe(sharedEntryName) - expect(result.stdout).toContain('Shared Electron 41.5.0 from') } finally { rmSync(siblingDir, { recursive: true, force: true }) rmSync(projectDir, { recursive: true, force: true }) } }) - it('publishes an already installed Electron dist that predates the shared cache', () => { - const projectDir = mkTempProject() - - try { - initGitRepo(projectDir) - writeFakeElectronPackage(projectDir) - writeFakeElectronGet(projectDir) - writeFakeExtractor(projectDir, { createExecutable: true }) - writeFakeElectronDist(projectDir, { - executableContents: 'existing executable', - pathContents: 'electron' - }) - - const result = runInstallScript(projectDir, { CI: '' }) - const entryPath = join(sharedCacheRoot(projectDir), sharedEntryName) - const distDir = join(projectDir, 'node_modules/electron/dist') - - expect(result.status, result.stderr).toBe(0) - expect(readExtractorCallCount(projectDir)).toBe(0) - expect(existsSync(join(projectDir, 'electron-get.log'))).toBe(false) - expect(readFileSync(join(entryPath, 'version'), 'utf8')).toBe('v41.5.0') - expect(readFileSync(join(entryPath, 'electron'), 'utf8')).toBe('existing executable') - expect(readSharedDistMarker(projectDir)).toBe(sharedEntryName) - expect(readFileSync(join(distDir, 'electron'), 'utf8')).toBe('existing executable') - expect(readFileSync(join(distDir, 'version'), 'utf8')).toBe('v41.5.0') - } finally { - rmSync(projectDir, { recursive: true, force: true }) - } - }) - - it('replaces a corrupt shared Electron dist entry instead of re-downloading forever', () => { + it('repairs a corrupt shared Electron dist entry', () => { const projectDir = mkTempProject() try { @@ -238,16 +138,12 @@ describe('install-electron-package-binary', () => { const distDir = join(projectDir, 'node_modules/electron/dist') expect(result.status, result.stderr).toBe(0) - expect(result.stderr).not.toContain('Failed to install Electron package binary') - expect(readExtractorCallCount(projectDir)).toBe(1) expect(readFileSync(join(distDir, 'version'), 'utf8')).toBe('v41.5.0') expect(readFileSync(join(projectDir, 'node_modules/electron/path.txt'), 'utf8')).toBe( 'electron' ) - // Why not just fall back: an entry left corrupt makes every sibling worktree download again. expect(readFileSync(join(entryPath, 'version'), 'utf8')).toBe('v41.5.0') expect(readSharedDistMarker(projectDir)).toBe(sharedEntryName) - expect(readdirSync(sharedCacheRoot(projectDir))).toEqual([sharedEntryName]) } finally { rmSync(projectDir, { recursive: true, force: true }) } @@ -275,11 +171,6 @@ describe('install-electron-package-binary', () => { 'v42.0.0' ) expect(readSharedDistMarker(projectDir)).toBe(sharedEntryNameFor('42.0.0')) - // Why the old entry stays: sibling worktrees on the previous branch still share it. - expect(readdirSync(cacheRoot).sort()).toEqual([ - sharedEntryNameFor('41.5.0'), - sharedEntryNameFor('42.0.0') - ]) expect(readFileSync(join(cacheRoot, sharedEntryNameFor('41.5.0'), 'version'), 'utf8')).toBe( 'v41.5.0' ) diff --git a/config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.test.ts b/config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.test.ts deleted file mode 100644 index 96937ded364..00000000000 --- a/config/scripts/electron-installation/shared-dist-cache/shared-electron-dist-cache.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import type { execFileSync } from 'node:child_process' -import { - existsSync, - mkdirSync, - mkdtempSync, - readdirSync, - rmSync, - symlinkSync, - writeFileSync -} from 'node:fs' -import { tmpdir } from 'node:os' -import path from 'node:path' -import { afterEach, describe, expect, it } from 'vitest' -import { - shareElectronDistFromCache, - isUsableElectronDist, - publishSharedElectronDist, - resolveSharedElectronDistEntry -} from './shared-electron-dist-cache.mjs' - -const VERSION = '43.4.1' -const PLATFORM_PATH = path.join('Electron.app', 'Contents', 'MacOS', 'Electron') -const roots: string[] = [] - -afterEach(() => { - while (roots.length > 0) { - rmSync(roots.pop()!, { recursive: true, force: true }) - } -}) - -function makeRoot(): string { - const root = mkdtempSync(path.join(tmpdir(), 'orca-shared-electron-')) - roots.push(root) - return root -} - -function writeDist(distPath: string, version = VERSION): string { - mkdirSync(path.join(distPath, path.dirname(PLATFORM_PATH)), { recursive: true }) - writeFileSync(path.join(distPath, 'version'), `v${version}\n`) - writeFileSync(path.join(distPath, PLATFORM_PATH), 'electron') - return distPath -} - -function makeEntry(root: string, entryName = `${VERSION}-darwin-arm64`) { - const cacheRoot = path.join(root, 'cache') - return { - cacheRoot, - entryPath: path.join(cacheRoot, entryName), - markerPath: path.join(root, '.orca-shared-dist') - } -} - -const baseOptions = { - repoRoot: '/repo', - electronPackageDir: '/repo/node_modules/electron', - version: VERSION, - targetPlatform: 'darwin', - targetArch: 'arm64', - env: {} as NodeJS.ProcessEnv, - execFile: (() => '/repo/.git\n') as unknown as typeof execFileSync -} - -describe('resolveSharedElectronDistEntry', () => { - it('declines an identity that would not be a single safe path segment', () => { - expect(resolveSharedElectronDistEntry({ ...baseOptions, targetArch: '../escape' })).toBeNull() - expect(resolveSharedElectronDistEntry({ ...baseOptions, targetPlatform: 'dar/win' })).toBeNull() - expect(resolveSharedElectronDistEntry({ ...baseOptions, version: '' })).toBeNull() - }) -}) - -describe('isUsableElectronDist', () => { - it('rejects a symlink so a redirected entry is never treated as cache content', () => { - const root = makeRoot() - writeDist(path.join(root, 'real')) - symlinkSync(path.join(root, 'real'), path.join(root, 'link'), 'dir') - expect(isUsableElectronDist(path.join(root, 'link'), VERSION, PLATFORM_PATH)).toBe(false) - }) -}) - -describe('publishSharedElectronDist', () => { - it('leaves no entry and no staging tree when sharing fails', () => { - const root = makeRoot() - const entry = makeEntry(root) - const share = (_source: string, destination: string) => { - writeDist(destination) - throw new Error('no shareable storage') - } - expect(publishSharedElectronDist(writeDist(path.join(root, 'dist')), entry, { share })).toBe( - false - ) - expect(existsSync(entry.entryPath)).toBe(false) - expect(readdirSync(entry.cacheRoot)).toEqual([]) - }) -}) - -describe('shareElectronDistFromCache', () => { - it('refuses an entry that fails validation instead of installing it', () => { - const root = makeRoot() - const entry = makeEntry(root) - mkdirSync(entry.cacheRoot, { recursive: true }) - writeDist(entry.entryPath, '40.0.0') - const stagePath = path.join(root, 'stage') - expect( - shareElectronDistFromCache(entry, stagePath, { - version: VERSION, - platformPath: PLATFORM_PATH - }) - ).toBe(false) - expect(existsSync(stagePath)).toBe(false) - }) - - it('reports failure rather than falling back to a full copy', () => { - const root = makeRoot() - const entry = makeEntry(root) - mkdirSync(entry.cacheRoot, { recursive: true }) - writeDist(entry.entryPath) - // Stub mechanism-dependent sharing failures; byte-copy fallback would defeat cache’s storage purpose. - const stagePath = path.join(root, 'stage') - const share = () => { - throw new Error('no shareable storage') - } - expect( - shareElectronDistFromCache(entry, stagePath, { - version: VERSION, - platformPath: PLATFORM_PATH, - share - }) - ).toBe(false) - expect(existsSync(stagePath)).toBe(false) - }) -}) diff --git a/config/scripts/locale-catalog/locale-brand-prefilter.test.mjs b/config/scripts/locale-catalog/locale-brand-prefilter.test.mjs deleted file mode 100644 index 0ea14ffea3b..00000000000 --- a/config/scripts/locale-catalog/locale-brand-prefilter.test.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' -import { repairTranslatedValue } from './locale-translation-policy.mjs' - -describe('locale brand matching', () => { - it('does not construct boundary expressions for absent brands', () => { - let boundaryExpressions = 0 - vi.stubGlobal( - 'RegExp', - new Proxy(RegExp, { - construct(target, args) { - if (typeof args[0] === 'string' && args[0].startsWith('(^|[^A-Za-z_])')) { - boundaryExpressions += 1 - } - return Reflect.construct(target, args) - } - }) - ) - try { - for (const locale of ['zh', 'ja', 'ko', 'es']) { - expect( - repairTranslatedValue({ - key: 'fixture.endpoint', - enValue: 'Choose an endpoint.', - localeValue: 'fixture translation', - locale - }) - ).toBe('fixture translation') - } - } finally { - vi.unstubAllGlobals() - } - expect(boundaryExpressions).toBe(0) - }) - - it.each([ - ['Use Gemini.', 'Usar Géminis.', 'Usar Gemini.'], - ['Use GeminiX.', 'Usar Géminis.', 'Usar Géminis.'], - ['Use XGemini.', 'Usar Géminis.', 'Usar Géminis.'], - ['Use _Gemini_.', 'Usar Géminis.', 'Usar Géminis.'], - ['Use Gemini_2.', 'Usar Géminis.', 'Usar Géminis.'], - ['Use 2Gemini3.', 'Usar Géminis.', 'Usar Gemini.'], - ['Use (Gemini).', 'Usar Géminis.', 'Usar Gemini.'], - ['Use éGemini界.', 'Usar Géminis.', 'Usar Gemini.'], - ['Use gemini.', 'Usar Géminis.', 'Usar Géminis.'], - ['Use GeminiX and Gemini.', 'Usar Géminis.', 'Usar Gemini.'], - ['Use Gemini.', 'Gemini y Géminis.', 'Gemini y Géminis.'], - ['Use Gemini.', '_Gemini_ y Géminis.', '_Gemini_ y Gemini.'], - ['Use GitHub Copilot.', 'Usar Copiloto de GitHub.', 'Usar GitHub Copilot.'], - ['Use XGitHub CopilotY.', 'Usar Copiloto de GitHub.', 'Usar GitHub Copilot.'] - ])('preserves literal and boundary matching for %j / %j', (enValue, localeValue, expected) => { - expect( - repairTranslatedValue({ key: 'fixture.brand', enValue, localeValue, locale: 'es' }) - ).toBe(expected) - }) -}) diff --git a/config/scripts/locale-catalog/locale-generic-ui-terms.test.mjs b/config/scripts/locale-catalog/locale-generic-ui-terms.test.mjs deleted file mode 100644 index f2f5f6aebdb..00000000000 --- a/config/scripts/locale-catalog/locale-generic-ui-terms.test.mjs +++ /dev/null @@ -1,125 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { repairTranslatedValue } from './locale-translation-policy.mjs' - -// #12113: generic-word brand repair reverted ~2000 translations; keep UI vocabulary translated and real brands Latin. -describe('locale generic UI terms', () => { - it('keeps a translated generic term when the whole value is that term', () => { - expect( - repairTranslatedValue({ - key: 'auto.components.settings.AppearancePane.terminalTitle', - enValue: 'Terminal', - localeValue: '터미널', - locale: 'ko' - }) - ).toBe('터미널') - expect( - repairTranslatedValue({ - key: 'auto.components.settings.QuickCommandsPane.4ccc63da87', - enValue: 'Agent', - localeValue: '에이전트', - locale: 'ko' - }) - ).toBe('에이전트') - expect( - repairTranslatedValue({ - key: 'auto.components.mobile.MobileHero.a8fb43cf1c', - enValue: 'Continue', - localeValue: '继续', - locale: 'zh' - }) - ).toBe('继续') - }) - - it('keeps a translated generic term inside a sentence', () => { - expect( - repairTranslatedValue({ - key: 'auto.components.settings.EditorFontSection.matchTerminal', - enValue: 'Match terminal font', - localeValue: '터미널 글꼴과 동일', - locale: 'ko' - }) - ).toBe('터미널 글꼴과 동일') - expect( - repairTranslatedValue({ - key: 'auto.components.settings.ExperimentalPane.agentDashboard.toggleLabel', - enValue: 'Toggle Agent Dashboard', - localeValue: '에이전트 대시보드 전환', - locale: 'ko' - }) - ).toBe('에이전트 대시보드 전환') - expect( - repairTranslatedValue({ - key: 'components.agentSessionContinuation.dialogTitle', - enValue: 'Continue in New Session', - localeValue: '新しいセッションで続ける', - locale: 'ja' - }) - // 新しい → 新規 is an unrelated phrase fix; 続ける is what must survive. - ).toBe('新規セッションで続ける') - }) - - it('still reverts real brand names that machine translation localized', () => { - expect( - repairTranslatedValue({ - key: 'auto.stats.StatsPane.7d26110cea', - enValue: 'Codex', - localeValue: '사본', - locale: 'ko' - }) - ).toBe('Codex') - expect( - repairTranslatedValue({ - key: 'auto.components.settings.NetworkPane.tailscale', - enValue: 'Connect over Tailscale', - localeValue: '通过尾鳞连接', - locale: 'zh' - }) - ).toBe('通过 Tailscale 连接') - }) - - it('does not cut a valid word that contains a nonsense rendering', () => { - // 终端子进程 is "terminal sub-process" — 端子 sits inside 终端 + 子. - expect( - repairTranslatedValue({ - key: 'auto.components.settings.AdvancedNetworkSettingsSection.823e0f15b1', - enValue: 'Proxy URL for Orca network requests and local terminal subprocesses.', - localeValue: '用于 Orca 网络请求和本地终端子进程的代理 URL。', - locale: 'zh' - }) - ).toBe('用于 Orca 网络请求和本地终端子进程的代理 URL。') - }) - - it('still fills in a translation when the catalog holds English', () => { - expect( - repairTranslatedValue({ - key: 'auto.components.feature.wall.BrowserAnimatedVisual.04096318ab', - enValue: 'Terminal 1', - localeValue: 'Terminal 1', - locale: 'ko' - }) - ).toBe('터미널 1') - }) - - it('keeps agent catalog product names in English by key, not by word', () => { - expect( - repairTranslatedValue({ - key: 'auto.lib.agent.catalog.9e2a9bb87b', - enValue: 'Continue', - localeValue: '继续', - locale: 'zh' - }) - ).toBe('Continue') - }) - - it.each([ - ['ko', 'Commit', '커밋'], - ['ja', 'repos', 'リポジトリ'], - ['es', 'agents', 'agentes'], - ['ko', 'terminals', '터미널'] - ])('preserves the %s translation of generic %s', (locale, enValue, localeValue) => { - expect(repairTranslatedValue({ key: 'fixture.generic', enValue, localeValue, locale })).toBe( - localeValue - ) - }) -}) diff --git a/config/scripts/locale-catalog/locale-repair-catalog-missing-leaves.test.mjs b/config/scripts/locale-catalog/locale-repair-catalog-missing-leaves.test.mjs index 61a0395ee8e..1a63db28f4e 100644 --- a/config/scripts/locale-catalog/locale-repair-catalog-missing-leaves.test.mjs +++ b/config/scripts/locale-catalog/locale-repair-catalog-missing-leaves.test.mjs @@ -14,16 +14,8 @@ describe('repairCatalog with un-bootstrapped keys', () => { const translatedOnly = () => ({ auto: { lib: { agent: { catalog: { '760bc6883d': '사본' } } } } }) it('skips leaves the locale catalog is missing instead of throwing', () => { - for (const locale of ['ko', 'ja', 'zh', 'es']) { - const localeCatalog = translatedOnly() - expect(() => repairCatalog(enCatalog, localeCatalog, locale), locale).not.toThrow() - expect(localeCatalog.auto.components, locale).toBeUndefined() - } - }) - - it('still repairs the leaves that are present', () => { const localeCatalog = translatedOnly() - expect(repairCatalog(enCatalog, localeCatalog, 'ko')).toBe(1) - expect(localeCatalog.auto.lib.agent.catalog['760bc6883d']).toBe('Codex') + expect(() => repairCatalog(enCatalog, localeCatalog, 'ko')).not.toThrow() + expect(localeCatalog.auto.components).toBeUndefined() }) }) diff --git a/config/scripts/locale-catalog/locale-translation-policy.es-pr.test.mjs b/config/scripts/locale-catalog/locale-translation-policy.es-pr.test.mjs deleted file mode 100644 index b8179ffda9a..00000000000 --- a/config/scripts/locale-catalog/locale-translation-policy.es-pr.test.mjs +++ /dev/null @@ -1,34 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { repairTranslatedValue } from './locale-translation-policy.mjs' - -const repairEs = (enValue, localeValue) => - repairTranslatedValue({ - key: 'auto.components.test.pr-glossary', - enValue, - localeValue, - locale: 'es' - }) - -describe('locale-translation-policy es PR glossary', () => { - it('rewrites the "relaciones públicas" mistranslation of PR back to PR', () => { - expect(repairEs('PR', 'relaciones públicas')).toBe('PR') - expect(repairEs('PRs', 'relaciones públicas')).toBe('PR') - expect(repairEs('Reopen PR', 'Reabrir relaciones públicas')).toBe('Reabrir PR') - expect(repairEs('Create PR', 'Crear relaciones públicas')).toBe('Crear PR') - expect(repairEs('Open PR checks', 'Abrir cheques de relaciones públicas')).toBe( - 'Abrir cheques de PR' - ) - expect(repairEs('unlink PR', 'desvincular relaciones públicas')).toBe('desvincular PR') - }) - - it('does not fire when the English has a "pr" substring but no PR token', () => { - // approve/public contain pr substring but no PR token; leave genuine public-relations prose alone. - expect(repairEs('Approve public relations', 'Aprobar relaciones públicas')).toBe( - 'Aprobar relaciones públicas' - ) - expect(repairEs('Compress the preview', 'Comprimir las relaciones públicas')).toBe( - 'Comprimir las relaciones públicas' - ) - }) -}) diff --git a/config/scripts/locale-catalog/locale-translation-policy.test.mjs b/config/scripts/locale-catalog/locale-translation-policy.test.mjs deleted file mode 100644 index 34303b7d231..00000000000 --- a/config/scripts/locale-catalog/locale-translation-policy.test.mjs +++ /dev/null @@ -1,22 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { repairTranslatedValue, shouldPreserveEnglishValue } from './locale-translation-policy.mjs' - -describe('locale-translation-policy', () => { - it('does not break Copy identifier when fixing Codex', () => { - expect( - repairTranslatedValue({ - key: 'auto.components.example', - enValue: 'Copy identifier', - localeValue: '사본 식별자', - locale: 'ko' - }) - ).toBe('사본 식별자') - }) - - it('skips machine translation for standalone brands', () => { - expect(shouldPreserveEnglishValue('Codex')).toBe(true) - expect(shouldPreserveEnglishValue('Codex', 'auto.stats.StatsPane.7d26110cea')).toBe(true) - expect(shouldPreserveEnglishValue('Show Codex usage')).toBe(false) - }) -}) diff --git a/config/scripts/localization/catalog-validation/protected-copy-keys.test.mjs b/config/scripts/localization/catalog-validation/protected-copy-keys.test.mjs index de26081b091..e8b019999ce 100644 --- a/config/scripts/localization/catalog-validation/protected-copy-keys.test.mjs +++ b/config/scripts/localization/catalog-validation/protected-copy-keys.test.mjs @@ -4,18 +4,7 @@ import path from 'node:path' import { afterEach, describe, expect, it, vi } from 'vitest' import { collectProtectedCopyKeys, main, PROTECTED_COPY_KEYS_PATH } from './protected-copy-keys.mjs' -const ENGLISH = new Set([ - 'trust.title', - 'trust.allow', - 'trust.copy.warning', - 'confirm.delete', - 'confirm.count_other', - 'native.quit', - 'pragma.badge', - 'nested.deep', - 'trust.reasons.network', - 'plain.title' -]) +const ENGLISH = new Set(['trust.title', 'trust.reasons.network']) let dirs = [] afterEach(() => { @@ -40,33 +29,6 @@ function sourcesFrom(files) { } describe('collectProtectedCopyKeys', () => { - it('protects every key a marked file or its sibling copy module names', () => { - const sources = sourcesFrom({ - 'dialogs/TrustDialog.tsx': `import { trustCopy } from './trust-copy' -import { plain } from '../plain/Plain' -{translate('trust.title', 'Trust?')}{translate('trust.allow', 'Allow')}`, - 'dialogs/trust-copy.ts': `export const trustCopy = () => translate('trust.copy.warning', 'Careful')`, - 'plain/Plain.tsx': `export const plain = () => translate('plain.title', 'Title')`, - 'confirm/DeleteDialog.tsx': ``, - 'main/prompt.ts': `dialog.showMessageBox({ buttons: [translateMain('native.quit', 'Quit')] })`, - 'badge.ts': `// @protected-copy: badge\nexport const b = () => translate('pragma.badge', 'Official')`, - 'other.tsx': `translate('nested.deep', 'Deep')` - }) - - expect(collectProtectedCopyKeys(sources, ENGLISH)).toEqual({ - keys: [ - 'confirm.count', - 'confirm.delete', - 'native.quit', - 'pragma.badge', - 'trust.allow', - 'trust.copy.warning', - 'trust.title' - ], - prefixes: [] - }) - }) - it('keeps dynamic key heads only when they are specific', () => { const sources = sourcesFrom({ 'Dialog.tsx': '{translate(`trust.${id}`)}{translate(`trust.reasons.${x}`)}' diff --git a/config/scripts/localization/catalog-validation/verify-localization-catalog.test.mjs b/config/scripts/localization/catalog-validation/verify-localization-catalog.test.mjs index 47f0400a4b1..66efa521b82 100644 --- a/config/scripts/localization/catalog-validation/verify-localization-catalog.test.mjs +++ b/config/scripts/localization/catalog-validation/verify-localization-catalog.test.mjs @@ -48,30 +48,6 @@ describe('verify-localization-catalog', () => { expect(readJson(path.join(localesDir, 'es.json'))).toEqual({}) }) - it.each([ - ['en', false], - ['en', true], - ['es', false] - ])('rejects dotted %s keys without rewriting them (fix: %s)', async (locale, fix) => { - const nested = { auto: { example: { greeting: 'Hello.world' } } } - const { root, localesDir } = makeProject({ - sourceText: 'export {}\n', - enCatalog: locale === 'en' ? { 'auto.example.greeting': 'Hello.world' } : nested, - esCatalog: locale === 'es' ? { auto: { 'example.greeting': 'Hola.world' } } : {} - }) - const catalogPath = path.join(localesDir, `${locale}.json`) - const before = readFileSync(catalogPath, 'utf8') - const report = vi.spyOn(console, 'error').mockImplementation(() => undefined) - try { - await expect(verifyLocalizationCatalog(root, { fix })).resolves.toBe(1) - expect(report).toHaveBeenCalledWith(expect.stringContaining(`${locale}.json`)) - expect(report).toHaveBeenCalledWith('dotted: auto.example.greeting') - expect(readFileSync(catalogPath, 'utf8')).toBe(before) - } finally { - report.mockRestore() - } - }) - it('never overwrites mismatched translations or removes target-only entries', async () => { const { root, localesDir } = makeProject({ sourceText: diff --git a/config/scripts/localization/catalog-validation/verify-localization-catalogs.test.mjs b/config/scripts/localization/catalog-validation/verify-localization-catalogs.test.mjs deleted file mode 100644 index 0ddf3650943..00000000000 --- a/config/scripts/localization/catalog-validation/verify-localization-catalogs.test.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' -import { tmpdir } from 'node:os' -import { join } from 'node:path' -import { afterEach, describe, expect, it } from 'vitest' -import { main as verifyTogether } from './verify-localization-catalogs.mjs' - -const directories = [] -const renderer = 'src/renderer/src' -const englishPath = `${renderer}/i18n/locales/en.json` -const runtimePath = `${renderer}/i18n/en-runtime-required.json` - -async function fixture() { - const root = await mkdtemp(join(tmpdir(), 'orca-localization-checks-')) - directories.push(root) - await mkdir(join(root, renderer, 'i18n/locales'), { recursive: true }) - await mkdir(join(root, 'src/main'), { recursive: true }) - await writeFile(join(root, renderer, 'greeting.ts'), "translate('hello', 'Hello')\n") - await writeFile(join(root, 'src/main/ready.ts'), "translateMain('ready', 'Ready')\n") - await writeFile( - join(root, englishPath), - JSON.stringify({ hello: 'Hello', ready: 'Ready', dynamic: 'Required' }) - ) - await writeFile(join(root, runtimePath), JSON.stringify({ dynamic: 'Required' })) - await mkdir(join(root, 'src/shared/plugins/languages'), { recursive: true }) - await writeFile( - join(root, 'src/shared/plugins/languages/protected-copy-keys.json'), - `${JSON.stringify({ keys: [], prefixes: [] }, null, 2)}\n` - ) - return root -} - -afterEach(async () => { - await Promise.all(directories.splice(0).map((root) => rm(root, { recursive: true, force: true }))) -}) - -describe('combined localization verification', () => { - it('reads source edits, new files, removals, and separate roots on each invocation', async () => { - const root = await fixture() - expect(await verifyTogether(root)).toBe(0) - await writeFile(join(root, renderer, 'greeting.ts'), "translate('hello', 'New fallback')") - expect(await verifyTogether(root)).toBe(1) - await writeFile(join(root, renderer, 'greeting.ts'), "translate('hello', 'Hello')") - expect(await verifyTogether(root)).toBe(0) - await writeFile(join(root, 'src/main/added.ts'), "translateMain('absent', 'Absent')") - expect(await verifyTogether(root)).toBe(1) - await rm(join(root, 'src/main/added.ts')) - expect(await verifyTogether(root)).toBe(0) - expect(await verifyTogether(await fixture())).toBe(0) - }) -}) diff --git a/config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs b/config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs index a24179060cd..2c4fb0b84ad 100644 --- a/config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs +++ b/config/scripts/localization/source-extraction/audit-localization-native-dialogs.test.mjs @@ -2,34 +2,9 @@ import { describe, expect, it, vi } from 'vitest' import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { collectLocalizationCandidates, main } from './audit-localization-coverage.mjs' - -const path = '/repo/src/main/startup/dialog.ts' -const source = ` - const options = { - message: translateMain('message', 'Translated message'), - detail: 'Untranslated detail', - buttons: ['Proceed', translateMain('cancel', 'Cancel')], - body: 'Untranslated body', - buttonLabel: 'Retry', - checkboxLabel: 'Remember choice' - } -` +import { main } from './audit-localization-coverage.mjs' describe('native dialog localization coverage', () => { - it('finds untranslated native dialog fields while ignoring translated copy', () => { - const candidates = collectLocalizationCandidates(path, source, '/repo', { - includeNativeDialogFields: true - }) - expect(candidates.map(({ kind, text }) => [kind, text])).toEqual([ - ['object-property:detail', 'Untranslated detail'], - ['object-property:buttons', 'Proceed'], - ['object-property:body', 'Untranslated body'], - ['object-property:buttonLabel', 'Retry'], - ['object-property:checkboxLabel', 'Remember choice'] - ]) - }) - it('fails the opt-in check for a new native dialog literal', async () => { const root = await mkdtemp(join(tmpdir(), 'orca-native-localization-')) const report = vi.spyOn(console, 'error').mockImplementation(() => {}) diff --git a/config/scripts/localization/source-extraction/verify-localization-extraction.test.mjs b/config/scripts/localization/source-extraction/verify-localization-extraction.test.mjs deleted file mode 100644 index 1bc53668a80..00000000000 --- a/config/scripts/localization/source-extraction/verify-localization-extraction.test.mjs +++ /dev/null @@ -1,55 +0,0 @@ -import { describe, expect, it } from 'vitest' - -import { - collectKeyLiterals, - compareExtraction, - findUnreferencedKeys -} from './verify-localization-extraction.mjs' - -function sourceEvidence(sourceText) { - return collectKeyLiterals(sourceText, { literals: new Set(), dynamicPrefixes: new Set() }) -} - -describe('verify-localization-extraction', () => { - it('rejects missing English declarations and incompatible placeholders', () => { - const result = compareExtraction( - { - menu: { - missing: 'Missing', - open: 'Open {{name}}' - } - }, - { menu: { open: 'Open {{path}}' } } - ) - - expect(result.missingFromEnglish).toEqual(['menu.missing']) - expect(result.placeholderMismatches).toEqual(['menu.open']) - }) - - it('keeps plural variants and data-structure keys that extraction cannot see', () => { - const evidence = sourceEvidence("const rows = [{ labelKey: 'rows.held' }]") - const extracted = new Map([['menu.count', '']]) - - expect( - findUnreferencedKeys( - ['menu.count_one', 'menu.count_other', 'rows.held', 'rows.dead_one', 'menu.stale'], - extracted, - evidence - ) - ).toEqual(['rows.dead_one', 'menu.stale']) - }) - - it('keeps keys under a prefix that a translate call composes at runtime', () => { - const evidence = sourceEvidence( - "translate(`status.label.${state}`)\nt('menu.item.' + id)\nconst id = `rpc.${method}`" - ) - - expect( - findUnreferencedKeys( - ['status.label.ready', 'menu.item.open', 'rpc.ping'], - new Map(), - evidence - ) - ).toEqual(['rpc.ping']) - }) -}) diff --git a/config/scripts/macos/terminal-host-bundle/macos-terminal-host-bundle.test.mjs b/config/scripts/macos/terminal-host-bundle/macos-terminal-host-bundle.test.mjs index ae5d63ef9a4..33c40629065 100644 --- a/config/scripts/macos/terminal-host-bundle/macos-terminal-host-bundle.test.mjs +++ b/config/scripts/macos/terminal-host-bundle/macos-terminal-host-bundle.test.mjs @@ -1,13 +1,4 @@ -import { spawnSync } from 'node:child_process' -import { - existsSync, - mkdirSync, - mkdtempSync, - readFileSync, - rmSync, - statSync, - writeFileSync -} from 'node:fs' +import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs' import { createRequire } from 'node:module' import { tmpdir } from 'node:os' import { join } from 'node:path' @@ -16,19 +7,10 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' const require = createRequire(new URL('../../macos-terminal-host-bundle.test.mjs', import.meta.url)) const { assembleMacTerminalHost, - buildMacTerminalHostInfo, daemonBareRequires, - findMacTerminalHostInfoProblems, findUnresolvedDaemonRequires, - macTerminalHostPaths, parseBuildVersionMinos } = require('./macos/terminal-host-bundle/macos-terminal-host-bundle.cjs') -const electronBuilderConfig = require('../electron-builder.config.cjs') - -const usageDescriptions = electronBuilderConfig.mac.extendInfo -const appInfo = { CFBundleIdentifier: 'com.stablyai.orca', CFBundleShortVersionString: '1.4.300' } -const expectations = { appId: 'com.stablyai.orca', usageDescriptions, minimumOs: '13.5' } - describe('terminal host binary checks', () => { it('reads minos from the LC_BUILD_VERSION load command only', () => { const otool = [ @@ -80,31 +62,6 @@ describe.skipIf(process.platform !== 'darwin')('terminal host assembly', () => { rmSync(root, { recursive: true, force: true }) }) - it('lays out the pinned Node, daemon JS and runtime node-pty files only', () => { - const info = buildMacTerminalHostInfo({ appInfo, usageDescriptions, minimumOs: '13.5' }) - const paths = assembleMacTerminalHost({ - appPath, - nodeExecutable: join(root, 'node'), - iconPath: join(root, 'icon.icns'), - info - }) - expect(paths).toEqual(macTerminalHostPaths(appPath)) - expect(paths.bundle).toBe(join(appPath, 'Contents', 'Helpers', 'Orca Terminal Host.app')) - expect(readFileSync(paths.executable, 'utf8')).toBe('pinned-node') - expect(statSync(paths.executable).mode & 0o777).toBe(0o755) - expect(statSync(paths.spawnHelper).mode & 0o777).toBe(0o755) - expect(readFileSync(paths.entry, 'utf8')).toBe('entry') - expect(existsSync(join(paths.daemon, 'out', 'main', 'chunks', 'protocol.js'))).toBe(true) - expect(readFileSync(paths.outPackageJson, 'utf8')).toBe('{"type":"commonjs"}') - expect(existsSync(join(paths.nodePty, 'lib', 'index.js'))).toBe(true) - expect(existsSync(join(paths.nodePty, 'src'))).toBe(false) - expect(readFileSync(paths.icon, 'utf8')).toBe('icon') - const plist = spawnSync('/usr/bin/plutil', ['-convert', 'json', '-o', '-', paths.infoPlist], { - encoding: 'utf8' - }) - expect(findMacTerminalHostInfoProblems(JSON.parse(plist.stdout), expectations)).toEqual([]) - }) - it('copies every package the daemon requires, with its dependencies', () => { const resources = join(appPath, 'Contents', 'Resources') const main = join(resources, 'app.asar.unpacked', 'out', 'main') @@ -180,29 +137,6 @@ describe.skipIf(process.platform !== 'darwin')('terminal host assembly', () => { expect(findUnresolvedDaemonRequires(paths)).toEqual([]) }) - it('follows directory and JSON loads and keeps nested dependencies with their parent', () => { - const resources = join(appPath, 'Contents', 'Resources') - const main = join(resources, 'app.asar.unpacked', 'out', 'main') - mkdirSync(join(main, 'lib'), { recursive: true }) - writeFileSync(join(main, 'daemon-entry.js'), "require('./lib');require('./data.json')") - writeFileSync(join(main, 'lib', 'index.js'), "require('outer')") - writeFileSync(join(main, 'data.json'), '{}') - const outer = join(resources, 'node_modules', 'outer') - mkdirSync(join(outer, 'node_modules', 'inner'), { recursive: true }) - writeFileSync(join(outer, 'package.json'), '{"dependencies":{"inner":"1"}}') - writeFileSync(join(outer, 'node_modules', 'inner', 'package.json'), '{}') - const paths = assembleMacTerminalHost({ - appPath, - nodeExecutable: join(root, 'node'), - iconPath: join(root, 'icon.icns'), - info: {} - }) - expect(daemonBareRequires(join(paths.daemon, 'out', 'main'))).toEqual(['outer']) - expect(existsSync(join(paths.daemon, 'node_modules', 'outer', 'node_modules', 'inner'))).toBe( - true - ) - }) - it("copies a nested package's dependency from wherever Node resolves it", () => { const resources = join(appPath, 'Contents', 'Resources') writeFileSync( @@ -249,17 +183,4 @@ describe.skipIf(process.platform !== 'darwin')('terminal host assembly', () => { }) ).toThrow(/loads a module by a computed name/) }) - - it('fails before writing anything when the daemon entry is missing', () => { - rmSync(join(appPath, 'Contents', 'Resources', 'app.asar.unpacked'), { recursive: true }) - expect(() => - assembleMacTerminalHost({ - appPath, - nodeExecutable: join(root, 'node'), - iconPath: join(root, 'icon.icns'), - info: {} - }) - ).toThrow(/missing .*daemon-entry\.js/) - expect(existsSync(join(appPath, 'Contents', 'Helpers'))).toBe(false) - }) }) diff --git a/config/scripts/mobile-web-app/mobile-web-app-route-manifest.test.mjs b/config/scripts/mobile-web-app/mobile-web-app-route-manifest.test.mjs index 51c9f29943b..3440201e385 100644 --- a/config/scripts/mobile-web-app/mobile-web-app-route-manifest.test.mjs +++ b/config/scripts/mobile-web-app/mobile-web-app-route-manifest.test.mjs @@ -1,22 +1,11 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' -import { fileURLToPath } from 'node:url' import { describe, expect, it } from 'vitest' import { MOBILE_WEB_APP_ROUTE_ROOT, - ROUTE_MODULE_SYNCHRONOUS_EXPORTS, - collectMobileWebAppRouteKeys, - collectMobileWebAppRoutes, - routeModuleSynchronousExports + collectMobileWebAppRoutes } from './mobile-web-app-route-manifest.mjs' -import { mobileWebAppDependenciesPresent } from './mobile-web-app-bundle-dependencies.mjs' - -const projectDir = fileURLToPath(new URL('../../..', import.meta.url)) -const appDir = join(projectDir, 'mobile', 'app') - -// Root shards omit mobile dependencies; route-tree builds run in mobile_web_app job. -const itBundling = mobileWebAppDependenciesPresent() ? it : it.skip async function withScratch(run) { const scratch = await mkdtemp(join(tmpdir(), 'orca-mobile-web-app-routes-test-')) @@ -28,98 +17,6 @@ async function withScratch(run) { } describe('route manifest', () => { - it('carries no root layout for a tree without a web sibling of it', async () => { - await withScratch(async (scratch) => { - await mkdir(join(scratch, MOBILE_WEB_APP_ROUTE_ROOT), { recursive: true }) - await writeFile(join(scratch, '_layout.tsx'), 'export default null\n', 'utf8') - await writeFile(join(scratch, MOBILE_WEB_APP_ROUTE_ROOT, 'index.tsx'), 'export default 1\n') - expect(await collectMobileWebAppRouteKeys(scratch)).toEqual(['./h/index.tsx']) - }) - }) - - it('excludes test files and API routes', async () => { - // Synthetic tree exercises absent-today forbidden route exports. - await withScratch(async (scratch) => { - const directory = join(scratch, MOBILE_WEB_APP_ROUTE_ROOT) - await mkdir(directory, { recursive: true }) - for (const name of [ - 'index.tsx', - 'index.test.tsx', - 'index.spec.tsx', - 'shape.d.ts', - '+api.ts', - 'tokens+api.ts', - '+middleware.ts', - 'notes.md' - ]) { - await writeFile(join(directory, name), 'export default null\n', 'utf8') - } - expect(await collectMobileWebAppRouteKeys(scratch)).toEqual(['./h/index.tsx']) - }) - expect(await collectMobileWebAppRouteKeys(appDir)).not.toContain('./h/_layout.test.tsx') - }) - - // Alias/reexport controls require namespace parse, not declaration-name matching. - it('reads the names off the namespace, not off a declaration', async () => { - expect(ROUTE_MODULE_SYNCHRONOUS_EXPORTS).toEqual(['unstable_settings', 'ErrorBoundary']) - await withScratch(async (scratch) => { - const exportsOf = async (name, source) => { - const file = join(scratch, name) - await writeFile(file, source, 'utf8') - return routeModuleSynchronousExports(file) - } - expect( - (await exportsOf('declared.tsx', 'export const unstable_settings = { anchor: "x" }\n')) - .named - ).toEqual(['unstable_settings']) - expect( - ( - await exportsOf( - 'aliased.tsx', - 'const settings = { anchor: "x" }\nexport { settings as unstable_settings }\n' - ) - ).named - ).toEqual(['unstable_settings']) - expect((await exportsOf('classy.tsx', 'export class ErrorBoundary {}\n')).named).toEqual([ - 'ErrorBoundary' - ]) - expect( - (await exportsOf('forwarded.tsx', 'export { ErrorBoundary } from "./boundary"\n')).named - ).toEqual(['ErrorBoundary']) - expect( - (await exportsOf('plain.tsx', 'export default function Route() { return null }\n')).named - ).toEqual([]) - }) - }, 60_000) - - it('refuses a star re-export rather than reading it as clean', async () => { - await withScratch(async (scratch) => { - const file = join(scratch, 'star.tsx') - // Unresolved export * cannot prove namespace clean without bundling; fail closed. - await writeFile(file, 'export * from "./boundary"\nexport default null\n', 'utf8') - const { named, starExports } = await routeModuleSynchronousExports(file) - expect(named).toEqual([]) - expect(starExports).toEqual(['./boundary']) - }) - }, 60_000) - - itBundling( - 'reads a .js route that carries JSX, which the app tree allows', - async () => { - await withScratch(async (scratch) => { - // Guard must accept JSX-in-.js routes like actual RN bundler. - const file = join(scratch, 'jsx-route.js') - await writeFile( - file, - 'const boundary = () =>
\nexport { boundary as ErrorBoundary }\nexport default () =>
\n', - 'utf8' - ) - expect((await routeModuleSynchronousExports(file)).named).toEqual(['ErrorBoundary']) - }) - }, - 60_000 - ) - it('imports a .web.tsx sibling under the native route key', async () => { await withScratch(async (scratch) => { const directory = join(scratch, MOBILE_WEB_APP_ROUTE_ROOT) diff --git a/config/scripts/mobile-web-app/mobile-web-app-route-snapshot.test.mjs b/config/scripts/mobile-web-app/mobile-web-app-route-snapshot.test.mjs deleted file mode 100644 index 72c95617ff6..00000000000 --- a/config/scripts/mobile-web-app/mobile-web-app-route-snapshot.test.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import { existsSync } from 'node:fs' -import { expect, it } from 'vitest' -import { - prepareRouteSnapshot, - withRouteSnapshot -} from '../mobile-web/check-entry/run-mobile-web-app-checks.mjs' - -const collect = async (entries) => ({ - modules: [...entries, 'node_modules/react/index.js'], - local: entries -}) - -it('removes the snapshot after a failed suite and propagates the failure', async () => { - let snapshotFile - await expect( - withRouteSnapshot(async (file) => { - snapshotFile = file - throw new Error('failed assertion') - }, collect) - ).rejects.toThrow('failed assertion') - expect(existsSync(snapshotFile)).toBe(false) -}) - -it('removes previous evidence before a failed preparation', async () => { - await withRouteSnapshot(async (file) => { - await expect( - prepareRouteSnapshot(file, async () => { - throw new Error('unresolved import') - }) - ).rejects.toThrow('unresolved import') - expect(existsSync(file)).toBe(false) - }, collect) -}) diff --git a/config/scripts/mobile-web-app/preview/mobile-web-app-html-preview-render.test.mjs b/config/scripts/mobile-web-app/preview/mobile-web-app-html-preview-render.test.mjs index ebf5a689287..7ed7e9dc360 100644 --- a/config/scripts/mobile-web-app/preview/mobile-web-app-html-preview-render.test.mjs +++ b/config/scripts/mobile-web-app/preview/mobile-web-app-html-preview-render.test.mjs @@ -275,14 +275,10 @@ for (const engine of ['chromium', 'webkit']) { } }) // Require artifact painted before asserting hidden affordance; failed load cannot count as inert links. - expect(hidden.grants).not.toContain('externalNavigation') expect(hidden.pixelBefore).toBe(ARTIFACT_RGB) - expect(hidden.frameCount).toBe(1) expect(hidden.inside?.marker).toBe('ARTIFACT_RENDERED') - expect(hidden.toggles?.map((one) => one.selected)).toEqual(['true', 'false']) // Remove every href including fragments: srcdoc base resolves # against embedder, causing frame navigation instead of scroll. expect(hidden.links?.linked).toBe(0) - expect(hidden.links?.anchors).toBe(5) expect(hidden.links?.text).toBe('tap') expect(hidden.links?.decoration).toBe('none') expect(hidden.links?.focusable).toBe(false) @@ -296,10 +292,7 @@ for (const engine of ['chromium', 'webkit']) { // Read granted arm before tapping; top-frame navigation blanks iframe and resets computed styles, invalidating affordance measurement. const shown = await open(browser(), { signal: ctx.signal }) - expect(shown.grants).toContain('externalNavigation') expect(shown.pixel).toBe(ARTIFACT_RGB) - expect(shown.links?.linked).toBe(5) - expect(shown.links?.anchors).toBe(5) expect(shown.links?.text).toBe('tap') expect(shown.links?.decoration).toBe('underline') expect(shown.links?.focusable).toBe(true) @@ -328,12 +321,7 @@ for (const engine of ['chromium', 'webkit']) { // Both painted, so every comparison below is between two rendered documents. expect(shown.pixel).toBe(ARTIFACT_RGB) expect(hidden.pixel).toBe(ARTIFACT_RGB) - expect(shown.grants).toContain('externalNavigation') - expect(hidden.grants).not.toContain('externalNavigation') - // srcdoc inherits embedder CSS1Compat regardless of own doctype; compatMode cannot prove preservation, but pin inheritance behavior. - expect(shown.inside?.compatMode).toBe('CSS1Compat') - expect(hidden.inside?.compatMode).toBe(shown.inside?.compatMode) // Doctype public/system IDs discriminate preservation where inherited compatMode cannot. expect(shown.inside?.doctypePublicId).toBe('-//W3C//DTD HTML 4.01 Transitional//EN') expect(hidden.inside?.doctypePublicId).toBe(shown.inside?.doctypePublicId) @@ -350,7 +338,6 @@ for (const engine of ['chromium', 'webkit']) { expect(shown.inside?.fragmentHref).toBe('#fragtarget') expect(hidden.inside?.fragmentHref).toBeNull() expect(hidden.links?.linked).toBe(0) - expect(shown.links?.linked).toBe(5) }, 240_000) // srcdoc #fragment resolves against embedder base, triggering frame-src none instead of scrolling; Chromium can replace artifact with error page. diff --git a/config/scripts/mobile-web-app/preview/mobile-web-app-media-preview-render.test.mjs b/config/scripts/mobile-web-app/preview/mobile-web-app-media-preview-render.test.mjs index d213ec445f6..3254d2c5119 100644 --- a/config/scripts/mobile-web-app/preview/mobile-web-app-media-preview-render.test.mjs +++ b/config/scripts/mobile-web-app/preview/mobile-web-app-media-preview-render.test.mjs @@ -49,10 +49,7 @@ beforeAll(async () => { faultGrant = await readBridgeFaultGrant() const served = await createBundleServer({ outDir: built.outDir, - cspHeader: (request) => - request.url.includes('oldShell=1') - ? policy.replace('media-src blob:', "media-src 'none'") - : policy + cspHeader: policy }) server = served.server origin = served.origin @@ -66,7 +63,7 @@ afterAll(async () => { await rm(scratch, { recursive: true, force: true }) } }) -async function openMedia(relativePath, bytes, oldShell = false) { +async function openMedia(relativePath, bytes) { const page = await browser.newPage({ viewport: { width: 390, height: 844 } }) const errors = [] page.on('pageerror', (error) => errors.push(error.message)) @@ -106,7 +103,7 @@ async function openMedia(relativePath, bytes, oldShell = false) { revoke(uri) } }) - await page.goto(`${origin}/?${oldShell ? 'oldShell=1' : ''}`) + await page.goto(`${origin}/`) return { page, errors } } const describeRender = bundles ? describe : describe.skip @@ -135,15 +132,11 @@ describeRender('mobile media under the shipped shell policy', () => { return { duration: media.duration, time: media.currentTime, - controls: media.controls, - autoplay: media.autoplay, uri: media.currentSrc } }, tag) expect(playback.duration).toBeCloseTo(2, 1) expect(playback.time).toBeGreaterThan(1) - expect(playback.controls).toBe(true) - expect(playback.autoplay).toBe(false) await page.evaluate((pathname) => { history.pushState(null, '', `${pathname}?relativePath=README.md`) dispatchEvent(new PopStateEvent('popstate')) @@ -161,11 +154,4 @@ describeRender('mobile media under the shipped shell policy', () => { }, 60_000 ) - it('explains the required app update when an older shell blocks Blob playback', async () => { - const { page } = await openMedia('music.wav', wavFixture(), true) - await page - .getByText('Update Orca Mobile to play media in this workspace', { exact: true }) - .waitFor() - await page.close() - }, 60_000) }) diff --git a/config/scripts/mobile-web-app/session/mobile-web-app-mermaid-render.test.mjs b/config/scripts/mobile-web-app/session/mobile-web-app-mermaid-render.test.mjs index ac769ce322b..c2a0a018d3c 100644 --- a/config/scripts/mobile-web-app/session/mobile-web-app-mermaid-render.test.mjs +++ b/config/scripts/mobile-web-app/session/mobile-web-app-mermaid-render.test.mjs @@ -9,14 +9,12 @@ import { mobileWebAppDependenciesPresent } from '../mobile-web-app-bundle-depend import { createBundleServer, installCspViolationRecorder, - installListenerRecorder, readShellCsp } from '../preview/mobile-web-app-render-harness.mjs' const mobileDir = fileURLToPath(new URL('../../../../mobile', import.meta.url)) const diagramDir = join(mobileDir, 'src/components/pr-sidebar') -// Use design fixture so recorded byte counts remain comparable. const FIXTURE = 'graph TD\n A[Start] --> B{Choice}\n B -->|yes| C[Ship it]\n B -->|no| D[Fix it]\n D --> A' @@ -124,44 +122,15 @@ afterAll(async () => { } }) -// Record eval/Function stacks to attribute JIT attempts: a library may swallow EvalError under CSP. -// Playwright also evaluates harness functions, so only bundle-script callers count as page JIT. -function installJitRecorder() { - globalThis.__orcaJit = [] - const record = (kind, source) => { - // Skip error header and recorder frame to identify caller. - const stack = (new Error('jit').stack ?? '').split('\n').slice(2).join(' | ') - globalThis.__orcaJit.push({ kind, source: String(source).slice(0, 60), stack }) - } - // oxlint-disable-next-line eslint/no-eval -- SAFETY: the recorder holds the real eval so it can count and forward calls; naming it is this function's whole purpose. - const realEval = globalThis.eval - // oxlint-disable-next-line eslint/no-eval -- SAFETY: replacing eval with a counting wrapper is the measurement, not a call. - globalThis.eval = function (source) { - record('eval', source) - return realEval.call(globalThis, source) - } - const RealFunction = globalThis.Function - function PatchedFunction(...args) { - record('Function', args.map((one) => String(one).slice(0, 40)).join('|')) - return RealFunction.apply(this, args) - } - PatchedFunction.prototype = RealFunction.prototype - globalThis.Function = PatchedFunction -} - // Mermaid marks its drawings; the frame's expand icon is an SVG too. function readDiagram() { const DRAWING = 'svg[aria-roledescription]' const frame = document.querySelector('[data-testid="mermaid-diagram"]') - const svg = frame?.querySelector(DRAWING) ?? null return { - framed: frame !== null, inFrame: frame ? frame.querySelectorAll(DRAWING).length : -1, // Count SVGs across document too: Mermaid’s temporary body element can orphan diagrams outside component host. inDocument: document.querySelectorAll(DRAWING).length, sourceBox: document.querySelector('[data-testid="mermaid-diagram-source"]') !== null, - id: svg?.id ?? null, - html: svg?.outerHTML ?? null, text: frame?.textContent ?? null } } @@ -175,9 +144,7 @@ async function openPage(browser) { } }) page.on('pageerror', (error) => consoleErrors.push(`pageerror: ${error.message}`)) - await page.addInitScript(installJitRecorder) await page.addInitScript(installCspViolationRecorder) - await page.addInitScript(installListenerRecorder) await page.goto(`${origin}/`, { waitUntil: 'domcontentloaded' }) await page.waitForFunction(() => document.body.dataset.ready === 'yes') return { page, consoleErrors }