test: use playwright instead of testcafe

This commit is contained in:
Filip Skokan
2026-03-07 18:21:15 +01:00
parent 15b76e26c1
commit b690049b69
7 changed files with 124 additions and 56 deletions
+15 -19
View File
@@ -197,22 +197,14 @@ jobs:
browsers:
needs:
- build
runs-on: ${{ matrix.runs-on || 'ubuntu-latest' }}
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
browser:
- name: chrome
id: chrome:headless
- name: firefox
id: firefox:headless
- name: edge
id: edge:headless
include:
- runs-on: macos-15
browser:
name: safari
id: safari
- chromium
- firefox
- safari
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -222,21 +214,25 @@ jobs:
node-version: lts/*
cache: 'npm'
- run: npm clean-install
- run: npm install --global testcafe@3
- name: Add rows to the TCC.db
if: ${{ matrix.runs-on == 'macos-15' }}
- name: Get Playwright version
id: playwright-version
run: |
sudo sqlite3 "$HOME/Library/Application Support/com.apple.TCC/TCC.db" "INSERT OR REPLACE INTO access VALUES('kTCCServiceAppleEvents','com.devexpress.testcafe-browser-tools',0,2,3,1,X'fade0c0000000068000000010000000700000007000000080000001443fa4ca5141baeda21aeca1f50894673b440d4690000000800000014f8afcf6e69791b283e55bd0b03e39e422745770e0000000800000014bf4fc1aed64c871a49fc6bc9dd3878ce5d4d17c6',NULL,0,'com.apple.Safari',X'fade0c000000002c00000001000000060000000200000010636f6d2e6170706c652e53616661726900000003',NULL,1687952810,NULL,NULL,'UNUSED',1687952810);"
sudo sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" "INSERT OR REPLACE INTO access VALUES('kTCCServiceScreenCapture','com.devexpress.testcafe-browser-tools',0,2,3,1,X'fade0c0000000068000000010000000700000007000000080000001443fa4ca5141baeda21aeca1f50894673b440d4690000000800000014f8afcf6e69791b283e55bd0b03e39e422745770e0000000800000014bf4fc1aed64c871a49fc6bc9dd3878ce5d4d17c6',NULL,0,'UNUSED',NULL,0,1687952810,NULL,NULL,'UNUSED',1687952810);"
echo "version=$(npm list playwright --json | jq -r '.dependencies["@playwright/test"].dependencies.playwright.version')" >>
$GITHUB_OUTPUT
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ~/Library/Caches/ms-playwright
key: playwright-${{ runner.os }}-${{ steps.playwright-version.outputs.version }}
- run: npx playwright install --only-shell chromium firefox webkit
- name: Run Test Suite
run: npm run tap:browsers
env:
BROWSER: ${{ matrix.browser.id }}
BROWSER: ${{ matrix.browser }}
- name: Upload server logs
if: ${{ failure() }}
id: artifact-upload-step
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
path: server.log
name: ${{ matrix.browser.name }} server log
name: ${{ matrix.browser }} server log
if-no-files-found: warn
+1
View File
@@ -42,3 +42,4 @@ tap/.workers.capnp
tap/*.js
tap/run-*.cjs
*.zip
test-results/.last-run.json
+64
View File
@@ -14,6 +14,7 @@
},
"devDependencies": {
"@koa/cors": "^5.0.0",
"@playwright/test": "^1.58.2",
"@types/connect-ensure-login": "^0.1.9",
"@types/cookie-parser": "^1.4.10",
"@types/express": "^5.0.6",
@@ -839,6 +840,22 @@
"node": ">=14"
}
},
"node_modules/@playwright/test": {
"version": "1.58.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz",
"integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright": "1.58.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz",
@@ -4852,6 +4869,53 @@
"node": ">=16.0.0"
}
},
"node_modules/playwright": {
"version": "1.58.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
"integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"playwright-core": "1.58.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.58.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
"integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/playwright/node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/plur": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/plur/-/plur-6.0.0.tgz",
+1
View File
@@ -89,6 +89,7 @@
},
"devDependencies": {
"@koa/cors": "^5.0.0",
"@playwright/test": "^1.58.2",
"@types/connect-ensure-login": "^0.1.9",
"@types/cookie-parser": "^1.4.10",
"@types/express": "^5.0.6",
+12
View File
@@ -0,0 +1,12 @@
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './tap',
testMatch: '.browser.ts',
timeout: 120_000,
projects: [
{ name: 'chromium', use: devices['Desktop Chrome'] },
{ name: 'firefox', use: devices['Desktop Firefox'] },
{ name: 'safari', use: devices['Desktop Safari'] },
],
})
+29 -35
View File
@@ -1,46 +1,40 @@
import { t, ClientFunction } from 'testcafe'
import * as fs from 'node:fs'
import { test, expect } from '@playwright/test'
import { createServer } from 'node:http'
import { readFileSync } from 'node:fs'
const script = fs.readFileSync('./tap/run-browser.js', { encoding: 'utf-8' })
const script = readFileSync('./tap/run-browser.js', 'utf-8')
fixture('test suite').page('https://important-clam-66.deno.dev')
test('passes tests', async ({ page }) => {
const server = createServer((req, res) => {
if (req.url === '/run-browser.js') {
res.writeHead(200, { 'Content-Type': 'application/javascript' })
res.end(script)
} else {
res.writeHead(200, { 'Content-Type': 'text/html' })
res.end(
'<!DOCTYPE html><html><head></head><body><script type="module" src="/run-browser.js"></script></body></html>',
)
}
})
test('passes tests', async (user) => {
await ClientFunction(
() => {
function escapeHTML(str: string) {
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
}
// @ts-expect-error
document.getElementById('js').innerHTML = escapeHTML(innerHTML)
document.querySelector('form')?.submit()
},
{ dependencies: { innerHTML: script } },
)()
await new Promise<void>((resolve) => server.listen(0, resolve))
const port = (server.address() as import('node:net').AddressInfo).port
let i = 0
const interval = setInterval(() => {
t.getBrowserConsoleMessages().then(({ log: messages }) => {
messages.forEach((message, index) => {
if (i && index <= i) return
i++
console.log(message)
})
})
}, 100)
page.on('console', (msg) => {
if (msg.type() === 'log') {
console.log(msg.text())
}
})
await page.goto(`http://localhost:${port}`)
let stats
do {
await new Promise((resolve) => setTimeout(resolve, 1000))
stats = await t.eval(() => globalThis.stats)
await page.waitForTimeout(1000)
stats = await page.evaluate(() => (globalThis as any).stats)
} while (!stats)
clearInterval(interval)
server.close()
await t.expect(stats?.failed).eql(0)
expect(stats.failed).toBe(0)
})
+2 -2
View File
@@ -11,6 +11,6 @@
--outfile=tap/run-browser.js \
tap/run-browser.ts
: "${BROWSER:=chrome:headless}"
: "${BROWSER:=chromium}"
testcafe "$BROWSER" --hostname localhost tap/.browser.ts
npx playwright test --project="$BROWSER"