Skip to content

Commit 7eed4b1

Browse files
authored
Merge pull request #94 from koji-1009/chore/vitest-5
chore: update vitest to v5 and type-check the tests
2 parents bc028f3 + a7e73c4 commit 7eed4b1

14 files changed

Lines changed: 256 additions & 666 deletions

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
* **Retry wraps download + verify**: `downloadAndVerify` retries the entire `downloadWithHash` + SHA-256 check as a unit. Do not retry at the HTTP layer alone — a corrupted transfer must re-download from scratch.
77
* **Timeouts use native mechanisms**: HTTP uses `HttpClient`'s `socketTimeout` (idle detection). Git uses `GIT_HTTP_LOW_SPEED_LIMIT`/`GIT_HTTP_LOW_SPEED_TIME` env vars (git-native idle detection) plus `execWithTimeout` (total command timeout). Do not replace with custom polling.
88
* **Cache keys include OS**: Both SDK and pub cache keys include the OS name for easier cache management in the GitHub Actions UI, even though `@actions/cache` internally scopes by runner OS.
9-
* **ESM mocking**: Use `vi.mock()` + `Mocked<typeof>`, not `vi.spyOn()` on module namespaces. Class mocks must use class fields (`get = vi.fn()...`), not prototype methods.
9+
* **ESM mocking**: Use `vi.mock()` + `Mocked<typeof>`, not `vi.spyOn()` on module namespaces. A class passed to `mockImplementation()` must define its members as class fields (`get = vi.fn()...`); prototype methods on it are not reachable from the created instance. Automocked classes (bare `vi.mock()`) do expose prototype methods as mocks.
1010
* **Timeout tests require handler-first ordering**: When testing `execWithTimeout` with fake timers, set up the rejection handler (`expect(promise).rejects`) before advancing timers to avoid unhandled rejections.
1111
* **Test coverage must stay at 100%**: Statements, branches, functions, and lines are all 100%. Run `npx vitest run --coverage` to verify after any change.

‎__tests__/cache.test.ts‎

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { existsSync, readdirSync } from "node:fs";
22
import { join } from "node:path";
33
import { restoreCache, saveCache } from "@actions/cache";
44
import { info, warning } from "@actions/core";
5-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5+
import { afterEach, describe, expect, it, vi } from "vitest";
66
import {
77
getPubCachePaths,
88
isValidLocalSdk,
@@ -146,10 +146,6 @@ describe("isValidLocalSdk", () => {
146146
});
147147

148148
describe("restoreSdkCache", () => {
149-
beforeEach(() => {
150-
vi.clearAllMocks();
151-
});
152-
153149
it("returns true on cache hit", async () => {
154150
// First existsSync call is the pre-restore local check (miss), the
155151
// second validates the restored content (valid).
@@ -215,10 +211,6 @@ describe("restoreSdkCache", () => {
215211
});
216212

217213
describe("saveSdkCache", () => {
218-
beforeEach(() => {
219-
vi.clearAllMocks();
220-
});
221-
222214
it("saves cache successfully", async () => {
223215
vi.mocked(saveCache).mockResolvedValue(1);
224216
await saveSdkCache("/opt/flutter", "key1");
@@ -280,10 +272,6 @@ describe("getPubCachePaths", () => {
280272
});
281273

282274
describe("restorePubCache", () => {
283-
beforeEach(() => {
284-
vi.clearAllMocks();
285-
});
286-
287275
it("returns true on cache hit", async () => {
288276
vi.mocked(restoreCache).mockResolvedValue("key");
289277
const result = await restorePubCache(["/pub-cache"], "key");
@@ -305,10 +293,6 @@ describe("restorePubCache", () => {
305293
});
306294

307295
describe("savePubCache", () => {
308-
beforeEach(() => {
309-
vi.clearAllMocks();
310-
});
311-
312296
it("saves cache when directory is not empty", async () => {
313297
vi.mocked(existsSync).mockReturnValue(true);
314298
vi.mocked(readdirSync).mockReturnValue(["file1"] as unknown as ReturnType<

‎__tests__/git-source.test.ts‎

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ describe("resolveGitRef (original repo + manifest)", () => {
9191
});
9292

9393
describe("resolveGitRef (fork)", () => {
94-
beforeEach(() => {
95-
vi.clearAllMocks();
96-
});
97-
9894
it("resolves branch from ls-remote", async () => {
9995
vi.mocked(exec).mockImplementation(async (_cmd, _args, options) => {
10096
if (options?.listeners?.stdout) {
@@ -180,10 +176,6 @@ describe("resolveGitRef (fork)", () => {
180176
});
181177

182178
describe("resolveGitVersion (original repo + manifest)", () => {
183-
beforeEach(() => {
184-
vi.clearAllMocks();
185-
});
186-
187179
it("resolves a range to the newest matching tagged version", async () => {
188180
const result = await resolveGitVersion(
189181
"https://github.com/flutter/flutter.git",
@@ -264,10 +256,6 @@ describe("resolveGitVersion (original repo + manifest)", () => {
264256
});
265257

266258
describe("resolveGitVersion (fork via ls-remote --tags)", () => {
267-
beforeEach(() => {
268-
vi.clearAllMocks();
269-
});
270-
271259
function mockTags(output: string) {
272260
vi.mocked(exec).mockImplementation(async (_cmd, _args, options) => {
273261
if (options?.listeners?.stdout) {
@@ -479,10 +467,6 @@ describe("resolveGitVersion (fork via ls-remote --tags)", () => {
479467
});
480468

481469
describe("resolveGit (dispatch)", () => {
482-
beforeEach(() => {
483-
vi.clearAllMocks();
484-
});
485-
486470
it("routes range/constraint specs to version resolution", async () => {
487471
const result = await resolveGit(
488472
"https://github.com/flutter/flutter.git",
@@ -589,7 +573,6 @@ describe("installFromGit", () => {
589573
}
590574

591575
beforeEach(() => {
592-
vi.clearAllMocks();
593576
mockExecWithHead(FULL_HASH);
594577
});
595578

‎__tests__/installer.test.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ function mockHttpGetSequence(
7373
}
7474

7575
beforeEach(() => {
76-
vi.clearAllMocks();
7776
mockHttpGetWith(200, String(testBuffer.length));
7877
vi.mocked(extractTar).mockResolvedValue("/opt");
7978
vi.mocked(extractZip).mockResolvedValue("/opt");

‎__tests__/main.test.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
setOutput,
1010
warning,
1111
} from "@actions/core";
12-
import { beforeEach, describe, expect, it, vi } from "vitest";
12+
import { describe, expect, it, vi } from "vitest";
1313
import {
1414
getPubCachePaths,
1515
pubCacheKey,
@@ -130,10 +130,6 @@ function setupDefaultMocks() {
130130
}
131131

132132
describe("main run()", () => {
133-
beforeEach(() => {
134-
vi.clearAllMocks();
135-
});
136-
137133
it("installs latest stable with zero config", async () => {
138134
setupDefaultMocks();
139135
await run();

‎__tests__/post.test.ts‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { getState, info, warning } from "@actions/core";
2-
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
import { describe, expect, it, vi } from "vitest";
33
import { getPubCachePaths, savePubCache, saveSdkCache } from "../src/cache";
44

55
vi.mock("@actions/core");
@@ -16,10 +16,6 @@ function setupState(state: Record<string, string>) {
1616
}
1717

1818
describe("post run()", () => {
19-
beforeEach(() => {
20-
vi.clearAllMocks();
21-
});
22-
2319
it("skips save when installSuccess is false", async () => {
2420
setupState({ installSuccess: "false" });
2521
await run();

‎__tests__/problem-matcher.test.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ describe("flutter-analyzer.json", () => {
289289

290290
describe("registerProblemMatcher()", () => {
291291
beforeEach(() => {
292-
vi.clearAllMocks();
293292
vi.mocked(existsSync).mockImplementation(realFs.existsSync);
294293
});
295294

‎__tests__/version.test.ts‎

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
import { readFileSync } from "node:fs";
22
import { join } from "node:path";
3-
import {
4-
afterEach,
5-
beforeEach,
6-
describe,
7-
expect,
8-
it,
9-
type Mock,
10-
vi,
11-
} from "vitest";
3+
import { afterEach, describe, expect, it, type Mock, vi } from "vitest";
124
import {
135
type FlutterManifest,
146
fetchManifest,
@@ -572,17 +564,13 @@ describe("resolveFromManifest (macos arm64)", () => {
572564
});
573565
});
574566

575-
const { HttpClient } = (await import("@actions/http-client")) as {
576-
HttpClient: Mock;
567+
const { HttpClient } = (await import("@actions/http-client")) as unknown as {
568+
HttpClient: Mock<new () => unknown>;
577569
};
578570

579571
describe("fetchManifest", () => {
580572
const originalEnv = process.env.FLUTTER_STORAGE_BASE_URL;
581573

582-
beforeEach(() => {
583-
vi.clearAllMocks();
584-
});
585-
586574
afterEach(() => {
587575
if (originalEnv === undefined) {
588576
delete process.env.FLUTTER_STORAGE_BASE_URL;

‎dist/post/index.js‎

Lines changed: 1 addition & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -22101,121 +22101,6 @@ var require_browser = __commonJS({
2210122101
}
2210222102
});
2210322103

22104-
// node_modules/has-flag/index.js
22105-
var require_has_flag = __commonJS({
22106-
"node_modules/has-flag/index.js"(exports2, module2) {
22107-
"use strict";
22108-
module2.exports = (flag, argv = process.argv) => {
22109-
const prefix2 = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
22110-
const position = argv.indexOf(prefix2 + flag);
22111-
const terminatorPosition = argv.indexOf("--");
22112-
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
22113-
};
22114-
}
22115-
});
22116-
22117-
// node_modules/supports-color/index.js
22118-
var require_supports_color = __commonJS({
22119-
"node_modules/supports-color/index.js"(exports2, module2) {
22120-
"use strict";
22121-
var os7 = require("os");
22122-
var tty = require("tty");
22123-
var hasFlag = require_has_flag();
22124-
var { env } = process;
22125-
var forceColor;
22126-
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
22127-
forceColor = 0;
22128-
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
22129-
forceColor = 1;
22130-
}
22131-
if ("FORCE_COLOR" in env) {
22132-
if (env.FORCE_COLOR === "true") {
22133-
forceColor = 1;
22134-
} else if (env.FORCE_COLOR === "false") {
22135-
forceColor = 0;
22136-
} else {
22137-
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
22138-
}
22139-
}
22140-
function translateLevel(level) {
22141-
if (level === 0) {
22142-
return false;
22143-
}
22144-
return {
22145-
level,
22146-
hasBasic: true,
22147-
has256: level >= 2,
22148-
has16m: level >= 3
22149-
};
22150-
}
22151-
function supportsColor(haveStream, streamIsTTY) {
22152-
if (forceColor === 0) {
22153-
return 0;
22154-
}
22155-
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
22156-
return 3;
22157-
}
22158-
if (hasFlag("color=256")) {
22159-
return 2;
22160-
}
22161-
if (haveStream && !streamIsTTY && forceColor === void 0) {
22162-
return 0;
22163-
}
22164-
const min = forceColor || 0;
22165-
if (env.TERM === "dumb") {
22166-
return min;
22167-
}
22168-
if (process.platform === "win32") {
22169-
const osRelease = os7.release().split(".");
22170-
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
22171-
return Number(osRelease[2]) >= 14931 ? 3 : 2;
22172-
}
22173-
return 1;
22174-
}
22175-
if ("CI" in env) {
22176-
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
22177-
return 1;
22178-
}
22179-
return min;
22180-
}
22181-
if ("TEAMCITY_VERSION" in env) {
22182-
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
22183-
}
22184-
if (env.COLORTERM === "truecolor") {
22185-
return 3;
22186-
}
22187-
if ("TERM_PROGRAM" in env) {
22188-
const version3 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
22189-
switch (env.TERM_PROGRAM) {
22190-
case "iTerm.app":
22191-
return version3 >= 3 ? 3 : 2;
22192-
case "Apple_Terminal":
22193-
return 2;
22194-
}
22195-
}
22196-
if (/-256(color)?$/i.test(env.TERM)) {
22197-
return 2;
22198-
}
22199-
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
22200-
return 1;
22201-
}
22202-
if ("COLORTERM" in env) {
22203-
return 1;
22204-
}
22205-
return min;
22206-
}
22207-
function getSupportLevel(stream) {
22208-
const level = supportsColor(stream, stream && stream.isTTY);
22209-
return translateLevel(level);
22210-
}
22211-
module2.exports = {
22212-
supportsColor: getSupportLevel,
22213-
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
22214-
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
22215-
};
22216-
}
22217-
});
22218-
2221922104
// node_modules/debug/src/node.js
2222022105
var require_node = __commonJS({
2222122106
"node_modules/debug/src/node.js"(exports2, module2) {
@@ -22234,7 +22119,7 @@ var require_node = __commonJS({
2223422119
);
2223522120
exports2.colors = [6, 2, 3, 4, 5, 1];
2223622121
try {
22237-
const supportsColor = require_supports_color();
22122+
const supportsColor = require("supports-color");
2223822123
if (supportsColor && (supportsColor.stderr || supportsColor).level >= 2) {
2223922124
exports2.colors = [
2224022125
20,

0 commit comments

Comments
 (0)