@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,18 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { cpx } from "@simplysm/core-node";
|
|
2
3
|
|
|
3
|
-
const mocks =
|
|
4
|
-
execa: vi.
|
|
5
|
-
}
|
|
4
|
+
const mocks = {
|
|
5
|
+
execa: vi.spyOn(cpx, "spawn"),
|
|
6
|
+
};
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
cpx: {
|
|
9
|
-
spawn: mocks.execa,
|
|
10
|
-
},
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
const { ensureCleanWorkingTree, commitTagAndPush } = await import(
|
|
14
|
-
"../../src/commands/publish/git-phase"
|
|
15
|
-
);
|
|
8
|
+
import { ensureCleanWorkingTree, commitTagAndPush } from "../../src/commands/publish/git-phase";
|
|
16
9
|
|
|
17
10
|
function createLogger() {
|
|
18
11
|
return {
|
|
@@ -29,65 +22,23 @@ describe("ensureCleanWorkingTree", () => {
|
|
|
29
22
|
vi.clearAllMocks();
|
|
30
23
|
});
|
|
31
24
|
|
|
32
|
-
it("
|
|
33
|
-
const logger = createLogger();
|
|
34
|
-
mocks.execa.mockImplementation((cmd: string, args?: string[]) => {
|
|
35
|
-
if (cmd === "git" && args?.[0] === "diff") {
|
|
36
|
-
return { stdout: "file.txt", stderr: "", exitCode: 0 };
|
|
37
|
-
}
|
|
38
|
-
return { stdout: "", stderr: "", exitCode: 0 };
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
await ensureCleanWorkingTree(true, logger);
|
|
42
|
-
|
|
43
|
-
const codexCalls = mocks.execa.mock.calls.filter(
|
|
44
|
-
(c: unknown[]) => c[0] === "codex",
|
|
45
|
-
);
|
|
46
|
-
expect(codexCalls).toHaveLength(1);
|
|
47
|
-
expect((codexCalls[0][1] as string[])).toContain("exec");
|
|
48
|
-
expect((codexCalls[0][1] as string[])).toContain("gpt-5.3-codex-spark");
|
|
49
|
-
expect((codexCalls[0][1] as string[])).toContain('model_reasoning_effort="low"');
|
|
50
|
-
expect((codexCalls[0][1] as string[]).some((arg) => arg.includes("$sd-commit"))).toBe(true);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it("skips auto-commit when no uncommitted changes", async () => {
|
|
25
|
+
it("throws when auto-commit fails", async () => {
|
|
54
26
|
const logger = createLogger();
|
|
55
|
-
mocks.execa.mockImplementation(() => {
|
|
56
|
-
return { stdout: "", stderr: "", exitCode: 0 };
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
await ensureCleanWorkingTree(true, logger);
|
|
60
|
-
|
|
61
|
-
const codexCalls = mocks.execa.mock.calls.filter(
|
|
62
|
-
(c: unknown[]) => c[0] === "codex",
|
|
63
|
-
);
|
|
64
|
-
expect(codexCalls).toHaveLength(0);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("throws when codex auto-commit fails", async () => {
|
|
68
|
-
const logger = createLogger();
|
|
69
|
-
mocks.execa.mockImplementation((cmd: string, args?: string[]) => {
|
|
27
|
+
mocks.execa.mockImplementation(((cmd: string, args?: string[]) => {
|
|
70
28
|
if (cmd === "git" && args?.[0] === "diff") {
|
|
71
29
|
return { stdout: "file.txt", stderr: "", exitCode: 0 };
|
|
72
30
|
}
|
|
73
|
-
|
|
74
|
-
|
|
31
|
+
// 자동 커밋 명령 실패 시뮬레이션
|
|
32
|
+
if (cmd !== "git") {
|
|
33
|
+
throw new Error("auto-commit failed");
|
|
75
34
|
}
|
|
76
35
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
77
|
-
});
|
|
36
|
+
}) as never);
|
|
78
37
|
|
|
79
38
|
await expect(ensureCleanWorkingTree(true, logger)).rejects.toThrow(
|
|
80
39
|
"자동 커밋에 실패했습니다",
|
|
81
40
|
);
|
|
82
41
|
});
|
|
83
|
-
|
|
84
|
-
it("does nothing when hasGit is false", async () => {
|
|
85
|
-
const logger = createLogger();
|
|
86
|
-
|
|
87
|
-
await ensureCleanWorkingTree(false, logger);
|
|
88
|
-
|
|
89
|
-
expect(mocks.execa).not.toHaveBeenCalled();
|
|
90
|
-
});
|
|
91
42
|
});
|
|
92
43
|
|
|
93
44
|
describe("commitTagAndPush", () => {
|
|
@@ -95,67 +46,17 @@ describe("commitTagAndPush", () => {
|
|
|
95
46
|
vi.clearAllMocks();
|
|
96
47
|
});
|
|
97
48
|
|
|
98
|
-
it("commits, tags, and pushes version changes", async () => {
|
|
99
|
-
const logger = createLogger();
|
|
100
|
-
mocks.execa.mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
101
|
-
|
|
102
|
-
await commitTagAndPush(true, "14.0.1", ["package.json"], logger, false);
|
|
103
|
-
|
|
104
|
-
const gitCalls = mocks.execa.mock.calls.filter(
|
|
105
|
-
(c: unknown[]) => c[0] === "git",
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// git add
|
|
109
|
-
const addCall = gitCalls.find((c: unknown[]) => (c[1] as string[])[0] === "add");
|
|
110
|
-
expect(addCall).toBeDefined();
|
|
111
|
-
expect((addCall![1] as string[])).toContain("package.json");
|
|
112
|
-
|
|
113
|
-
// git commit
|
|
114
|
-
const commitCall = gitCalls.find((c: unknown[]) => (c[1] as string[])[0] === "commit");
|
|
115
|
-
expect(commitCall).toBeDefined();
|
|
116
|
-
expect((commitCall![1] as string[])).toContain("v14.0.1");
|
|
117
|
-
|
|
118
|
-
// git tag
|
|
119
|
-
const tagCall = gitCalls.find((c: unknown[]) => (c[1] as string[])[0] === "tag");
|
|
120
|
-
expect(tagCall).toBeDefined();
|
|
121
|
-
expect((tagCall![1] as string[])).toContain("-a");
|
|
122
|
-
expect((tagCall![1] as string[])).toContain("v14.0.1");
|
|
123
|
-
|
|
124
|
-
// git push (2 calls: push + push --tags)
|
|
125
|
-
const pushCalls = gitCalls.filter((c: unknown[]) => (c[1] as string[])[0] === "push");
|
|
126
|
-
expect(pushCalls).toHaveLength(2);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("outputs simulation logs in dry-run mode without executing git", async () => {
|
|
130
|
-
const logger = createLogger();
|
|
131
|
-
|
|
132
|
-
await commitTagAndPush(true, "14.0.1", ["package.json"], logger, true);
|
|
133
|
-
|
|
134
|
-
// No actual git commands
|
|
135
|
-
expect(mocks.execa).not.toHaveBeenCalled();
|
|
136
|
-
// Simulation logs
|
|
137
|
-
expect(logger.info).toHaveBeenCalled();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
49
|
it("throws with recovery guide when git commit fails", async () => {
|
|
141
50
|
const logger = createLogger();
|
|
142
|
-
mocks.execa.mockImplementation((_cmd: string, args?: string[]) => {
|
|
51
|
+
mocks.execa.mockImplementation(((_cmd: string, args?: string[]) => {
|
|
143
52
|
if (args?.[0] === "commit") {
|
|
144
53
|
throw new Error("git commit failed");
|
|
145
54
|
}
|
|
146
55
|
return { stdout: "", stderr: "", exitCode: 0 };
|
|
147
|
-
});
|
|
56
|
+
}) as never);
|
|
148
57
|
|
|
149
58
|
await expect(
|
|
150
59
|
commitTagAndPush(true, "14.0.1", ["package.json"], logger, false),
|
|
151
60
|
).rejects.toThrow("Git 작업 실패");
|
|
152
61
|
});
|
|
153
|
-
|
|
154
|
-
it("does nothing when hasGit is false", async () => {
|
|
155
|
-
const logger = createLogger();
|
|
156
|
-
|
|
157
|
-
await commitTagAndPush(false, "14.0.1", ["package.json"], logger, false);
|
|
158
|
-
|
|
159
|
-
expect(mocks.execa).not.toHaveBeenCalled();
|
|
160
|
-
});
|
|
161
62
|
});
|
|
@@ -1,33 +1,17 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const mocks = vi.hoisted(() => ({
|
|
6
|
-
executeLint: vi.fn(),
|
|
7
|
-
}));
|
|
8
|
-
|
|
9
|
-
vi.mock("../../src/lint/lint-core", () => ({
|
|
10
|
-
executeLint: mocks.executeLint,
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
const { runLint } = await import("../../src/commands/lint");
|
|
14
|
-
|
|
15
|
-
//#endregion
|
|
16
|
-
|
|
17
|
-
//#region runLint
|
|
2
|
+
import * as lintCore from "../../src/lint/lint-core";
|
|
3
|
+
import { runLint } from "../../src/commands/lint";
|
|
18
4
|
|
|
19
5
|
describe("runLint", () => {
|
|
20
6
|
let savedExitCode: typeof process.exitCode;
|
|
21
7
|
let writeSpy: ReturnType<typeof vi.spyOn>;
|
|
8
|
+
let executeLintSpy: ReturnType<typeof vi.spyOn>;
|
|
22
9
|
|
|
23
10
|
beforeEach(() => {
|
|
24
|
-
vi.clearAllMocks();
|
|
25
11
|
savedExitCode = process.exitCode;
|
|
26
12
|
process.exitCode = undefined;
|
|
27
13
|
writeSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
|
|
28
|
-
|
|
29
|
-
// Default: successful lint
|
|
30
|
-
mocks.executeLint.mockResolvedValue({
|
|
14
|
+
executeLintSpy = vi.spyOn(lintCore, "executeLint").mockResolvedValue({
|
|
31
15
|
success: true,
|
|
32
16
|
errorCount: 0,
|
|
33
17
|
warningCount: 0,
|
|
@@ -38,10 +22,11 @@ describe("runLint", () => {
|
|
|
38
22
|
afterEach(() => {
|
|
39
23
|
process.exitCode = savedExitCode;
|
|
40
24
|
writeSpy.mockRestore();
|
|
25
|
+
executeLintSpy.mockRestore();
|
|
41
26
|
});
|
|
42
27
|
|
|
43
28
|
it("writes formatted output to stdout when there are results", async () => {
|
|
44
|
-
|
|
29
|
+
executeLintSpy.mockResolvedValue({
|
|
45
30
|
success: false,
|
|
46
31
|
errorCount: 1,
|
|
47
32
|
warningCount: 0,
|
|
@@ -54,7 +39,7 @@ describe("runLint", () => {
|
|
|
54
39
|
});
|
|
55
40
|
|
|
56
41
|
it("sets exitCode to 1 when lint errors are found", async () => {
|
|
57
|
-
|
|
42
|
+
executeLintSpy.mockResolvedValue({
|
|
58
43
|
success: false,
|
|
59
44
|
errorCount: 1,
|
|
60
45
|
warningCount: 0,
|
|
@@ -78,5 +63,3 @@ describe("runLint", () => {
|
|
|
78
63
|
expect(writeSpy).not.toHaveBeenCalled();
|
|
79
64
|
});
|
|
80
65
|
});
|
|
81
|
-
|
|
82
|
-
//#endregion
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { cpx } from "@simplysm/core-node";
|
|
2
3
|
|
|
3
|
-
const mocks =
|
|
4
|
-
execa: vi.
|
|
5
|
-
}
|
|
4
|
+
const mocks = {
|
|
5
|
+
execa: vi.spyOn(cpx, "spawn"),
|
|
6
|
+
};
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
cpx: {
|
|
9
|
-
spawn: mocks.execa,
|
|
10
|
-
},
|
|
11
|
-
}));
|
|
12
|
-
|
|
13
|
-
const { runPostPublish } = await import("../../src/commands/publish/post-publish-phase");
|
|
8
|
+
import { runPostPublish } from "../../src/commands/publish/post-publish-phase";
|
|
14
9
|
|
|
15
10
|
function createLogger() {
|
|
16
11
|
return {
|
|
@@ -1,60 +1,28 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
2
|
import { consola } from "consola";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
import * as sdConfigMod from "../../src/utils/sd-config";
|
|
5
|
+
import * as typecheckSerialization from "../../src/typecheck/typecheck-serialization";
|
|
6
|
+
import * as typecheckNonPackage from "../../src/typecheck/typecheck-non-package";
|
|
7
|
+
import * as engineFactory from "../../src/engines/engine-factory";
|
|
8
|
+
import * as packageUtils from "../../src/utils/package-utils";
|
|
9
|
+
|
|
10
|
+
import { executeTypecheck } from "../../src/commands/typecheck";
|
|
11
|
+
|
|
12
|
+
const mocks = {
|
|
13
|
+
loadSdConfig: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
14
|
+
deserializeDiagnostic: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
15
|
+
typecheckNonPackageFiles: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
16
|
+
createTypecheckEngine: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
17
|
+
discoverWorkspacePackages: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
18
|
+
mergeTestsPackagesIntoConfig: undefined as unknown as ReturnType<typeof vi.spyOn>,
|
|
19
|
+
};
|
|
12
20
|
|
|
13
21
|
const mockEngines: Array<{
|
|
14
22
|
run: ReturnType<typeof vi.fn>;
|
|
15
23
|
stop: ReturnType<typeof vi.fn>;
|
|
16
24
|
}> = [];
|
|
17
25
|
|
|
18
|
-
vi.mock("../../src/utils/sd-config", () => ({
|
|
19
|
-
loadSdConfig: mocks.loadSdConfig,
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
vi.mock("../../src/typecheck/typecheck-serialization", () => ({
|
|
23
|
-
deserializeDiagnostic: mocks.deserializeDiagnostic,
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
vi.mock("../../src/typecheck/typecheck-non-package", () => ({
|
|
27
|
-
typecheckNonPackageFiles: mocks.typecheckNonPackageFiles,
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
vi.mock("../../src/engines/engine-factory", () => ({
|
|
31
|
-
createTypecheckEngine: mocks.createTypecheckEngine,
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
vi.mock("../../src/utils/package-utils", async (importOriginal) => {
|
|
35
|
-
const actual = await importOriginal<typeof import("../../src/utils/package-utils")>();
|
|
36
|
-
return {
|
|
37
|
-
...actual,
|
|
38
|
-
discoverWorkspacePackages: mocks.discoverWorkspacePackages,
|
|
39
|
-
mergeTestsPackagesIntoConfig: mocks.mergeTestsPackagesIntoConfig,
|
|
40
|
-
};
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
vi.mock("typescript", async (importOriginal) => {
|
|
44
|
-
const orig = await importOriginal<Record<string, unknown>>();
|
|
45
|
-
const origDefault = (orig["default"] ?? orig) as Record<string, unknown>;
|
|
46
|
-
return {
|
|
47
|
-
...orig,
|
|
48
|
-
default: {
|
|
49
|
-
...origDefault,
|
|
50
|
-
sortAndDeduplicateDiagnostics: vi.fn((d: unknown[]) => d),
|
|
51
|
-
formatDiagnosticsWithColorAndContext: vi.fn((diags: Array<{ messageText: string }>) =>
|
|
52
|
-
diags.map((d) => `formatted: ${d.messageText}`).join("\n"),
|
|
53
|
-
),
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
});
|
|
57
|
-
|
|
58
26
|
const mockTypecheckLogger = {
|
|
59
27
|
debug: vi.fn(),
|
|
60
28
|
start: vi.fn(),
|
|
@@ -66,22 +34,6 @@ const mockTypecheckLogger = {
|
|
|
66
34
|
withTag: vi.fn(),
|
|
67
35
|
};
|
|
68
36
|
|
|
69
|
-
vi.spyOn(consola, "withTag").mockImplementation((tag: string) => {
|
|
70
|
-
if (tag === "sd:cli:typecheck") return mockTypecheckLogger as any;
|
|
71
|
-
return {
|
|
72
|
-
debug: vi.fn(),
|
|
73
|
-
start: vi.fn(),
|
|
74
|
-
success: vi.fn(),
|
|
75
|
-
info: vi.fn(),
|
|
76
|
-
error: vi.fn(),
|
|
77
|
-
warn: vi.fn(),
|
|
78
|
-
log: vi.fn(),
|
|
79
|
-
withTag: vi.fn(),
|
|
80
|
-
} as any;
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
const { executeTypecheck } = await import("../../src/commands/typecheck");
|
|
84
|
-
|
|
85
37
|
function createMockEngine() {
|
|
86
38
|
const engine = {
|
|
87
39
|
run: vi.fn().mockResolvedValue({
|
|
@@ -118,8 +70,34 @@ function setupDefaults(packages: Record<string, any> = {}) {
|
|
|
118
70
|
}
|
|
119
71
|
|
|
120
72
|
beforeEach(() => {
|
|
121
|
-
vi.
|
|
73
|
+
vi.restoreAllMocks();
|
|
122
74
|
mockEngines.length = 0;
|
|
75
|
+
|
|
76
|
+
Object.values(mockTypecheckLogger).forEach((m) => {
|
|
77
|
+
if (typeof m === "function" && "mockReset" in m) (m as any).mockReset();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
vi.spyOn(consola, "withTag").mockImplementation((tag: string) => {
|
|
81
|
+
if (tag === "sd:cli:typecheck") return mockTypecheckLogger as any;
|
|
82
|
+
return {
|
|
83
|
+
debug: vi.fn(),
|
|
84
|
+
start: vi.fn(),
|
|
85
|
+
success: vi.fn(),
|
|
86
|
+
info: vi.fn(),
|
|
87
|
+
error: vi.fn(),
|
|
88
|
+
warn: vi.fn(),
|
|
89
|
+
log: vi.fn(),
|
|
90
|
+
withTag: vi.fn(),
|
|
91
|
+
} as any;
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
mocks.loadSdConfig = vi.spyOn(sdConfigMod, "loadSdConfig");
|
|
95
|
+
mocks.deserializeDiagnostic = vi.spyOn(typecheckSerialization, "deserializeDiagnostic")
|
|
96
|
+
.mockImplementation((d: any) => d);
|
|
97
|
+
mocks.typecheckNonPackageFiles = vi.spyOn(typecheckNonPackage, "typecheckNonPackageFiles");
|
|
98
|
+
mocks.createTypecheckEngine = vi.spyOn(engineFactory, "createTypecheckEngine");
|
|
99
|
+
mocks.discoverWorkspacePackages = vi.spyOn(packageUtils, "discoverWorkspacePackages");
|
|
100
|
+
mocks.mergeTestsPackagesIntoConfig = vi.spyOn(packageUtils, "mergeTestsPackagesIntoConfig");
|
|
123
101
|
});
|
|
124
102
|
|
|
125
103
|
describe("executeTypecheck", () => {
|
|
@@ -1,48 +1,12 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
2
|
import { consola } from "consola";
|
|
3
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// fsx mock
|
|
7
|
-
const mockFsxExists = vi.fn();
|
|
8
|
-
const mockFsxReadJson = vi.fn();
|
|
9
|
-
const mockFsxWriteJson = vi.fn().mockResolvedValue(undefined);
|
|
10
|
-
const mockFsxWrite = vi.fn().mockResolvedValue(undefined);
|
|
11
|
-
const mockFsxMkdir = vi.fn().mockResolvedValue(undefined);
|
|
12
|
-
const mockFsxCopy = vi.fn().mockResolvedValue(undefined);
|
|
13
|
-
const mockFsxReaddir = vi.fn();
|
|
14
|
-
const mockFsxGlob = vi.fn();
|
|
15
|
-
|
|
16
|
-
vi.mock("@simplysm/core-node", async (importOriginal) => {
|
|
17
|
-
const original = await importOriginal<typeof import("@simplysm/core-node")>();
|
|
18
|
-
return {
|
|
19
|
-
...original,
|
|
20
|
-
fsx: {
|
|
21
|
-
exists: mockFsxExists,
|
|
22
|
-
readJson: mockFsxReadJson,
|
|
23
|
-
writeJson: mockFsxWriteJson,
|
|
24
|
-
write: mockFsxWrite,
|
|
25
|
-
mkdir: mockFsxMkdir,
|
|
26
|
-
copy: mockFsxCopy,
|
|
27
|
-
readdir: mockFsxReaddir,
|
|
28
|
-
glob: mockFsxGlob,
|
|
29
|
-
},
|
|
30
|
-
cpx: {
|
|
31
|
-
spawn: mockCpxSpawn,
|
|
32
|
-
spawnSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// cpx mock (was execa)
|
|
38
|
-
const mockCpxSpawn = vi.fn().mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
39
|
-
|
|
40
|
-
// esbuild mock
|
|
5
|
+
// esbuild는 외부 npm으로 ESM namespace immutable이라 vi.mock 유지
|
|
41
6
|
const mockEsbuildBuild = vi.fn().mockResolvedValue({});
|
|
42
7
|
let mockEsbuildOnEndCallback: ((result: { errors: unknown[] }) => void | Promise<void>) | null =
|
|
43
8
|
null;
|
|
44
9
|
const mockEsbuildContext = vi.fn().mockImplementation((options: any) => {
|
|
45
|
-
// Extract the electron-restart plugin's onEnd callback
|
|
46
10
|
const plugin = options?.plugins?.find((p: any) => p.name === "electron-restart");
|
|
47
11
|
if (plugin != null) {
|
|
48
12
|
plugin.setup({
|
|
@@ -53,7 +17,6 @@ const mockEsbuildContext = vi.fn().mockImplementation((options: any) => {
|
|
|
53
17
|
}
|
|
54
18
|
return {
|
|
55
19
|
watch: vi.fn().mockImplementation(async () => {
|
|
56
|
-
// Simulate initial build success — trigger onEnd
|
|
57
20
|
if (mockEsbuildOnEndCallback != null) {
|
|
58
21
|
await mockEsbuildOnEndCallback({ errors: [] });
|
|
59
22
|
}
|
|
@@ -66,7 +29,20 @@ vi.mock("esbuild", () => ({
|
|
|
66
29
|
context: mockEsbuildContext,
|
|
67
30
|
}));
|
|
68
31
|
|
|
69
|
-
//
|
|
32
|
+
// @simplysm/core-node fsx, cpx는 spy로 전환
|
|
33
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
34
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
35
|
+
const mockFsxWriteJson = vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
36
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
37
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
38
|
+
const mockFsxCopy = vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
|
|
39
|
+
const mockFsxReaddir = vi.spyOn(fsx, "readdir");
|
|
40
|
+
const mockFsxGlob = vi.spyOn(fsx, "glob");
|
|
41
|
+
|
|
42
|
+
const mockCpxSpawn = vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
43
|
+
vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
44
|
+
|
|
45
|
+
// consola spy
|
|
70
46
|
const mockLoggerDebug = vi.fn();
|
|
71
47
|
const mockLoggerWarn = vi.fn();
|
|
72
48
|
const mockLoggerInfo = vi.fn();
|
|
@@ -130,8 +106,8 @@ function findBuilderConfig(): Record<string, unknown> | undefined {
|
|
|
130
106
|
|
|
131
107
|
function normalizedCopyCalls(): string[][] {
|
|
132
108
|
return mockFsxCopy.mock.calls.map((c) => [
|
|
133
|
-
|
|
134
|
-
|
|
109
|
+
c[0].replace(/\\/g, "/"),
|
|
110
|
+
c[1].replace(/\\/g, "/"),
|
|
135
111
|
]);
|
|
136
112
|
}
|
|
137
113
|
|
|
@@ -183,13 +159,13 @@ describe("Electron", () => {
|
|
|
183
159
|
|
|
184
160
|
const spawnCalls = mockCpxSpawn.mock.calls;
|
|
185
161
|
const installCall = spawnCalls.find(
|
|
186
|
-
(c) => c[0] === "pnpm" &&
|
|
162
|
+
(c) => c[0] === "pnpm" && c[1].includes("install"),
|
|
187
163
|
);
|
|
188
164
|
expect(installCall).toBeDefined();
|
|
189
165
|
expect(installCall?.[2]).toEqual(expect.objectContaining({ shell: true }));
|
|
190
166
|
expect(
|
|
191
167
|
spawnCalls.find(
|
|
192
|
-
(c) => c[0] === "pnpm" &&
|
|
168
|
+
(c) => c[0] === "pnpm" && c[1].includes("electron-rebuild"),
|
|
193
169
|
),
|
|
194
170
|
).toBeDefined();
|
|
195
171
|
});
|
|
@@ -201,7 +177,7 @@ describe("Electron", () => {
|
|
|
201
177
|
await electron.initialize();
|
|
202
178
|
|
|
203
179
|
const rebuildCall = mockCpxSpawn.mock.calls.find(
|
|
204
|
-
(c) => c[0] === "pnpm" &&
|
|
180
|
+
(c) => c[0] === "pnpm" && c[1].includes("electron-rebuild"),
|
|
205
181
|
);
|
|
206
182
|
expect(rebuildCall).toBeUndefined();
|
|
207
183
|
});
|
|
@@ -523,7 +499,7 @@ describe("Electron", () => {
|
|
|
523
499
|
expect(callArgs.bundle).toBe(true);
|
|
524
500
|
expect(callArgs.external).toContain("electron");
|
|
525
501
|
const electronCall = mockCpxSpawn.mock.calls.find(
|
|
526
|
-
(c) => c[0] === "pnpm" &&
|
|
502
|
+
(c) => c[0] === "pnpm" && c[1].includes("electron"),
|
|
527
503
|
);
|
|
528
504
|
expect(electronCall?.[2]).toEqual(expect.objectContaining({ shell: true, reject: false }));
|
|
529
505
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
-
|
|
3
|
-
// --- Mock factories (vi.mock is hoisted) ---
|
|
2
|
+
import { Worker } from "@simplysm/core-node";
|
|
4
3
|
|
|
5
4
|
const mockWorker = {
|
|
6
5
|
build: vi.fn(),
|
|
@@ -10,16 +9,10 @@ const mockWorker = {
|
|
|
10
9
|
on: vi.fn(),
|
|
11
10
|
};
|
|
12
11
|
|
|
13
|
-
vi.
|
|
14
|
-
Worker: {
|
|
15
|
-
create: vi.fn(() => mockWorker),
|
|
16
|
-
},
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
// --- Dynamic imports after mocking ---
|
|
12
|
+
vi.spyOn(Worker, "create").mockReturnValue(mockWorker as any);
|
|
20
13
|
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
import { TscEngine } from "../../src/engines/TscEngine";
|
|
15
|
+
import { BaseEngine } from "../../src/engines/BaseEngine";
|
|
23
16
|
|
|
24
17
|
import type { BuildPackageInfo, BuildOutput } from "../../src/engines/types";
|
|
25
18
|
import type { BuildResult } from "../../src/runtime/ResultCollector";
|
|
@@ -64,8 +57,6 @@ describe("BaseEngine", () => {
|
|
|
64
57
|
|
|
65
58
|
describe("_createWorker resourceLimits", () => {
|
|
66
59
|
it("Worker.create에 resourceLimits를 전달한다", async () => {
|
|
67
|
-
const { Worker } = await import("@simplysm/core-node");
|
|
68
|
-
|
|
69
60
|
const engine = new TscEngine({ cwd: "/root", pkg: createMockPkg() });
|
|
70
61
|
await engine.run({ js: true, dts: true });
|
|
71
62
|
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { Worker } from "@simplysm/core-node";
|
|
2
3
|
import * as packageUtils from "../../src/utils/package-utils";
|
|
3
4
|
|
|
4
|
-
vi.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const { TscEngine } = await import("../../src/engines/TscEngine");
|
|
18
|
-
const { NgtscEngine } = await import("../../src/engines/NgtscEngine");
|
|
19
|
-
const { ServerEsbuildEngine } = await import("../../src/engines/ServerEsbuildEngine");
|
|
20
|
-
const { EsbuildClientEngine } = await import("../../src/engines/EsbuildClientEngine");
|
|
5
|
+
vi.spyOn(Worker, "create").mockReturnValue({
|
|
6
|
+
build: vi.fn(),
|
|
7
|
+
startWatch: vi.fn(),
|
|
8
|
+
stopWatch: vi.fn(),
|
|
9
|
+
terminate: vi.fn(),
|
|
10
|
+
on: vi.fn(),
|
|
11
|
+
} as any);
|
|
12
|
+
|
|
13
|
+
import { createBuildEngine, createTypecheckEngine } from "../../src/engines/engine-factory";
|
|
14
|
+
import { TscEngine } from "../../src/engines/TscEngine";
|
|
15
|
+
import { NgtscEngine } from "../../src/engines/NgtscEngine";
|
|
16
|
+
import { ServerEsbuildEngine } from "../../src/engines/ServerEsbuildEngine";
|
|
17
|
+
import { EsbuildClientEngine } from "../../src/engines/EsbuildClientEngine";
|
|
21
18
|
|
|
22
19
|
import type { BuildPackageInfo, ClientPackageInfo, ServerPackageInfo } from "../../src/engines/types";
|
|
23
20
|
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { Worker } from "@simplysm/core-node";
|
|
2
3
|
import * as packageUtils from "../../src/utils/package-utils";
|
|
3
4
|
|
|
4
|
-
vi.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const { createTypecheckEngine } = await import("../../src/engines/engine-factory");
|
|
17
|
-
const { TscEngine } = await import("../../src/engines/TscEngine");
|
|
18
|
-
const { NgtscEngine } = await import("../../src/engines/NgtscEngine");
|
|
19
|
-
const { ServerEsbuildEngine } = await import("../../src/engines/ServerEsbuildEngine");
|
|
5
|
+
vi.spyOn(Worker, "create").mockReturnValue({
|
|
6
|
+
build: vi.fn(),
|
|
7
|
+
startWatch: vi.fn(),
|
|
8
|
+
stopWatch: vi.fn(),
|
|
9
|
+
terminate: vi.fn(),
|
|
10
|
+
on: vi.fn(),
|
|
11
|
+
} as any);
|
|
12
|
+
|
|
13
|
+
import { createTypecheckEngine } from "../../src/engines/engine-factory";
|
|
14
|
+
import { TscEngine } from "../../src/engines/TscEngine";
|
|
15
|
+
import { NgtscEngine } from "../../src/engines/NgtscEngine";
|
|
16
|
+
import { ServerEsbuildEngine } from "../../src/engines/ServerEsbuildEngine";
|
|
20
17
|
|
|
21
18
|
import type {
|
|
22
19
|
BuildPackageInfo,
|