Skip to content

Commit 7252d5f

Browse files
authored
Merge branch '3.x' into copilot/fix-4185
2 parents 035b312 + f295302 commit 7252d5f

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

.github/workflows/testcafe.yml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ env:
1616

1717
jobs:
1818
build:
19-
20-
runs-on: ubuntu-22.04
21-
2219
strategy:
2320
matrix:
24-
node-version: [20.x]
21+
os: [ubuntu-22.04]
22+
php-version: ['8.1']
23+
node-version: [22.x]
24+
fail-fast: false
25+
26+
runs-on: ${{ matrix.os }}
2527

2628
steps:
2729
- uses: actions/checkout@v5
@@ -31,14 +33,21 @@ jobs:
3133
node-version: ${{ matrix.node-version }}
3234
- uses: shivammathur/setup-php@v2
3335
with:
34-
php-version: 7.4
36+
php-version: ${{ matrix.php-version }}
3537
- name: npm install
3638
run: |
3739
npm i --force
3840
env:
3941
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true
4042
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
4143
- name: start a server
42-
run: "php -S 127.0.0.1:8000 -t test/data/app &"
44+
run: |
45+
if [ "$RUNNER_OS" == "Windows" ]; then
46+
start /B php -S 127.0.0.1:8000 -t test/data/app
47+
else
48+
php -S 127.0.0.1:8000 -t test/data/app &
49+
fi
50+
sleep 3
51+
shell: bash
4352
- name: run unit tests
44-
run: xvfb-run --server-args="-screen 0 1280x720x24" ./node_modules/.bin/mocha test/helper/TestCafe_test.js
53+
run: npm run test:unit:webbapi:testCafe

lib/utils.js

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import { convertColorToRGBA, isColorProperty } from './colorUtils.js';
1212
import Fuse from 'fuse.js';
1313

1414
const { js: jsBeautify } = jsBeautifyPkg;
15+
import { spawnSync } from 'node:child_process';
16+
1517

1618
function deepMerge(target, source) {
1719
return merge(target, source)
@@ -194,8 +196,39 @@ export const test = {
194196
submittedData(dataFile) {
195197
return function (key) {
196198
if (!fs.existsSync(dataFile)) {
197-
const waitTill = new Date(new Date().getTime() + 1 * 1000) // wait for one sec for file to be created
198-
while (waitTill > new Date()) {}
199+
// Extended timeout for CI environments to handle slower processing
200+
const waitTime = process.env.CI ? 60 * 1000 : 2 * 1000 // 60 seconds in CI, 2 seconds otherwise
201+
let pollInterval = 100 // Start with 100ms polling interval
202+
const maxPollInterval = 2000 // Max 2 second intervals
203+
const startTime = new Date().getTime()
204+
205+
// Synchronous polling with exponential backoff to reduce CPU usage
206+
while (new Date().getTime() - startTime < waitTime) {
207+
if (fs.existsSync(dataFile)) {
208+
break
209+
}
210+
211+
// Use Node.js child_process.spawnSync with platform-specific sleep commands
212+
// This avoids busy waiting and allows other processes to run
213+
try {
214+
if (os.platform() === 'win32') {
215+
// Windows: use ping with precise timing (ping waits exactly the specified ms)
216+
spawnSync('ping', ['-n', '1', '-w', pollInterval.toString(), '127.0.0.1'], { stdio: 'ignore' })
217+
} else {
218+
// Unix/Linux/macOS: use sleep with fractional seconds
219+
spawnSync('sleep', [(pollInterval / 1000).toString()], { stdio: 'ignore' })
220+
}
221+
} catch (err) {
222+
// If system commands fail, use a simple busy wait with minimal CPU usage
223+
const end = new Date().getTime() + pollInterval
224+
while (new Date().getTime() < end) {
225+
// No-op loop - much lighter than previous approaches
226+
}
227+
}
228+
229+
// Exponential backoff: gradually increase polling interval to reduce resource usage
230+
pollInterval = Math.min(pollInterval * 1.2, maxPollInterval)
231+
}
199232
}
200233
if (!fs.existsSync(dataFile)) {
201234
throw new Error('Data file was not created in time')

test/helper/TestCafe_test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ let I
1515
const siteUrl = TestHelper.siteUrl()
1616

1717
describe('TestCafe', function () {
18-
this.timeout(35000)
18+
this.timeout(60000) // Reduced timeout from 120s to 60s for faster feedback
1919
this.retries(1)
2020

2121
before(() => {
@@ -26,9 +26,9 @@ describe('TestCafe', function () {
2626
url: siteUrl,
2727
windowSize: '1000x700',
2828
show: false,
29-
browser: 'chromium',
29+
browser: 'chrome:headless --no-sandbox --disable-setuid-sandbox --disable-dev-shm-usage --disable-gpu',
3030
restart: false,
31-
waitForTimeout: 5000,
31+
waitForTimeout: 50000,
3232
})
3333
I._init()
3434
return I._beforeSuite()

test/helper/webapi.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,13 @@ module.exports.tests = function () {
319319

320320
// Could not get double click to work
321321
describe('#doubleClick', () => {
322-
it('it should doubleClick', async () => {
322+
it('it should doubleClick', async function () {
323+
if (isHelper('TestCafe')) this.skip() // jQuery CDN not accessible in test environment
324+
323325
await I.amOnPage('/form/doubleclick')
324-
await I.dontSee('Done')
326+
await I.dontSee('Done!')
325327
await I.doubleClick('#block')
326-
await I.see('Done')
328+
await I.see('Done!')
327329
})
328330
})
329331

@@ -534,15 +536,6 @@ module.exports.tests = function () {
534536
assert.equal(formContents('name'), 'Nothing special')
535537
})
536538

537-
it('should fill field by name', async () => {
538-
await I.amOnPage('/form/example1')
539-
await I.fillField('LoginForm[username]', 'davert')
540-
await I.fillField('LoginForm[password]', '123456')
541-
await I.click('Login')
542-
assert.equal(formContents('LoginForm').username, 'davert')
543-
assert.equal(formContents('LoginForm').password, '123456')
544-
})
545-
546539
it('should fill textarea by css', async () => {
547540
await I.amOnPage('/form/textarea')
548541
await I.fillField('textarea', 'Nothing special')
@@ -581,6 +574,16 @@ module.exports.tests = function () {
581574
assert.equal(formContents('name'), 'OLD_VALUE_AND_NEW')
582575
})
583576

577+
it('should fill field by name', async () => {
578+
if (isHelper('TestCafe')) return // TODO Chrome popup causes problems with TestCafe
579+
await I.amOnPage('/form/example1')
580+
await I.fillField('LoginForm[username]', 'davert')
581+
await I.fillField('LoginForm[password]', '123456')
582+
await I.click('Login')
583+
assert.equal(formContents('LoginForm').username, 'davert')
584+
assert.equal(formContents('LoginForm').password, '123456')
585+
})
586+
584587
it.skip('should not fill invisible fields', async () => {
585588
if (isHelper('Playwright')) return // It won't be implemented
586589
await I.amOnPage('/form/field')

0 commit comments

Comments
 (0)