diff --git a/Makefile b/Makefile index a82830eec37..8a8becafd6c 100644 --- a/Makefile +++ b/Makefile @@ -166,6 +166,11 @@ else npm run test:snapshots -- --headed --update-snapshots=$(E2E_MODE) endif +.PHONY: glass-skeleton +glass-skeleton: + $(MAKE) test-e2e-desktop MAKE_GLASS_SKELETON=yes + + ############################################################################### # CLEAN diff --git a/e2e/playwright/zoo-test.ts b/e2e/playwright/zoo-test.ts index 3b3fa6f6c00..20cfcd87529 100644 --- a/e2e/playwright/zoo-test.ts +++ b/e2e/playwright/zoo-test.ts @@ -1,6 +1,13 @@ /* eslint-disable react-hooks/rules-of-hooks */ -import { test as playwrightTestFn } from '@playwright/test' +import { + test as playwrightTestFn, + beforeEach, + afterEach, +} from '@playwright/test' +import fs from 'node:fs/promises' +import path from 'node:path' +import { GlassSkeletonRecorder } from 'glass-skeleton-recorder' import type { Fixtures } from '@e2e/playwright/fixtures/fixtureSetup' import { ElectronZoo, @@ -94,8 +101,60 @@ const playwrightTestFnWithFixtures_ = playwrightTestFn.extend<{ ], }) -const test = playwrightTestFnWithFixtures_.extend( - fixturesBasedOnProcessEnvPlatform -) +const playwrightTestFnWithFixtures__ = + playwrightTestFnWithFixtures_.extend( + fixturesBasedOnProcessEnvPlatform + ) + +// Add the Glass Skeleton as a fixture to promise a fresh skeleton state +const test = playwrightTestFnWithFixtures__.extend<{ + glassSkeleton?: GlassSkeletonRecorder +}>({ + glassSkeleton: async ({ page }, use) => { + const glassSkeleton = process.env.MAKE_GLASS_SKELETON + ? // These are functions because those properties are late-bound. + new GlassSkeletonRecorder({ + type: 'playwright', + page, + fs: { + writeFile: fs.writeFile, + mkdir: fs.mkdir, + }, + path: { + resolve: path.resolve, + }, + resources: [ + { + protocol: GlassSkeletonRecorder.SupportedProtocol.WebSocket, + urlRegExpStr: 'wss://api.dev.zoo.dev', + removeMatchingRegExpStrs: [ + 'api-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', + ], + }, + ], + }) + : undefined + await use(glassSkeleton) + }, +}) +// These exist because otherwise the page is not navigated to yet. +beforeEach(async ({ glassSkeleton }) => { + if (glassSkeleton === undefined) return + await glassSkeleton.start() +}) +afterEach(async ({ glassSkeleton }, testInfo) => { + if (glassSkeleton === undefined) return + await glassSkeleton.stop() + void glassSkeleton.save({ + outputDir: path.resolve(testInfo.outputPath(), '..'), + outputName: + testInfo.titlePath + .join('-') + .toLowerCase() + .trim() + .replace(/'"/g, '') + .replaceAll(' ', '-') + '.bson', + }) +}) export { test } diff --git a/package-lock.json b/package-lock.json index b52c4eabe1f..4328b9fe570 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "hasInstallScript": true, "license": "MIT", "workspaces": [ + "../glass-skeleton/recorder", "packages/codemirror-lang-kcl", "packages/codemirror-lsp-client", "rust/kcl-language-server" @@ -160,6 +161,18 @@ "ws": "^8.18.3" } }, + "../glass-skeleton/recorder": { + "name": "playwright-glass-skeleton", + "version": "0.0.1", + "license": "ISC", + "dependencies": { + "bson": "^6.10.4" + }, + "devDependencies": { + "@types/node": "^24.8.0", + "typescript": "^5.9.3" + } + }, "node_modules/@adobe/css-tools": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.2.tgz", @@ -2512,6 +2525,7 @@ }, "node_modules/@clack/prompts/node_modules/is-unicode-supported": { "version": "1.3.0", + "extraneous": true, "inBundle": true, "license": "MIT", "engines": { @@ -24326,6 +24340,10 @@ "node": ">=18" } }, + "node_modules/playwright-glass-skeleton": { + "resolved": "../glass-skeleton/recorder", + "link": true + }, "node_modules/plist": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", @@ -28263,9 +28281,9 @@ } }, "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -30433,6 +30451,18 @@ "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true }, + "packages/playwright-glass-skeleton": { + "version": "0.0.1", + "extraneous": true, + "license": "ISC", + "dependencies": { + "bson": "^6.10.4" + }, + "devDependencies": { + "@types/node": "^24.8.0", + "typescript": "^5.9.3" + } + }, "rust/kcl-language-server": { "version": "0.0.0", "license": "MIT", diff --git a/package.json b/package.json index c0b84a8435c..78c83a22e4e 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "main": ".vite/build/main.js", "license": "MIT", "workspaces": [ + "../glass-skeleton/recorder", "packages/codemirror-lang-kcl", "packages/codemirror-lsp-client", "rust/kcl-language-server"