1
0
mirror of https://github.com/morris/vanilla-todo.git synced 2025-01-16 20:28:22 +01:00

add basic testing, fix #8

This commit is contained in:
Morris Brodersen 2023-05-13 18:20:50 +02:00
parent 97c1b625a3
commit 9d1c3b7b8f
5 changed files with 143 additions and 2 deletions

View File

@ -532,7 +532,25 @@ Reference:
## 4. Testing
_TODO_
I've implemented one end-to-end test and one unit test
using [Playwright](https://playwright.dev/).
This was straightforward besides small details like the `*.mjs` extension
and the fact that you cannot use named imports when importing from
`public/scripts`.
There's a lot more to explore here, but it's not much different from
testing other frontend stacks. It's actually simpler as there was zero
configuration and just one dependency.
However, it's currently lacking code coverage. Playwright provides some
[code coverage facilities](https://playwright.dev/docs/api/class-coverage)
but it's not straight-forward to produce a standard LCOV report from that,
and it would probably be difficult to unify end-to-end and unit test coverage.
Reference:
- [addItem.test.mjs](./test/e2e/addItem.test.mjs)
- [util.test.mjs](./test/unit/util.test.mjs)
## 5. Assessment
@ -615,6 +633,7 @@ and some opinionated statements based on my experience in the industry.
- Little indirection
- Low coupling
- The result is literally just a bunch of HTML, CSS, and JS files.
- Straight-forward, zero-config testing with Playwright
All source files (HTML, CSS and JS) combine to **under 2400 lines of code**,
including comments and empty lines.
@ -663,6 +682,7 @@ would reduce the comparably low code size (see above) even further.
continuously monitor regressions with extensive test suites.
The cost of browser testing is surely a lot higher
when using a vanilla approach.
- No code coverage from tests
---
@ -805,6 +825,7 @@ Thanks!
### 05/2023
- Add basic testing
- Fix stylelint errors
- Update dependencies

82
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.33.0",
"eslint": "^8.20.0",
"eslint-plugin-compat": "^4.0.2",
"http-server": "^14.1.1",
@ -316,6 +317,25 @@
"node": ">= 8"
}
},
"node_modules/@playwright/test": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz",
"integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==",
"dev": true,
"dependencies": {
"@types/node": "*",
"playwright-core": "1.33.0"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=14"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
@ -328,6 +348,12 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
"node_modules/@types/node": {
"version": "20.1.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==",
"dev": true
},
"node_modules/@types/normalize-package-data": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
@ -1154,6 +1180,20 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
"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,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -2121,6 +2161,18 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/playwright-core": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz",
"integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==",
"dev": true,
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
@ -3352,6 +3404,17 @@
"fastq": "^1.6.0"
}
},
"@playwright/test": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.33.0.tgz",
"integrity": "sha512-YunBa2mE7Hq4CfPkGzQRK916a4tuZoVx/EpLjeWlTVOnD4S2+fdaQZE0LJkbfhN5FTSKNLdcl7MoT5XB37bTkg==",
"dev": true,
"requires": {
"@types/node": "*",
"fsevents": "2.3.2",
"playwright-core": "1.33.0"
}
},
"@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
@ -3364,6 +3427,12 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
"@types/node": {
"version": "20.1.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q==",
"dev": true
},
"@types/normalize-package-data": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
@ -3961,6 +4030,13 @@
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
"dev": true
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -4675,6 +4751,12 @@
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true
},
"playwright-core": {
"version": "1.33.0",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.33.0.tgz",
"integrity": "sha512-aizyPE1Cj62vAECdph1iaMILpT0WUDCq3E6rW6I+dleSbBoGbktvJtzS6VHkZ4DKNEOG9qJpiom/ZxO+S15LAw==",
"dev": true
},
"portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",

View File

@ -7,7 +7,8 @@
"format-check": "prettier --check .",
"lint": "eslint public",
"lint-styles": "stylelint public/styles/*",
"serve": "http-server -c-1 public"
"serve": "http-server -c-1 public",
"test": "playwright test"
},
"repository": {
"type": "git",
@ -26,6 +27,7 @@
},
"homepage": "https://github.com/morris/vanilla-todo#readme",
"devDependencies": {
"@playwright/test": "^1.33.0",
"eslint": "^8.20.0",
"eslint-plugin-compat": "^4.0.2",
"http-server": "^14.1.1",

27
test/e2e/addItem.test.mjs Normal file
View File

@ -0,0 +1,27 @@
import { expect, test } from '@playwright/test';
test("Add item to today's todo list (Enter)", async ({ page }) => {
await page.goto('http://localhost:8080');
const input = page.locator('.-today .todo-item-input > input').filter();
await input.focus();
await input.type('Hello, world!');
await page.keyboard.press('Enter');
await expect(page.locator('.-today .todo-item > .label')).toHaveText(
'Hello, world!'
);
});
test("Add item to today's todo list (click)", async ({ page }) => {
await page.goto('http://localhost:8080');
const input = page.locator('.-today .todo-item-input > input').filter();
await input.focus();
await input.type('Hello, world!');
await page.locator('.-today .todo-item-input > .save').click();
await expect(page.locator('.-today .todo-item > .label')).toHaveText(
'Hello, world!'
);
});

9
test/unit/util.test.mjs Normal file
View File

@ -0,0 +1,9 @@
import { expect, test } from '@playwright/test';
import util from '../../public/scripts/util.js';
test('formatDate', () => {
expect(util.formatDate(new Date(0))).toEqual('January 1st 1970');
expect(util.formatDate(new Date('2023-05-13 12:00:00'))).toEqual(
'May 13th 2023'
);
});