@simplysm/sd-cli 14.1.9 → 14.1.11
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-icon.js +2 -2
- package/dist/capacitor/capacitor-icon.js.map +1 -1
- package/dist/capacitor/capacitor-npm-config.d.ts +1 -1
- package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
- package/dist/capacitor/capacitor-npm-config.js +11 -18
- package/dist/capacitor/capacitor-npm-config.js.map +1 -1
- package/dist/capacitor/capacitor.d.ts +1 -1
- package/dist/capacitor/capacitor.js +2 -2
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +1 -0
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/device.js +2 -2
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/init/generators/root.d.ts.map +1 -1
- package/dist/commands/init/generators/root.js +0 -1
- package/dist/commands/init/generators/root.js.map +1 -1
- package/dist/commands/init/init-client.js +1 -1
- package/dist/commands/init/init-client.js.map +1 -1
- package/dist/commands/init/init.js +2 -2
- package/dist/commands/init/init.js.map +1 -1
- package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
- package/dist/commands/publish/deployment-phase.js +1 -0
- package/dist/commands/publish/deployment-phase.js.map +1 -1
- package/dist/commands/publish/npm-publisher.js +3 -3
- package/dist/commands/publish/npm-publisher.js.map +1 -1
- package/dist/commands/publish/post-publish-phase.d.ts.map +1 -1
- package/dist/commands/publish/post-publish-phase.js +1 -0
- package/dist/commands/publish/post-publish-phase.js.map +1 -1
- package/dist/commands/publish/publish-command.d.ts.map +1 -1
- package/dist/commands/publish/publish-command.js +7 -12
- package/dist/commands/publish/publish-command.js.map +1 -1
- package/dist/commands/publish/version-upgrade.d.ts.map +1 -1
- package/dist/commands/publish/version-upgrade.js +50 -0
- package/dist/commands/publish/version-upgrade.js.map +1 -1
- package/dist/deps/replace-deps/collect-deps.js +4 -4
- package/dist/deps/replace-deps/collect-deps.js.map +1 -1
- package/dist/deps/replace-deps/replace-deps-resolve.d.ts +4 -12
- package/dist/deps/replace-deps/replace-deps-resolve.d.ts.map +1 -1
- package/dist/deps/replace-deps/replace-deps-resolve.js +13 -49
- package/dist/deps/replace-deps/replace-deps-resolve.js.map +1 -1
- package/dist/deps/replace-deps/replace-deps.d.ts +2 -2
- package/dist/deps/replace-deps/replace-deps.js +3 -3
- package/dist/deps/server-externals/server-production-files.d.ts +3 -3
- package/dist/deps/server-externals/server-production-files.d.ts.map +1 -1
- package/dist/deps/server-externals/server-production-files.js +24 -17
- package/dist/deps/server-externals/server-production-files.js.map +1 -1
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +6 -11
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts +1 -0
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +2 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/esbuild/esbuild-config.d.ts +6 -2
- package/dist/esbuild/esbuild-config.d.ts.map +1 -1
- package/dist/esbuild/esbuild-config.js +4 -3
- package/dist/esbuild/esbuild-config.js.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
- package/dist/esbuild/esbuild-tsc-plugin.js +3 -1
- package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
- package/dist/orchestrators/BaseOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BaseOrchestrator.js +1 -0
- package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +3 -5
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevOrchestrator.js +1 -0
- package/dist/orchestrators/DevOrchestrator.js.map +1 -1
- package/dist/orchestrators/ServerRuntimeManager.d.ts.map +1 -1
- package/dist/orchestrators/ServerRuntimeManager.js +4 -0
- package/dist/orchestrators/ServerRuntimeManager.js.map +1 -1
- package/dist/orchestrators/TypecheckOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/TypecheckOrchestrator.js +4 -6
- package/dist/orchestrators/TypecheckOrchestrator.js.map +1 -1
- package/dist/runtime/engine-watch-events.d.ts.map +1 -1
- package/dist/runtime/engine-watch-events.js +5 -0
- package/dist/runtime/engine-watch-events.js.map +1 -1
- package/dist/runtime/worker-events.d.ts +1 -0
- package/dist/runtime/worker-events.d.ts.map +1 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +0 -4
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.js +2 -0
- package/dist/sd-cli.js.map +1 -1
- package/dist/typecheck/typecheck-non-package.d.ts.map +1 -1
- package/dist/typecheck/typecheck-non-package.js +10 -0
- package/dist/typecheck/typecheck-non-package.js.map +1 -1
- package/dist/utils/package-utils.d.ts +8 -6
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +26 -24
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/workspace-utils.d.ts +17 -0
- package/dist/utils/workspace-utils.d.ts.map +1 -0
- package/dist/utils/workspace-utils.js +95 -0
- package/dist/utils/workspace-utils.js.map +1 -0
- package/dist/workers/client.worker.d.ts +1 -0
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +8 -3
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +1 -0
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +3 -2
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts +1 -0
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +12 -12
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-esbuild-context.d.ts.map +1 -1
- package/dist/workers/server-esbuild-context.js +4 -2
- package/dist/workers/server-esbuild-context.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts +1 -0
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js +9 -3
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/dist/workers/server-watch-manager.d.ts +1 -1
- package/dist/workers/server-watch-manager.d.ts.map +1 -1
- package/dist/workers/server-watch-manager.js +2 -2
- package/dist/workers/server-watch-manager.js.map +1 -1
- package/package.json +11 -11
- package/src/capacitor/capacitor-icon.ts +2 -2
- package/src/capacitor/capacitor-npm-config.ts +10 -19
- package/src/capacitor/capacitor.ts +2 -2
- package/src/commands/check.ts +1 -0
- package/src/commands/device.ts +2 -2
- package/src/commands/init/generators/root.ts +0 -1
- package/src/commands/init/init-client.ts +1 -1
- package/src/commands/init/init.ts +2 -2
- package/src/commands/init/templates/workspace-root/mise.toml.hbs +1 -1
- package/src/commands/publish/deployment-phase.ts +1 -0
- package/src/commands/publish/npm-publisher.ts +3 -3
- package/src/commands/publish/post-publish-phase.ts +1 -0
- package/src/commands/publish/publish-command.ts +7 -15
- package/src/commands/publish/version-upgrade.ts +51 -0
- package/src/deps/replace-deps/collect-deps.ts +4 -4
- package/src/deps/replace-deps/replace-deps-resolve.ts +13 -56
- package/src/deps/replace-deps/replace-deps.ts +3 -3
- package/src/deps/server-externals/server-production-files.ts +31 -18
- package/src/electron/electron.ts +7 -13
- package/src/engines/BaseEngine.ts +3 -2
- package/src/esbuild/esbuild-config.ts +12 -3
- package/src/esbuild/esbuild-tsc-plugin.ts +4 -1
- package/src/orchestrators/BaseOrchestrator.ts +1 -0
- package/src/orchestrators/BuildOrchestrator.ts +3 -5
- package/src/orchestrators/DevOrchestrator.ts +1 -0
- package/src/orchestrators/ServerRuntimeManager.ts +4 -0
- package/src/orchestrators/TypecheckOrchestrator.ts +4 -6
- package/src/runtime/engine-watch-events.ts +7 -1
- package/src/runtime/worker-events.ts +1 -0
- package/src/sd-cli-entry.ts +0 -9
- package/src/sd-cli.ts +2 -0
- package/src/typecheck/typecheck-non-package.ts +11 -0
- package/src/utils/package-utils.ts +30 -23
- package/src/utils/workspace-utils.ts +117 -0
- package/src/workers/client.worker.ts +9 -4
- package/src/workers/library-build.worker.ts +4 -3
- package/src/workers/server-build.worker.ts +13 -13
- package/src/workers/server-esbuild-context.ts +5 -2
- package/src/workers/server-runtime.worker.ts +10 -3
- package/src/workers/server-watch-manager.ts +3 -3
- package/tests/capacitor/capacitor-build.spec.ts +142 -142
- package/tests/capacitor/capacitor-init.spec.ts +181 -181
- package/tests/capacitor/capacitor-npm-config.acc.spec.ts +114 -114
- package/tests/capacitor/capacitor-npm-config.spec.ts +94 -94
- package/tests/commands/publish-manifest.acc.spec.ts +67 -0
- package/tests/deps/replace-deps/collect-deps.acc.spec.ts +16 -1
- package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +9 -5
- package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +3 -3
- package/tests/deps/server-externals/server-production-files.spec.ts +68 -0
- package/tests/electron/electron.spec.ts +608 -608
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -1
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -1
- package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -1
- package/tests/utils/engine-watch-events.spec.ts +17 -0
- package/tests/utils/esbuild-config.spec.ts +15 -0
- package/tests/utils/package-utils.spec.ts +36 -4
- package/tests/utils/replace-deps-watch.acc.spec.ts +4 -4
- package/tests/utils/replace-deps-watch.spec.ts +3 -3
- package/tests/utils/replace-deps.spec.ts +1 -35
- package/tests/utils/workspace-utils.spec.ts +87 -0
- package/tests/workers/library-build-worker.spec.ts +1 -1
- package/tests/workers/server-esbuild-context.spec.ts +4 -3
- package/dist/commands/reinstall.d.ts +0 -13
- package/dist/commands/reinstall.d.ts.map +0 -1
- package/dist/commands/reinstall.js +0 -56
- package/dist/commands/reinstall.js.map +0 -1
- package/src/commands/init/templates/workspace-root/pnpm-workspace.yaml +0 -5
- package/src/commands/reinstall.ts +0 -63
- package/tests/angular/angular-compiler-hmr-removal.verify.md +0 -16
- package/tests/angular/onbuild-lint-removal.verify.md +0 -8
- package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +0 -13
- package/tests/angular/vite-angular-plugin-vitest.verify.md +0 -20
- package/tests/capacitor/capacitor-android-exports.verify.md +0 -11
- package/tests/commands/publish-npm-local-split.verify.md +0 -9
- package/tests/commands/publish-responsibility-split.verify.md +0 -13
- package/tests/commands/publish-set.verify.md +0 -7
- package/tests/commands/publish-storage-split.verify.md +0 -8
- package/tests/commands/slice3-severity-cleanup.verify.md +0 -12
- package/tests/deps/deps-directory-separation.verify.md +0 -15
- package/tests/deps/replace-deps/replace-deps-perf.verify.md +0 -15
- package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +0 -16
- package/tests/electron/electron-symlink-cleanup.verify.md +0 -8
- package/tests/engines/engine-duplicate-output-removal.verify.md +0 -10
- package/tests/engines/engine-typecheck-selection.verify.md +0 -8
- package/tests/engines/esbuild-client-engine.verify.md +0 -15
- package/tests/engines/normalize-result.verify.md +0 -9
- package/tests/engines/vite-dependency-cleanup.verify.md +0 -24
- package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +0 -23
- package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +0 -21
- package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +0 -16
- package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +0 -15
- package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +0 -31
- package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +0 -59
- package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +0 -21
- package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +0 -17
- package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +0 -13
- package/tests/esbuild/esbuild-worker-plugin-node.verify.md +0 -12
- package/tests/esbuild/esbuild-worker-plugin.verify.md +0 -7
- package/tests/orchestrators/dist-delete-watcher.verify.md +0 -10
- package/tests/orchestrators/orchestrator-baseenv.verify.md +0 -10
- package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +0 -10
- package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +0 -9
- package/tests/orchestrators/slice1-stdout-to-consola.verify.md +0 -10
- package/tests/sd-cli-catch-all.verify.md +0 -7
- package/tests/sd-cli-log-tag.verify.md +0 -11
- package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +0 -8
- package/tests/ts-compiler/SdTsCompiler-crash-handling.verify.md +0 -24
- package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +0 -12
- package/tests/ts-compiler/SdTsCompiler-emit.verify.md +0 -9
- package/tests/ts-compiler/SdTsCompiler.verify.md +0 -41
- package/tests/ts-compiler/scss-lint-integration.verify.md +0 -14
- package/tests/utils/copy-public-outdir.verify.md +0 -8
- package/tests/utils/dev-http-server.verify.md +0 -8
- package/tests/utils/engine-watch-events.verify.md +0 -17
- package/tests/utils/esbuild-client-config-integration.verify.md +0 -9
- package/tests/utils/esbuild-client-config-postcss.verify.md +0 -6
- package/tests/utils/esbuild-client-config.verify.md +0 -26
- package/tests/utils/esbuild-index-html.verify.md +0 -10
- package/tests/utils/esbuild-pwa.verify.md +0 -9
- package/tests/utils/esbuild-scss-plugin.verify.md +0 -8
- package/tests/utils/hmr-service.verify.md +0 -17
- package/tests/utils/lint-core-import-paths.verify.md +0 -10
- package/tests/utils/replace-deps-split.verify.md +0 -15
- package/tests/utils/replace-deps-watch.verify.md +0 -9
- package/tests/utils/server-production-files-import-paths.verify.md +0 -14
- package/tests/utils/vite-config-cleanup.verify.md +0 -7
- package/tests/workers/build-watch-paths-library.verify.md +0 -10
- package/tests/workers/build-watch-paths-ngtsc-server.verify.md +0 -12
- package/tests/workers/client-worker-browser-support.verify.md +0 -7
- package/tests/workers/client-worker-cleanup.verify.md +0 -8
- package/tests/workers/client-worker-initial-build-error.verify.md +0 -7
- package/tests/workers/client-worker-initial-build-warnings.verify.md +0 -7
- package/tests/workers/client-worker-mtime-incremental.verify.md +0 -10
- package/tests/workers/client-worker-onend-sync.verify.md +0 -7
- package/tests/workers/client-worker-refactor.verify.md +0 -22
- package/tests/workers/client-worker-ts-cache-invalidation.verify.md +0 -12
- package/tests/workers/dev-port-file.verify.md +0 -6
- package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +0 -8
- package/tests/workers/server-build-context-dispose.verify.md +0 -8
- package/tests/workers/server-build-worker-plugin.verify.md +0 -9
- package/tests/workers/server-build-worker-refactoring.verify.md +0 -14
- package/tests/workers/server-esbuild-context-integration.verify.md +0 -10
- package/tests/workers/server-esbuild-context-tsc.verify.md +0 -7
|
@@ -1,142 +1,142 @@
|
|
|
1
|
-
/* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
|
|
2
|
-
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
|
|
3
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { fsx, cpx } from "@simplysm/core-node";
|
|
7
|
-
|
|
8
|
-
// sharp는 외부 npm 네이티브 라이브러리로 이미지 처리 시간이 크고 결정적 검증에 mock 필요
|
|
9
|
-
vi.mock("sharp", () => ({
|
|
10
|
-
default: vi.fn().mockReturnValue({
|
|
11
|
-
resize: vi.fn().mockReturnThis(),
|
|
12
|
-
composite: vi.fn().mockReturnThis(),
|
|
13
|
-
png: vi.fn().mockReturnThis(),
|
|
14
|
-
toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
|
|
15
|
-
toFile: vi.fn().mockResolvedValue(undefined),
|
|
16
|
-
}),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
20
|
-
const mockFsxRead = vi.spyOn(fsx, "read");
|
|
21
|
-
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
22
|
-
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
23
|
-
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
24
|
-
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
25
|
-
vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
|
|
26
|
-
const mockFsxGlob = vi.spyOn(fsx, "glob").mockResolvedValue([]);
|
|
27
|
-
vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
|
|
28
|
-
|
|
29
|
-
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
30
|
-
vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
31
|
-
|
|
32
|
-
let tmpRoot: string;
|
|
33
|
-
let PKG_PATH: string;
|
|
34
|
-
|
|
35
|
-
beforeAll(() => {
|
|
36
|
-
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-build-"));
|
|
37
|
-
writeFileSync(path.join(tmpRoot, "
|
|
38
|
-
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
39
|
-
mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
afterAll(() => {
|
|
43
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
function setupDefaultMocks() {
|
|
47
|
-
mockFsxExists.mockResolvedValue(true);
|
|
48
|
-
|
|
49
|
-
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
50
|
-
const normalized = p.replace(/\\/g, "/");
|
|
51
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
52
|
-
return {
|
|
53
|
-
name: "com.test.app",
|
|
54
|
-
version: "1.2.3",
|
|
55
|
-
dependencies: {
|
|
56
|
-
"@capacitor/core": "^7.0.0",
|
|
57
|
-
"@capacitor/app": "^7.0.0",
|
|
58
|
-
"@capacitor/android": "^7.0.0",
|
|
59
|
-
},
|
|
60
|
-
devDependencies: {
|
|
61
|
-
"@capacitor/cli": "^7.0.0",
|
|
62
|
-
"@capacitor/assets": "^3.0.0",
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
return { name: "test-pkg", version: "1.2.3" };
|
|
67
|
-
}) as never);
|
|
68
|
-
|
|
69
|
-
mockFsxRead.mockImplementation(((p: string) => {
|
|
70
|
-
if (p.includes("AndroidManifest.xml")) {
|
|
71
|
-
return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n</application>\n</manifest>';
|
|
72
|
-
}
|
|
73
|
-
if (p.includes("build.gradle")) {
|
|
74
|
-
return `android {
|
|
75
|
-
defaultConfig {
|
|
76
|
-
versionCode 1
|
|
77
|
-
versionName "1.0"
|
|
78
|
-
minSdkVersion rootProject.ext.minSdkVersion
|
|
79
|
-
targetSdkVersion rootProject.ext.targetSdkVersion
|
|
80
|
-
}
|
|
81
|
-
buildTypes { release { } }
|
|
82
|
-
}`;
|
|
83
|
-
}
|
|
84
|
-
if (p.includes("gradle.properties")) {
|
|
85
|
-
return "org.gradle.jvmargs=-Xmx2048m";
|
|
86
|
-
}
|
|
87
|
-
return "";
|
|
88
|
-
}) as never);
|
|
89
|
-
|
|
90
|
-
mockFsxGlob.mockImplementation(((pattern: string) => {
|
|
91
|
-
if (pattern.includes("Corretto") || pattern.includes("jdk")) {
|
|
92
|
-
return ["C:/Program Files/Amazon Corretto/jdk21.0.1"];
|
|
93
|
-
}
|
|
94
|
-
return [];
|
|
95
|
-
}) as never);
|
|
96
|
-
|
|
97
|
-
process.env["ANDROID_HOME"] = "C:/Android/Sdk";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let savedEnv: Record<string, string | undefined>;
|
|
101
|
-
beforeEach(() => {
|
|
102
|
-
savedEnv = { ...process.env };
|
|
103
|
-
});
|
|
104
|
-
afterEach(() => {
|
|
105
|
-
process.env = savedEnv;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe("Capacitor 빌드", () => {
|
|
109
|
-
beforeEach(() => {
|
|
110
|
-
vi.clearAllMocks();
|
|
111
|
-
setupDefaultMocks();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
describe("서명", () => {
|
|
115
|
-
it("keystore 파일이 없으면 에러가 발생한다", async () => {
|
|
116
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
117
|
-
|
|
118
|
-
// keystore 파일만 존재하지 않도록 설정
|
|
119
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
120
|
-
if (p.includes("my-release.keystore")) return false;
|
|
121
|
-
return true;
|
|
122
|
-
}) as never);
|
|
123
|
-
|
|
124
|
-
const cap = await Capacitor.create(PKG_PATH, {
|
|
125
|
-
appId: "com.test.app",
|
|
126
|
-
appName: "Test App",
|
|
127
|
-
platform: {
|
|
128
|
-
android: {
|
|
129
|
-
sign: {
|
|
130
|
-
keystore: "my-release.keystore",
|
|
131
|
-
storePassword: "store123",
|
|
132
|
-
alias: "my-key",
|
|
133
|
-
password: "key123",
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
await expect(cap.build("/fake/out")).rejects.toThrow("keystore");
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
});
|
|
1
|
+
/* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
|
|
2
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
7
|
+
|
|
8
|
+
// sharp는 외부 npm 네이티브 라이브러리로 이미지 처리 시간이 크고 결정적 검증에 mock 필요
|
|
9
|
+
vi.mock("sharp", () => ({
|
|
10
|
+
default: vi.fn().mockReturnValue({
|
|
11
|
+
resize: vi.fn().mockReturnThis(),
|
|
12
|
+
composite: vi.fn().mockReturnThis(),
|
|
13
|
+
png: vi.fn().mockReturnThis(),
|
|
14
|
+
toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
|
|
15
|
+
toFile: vi.fn().mockResolvedValue(undefined),
|
|
16
|
+
}),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
20
|
+
const mockFsxRead = vi.spyOn(fsx, "read");
|
|
21
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
22
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
23
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
24
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
25
|
+
vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
|
|
26
|
+
const mockFsxGlob = vi.spyOn(fsx, "glob").mockResolvedValue([]);
|
|
27
|
+
vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
|
|
28
|
+
|
|
29
|
+
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
30
|
+
vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
31
|
+
|
|
32
|
+
let tmpRoot: string;
|
|
33
|
+
let PKG_PATH: string;
|
|
34
|
+
|
|
35
|
+
beforeAll(() => {
|
|
36
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-build-"));
|
|
37
|
+
writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
|
|
38
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
39
|
+
mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterAll(() => {
|
|
43
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function setupDefaultMocks() {
|
|
47
|
+
mockFsxExists.mockResolvedValue(true);
|
|
48
|
+
|
|
49
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
50
|
+
const normalized = p.replace(/\\/g, "/");
|
|
51
|
+
if (normalized.includes(".capacitor/package.json")) {
|
|
52
|
+
return {
|
|
53
|
+
name: "com.test.app",
|
|
54
|
+
version: "1.2.3",
|
|
55
|
+
dependencies: {
|
|
56
|
+
"@capacitor/core": "^7.0.0",
|
|
57
|
+
"@capacitor/app": "^7.0.0",
|
|
58
|
+
"@capacitor/android": "^7.0.0",
|
|
59
|
+
},
|
|
60
|
+
devDependencies: {
|
|
61
|
+
"@capacitor/cli": "^7.0.0",
|
|
62
|
+
"@capacitor/assets": "^3.0.0",
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return { name: "test-pkg", version: "1.2.3" };
|
|
67
|
+
}) as never);
|
|
68
|
+
|
|
69
|
+
mockFsxRead.mockImplementation(((p: string) => {
|
|
70
|
+
if (p.includes("AndroidManifest.xml")) {
|
|
71
|
+
return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n</application>\n</manifest>';
|
|
72
|
+
}
|
|
73
|
+
if (p.includes("build.gradle")) {
|
|
74
|
+
return `android {
|
|
75
|
+
defaultConfig {
|
|
76
|
+
versionCode 1
|
|
77
|
+
versionName "1.0"
|
|
78
|
+
minSdkVersion rootProject.ext.minSdkVersion
|
|
79
|
+
targetSdkVersion rootProject.ext.targetSdkVersion
|
|
80
|
+
}
|
|
81
|
+
buildTypes { release { } }
|
|
82
|
+
}`;
|
|
83
|
+
}
|
|
84
|
+
if (p.includes("gradle.properties")) {
|
|
85
|
+
return "org.gradle.jvmargs=-Xmx2048m";
|
|
86
|
+
}
|
|
87
|
+
return "";
|
|
88
|
+
}) as never);
|
|
89
|
+
|
|
90
|
+
mockFsxGlob.mockImplementation(((pattern: string) => {
|
|
91
|
+
if (pattern.includes("Corretto") || pattern.includes("jdk")) {
|
|
92
|
+
return ["C:/Program Files/Amazon Corretto/jdk21.0.1"];
|
|
93
|
+
}
|
|
94
|
+
return [];
|
|
95
|
+
}) as never);
|
|
96
|
+
|
|
97
|
+
process.env["ANDROID_HOME"] = "C:/Android/Sdk";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let savedEnv: Record<string, string | undefined>;
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
savedEnv = { ...process.env };
|
|
103
|
+
});
|
|
104
|
+
afterEach(() => {
|
|
105
|
+
process.env = savedEnv;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe("Capacitor 빌드", () => {
|
|
109
|
+
beforeEach(() => {
|
|
110
|
+
vi.clearAllMocks();
|
|
111
|
+
setupDefaultMocks();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe("서명", () => {
|
|
115
|
+
it("keystore 파일이 없으면 에러가 발생한다", async () => {
|
|
116
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
117
|
+
|
|
118
|
+
// keystore 파일만 존재하지 않도록 설정
|
|
119
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
120
|
+
if (p.includes("my-release.keystore")) return false;
|
|
121
|
+
return true;
|
|
122
|
+
}) as never);
|
|
123
|
+
|
|
124
|
+
const cap = await Capacitor.create(PKG_PATH, {
|
|
125
|
+
appId: "com.test.app",
|
|
126
|
+
appName: "Test App",
|
|
127
|
+
platform: {
|
|
128
|
+
android: {
|
|
129
|
+
sign: {
|
|
130
|
+
keystore: "my-release.keystore",
|
|
131
|
+
storePassword: "store123",
|
|
132
|
+
alias: "my-key",
|
|
133
|
+
password: "key123",
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await expect(cap.build("/fake/out")).rejects.toThrow("keystore");
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -1,181 +1,181 @@
|
|
|
1
|
-
/* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
|
|
2
|
-
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
|
|
3
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
import { fsx, cpx } from "@simplysm/core-node";
|
|
7
|
-
|
|
8
|
-
vi.mock("sharp", () => ({
|
|
9
|
-
default: vi.fn().mockReturnValue({
|
|
10
|
-
resize: vi.fn().mockReturnThis(),
|
|
11
|
-
composite: vi.fn().mockReturnThis(),
|
|
12
|
-
png: vi.fn().mockReturnThis(),
|
|
13
|
-
toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
|
|
14
|
-
toFile: vi.fn().mockResolvedValue(undefined),
|
|
15
|
-
}),
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
19
|
-
const mockFsxRead = vi.spyOn(fsx, "read");
|
|
20
|
-
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
21
|
-
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
22
|
-
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
23
|
-
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
24
|
-
vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
|
|
25
|
-
const mockFsxGlob = vi.spyOn(fsx, "glob");
|
|
26
|
-
vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
|
|
27
|
-
|
|
28
|
-
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
29
|
-
vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
30
|
-
|
|
31
|
-
let tmpRoot: string;
|
|
32
|
-
let PKG_PATH: string;
|
|
33
|
-
|
|
34
|
-
beforeAll(() => {
|
|
35
|
-
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-init-"));
|
|
36
|
-
writeFileSync(path.join(tmpRoot, "
|
|
37
|
-
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
38
|
-
// capacitor.ts가 .capacitor/.capacitor.lock 파일을 작성하므로 디렉토리 미리 생성
|
|
39
|
-
mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
afterAll(() => {
|
|
43
|
-
rmSync(tmpRoot, { recursive: true, force: true });
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
function setupDefaultMocks() {
|
|
47
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
48
|
-
if (p.includes(".capacitor.lock")) return false;
|
|
49
|
-
return true;
|
|
50
|
-
}) as never);
|
|
51
|
-
|
|
52
|
-
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
53
|
-
const normalized = p.replace(/\\/g, "/");
|
|
54
|
-
if (normalized.includes(".capacitor/package.json")) {
|
|
55
|
-
return {
|
|
56
|
-
name: "com.test.app",
|
|
57
|
-
version: "1.0.0",
|
|
58
|
-
dependencies: {
|
|
59
|
-
"@capacitor/core": "^7.0.0",
|
|
60
|
-
"@capacitor/app": "^7.0.0",
|
|
61
|
-
"@capacitor/android": "^7.0.0",
|
|
62
|
-
},
|
|
63
|
-
devDependencies: {
|
|
64
|
-
"@capacitor/cli": "^7.0.0",
|
|
65
|
-
"@capacitor/assets": "^3.0.0",
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
if (normalized.endsWith("package.json")) {
|
|
70
|
-
return { name: "test-pkg", version: "1.0.0" };
|
|
71
|
-
}
|
|
72
|
-
return {};
|
|
73
|
-
}) as never);
|
|
74
|
-
|
|
75
|
-
mockFsxRead.mockImplementation(((p: string) => {
|
|
76
|
-
if (p.includes("AndroidManifest.xml")) {
|
|
77
|
-
return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n<activity android:name=".MainActivity">\n</activity>\n</application>\n</manifest>';
|
|
78
|
-
}
|
|
79
|
-
if (p.includes("build.gradle")) {
|
|
80
|
-
return `android {
|
|
81
|
-
defaultConfig {
|
|
82
|
-
versionCode 1
|
|
83
|
-
versionName "1.0"
|
|
84
|
-
minSdkVersion rootProject.ext.minSdkVersion
|
|
85
|
-
targetSdkVersion rootProject.ext.targetSdkVersion
|
|
86
|
-
}
|
|
87
|
-
buildTypes { release { } }
|
|
88
|
-
}`;
|
|
89
|
-
}
|
|
90
|
-
if (p.includes("gradle.properties")) {
|
|
91
|
-
return "org.gradle.jvmargs=-Xmx2048m";
|
|
92
|
-
}
|
|
93
|
-
return "";
|
|
94
|
-
}) as never);
|
|
95
|
-
|
|
96
|
-
mockFsxGlob.mockResolvedValue(["C:/Program Files/Amazon Corretto/jdk21.0.1"]);
|
|
97
|
-
process.env["ANDROID_HOME"] = "C:/Android/Sdk";
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let savedEnv: Record<string, string | undefined>;
|
|
101
|
-
beforeEach(() => {
|
|
102
|
-
savedEnv = { ...process.env };
|
|
103
|
-
});
|
|
104
|
-
afterEach(() => {
|
|
105
|
-
process.env = savedEnv;
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
describe("Capacitor 설정 검증", () => {
|
|
109
|
-
beforeEach(() => {
|
|
110
|
-
vi.clearAllMocks();
|
|
111
|
-
setupDefaultMocks();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("유효한 appId를 허용한다", async () => {
|
|
115
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
116
|
-
const instance = await Capacitor.create(PKG_PATH, {
|
|
117
|
-
appId: "com.example.myapp",
|
|
118
|
-
appName: "Test App",
|
|
119
|
-
});
|
|
120
|
-
expect(instance).toBeDefined();
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("잘못된 appId (숫자 시작)를 거부한다", async () => {
|
|
124
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
125
|
-
await expect(
|
|
126
|
-
Capacitor.create(PKG_PATH, { appId: "123.app", appName: "Test" }),
|
|
127
|
-
).rejects.toThrow("appId");
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("잘못된 appId (단일 세그먼트)를 거부한다", async () => {
|
|
131
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
132
|
-
await expect(
|
|
133
|
-
Capacitor.create(PKG_PATH, { appId: "myapp", appName: "Test" }),
|
|
134
|
-
).rejects.toThrow("appId");
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("잘못된 appName (특수문자)을 거부한다", async () => {
|
|
138
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
139
|
-
await expect(
|
|
140
|
-
Capacitor.create(PKG_PATH, { appId: "com.test.app", appName: "Test@App!" }),
|
|
141
|
-
).rejects.toThrow("appName");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("한글 appName을 허용한다", async () => {
|
|
145
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
146
|
-
const instance = await Capacitor.create(PKG_PATH, {
|
|
147
|
-
appId: "com.test.app",
|
|
148
|
-
appName: "내 앱",
|
|
149
|
-
});
|
|
150
|
-
expect(instance).toBeDefined();
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
describe("Android 개발 도구 감지", () => {
|
|
155
|
-
beforeEach(() => {
|
|
156
|
-
vi.clearAllMocks();
|
|
157
|
-
setupDefaultMocks();
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
it("Android SDK 미설치 시 에러가 발생한다", async () => {
|
|
161
|
-
delete process.env["ANDROID_HOME"];
|
|
162
|
-
mockFsxExists.mockImplementation(((p: string) => {
|
|
163
|
-
const n = p.replace(/\\/g, "/");
|
|
164
|
-
if (n.includes(".capacitor.lock")) return false;
|
|
165
|
-
if (n.includes("Android/Sdk")) return false;
|
|
166
|
-
if (n.includes("Android\\Sdk")) return false;
|
|
167
|
-
if (n.includes("Program Files/Android")) return false;
|
|
168
|
-
if (n.includes("C:/Android")) return false;
|
|
169
|
-
return true;
|
|
170
|
-
}) as never);
|
|
171
|
-
|
|
172
|
-
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
173
|
-
const cap = await Capacitor.create(PKG_PATH, {
|
|
174
|
-
appId: "com.test.app",
|
|
175
|
-
appName: "Test App",
|
|
176
|
-
platform: { android: {} },
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
await expect(cap.initialize()).rejects.toThrow("Android SDK");
|
|
180
|
-
});
|
|
181
|
-
});
|
|
1
|
+
/* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
|
|
2
|
+
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fsx, cpx } from "@simplysm/core-node";
|
|
7
|
+
|
|
8
|
+
vi.mock("sharp", () => ({
|
|
9
|
+
default: vi.fn().mockReturnValue({
|
|
10
|
+
resize: vi.fn().mockReturnThis(),
|
|
11
|
+
composite: vi.fn().mockReturnThis(),
|
|
12
|
+
png: vi.fn().mockReturnThis(),
|
|
13
|
+
toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
|
|
14
|
+
toFile: vi.fn().mockResolvedValue(undefined),
|
|
15
|
+
}),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const mockFsxExists = vi.spyOn(fsx, "exists");
|
|
19
|
+
const mockFsxRead = vi.spyOn(fsx, "read");
|
|
20
|
+
vi.spyOn(fsx, "write").mockResolvedValue(undefined);
|
|
21
|
+
const mockFsxReadJson = vi.spyOn(fsx, "readJson");
|
|
22
|
+
vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
|
|
23
|
+
vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
|
|
24
|
+
vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
|
|
25
|
+
const mockFsxGlob = vi.spyOn(fsx, "glob");
|
|
26
|
+
vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
|
|
27
|
+
|
|
28
|
+
vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
29
|
+
vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
|
|
30
|
+
|
|
31
|
+
let tmpRoot: string;
|
|
32
|
+
let PKG_PATH: string;
|
|
33
|
+
|
|
34
|
+
beforeAll(() => {
|
|
35
|
+
tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-init-"));
|
|
36
|
+
writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
|
|
37
|
+
PKG_PATH = path.join(tmpRoot, "pkg");
|
|
38
|
+
// capacitor.ts가 .capacitor/.capacitor.lock 파일을 작성하므로 디렉토리 미리 생성
|
|
39
|
+
mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterAll(() => {
|
|
43
|
+
rmSync(tmpRoot, { recursive: true, force: true });
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
function setupDefaultMocks() {
|
|
47
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
48
|
+
if (p.includes(".capacitor.lock")) return false;
|
|
49
|
+
return true;
|
|
50
|
+
}) as never);
|
|
51
|
+
|
|
52
|
+
mockFsxReadJson.mockImplementation(((p: string) => {
|
|
53
|
+
const normalized = p.replace(/\\/g, "/");
|
|
54
|
+
if (normalized.includes(".capacitor/package.json")) {
|
|
55
|
+
return {
|
|
56
|
+
name: "com.test.app",
|
|
57
|
+
version: "1.0.0",
|
|
58
|
+
dependencies: {
|
|
59
|
+
"@capacitor/core": "^7.0.0",
|
|
60
|
+
"@capacitor/app": "^7.0.0",
|
|
61
|
+
"@capacitor/android": "^7.0.0",
|
|
62
|
+
},
|
|
63
|
+
devDependencies: {
|
|
64
|
+
"@capacitor/cli": "^7.0.0",
|
|
65
|
+
"@capacitor/assets": "^3.0.0",
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (normalized.endsWith("package.json")) {
|
|
70
|
+
return { name: "test-pkg", version: "1.0.0" };
|
|
71
|
+
}
|
|
72
|
+
return {};
|
|
73
|
+
}) as never);
|
|
74
|
+
|
|
75
|
+
mockFsxRead.mockImplementation(((p: string) => {
|
|
76
|
+
if (p.includes("AndroidManifest.xml")) {
|
|
77
|
+
return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n<activity android:name=".MainActivity">\n</activity>\n</application>\n</manifest>';
|
|
78
|
+
}
|
|
79
|
+
if (p.includes("build.gradle")) {
|
|
80
|
+
return `android {
|
|
81
|
+
defaultConfig {
|
|
82
|
+
versionCode 1
|
|
83
|
+
versionName "1.0"
|
|
84
|
+
minSdkVersion rootProject.ext.minSdkVersion
|
|
85
|
+
targetSdkVersion rootProject.ext.targetSdkVersion
|
|
86
|
+
}
|
|
87
|
+
buildTypes { release { } }
|
|
88
|
+
}`;
|
|
89
|
+
}
|
|
90
|
+
if (p.includes("gradle.properties")) {
|
|
91
|
+
return "org.gradle.jvmargs=-Xmx2048m";
|
|
92
|
+
}
|
|
93
|
+
return "";
|
|
94
|
+
}) as never);
|
|
95
|
+
|
|
96
|
+
mockFsxGlob.mockResolvedValue(["C:/Program Files/Amazon Corretto/jdk21.0.1"]);
|
|
97
|
+
process.env["ANDROID_HOME"] = "C:/Android/Sdk";
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let savedEnv: Record<string, string | undefined>;
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
savedEnv = { ...process.env };
|
|
103
|
+
});
|
|
104
|
+
afterEach(() => {
|
|
105
|
+
process.env = savedEnv;
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
describe("Capacitor 설정 검증", () => {
|
|
109
|
+
beforeEach(() => {
|
|
110
|
+
vi.clearAllMocks();
|
|
111
|
+
setupDefaultMocks();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("유효한 appId를 허용한다", async () => {
|
|
115
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
116
|
+
const instance = await Capacitor.create(PKG_PATH, {
|
|
117
|
+
appId: "com.example.myapp",
|
|
118
|
+
appName: "Test App",
|
|
119
|
+
});
|
|
120
|
+
expect(instance).toBeDefined();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("잘못된 appId (숫자 시작)를 거부한다", async () => {
|
|
124
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
125
|
+
await expect(
|
|
126
|
+
Capacitor.create(PKG_PATH, { appId: "123.app", appName: "Test" }),
|
|
127
|
+
).rejects.toThrow("appId");
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("잘못된 appId (단일 세그먼트)를 거부한다", async () => {
|
|
131
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
132
|
+
await expect(
|
|
133
|
+
Capacitor.create(PKG_PATH, { appId: "myapp", appName: "Test" }),
|
|
134
|
+
).rejects.toThrow("appId");
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("잘못된 appName (특수문자)을 거부한다", async () => {
|
|
138
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
139
|
+
await expect(
|
|
140
|
+
Capacitor.create(PKG_PATH, { appId: "com.test.app", appName: "Test@App!" }),
|
|
141
|
+
).rejects.toThrow("appName");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("한글 appName을 허용한다", async () => {
|
|
145
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
146
|
+
const instance = await Capacitor.create(PKG_PATH, {
|
|
147
|
+
appId: "com.test.app",
|
|
148
|
+
appName: "내 앱",
|
|
149
|
+
});
|
|
150
|
+
expect(instance).toBeDefined();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe("Android 개발 도구 감지", () => {
|
|
155
|
+
beforeEach(() => {
|
|
156
|
+
vi.clearAllMocks();
|
|
157
|
+
setupDefaultMocks();
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
it("Android SDK 미설치 시 에러가 발생한다", async () => {
|
|
161
|
+
delete process.env["ANDROID_HOME"];
|
|
162
|
+
mockFsxExists.mockImplementation(((p: string) => {
|
|
163
|
+
const n = p.replace(/\\/g, "/");
|
|
164
|
+
if (n.includes(".capacitor.lock")) return false;
|
|
165
|
+
if (n.includes("Android/Sdk")) return false;
|
|
166
|
+
if (n.includes("Android\\Sdk")) return false;
|
|
167
|
+
if (n.includes("Program Files/Android")) return false;
|
|
168
|
+
if (n.includes("C:/Android")) return false;
|
|
169
|
+
return true;
|
|
170
|
+
}) as never);
|
|
171
|
+
|
|
172
|
+
const { Capacitor } = await import("../../src/capacitor/capacitor.js");
|
|
173
|
+
const cap = await Capacitor.create(PKG_PATH, {
|
|
174
|
+
appId: "com.test.app",
|
|
175
|
+
appName: "Test App",
|
|
176
|
+
platform: { android: {} },
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await expect(cap.initialize()).rejects.toThrow("Android SDK");
|
|
180
|
+
});
|
|
181
|
+
});
|