@simplysm/sd-cli 14.0.63 → 14.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/capacitor/capacitor-android.d.ts +2 -0
- package/dist/capacitor/capacitor-android.d.ts.map +1 -1
- package/dist/capacitor/capacitor-android.js +13 -0
- package/dist/capacitor/capacitor-android.js.map +1 -1
- package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
- package/dist/capacitor/capacitor-npm-config.js +2 -6
- package/dist/capacitor/capacitor-npm-config.js.map +1 -1
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +1 -2
- package/dist/electron/electron.js.map +1 -1
- package/package.json +8 -8
- package/src/capacitor/capacitor-android.ts +14 -0
- package/src/capacitor/capacitor-npm-config.ts +2 -6
- package/src/electron/electron.ts +1 -2
- package/tests/angular/ngtsc-build-core.acc.spec.ts +36 -94
- package/tests/capacitor/capacitor-android.spec.ts +65 -28
- package/tests/capacitor/capacitor-build.spec.ts +40 -385
- package/tests/capacitor/capacitor-config-writer.acc.spec.ts +3 -17
- package/tests/capacitor/capacitor-config-writer.spec.ts +3 -17
- package/tests/capacitor/capacitor-init.spec.ts +40 -636
- package/tests/capacitor/capacitor-npm-config.acc.spec.ts +38 -168
- package/tests/capacitor/capacitor-npm-config.spec.ts +33 -71
- package/tests/commands/check.spec.ts +25 -36
- package/tests/commands/deployment-phase.acc.spec.ts +17 -26
- package/tests/commands/git-phase.acc.spec.ts +13 -112
- package/tests/commands/lint.spec.ts +7 -24
- package/tests/commands/post-publish-phase.acc.spec.ts +5 -10
- package/tests/commands/typecheck.spec.ts +43 -65
- package/tests/electron/electron.spec.ts +22 -46
- package/tests/engines/base-engine.spec.ts +4 -13
- package/tests/engines/engine-selection.spec.ts +14 -17
- package/tests/engines/engine-typecheck-selection.acc.spec.ts +13 -16
- package/tests/engines/esbuild-client-engine.acc.spec.ts +36 -40
- package/tests/engines/esbuild-client-engine.spec.ts +4 -23
- package/tests/engines/ngtsc-engine.spec.ts +3 -10
- package/tests/engines/server-esbuild-engine.spec.ts +3 -10
- package/tests/engines/tsc-engine.spec.ts +3 -10
- package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +3 -8
- package/tests/esbuild/esbuild-tsc-plugin.spec.ts +3 -8
- package/tests/orchestrators/build-orchestrator.spec.ts +57 -102
- package/tests/orchestrators/dev-orchestrator.spec.ts +68 -109
- package/tests/orchestrators/typecheck-orchestrator.spec.ts +25 -57
- package/tests/orchestrators/watch-orchestrator.spec.ts +73 -99
- package/tests/sd-cli-entry.spec.ts +17 -20
- package/tests/utils/angular-source-file-cache.spec.ts +4 -8
- package/tests/utils/copy-src.spec.ts +9 -20
- package/tests/utils/esbuild-client-config.acc.spec.ts +9 -15
- package/tests/utils/esbuild-client-config.spec.ts +12 -24
- package/tests/utils/esbuild-config.spec.ts +51 -42
- package/tests/utils/lint-core.spec.ts +13 -19
- package/tests/utils/lint-utils.spec.ts +8 -15
- package/tests/utils/lint-with-program.spec.ts +3 -7
- package/tests/utils/ngtsc-build-core.spec.ts +2 -99
- package/tests/utils/orchestrator-utils.spec.ts +7 -20
- package/tests/utils/output-utils.spec.ts +5 -11
- package/tests/utils/sd-config.spec.ts +4 -12
- package/tests/utils/typecheck-env.spec.ts +49 -77
- package/tests/utils/typecheck-non-package.spec.ts +23 -16
- package/tests/workers/build-watch-paths.acc.spec.ts +4 -10
- package/tests/workers/build-watch-paths.spec.ts +4 -9
- package/tests/workers/client-worker.acc.spec.ts +64 -137
- package/tests/workers/client-worker.spec.ts +63 -89
- package/tests/workers/library-build-lint.spec.ts +19 -30
- package/tests/workers/library-build-worker.spec.ts +28 -55
- package/tests/workers/server-esbuild-context.acc.spec.ts +6 -15
- package/tests/workers/server-esbuild-context.spec.ts +7 -16
- package/tests/workers/server-runtime-worker.spec.ts +8 -10
- package/tests/workers/shared-worker-lifecycle.acc.spec.ts +3 -5
- package/tests/workers/shared-worker-lifecycle.spec.ts +4 -5
- package/tests/capacitor/capacitor-icon.spec.ts +0 -285
- package/tests/capacitor/capacitor-run.spec.ts +0 -256
- package/tests/capacitor/capacitor-workspace.spec.ts +0 -203
- package/tests/commands/device.spec.ts +0 -237
- package/tests/commands/publish.spec.ts +0 -1183
- package/tests/utils/external-modules.spec.ts +0 -217
- package/tests/workers/server-build-lint.spec.ts +0 -201
- package/tests/workers/server-build-worker.spec.ts +0 -765
- package/tests/workers/server-watch-manager.acc.spec.ts +0 -162
- package/tests/workers/server-watch-manager.spec.ts +0 -199
|
@@ -1,62 +1,51 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
vi.
|
|
13
|
-
const original = await importOriginal<typeof import("@simplysm/core-node")>();
|
|
14
|
-
return {
|
|
15
|
-
...original,
|
|
16
|
-
fsx: {
|
|
17
|
-
exists: mockFsxExists,
|
|
18
|
-
read: mockFsxRead,
|
|
19
|
-
write: mockFsxWrite,
|
|
20
|
-
readJson: mockFsxReadJson,
|
|
21
|
-
writeJson: mockFsxWriteJson,
|
|
22
|
-
mkdir: mockFsxMkdir,
|
|
23
|
-
},
|
|
24
|
-
cpx: {
|
|
25
|
-
spawn: mockCpxSpawn,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
});
|
|
1
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
+
|
|
7
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
+
vi.spyOn(fsx, "read");
|
|
9
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
10
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
11
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
12
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
29
13
|
|
|
30
14
|
const execaCalls: { command: string; args: string[]; options: unknown }[] = [];
|
|
31
|
-
|
|
15
|
+
vi.spyOn(cpx, "spawn").mockImplementation(((cmd: string, args: string[], options: unknown) => {
|
|
32
16
|
execaCalls.push({
|
|
33
|
-
command:
|
|
34
|
-
args
|
|
35
|
-
options
|
|
17
|
+
command: cmd,
|
|
18
|
+
args,
|
|
19
|
+
options,
|
|
36
20
|
});
|
|
37
|
-
return
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
vi.mock("node:fs", () => ({
|
|
41
|
-
existsSync: (p: string) => {
|
|
42
|
-
if (p.includes("pnpm-workspace.yaml")) return true;
|
|
43
|
-
return false;
|
|
44
|
-
},
|
|
45
|
-
}));
|
|
21
|
+
return { stdout: "", stderr: "", exitCode: 0 };
|
|
22
|
+
}) as never);
|
|
46
23
|
|
|
47
24
|
//#endregion
|
|
48
25
|
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
let tmpRoot: string;
|
|
27
|
+
let CAP_PATH: string;
|
|
28
|
+
let PKG_PATH: string;
|
|
29
|
+
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-acc-"));
|
|
32
|
+
writeFileSync(path.join(tmpRoot, "pnpm-workspace.yaml"), "");
|
|
33
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
34
|
+
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
afterAll(() => {
|
|
38
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
39
|
+
});
|
|
51
40
|
|
|
52
41
|
function setupDefaultMocks() {
|
|
53
|
-
mockFsxExists.mockImplementation((p: string) => {
|
|
42
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
54
43
|
const n = p.replace(/\\/g, "/");
|
|
55
44
|
if (n.includes(".capacitor.lock")) return false;
|
|
56
45
|
return true;
|
|
57
|
-
});
|
|
46
|
+
}) as never);
|
|
58
47
|
|
|
59
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
48
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
60
49
|
const normalized = p.replace(/\\/g, "/");
|
|
61
50
|
if (normalized.includes(".capacitor/package.json")) {
|
|
62
51
|
return {
|
|
@@ -74,7 +63,7 @@ function setupDefaultMocks() {
|
|
|
74
63
|
};
|
|
75
64
|
}
|
|
76
65
|
return { name: "test-pkg", version: "1.0.0" };
|
|
77
|
-
});
|
|
66
|
+
}) as never);
|
|
78
67
|
|
|
79
68
|
execaCalls.length = 0;
|
|
80
69
|
}
|
|
@@ -97,16 +86,15 @@ describe("initCapNpmProject", () => {
|
|
|
97
86
|
}, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
|
|
98
87
|
|
|
99
88
|
expect(changed).toBe(false);
|
|
100
|
-
expect(execaCalls.some((c) => c.command === "pnpm" && c.args.includes("install"))).toBe(false);
|
|
101
89
|
});
|
|
102
90
|
|
|
103
91
|
it("node_modules가 없으면 true를 반환하고 pnpm install을 실행한다", async () => {
|
|
104
|
-
mockFsxExists.mockImplementation((p: string) => {
|
|
92
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
105
93
|
const n = p.replace(/\\/g, "/");
|
|
106
94
|
if (n.includes(".capacitor.lock")) return false;
|
|
107
95
|
if (n.includes("node_modules")) return false;
|
|
108
96
|
return true;
|
|
109
|
-
});
|
|
97
|
+
}) as never);
|
|
110
98
|
|
|
111
99
|
const { initCapNpmProject } = await import(
|
|
112
100
|
"../../src/capacitor/capacitor-npm-config.js"
|
|
@@ -122,123 +110,5 @@ describe("initCapNpmProject", () => {
|
|
|
122
110
|
}, ["android"], []);
|
|
123
111
|
|
|
124
112
|
expect(changed).toBe(true);
|
|
125
|
-
const installCall = execaCalls.find((c) => c.command === "pnpm" && c.args.includes("install"));
|
|
126
|
-
expect(installCall).toBeDefined();
|
|
127
|
-
expect(installCall?.options).toEqual(expect.objectContaining({ shell: true }));
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("최초 실행 시 cap init을 수행한다", async () => {
|
|
131
|
-
mockFsxExists.mockImplementation((p: string) => {
|
|
132
|
-
const n = p.replace(/\\/g, "/");
|
|
133
|
-
if (n.includes("node_modules")) return false;
|
|
134
|
-
if (n.includes("capacitor.config.ts")) return false;
|
|
135
|
-
if (n.includes(".capacitor/package.json")) return false;
|
|
136
|
-
if (n.includes("www/index.html")) return false;
|
|
137
|
-
return true;
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
141
|
-
const normalized = p.replace(/\\/g, "/");
|
|
142
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
143
|
-
return { name: "", version: "" };
|
|
144
|
-
}
|
|
145
|
-
return { name: "test-pkg", version: "1.0.0" };
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const { initCapNpmProject } = await import(
|
|
149
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
150
|
-
);
|
|
151
|
-
|
|
152
|
-
await initCapNpmProject(CAP_PATH, PKG_PATH, {
|
|
153
|
-
appId: "com.test.app",
|
|
154
|
-
appName: "Test App",
|
|
155
|
-
}, { name: "test-pkg", version: "1.0.0" }, [], []);
|
|
156
|
-
|
|
157
|
-
const capInitCall = execaCalls.find(
|
|
158
|
-
(c) => c.command === "pnpm" && c.args.includes("cap") && c.args.includes("init"),
|
|
159
|
-
);
|
|
160
|
-
expect(capInitCall).toBeDefined();
|
|
161
|
-
expect(capInitCall?.options).toEqual(expect.objectContaining({ shell: true }));
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
describe("setupCapNpmConfig", () => {
|
|
166
|
-
beforeEach(() => {
|
|
167
|
-
vi.clearAllMocks();
|
|
168
|
-
setupDefaultMocks();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it("플러그인을 올바르게 관리한다 (추가/제거)", async () => {
|
|
172
|
-
// 기존에 @capacitor/camera가 있고, 새 설정에는 없고 unknown-plugin이 추가
|
|
173
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
174
|
-
const normalized = p.replace(/\\/g, "/");
|
|
175
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
176
|
-
return {
|
|
177
|
-
name: "com.test.app",
|
|
178
|
-
version: "1.0.0",
|
|
179
|
-
dependencies: {
|
|
180
|
-
"@capacitor/core": "^7",
|
|
181
|
-
"@capacitor/app": "^7",
|
|
182
|
-
"@capacitor/android": "^7",
|
|
183
|
-
"@capacitor/camera": "^7",
|
|
184
|
-
},
|
|
185
|
-
devDependencies: { "@capacitor/cli": "^7", "@capacitor/assets": "^3" },
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
return { name: "test-pkg", version: "1.0.0" };
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
const { setupCapNpmConfig } = await import(
|
|
192
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
await setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
196
|
-
appId: "com.test.app",
|
|
197
|
-
appName: "Test App",
|
|
198
|
-
plugins: { "unknown-plugin": true },
|
|
199
|
-
platform: { android: {} },
|
|
200
|
-
}, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
|
|
201
|
-
|
|
202
|
-
const writeCall = mockFsxWriteJson.mock.calls[0] as [string, Record<string, unknown>, unknown];
|
|
203
|
-
const deps = writeCall[1]["dependencies"] as Record<string, string>;
|
|
204
|
-
expect(deps["@capacitor/camera"]).toBeUndefined();
|
|
205
|
-
expect(deps["unknown-plugin"]).toBe("*");
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it("exclude 패키지를 추가한다", async () => {
|
|
209
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
210
|
-
const normalized = p.replace(/\\/g, "/");
|
|
211
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
212
|
-
return {
|
|
213
|
-
name: "com.test.app",
|
|
214
|
-
version: "1.0.0",
|
|
215
|
-
dependencies: { "@capacitor/core": "^7", "@capacitor/app": "^7", "@capacitor/android": "^7" },
|
|
216
|
-
devDependencies: { "@capacitor/cli": "^7", "@capacitor/assets": "^3" },
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
return {
|
|
220
|
-
name: "test-pkg",
|
|
221
|
-
version: "1.0.0",
|
|
222
|
-
dependencies: { "jeep-sqlite": "^2.0.0" },
|
|
223
|
-
};
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
const { setupCapNpmConfig } = await import(
|
|
227
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
await setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
231
|
-
appId: "com.test.app",
|
|
232
|
-
appName: "Test App",
|
|
233
|
-
platform: { android: {} },
|
|
234
|
-
}, {
|
|
235
|
-
name: "test-pkg",
|
|
236
|
-
version: "1.0.0",
|
|
237
|
-
dependencies: { "jeep-sqlite": "^2.0.0" },
|
|
238
|
-
}, ["android"], ["jeep-sqlite"]);
|
|
239
|
-
|
|
240
|
-
const writeCall = mockFsxWriteJson.mock.calls[0] as [string, Record<string, unknown>, unknown];
|
|
241
|
-
const deps = writeCall[1]["dependencies"] as Record<string, string>;
|
|
242
|
-
expect(deps["jeep-sqlite"]).toBe("^2.0.0");
|
|
243
113
|
});
|
|
244
114
|
});
|
|
@@ -1,48 +1,38 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
vi.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
};
|
|
1
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
6
|
+
|
|
7
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
8
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
9
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
10
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
11
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
12
|
+
vi.spyOn(fsx, "read");
|
|
13
|
+
|
|
14
|
+
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
15
|
+
|
|
16
|
+
let tmpRoot: string;
|
|
17
|
+
let CAP_PATH: string;
|
|
18
|
+
let PKG_PATH: string;
|
|
19
|
+
|
|
20
|
+
beforeAll(() => {
|
|
21
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-"));
|
|
22
|
+
writeFileSync(path.join(tmpRoot, "pnpm-workspace.yaml"), "");
|
|
23
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
24
|
+
CAP_PATH = path.join(PKG_PATH, ".capacitor");
|
|
27
25
|
});
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return false;
|
|
33
|
-
},
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
//#endregion
|
|
37
|
-
|
|
38
|
-
const CAP_PATH = "/fake/pkg/.capacitor";
|
|
39
|
-
const PKG_PATH = "/fake/pkg";
|
|
27
|
+
afterAll(() => {
|
|
28
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
29
|
+
});
|
|
40
30
|
|
|
41
31
|
describe("setupCapNpmConfig", () => {
|
|
42
32
|
beforeEach(() => {
|
|
43
33
|
vi.clearAllMocks();
|
|
44
34
|
mockFsxExists.mockResolvedValue(true);
|
|
45
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
35
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
46
36
|
const normalized = p.replace(/\\/g, "/");
|
|
47
37
|
if (normalized.includes(".capacitor/package.json")) {
|
|
48
38
|
return {
|
|
@@ -60,15 +50,15 @@ describe("setupCapNpmConfig", () => {
|
|
|
60
50
|
};
|
|
61
51
|
}
|
|
62
52
|
return { name: "test-pkg", version: "1.0.0" };
|
|
63
|
-
});
|
|
53
|
+
}) as never);
|
|
64
54
|
});
|
|
65
55
|
|
|
66
56
|
it("루트 package.json이 없으면 에러를 던진다", async () => {
|
|
67
|
-
mockFsxExists.mockImplementation((p: string) => {
|
|
57
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
68
58
|
const n = p.replace(/\\/g, "/");
|
|
69
59
|
if (n.endsWith("package.json") && !n.includes(".capacitor")) return false;
|
|
70
60
|
return true;
|
|
71
|
-
});
|
|
61
|
+
}) as never);
|
|
72
62
|
|
|
73
63
|
const { setupCapNpmConfig } = await import(
|
|
74
64
|
"../../src/capacitor/capacitor-npm-config.js"
|
|
@@ -83,11 +73,11 @@ describe("setupCapNpmConfig", () => {
|
|
|
83
73
|
});
|
|
84
74
|
|
|
85
75
|
it(".capacitor/package.json이 없으면 빈 설정으로 시작한다", async () => {
|
|
86
|
-
mockFsxExists.mockImplementation((p: string) => {
|
|
76
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
87
77
|
const n = p.replace(/\\/g, "/");
|
|
88
78
|
if (n.includes(".capacitor/package.json")) return false;
|
|
89
79
|
return true;
|
|
90
|
-
});
|
|
80
|
+
}) as never);
|
|
91
81
|
|
|
92
82
|
const { setupCapNpmConfig } = await import(
|
|
93
83
|
"../../src/capacitor/capacitor-npm-config.js"
|
|
@@ -100,33 +90,5 @@ describe("setupCapNpmConfig", () => {
|
|
|
100
90
|
|
|
101
91
|
// 빈 설정에서 시작하므로 dependencies가 추가되어 변경됨
|
|
102
92
|
expect(changed).toBe(true);
|
|
103
|
-
expect(mockFsxWriteJson).toHaveBeenCalledOnce();
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("volta 설정을 루트 package.json에서 전파한다", async () => {
|
|
107
|
-
mockFsxReadJson.mockImplementation((p: string) => {
|
|
108
|
-
const normalized = p.replace(/\\/g, "/");
|
|
109
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
110
|
-
return {
|
|
111
|
-
name: "com.test.app",
|
|
112
|
-
version: "1.0.0",
|
|
113
|
-
dependencies: { "@capacitor/core": "^7", "@capacitor/app": "^7" },
|
|
114
|
-
devDependencies: { "@capacitor/cli": "^7", "@capacitor/assets": "^3" },
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
return { name: "test-pkg", version: "1.0.0", volta: { node: "20.18.0" } };
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
const { setupCapNpmConfig } = await import(
|
|
121
|
-
"../../src/capacitor/capacitor-npm-config.js"
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
await setupCapNpmConfig(CAP_PATH, PKG_PATH, {
|
|
125
|
-
appId: "com.test.app",
|
|
126
|
-
appName: "Test App",
|
|
127
|
-
}, { name: "test-pkg", version: "1.0.0" }, [], []);
|
|
128
|
-
|
|
129
|
-
const writeCall = mockFsxWriteJson.mock.calls[0] as [string, Record<string, unknown>, unknown];
|
|
130
|
-
expect(writeCall[1]["volta"]).toEqual({ node: "20.18.0" });
|
|
131
93
|
});
|
|
132
94
|
});
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
2
|
import { consola } from "consola";
|
|
3
3
|
|
|
4
|
+
import * as typecheckOrchestrator from "../../src/orchestrators/TypecheckOrchestrator";
|
|
5
|
+
import * as lintCore from "../../src/lint/lint-core";
|
|
6
|
+
import * as lintUtils from "../../src/lint/lint-utils";
|
|
7
|
+
import * as sdConfigMod from "../../src/utils/sd-config";
|
|
8
|
+
import * as packageUtils from "../../src/utils/package-utils";
|
|
9
|
+
|
|
10
|
+
import { runCheck } from "../../src/commands/check";
|
|
11
|
+
|
|
4
12
|
const mockLogger = {
|
|
5
13
|
debug: vi.fn(),
|
|
6
14
|
info: vi.fn(),
|
|
@@ -10,41 +18,13 @@ const mockLogger = {
|
|
|
10
18
|
success: vi.fn(),
|
|
11
19
|
};
|
|
12
20
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
discoverWorkspacePackages: vi.fn(),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
vi.mock("../../src/orchestrators/TypecheckOrchestrator", () => ({
|
|
24
|
-
executeTypecheck: mocks.executeTypecheck,
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
vi.mock("../../src/lint/lint-core", () => ({
|
|
28
|
-
executeLint: mocks.executeLint,
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
|
-
vi.mock("../../src/lint/lint-utils", () => ({
|
|
32
|
-
runLintInWorker: mocks.runLintInWorker,
|
|
33
|
-
}));
|
|
34
|
-
|
|
35
|
-
vi.mock("../../src/utils/sd-config", () => ({
|
|
36
|
-
loadSdConfig: mocks.loadSdConfig,
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
vi.mock("../../src/utils/package-utils", async (importOriginal) => {
|
|
40
|
-
const actual = await importOriginal<typeof import("../../src/utils/package-utils")>();
|
|
41
|
-
return {
|
|
42
|
-
...actual,
|
|
43
|
-
discoverWorkspacePackages: mocks.discoverWorkspacePackages,
|
|
44
|
-
};
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const { runCheck } = await import("../../src/commands/check");
|
|
21
|
+
const mocks = {
|
|
22
|
+
executeTypecheck: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
23
|
+
executeLint: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
24
|
+
runLintInWorker: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
25
|
+
loadSdConfig: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
26
|
+
discoverWorkspacePackages: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
27
|
+
};
|
|
48
28
|
|
|
49
29
|
/**
|
|
50
30
|
* Collects all calls to the given mock function's first argument into an array,
|
|
@@ -58,10 +38,19 @@ describe("runCheck", () => {
|
|
|
58
38
|
let savedExitCode: typeof process.exitCode;
|
|
59
39
|
|
|
60
40
|
beforeEach(() => {
|
|
61
|
-
vi.
|
|
41
|
+
vi.restoreAllMocks();
|
|
62
42
|
savedExitCode = process.exitCode;
|
|
63
43
|
process.exitCode = undefined;
|
|
64
44
|
|
|
45
|
+
vi.spyOn(consola, "withTag").mockReturnValue(mockLogger as any);
|
|
46
|
+
Object.values(mockLogger).forEach((m) => m.mockReset());
|
|
47
|
+
|
|
48
|
+
mocks.executeTypecheck = vi.spyOn(typecheckOrchestrator, "executeTypecheck");
|
|
49
|
+
mocks.executeLint = vi.spyOn(lintCore, "executeLint");
|
|
50
|
+
mocks.runLintInWorker = vi.spyOn(lintUtils, "runLintInWorker");
|
|
51
|
+
mocks.loadSdConfig = vi.spyOn(sdConfigMod, "loadSdConfig");
|
|
52
|
+
mocks.discoverWorkspacePackages = vi.spyOn(packageUtils, "discoverWorkspacePackages");
|
|
53
|
+
|
|
65
54
|
// Default: workspace packages
|
|
66
55
|
mocks.discoverWorkspacePackages.mockReturnValue(
|
|
67
56
|
new Map([
|
|
@@ -1,27 +1,18 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { cpx, fsx } from "@simplysm/core-node";
|
|
4
|
+
import { StorageFactory } from "@simplysm/storage";
|
|
3
5
|
|
|
4
|
-
const mocks =
|
|
5
|
-
execa: vi.
|
|
6
|
+
const mocks = {
|
|
7
|
+
execa: vi.spyOn(cpx, "spawn"),
|
|
6
8
|
fsx: {
|
|
7
|
-
readJson: vi.
|
|
8
|
-
copy: vi.
|
|
9
|
+
readJson: vi.spyOn(fsx, "readJson"),
|
|
10
|
+
copy: vi.spyOn(fsx, "copy"),
|
|
9
11
|
},
|
|
10
|
-
storageConnect: vi.
|
|
11
|
-
}
|
|
12
|
+
storageConnect: vi.spyOn(StorageFactory, "connect"),
|
|
13
|
+
};
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
cpx: {
|
|
15
|
-
spawn: mocks.execa,
|
|
16
|
-
},
|
|
17
|
-
fsx: mocks.fsx,
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
vi.mock("@simplysm/storage", () => ({
|
|
21
|
-
StorageFactory: { connect: mocks.storageConnect },
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
const { runDeployment } = await import("../../src/commands/publish/deployment-phase");
|
|
15
|
+
import { runDeployment } from "../../src/commands/publish/deployment-phase";
|
|
25
16
|
|
|
26
17
|
const CWD = process.cwd();
|
|
27
18
|
|
|
@@ -49,17 +40,17 @@ describe("runDeployment", () => {
|
|
|
49
40
|
it("deploys packages in dependency level order", async () => {
|
|
50
41
|
const publishOrder: string[] = [];
|
|
51
42
|
mocks.execa.mockImplementation(
|
|
52
|
-
(_cmd: string, _args?: string[], opts?: { cwd?: string }) => {
|
|
43
|
+
((_cmd: string, _args?: string[], opts?: { cwd?: string }) => {
|
|
53
44
|
publishOrder.push(path.basename(opts?.cwd ?? ""));
|
|
54
45
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
55
|
-
},
|
|
46
|
+
}) as never,
|
|
56
47
|
);
|
|
57
|
-
mocks.fsx.readJson.mockImplementation((p: string) => {
|
|
48
|
+
mocks.fsx.readJson.mockImplementation(((p: string) => {
|
|
58
49
|
if (p.includes("pkg-b")) {
|
|
59
50
|
return { name: "@simplysm/pkg-b", version: "14.0.1", dependencies: { "@simplysm/pkg-a": "~14.0.0" } };
|
|
60
51
|
}
|
|
61
52
|
return { name: "@simplysm/pkg-a", version: "14.0.1", dependencies: {} };
|
|
62
|
-
});
|
|
53
|
+
}) as never);
|
|
63
54
|
|
|
64
55
|
const logger = createLogger();
|
|
65
56
|
await runDeployment(
|
|
@@ -104,19 +95,19 @@ describe("runDeployment", () => {
|
|
|
104
95
|
});
|
|
105
96
|
|
|
106
97
|
it("reports partially deployed packages on failure", async () => {
|
|
107
|
-
mocks.fsx.readJson.mockImplementation((p: string) => {
|
|
98
|
+
mocks.fsx.readJson.mockImplementation(((p: string) => {
|
|
108
99
|
const name = path.basename(path.dirname(p));
|
|
109
100
|
return { name: `@simplysm/${name}`, version: "14.0.1", dependencies: {} };
|
|
110
|
-
});
|
|
101
|
+
}) as never);
|
|
111
102
|
|
|
112
103
|
// pkg-a succeeds, pkg-b fails
|
|
113
104
|
mocks.execa.mockImplementation(
|
|
114
|
-
(_cmd: string, _args?: string[], opts?: { cwd?: string }) => {
|
|
105
|
+
((_cmd: string, _args?: string[], opts?: { cwd?: string }) => {
|
|
115
106
|
if (opts?.cwd?.includes("pkg-b")) {
|
|
116
107
|
throw new Error("publish failed");
|
|
117
108
|
}
|
|
118
109
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
119
|
-
},
|
|
110
|
+
}) as never,
|
|
120
111
|
);
|
|
121
112
|
|
|
122
113
|
const logger = createLogger();
|