diff --git a/.github/workflows/test-and-build.yml b/.github/workflows/test-and-build.yml index b26c509..f6863b6 100644 --- a/.github/workflows/test-and-build.yml +++ b/.github/workflows/test-and-build.yml @@ -53,6 +53,9 @@ jobs: - name: Build run: pnpm run build + - name: Install Playwright browsers + run: pnpm run playwright:install + - name: Test run: pnpm run test:all diff --git a/.gitignore b/.gitignore index 7e5e851..fd03684 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ toml-patch.code-workspace *.cpuprofile benchmark-*.md + +test-results/ +playwright-report/ diff --git a/browser-tests/smoke.spec.ts b/browser-tests/smoke.spec.ts new file mode 100644 index 0000000..7829f88 --- /dev/null +++ b/browser-tests/smoke.spec.ts @@ -0,0 +1,42 @@ +import { test, expect } from '@playwright/test'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +const bundle = readFileSync(join(process.cwd(), 'dist/toml-patch.js'), 'utf-8'); + +// Load the bundle into the page via a blob URL so it runs in a real browser +// module context — no Node.js APIs available. +async function loadTOML(page: import('@playwright/test').Page) { + await page.goto('about:blank'); + await page.evaluate(async (src: string) => { + const blob = new Blob([src], { type: 'application/javascript' }); + const url = URL.createObjectURL(blob); + (window as any).__TOML__ = await import(url); + URL.revokeObjectURL(url); + }, bundle); +} + +test.beforeEach(async ({ page }) => { + await loadTOML(page); +}); + +test('parse should work in real browser', async ({ page }) => { + const result = await page.evaluate(() => + (window as any).__TOML__.parse('key = "hello"') + ); + expect(result).toEqual({ key: 'hello' }); +}); + +test('stringify should work in real browser', async ({ page }) => { + const result = await page.evaluate(() => + (window as any).__TOML__.stringify({ key: 'hello' }) + ); + expect(result).toBe('key = "hello"\n'); +}); + +test('patch should work in real browser', async ({ page }) => { + const result = await page.evaluate(() => + (window as any).__TOML__.patch('key = "hello"\n', { key: 'world' }) + ); + expect(result).toBe('key = "world"\n'); +}); diff --git a/jest.config.json b/jest.config.json index 2122c45..3b4b9bf 100644 --- a/jest.config.json +++ b/jest.config.json @@ -2,6 +2,7 @@ "testEnvironment": "node", "preset": "ts-jest", "testRegex": "/__tests__/(?!__js__).*\\.[jt]sx?$", + "testPathIgnorePatterns": ["/worktrees/"], "snapshotFormat": { "escapeString": true, "printBasicPrototype": true diff --git a/jest.config.mjs b/jest.config.mjs index 2f2e51d..0322355 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -4,6 +4,7 @@ export default { testEnvironment: 'node', testRegex: '/__tests__/.*\\.mjs$', + testPathIgnorePatterns: ['/worktrees/'], transform: {}, moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', diff --git a/package.json b/package.json index 563869f..202b59194 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,9 @@ "dev": "pnpm run typecheck && pnpm run build && npm-run-all2 --parallel test:all specs", "test": "jest --config jest.config.json", "test:js": "node --experimental-vm-modules node_modules/jest/bin/jest.js --config jest.config.mjs", - "test:all": "pnpm run test && pnpm run test:js", + "test:playwright": "playwright test", + "playwright:install": "playwright install --with-deps chromium", + "test:all": "pnpm run test && pnpm run test:js && pnpm run test:playwright", "typecheck": "tsc", "specs": "jest --config specs.config.cjs", "benchmark": "npm-run-all2 bench:*", @@ -53,6 +55,7 @@ }, "devDependencies": { "@decimalturn/toml-patch": "npm:@decimalturn/toml-patch@1.0.7", + "@playwright/test": "^1.59.1", "@rollup/plugin-terser": "^1.0.0", "@rollup/plugin-typescript": "^12.1.2", "@types/dedent": "^0.7.2", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..7fe1285 --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from '@playwright/test'; + +export default defineConfig({ + testDir: './browser-tests', + projects: [ + { name: 'chromium', use: { browserName: 'chromium' } }, + ], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7c87e88..52d0acd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: '@decimalturn/toml-patch': specifier: npm:@decimalturn/toml-patch@1.0.7 version: 1.0.7 + '@playwright/test': + specifier: ^1.59.1 + version: 1.59.1 '@rollup/plugin-terser': specifier: ^1.0.0 version: 1.0.0(rollup@4.60.1) @@ -555,6 +558,11 @@ packages: resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + engines: {node: '>=18'} + hasBin: true + '@rollup/plugin-terser@1.0.0': resolution: {integrity: sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==} engines: {node: '>=20.0.0'} @@ -1260,6 +1268,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1935,6 +1948,16 @@ packages: platform@1.3.6: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + playwright-core@1.59.1: + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.59.1: + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} + hasBin: true + pretty-format@30.3.0: resolution: {integrity: sha512-oG4T3wCbfeuvljnyAzhBvpN45E8iOTXCU/TD3zXW80HA3dQ4ahdqMkWGiPWZvjpQwlbyHrPTWUAqUzGzv4l1JQ==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -2921,6 +2944,10 @@ snapshots: '@pkgr/core@0.2.9': {} + '@playwright/test@1.59.1': + dependencies: + playwright: 1.59.1 + '@rollup/plugin-terser@1.0.0(rollup@4.60.1)': dependencies: serialize-javascript: 7.0.5 @@ -3533,6 +3560,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -4443,6 +4473,14 @@ snapshots: platform@1.3.6: {} + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + pretty-format@30.3.0: dependencies: '@jest/schemas': 30.0.5 diff --git a/tsconfig.json b/tsconfig.json index 4e870e2..c7f1c55 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,6 @@ "noEmit": true, "skipLibCheck": true }, - "include": ["src/**/*"], + "include": ["*.ts", "src/**/*"], "exclude": ["node_modules"] } \ No newline at end of file