From 13a75d3939f60bbc5ebf3bc083fe31fe74813168 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Tue, 13 Oct 2026 20:25:00 -0700 Subject: [PATCH] [CI] Reduce redundant test work and import existing helpers directly (#28365) * [CI] Reduce redundant test work and import existing helpers directly * [CI] Preserve provider guards and pin the mobile browser test core * [CI] Fix CI test setup and verify retained contracts * [CI] Compare native media chunks without boxed byte arrays * [CI] Detect shifted native media reads with position-sensitive bytes --- .github/workflows/pr.yml | 2 +- .../build-mobile-web-app-bundle.test.mjs | 111 +------------- .../build-windows-cli-launcher.test.mjs | 24 ---- .../scripts/electron-builder-config.test.mjs | 52 ------- .../electron-vite-output-contract.test.ts | 35 ++++- .../generate-bundled-skill-guides.test.mjs | 136 +++++------------- ...web-app-external-navigation-grant.test.mjs | 6 - .../mobile-web-app-haptics-seam.test.mjs | 19 --- ...ile-web-app-page-grant-call-sites.test.mjs | 98 +------------ ...ile-web-app-screencast-lane-grant.test.mjs | 6 - ...web-app-session-webview-consumers.test.mjs | 8 -- ...obile-web-terminal-engine-closure.test.mjs | 61 ++++---- .../scripts/regenerate-xterm-patches.test.mjs | 17 --- .../bridge-terminal-output-backlog.test.ts | 44 +++++- mobile/src/platform/native-media.test.ts | 22 ++- .../mobile-image-base64-accumulator.test.ts | 5 +- .../src/transport/base64-byte-codec.test.ts | 5 +- package.json | 1 + pnpm-lock.yaml | 10 ++ src/cli/handler-group-manifest.test.ts | 4 - .../session-search-schema.test.ts | 20 --- ...aude-child-work-evidence-retention.test.ts | 112 +++------------ .../claude-structured-history-window.test.ts | 17 --- .../codex-structured-dispatch-echo.test.ts | 89 +----------- src/main/git/runner-gh-host-args.test.ts | 3 +- .../git/worktree-add-timeout-override.test.ts | 2 +- .../orcad-managed-stop-cancellation.test.ts | 19 +++ .../src/components/UpdateCard.test.ts | 2 +- .../ContextualTourOverlay.test.tsx | 2 +- .../project-picker-input.test.ts | 3 +- .../native-chat-type-scale.test.ts | 43 ------ .../right-sidebar/PortsPanel.test.tsx | 2 +- .../components/sidebar/WorktreeCard.test.ts | 2 +- .../sidebar/WorktreeContextMenu.test.ts | 2 +- .../status-bar-runtime-groups.test.ts | 8 +- 35 files changed, 225 insertions(+), 767 deletions(-) delete mode 100644 src/renderer/src/components/native-chat/native-chat-type-scale.test.ts diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 45e6e5ca28b..c0c199f88e6 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -903,7 +903,7 @@ jobs: - name: Install WebKit for the drawer check id: webkit background: true - run: pnpm exec playwright install --with-deps webkit + run: pnpm exec playwright-core install --with-deps webkit # The entry lives in mobile/ so one React resolves; without this every RN import is nothing. - uses: ./.github/actions/install-mobile-dependencies diff --git a/config/scripts/build-mobile-web-app-bundle.test.mjs b/config/scripts/build-mobile-web-app-bundle.test.mjs index 489599d7bf3..083a7f10a2c 100644 --- a/config/scripts/build-mobile-web-app-bundle.test.mjs +++ b/config/scripts/build-mobile-web-app-bundle.test.mjs @@ -11,19 +11,15 @@ import { import { MOBILE_WEB_APP_NATIVE_PARITY_STYLE, MOBILE_WEB_APP_ROOT_RESET, - MOBILE_WEB_APP_SHIMS, bundleMobileWebApp, buildMobileWebAppBundle, entryStaticClosure, - mobileWebAppBuildOptions, renameOutputsByContent, routeChunkNames } from './build-mobile-web-app-bundle.mjs' import { MOBILE_WEB_APP_ROUTE_ROOT, - ROUTE_SOURCE_LOADERS, - collectMobileWebAppRouteKeys, - collectMobileWebAppRoutes + collectMobileWebAppRouteKeys } from './mobile-web-app-route-manifest.mjs' import { MOBILE_WEB_APP_BUNDLE_MAX_ENTRY_BYTES, @@ -42,7 +38,6 @@ import { BINARY_SOURCE_EXTENSIONS, assertNoCarriageReturnsInSource } from './mobile-web-source-line-endings.mjs' -import { spelledCountsAgainstTables } from './spelled-count-census.mjs' import { hashedAsset, readDesktopVersion, @@ -87,34 +82,6 @@ describe('the CRLF pin', () => { }) describeBundling('the app bundle', () => { - it('isolates read-only fixture consumers from mutations in another assertion', async () => { - const first = await readAppBundle() - const original = first.script[0] - first.script[0] ^= 255 - first.chunks.length = 0 - first.routeKeys.length = 0 - const next = await readAppBundle() - expect(next.script[0]).toBe(original) - expect(next.chunks.length).toBeGreaterThan(0) - expect(next.routeKeys.length).toBeGreaterThan(0) - const written = await readWrittenBundle() - written.manifest.assets.length = 0 - expect((await readWrittenBundle()).manifest.assets.length).toBeGreaterThan(0) - const originalByte = written.files[0].bytes[0] - written.files[0].bytes[0] ^= 255 - expect((await readWrittenBundle()).files[0].bytes[0]).toBe(originalByte) - await withScratch(async (scratch) => { - const firstDir = join(scratch, 'first') - await copyWrittenBundle(firstDir) - await writeFile(join(firstDir, 'manifest.json'), 'corrupted') - const secondDir = join(scratch, 'second') - const second = await copyWrittenBundle(secondDir) - for (const { file, bytes } of second.files) { - expect((await readFile(join(secondDir, file))).equals(bytes), file).toBe(true) - } - }) - }, 120_000) - it('resolves react-native to react-native-web and leaves no require.context', async () => { const sources = allScriptSource(await readAppBundle()) for (const source of sources) { @@ -307,47 +274,6 @@ describeBundling('the app bundle', () => { } }, 120_000) - it('asks esbuild for the split the budgets assume', async () => { - const options = mobileWebAppBuildOptions(await collectMobileWebAppRoutes(appDir)) - // Each of these is load-bearing for a budget below: esm and splitting are what make a route a - // chunk, and the metafile is the only thing that says which imports are static. - expect(options.format).toBe('esm') - expect(options.splitting).toBe(true) - expect(options.chunkNames).toBe('[hash]') - expect(options.metafile).toBe(true) - }) - - it('reads a route source the same way the export guard does', async () => { - const options = mobileWebAppBuildOptions(await collectMobileWebAppRoutes(appDir)) - // The guard parses each route on its own, outside this build. Sharing the table is what stops - // a loader the bundle relies on from being missing there and reported as a syntax error. - for (const [extension, loader] of Object.entries(ROUTE_SOURCE_LOADERS)) { - expect(options.loader[extension], extension).toBe(loader) - } - }) - - it('applies every shim it names', async () => { - const options = mobileWebAppBuildOptions(await collectMobileWebAppRoutes(appDir)) - for (const shim of MOBILE_WEB_APP_SHIMS) { - expect(shim.appliesTo(options), `${shim.name} is named but not applied`).toBe(true) - } - }) - - it('fails the named shim, not the whole build, when its option goes missing', async () => { - const options = mobileWebAppBuildOptions(await collectMobileWebAppRoutes(appDir)) - // Each shim reads an option of its own (two read `banner.js`), so stripping every option - // leaves none applying. Without that, the list could name a shim the build stopped applying. - const stripped = { - ...options, - alias: {}, - loader: {}, - define: {}, - banner: {}, - plugins: [] - } - expect(MOBILE_WEB_APP_SHIMS.filter((shim) => shim.appliesTo(stripped))).toEqual([]) - }) - it('ships no haptic that reaches for the DOM', async () => { // expo-haptics' web build fakes an iOS haptic by appending a hidden // `