@ai-ecoverse/slicc-shared-web 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/harness/cdn.mjs +35 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ test('boots', async (t) => {
|
|
|
59
59
|
| `isolated` | Send COOP, COEP and CORP on every response, so pages are cross-origin isolated | `false` |
|
|
60
60
|
| `coverage` | URL prefixes whose `.js`/`.mjs` scripts count for coverage. `node_modules/` never does. A `.map` next to a file is used | `['/']` |
|
|
61
61
|
| `exits` | `{ urlPath: [regex, ...] }`: a breakpoint on the first line matching each pattern in that worker script, where the harness takes the worker's coverage and profile before it closes itself | none |
|
|
62
|
-
| `intercept` | Remote URL prefixes answered from a disk cache in `node_modules/.cache
|
|
62
|
+
| `intercept` | Remote URL prefixes answered from a disk cache in `node_modules/.cache/`. Registry documents (anything on a `registry.*` host but a `/-/….tgz` tarball: packuments, abbreviated or full, and dist-tags) are fetched fresh once per test process and only served from the disk cache when the registry can't be reached (a `4xx` is passed on) | none |
|
|
63
63
|
| `extensions` | Unpacked extension directories to load. Their scripts are covered and profiled like the repo's own, and tests then run in the default browser context, closing their tabs when they end, because Chrome does not run extensions in the per-test contexts | none |
|
|
64
64
|
| `args` | Extra Chromium flags, such as `--host-resolver-rules` or `--ignore-certificate-errors` | none |
|
|
65
65
|
| `timeout` | How long `page.until` polls and `page.evaluate` waits, in ms | `30000` |
|
|
@@ -89,6 +89,7 @@ Why it works the way it does:
|
|
|
89
89
|
- `takePreciseCoverage` resets the counters, so every snapshot is a delta, and all of them are kept and summed.
|
|
90
90
|
- monocart's `add()` from parallel test processes loses data, so each test writes raw JSON and the teardown merges it once.
|
|
91
91
|
- Coverage of a script served from `chrome.overrides` would be mapped onto the file on disk, so a path overridden during a test is left out of that test's coverage.
|
|
92
|
+
- A CI cache restored with a prefix key kept packuments from before a release, so pnpm in the page saw an outdated `latest` and failed with `ERR_PNPM_NO_MATCHING_VERSION`. Tarballs and versioned CDN files never change and stay cached forever; registry documents do change, so the disk copy is only the offline fallback.
|
|
92
93
|
- `--disable-extensions --disable-component-extensions-with-background-pages` keeps a Hangouts service worker out of every run.
|
|
93
94
|
- The attach event can arrive before `Target.createTarget` returns, so new tabs wait on a slot keyed by target id.
|
|
94
95
|
- A worker blocked in `Atomics.wait`, or one that is already gone, may never answer; snapshots give up after 3 s, and closing a context or the browser after 10 s. A call to a target that detaches or crashes fails instead of waiting forever, and a new tab that never attaches fails after 10 s.
|
package/harness/cdn.mjs
CHANGED
|
@@ -21,18 +21,47 @@ export async function fetched(url, { attempts = 3, ms = DOWNLOAD_TIMEOUT, fetche
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
const fresh = new Map();
|
|
25
|
+
|
|
26
|
+
export function mutable(url) {
|
|
27
|
+
const { hostname, pathname } = new URL(url);
|
|
28
|
+
return hostname.startsWith('registry.') && !/\/-\/[^/]+\.tgz$/.test(pathname);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function save(file, body) {
|
|
32
|
+
await mkdir(dirname(fileURLToPath(file)), { recursive: true });
|
|
33
|
+
const partial = new URL(`${file.href}.${process.pid}`);
|
|
34
|
+
await writeFile(partial, body);
|
|
35
|
+
await rename(partial, file);
|
|
36
|
+
return body;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function refresh(url, file) {
|
|
40
|
+
const body = await fetched(url).catch(async (error) => {
|
|
41
|
+
if (/^4\d\d /.test(error.message)) throw error;
|
|
42
|
+
const stale = await readFile(file).catch(ignore);
|
|
43
|
+
if (!stale) throw error;
|
|
44
|
+
console.warn(`harness: serving cached ${url}: ${error.message}`);
|
|
45
|
+
return null;
|
|
46
|
+
});
|
|
47
|
+
return body ? save(file, body) : readFile(file);
|
|
48
|
+
}
|
|
49
|
+
|
|
24
50
|
export async function download(url) {
|
|
25
51
|
const { host, pathname, search } = new URL(url);
|
|
26
52
|
const query = search ? encodeURIComponent(search) : '';
|
|
27
53
|
const file = new URL(`./${host}${pathname}${query}`.replaceAll('%', '%25'), store);
|
|
54
|
+
if (mutable(url)) {
|
|
55
|
+
if (!fresh.has(url)) {
|
|
56
|
+
const pending = refresh(url, file);
|
|
57
|
+
fresh.set(url, pending);
|
|
58
|
+
pending.catch(() => fresh.delete(url));
|
|
59
|
+
}
|
|
60
|
+
return fresh.get(url);
|
|
61
|
+
}
|
|
28
62
|
const hit = await readFile(file).catch(ignore);
|
|
29
63
|
if (hit) return hit;
|
|
30
|
-
|
|
31
|
-
await mkdir(dirname(fileURLToPath(file)), { recursive: true });
|
|
32
|
-
const partial = new URL(`${file.href}.${process.pid}`);
|
|
33
|
-
await writeFile(partial, body);
|
|
34
|
-
await rename(partial, file);
|
|
35
|
-
return body;
|
|
64
|
+
return save(file, await fetched(url));
|
|
36
65
|
}
|
|
37
66
|
|
|
38
67
|
export async function cdn(cdp, remotes) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-ecoverse/slicc-shared-web",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"description": "Shared Renovate, Biome, TypeScript, lefthook and GitHub Actions configuration, plus the CDP integration-test harness, for SLICC's web repos",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|