Skip to content

Commit 5420b5f

Browse files
Improved testing options (#460)
* Improved testing options * Review feedback * Fix typo * Slight tweaks * Allow multiple browsers or metrics * Add e2e test * Test action * Revert test * Revert properly * Chrome tests * Inly unit tests for now * Retry Chrome tests * Comment * Disable gpu * Try some mroe options * One more try * Onre more, one more try * Give up, leave to just unit tests * Rename test to make clear * Try MacOS * Set screensize * More tests * Set better standard size * Plit out tests * Revert back to one file * Fix flakey test * More flakiness * didn'\t need visibility change * Machines * Firefox to MacOS * Make command line flags case insensitive * Revert test change * Add rAF * Fixup CLS tests * Fix one genuine 0 * Add await * Clear beacons * Add another await * More gte to gt * strictEquals * Clean up * See if equals now works --------- Co-authored-by: Philip Walton <[email protected]>
1 parent 79d6f28 commit 5420b5f

File tree

9 files changed

+155
-60
lines changed

9 files changed

+155
-60
lines changed

Diff for: .github/workflows/lint.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ on:
88
jobs:
99
lint:
1010
name: Lint Code Base
11-
runs-on: ubuntu-20.04
11+
runs-on: ubuntu-latest
1212
steps:
1313
- name: Checkout Code
14-
uses: actions/checkout@v3
14+
uses: actions/checkout@v4
1515
- name: NPM install
1616
run: npm install
1717
- name: Run Prettier

Diff for: .github/workflows/tests.yml

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Run tests
2+
on:
3+
pull_request:
4+
push:
5+
branches:
6+
- main
7+
workflow_dispatch:
8+
jobs:
9+
unit-tests:
10+
name: Run unit tests
11+
# Doesn't require anything special so let's use ubuntu as more available
12+
runs-on: ubuntu-latest
13+
steps:
14+
- name: Checkout Code
15+
uses: actions/checkout@v4
16+
- name: NPM install
17+
run: npm install
18+
- name: Build
19+
run: npm run build
20+
- name: Run unit tests
21+
run: npm run test:unit
22+
chrome-tests:
23+
name: Run Chrome e2e tests
24+
# Runs best on macos for CI as linux requires extra chrome flags
25+
runs-on: macos-latest
26+
steps:
27+
- name: Checkout Code
28+
uses: actions/checkout@v4
29+
- name: NPM install
30+
run: npm install
31+
- name: Build
32+
run: npm run build
33+
- name: Run server
34+
run: npm run test:server &
35+
- name: Run e2e tests for chrome
36+
run: npm run test:e2e -- --browsers=chrome
37+
firefox-tests:
38+
name: Run Firefox e2e tests
39+
# Runs best on macos for CI as linux requires extra setup
40+
runs-on: macos-latest
41+
steps:
42+
- name: Checkout Code
43+
uses: actions/checkout@v4
44+
- name: NPM install
45+
run: npm install
46+
- name: Build
47+
run: npm run build
48+
- name: Run server
49+
run: npm run test:server &
50+
- name: Run e2e tests for firefox
51+
run: npm run test:e2e -- --browsers=firefox
52+
safari-tests:
53+
name: Run Safari e2e tests
54+
# Requires macos
55+
runs-on: macos-latest
56+
steps:
57+
- name: Checkout Code
58+
uses: actions/checkout@v4
59+
- name: NPM install
60+
run: npm install
61+
- name: Build
62+
run: npm run build
63+
- name: Run server
64+
run: npm run test:server &
65+
- name: Run e2e tests for safari
66+
run: npm run test:e2e -- --browsers=safari

Diff for: .husky/pre-commit

+8
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,11 @@
22
. "$(dirname -- "$0")/_/husky.sh"
33

44
npm exec lint-staged
5+
6+
grep -r "\.only(" test/e2e \
7+
&& echo "ERROR: found .only() use in test" && exit 1
8+
9+
grep -r "browser\.debug(" test/e2e \
10+
&& echo "ERROR: found browser.debug() use in test" && exit 1
11+
12+
exit 0
File renamed without changes.

Diff for: docs/contributing.md renamed to CONTRIBUTING.md

+20
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,26 @@ use GitHub pull requests for this purpose. Consult
2222
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
2323
information on using pull requests.
2424

25+
## Testing
26+
27+
To test the full suite run `npm run test`.
28+
29+
To test a subset of browsers or metrics, run the following in separate terminals:
30+
31+
- `npm run watch`
32+
- `npm run test:server`
33+
- `npm run test:e2e -- --browsesr=chrome --metrics=TTFB`
34+
35+
The last command can be replaced as you see fit and include comma, separated values. For example:
36+
37+
- `npm run test:e2e -- --browsesr=chrome,firefox --metrics=TTFB,LCP`
38+
39+
To run an individual test, change `it('test name')` to `it.only('test name')`.
40+
41+
You can also add `await browser.debug()` lines to the individual test files to pause execution, and press `CTRL+C` in the command line to continue the tests.
42+
43+
See the https://webdriver.io/ for more information.
44+
2545
## Community Guidelines
2646

2747
This project follows [Google's Open Source Community

Diff for: package-lock.json

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@
164164
"rollup": "^4.9.1",
165165
"selenium-standalone": "^9.3.1",
166166
"typescript": "^5.3.3",
167-
"wdio-chromedriver-service": "^8.1.1"
167+
"wdio-chromedriver-service": "^8.1.1",
168+
"yargs": "^17.7.2"
168169
},
169170
"lint-staged": {
170171
"**/*.{js,ts}": "eslint --fix --ignore-path .gitignore",

Diff for: test/e2e/onCLS-test.js

+32-28
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ describe('onCLS()', async function () {
3131
let browserSupportsCLS;
3232
before(async function () {
3333
browserSupportsCLS = await browserSupportsEntry('layout-shift');
34+
35+
// Set a standard screen size so thresholds are the same
36+
browser.setWindowSize(1280, 1024);
3437
});
3538

3639
beforeEach(async function () {
@@ -50,7 +53,7 @@ describe('onCLS()', async function () {
5053
await beaconCountIs(1);
5154

5255
const [cls] = await getBeacons();
53-
assert(cls.value >= 0);
56+
assert(cls.value > 0);
5457
assert(cls.id.match(/^v4-\d+-\d+$/));
5558
assert.strictEqual(cls.name, 'CLS');
5659
assert.strictEqual(cls.value, cls.delta);
@@ -71,7 +74,7 @@ describe('onCLS()', async function () {
7174
await beaconCountIs(1);
7275

7376
const [cls] = await getBeacons();
74-
assert(cls.value >= 0);
77+
assert(cls.value > 0);
7578
assert(cls.id.match(/^v4-\d+-\d+$/));
7679
assert.strictEqual(cls.name, 'CLS');
7780
assert.strictEqual(cls.value, cls.delta);
@@ -92,7 +95,7 @@ describe('onCLS()', async function () {
9295
await beaconCountIs(1);
9396

9497
const [cls] = await getBeacons();
95-
assert(cls.value >= 0);
98+
assert(cls.value > 0);
9699
assert(cls.id.match(/^v4-\d+-\d+$/));
97100
assert.strictEqual(cls.name, 'CLS');
98101
assert.strictEqual(cls.value, cls.delta);
@@ -117,7 +120,7 @@ describe('onCLS()', async function () {
117120
await beaconCountIs(1);
118121

119122
const [cls] = await getBeacons();
120-
assert(cls.value >= 0);
123+
assert(cls.value > 0);
121124
assert(cls.id.match(/^v4-\d+-\d+$/));
122125
assert.strictEqual(cls.name, 'CLS');
123126
assert.strictEqual(cls.value, cls.delta);
@@ -140,7 +143,7 @@ describe('onCLS()', async function () {
140143

141144
const [cls1] = await getBeacons();
142145

143-
assert(cls1.value >= 0);
146+
assert(cls1.value > 0);
144147
assert(cls1.id.match(/^v4-\d+-\d+$/));
145148
assert.strictEqual(cls1.name, 'CLS');
146149
assert.strictEqual(cls1.value, cls1.delta);
@@ -268,7 +271,7 @@ describe('onCLS()', async function () {
268271
assert.strictEqual(cls1.entries.length, 0);
269272
assert.match(cls1.navigationType, /navigate|reload/);
270273

271-
assert(cls2.value >= 0);
274+
assert(cls2.value > 0);
272275
assert.strictEqual(cls2.name, 'CLS');
273276
assert.strictEqual(cls2.id, cls1.id);
274277
assert.strictEqual(cls2.value, cls1.delta + cls2.delta);
@@ -312,7 +315,7 @@ describe('onCLS()', async function () {
312315
assert.strictEqual(cls1.entries.length, 0);
313316
assert.match(cls1.navigationType, /navigate|reload/);
314317

315-
assert(cls2.value >= 0);
318+
assert(cls2.value > 0);
316319
assert.strictEqual(cls2.name, 'CLS');
317320
assert.strictEqual(cls2.id, cls1.id);
318321
assert.strictEqual(cls2.value, cls1.delta + cls2.delta);
@@ -352,8 +355,8 @@ describe('onCLS()', async function () {
352355

353356
const [cls1] = await getBeacons();
354357

355-
assert(cls1.value >= 0);
356-
assert(cls1.delta >= 0);
358+
assert(cls1.value > 0);
359+
assert(cls1.delta > 0);
357360
assert(cls1.id.match(/^v4-\d+-\d+$/));
358361
assert.strictEqual(cls1.name, 'CLS');
359362
assert.strictEqual(cls1.value, cls1.delta);
@@ -399,7 +402,7 @@ describe('onCLS()', async function () {
399402
assert.strictEqual(cls1.entries.length, 0);
400403
assert.match(cls1.navigationType, /navigate|reload/);
401404

402-
assert(cls2.value >= 0);
405+
assert(cls2.value > 0);
403406
assert.strictEqual(cls2.name, 'CLS');
404407
assert.strictEqual(cls2.id, cls1.id);
405408
assert.strictEqual(cls2.value, cls1.delta + cls2.delta);
@@ -450,7 +453,7 @@ describe('onCLS()', async function () {
450453

451454
const [cls1] = await getBeacons();
452455

453-
assert(cls1.value >= 0);
456+
assert(cls1.value > 0);
454457
assert(cls1.id.match(/^v4-\d+-\d+$/));
455458
assert.strictEqual(cls1.delta, cls1.value);
456459
assert.strictEqual(cls1.name, 'CLS');
@@ -467,7 +470,7 @@ describe('onCLS()', async function () {
467470

468471
const [cls2] = await getBeacons();
469472

470-
assert(cls2.value >= 0);
473+
assert(cls2.value > 0);
471474
assert(cls2.id.match(/^v4-\d+-\d+$/));
472475
assert(cls2.id !== cls1.id);
473476

@@ -485,7 +488,7 @@ describe('onCLS()', async function () {
485488

486489
const [cls3] = await getBeacons();
487490

488-
assert(cls3.value >= 0);
491+
assert(cls3.value > 0);
489492
assert(cls3.id.match(/^v4-\d+-\d+$/));
490493
assert(cls3.id !== cls2.id);
491494

@@ -512,7 +515,7 @@ describe('onCLS()', async function () {
512515
assert.strictEqual(cls1.entries.length, 0);
513516
assert.match(cls1.navigationType, /navigate|reload/);
514517

515-
assert(cls2.value >= 0);
518+
assert(cls2.value > 0);
516519
assert.strictEqual(cls2.name, 'CLS');
517520
assert.strictEqual(cls2.id, cls1.id);
518521
assert.strictEqual(cls2.value, cls1.delta + cls2.delta);
@@ -658,12 +661,12 @@ describe('onCLS()', async function () {
658661
it('reports if the page is restored from bfcache even when the document was hidden at page load time', async function () {
659662
if (!browserSupportsCLS) this.skip();
660663

661-
await navigateTo('/test/cls?hidden=1');
664+
await navigateTo('/test/cls?hidden=1', {readyState: 'complete'});
662665

663666
await stubForwardBack();
664667

665-
// Wait for a frame to be painted.
666-
await nextFrame();
668+
// clear any beacons from page load.
669+
await clearBeacons();
667670

668671
await triggerLayoutShift();
669672

@@ -672,7 +675,7 @@ describe('onCLS()', async function () {
672675

673676
const [cls] = await getBeacons();
674677

675-
assert(cls.value >= 0);
678+
assert(cls.value > 0);
676679
assert(cls.id.match(/^v4-\d+-\d+$/));
677680
assert.strictEqual(cls.name, 'CLS');
678681
assert.strictEqual(cls.delta, cls.value);
@@ -693,7 +696,7 @@ describe('onCLS()', async function () {
693696
await beaconCountIs(1);
694697
const [cls] = await getBeacons();
695698

696-
assert(cls.value >= 0);
699+
assert(cls.value > 0);
697700
assert(cls.id.match(/^v4-\d+-\d+$/));
698701
assert.strictEqual(cls.name, 'CLS');
699702
assert.strictEqual(cls.value, cls.delta);
@@ -714,7 +717,7 @@ describe('onCLS()', async function () {
714717
await beaconCountIs(1);
715718
const [cls] = await getBeacons();
716719

717-
assert(cls.value >= 0);
720+
assert(cls.value > 0);
718721
assert(cls.id.match(/^v4-\d+-\d+$/));
719722
assert.strictEqual(cls.name, 'CLS');
720723
assert.strictEqual(cls.value, cls.delta);
@@ -736,7 +739,7 @@ describe('onCLS()', async function () {
736739
await beaconCountIs(1);
737740

738741
const [cls] = await getBeacons();
739-
assert(cls.value >= 0);
742+
assert(cls.value > 0);
740743
assert(cls.id.match(/^v4-\d+-\d+$/));
741744
assert.strictEqual(cls.name, 'CLS');
742745
assert.strictEqual(cls.value, cls.delta);
@@ -782,7 +785,7 @@ describe('onCLS()', async function () {
782785
await beaconCountIs(1);
783786
const [cls] = await getBeacons();
784787

785-
assert(cls.value >= 0);
788+
assert(cls.value > 0);
786789
assert(cls.id.match(/^v4-\d+-\d+$/));
787790
assert.strictEqual(cls.name, 'CLS');
788791
assert.strictEqual(cls.value, cls.delta);
@@ -822,7 +825,7 @@ describe('onCLS()', async function () {
822825
await beaconCountIs(1);
823826
const [cls] = await getBeacons();
824827

825-
assert(cls.value >= 0);
828+
assert.strictEqual(cls.value, 0);
826829
assert(cls.id.match(/^v4-\d+-\d+$/));
827830
assert.strictEqual(cls.name, 'CLS');
828831
assert.strictEqual(cls.value, cls.delta);
@@ -838,14 +841,15 @@ describe('onCLS()', async function () {
838841
let marginTop = 0;
839842

840843
/**
841-
* Returns a promise that resolves once the browser window has loaded and all
842-
* the images in the document have decoded and rendered.
843-
* @return {Promise<void>}
844+
* Adds
845+
* @return {void}
844846
*/
845-
function triggerLayoutShift() {
846-
return browser.execute((marginTop) => {
847+
async function triggerLayoutShift() {
848+
await browser.execute((marginTop) => {
847849
document.querySelector('h1').style.marginTop = marginTop + 'em';
848850
}, ++marginTop);
851+
// Wait for a frame to be painted to ensure shifts are finished painting.
852+
await nextFrame();
849853
}
850854

851855
/**

0 commit comments

Comments
 (0)