Skip to content

Commit 38c1ce4

Browse files
committed
fix: udpates utils/parser test
1 parent 7f71e7a commit 38c1ce4

File tree

9 files changed

+145
-62
lines changed

9 files changed

+145
-62
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@
9191
],
9292
"transformIgnorePatterns": [
9393
"node_modules/(?!node:http)",
94-
"node_modules/(?!@jspm/import-map)"
94+
"node_modules/(?!@jspm/import-map)",
95+
"node_modules/(?!@jspm/generator)"
9596
],
9697
"transform": {
9798
"^.+\\.(ts)$": "@swc/jest"

src/__tests__/parser.test.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
import * as fs from "node:fs";
2-
import * as utils from 'src/utils';
31
import { parseNodeModuleCachePath } from '../parser';
42

5-
jest.mock("node:fs");
3+
import * as fs from "node:fs";
64

75
jest.mock("node:path", () => {
86
const actual = jest.requireActual("node:path");
@@ -20,21 +18,26 @@ jest.mock("node-fetch", () =>
2018
})
2119
);
2220

23-
const mockImportMapResolve = jest.fn();
24-
2521
jest.mock("@jspm/import-map", () => ({
2622
ImportMap: jest.fn(() => ({
27-
resolve: mockImportMapResolve,
23+
resolve: jest.fn(),
2824
})),
2925
}));
3026

31-
jest.mock("src/utils", () => {
32-
const actual = jest.requireActual("src/utils");
27+
jest.mock('@jspm/generator', () => ({
28+
parseUrlPkg: jest.fn(),
29+
}))
30+
31+
jest.mock("../utils", () => {
32+
const actual = jest.requireActual("../utils");
3333
return {
3434
__esModule: true,
3535
...actual,
3636
};
3737
});
38+
import * as utils from "../utils";
39+
40+
jest.mock('../config')
3841

3942
describe("parseNodeModuleCachePath", () => {
4043
const cachePath = "file:///path/to/cache";
@@ -43,6 +46,7 @@ describe("parseNodeModuleCachePath", () => {
4346
return {
4447
...actual,
4548
existsSync: jest.fn(),
49+
writeFileSync: jest.fn(),
4650
};
4751
});
4852

@@ -51,22 +55,20 @@ describe("parseNodeModuleCachePath", () => {
5155
});
5256

5357
test("should return cachePath if it exists", async () => {
54-
(fs.existsSync as jest.Mock).mockReturnValue(true);
58+
jest.spyOn(fs, "existsSync").mockReturnValue(true);
5559
const result = await parseNodeModuleCachePath("modulePath", cachePath);
5660
expect(result).toBe(cachePath);
5761
});
5862

5963
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");
64+
jest.spyOn(fs, "existsSync").mockReturnValue(false);
65+
const ensureFileSyncSpy = jest.spyOn(utils, "ensureFileSync");
6366
await parseNodeModuleCachePath("modulePath", cachePath);
64-
expect(ensureDirSyncSpy).toBeCalled();
65-
expect(writeFileSyncSpy).toBeCalledWith(cachePath, "module code");
67+
expect(ensureFileSyncSpy).toBeCalled();
6668
});
6769

6870
test("should return empty string if there is an error", async () => {
69-
(fs.existsSync as jest.Mock).mockReturnValue(false);
71+
jest.spyOn(fs, "existsSync").mockReturnValue(false);
7072
await jest.spyOn(fs, "writeFileSync").mockImplementation(() => {
7173
throw new Error("error");
7274
});

src/__tests__/utils.test.ts

Lines changed: 103 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,119 @@
1+
import {
2+
checkIfNodeOrFileProtocol,
3+
ensureDirSync,
4+
ensureFileSync,
5+
resolveModulePath,
6+
resolveNodeModuleCachePath,
7+
resolveParsedModulePath
8+
} from '../utils';
9+
10+
jest.mock('node:fs');
11+
jest.mock('node:path');
112
import * as fs from "node:fs";
2-
import { ensureDirSync } from 'src/utils';
13+
import * as path from "node:path";
14+
15+
jest.mock("@jspm/import-map", () => ({
16+
ImportMap: jest.fn(() => ({
17+
resolve: jest.fn(),
18+
})),
19+
}));
20+
21+
jest.mock('@jspm/generator', () => ({
22+
parseUrlPkg: jest.fn(),
23+
}))
324

4-
jest.mock("node:fs");
25+
import * as generator from '@jspm/generator';
26+
27+
jest.mock('../config')
28+
import * as config from '../config';
29+
30+
jest.mock('../parser', () => ({
31+
parseNodeModuleCachePath: jest.fn(),
32+
}))
33+
import * as parser from '../parser';
534

635
test("ensureDirSync has dir", () => {
736
const dir = "/path/to/dir";
837
const existsSyncMock = jest.spyOn(fs, 'existsSync').mockReturnValue(true);
38+
const dirnameMock = jest.spyOn(path, 'dirname')
939
ensureDirSync(dir);
1040
expect(existsSyncMock).toBeCalledWith(dir);
11-
expect(fs.mkdirSync).not.toBeCalled();
41+
expect(dirnameMock).not.toBeCalled();
1242
});
1343

14-
test("ensureDirSync has no dir", () => {
44+
test("ensureDirSync has parent dir", () => {
1545
const dir = "/path/to/dir";
1646
const existsSyncMock = jest.spyOn(fs, 'existsSync').mockReturnValue(false);
47+
const dirnameMock = jest.spyOn(path, 'dirname').mockReturnValue("/path/to/dir");
1748
const mkdirSyncMock = jest.spyOn(fs, 'mkdirSync')
1849
ensureDirSync(dir);
1950
expect(existsSyncMock).toBeCalledWith(dir);
20-
expect(mkdirSyncMock).toBeCalledWith(dir);
51+
expect(dirnameMock).toBeCalledWith(dir);
52+
expect(mkdirSyncMock).toHaveBeenCalledTimes(1);
2153
});
54+
55+
test("ensureDirSync to have recursion", () => {
56+
const dir = "/path/to/dir";
57+
const existsSyncMock = jest.spyOn(fs, 'existsSync').mockReturnValue(false);
58+
const dirnameMock = jest.spyOn(path, 'dirname').mockReturnValue("/path/");
59+
const mkdirSyncMock = jest.spyOn(fs, 'mkdirSync')
60+
ensureDirSync(dir);
61+
expect(existsSyncMock).toBeCalledWith(dir);
62+
expect(dirnameMock).toBeCalledWith(dir);
63+
expect(mkdirSyncMock).toHaveBeenCalledTimes(2);
64+
});
65+
66+
test("ensureFileSync has file", () => {
67+
const dir = 'path/to/file';
68+
const dirnameMock = jest.spyOn(path, 'dirname').mockReturnValue("/path/to/dir");
69+
const existsSyncMock = jest.spyOn(fs, 'existsSync').mockReturnValue(true);
70+
const writeFileSyncSpy = jest.spyOn(fs, 'writeFileSync');
71+
ensureFileSync(dir);
72+
expect(dirnameMock).toBeCalled();
73+
expect(existsSyncMock).toBeCalled();
74+
expect(writeFileSyncSpy).toBeCalled();
75+
});
76+
77+
test('checkIfNodeOrFileProtocol returns true', () => {
78+
const protocol = 'node:foo';
79+
expect(checkIfNodeOrFileProtocol(protocol)).toBeTruthy();
80+
})
81+
82+
test('checkIfNodeOrFileProtocol returns false', () => {
83+
const protocol = 'http:foo';
84+
expect(checkIfNodeOrFileProtocol(protocol)).toBeFalsy();
85+
})
86+
87+
test('resolveModulePath', () => {
88+
const specifier = 'foo';
89+
const cacheMapPath = 'file:///bar';
90+
const resolve = jest.fn().mockReturnValue('file:///bar/foo');
91+
(jest.mocked(config).importmap as unknown) = {
92+
resolve
93+
}
94+
const result = resolveModulePath(specifier, cacheMapPath);
95+
expect(result).toBe('file:///bar/foo');
96+
})
97+
98+
test('resolveModulePath with modulePath', async () => {
99+
const parseUrlPkgSpy = await jest.spyOn(generator, 'parseUrlPkg').mockResolvedValue({
100+
pkg: {
101+
name: 'foo',
102+
version: '1.0.0',
103+
}
104+
} as any);
105+
(jest.mocked(config).cache as unknown) = 'test/.cache'
106+
const modulePath = 'file:///bar/index.js';
107+
const joinSpy = jest.spyOn(path, 'join').mockReturnValue('test/.cache/[email protected]/bar/index.js');
108+
const result = await resolveNodeModuleCachePath(modulePath);
109+
expect(parseUrlPkgSpy).toBeCalledWith(modulePath);
110+
expect(joinSpy).toBeCalled();
111+
expect(result).toBe('test/.cache/[email protected]/bar/index.js');
112+
});
113+
114+
test('resolveParsedModulePath', async () => {
115+
const parseNodeModuleCachePathSpy = await jest.spyOn(parser, 'parseNodeModuleCachePath').mockResolvedValue('file:///foo/bar');
116+
const result = await resolveParsedModulePath('file:///foo/bar', 'file:///foo/bar');
117+
expect(parseNodeModuleCachePathSpy).toBeCalled();
118+
expect(result).toBe('file:///foo/bar');
119+
})

src/config.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,19 @@ import { fileURLToPath } from "node:url";
44
import { ImportMap } from "@jspm/import-map";
55
/**
66
* ******************************************************
7-
* CONFIG
7+
* CONFIG 🗺️
88
* ------------------------------------------------------
99
* @description utility variable assignment
10-
* @summary utility variables which are assigned 1x. Assigning them here simplifies testability and later configuration if CLI functionality is added.
10+
* @summary utility variables which are assigned 1x.
11+
* Assigning them here simplifies testability and later configuration if CLI functionality is added.
1112
*
1213
* ******************************************************
1314
*/
1415
export const root = fileURLToPath(`file://${process.cwd()}`);
1516
export const cacheMap = new Map();
1617
export const nodeImportMapPath = join(root, "node.importmap");
1718
export const cache = join(root, ".cache");
18-
export const map = existsSync(nodeImportMapPath)
19+
const map = existsSync(nodeImportMapPath)
1920
? JSON.parse(readFileSync(nodeImportMapPath, { encoding: "utf8" }))
2021
: {};
21-
export const importMap = new ImportMap({ rootUrl: import.meta.url, map });
22+
export const importmap = new ImportMap({ rootUrl: import.meta.url, map });

src/loader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Context, NextResolve } from "./types";
99

1010
/**
1111
* ******************************************************
12-
* LOADER
12+
* LOADER 🚛
1313
* ------------------------------------------------------
1414
* @summary loads node modules via an *assumed root working directory with a cache and node.importmap*
1515
* @notes

src/parser.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import { ensureFileSync } from "src/utils";
44
import { IS_DEBUGGING } from "src/constants";
55
import { logger } from "src/logger";
66

7+
/**
8+
* ******************************************************
9+
* PARSER 🔪
10+
* ------------------------------------------------------
11+
* @description handles parsing directories for cached paths
12+
*
13+
* ******************************************************
14+
*/
15+
716
const log = logger({ file: "parser", isLogging: IS_DEBUGGING });
817

918
/**

src/types.ts

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,9 @@
1-
import { URL } from "node:url";
2-
31
export type Context = {
42
parentURL?: string;
53
};
64

7-
export type ConstructCachePath = {
8-
cache: string;
9-
modulePath: string;
10-
debug?: boolean;
11-
matcher?: RegExp | string;
12-
};
13-
145
export type NextResolve = (specifier: string) => Promise<string | unknown>;
156

16-
export type UrlType = URL;
17-
18-
export type CreateCacheMapFactory = {
19-
cachePath?: string;
20-
instance: Map<string, string>;
21-
isDebugging?: boolean;
22-
modulePath?: string;
23-
get: (cachePath: string) => string | undefined;
24-
set: (cachePath: string, modulePath: string) => void;
25-
};
26-
27-
export type ResolveOptions = {
28-
base?: string;
29-
cache?: string;
30-
debug?: boolean;
31-
importmap?: string;
32-
cacheMap?: CreateCacheMapFactory;
33-
};
34-
357
export type LoggerOptions = {
368
file: string;
379
isLogging?: boolean;

src/utils.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
22
import { dirname, join } from "node:path";
33
import { parseUrlPkg } from "@jspm/generator";
4-
import { parseNodeModuleCachePath } from "src/parser";
5-
import { cache, importMap } from "src/config";
6-
import { IS_DEBUGGING } from "src/constants";
7-
import { logger } from "src/logger";
4+
import { parseNodeModuleCachePath } from "./parser";
5+
import { cache, importmap } from "./config";
6+
import { IS_DEBUGGING } from "./constants";
7+
import { logger } from "./logger";
88

99
/**
1010
* ******************************************************
11-
* UTILS
11+
* UTILS 📦
1212
* ------------------------------------------------------
1313
* @description a collection of utility functions
1414
* @summary a collection of utility functions
@@ -44,7 +44,7 @@ export const checkIfNodeOrFileProtocol = (modulePath: string) => {
4444
};
4545

4646
export const resolveModulePath = (specifier: string, cacheMapPath: string) => {
47-
const modulePath = importMap.resolve(specifier, cacheMapPath);
47+
const modulePath = importmap.resolve(specifier, cacheMapPath);
4848
log.debug("resolveModulePath:", { modulePath });
4949
return modulePath;
5050
};
@@ -56,7 +56,7 @@ export const resolveNodeModuleCachePath = async (modulePath: string) => {
5656
const version = moduleMetadata?.pkg?.version;
5757
const moduleFile = modulePath.split("/").reverse()[0] || "";
5858
const nodeModuleCachePath = join(cache, `${name}@${version}`, moduleFile);
59-
log.debug("resolveNodeModuleCachePath:", { moduleMetadata, name, version, nodeModuleCachePath });
59+
log.debug("resolveNodeModuleCachePath:", { nodeModuleCachePath });
6060
return nodeModuleCachePath;
6161
} catch (err) {
6262
log.error("resolveNodeModuleCachePath:", err);

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@
3030
"types": ["jest", "node"]
3131
},
3232
"include": ["src/**/*"],
33-
"exclude": ["tests/*.ts", "tests/e2e/*.js"]
33+
"exclude": ["src/__tests__/*.ts", "tests/e2e/*.js"]
3434
}

0 commit comments

Comments
 (0)