@simplysm/sd-cli 14.0.64 → 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,8 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
2
|
import path from "path";
|
|
3
3
|
|
|
4
|
-
//
|
|
5
|
-
|
|
4
|
+
// 외부 npm + Node 표준 모듈은 ESM namespace immutable이라 vi.mock 유지
|
|
6
5
|
const mockContext = {
|
|
7
6
|
rebuild: vi.fn(),
|
|
8
7
|
watch: vi.fn(),
|
|
@@ -15,18 +14,6 @@ vi.mock("esbuild", () => ({
|
|
|
15
14
|
},
|
|
16
15
|
}));
|
|
17
16
|
|
|
18
|
-
const mockAngularPlugin = { name: "sd-angular-compiler" };
|
|
19
|
-
|
|
20
|
-
vi.mock("../../src/esbuild/esbuild-angular-compiler-plugin", () => ({
|
|
21
|
-
createAngularCompilerPlugin: vi.fn(() => mockAngularPlugin),
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
const mockTransformStylesheet = vi.fn();
|
|
25
|
-
|
|
26
|
-
vi.mock("../../src/angular/client-transform-stylesheet", () => ({
|
|
27
|
-
createClientTransformStylesheet: vi.fn(() => mockTransformStylesheet),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
17
|
vi.mock("browserslist-to-esbuild", () => ({
|
|
31
18
|
default: vi.fn(() => ["chrome61"]),
|
|
32
19
|
}));
|
|
@@ -44,7 +31,14 @@ vi.mock("module", async (importOriginal) => {
|
|
|
44
31
|
};
|
|
45
32
|
});
|
|
46
33
|
|
|
47
|
-
|
|
34
|
+
import * as angularPluginMod from "../../src/esbuild/esbuild-angular-compiler-plugin";
|
|
35
|
+
import * as transformStylesheetMod from "../../src/angular/client-transform-stylesheet";
|
|
36
|
+
|
|
37
|
+
const mockAngularPlugin = { name: "sd-angular-compiler" };
|
|
38
|
+
const mockTransformStylesheet = vi.fn();
|
|
39
|
+
|
|
40
|
+
vi.spyOn(angularPluginMod, "createAngularCompilerPlugin").mockReturnValue(mockAngularPlugin as any);
|
|
41
|
+
vi.spyOn(transformStylesheetMod, "createClientTransformStylesheet").mockReturnValue(mockTransformStylesheet as any);
|
|
48
42
|
|
|
49
43
|
const { createClientEsbuildContext, ClientSourceFileCache } = await import(
|
|
50
44
|
"../../src/esbuild/esbuild-client-config"
|
|
@@ -2,8 +2,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import type esbuildTypes from "esbuild";
|
|
4
4
|
|
|
5
|
-
//
|
|
6
|
-
|
|
5
|
+
// 외부 npm + Node 표준 모듈은 ESM namespace immutable이라 vi.mock 유지
|
|
7
6
|
const mockContext = {
|
|
8
7
|
rebuild: vi.fn(),
|
|
9
8
|
watch: vi.fn(),
|
|
@@ -16,18 +15,6 @@ vi.mock("esbuild", () => ({
|
|
|
16
15
|
},
|
|
17
16
|
}));
|
|
18
17
|
|
|
19
|
-
const mockAngularPlugin = { name: "sd-angular-compiler" };
|
|
20
|
-
|
|
21
|
-
vi.mock("../../src/esbuild/esbuild-angular-compiler-plugin", () => ({
|
|
22
|
-
createAngularCompilerPlugin: vi.fn(() => mockAngularPlugin),
|
|
23
|
-
}));
|
|
24
|
-
|
|
25
|
-
const mockTransformStylesheet = vi.fn();
|
|
26
|
-
|
|
27
|
-
vi.mock("../../src/angular/client-transform-stylesheet", () => ({
|
|
28
|
-
createClientTransformStylesheet: vi.fn(() => mockTransformStylesheet),
|
|
29
|
-
}));
|
|
30
|
-
|
|
31
18
|
vi.mock("browserslist-to-esbuild", () => ({
|
|
32
19
|
default: vi.fn(() => ["chrome61"]),
|
|
33
20
|
}));
|
|
@@ -45,18 +32,19 @@ vi.mock("module", async (importOriginal) => {
|
|
|
45
32
|
};
|
|
46
33
|
});
|
|
47
34
|
|
|
48
|
-
|
|
35
|
+
import * as angularPluginMod from "../../src/esbuild/esbuild-angular-compiler-plugin";
|
|
36
|
+
import * as transformStylesheetMod from "../../src/angular/client-transform-stylesheet";
|
|
37
|
+
|
|
38
|
+
const mockAngularPlugin = { name: "sd-angular-compiler" };
|
|
39
|
+
const mockTransformStylesheet = vi.fn();
|
|
40
|
+
|
|
41
|
+
vi.spyOn(angularPluginMod, "createAngularCompilerPlugin").mockReturnValue(mockAngularPlugin as any);
|
|
42
|
+
vi.spyOn(transformStylesheetMod, "createClientTransformStylesheet").mockReturnValue(mockTransformStylesheet as any);
|
|
49
43
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
44
|
+
import { createClientEsbuildContext, ClientSourceFileCache } from "../../src/esbuild/esbuild-client-config";
|
|
45
|
+
import { createAngularCompilerPlugin } from "../../src/esbuild/esbuild-angular-compiler-plugin";
|
|
46
|
+
import { createClientTransformStylesheet } from "../../src/angular/client-transform-stylesheet";
|
|
53
47
|
const esbuild = (await import("esbuild")).default;
|
|
54
|
-
const { createAngularCompilerPlugin } = await import(
|
|
55
|
-
"../../src/esbuild/esbuild-angular-compiler-plugin"
|
|
56
|
-
);
|
|
57
|
-
const { createClientTransformStylesheet } = await import(
|
|
58
|
-
"../../src/angular/client-transform-stylesheet"
|
|
59
|
-
);
|
|
60
48
|
const browserslistToEsbuild = (await import("browserslist-to-esbuild")).default;
|
|
61
49
|
|
|
62
50
|
// --- Helpers ---
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { describe, it, expect,
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import fs from "fs/promises";
|
|
4
|
+
import os from "os";
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
const { createServerEsbuildOptions, createEnvBanner, writeChangedOutputFiles } =
|
|
13
|
-
await import("../../src/esbuild/esbuild-config");
|
|
14
|
-
|
|
15
|
-
const { default: mockFs } = await import("fs/promises");
|
|
6
|
+
import {
|
|
7
|
+
createServerEsbuildOptions,
|
|
8
|
+
createEnvBanner,
|
|
9
|
+
writeChangedOutputFiles,
|
|
10
|
+
} from "../../src/esbuild/esbuild-config";
|
|
16
11
|
|
|
17
12
|
describe("createServerEsbuildOptions", () => {
|
|
18
13
|
const baseOptions = {
|
|
@@ -121,93 +116,107 @@ describe("createEnvBanner", () => {
|
|
|
121
116
|
});
|
|
122
117
|
|
|
123
118
|
describe("writeChangedOutputFiles", () => {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
119
|
+
let tmpDir: string;
|
|
120
|
+
|
|
121
|
+
beforeEach(async () => {
|
|
122
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "sd-esbuild-config-"));
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
afterEach(async () => {
|
|
126
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
128
127
|
});
|
|
129
128
|
|
|
130
129
|
it("adds .js extension to relative import paths in .js files", async () => {
|
|
131
|
-
|
|
130
|
+
const distDir = path.join(tmpDir, "dist");
|
|
131
|
+
const filePath = path.join(distDir, "foo.js");
|
|
132
132
|
|
|
133
133
|
await writeChangedOutputFiles([
|
|
134
134
|
{
|
|
135
|
-
path:
|
|
135
|
+
path: filePath,
|
|
136
136
|
text: 'import { bar } from "./bar";\nexport { baz } from "../utils/baz";',
|
|
137
137
|
},
|
|
138
138
|
] as any);
|
|
139
139
|
|
|
140
|
-
|
|
141
|
-
|
|
140
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
141
|
+
expect(written).toBe(
|
|
142
142
|
'import { bar } from "./bar.js";\nexport { baz } from "../utils/baz.js";',
|
|
143
143
|
);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
146
|
it("preserves imports that already have extensions", async () => {
|
|
147
|
-
|
|
147
|
+
const filePath = path.join(tmpDir, "dist", "foo.js");
|
|
148
148
|
|
|
149
149
|
await writeChangedOutputFiles([
|
|
150
150
|
{
|
|
151
|
-
path:
|
|
151
|
+
path: filePath,
|
|
152
152
|
text: 'import data from "./data.json";\nimport styles from "./styles.css";\nimport mod from "./native.node";',
|
|
153
153
|
},
|
|
154
154
|
] as any);
|
|
155
155
|
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
157
|
+
expect(written).toBe(
|
|
158
158
|
'import data from "./data.json";\nimport styles from "./styles.css";\nimport mod from "./native.node";',
|
|
159
159
|
);
|
|
160
160
|
});
|
|
161
161
|
|
|
162
162
|
it("skips writing when transformed content matches existing file", async () => {
|
|
163
|
-
|
|
163
|
+
const filePath = path.join(tmpDir, "dist", "foo.js");
|
|
164
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
165
|
+
const existing = 'import { bar } from "./bar.js";';
|
|
166
|
+
await fs.writeFile(filePath, existing);
|
|
167
|
+
const statBefore = await fs.stat(filePath);
|
|
164
168
|
|
|
169
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
165
170
|
await writeChangedOutputFiles([
|
|
166
171
|
{
|
|
167
|
-
path:
|
|
172
|
+
path: filePath,
|
|
168
173
|
text: 'import { bar } from "./bar";',
|
|
169
174
|
},
|
|
170
175
|
] as any);
|
|
171
176
|
|
|
172
|
-
|
|
177
|
+
const statAfter = await fs.stat(filePath);
|
|
178
|
+
expect(statAfter.mtimeMs).toBe(statBefore.mtimeMs);
|
|
179
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
180
|
+
expect(written).toBe(existing);
|
|
173
181
|
});
|
|
174
182
|
|
|
175
183
|
it("writes file when content changed", async () => {
|
|
176
|
-
|
|
184
|
+
const filePath = path.join(tmpDir, "dist", "foo.js");
|
|
185
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
186
|
+
await fs.writeFile(filePath, 'import { old } from "./old.js";');
|
|
177
187
|
|
|
178
188
|
await writeChangedOutputFiles([
|
|
179
189
|
{
|
|
180
|
-
path:
|
|
190
|
+
path: filePath,
|
|
181
191
|
text: 'import { bar } from "./bar";',
|
|
182
192
|
},
|
|
183
193
|
] as any);
|
|
184
194
|
|
|
185
|
-
|
|
195
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
196
|
+
expect(written).toBe('import { bar } from "./bar.js";');
|
|
186
197
|
});
|
|
187
198
|
|
|
188
199
|
it("writes new file when existing file does not exist", async () => {
|
|
189
|
-
|
|
200
|
+
const filePath = path.join(tmpDir, "dist", "foo.js");
|
|
190
201
|
|
|
191
202
|
await writeChangedOutputFiles([
|
|
192
|
-
{
|
|
193
|
-
path: "/pkg/dist/foo.js",
|
|
194
|
-
text: 'const x = 1;',
|
|
195
|
-
},
|
|
203
|
+
{ path: filePath, text: "const x = 1;" },
|
|
196
204
|
] as any);
|
|
197
205
|
|
|
198
|
-
|
|
199
|
-
expect(
|
|
206
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
207
|
+
expect(written).toBe("const x = 1;");
|
|
200
208
|
});
|
|
201
209
|
|
|
202
210
|
it("does not transform non-.js files", async () => {
|
|
203
|
-
|
|
204
|
-
|
|
211
|
+
const filePath = path.join(tmpDir, "dist", "foo.js.map");
|
|
205
212
|
const mapContent = '{"version":3,"sources":["./bar"]}';
|
|
213
|
+
|
|
206
214
|
await writeChangedOutputFiles([
|
|
207
|
-
{ path:
|
|
215
|
+
{ path: filePath, text: mapContent },
|
|
208
216
|
] as any);
|
|
209
217
|
|
|
210
|
-
|
|
218
|
+
const written = await fs.readFile(filePath, "utf8");
|
|
219
|
+
expect(written).toBe(mapContent);
|
|
211
220
|
});
|
|
212
221
|
});
|
|
213
222
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
/* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
|
|
2
2
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// eslint, jiti는 외부 npm 패키지로 ESM namespace immutable — vi.mock 유지
|
|
5
5
|
const mocks = vi.hoisted(() => ({
|
|
6
|
-
fsxExists: vi.fn<(path: string) => Promise<boolean>>(),
|
|
7
|
-
fsxGlob: vi.fn<(...args: unknown[]) => Promise<string[]>>(),
|
|
8
6
|
lintFiles: vi.fn<() => Promise<Array<{ errorCount: number; warningCount: number }>>>(),
|
|
9
7
|
loadFormatter: vi.fn(),
|
|
10
8
|
outputFixes: vi.fn(),
|
|
@@ -12,14 +10,6 @@ const mocks = vi.hoisted(() => ({
|
|
|
12
10
|
eslintCtor: vi.fn(),
|
|
13
11
|
}));
|
|
14
12
|
|
|
15
|
-
vi.mock("@simplysm/core-node", async (importOriginal) => {
|
|
16
|
-
const actual = await importOriginal<typeof import("@simplysm/core-node")>();
|
|
17
|
-
return {
|
|
18
|
-
...actual,
|
|
19
|
-
fsx: { exists: mocks.fsxExists, glob: mocks.fsxGlob },
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
13
|
vi.mock("eslint", () => ({
|
|
24
14
|
ESLint: class MockESLint {
|
|
25
15
|
constructor(options: unknown) { mocks.eslintCtor(options); }
|
|
@@ -33,7 +23,11 @@ vi.mock("jiti", () => ({
|
|
|
33
23
|
createJiti: vi.fn(() => ({ import: mocks.jitiImport })),
|
|
34
24
|
}));
|
|
35
25
|
|
|
36
|
-
|
|
26
|
+
import { fsx } from "@simplysm/core-node";
|
|
27
|
+
import { loadIgnorePatterns, executeLint } from "../../src/lint/lint-core";
|
|
28
|
+
|
|
29
|
+
const fsxExists = vi.spyOn(fsx, "exists");
|
|
30
|
+
const fsxGlob = vi.spyOn(fsx, "glob");
|
|
37
31
|
|
|
38
32
|
//#region loadIgnorePatterns
|
|
39
33
|
|
|
@@ -41,7 +35,7 @@ describe("loadIgnorePatterns", () => {
|
|
|
41
35
|
beforeEach(() => vi.clearAllMocks());
|
|
42
36
|
|
|
43
37
|
it("extracts globalIgnores patterns from eslint config", async () => {
|
|
44
|
-
|
|
38
|
+
fsxExists.mockImplementation((p) =>
|
|
45
39
|
Promise.resolve(typeof p === "string" && p.endsWith("eslint.config.ts")),
|
|
46
40
|
);
|
|
47
41
|
mocks.jitiImport.mockResolvedValue({
|
|
@@ -57,7 +51,7 @@ describe("loadIgnorePatterns", () => {
|
|
|
57
51
|
});
|
|
58
52
|
|
|
59
53
|
it("ignores config objects that have files key", async () => {
|
|
60
|
-
|
|
54
|
+
fsxExists.mockImplementation((p) =>
|
|
61
55
|
Promise.resolve(typeof p === "string" && p.endsWith("eslint.config.ts")),
|
|
62
56
|
);
|
|
63
57
|
mocks.jitiImport.mockResolvedValue({
|
|
@@ -69,7 +63,7 @@ describe("loadIgnorePatterns", () => {
|
|
|
69
63
|
});
|
|
70
64
|
|
|
71
65
|
it("throws when no eslint config file found", async () => {
|
|
72
|
-
|
|
66
|
+
fsxExists.mockResolvedValue(false);
|
|
73
67
|
|
|
74
68
|
await expect(loadIgnorePatterns("/project")).rejects.toThrow(
|
|
75
69
|
"ESLint 설정 파일",
|
|
@@ -85,11 +79,11 @@ describe("executeLint", () => {
|
|
|
85
79
|
beforeEach(() => {
|
|
86
80
|
vi.clearAllMocks();
|
|
87
81
|
// Default: eslint config exists with no ignores
|
|
88
|
-
|
|
82
|
+
fsxExists.mockImplementation((p) =>
|
|
89
83
|
Promise.resolve(typeof p === "string" && p.endsWith("eslint.config.ts")),
|
|
90
84
|
);
|
|
91
85
|
mocks.jitiImport.mockResolvedValue({ default: [] });
|
|
92
|
-
|
|
86
|
+
fsxGlob.mockResolvedValue(["/project/src/a.ts", "/project/src/b.ts"]);
|
|
93
87
|
mocks.lintFiles.mockResolvedValue([{ errorCount: 0, warningCount: 0 }]);
|
|
94
88
|
mocks.loadFormatter.mockResolvedValue({
|
|
95
89
|
format: vi.fn().mockResolvedValue(""),
|
|
@@ -106,7 +100,7 @@ describe("executeLint", () => {
|
|
|
106
100
|
|
|
107
101
|
it("filters files by targets via pathx.filterByTargets", async () => {
|
|
108
102
|
const cwd = process.cwd().replace(/\\/g, "/");
|
|
109
|
-
|
|
103
|
+
fsxGlob.mockResolvedValue([
|
|
110
104
|
`${cwd}/packages/core-common/src/a.ts`,
|
|
111
105
|
`${cwd}/packages/other/src/b.ts`,
|
|
112
106
|
]);
|
|
@@ -162,7 +156,7 @@ describe("executeLint", () => {
|
|
|
162
156
|
});
|
|
163
157
|
|
|
164
158
|
it("returns success when no files to lint", async () => {
|
|
165
|
-
|
|
159
|
+
fsxGlob.mockResolvedValue([]);
|
|
166
160
|
|
|
167
161
|
const result = await executeLint({ targets: [], fix: false, timing: false });
|
|
168
162
|
|
|
@@ -1,29 +1,22 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { Worker } from "@simplysm/core-node";
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const mocks = vi.hoisted(() => ({
|
|
6
|
-
workerCreate: vi.fn(),
|
|
4
|
+
const mocks = {
|
|
5
|
+
workerCreate: vi.spyOn(Worker, "create"),
|
|
7
6
|
lintFn: vi.fn(),
|
|
8
7
|
terminateFn: vi.fn(async () => {}),
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
vi.mock("@simplysm/core-node", () => ({
|
|
12
|
-
Worker: {
|
|
13
|
-
create: mocks.workerCreate,
|
|
14
|
-
},
|
|
15
|
-
}));
|
|
8
|
+
};
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
10
|
+
import { runLintInWorker } from "../../src/lint/lint-utils";
|
|
20
11
|
|
|
21
12
|
beforeEach(() => {
|
|
22
13
|
vi.clearAllMocks();
|
|
23
14
|
mocks.workerCreate.mockReturnValue({
|
|
24
15
|
lint: mocks.lintFn,
|
|
25
16
|
terminate: mocks.terminateFn,
|
|
26
|
-
|
|
17
|
+
on: vi.fn(),
|
|
18
|
+
off: vi.fn(),
|
|
19
|
+
} as never);
|
|
27
20
|
});
|
|
28
21
|
|
|
29
22
|
describe("runLintInWorker", () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { consola } from "consola";
|
|
2
3
|
|
|
3
|
-
//
|
|
4
|
-
|
|
4
|
+
// eslint은 외부 npm으로 ESM namespace immutable — vi.mock 유지
|
|
5
5
|
const { mockLintFiles, mockLoadFormatter, MockESLintClass } = vi.hoisted(() => {
|
|
6
6
|
const lintFilesFn = vi.fn();
|
|
7
7
|
const loadFormatterFn = vi.fn();
|
|
@@ -18,10 +18,6 @@ vi.mock("eslint", () => ({
|
|
|
18
18
|
ESLint: MockESLintClass,
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
|
-
// --- Spy consola ---
|
|
22
|
-
|
|
23
|
-
import { consola } from "consola";
|
|
24
|
-
|
|
25
21
|
const mockLintLogger = {
|
|
26
22
|
debug: vi.fn(),
|
|
27
23
|
info: vi.fn(),
|
|
@@ -31,7 +27,7 @@ const mockLintLogger = {
|
|
|
31
27
|
|
|
32
28
|
vi.spyOn(consola, "withTag").mockReturnValue(mockLintLogger as any);
|
|
33
29
|
|
|
34
|
-
|
|
30
|
+
import { LintWithProgramRunner } from "../../src/lint/lint-with-program";
|
|
35
31
|
|
|
36
32
|
// --- Helpers ---
|
|
37
33
|
|
|
@@ -1,104 +1,8 @@
|
|
|
1
|
-
import { describe, it, expect
|
|
2
|
-
import ts from "typescript";
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const mockInitialize = vi.fn().mockResolvedValue({ affectedFiles: new Set() });
|
|
7
|
-
const mockCollectDiagnostics = vi.fn().mockReturnValue([]);
|
|
8
|
-
const mockEmitAffectedFiles = vi.fn().mockReturnValue([]);
|
|
9
|
-
const mockGetTsProgram = vi.fn().mockReturnValue({
|
|
10
|
-
getSourceFiles: () => [],
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const angularCompilerConstructorSpy = vi.fn();
|
|
14
|
-
|
|
15
|
-
vi.mock("../../src/angular/angular-compiler", () => {
|
|
16
|
-
class AngularCompiler {
|
|
17
|
-
constructor(options: unknown) {
|
|
18
|
-
angularCompilerConstructorSpy(options);
|
|
19
|
-
}
|
|
20
|
-
initialize = mockInitialize;
|
|
21
|
-
*collectDiagnostics() {
|
|
22
|
-
yield* mockCollectDiagnostics();
|
|
23
|
-
}
|
|
24
|
-
*emitAffectedFiles() {
|
|
25
|
-
yield* mockEmitAffectedFiles();
|
|
26
|
-
}
|
|
27
|
-
getTsProgram = mockGetTsProgram;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
class AngularSourceFileCache extends Map<string, ts.SourceFile> {
|
|
31
|
-
readonly modifiedFiles = new Set<string>();
|
|
32
|
-
invalidate(_files: Iterable<string>): void {
|
|
33
|
-
// no-op
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
AngularCompiler,
|
|
39
|
-
AngularSourceFileCache,
|
|
40
|
-
augmentHostWithCaching: vi.fn(),
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
vi.mock("../../src/utils/tsconfig", () => ({
|
|
45
|
-
parseTsconfig: vi.fn().mockReturnValue({
|
|
46
|
-
options: {
|
|
47
|
-
target: ts.ScriptTarget.ESNext,
|
|
48
|
-
module: ts.ModuleKind.ESNext,
|
|
49
|
-
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
50
|
-
strict: false,
|
|
51
|
-
skipLibCheck: true,
|
|
52
|
-
},
|
|
53
|
-
fileNames: ["/workspace/packages/test-pkg/src/main.ts"],
|
|
54
|
-
}),
|
|
55
|
-
getPackageSourceFiles: vi
|
|
56
|
-
.fn()
|
|
57
|
-
.mockReturnValue(["/workspace/packages/test-pkg/src/main.ts"]),
|
|
58
|
-
getCompilerOptionsForEnv: vi.fn().mockImplementation((opts: ts.CompilerOptions) => opts),
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
const ngtscProgramSpy = vi.fn();
|
|
62
|
-
vi.mock("../../src/angular/angular-build", () => {
|
|
63
|
-
class NgtscProgram {
|
|
64
|
-
constructor(...args: unknown[]) {
|
|
65
|
-
ngtscProgramSpy(...args);
|
|
66
|
-
}
|
|
67
|
-
compiler = {
|
|
68
|
-
analyzeAsync: vi.fn().mockResolvedValue(undefined),
|
|
69
|
-
getDiagnosticsForFile: vi.fn().mockReturnValue([]),
|
|
70
|
-
getOptionDiagnostics: vi.fn().mockReturnValue([]),
|
|
71
|
-
getResourceDependencies: vi.fn().mockReturnValue([]),
|
|
72
|
-
ignoreForDiagnostics: new Set(),
|
|
73
|
-
ignoreForEmit: new Set(),
|
|
74
|
-
incrementalCompilation: {
|
|
75
|
-
safeToSkipEmit: vi.fn().mockReturnValue(false),
|
|
76
|
-
recordSuccessfulEmit: vi.fn(),
|
|
77
|
-
},
|
|
78
|
-
prepareEmit: vi.fn().mockReturnValue({ transformers: { before: [], after: [] } }),
|
|
79
|
-
};
|
|
80
|
-
getTsProgram() {
|
|
81
|
-
return { getSourceFiles: () => [] } as unknown as ts.Program;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return {
|
|
85
|
-
NgtscProgram,
|
|
86
|
-
OptimizeFor: { WholeProgram: 0, SingleFile: 1 },
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const {
|
|
91
|
-
createLibraryTransformStylesheet,
|
|
92
|
-
} = await import("../../src/angular/ngtsc-build-core");
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// ─── createLibraryTransformStylesheet ───
|
|
3
|
+
import { createLibraryTransformStylesheet } from "../../src/angular/ngtsc-build-core";
|
|
96
4
|
|
|
97
5
|
describe("createLibraryTransformStylesheet", () => {
|
|
98
|
-
beforeEach(() => {
|
|
99
|
-
vi.restoreAllMocks();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
6
|
it("외부 .scss 파일이면 compileScssFile로 CSS를 반환하고 의존성을 기록한다", async () => {
|
|
103
7
|
const loadPaths = ["/pkg/scss", "/cwd/node_modules"];
|
|
104
8
|
const scssErrors: string[] = [];
|
|
@@ -185,4 +89,3 @@ describe("createLibraryTransformStylesheet", () => {
|
|
|
185
89
|
expect(scssDependencies.has("/project/src/app.component.ts")).toBe(true);
|
|
186
90
|
});
|
|
187
91
|
});
|
|
188
|
-
|
|
@@ -1,28 +1,15 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
2
|
import type { SdConfig } from "../../src/sd-config.types";
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import * as sdConfigMod from "../../src/utils/sd-config";
|
|
5
|
+
import * as packageUtilsMod from "../../src/utils/package-utils";
|
|
5
6
|
|
|
6
|
-
const mocks =
|
|
7
|
-
loadSdConfig: vi.
|
|
8
|
-
validateTargets: vi.
|
|
9
|
-
}
|
|
7
|
+
const mocks = {
|
|
8
|
+
loadSdConfig: vi.spyOn(sdConfigMod, "loadSdConfig"),
|
|
9
|
+
validateTargets: vi.spyOn(packageUtilsMod, "validateTargets"),
|
|
10
|
+
};
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
loadSdConfig: mocks.loadSdConfig,
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
vi.mock("../../src/utils/package-utils", async (importOriginal) => {
|
|
16
|
-
const actual = await importOriginal<typeof import("../../src/utils/package-utils")>();
|
|
17
|
-
return {
|
|
18
|
-
...actual,
|
|
19
|
-
validateTargets: mocks.validateTargets,
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const { loadAndValidateConfig } = await import("../../src/utils/orchestrator-utils");
|
|
24
|
-
|
|
25
|
-
//#endregion
|
|
12
|
+
import { loadAndValidateConfig } from "../../src/utils/orchestrator-utils";
|
|
26
13
|
|
|
27
14
|
beforeEach(() => {
|
|
28
15
|
vi.clearAllMocks();
|
|
@@ -4,21 +4,15 @@ import type { BuildResult } from "../../src/runtime/ResultCollector";
|
|
|
4
4
|
import type { PartialMessage } from "esbuild";
|
|
5
5
|
|
|
6
6
|
// output-utils.ts가 모듈 로드 시 consola.withTag("sd:cli:output")로 로거를 생성하므로,
|
|
7
|
-
//
|
|
8
|
-
vi.
|
|
9
|
-
const mod = await importOriginal<typeof import("consola")>();
|
|
10
|
-
const orig = mod.consola;
|
|
11
|
-
vi.spyOn(orig, "withTag").mockReturnValue(orig);
|
|
12
|
-
return { consola: orig };
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const { formatBuildMessages, formatEsbuildMessages, printDiagnostics, printServers } =
|
|
16
|
-
await import("../../src/utils/output-utils");
|
|
17
|
-
|
|
7
|
+
// 동적 import 전에 spy 등록하여 withTag가 consola 자체를 반환하게 한다
|
|
8
|
+
vi.spyOn(consola, "withTag").mockReturnValue(consola);
|
|
18
9
|
vi.spyOn(consola, "error").mockImplementation(() => {});
|
|
19
10
|
vi.spyOn(consola, "warn").mockImplementation(() => {});
|
|
20
11
|
vi.spyOn(consola, "info").mockImplementation(() => {});
|
|
21
12
|
|
|
13
|
+
const { formatBuildMessages, formatEsbuildMessages, printDiagnostics, printServers } =
|
|
14
|
+
await import("../../src/utils/output-utils");
|
|
15
|
+
|
|
22
16
|
describe("formatBuildMessages", () => {
|
|
23
17
|
it("formats name, label, and messages into indented lines", () => {
|
|
24
18
|
const result = formatBuildMessages("core", "node", ["error in file.ts"]);
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { fsx } from "@simplysm/core-node";
|
|
2
3
|
|
|
3
|
-
const mockExists = vi.
|
|
4
|
+
const mockExists = vi.spyOn(fsx, "exists");
|
|
4
5
|
const mockJitiImport = vi.fn();
|
|
5
6
|
|
|
6
|
-
vi.mock
|
|
7
|
-
const actual = await importOriginal<typeof import("@simplysm/core-node")>();
|
|
8
|
-
return {
|
|
9
|
-
...actual,
|
|
10
|
-
fsx: {
|
|
11
|
-
exists: (...args: unknown[]) => mockExists(...args),
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
|
|
7
|
+
// jiti는 외부 npm으로 ESM namespace immutable이라 vi.mock 유지
|
|
16
8
|
vi.mock("jiti", () => ({
|
|
17
9
|
createJiti: () => ({
|
|
18
10
|
import: (...args: unknown[]) => mockJitiImport(...args),
|
|
19
11
|
}),
|
|
20
12
|
}));
|
|
21
13
|
|
|
22
|
-
|
|
14
|
+
import { loadSdConfig } from "../../src/utils/sd-config";
|
|
23
15
|
|
|
24
16
|
describe("loadSdConfig", () => {
|
|
25
17
|
const baseParams = { cwd: "/project", dev: true, opt: [] as string[] };
|