Skip to content

Commit ff5e56a

Browse files
authored
Merge pull request #19 from arethetypeswrong/snapshot-testing
Add snapshot testing for end-to-end testing of core on real data
2 parents 98b850c + 86469fb commit ff5e56a

12 files changed

+450
-3
lines changed

.github/workflows/ci.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ jobs:
1111
steps:
1212
- uses: actions/checkout@v3
1313
- uses: actions/setup-node@v3
14-
- run: npm install -g [email protected]
14+
with:
15+
node-version: 19
1516
- run: npm install
1617
- run: npm run tsc
1718
- run: npm run build

.github/workflows/deploy-web.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ jobs:
99
steps:
1010
- uses: actions/checkout@v3
1111
- uses: actions/setup-node@v3
12-
- run: npm install -g [email protected]
12+
with:
13+
node-version: 19
1314
- run: npm install
1415
- run: npm run tsc
1516
- run: npm run build

.github/workflows/publish-core.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ jobs:
1010
steps:
1111
- uses: actions/checkout@v3
1212
- uses: actions/setup-node@v3
13-
- run: npm install -g [email protected]
13+
with:
14+
node-version: 19
1415
- run: npm install
1516
working-directory: ./packages/core
1617
- run: npm publish

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,8 @@
2121
"@types/node": "^18.11.18",
2222
"prettier": "^2.8.3",
2323
"typescript": "^5.0.0-dev.20230207"
24+
},
25+
"volta": {
26+
"node": "19.8.1"
2427
}
2528
}

packages/core/package.json

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"tsc": "tsc",
2121
"pretest": "tsc -b test",
2222
"test": "node --test test/dist",
23+
"snapshot": "node scripts/createSnapshotFixture.js",
2324
"patch": "npm version patch && npm run commit-patch",
2425
"commit-patch": "git commit -am \"Bump core to v$npm_package_version\" && git tag \"v$npm_package_version\"",
2526
"prepublishOnly": "npm run tsc && npm run test"
@@ -52,5 +53,8 @@
5253
},
5354
"devDependencies": {
5455
"@types/ts-expose-internals": "npm:[email protected]"
56+
},
57+
"volta": {
58+
"node": "19.8.1"
5559
}
5660
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { writeFile } from "fs/promises";
2+
import createFetch from "fetch-ponyfill";
3+
const { fetch } = createFetch();
4+
5+
if (import.meta.url === "file://" + process.argv[1]) {
6+
const [, , packageSpec] = process.argv;
7+
const manifest = await fetchManifest(packageSpec);
8+
const { name, version } = manifest;
9+
console.log(`Resolved '${name}@${version}'`);
10+
const localUrl = await writePackage(manifest);
11+
console.log(`Wrote '${localUrl}'`);
12+
}
13+
14+
/**
15+
* @param {string} packageSpec
16+
*/
17+
async function fetchManifest(packageSpec) {
18+
const versionIndex = packageSpec.indexOf("@", 1);
19+
const packageName = packageSpec.substring(0, versionIndex < 0 ? undefined : versionIndex);
20+
const version = versionIndex < 0 ? "latest" : packageSpec.substring(versionIndex + 1);
21+
const manifestUrl = `https://registry.npmjs.org/${packageName}/${version}`;
22+
return fetch(manifestUrl).then((r) => r.json());
23+
}
24+
25+
/**
26+
* @param {any} manifest
27+
*/
28+
async function writePackage(manifest) {
29+
const localUrl = new URL(`../test/fixtures/${manifest.name.replace("/", "__")}@${manifest.version}.tgz`, import.meta.url);
30+
const tarballUrl = manifest.dist.tarball;
31+
const packageBuffer = await fetch(tarballUrl).then((r) => r.arrayBuffer());
32+
await writeFile(localUrl, Buffer.from(packageBuffer));
33+
return localUrl;
34+
}

packages/core/scripts/tsconfig.json

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"compilerOptions": {
3+
"checkJs": true,
4+
"strict": true,
5+
"noEmit": true,
6+
"target": "esnext",
7+
"module": "nodenext",
8+
"types": [
9+
"node"
10+
]
11+
}
12+
}
8.37 KB
Binary file not shown.
43.2 KB
Binary file not shown.

packages/core/test/snapshots.test.ts

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import fs from "fs";
2+
import { access, readFile, writeFile } from "fs/promises";
3+
import assert from "node:assert";
4+
import { after, describe, test } from "node:test";
5+
import { checkTgz, getProblems, summarizeProblems } from "@arethetypeswrong/core";
6+
7+
const updateSnapshots = process.env.UPDATE_SNAPSHOTS;
8+
9+
describe("snapshots", async () => {
10+
const snapshotsWritten: URL[] = [];
11+
12+
after(() => {
13+
if (updateSnapshots && snapshotsWritten.length > 0) {
14+
console.log(`Updated ${snapshotsWritten.length} snapshots:`);
15+
} else if (snapshotsWritten.length > 0) {
16+
console.log(`Wrote ${snapshotsWritten.length} snapshots:`);
17+
}
18+
19+
if (snapshotsWritten.length > 0) {
20+
console.log(snapshotsWritten.map((url) => ` ${url.pathname}`).join("\n"));
21+
}
22+
});
23+
24+
for (const fixture of fs.readdirSync(new URL("../fixtures", import.meta.url))) {
25+
test(fixture, async () => {
26+
const tarball = await readFile(new URL(`../fixtures/${fixture}`, import.meta.url));
27+
const analysis = await checkTgz(tarball);
28+
assert(analysis.containsTypes);
29+
const problems = getProblems(analysis);
30+
const summary = summarizeProblems(problems, analysis);
31+
const snapshotURL = new URL(`../snapshots/${fixture}.md`, import.meta.url);
32+
const expectedSnapshot = [
33+
`# ${fixture}`,
34+
"",
35+
"## Summary",
36+
"",
37+
"```json",
38+
JSON.stringify(summary, null, 2),
39+
"```",
40+
"",
41+
"## Problems",
42+
"",
43+
"```json",
44+
JSON.stringify(problems, null, 2),
45+
"```",
46+
].join("\n");
47+
48+
if (
49+
await access(snapshotURL)
50+
.then(() => true)
51+
.catch(() => false)
52+
) {
53+
const snapshot = await readFile(snapshotURL, "utf8");
54+
if (updateSnapshots) {
55+
await writeFile(snapshotURL, expectedSnapshot);
56+
snapshotsWritten.push(snapshotURL);
57+
} else {
58+
assert.strictEqual(snapshot, expectedSnapshot);
59+
}
60+
} else {
61+
await writeFile(snapshotURL, expectedSnapshot);
62+
snapshotsWritten.push(snapshotURL);
63+
}
64+
});
65+
}
66+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
2+
3+
## Summary
4+
5+
```json
6+
[
7+
{
8+
"kind": "FalseCJS",
9+
"title": "Types are CJS, but implementation is ESM",
10+
"messages": [
11+
{
12+
"messageText": "Imports of the package under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.",
13+
"messageHtml": "Imports of the package under the <code>node16</code> module resolution setting when the importing module is ESM (its extension is <code>.mts</code> or <code>.mjs</code>, or it has a <code>.ts</code> or <code>.js</code> extension and is in scope of a <code>package.json</code> that contains <code>\"type\"\"module\"</code>) resolved to CJS types, but ESM implementations."
14+
}
15+
]
16+
}
17+
]
18+
```
19+
20+
## Problems
21+
22+
```json
23+
[
24+
{
25+
"kind": "FalseCJS",
26+
"entrypoint": ".",
27+
"resolutionKind": "node16-esm"
28+
}
29+
]
30+
```

0 commit comments

Comments
 (0)