Skip to content

Commit c9890b5

Browse files
committed
fix: simplifies loader more
1 parent bea5ebd commit c9890b5

File tree

8 files changed

+172
-278
lines changed

8 files changed

+172
-278
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
"collectCoverageFrom": [
112112
"<rootDir>/src/loader.ts",
113113
"<rootDir>/src/logger.ts",
114+
"<rootDir>/src/parser.ts",
114115
"<rootDir>/src/utils.ts"
115116
]
116117
},

src/__tests__/loader.test.ts

Lines changed: 18 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import { parseUrlPkg } from "@jspm/generator";
33
import { ImportMap } from "@jspm/import-map";
44
import * as utils from "src/utils";
55
import * as config from "src/config";
6+
import * as parser from "src/parser";
67

78

8-
jest.mock("node-fetch", () => jest.fn());
9+
jest.mock("node-fetch", () =>
10+
jest.fn().mockResolvedValue({
11+
ok: true,
12+
text: jest.fn().mockResolvedValue("module code"),
13+
})
14+
);
915

1016
jest.mock("@jspm/generator", () => ({
1117
parseUrlPkg: jest.fn(),
1218
}));
1319

1420
let mockImportMapResolve = jest.fn();
21+
1522
jest.mock("@jspm/import-map", () => ({
1623
ImportMap: jest.fn(() => ({
1724
resolve: mockImportMapResolve,
@@ -26,6 +33,14 @@ jest.mock("src/utils", () => {
2633
};
2734
});
2835

36+
jest.mock("src/parser", () => {
37+
const actual = jest.requireActual("src/parser");
38+
return {
39+
__esModule: true,
40+
...actual,
41+
};
42+
});
43+
2944
jest.mock("src/config", () => {
3045
const actual = jest.requireActual("src/config");
3146
return {
@@ -43,56 +58,6 @@ describe('loader', () => {
4358
jest.clearAllMocks();
4459
})
4560

46-
test("resolved with no cache path error", async () => {
47-
const context = { parentURL: undefined };
48-
await resolve(specifier, context, nextResolve);
49-
expect(errorSpy).toHaveBeenCalledWith("jspm:[loader]: resolve: Error: Failed in resolving cache path");
50-
});
51-
52-
test("resolved with no modulePath error", async () => {
53-
const cachePath = 'test/.cache';
54-
(jest.mocked(config).cache as string) = cachePath
55-
mockImportMapResolve = jest.fn().mockReturnValue(undefined);
56-
const constructImportMapSpy = jest.spyOn(utils, "constructImportMap").mockReturnValue(new ImportMap({}));
57-
const context = { parentURL: "parentURL" };
58-
await resolve(specifier, context, nextResolve);
59-
expect(constructImportMapSpy).toHaveBeenCalled();
60-
expect(errorSpy).toHaveBeenCalledWith("jspm:[loader]: resolve: Error: Failed in resolving module path");
61-
});
62-
63-
test("resolved with URL error", async () => {
64-
const cachePath = 'test/.cache';
65-
(jest.mocked(config).cache as string) = cachePath
66-
mockImportMapResolve = jest.fn().mockReturnValue("./some/path");
67-
const constructImportMapSpy = jest.spyOn(utils, "constructImportMap").mockReturnValue(new ImportMap({}));
68-
const context = { parentURL: "parentURL" };
69-
await resolve(specifier, context, nextResolve);
70-
expect(constructImportMapSpy).toHaveBeenCalled();
71-
expect(errorSpy).toHaveBeenCalledWith("jspm:[loader]: resolve: TypeError [ERR_INVALID_URL]: Invalid URL");
72-
});
73-
74-
test("resolved with `isNode` protocol error", async () => {
75-
const cachePath = 'test/.cache';
76-
(jest.mocked(config).cache as string) = cachePath
77-
mockImportMapResolve = jest.fn().mockReturnValue("node:/some/path");
78-
const constructImportMapSpy = jest.spyOn(utils, "constructImportMap").mockReturnValue(new ImportMap({}));
79-
const context = { parentURL: "parentURL" };
80-
await resolve(specifier, context, nextResolve);
81-
expect(constructImportMapSpy).toHaveBeenCalled();
82-
expect(nextResolve).toHaveBeenCalledWith('specifier');
83-
});
84-
85-
test("resolved with `isFile` protocol error", async () => {
86-
const cachePath = 'test/.cache';
87-
(jest.mocked(config).cache as string) = cachePath
88-
mockImportMapResolve = jest.fn().mockReturnValue("node:/some/path");
89-
const constructImportMapSpy = jest.spyOn(utils, "constructImportMap").mockReturnValue(new ImportMap({}));
90-
const context = { parentURL: "parentURL" };
91-
await resolve(specifier, context, nextResolve);
92-
expect(constructImportMapSpy).toHaveBeenCalled();
93-
expect(nextResolve).toHaveBeenCalledWith('specifier');
94-
});
95-
9661
test("resolved with parseUrlPkg error", async () => {
9762
const cachePath = 'test/.cache';
9863
(jest.mocked(config).cache as string) = cachePath
@@ -116,7 +81,7 @@ describe('loader', () => {
11681
await resolve(specifier, context, nextResolve);
11782
expect(constructImportMapSpy).toHaveBeenCalled();
11883
expect(parseUrlPkg).toHaveBeenCalled();
119-
expect(errorSpy).toHaveBeenCalledWith("jspm:[loader]: resolve: Error: Failed in parsing node module cache path");
84+
expect(nextResolve).toHaveBeenCalledWith("test/.cache/name@version/path");
12085
});
12186

12287
test("resolved without an error", async () => {
@@ -127,14 +92,12 @@ describe('loader', () => {
12792
const constructImportMapSpy = jest.spyOn(utils, "constructImportMap").mockReturnValue(new ImportMap({}));
12893
const context = { parentURL: "parentURL" };
12994
const parseNodeModuleCachePathSpy = jest
130-
.spyOn(utils, "parseNodeModuleCachePath")
95+
.spyOn(parser, "parseNodeModuleCachePath")
13196
.mockResolvedValue("node_modules/name/version");
132-
const nodeModuleCachePathSpy = jest.spyOn(utils, 'constructPath').mockReturnValue('node_modules/name/version')
13397
await resolve(specifier, context, nextResolve);
13498
expect(constructImportMapSpy).toHaveBeenCalled();
13599
expect(parseUrlPkg).toHaveBeenCalled();
136100
expect(parseNodeModuleCachePathSpy).toHaveBeenCalled();
137-
expect(nodeModuleCachePathSpy).toHaveBeenCalled();
138101
expect(nextResolve).toHaveBeenCalledWith("node_modules/name/version");
139102
});
140103
});

src/__tests__/parser.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import * as fs from "node:fs";
2+
import * as utils from 'src/utils';
3+
import { parseNodeModuleCachePath } from '../parser';
4+
5+
jest.mock("node:fs");
6+
7+
jest.mock("node:path", () => {
8+
const actual = jest.requireActual("node:path");
9+
return {
10+
...actual,
11+
dirname: jest.fn((str) => str),
12+
join: jest.fn((str, str2) => `${str}${str2}`),
13+
};
14+
});
15+
16+
jest.mock("node-fetch", () =>
17+
jest.fn().mockResolvedValue({
18+
ok: true,
19+
text: jest.fn().mockResolvedValue("module code"),
20+
})
21+
);
22+
23+
const mockImportMapResolve = jest.fn();
24+
25+
jest.mock("@jspm/import-map", () => ({
26+
ImportMap: jest.fn(() => ({
27+
resolve: mockImportMapResolve,
28+
})),
29+
}));
30+
31+
jest.mock("src/utils", () => {
32+
const actual = jest.requireActual("src/utils");
33+
return {
34+
__esModule: true,
35+
...actual,
36+
};
37+
});
38+
39+
describe("parseNodeModuleCachePath", () => {
40+
const cachePath = "file:///path/to/cache";
41+
jest.mock("node:fs", async () => {
42+
const actual = await jest.requireActual<typeof import("node:fs")>("node:fs");
43+
return {
44+
...actual,
45+
existsSync: jest.fn(),
46+
};
47+
});
48+
49+
afterEach(() => {
50+
jest.clearAllMocks();
51+
});
52+
53+
test("should return cachePath if it exists", async () => {
54+
(fs.existsSync as jest.Mock).mockReturnValue(true);
55+
const result = await parseNodeModuleCachePath("modulePath", cachePath);
56+
expect(result).toBe(cachePath);
57+
});
58+
59+
test("should make directories and write file if cachePath does not exist", async () => {
60+
(fs.existsSync as jest.Mock).mockReturnValue(false);
61+
const ensureDirSyncSpy = jest.spyOn(utils, "ensureDirSync");
62+
const writeFileSyncSpy = jest.spyOn(fs, "writeFileSync");
63+
await parseNodeModuleCachePath("modulePath", cachePath);
64+
expect(ensureDirSyncSpy).toBeCalled();
65+
expect(writeFileSyncSpy).toBeCalledWith(cachePath, "module code");
66+
});
67+
68+
test("should return empty string if there is an error", async () => {
69+
(fs.existsSync as jest.Mock).mockReturnValue(false);
70+
await jest.spyOn(fs, "writeFileSync").mockImplementation(() => {
71+
throw new Error("error");
72+
});
73+
const errorSpy = await jest.spyOn(console, "error").mockImplementation(() => undefined);
74+
const result = await parseNodeModuleCachePath("modulePath", cachePath);
75+
expect(result).toBe("file:///path/to/cache");
76+
expect(errorSpy).toHaveBeenCalled();
77+
});
78+
});

src/__tests__/utils.test.ts

Lines changed: 2 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
import * as fs from "node:fs";
2-
import * as path from "node:path";
32
import { ImportMap } from "@jspm/import-map";
4-
5-
import {
6-
constructPath,
7-
constructImportMap,
8-
createCacheMap,
9-
parseNodeModuleCachePath,
10-
} from "src/utils";
11-
12-
import { ALL_CACHE_MAP_REQUIREMENTS_MUST_BE_DEFINED } from "src/constants";
3+
import { constructImportMap } from "src/utils";
134

145
jest.mock("node:fs");
156

@@ -34,16 +25,6 @@ jest.mock("@jspm/import-map", () => {
3425
return { ImportMap };
3526
});
3627

37-
test("constructPath minimal", () => {
38-
const result = constructPath("foo", './');
39-
expect(result).toStrictEqual("./foo");
40-
});
41-
42-
test("constructPath with root", () => {
43-
const result = constructPath("/foo", "./bar");
44-
expect(result).toStrictEqual("./bar/foo");
45-
});
46-
4728
test("constructImportMap minimal", () => {
4829
const result = constructImportMap();
4930
expect(result).toBeInstanceOf(ImportMap);
@@ -64,82 +45,7 @@ test("constructImportMap should return ImportMap instance if path exists", () =>
6445
test("constructImportMap should use cwd if no path provided", () => {
6546
constructImportMap();
6647
expect(ImportMap).toHaveBeenCalledWith({
67-
rootUrl: `file://${process.cwd()}`,
48+
rootUrl: `file://${process.cwd()}/src/utils.ts`,
6849
map: {},
6950
});
7051
});
71-
72-
test("createCacheMap should return an object with instance, cachePath and modulePath properties", () => {
73-
const cacheMap = createCacheMap();
74-
expect(cacheMap).toHaveProperty("instance");
75-
expect(cacheMap).toHaveProperty("cachePath");
76-
expect(cacheMap).toHaveProperty("modulePath");
77-
});
78-
79-
test("createCacheMap.get should return cachePath if defined", () => {
80-
const cacheMap = createCacheMap();
81-
cacheMap.set("foo", "bar");
82-
expect(cacheMap.get("foo")).toBe("bar");
83-
});
84-
85-
test("createCacheMap.get should return undefined if cachePath is not defined", () => {
86-
const cacheMap = createCacheMap();
87-
expect(cacheMap.get("foo")).toEqual("foo");
88-
});
89-
90-
test("createCacheMap.set should set cachePath and modulePath", () => {
91-
const cacheMap = createCacheMap();
92-
cacheMap.set("foo", "bar");
93-
expect(cacheMap.get("foo")).toBe("bar");
94-
});
95-
96-
test("createCacheMap.set should log error if cachePath or modulePath are undefined", () => {
97-
const spy = jest.spyOn(console, "error").mockImplementation(() => undefined);
98-
const cacheMap = createCacheMap(true);
99-
cacheMap.set(undefined as unknown as string, "bar");
100-
expect(spy).toHaveBeenCalledWith(`jspm:[utils]: ${ALL_CACHE_MAP_REQUIREMENTS_MUST_BE_DEFINED}`);
101-
});
102-
103-
describe("parseNodeModuleCachePath", () => {
104-
const cachePath = "/path/to/cache";
105-
jest.mock("node:fs", async () => {
106-
const actual = await jest.requireActual<typeof import("node:fs")>("node:fs");
107-
return {
108-
...actual,
109-
existsSync: jest.fn(),
110-
};
111-
});
112-
113-
afterEach(() => {
114-
jest.clearAllMocks();
115-
});
116-
117-
test("should return cachePath if it exists", async () => {
118-
(fs.existsSync as jest.Mock).mockReturnValue(true);
119-
const result = await parseNodeModuleCachePath("modulePath", cachePath);
120-
expect(result).toBe(cachePath);
121-
});
122-
123-
test("should make directories and write file if cachePath does not exist", async () => {
124-
(fs.existsSync as jest.Mock).mockReturnValue(false);
125-
const dirNameSpy = jest.spyOn(path, "dirname");
126-
const mkdirSyncSpy = jest.spyOn(fs, "mkdirSync").mockReturnValue("");
127-
const writeFileSyncSpy = jest.spyOn(fs, "writeFileSync");
128-
await parseNodeModuleCachePath("modulePath", cachePath);
129-
expect(dirNameSpy).toBeCalled();
130-
expect(mkdirSyncSpy).toBeCalledWith("/path/to/cache", { recursive: true });
131-
expect(writeFileSyncSpy).toBeCalledWith(cachePath, "module code");
132-
});
133-
134-
test("should return empty string if there is an error", async () => {
135-
(fs.existsSync as jest.Mock).mockReturnValue(false);
136-
await jest.spyOn(fs, "mkdirSync").mockReturnValue("");
137-
await jest.spyOn(fs, "writeFileSync").mockImplementation(() => {
138-
throw new Error("error");
139-
});
140-
const errorSpy = await jest.spyOn(console, "error").mockImplementation(() => undefined);
141-
const result = await parseNodeModuleCachePath("modulePath", cachePath);
142-
expect(result).toBe("");
143-
expect(errorSpy).toHaveBeenCalled();
144-
});
145-
});

src/config.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { IS_DEBUGGING } from "src/constants";
2-
import { constructPath, createCacheMap } from "src/utils";
3-
1+
import { join } from 'node:path';
2+
import { fileURLToPath } from 'node:url';
43
/**
54
* ******************************************************
65
* CONFIG
@@ -10,7 +9,7 @@ import { constructPath, createCacheMap } from "src/utils";
109
*
1110
* ******************************************************
1211
*/
13-
const root = process.cwd();
14-
export const cacheMap = createCacheMap(IS_DEBUGGING);
15-
export const cache = constructPath(".cache", root);
16-
export const nodeImportMapPath = constructPath("node.importmap", root);
12+
export const root = fileURLToPath(`file://${process.cwd()}`);
13+
export const cacheMap = new Map()
14+
export const nodeImportMapPath = join(root, "node.importmap");
15+
export const cache = join(root, '.cache')

0 commit comments

Comments
 (0)