Skip to content

Commit 38db136

Browse files
authored
Merge pull request #458 from nanasess/feature/bump-tools-cache
build: migrate to ESM and bump @actions/tool-cache to 4.x
2 parents f6b8cbe + 359dcf4 commit 38db136

32 files changed

Lines changed: 32932 additions & 60347 deletions

__tests__/chromedriver-api.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
* Run with: RUN_CHROMEDRIVER_API_TESTS=1 pnpm test __tests__/chromedriver-api.test.ts
66
*/
77

8+
import { jest } from "@jest/globals";
89
import {
910
buildLegacyLatestReleaseUrl,
1011
extractDriverUrlFromJson,
1112
ChromeKnownGoodVersions,
1213
ChromeVersion,
13-
} from "../src/chromedriver-helper";
14+
} from "../src/chromedriver-helper.js";
1415

1516
const JSON_URL =
1617
"https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json";
@@ -47,14 +48,15 @@ describeIfIntegration("Chrome for Testing JSON API", () => {
4748
it("can extract a chromedriver URL from a recent version", () => {
4849
// Find a version that has chromedriver downloads
4950
const withDriver = json.versions.find(
50-
(v: ChromeVersion) => v.downloads.chromedriver && v.downloads.chromedriver.length > 0
51+
(v: ChromeVersion) =>
52+
v.downloads.chromedriver && v.downloads.chromedriver.length > 0,
5153
);
5254
expect(withDriver).toBeDefined();
5355

5456
const url = extractDriverUrlFromJson(
5557
json,
5658
withDriver!.version,
57-
withDriver!.downloads.chromedriver![0].platform
59+
withDriver!.downloads.chromedriver![0].platform,
5860
);
5961
expect(url).not.toBeNull();
6062
expect(url).toMatch(/^https:\/\//);

__tests__/chromedriver-helper.test.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
findFallbackVersion,
1212
getDefaultChromePath,
1313
getInstallPath,
14-
} from "../src/chromedriver-helper";
14+
} from "../src/chromedriver-helper.js";
1515

1616
// ---------------------------------------------------------------------------
1717
// Mock API response fixture
@@ -106,7 +106,7 @@ describe("parseVersion3", () => {
106106

107107
it("throws when version has fewer than 3 parts", () => {
108108
expect(() => parseVersion3("115.0")).toThrow(
109-
"Version must have at least 3 parts"
109+
"Version must have at least 3 parts",
110110
);
111111
});
112112
});
@@ -180,21 +180,21 @@ describe("convertArchForModernAPI", () => {
180180
describe("buildLegacyLatestReleaseUrl", () => {
181181
it("builds correct URL for version 114", () => {
182182
expect(buildLegacyLatestReleaseUrl(114)).toBe(
183-
"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_114"
183+
"https://chromedriver.storage.googleapis.com/LATEST_RELEASE_114",
184184
);
185185
});
186186
});
187187

188188
describe("buildLegacyDownloadUrl", () => {
189189
it("builds correct download URL", () => {
190190
expect(buildLegacyDownloadUrl("114.0.5735.90", "linux64")).toBe(
191-
"https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip"
191+
"https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip",
192192
);
193193
});
194194

195195
it("builds correct URL for mac64", () => {
196196
expect(buildLegacyDownloadUrl("114.0.5735.90", "mac64")).toBe(
197-
"https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_mac64.zip"
197+
"https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_mac64.zip",
198198
);
199199
});
200200
});
@@ -204,29 +204,29 @@ describe("extractDriverUrlFromJson", () => {
204204
const url = extractDriverUrlFromJson(
205205
MOCK_API_RESPONSE,
206206
"131.0.6778.204",
207-
"linux64"
207+
"linux64",
208208
);
209209
expect(url).toBe(
210-
"https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/linux64/chromedriver-linux64.zip"
210+
"https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/linux64/chromedriver-linux64.zip",
211211
);
212212
});
213213

214214
it("extracts URL for mac-arm64", () => {
215215
const url = extractDriverUrlFromJson(
216216
MOCK_API_RESPONSE,
217217
"131.0.6778.204",
218-
"mac-arm64"
218+
"mac-arm64",
219219
);
220220
expect(url).toBe(
221-
"https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/mac-arm64/chromedriver-mac-arm64.zip"
221+
"https://storage.googleapis.com/chrome-for-testing-public/131.0.6778.204/mac-arm64/chromedriver-mac-arm64.zip",
222222
);
223223
});
224224

225225
it("returns null for non-existent version", () => {
226226
const url = extractDriverUrlFromJson(
227227
MOCK_API_RESPONSE,
228228
"999.0.0.0",
229-
"linux64"
229+
"linux64",
230230
);
231231
expect(url).toBeNull();
232232
});
@@ -235,7 +235,7 @@ describe("extractDriverUrlFromJson", () => {
235235
const url = extractDriverUrlFromJson(
236236
MOCK_API_RESPONSE,
237237
"114.0.5735.90",
238-
"win32"
238+
"win32",
239239
);
240240
expect(url).toBeNull();
241241
});
@@ -274,27 +274,27 @@ describe("findFallbackVersion", () => {
274274
describe("getDefaultChromePath", () => {
275275
it("returns google-chrome-stable for linux", () => {
276276
expect(getDefaultChromePath("linux" as NodeJS.Platform)).toBe(
277-
"google-chrome-stable"
277+
"google-chrome-stable",
278278
);
279279
});
280280

281281
it("returns macOS app path for darwin", () => {
282282
expect(getDefaultChromePath("darwin")).toBe(
283-
"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/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
283+
"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/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
284284
);
285285
});
286286

287287
it("returns Windows exe path for win32", () => {
288288
expect(getDefaultChromePath("win32")).toBe(
289-
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
289+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
290290
);
291291
});
292292
});
293293

294294
describe("getInstallPath", () => {
295295
it("returns /usr/local/bin/chromedriver for linux", () => {
296296
expect(getInstallPath("linux" as NodeJS.Platform)).toBe(
297-
"/usr/local/bin/chromedriver"
297+
"/usr/local/bin/chromedriver",
298298
);
299299
});
300300

@@ -304,7 +304,7 @@ describe("getInstallPath", () => {
304304

305305
it("returns Windows SeleniumWebDrivers path for win32", () => {
306306
expect(getInstallPath("win32")).toBe(
307-
"C:\\SeleniumWebDrivers\\ChromeDriver"
307+
"C:\\SeleniumWebDrivers\\ChromeDriver",
308308
);
309309
});
310310
});

__tests__/chromedriver.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,41 @@
11
import { Builder, Capabilities, until } from "selenium-webdriver";
2-
import * as chrome from "selenium-webdriver/chrome";
2+
// ESM (the project is "type":"module") requires an explicit extension for this
3+
// CJS subpath; without it Node throws ERR_MODULE_NOT_FOUND under ts-node.
4+
import * as chrome from "selenium-webdriver/chrome.js";
35

46
(async () => {
57
const timeout = 30000;
6-
8+
79
// Chrome options for better compatibility, especially on macOS
810
const options = new chrome.Options();
911
options.addArguments(
10-
'--no-sandbox',
11-
'--disable-dev-shm-usage',
12-
'--disable-gpu',
13-
'--disable-web-security',
14-
'--disable-features=VizDisplayCompositor',
15-
'--remote-debugging-port=9222',
16-
'--disable-background-timer-throttling',
17-
'--disable-backgrounding-occluded-windows',
18-
'--disable-renderer-backgrounding'
12+
"--no-sandbox",
13+
"--disable-dev-shm-usage",
14+
"--disable-gpu",
15+
"--disable-web-security",
16+
"--disable-features=VizDisplayCompositor",
17+
"--remote-debugging-port=9222",
18+
"--disable-background-timer-throttling",
19+
"--disable-backgrounding-occluded-windows",
20+
"--disable-renderer-backgrounding",
1921
);
20-
22+
2123
// Add headless mode for CI environments
2224
if (process.env.CI) {
23-
options.addArguments('--headless=new');
25+
options.addArguments("--headless=new");
2426
}
25-
27+
2628
// Set a custom user data directory to avoid permission issues
27-
const userDataDir = process.platform === 'darwin'
28-
? '/tmp/chrome-user-data-' + Date.now()
29-
: undefined;
29+
const userDataDir =
30+
process.platform === "darwin"
31+
? "/tmp/chrome-user-data-" + Date.now()
32+
: undefined;
3033
if (userDataDir) {
3134
options.addArguments(`--user-data-dir=${userDataDir}`);
3235
}
33-
36+
3437
const driver = new Builder()
35-
.forBrowser('chrome')
38+
.forBrowser("chrome")
3639
.setChromeOptions(options)
3740
.build();
3841
try {

__tests__/equivalence.test.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import { execSync } from "child_process";
99
import * as path from "path";
10+
import { fileURLToPath } from "url";
1011
import {
1112
parseMajorVersion,
1213
parseVersion3,
@@ -19,7 +20,10 @@ import {
1920
getInstallPath,
2021
extractDriverUrlFromJson,
2122
findFallbackVersion,
22-
} from "../src/chromedriver-helper";
23+
} from "../src/chromedriver-helper.js";
24+
25+
// ESM has no __dirname; derive this file's directory from import.meta.url.
26+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
2327

2428
// ---------------------------------------------------------------------------
2529
// Run shell script and parse output
@@ -164,7 +168,7 @@ describe("Shell ↔ TypeScript equivalence", () => {
164168
for (const line of lines) {
165169
const kv = parseKeyValue(line);
166170
expect(buildLegacyDownloadUrl(kv["VERSION"], kv["ARCH"])).toBe(
167-
kv["URL"]
171+
kv["URL"],
168172
);
169173
}
170174
});
@@ -175,9 +179,9 @@ describe("Shell ↔ TypeScript equivalence", () => {
175179
const lines = parseSection(shellOutput, "DEFAULT_CHROME_PATH");
176180
for (const line of lines) {
177181
const kv = parseKeyValue(line);
178-
expect(
179-
getDefaultChromePath(kv["PLATFORM"] as NodeJS.Platform)
180-
).toBe(kv["PATH"]);
182+
expect(getDefaultChromePath(kv["PLATFORM"] as NodeJS.Platform)).toBe(
183+
kv["PATH"],
184+
);
181185
}
182186
});
183187
});
@@ -188,7 +192,7 @@ describe("Shell ↔ TypeScript equivalence", () => {
188192
for (const line of lines) {
189193
const kv = parseKeyValue(line);
190194
expect(getInstallPath(kv["PLATFORM"] as NodeJS.Platform)).toBe(
191-
kv["PATH"]
195+
kv["PATH"],
192196
);
193197
}
194198
});
@@ -202,7 +206,7 @@ describe("Shell ↔ TypeScript equivalence", () => {
202206
const result = extractDriverUrlFromJson(
203207
TEST_JSON,
204208
kv["VERSION"],
205-
kv["PLATFORM"]
209+
kv["PLATFORM"],
206210
);
207211
const expected = kv["URL"] === "null" ? null : kv["URL"];
208212
expect(result).toBe(expected);

__tests__/installer-download.test.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,23 @@
22
* Unit tests for src/installer/download.ts.
33
*
44
* @actions/tool-cache is mocked so no real network or filesystem I/O occurs.
5+
*
6+
* The project is ESM, so the mock is registered with
7+
* `jest.unstable_mockModule` and both the mocked module and the module under
8+
* test are pulled in with dynamic `import()` *after* the mock is in place.
59
*/
610

7-
import * as tc from "@actions/tool-cache";
8-
import { downloadAndExtractZip } from "../src/installer/download";
11+
import { jest } from "@jest/globals";
12+
13+
jest.unstable_mockModule("@actions/tool-cache", () => ({
14+
downloadTool: jest.fn(),
15+
extractZip: jest.fn(),
16+
}));
917

10-
jest.mock("@actions/tool-cache");
18+
const tc = await import("@actions/tool-cache");
19+
const { downloadAndExtractZip } = await import("../src/installer/download.js");
1120

12-
const mockedTc = tc as jest.Mocked<typeof tc>;
21+
const mockedTc = jest.mocked(tc);
1322

1423
describe("downloadAndExtractZip", () => {
1524
beforeEach(() => {

__tests__/installer-http.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,21 @@
1313
* typed-rest-client is mocked so no real network I/O occurs.
1414
*/
1515

16+
import { jest } from "@jest/globals";
17+
1618
// Shared mock for the HttpClient instance method `get`. The module under test
1719
// constructs a single client at load time, so the constructor mock must return
18-
// an object backed by this shared mock.
19-
const mockGet = jest.fn();
20+
// an object backed by this shared mock. Declared before the mock factory so it
21+
// is captured by the closure when `await import()` evaluates http.ts.
22+
const mockGet = jest.fn() as jest.Mock<(url: string) => Promise<unknown>>;
2023

21-
jest.mock("typed-rest-client/HttpClient", () => ({
24+
jest.unstable_mockModule("typed-rest-client/HttpClient.js", () => ({
2225
HttpClient: jest.fn().mockImplementation(() => ({
2326
get: mockGet,
2427
})),
2528
}));
2629

27-
import { fetchText, fetchJson } from "../src/installer/http";
30+
const { fetchText, fetchJson } = await import("../src/installer/http.js");
2831

2932
/**
3033
* Build a fake typed-rest-client response with the given status code and body.
@@ -33,7 +36,7 @@ import { fetchText, fetchJson } from "../src/installer/http";
3336
function makeResponse(statusCode: number, body: string) {
3437
return {
3538
message: { statusCode },
36-
readBody: jest.fn().mockResolvedValue(body),
39+
readBody: jest.fn(() => Promise.resolve(body)),
3740
};
3841
}
3942

0 commit comments

Comments
 (0)