@aigne/doc-smith 0.8.11-beta → 0.8.11-beta.2
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/.aigne/doc-smith/config.yaml +2 -0
- package/.aigne/doc-smith/output/structure-plan.json +3 -3
- package/.aigne/doc-smith/upload-cache.yaml +252 -0
- package/.github/workflows/publish-docs.yml +67 -0
- package/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +22 -0
- package/README.md +45 -115
- package/agents/clear/choose-contents.mjs +170 -0
- package/agents/clear/clear-auth-tokens.mjs +111 -0
- package/agents/clear/clear-document-config.mjs +39 -0
- package/agents/clear/clear-document-structure.mjs +106 -0
- package/agents/clear/clear-generated-docs.mjs +51 -0
- package/agents/clear/index.yaml +23 -0
- package/agents/evaluate/code-snippet.mjs +93 -0
- package/agents/evaluate/document-structure.yaml +70 -0
- package/agents/evaluate/document.yaml +79 -0
- package/agents/evaluate/generate-report.mjs +78 -0
- package/agents/evaluate/index.yaml +39 -0
- package/agents/generate/document-structure-tools/add-document.mjs +56 -0
- package/agents/generate/document-structure-tools/delete-document.mjs +49 -0
- package/agents/generate/document-structure-tools/move-document.mjs +82 -0
- package/agents/generate/document-structure-tools/update-document.mjs +50 -0
- package/agents/generate/generate-structure.yaml +1 -1
- package/agents/generate/update-document-structure.yaml +42 -0
- package/agents/generate/user-review-document-structure.mjs +6 -4
- package/agents/init/index.mjs +1 -1
- package/agents/publish/publish-docs.mjs +12 -3
- package/agents/translate/choose-language.mjs +1 -1
- package/agents/update/batch-update-document.yaml +7 -0
- package/agents/update/check-update-is-single.mjs +38 -0
- package/agents/update/document-tools/update-document-content.mjs +293 -0
- package/agents/update/index.yaml +4 -10
- package/agents/update/update-document-detail.yaml +52 -0
- package/agents/update/update-single-document.yaml +15 -0
- package/agents/update/user-review-document.mjs +248 -0
- package/agents/utils/choose-docs.mjs +4 -2
- package/agents/utils/format-document-structure.mjs +12 -2
- package/agents/utils/load-document-all-content.mjs +84 -0
- package/agents/utils/load-sources.mjs +4 -1
- package/aigne.yaml +59 -20
- package/assets/report-template/report.html +198 -0
- package/biome.json +14 -2
- package/docs/advanced-how-it-works.ja.md +101 -0
- package/docs/advanced-how-it-works.zh-TW.md +101 -0
- package/docs/advanced-how-it-works.zh.md +20 -20
- package/docs/advanced-quality-assurance.ja.md +96 -0
- package/docs/advanced-quality-assurance.zh-TW.md +96 -0
- package/docs/advanced-quality-assurance.zh.md +18 -18
- package/docs/advanced.ja.md +16 -0
- package/docs/advanced.zh-TW.md +16 -0
- package/docs/advanced.zh.md +4 -4
- package/docs/changelog.ja.md +309 -0
- package/docs/changelog.zh-TW.md +309 -0
- package/docs/changelog.zh.md +23 -23
- package/docs/cli-reference.ja.md +210 -0
- package/docs/cli-reference.zh-TW.md +210 -0
- package/docs/cli-reference.zh.md +21 -21
- package/docs/configuration-interactive-setup.ja.md +135 -0
- package/docs/configuration-interactive-setup.zh-TW.md +135 -0
- package/docs/configuration-interactive-setup.zh.md +29 -29
- package/docs/configuration-language-support.ja.md +94 -0
- package/docs/configuration-language-support.zh-TW.md +94 -0
- package/docs/configuration-language-support.zh.md +13 -13
- package/docs/configuration-llm-setup.ja.md +54 -0
- package/docs/configuration-llm-setup.zh-TW.md +54 -0
- package/docs/configuration-llm-setup.zh.md +12 -12
- package/docs/configuration-preferences.ja.md +129 -0
- package/docs/configuration-preferences.zh-TW.md +129 -0
- package/docs/configuration-preferences.zh.md +36 -36
- package/docs/configuration.ja.md +172 -0
- package/docs/configuration.zh-TW.md +172 -0
- package/docs/configuration.zh.md +49 -49
- package/docs/features-generate-documentation.ja.md +101 -0
- package/docs/features-generate-documentation.zh-TW.md +101 -0
- package/docs/features-generate-documentation.zh.md +17 -17
- package/docs/features-publish-your-docs.ja.md +107 -0
- package/docs/features-publish-your-docs.zh-TW.md +107 -0
- package/docs/features-publish-your-docs.zh.md +22 -22
- package/docs/features-translate-documentation.ja.md +79 -0
- package/docs/features-translate-documentation.zh-TW.md +79 -0
- package/docs/features-translate-documentation.zh.md +12 -12
- package/docs/features-update-and-refine.ja.md +138 -0
- package/docs/features-update-and-refine.zh-TW.md +138 -0
- package/docs/features-update-and-refine.zh.md +21 -21
- package/docs/features.ja.md +52 -0
- package/docs/features.zh-TW.md +52 -0
- package/docs/features.zh.md +8 -8
- package/docs/getting-started.ja.md +123 -0
- package/docs/getting-started.zh-TW.md +123 -0
- package/docs/getting-started.zh.md +24 -24
- package/docs/overview.ja.md +30 -0
- package/docs/overview.zh-TW.md +30 -0
- package/docs/overview.zh.md +8 -8
- package/package.json +19 -11
- package/prompts/common/document/content-rules-core.md +19 -0
- package/prompts/common/document/media-handling-rules.md +9 -0
- package/prompts/common/document/role-and-personality.md +15 -0
- package/prompts/common/document/user-preferences.md +9 -0
- package/prompts/common/document-structure/conflict-resolution-guidance.md +16 -0
- package/prompts/common/document-structure/document-structure-rules.md +45 -0
- package/prompts/common/document-structure/glossary.md +7 -0
- package/prompts/common/document-structure/intj-traits.md +5 -0
- package/prompts/common/document-structure/output-constraints.md +9 -0
- package/prompts/common/document-structure/user-locale-rules.md +10 -0
- package/prompts/common/document-structure/user-preferences.md +9 -0
- package/prompts/detail/custom/custom-components.md +9 -1
- package/prompts/detail/document-rules.md +6 -6
- package/prompts/detail/generate-document.md +5 -45
- package/prompts/detail/update-document.md +145 -0
- package/prompts/evaluate/document-structure.md +94 -0
- package/prompts/evaluate/document.md +149 -0
- package/prompts/structure/document-rules.md +1 -1
- package/prompts/structure/generate-structure-system.md +74 -0
- package/prompts/structure/generate-structure-user.md +41 -0
- package/prompts/structure/update-document-structure.md +118 -0
- package/prompts/translate/translate-document.md +1 -1
- package/prompts/utils/feedback-refiner.md +3 -3
- package/release-please-config.json +1 -7
- package/tests/agents/clear/choose-contents.test.mjs +280 -0
- package/tests/agents/clear/clear-auth-tokens.test.mjs +268 -0
- package/tests/agents/clear/clear-document-config.test.mjs +167 -0
- package/tests/agents/clear/clear-document-structure.test.mjs +374 -0
- package/tests/agents/clear/clear-generated-docs.test.mjs +222 -0
- package/tests/agents/evaluate/code-snippet.test.mjs +163 -0
- package/tests/agents/evaluate/fixtures/api-services.md +87 -0
- package/tests/agents/evaluate/fixtures/js-sdk.md +94 -0
- package/tests/agents/evaluate/generate-report.test.mjs +312 -0
- package/tests/agents/generate/check-document-structure.test.mjs +0 -6
- package/tests/agents/generate/document-structure-tools/add-document.test.mjs +449 -0
- package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +410 -0
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +476 -0
- package/tests/agents/generate/document-structure-tools/update-document.test.mjs +548 -0
- package/tests/agents/generate/generate-structure.test.mjs +0 -6
- package/tests/agents/generate/user-review-document-structure.test.mjs +9 -9
- package/tests/agents/publish/publish-docs.test.mjs +2 -2
- package/tests/agents/update/check-update-is-single.test.mjs +300 -0
- package/tests/agents/update/document-tools/update-document-content.test.mjs +326 -0
- package/tests/agents/update/user-review-document.test.mjs +561 -0
- package/tests/agents/utils/format-document-structure.test.mjs +100 -0
- package/tests/utils/auth-utils.test.mjs +239 -1
- package/tests/utils/blocklet.test.mjs +9 -7
- package/tests/utils/constants.test.mjs +1 -1
- package/tests/utils/d2-utils.test.mjs +1 -1
- package/tests/utils/deploy.test.mjs +310 -366
- package/tests/utils/kroki-utils.test.mjs +2 -15
- package/tests/utils/linter/fixtures/css/keyword-error.css +1 -0
- package/tests/utils/linter/fixtures/css/missing-semicolon.css +1 -0
- package/tests/utils/linter/fixtures/css/syntax-error.css +1 -0
- package/tests/utils/linter/fixtures/css/undeclare-variable.css +1 -0
- package/tests/utils/linter/fixtures/css/unused-variable.css +2 -0
- package/tests/utils/linter/fixtures/css/valid-code.css +1 -0
- package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +2 -0
- package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +2 -0
- package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +1 -0
- package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +2 -0
- package/tests/utils/linter/fixtures/go/keyword-error.go +5 -0
- package/tests/utils/linter/fixtures/go/missing-semicolon.go +5 -0
- package/tests/utils/linter/fixtures/go/syntax-error.go +6 -0
- package/tests/utils/linter/fixtures/go/undeclare-variable.go +5 -0
- package/tests/utils/linter/fixtures/go/unused-variable.go +5 -0
- package/tests/utils/linter/fixtures/go/valid-code.go +7 -0
- package/tests/utils/linter/fixtures/js/keyword-error.js +3 -0
- package/tests/utils/linter/fixtures/js/missing-semicolon.js +6 -0
- package/tests/utils/linter/fixtures/js/syntax-error.js +4 -0
- package/tests/utils/linter/fixtures/js/undeclare-variable.js +3 -0
- package/tests/utils/linter/fixtures/js/unused-variable.js +7 -0
- package/tests/utils/linter/fixtures/js/valid-code.js +15 -0
- package/tests/utils/linter/fixtures/json/keyword-error.json +1 -0
- package/tests/utils/linter/fixtures/json/missing-semicolon.json +1 -0
- package/tests/utils/linter/fixtures/json/syntax-error.json +1 -0
- package/tests/utils/linter/fixtures/json/undeclare-variable.json +1 -0
- package/tests/utils/linter/fixtures/json/unused-variable.json +1 -0
- package/tests/utils/linter/fixtures/json/valid-code.json +1 -0
- package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +5 -0
- package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +4 -0
- package/tests/utils/linter/fixtures/jsx/valid-code.jsx +5 -0
- package/tests/utils/linter/fixtures/python/keyword-error.py +3 -0
- package/tests/utils/linter/fixtures/python/missing-semicolon.py +2 -0
- package/tests/utils/linter/fixtures/python/syntax-error.py +3 -0
- package/tests/utils/linter/fixtures/python/undeclare-variable.py +3 -0
- package/tests/utils/linter/fixtures/python/unused-variable.py +6 -0
- package/tests/utils/linter/fixtures/python/valid-code.py +12 -0
- package/tests/utils/linter/fixtures/ruby/keyword-error.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +1 -0
- package/tests/utils/linter/fixtures/ruby/syntax-error.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +1 -0
- package/tests/utils/linter/fixtures/ruby/unused-variable.rb +2 -0
- package/tests/utils/linter/fixtures/ruby/valid-code.rb +1 -0
- package/tests/utils/linter/fixtures/sass/keyword-error.sass +2 -0
- package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +3 -0
- package/tests/utils/linter/fixtures/sass/syntax-error.sass +3 -0
- package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +2 -0
- package/tests/utils/linter/fixtures/sass/unused-variable.sass +4 -0
- package/tests/utils/linter/fixtures/sass/valid-code.sass +2 -0
- package/tests/utils/linter/fixtures/scss/keyword-error.scss +1 -0
- package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +1 -0
- package/tests/utils/linter/fixtures/scss/syntax-error.scss +1 -0
- package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +1 -0
- package/tests/utils/linter/fixtures/scss/unused-variable.scss +2 -0
- package/tests/utils/linter/fixtures/scss/valid-code.scss +1 -0
- package/tests/utils/linter/fixtures/shell/keyword-error.sh +5 -0
- package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +3 -0
- package/tests/utils/linter/fixtures/shell/syntax-error.sh +4 -0
- package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +3 -0
- package/tests/utils/linter/fixtures/shell/unused-variable.sh +4 -0
- package/tests/utils/linter/fixtures/shell/valid-code.sh +3 -0
- package/tests/utils/linter/fixtures/ts/keyword-error.ts +1 -0
- package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +1 -0
- package/tests/utils/linter/fixtures/ts/syntax-error.ts +1 -0
- package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +1 -0
- package/tests/utils/linter/fixtures/ts/unused-variable.ts +3 -0
- package/tests/utils/linter/fixtures/ts/valid-code.ts +3 -0
- package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +5 -0
- package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +6 -0
- package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +6 -0
- package/tests/utils/linter/fixtures/tsx/valid-code.tsx +5 -0
- package/tests/utils/linter/fixtures/vue/keyword-error.vue +6 -0
- package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +6 -0
- package/tests/utils/linter/fixtures/vue/syntax-error.vue +6 -0
- package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +6 -0
- package/tests/utils/linter/fixtures/vue/unused-variable.vue +7 -0
- package/tests/utils/linter/fixtures/vue/valid-code.vue +6 -0
- package/tests/utils/linter/fixtures/yaml/keyword-error.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +2 -0
- package/tests/utils/linter/fixtures/yaml/syntax-error.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +1 -0
- package/tests/utils/linter/fixtures/yaml/unused-variable.yml +2 -0
- package/tests/utils/linter/fixtures/yaml/valid-code.yml +3 -0
- package/tests/utils/linter/index.test.mjs +440 -0
- package/tests/utils/linter/scan-results.mjs +42 -0
- package/tests/utils/markdown/index.test.mjs +478 -0
- package/tests/utils/mermaid-validator.test.mjs +2 -2
- package/tests/utils/utils.test.mjs +3 -1
- package/types/document-schema.mjs +54 -0
- package/types/document-structure-schema.mjs +244 -0
- package/utils/auth-utils.mjs +131 -6
- package/utils/conflict-detector.mjs +5 -1
- package/utils/{constants.mjs → constants/index.mjs} +109 -0
- package/utils/constants/linter.mjs +102 -0
- package/utils/d2-utils.mjs +2 -4
- package/utils/debug.mjs +3 -0
- package/utils/deploy.mjs +81 -385
- package/utils/evaluate/report-utils.mjs +131 -0
- package/utils/file-utils.mjs +36 -1
- package/utils/kroki-utils.mjs +1 -1
- package/utils/linter/index.mjs +50 -0
- package/utils/markdown/index.mjs +26 -0
- package/utils/markdown-checker.mjs +1 -1
- package/utils/utils.mjs +19 -7
- package/prompts/structure/generate-structure.md +0 -161
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
|
|
2
2
|
import * as openModule from "open";
|
|
3
|
-
import * as
|
|
3
|
+
import * as authUtilsModule from "../../utils/auth-utils.mjs";
|
|
4
4
|
|
|
5
|
-
// Import the
|
|
5
|
+
// Import the deploy function
|
|
6
6
|
import { deploy } from "../../utils/deploy.mjs";
|
|
7
|
-
import * as
|
|
7
|
+
import * as utilsModule from "../../utils/utils.mjs";
|
|
8
|
+
|
|
9
|
+
const TEST_HOME_URL = "https_home_test_url";
|
|
10
|
+
const TEST_APP_URL = "https_app_test_url";
|
|
11
|
+
const TEST_DASHBOARD_URL = "https_dashboard_test_url";
|
|
12
|
+
const TEST_SUBSCRIPTION_URL = "https_subscription_test_url";
|
|
13
|
+
|
|
14
|
+
// Mock BrokerClient
|
|
15
|
+
const mockBrokerClient = {
|
|
16
|
+
deploy: mock(),
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const mockBrokerClientConstructor = mock(() => mockBrokerClient);
|
|
20
|
+
|
|
21
|
+
// Mock the payment broker client module
|
|
22
|
+
mock.module("@blocklet/payment-broker-client/node", () => ({
|
|
23
|
+
BrokerClient: mockBrokerClientConstructor,
|
|
24
|
+
STEPS: {
|
|
25
|
+
PAYMENT_PENDING: "PAYMENT_PENDING",
|
|
26
|
+
INSTALLATION_STARTING: "INSTALLATION_STARTING",
|
|
27
|
+
SERVICE_STARTING: "SERVICE_STARTING",
|
|
28
|
+
ACCESS_PREPARING: "ACCESS_PREPARING",
|
|
29
|
+
ACCESS_READY: "ACCESS_READY",
|
|
30
|
+
},
|
|
31
|
+
}));
|
|
8
32
|
|
|
9
33
|
describe("deploy", () => {
|
|
10
|
-
let originalFetch;
|
|
11
34
|
let originalConsole;
|
|
12
35
|
let consoleOutput;
|
|
36
|
+
let getOfficialAccessTokenSpy;
|
|
13
37
|
let saveValueToConfigSpy;
|
|
14
|
-
let originalSetTimeout;
|
|
15
|
-
let getComponentInfoWithMountPointSpy;
|
|
16
|
-
let getComponentInfoSpy;
|
|
17
38
|
let openDefaultSpy;
|
|
18
39
|
|
|
19
|
-
beforeEach(
|
|
20
|
-
//
|
|
21
|
-
process.env.DOC_SMITH_BASE_URL = "https://test.example.com";
|
|
22
|
-
process.env.NODE_ENV = "test";
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
// Note: DOC_SMITH_BASE_URL is not set, so BASE_URL will be empty string
|
|
23
42
|
|
|
24
43
|
// Mock console to capture output
|
|
25
44
|
consoleOutput = [];
|
|
@@ -30,433 +49,358 @@ describe("deploy", () => {
|
|
|
30
49
|
console.log = (...args) => consoleOutput.push({ type: "log", args });
|
|
31
50
|
console.error = (...args) => consoleOutput.push({ type: "error", args });
|
|
32
51
|
|
|
33
|
-
// Mock
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Mock fetch
|
|
41
|
-
originalFetch = global.fetch;
|
|
42
|
-
|
|
43
|
-
// Use spyOn to mock saveValueToConfig without affecting other tests
|
|
44
|
-
saveValueToConfigSpy = spyOn(utils, "saveValueToConfig").mockResolvedValue();
|
|
45
|
-
|
|
46
|
-
// Spy on blocklet module functions
|
|
47
|
-
getComponentInfoWithMountPointSpy = spyOn(
|
|
48
|
-
blockletModule,
|
|
49
|
-
"getComponentInfoWithMountPoint",
|
|
50
|
-
).mockResolvedValue({
|
|
51
|
-
mountPoint: "/payment",
|
|
52
|
-
PAYMENT_LINK_ID: "test-payment-id",
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
getComponentInfoSpy = spyOn(blockletModule, "getComponentInfo").mockResolvedValue({
|
|
56
|
-
status: "running",
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// Spy on open module
|
|
52
|
+
// Mock dependencies
|
|
53
|
+
getOfficialAccessTokenSpy = spyOn(authUtilsModule, "getOfficialAccessToken").mockResolvedValue(
|
|
54
|
+
"mock-auth-token",
|
|
55
|
+
);
|
|
56
|
+
saveValueToConfigSpy = spyOn(utilsModule, "saveValueToConfig").mockResolvedValue();
|
|
60
57
|
openDefaultSpy = spyOn(openModule, "default").mockResolvedValue();
|
|
58
|
+
|
|
59
|
+
// Reset mocks
|
|
60
|
+
mockBrokerClientConstructor.mockClear();
|
|
61
|
+
mockBrokerClient.deploy.mockClear();
|
|
61
62
|
});
|
|
62
63
|
|
|
63
64
|
afterEach(() => {
|
|
64
|
-
// Restore
|
|
65
|
-
global.fetch = originalFetch;
|
|
66
|
-
global.setTimeout = originalSetTimeout;
|
|
65
|
+
// Restore console
|
|
67
66
|
console.log = originalConsole.log;
|
|
68
67
|
console.error = originalConsole.error;
|
|
69
68
|
|
|
70
69
|
// Restore all spies
|
|
70
|
+
getOfficialAccessTokenSpy?.mockRestore();
|
|
71
71
|
saveValueToConfigSpy?.mockRestore();
|
|
72
|
-
getComponentInfoWithMountPointSpy?.mockRestore();
|
|
73
|
-
getComponentInfoSpy?.mockRestore();
|
|
74
72
|
openDefaultSpy?.mockRestore();
|
|
75
73
|
|
|
76
|
-
//
|
|
74
|
+
// Clean up environment
|
|
77
75
|
delete process.env.NODE_ENV;
|
|
78
76
|
});
|
|
79
77
|
|
|
80
78
|
test("successful deployment flow", async () => {
|
|
81
|
-
// Mock
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ok: true,
|
|
90
|
-
status: 200,
|
|
91
|
-
json: async () => ({
|
|
92
|
-
checkoutSession: { id: "checkout-123" },
|
|
93
|
-
paymentUrl: "https://payment.test/checkout-123",
|
|
94
|
-
}),
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Step 2-4: Poll payment/installation/service status
|
|
99
|
-
if (url.includes("/api/vendors/order/checkout-123/status")) {
|
|
100
|
-
if (callCount <= 2) {
|
|
101
|
-
// First call: payment completed, installation in progress
|
|
102
|
-
return {
|
|
103
|
-
ok: true,
|
|
104
|
-
status: 200,
|
|
105
|
-
json: async () => ({
|
|
106
|
-
payment_status: "paid",
|
|
107
|
-
vendors: [{ id: "vendor-1", progress: 50, appUrl: null }],
|
|
108
|
-
}),
|
|
109
|
-
};
|
|
110
|
-
} else {
|
|
111
|
-
// Subsequent calls: installation complete
|
|
112
|
-
return {
|
|
113
|
-
ok: true,
|
|
114
|
-
status: 200,
|
|
115
|
-
json: async () => ({
|
|
116
|
-
payment_status: "paid",
|
|
117
|
-
vendors: [{ id: "vendor-1", progress: 100, appUrl: "https://app.test" }],
|
|
118
|
-
}),
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Step 5: Get order details
|
|
124
|
-
if (url.includes("/api/vendors/order/checkout-123/detail")) {
|
|
125
|
-
return {
|
|
126
|
-
ok: true,
|
|
127
|
-
status: 200,
|
|
128
|
-
json: async () => ({
|
|
129
|
-
vendors: [
|
|
130
|
-
{
|
|
131
|
-
appUrl: "https://app.test",
|
|
132
|
-
dashboardUrl: "https://dashboard.test",
|
|
133
|
-
homeUrl: "https://home.test",
|
|
134
|
-
token: "auth-token-123",
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
}),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
79
|
+
// Mock successful deployment result
|
|
80
|
+
const mockResult = {
|
|
81
|
+
appUrl: TEST_APP_URL,
|
|
82
|
+
homeUrl: TEST_HOME_URL,
|
|
83
|
+
dashboardUrl: TEST_DASHBOARD_URL,
|
|
84
|
+
subscriptionUrl: TEST_SUBSCRIPTION_URL,
|
|
85
|
+
vendors: [{ token: "auth-token-123" }],
|
|
86
|
+
};
|
|
140
87
|
|
|
141
|
-
|
|
142
|
-
});
|
|
88
|
+
mockBrokerClient.deploy.mockResolvedValue(mockResult);
|
|
143
89
|
|
|
144
90
|
const result = await deploy();
|
|
145
91
|
|
|
146
|
-
// Verify
|
|
92
|
+
// Verify BrokerClient was constructed with correct config
|
|
93
|
+
expect(mockBrokerClientConstructor).toHaveBeenCalledWith({
|
|
94
|
+
baseUrl: "",
|
|
95
|
+
authToken: "mock-auth-token",
|
|
96
|
+
paymentLinkKey: "PAYMENT_LINK_ID",
|
|
97
|
+
timeout: 300000,
|
|
98
|
+
polling: {
|
|
99
|
+
interval: 3000,
|
|
100
|
+
maxAttempts: 100,
|
|
101
|
+
backoffStrategy: "linear",
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Verify deploy was called with correct parameters
|
|
106
|
+
expect(mockBrokerClient.deploy).toHaveBeenCalledWith(
|
|
107
|
+
expect.objectContaining({
|
|
108
|
+
cachedCheckoutId: undefined,
|
|
109
|
+
cachedPaymentUrl: undefined,
|
|
110
|
+
pageInfo: expect.objectContaining({
|
|
111
|
+
successMessage: expect.objectContaining({
|
|
112
|
+
en: expect.stringContaining("Congratulations"),
|
|
113
|
+
zh: expect.stringContaining("恭喜您"),
|
|
114
|
+
}),
|
|
115
|
+
}),
|
|
116
|
+
hooks: expect.objectContaining({
|
|
117
|
+
PAYMENT_PENDING: expect.any(Function),
|
|
118
|
+
INSTALLATION_STARTING: expect.any(Function),
|
|
119
|
+
SERVICE_STARTING: expect.any(Function),
|
|
120
|
+
ACCESS_PREPARING: expect.any(Function),
|
|
121
|
+
ACCESS_READY: expect.any(Function),
|
|
122
|
+
}),
|
|
123
|
+
onError: expect.any(Function),
|
|
124
|
+
}),
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Verify result transformation
|
|
147
128
|
expect(result).toEqual({
|
|
148
|
-
appUrl:
|
|
149
|
-
homeUrl:
|
|
129
|
+
appUrl: TEST_APP_URL,
|
|
130
|
+
homeUrl: TEST_HOME_URL,
|
|
131
|
+
dashboardUrl: TEST_DASHBOARD_URL,
|
|
132
|
+
subscriptionUrl: TEST_SUBSCRIPTION_URL,
|
|
150
133
|
token: "auth-token-123",
|
|
151
134
|
});
|
|
152
135
|
|
|
153
|
-
// Verify
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
136
|
+
// Verify console output
|
|
137
|
+
const logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
138
|
+
expect(logs.some((log) => log.includes("🚀 Starting deployment..."))).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("successful deployment with cached parameters", async () => {
|
|
142
|
+
const mockResult = {
|
|
143
|
+
appUrl: TEST_APP_URL,
|
|
144
|
+
homeUrl: TEST_HOME_URL,
|
|
145
|
+
vendors: [{ token: "auth-token-123" }],
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
mockBrokerClient.deploy.mockResolvedValue(mockResult);
|
|
149
|
+
|
|
150
|
+
const result = await deploy("cached-checkout-id", "https://cached-payment.url");
|
|
151
|
+
|
|
152
|
+
// Verify deploy was called with cached parameters
|
|
153
|
+
expect(mockBrokerClient.deploy).toHaveBeenCalledWith(
|
|
154
|
+
expect.objectContaining({
|
|
155
|
+
cachedCheckoutId: "cached-checkout-id",
|
|
156
|
+
cachedPaymentUrl: "https://cached-payment.url",
|
|
157
|
+
}),
|
|
163
158
|
);
|
|
164
159
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
expect(logs.some((log) => log.includes("Step 1/4: Waiting for payment"))).toBe(true);
|
|
168
|
-
expect(logs.some((log) => log.includes("Step 2/4: Installing Website"))).toBe(true);
|
|
169
|
-
expect(logs.some((log) => log.includes("Step 3/4: Starting Website"))).toBe(true);
|
|
170
|
-
expect(logs.some((log) => log.includes("Step 4/4: Getting Website URL"))).toBe(true);
|
|
171
|
-
expect(logs.some((log) => log.includes("Your website is available at"))).toBe(true);
|
|
160
|
+
expect(result.appUrl).toBe(TEST_APP_URL);
|
|
161
|
+
expect(result.token).toBe("auth-token-123");
|
|
172
162
|
});
|
|
173
163
|
|
|
174
|
-
test("
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
callCount++;
|
|
179
|
-
|
|
180
|
-
// Step 1: Create payment session
|
|
181
|
-
if (url.includes("/api/checkout-sessions/start")) {
|
|
182
|
-
return {
|
|
183
|
-
ok: true,
|
|
184
|
-
status: 200,
|
|
185
|
-
json: async () => ({
|
|
186
|
-
checkoutSession: { id: "checkout-123" },
|
|
187
|
-
paymentUrl: "https://payment.test/checkout-123",
|
|
188
|
-
}),
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Step 2-4: Poll payment/installation/service status
|
|
193
|
-
if (url.includes("/api/vendors/order/checkout-123/status")) {
|
|
194
|
-
if (callCount <= 2) {
|
|
195
|
-
// First call: payment completed, installation in progress
|
|
196
|
-
return {
|
|
197
|
-
ok: true,
|
|
198
|
-
status: 200,
|
|
199
|
-
json: async () => ({
|
|
200
|
-
payment_status: "paid",
|
|
201
|
-
vendors: [{ id: "vendor-1", progress: 50, appUrl: null }],
|
|
202
|
-
}),
|
|
203
|
-
};
|
|
204
|
-
} else {
|
|
205
|
-
// Subsequent calls: installation complete
|
|
206
|
-
return {
|
|
207
|
-
ok: true,
|
|
208
|
-
status: 200,
|
|
209
|
-
json: async () => ({
|
|
210
|
-
payment_status: "paid",
|
|
211
|
-
vendors: [{ id: "vendor-1", progress: 100, appUrl: "https://app.test" }],
|
|
212
|
-
}),
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Step 5: Get order details
|
|
218
|
-
if (url.includes("/api/vendors/order/checkout-123/detail")) {
|
|
219
|
-
return {
|
|
220
|
-
ok: true,
|
|
221
|
-
status: 200,
|
|
222
|
-
json: async () => ({
|
|
223
|
-
vendors: [
|
|
224
|
-
{
|
|
225
|
-
appUrl: "https://app.test",
|
|
226
|
-
dashboardUrl: "https://dashboard.test",
|
|
227
|
-
homeUrl: "https://home.test",
|
|
228
|
-
token: "auth-token-123",
|
|
229
|
-
},
|
|
230
|
-
],
|
|
231
|
-
subscriptionUrl: "https://subscription.test",
|
|
232
|
-
}),
|
|
233
|
-
};
|
|
234
|
-
}
|
|
164
|
+
test("handles missing auth token", async () => {
|
|
165
|
+
getOfficialAccessTokenSpy.mockResolvedValue(null);
|
|
166
|
+
|
|
167
|
+
await expect(deploy()).rejects.toThrow("Failed to get official access token");
|
|
235
168
|
|
|
236
|
-
|
|
169
|
+
// Verify BrokerClient was not created
|
|
170
|
+
expect(mockBrokerClientConstructor).not.toHaveBeenCalled();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
test("handles BrokerClient deployment failure", async () => {
|
|
174
|
+
const deployError = new Error("Deployment failed");
|
|
175
|
+
mockBrokerClient.deploy.mockRejectedValue(deployError);
|
|
176
|
+
|
|
177
|
+
await expect(deploy()).rejects.toThrow("Deployment failed");
|
|
178
|
+
|
|
179
|
+
// Verify BrokerClient was created and deploy was called
|
|
180
|
+
expect(mockBrokerClientConstructor).toHaveBeenCalled();
|
|
181
|
+
expect(mockBrokerClient.deploy).toHaveBeenCalled();
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("PAYMENT_PENDING hook functionality", async () => {
|
|
185
|
+
let paymentPendingHook;
|
|
186
|
+
|
|
187
|
+
mockBrokerClient.deploy.mockImplementation(async (config) => {
|
|
188
|
+
paymentPendingHook = config.hooks.PAYMENT_PENDING;
|
|
189
|
+
return {
|
|
190
|
+
appUrl: TEST_APP_URL,
|
|
191
|
+
vendors: [{ token: "test-token" }],
|
|
192
|
+
};
|
|
237
193
|
});
|
|
238
194
|
|
|
239
|
-
|
|
195
|
+
await deploy();
|
|
240
196
|
|
|
241
|
-
//
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
197
|
+
// Test the PAYMENT_PENDING hook
|
|
198
|
+
await paymentPendingHook({
|
|
199
|
+
sessionId: "session-123",
|
|
200
|
+
paymentUrl: "https://payment.test/session-123",
|
|
201
|
+
isResuming: false,
|
|
246
202
|
});
|
|
247
203
|
|
|
248
204
|
// Verify saveValueToConfig was called
|
|
249
205
|
expect(saveValueToConfigSpy).toHaveBeenCalledWith(
|
|
250
206
|
"checkoutId",
|
|
251
|
-
"
|
|
207
|
+
"session-123",
|
|
252
208
|
"Checkout ID for document deployment website",
|
|
253
209
|
);
|
|
254
210
|
expect(saveValueToConfigSpy).toHaveBeenCalledWith(
|
|
255
211
|
"paymentUrl",
|
|
256
|
-
|
|
212
|
+
"https://payment.test/session-123",
|
|
257
213
|
"Payment URL for document deployment website",
|
|
258
214
|
);
|
|
259
215
|
|
|
260
|
-
// Verify
|
|
261
|
-
|
|
216
|
+
// Verify browser was opened
|
|
217
|
+
expect(openDefaultSpy).toHaveBeenCalledWith("https://payment.test/session-123");
|
|
262
218
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
expect(logs.some((log) => log.includes("Step
|
|
266
|
-
expect(logs.some((log) => log.includes("
|
|
267
|
-
expect(logs.some((log) => log.includes("Your website is available at"))).toBe(true);
|
|
268
|
-
expect(logs.some((log) => log.includes("Your subscription management URL"))).toBe(true);
|
|
219
|
+
// Verify console output
|
|
220
|
+
const logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
221
|
+
expect(logs.some((log) => log.includes("⏳ Step 1/4: Waiting for payment..."))).toBe(true);
|
|
222
|
+
expect(logs.some((log) => log.includes("🔗 Payment link:"))).toBe(true);
|
|
269
223
|
});
|
|
270
224
|
|
|
271
|
-
test("
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
225
|
+
test("PAYMENT_PENDING hook with isResuming=true", async () => {
|
|
226
|
+
let paymentPendingHook;
|
|
227
|
+
|
|
228
|
+
mockBrokerClient.deploy.mockImplementation(async (config) => {
|
|
229
|
+
paymentPendingHook = config.hooks.PAYMENT_PENDING;
|
|
230
|
+
return {
|
|
231
|
+
appUrl: TEST_APP_URL,
|
|
232
|
+
vendors: [{ token: "test-token" }],
|
|
233
|
+
};
|
|
275
234
|
});
|
|
276
235
|
|
|
277
|
-
await
|
|
278
|
-
});
|
|
236
|
+
await deploy();
|
|
279
237
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
status: 400,
|
|
286
|
-
json: async () => ({ error: "Payment creation failed" }),
|
|
287
|
-
};
|
|
288
|
-
}
|
|
238
|
+
// Test the PAYMENT_PENDING hook with isResuming=true
|
|
239
|
+
await paymentPendingHook({
|
|
240
|
+
sessionId: "session-123",
|
|
241
|
+
paymentUrl: "https://payment.test/session-123",
|
|
242
|
+
isResuming: true,
|
|
289
243
|
});
|
|
290
244
|
|
|
291
|
-
|
|
245
|
+
// Verify browser was NOT opened when resuming
|
|
246
|
+
expect(openDefaultSpy).not.toHaveBeenCalled();
|
|
292
247
|
|
|
293
|
-
|
|
294
|
-
expect(
|
|
248
|
+
// But saveValueToConfig should still be called
|
|
249
|
+
expect(saveValueToConfigSpy).toHaveBeenCalledWith(
|
|
250
|
+
"checkoutId",
|
|
251
|
+
"session-123",
|
|
252
|
+
"Checkout ID for document deployment website",
|
|
253
|
+
);
|
|
295
254
|
});
|
|
296
255
|
|
|
297
|
-
test("
|
|
298
|
-
|
|
299
|
-
|
|
256
|
+
test("other hooks functionality", async () => {
|
|
257
|
+
let hooks;
|
|
258
|
+
|
|
259
|
+
mockBrokerClient.deploy.mockImplementation(async (config) => {
|
|
260
|
+
hooks = config.hooks;
|
|
261
|
+
return {
|
|
262
|
+
appUrl: TEST_APP_URL,
|
|
263
|
+
vendors: [{ token: "test-token" }],
|
|
264
|
+
};
|
|
300
265
|
});
|
|
301
266
|
|
|
302
|
-
await
|
|
303
|
-
});
|
|
267
|
+
await deploy();
|
|
304
268
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
json: async () => ({
|
|
335
|
-
vendors: [
|
|
336
|
-
{
|
|
337
|
-
appUrl: "https://app.test",
|
|
338
|
-
homeUrl: "https://home.test",
|
|
339
|
-
token: "auth-token-123",
|
|
340
|
-
},
|
|
341
|
-
],
|
|
342
|
-
}),
|
|
343
|
-
};
|
|
344
|
-
}
|
|
269
|
+
// Test INSTALLATION_STARTING hook
|
|
270
|
+
hooks.INSTALLATION_STARTING();
|
|
271
|
+
let logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
272
|
+
expect(logs.some((log) => log.includes("📦 Step 2/4: Installing Website..."))).toBe(true);
|
|
273
|
+
|
|
274
|
+
// Test SERVICE_STARTING hook
|
|
275
|
+
hooks.SERVICE_STARTING();
|
|
276
|
+
logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
277
|
+
expect(logs.some((log) => log.includes("🚀 Step 3/4: Starting Website..."))).toBe(true);
|
|
278
|
+
|
|
279
|
+
// Test ACCESS_PREPARING hook
|
|
280
|
+
hooks.ACCESS_PREPARING();
|
|
281
|
+
logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
282
|
+
expect(logs.some((log) => log.includes("🌐 Step 4/4: Getting Website URL..."))).toBe(true);
|
|
283
|
+
|
|
284
|
+
// Test ACCESS_READY hook without subscription
|
|
285
|
+
await hooks.ACCESS_READY({
|
|
286
|
+
appUrl: TEST_APP_URL,
|
|
287
|
+
homeUrl: TEST_HOME_URL,
|
|
288
|
+
});
|
|
289
|
+
logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
290
|
+
expect(logs.some((log) => log.includes("🔗 Your website is available at:"))).toBe(true);
|
|
291
|
+
expect(logs.some((log) => log.includes(TEST_HOME_URL))).toBe(true);
|
|
292
|
+
|
|
293
|
+
// Test ACCESS_READY hook with subscription
|
|
294
|
+
await hooks.ACCESS_READY({
|
|
295
|
+
appUrl: TEST_APP_URL,
|
|
296
|
+
homeUrl: TEST_HOME_URL,
|
|
297
|
+
subscriptionUrl: TEST_SUBSCRIPTION_URL,
|
|
345
298
|
});
|
|
299
|
+
logs = consoleOutput.filter((o) => o.type === "log").map((o) => o.args.join(" "));
|
|
300
|
+
expect(logs.some((log) => log.includes("🔗 Your subscription management URL:"))).toBe(true);
|
|
301
|
+
expect(logs.some((log) => log.includes(TEST_SUBSCRIPTION_URL))).toBe(true);
|
|
302
|
+
});
|
|
346
303
|
|
|
347
|
-
|
|
348
|
-
|
|
304
|
+
test("handles missing vendors in result", async () => {
|
|
305
|
+
const mockResult = {
|
|
306
|
+
appUrl: TEST_APP_URL,
|
|
307
|
+
homeUrl: TEST_HOME_URL,
|
|
308
|
+
vendors: null,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
mockBrokerClient.deploy.mockResolvedValue(mockResult);
|
|
349
312
|
|
|
350
|
-
// Call deploy without cached parameters - should still succeed
|
|
351
313
|
const result = await deploy();
|
|
352
314
|
|
|
353
|
-
|
|
354
|
-
expect(result.appUrl).toBe(
|
|
355
|
-
expect(result.homeUrl).toBe(
|
|
356
|
-
expect(result.token).toBe("auth-token-123");
|
|
315
|
+
expect(result.token).toBeUndefined();
|
|
316
|
+
expect(result.appUrl).toBe(TEST_APP_URL);
|
|
317
|
+
expect(result.homeUrl).toBe(TEST_HOME_URL);
|
|
357
318
|
});
|
|
358
319
|
|
|
359
|
-
test("handles
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
status: 200,
|
|
366
|
-
json: async () => ({
|
|
367
|
-
payment_status: "paid",
|
|
368
|
-
vendors: [{ id: "vendor-1", progress: 100, appUrl: "https://app.test" }],
|
|
369
|
-
}),
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (url.includes("/detail")) {
|
|
374
|
-
return {
|
|
375
|
-
ok: true,
|
|
376
|
-
status: 200,
|
|
377
|
-
json: async () => ({
|
|
378
|
-
vendors: [
|
|
379
|
-
{
|
|
380
|
-
appUrl: "https://app.test",
|
|
381
|
-
homeUrl: "https://home.test",
|
|
382
|
-
token: "auth-token-123",
|
|
383
|
-
},
|
|
384
|
-
],
|
|
385
|
-
}),
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
});
|
|
320
|
+
test("handles empty vendors array in result", async () => {
|
|
321
|
+
const mockResult = {
|
|
322
|
+
appUrl: TEST_APP_URL,
|
|
323
|
+
homeUrl: TEST_HOME_URL,
|
|
324
|
+
vendors: [],
|
|
325
|
+
};
|
|
389
326
|
|
|
390
|
-
|
|
327
|
+
mockBrokerClient.deploy.mockResolvedValue(mockResult);
|
|
391
328
|
|
|
392
|
-
|
|
329
|
+
const result = await deploy();
|
|
393
330
|
|
|
394
|
-
|
|
395
|
-
expect(
|
|
331
|
+
expect(result.token).toBeUndefined();
|
|
332
|
+
expect(result.appUrl).toBe(TEST_APP_URL);
|
|
333
|
+
expect(result.homeUrl).toBe(TEST_HOME_URL);
|
|
396
334
|
});
|
|
397
335
|
|
|
398
|
-
test("
|
|
399
|
-
|
|
400
|
-
let callCount = 0;
|
|
401
|
-
global.fetch = mock(async (url) => {
|
|
402
|
-
callCount++;
|
|
403
|
-
|
|
404
|
-
// First call: cache check fails
|
|
405
|
-
if (callCount === 1 && url.includes("/status")) {
|
|
406
|
-
throw new Error("Network error during cache check");
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// Create payment session
|
|
410
|
-
if (url.includes("/api/checkout-sessions/start")) {
|
|
411
|
-
return {
|
|
412
|
-
ok: true,
|
|
413
|
-
status: 200,
|
|
414
|
-
json: async () => ({
|
|
415
|
-
checkoutSession: { id: "new-checkout-123" },
|
|
416
|
-
paymentUrl: "https://payment.test/new-checkout-123",
|
|
417
|
-
}),
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
// Subsequent status checks and detail calls
|
|
422
|
-
if (url.includes("/status")) {
|
|
423
|
-
return {
|
|
424
|
-
ok: true,
|
|
425
|
-
status: 200,
|
|
426
|
-
json: async () => ({
|
|
427
|
-
payment_status: "paid",
|
|
428
|
-
vendors: [{ id: "vendor-1", progress: 100, appUrl: "https://app.test" }],
|
|
429
|
-
}),
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
if (url.includes("/detail")) {
|
|
434
|
-
return {
|
|
435
|
-
ok: true,
|
|
436
|
-
status: 200,
|
|
437
|
-
json: async () => ({
|
|
438
|
-
vendors: [
|
|
439
|
-
{
|
|
440
|
-
appUrl: "https://app.test",
|
|
441
|
-
homeUrl: "https://home.test",
|
|
442
|
-
token: "auth-token-123",
|
|
443
|
-
},
|
|
444
|
-
],
|
|
445
|
-
}),
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
});
|
|
336
|
+
test("uses default BASE_URL when not set", async () => {
|
|
337
|
+
delete process.env.DOC_SMITH_BASE_URL;
|
|
449
338
|
|
|
450
|
-
|
|
451
|
-
|
|
339
|
+
const mockResult = {
|
|
340
|
+
appUrl: TEST_APP_URL,
|
|
341
|
+
vendors: [{ token: "test-token" }],
|
|
342
|
+
};
|
|
452
343
|
|
|
453
|
-
|
|
344
|
+
mockBrokerClient.deploy.mockResolvedValue(mockResult);
|
|
454
345
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
346
|
+
await deploy();
|
|
347
|
+
|
|
348
|
+
// Verify BrokerClient was constructed with empty baseUrl
|
|
349
|
+
expect(mockBrokerClientConstructor).toHaveBeenCalledWith(
|
|
350
|
+
expect.objectContaining({
|
|
351
|
+
baseUrl: "",
|
|
352
|
+
}),
|
|
460
353
|
);
|
|
461
354
|
});
|
|
355
|
+
|
|
356
|
+
test("handles browser opening failure", async () => {
|
|
357
|
+
openDefaultSpy.mockRejectedValue(new Error("Cannot open browser"));
|
|
358
|
+
|
|
359
|
+
let paymentPendingHook;
|
|
360
|
+
mockBrokerClient.deploy.mockImplementation(async (config) => {
|
|
361
|
+
paymentPendingHook = config.hooks.PAYMENT_PENDING;
|
|
362
|
+
return {
|
|
363
|
+
appUrl: TEST_APP_URL,
|
|
364
|
+
vendors: [{ token: "test-token" }],
|
|
365
|
+
};
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
await deploy();
|
|
369
|
+
|
|
370
|
+
// The hook should throw when browser opening fails (expected behavior)
|
|
371
|
+
await expect(
|
|
372
|
+
paymentPendingHook({
|
|
373
|
+
sessionId: "session-123",
|
|
374
|
+
paymentUrl: "https://payment.test/session-123",
|
|
375
|
+
isResuming: false,
|
|
376
|
+
}),
|
|
377
|
+
).rejects.toThrow("Cannot open browser");
|
|
378
|
+
|
|
379
|
+
// Config should still be saved
|
|
380
|
+
expect(saveValueToConfigSpy).toHaveBeenCalled();
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
test("handles saveValueToConfig failure", async () => {
|
|
384
|
+
saveValueToConfigSpy.mockRejectedValue(new Error("Config save failed"));
|
|
385
|
+
|
|
386
|
+
let paymentPendingHook;
|
|
387
|
+
mockBrokerClient.deploy.mockImplementation(async (config) => {
|
|
388
|
+
paymentPendingHook = config.hooks.PAYMENT_PENDING;
|
|
389
|
+
return {
|
|
390
|
+
appUrl: TEST_APP_URL,
|
|
391
|
+
vendors: [{ token: "test-token" }],
|
|
392
|
+
};
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
await deploy();
|
|
396
|
+
|
|
397
|
+
// The hook should throw when config saving fails (expected behavior)
|
|
398
|
+
await expect(
|
|
399
|
+
paymentPendingHook({
|
|
400
|
+
sessionId: "session-123",
|
|
401
|
+
paymentUrl: "https://payment.test/session-123",
|
|
402
|
+
isResuming: false,
|
|
403
|
+
}),
|
|
404
|
+
).rejects.toThrow("Config save failed");
|
|
405
|
+
});
|
|
462
406
|
});
|