@aigne/doc-smith 0.8.12-beta.8 → 0.8.12-beta.9
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/CHANGELOG.md +13 -0
- package/agents/publish/index.yaml +4 -0
- package/agents/publish/publish-docs.mjs +77 -5
- package/agents/publish/translate-meta.mjs +103 -0
- package/agents/update/generate-document.yaml +30 -28
- package/agents/update/update-document-detail.yaml +3 -1
- package/agents/utils/update-branding.mjs +69 -0
- package/package.json +16 -2
- package/prompts/common/document/role-and-personality.md +3 -1
- package/prompts/detail/d2-diagram/guide.md +7 -1
- package/prompts/detail/d2-diagram/user-prompt.md +3 -0
- package/prompts/detail/generate/system-prompt.md +6 -7
- package/prompts/detail/generate/user-prompt.md +12 -3
- package/prompts/detail/update/user-prompt.md +0 -2
- package/prompts/structure/update/user-prompt.md +0 -4
- package/utils/file-utils.mjs +69 -24
- package/utils/markdown-checker.mjs +0 -20
- package/utils/request.mjs +7 -0
- package/utils/upload-files.mjs +231 -0
- package/utils/utils.mjs +11 -1
- package/.aigne/doc-smith/config.yaml +0 -77
- package/.aigne/doc-smith/history.yaml +0 -37
- package/.aigne/doc-smith/media-description.yaml +0 -91
- package/.aigne/doc-smith/output/structure-plan.json +0 -162
- package/.aigne/doc-smith/preferences.yml +0 -97
- package/.aigne/doc-smith/upload-cache.yaml +0 -1830
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -28
- package/.github/workflows/ci.yml +0 -54
- package/.github/workflows/create-release-pr.yaml +0 -21
- package/.github/workflows/publish-docs.yml +0 -65
- package/.github/workflows/release.yml +0 -49
- package/.github/workflows/reviewer.yml +0 -54
- package/.release-please-manifest.json +0 -3
- package/RELEASE.md +0 -9
- package/assets/screenshots/doc-complete-setup.png +0 -0
- package/assets/screenshots/doc-generate-docs.png +0 -0
- package/assets/screenshots/doc-generate.png +0 -0
- package/assets/screenshots/doc-generated-successfully.png +0 -0
- package/assets/screenshots/doc-publish.png +0 -0
- package/assets/screenshots/doc-regenerate.png +0 -0
- package/assets/screenshots/doc-translate-langs.png +0 -0
- package/assets/screenshots/doc-translate.png +0 -0
- package/assets/screenshots/doc-update.png +0 -0
- package/biome.json +0 -73
- package/codecov.yml +0 -15
- package/docs/_sidebar.md +0 -15
- package/docs/configuration-initial-setup.ja.md +0 -179
- package/docs/configuration-initial-setup.md +0 -198
- package/docs/configuration-initial-setup.zh-TW.md +0 -179
- package/docs/configuration-initial-setup.zh.md +0 -179
- package/docs/configuration-managing-preferences.ja.md +0 -100
- package/docs/configuration-managing-preferences.md +0 -100
- package/docs/configuration-managing-preferences.zh-TW.md +0 -100
- package/docs/configuration-managing-preferences.zh.md +0 -100
- package/docs/configuration.ja.md +0 -69
- package/docs/configuration.md +0 -69
- package/docs/configuration.zh-TW.md +0 -69
- package/docs/configuration.zh.md +0 -69
- package/docs/getting-started.ja.md +0 -107
- package/docs/getting-started.md +0 -107
- package/docs/getting-started.zh-TW.md +0 -107
- package/docs/getting-started.zh.md +0 -107
- package/docs/guides-cleaning-up.ja.md +0 -51
- package/docs/guides-cleaning-up.md +0 -52
- package/docs/guides-cleaning-up.zh-TW.md +0 -51
- package/docs/guides-cleaning-up.zh.md +0 -51
- package/docs/guides-evaluating-documents.ja.md +0 -66
- package/docs/guides-evaluating-documents.md +0 -107
- package/docs/guides-evaluating-documents.zh-TW.md +0 -66
- package/docs/guides-evaluating-documents.zh.md +0 -66
- package/docs/guides-generating-documentation.ja.md +0 -151
- package/docs/guides-generating-documentation.md +0 -89
- package/docs/guides-generating-documentation.zh-TW.md +0 -151
- package/docs/guides-generating-documentation.zh.md +0 -151
- package/docs/guides-interactive-chat.ja.md +0 -85
- package/docs/guides-interactive-chat.md +0 -93
- package/docs/guides-interactive-chat.zh-TW.md +0 -85
- package/docs/guides-interactive-chat.zh.md +0 -85
- package/docs/guides-managing-history.ja.md +0 -48
- package/docs/guides-managing-history.md +0 -53
- package/docs/guides-managing-history.zh-TW.md +0 -48
- package/docs/guides-managing-history.zh.md +0 -48
- package/docs/guides-publishing-your-docs.ja.md +0 -78
- package/docs/guides-publishing-your-docs.md +0 -83
- package/docs/guides-publishing-your-docs.zh-TW.md +0 -78
- package/docs/guides-publishing-your-docs.zh.md +0 -78
- package/docs/guides-translating-documentation.ja.md +0 -95
- package/docs/guides-translating-documentation.md +0 -100
- package/docs/guides-translating-documentation.zh-TW.md +0 -95
- package/docs/guides-translating-documentation.zh.md +0 -95
- package/docs/guides-updating-documentation.ja.md +0 -77
- package/docs/guides-updating-documentation.md +0 -79
- package/docs/guides-updating-documentation.zh-TW.md +0 -77
- package/docs/guides-updating-documentation.zh.md +0 -77
- package/docs/guides.ja.md +0 -32
- package/docs/guides.md +0 -32
- package/docs/guides.zh-TW.md +0 -32
- package/docs/guides.zh.md +0 -32
- package/docs/overview.ja.md +0 -61
- package/docs/overview.md +0 -61
- package/docs/overview.zh-TW.md +0 -61
- package/docs/overview.zh.md +0 -61
- package/docs/release-notes.ja.md +0 -255
- package/docs/release-notes.md +0 -288
- package/docs/release-notes.zh-TW.md +0 -255
- package/docs/release-notes.zh.md +0 -255
- package/prompts/common/afs/afs-tools-usage.md +0 -5
- package/prompts/common/afs/use-afs-instruction.md +0 -1
- package/release-please-config.json +0 -14
- package/tests/agents/chat/chat.test.mjs +0 -46
- package/tests/agents/clear/choose-contents.test.mjs +0 -284
- package/tests/agents/clear/clear-auth-tokens.test.mjs +0 -268
- package/tests/agents/clear/clear-document-config.test.mjs +0 -167
- package/tests/agents/clear/clear-document-structure.test.mjs +0 -380
- package/tests/agents/clear/clear-generated-docs.test.mjs +0 -222
- package/tests/agents/evaluate/code-snippet.test.mjs +0 -163
- package/tests/agents/evaluate/fixtures/api-services.md +0 -87
- package/tests/agents/evaluate/fixtures/js-sdk.md +0 -94
- package/tests/agents/evaluate/generate-report.test.mjs +0 -312
- package/tests/agents/generate/check-document-structure.test.mjs +0 -45
- package/tests/agents/generate/check-need-generate-structure.test.mjs +0 -279
- package/tests/agents/generate/document-structure-tools/add-document.test.mjs +0 -449
- package/tests/agents/generate/document-structure-tools/delete-document.test.mjs +0 -410
- package/tests/agents/generate/document-structure-tools/generate-sub-structure.test.mjs +0 -277
- package/tests/agents/generate/document-structure-tools/move-document.test.mjs +0 -476
- package/tests/agents/generate/document-structure-tools/update-document.test.mjs +0 -548
- package/tests/agents/generate/generate-structure.test.mjs +0 -45
- package/tests/agents/generate/user-review-document-structure.test.mjs +0 -319
- package/tests/agents/history/view.test.mjs +0 -97
- package/tests/agents/init/init.test.mjs +0 -1657
- package/tests/agents/prefs/prefs.test.mjs +0 -431
- package/tests/agents/publish/publish-docs.test.mjs +0 -787
- package/tests/agents/translate/choose-language.test.mjs +0 -311
- package/tests/agents/translate/translate-document.test.mjs +0 -51
- package/tests/agents/update/check-document.test.mjs +0 -463
- package/tests/agents/update/check-update-is-single.test.mjs +0 -300
- package/tests/agents/update/document-tools/update-document-content.test.mjs +0 -329
- package/tests/agents/update/generate-document.test.mjs +0 -51
- package/tests/agents/update/save-and-translate-document.test.mjs +0 -369
- package/tests/agents/update/user-review-document.test.mjs +0 -582
- package/tests/agents/utils/action-success.test.mjs +0 -54
- package/tests/agents/utils/check-detail-result.test.mjs +0 -743
- package/tests/agents/utils/check-feedback-refiner.test.mjs +0 -478
- package/tests/agents/utils/choose-docs.test.mjs +0 -406
- package/tests/agents/utils/exit.test.mjs +0 -70
- package/tests/agents/utils/feedback-refiner.test.mjs +0 -51
- package/tests/agents/utils/find-item-by-path.test.mjs +0 -517
- package/tests/agents/utils/find-user-preferences-by-path.test.mjs +0 -382
- package/tests/agents/utils/format-document-structure.test.mjs +0 -364
- package/tests/agents/utils/fs.test.mjs +0 -267
- package/tests/agents/utils/load-sources.test.mjs +0 -1470
- package/tests/agents/utils/save-docs.test.mjs +0 -109
- package/tests/agents/utils/save-output.test.mjs +0 -315
- package/tests/agents/utils/save-single-doc.test.mjs +0 -364
- package/tests/agents/utils/transform-detail-datasources.test.mjs +0 -320
- package/tests/utils/auth-utils.test.mjs +0 -596
- package/tests/utils/blocklet.test.mjs +0 -336
- package/tests/utils/conflict-detector.test.mjs +0 -355
- package/tests/utils/constants.test.mjs +0 -295
- package/tests/utils/d2-utils.test.mjs +0 -437
- package/tests/utils/deploy.test.mjs +0 -399
- package/tests/utils/docs-finder-utils.test.mjs +0 -650
- package/tests/utils/file-utils.test.mjs +0 -521
- package/tests/utils/history-utils.test.mjs +0 -206
- package/tests/utils/kroki-utils.test.mjs +0 -646
- package/tests/utils/linter/fixtures/css/keyword-error.css +0 -1
- package/tests/utils/linter/fixtures/css/missing-semicolon.css +0 -1
- package/tests/utils/linter/fixtures/css/syntax-error.css +0 -1
- package/tests/utils/linter/fixtures/css/undeclare-variable.css +0 -1
- package/tests/utils/linter/fixtures/css/unused-variable.css +0 -2
- package/tests/utils/linter/fixtures/css/valid-code.css +0 -1
- package/tests/utils/linter/fixtures/dockerfile/keyword-error.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/missing-semicolon.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/syntax-error.dockerfile +0 -2
- package/tests/utils/linter/fixtures/dockerfile/undeclare-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/unused-variable.dockerfile +0 -1
- package/tests/utils/linter/fixtures/dockerfile/valid-code.dockerfile +0 -2
- package/tests/utils/linter/fixtures/go/keyword-error.go +0 -5
- package/tests/utils/linter/fixtures/go/missing-semicolon.go +0 -5
- package/tests/utils/linter/fixtures/go/syntax-error.go +0 -6
- package/tests/utils/linter/fixtures/go/undeclare-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/unused-variable.go +0 -5
- package/tests/utils/linter/fixtures/go/valid-code.go +0 -7
- package/tests/utils/linter/fixtures/js/keyword-error.js +0 -3
- package/tests/utils/linter/fixtures/js/missing-semicolon.js +0 -6
- package/tests/utils/linter/fixtures/js/syntax-error.js +0 -4
- package/tests/utils/linter/fixtures/js/undeclare-variable.js +0 -3
- package/tests/utils/linter/fixtures/js/unused-variable.js +0 -7
- package/tests/utils/linter/fixtures/js/valid-code.js +0 -15
- package/tests/utils/linter/fixtures/json/keyword-error.json +0 -1
- package/tests/utils/linter/fixtures/json/missing-semicolon.json +0 -1
- package/tests/utils/linter/fixtures/json/syntax-error.json +0 -1
- package/tests/utils/linter/fixtures/json/undeclare-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/unused-variable.json +0 -1
- package/tests/utils/linter/fixtures/json/valid-code.json +0 -1
- package/tests/utils/linter/fixtures/jsx/keyword-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/missing-semicolon.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/syntax-error.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/undeclare-variable.jsx +0 -5
- package/tests/utils/linter/fixtures/jsx/unused-variable.jsx +0 -4
- package/tests/utils/linter/fixtures/jsx/valid-code.jsx +0 -5
- package/tests/utils/linter/fixtures/python/keyword-error.py +0 -3
- package/tests/utils/linter/fixtures/python/missing-semicolon.py +0 -2
- package/tests/utils/linter/fixtures/python/syntax-error.py +0 -3
- package/tests/utils/linter/fixtures/python/undeclare-variable.py +0 -3
- package/tests/utils/linter/fixtures/python/unused-variable.py +0 -6
- package/tests/utils/linter/fixtures/python/valid-code.py +0 -12
- package/tests/utils/linter/fixtures/ruby/keyword-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/missing-semicolon.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/syntax-error.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/undeclare-variable.rb +0 -1
- package/tests/utils/linter/fixtures/ruby/unused-variable.rb +0 -2
- package/tests/utils/linter/fixtures/ruby/valid-code.rb +0 -1
- package/tests/utils/linter/fixtures/sass/keyword-error.sass +0 -2
- package/tests/utils/linter/fixtures/sass/missing-semicolon.sass +0 -3
- package/tests/utils/linter/fixtures/sass/syntax-error.sass +0 -3
- package/tests/utils/linter/fixtures/sass/undeclare-variable.sass +0 -2
- package/tests/utils/linter/fixtures/sass/unused-variable.sass +0 -4
- package/tests/utils/linter/fixtures/sass/valid-code.sass +0 -2
- package/tests/utils/linter/fixtures/scss/keyword-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/missing-semicolon.scss +0 -1
- package/tests/utils/linter/fixtures/scss/syntax-error.scss +0 -1
- package/tests/utils/linter/fixtures/scss/undeclare-variable.scss +0 -1
- package/tests/utils/linter/fixtures/scss/unused-variable.scss +0 -2
- package/tests/utils/linter/fixtures/scss/valid-code.scss +0 -1
- package/tests/utils/linter/fixtures/shell/keyword-error.sh +0 -5
- package/tests/utils/linter/fixtures/shell/missing-semicolon.sh +0 -3
- package/tests/utils/linter/fixtures/shell/syntax-error.sh +0 -4
- package/tests/utils/linter/fixtures/shell/undeclare-variable.sh +0 -3
- package/tests/utils/linter/fixtures/shell/unused-variable.sh +0 -4
- package/tests/utils/linter/fixtures/shell/valid-code.sh +0 -3
- package/tests/utils/linter/fixtures/ts/keyword-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/missing-semicolon.ts +0 -1
- package/tests/utils/linter/fixtures/ts/syntax-error.ts +0 -1
- package/tests/utils/linter/fixtures/ts/undeclare-variable.ts +0 -1
- package/tests/utils/linter/fixtures/ts/unused-variable.ts +0 -3
- package/tests/utils/linter/fixtures/ts/valid-code.ts +0 -3
- package/tests/utils/linter/fixtures/tsx/keyword-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/missing-semicolon.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/syntax-error.tsx +0 -5
- package/tests/utils/linter/fixtures/tsx/undeclare-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/unused-variable.tsx +0 -6
- package/tests/utils/linter/fixtures/tsx/valid-code.tsx +0 -5
- package/tests/utils/linter/fixtures/vue/keyword-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/missing-semicolon.vue +0 -6
- package/tests/utils/linter/fixtures/vue/syntax-error.vue +0 -6
- package/tests/utils/linter/fixtures/vue/undeclare-variable.vue +0 -6
- package/tests/utils/linter/fixtures/vue/unused-variable.vue +0 -7
- package/tests/utils/linter/fixtures/vue/valid-code.vue +0 -6
- package/tests/utils/linter/fixtures/yaml/keyword-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/missing-semicolon.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/syntax-error.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/undeclare-variable.yml +0 -1
- package/tests/utils/linter/fixtures/yaml/unused-variable.yml +0 -2
- package/tests/utils/linter/fixtures/yaml/valid-code.yml +0 -3
- package/tests/utils/linter/index.test.mjs +0 -440
- package/tests/utils/linter/scan-results.mjs +0 -42
- package/tests/utils/load-config.test.mjs +0 -141
- package/tests/utils/markdown/index.test.mjs +0 -478
- package/tests/utils/mermaid-validator.test.mjs +0 -541
- package/tests/utils/mock-chat-model.mjs +0 -12
- package/tests/utils/preferences-utils.test.mjs +0 -465
- package/tests/utils/save-value-to-config.test.mjs +0 -483
- package/tests/utils/utils.test.mjs +0 -941
|
@@ -1,787 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
afterAll,
|
|
3
|
-
afterEach,
|
|
4
|
-
beforeAll,
|
|
5
|
-
beforeEach,
|
|
6
|
-
describe,
|
|
7
|
-
expect,
|
|
8
|
-
mock,
|
|
9
|
-
spyOn,
|
|
10
|
-
test,
|
|
11
|
-
} from "bun:test";
|
|
12
|
-
import publishDocs from "../../../agents/publish/publish-docs.mjs";
|
|
13
|
-
|
|
14
|
-
// Import internal utils for selective spying
|
|
15
|
-
import * as authUtils from "../../../utils/auth-utils.mjs";
|
|
16
|
-
import * as d2Utils from "../../../utils/d2-utils.mjs";
|
|
17
|
-
import * as utils from "../../../utils/utils.mjs";
|
|
18
|
-
import * as deployUtils from "../../../utils/deploy.mjs";
|
|
19
|
-
|
|
20
|
-
// Mock all external dependencies
|
|
21
|
-
const mockPublishDocs = {
|
|
22
|
-
publishDocs: mock(() => Promise.resolve({ success: true, boardId: "new-board-id" })),
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const mockBrokerClient = {
|
|
26
|
-
checkCacheSession: mock(() => Promise.resolve({ sessionId: null, paymentLink: null })),
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const mockBrokerClientConstructor = mock(() => mockBrokerClient);
|
|
30
|
-
|
|
31
|
-
const mockChalk = {
|
|
32
|
-
bold: mock((text) => text),
|
|
33
|
-
cyan: mock((text) => text),
|
|
34
|
-
blue: mock((text) => text),
|
|
35
|
-
green: mock((text) => text),
|
|
36
|
-
yellow: mock((text) => text),
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const mockFsExtra = {
|
|
40
|
-
rm: mock(() => Promise.resolve()),
|
|
41
|
-
mkdir: mock(() => Promise.resolve()),
|
|
42
|
-
cp: mock(() => Promise.resolve()),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
const mockPath = {
|
|
46
|
-
basename: mock(() => "test-project"),
|
|
47
|
-
join: mock((...paths) => paths.join("/")),
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
describe("publish-docs", () => {
|
|
51
|
-
let mockOptions;
|
|
52
|
-
let originalEnv;
|
|
53
|
-
|
|
54
|
-
// Spies for internal utils
|
|
55
|
-
let getAccessTokenSpy;
|
|
56
|
-
let getOfficialAccessTokenSpy;
|
|
57
|
-
let beforePublishHookSpy;
|
|
58
|
-
let ensureTmpDirSpy;
|
|
59
|
-
let getGithubRepoUrlSpy;
|
|
60
|
-
let loadConfigFromFileSpy;
|
|
61
|
-
let saveValueToConfigSpy;
|
|
62
|
-
let deploySpy;
|
|
63
|
-
|
|
64
|
-
beforeAll(() => {
|
|
65
|
-
// Apply mocks for external dependencies only
|
|
66
|
-
mock.module("@aigne/publish-docs", () => mockPublishDocs);
|
|
67
|
-
mock.module("@blocklet/payment-broker-client/node", () => ({
|
|
68
|
-
BrokerClient: mockBrokerClientConstructor,
|
|
69
|
-
}));
|
|
70
|
-
mock.module("chalk", () => ({ default: mockChalk }));
|
|
71
|
-
mock.module("fs-extra", () => ({ default: mockFsExtra }));
|
|
72
|
-
mock.module("node:path", () => mockPath);
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
afterAll(() => {
|
|
76
|
-
// Restore all mocks when this test file is complete
|
|
77
|
-
mock.restore();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
beforeEach(() => {
|
|
81
|
-
// Save original environment
|
|
82
|
-
originalEnv = { ...process.env };
|
|
83
|
-
|
|
84
|
-
// Reset external mocks and clear call history
|
|
85
|
-
mockPublishDocs.publishDocs.mockClear();
|
|
86
|
-
mockPublishDocs.publishDocs.mockImplementation(() =>
|
|
87
|
-
Promise.resolve({ success: true, boardId: "new-board-id" }),
|
|
88
|
-
);
|
|
89
|
-
mockFsExtra.rm.mockClear();
|
|
90
|
-
mockFsExtra.rm.mockImplementation(() => Promise.resolve());
|
|
91
|
-
mockFsExtra.mkdir.mockClear();
|
|
92
|
-
mockFsExtra.mkdir.mockImplementation(() => Promise.resolve());
|
|
93
|
-
mockFsExtra.cp.mockClear();
|
|
94
|
-
mockFsExtra.cp.mockImplementation(() => Promise.resolve());
|
|
95
|
-
mockPath.basename.mockClear();
|
|
96
|
-
mockPath.basename.mockImplementation(() => "test-project");
|
|
97
|
-
mockPath.join.mockClear();
|
|
98
|
-
mockPath.join.mockImplementation((...paths) => paths.join("/"));
|
|
99
|
-
mockChalk.bold.mockClear();
|
|
100
|
-
mockChalk.bold.mockImplementation((text) => text);
|
|
101
|
-
mockChalk.cyan.mockClear();
|
|
102
|
-
mockChalk.cyan.mockImplementation((text) => text);
|
|
103
|
-
|
|
104
|
-
// Reset BrokerClient mock
|
|
105
|
-
mockBrokerClientConstructor.mockClear();
|
|
106
|
-
mockBrokerClientConstructor.mockImplementation(() => mockBrokerClient);
|
|
107
|
-
mockBrokerClient.checkCacheSession.mockClear();
|
|
108
|
-
mockBrokerClient.checkCacheSession.mockImplementation(() =>
|
|
109
|
-
Promise.resolve({ sessionId: null, paymentLink: null }),
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
// Set up spies for internal utils
|
|
113
|
-
getAccessTokenSpy = spyOn(authUtils, "getAccessToken").mockResolvedValue("mock-token");
|
|
114
|
-
getOfficialAccessTokenSpy = spyOn(authUtils, "getOfficialAccessToken").mockResolvedValue(
|
|
115
|
-
"official-mock-token",
|
|
116
|
-
);
|
|
117
|
-
beforePublishHookSpy = spyOn(d2Utils, "beforePublishHook").mockResolvedValue();
|
|
118
|
-
ensureTmpDirSpy = spyOn(d2Utils, "ensureTmpDir").mockResolvedValue();
|
|
119
|
-
getGithubRepoUrlSpy = spyOn(utils, "getGithubRepoUrl").mockReturnValue(
|
|
120
|
-
"https://github.com/user/repo",
|
|
121
|
-
);
|
|
122
|
-
loadConfigFromFileSpy = spyOn(utils, "loadConfigFromFile").mockResolvedValue({});
|
|
123
|
-
saveValueToConfigSpy = spyOn(utils, "saveValueToConfig").mockResolvedValue();
|
|
124
|
-
deploySpy = spyOn(deployUtils, "deploy").mockResolvedValue({
|
|
125
|
-
appUrl: "https://deployed.example.com",
|
|
126
|
-
token: "deploy-token",
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
mockOptions = {
|
|
130
|
-
prompts: {
|
|
131
|
-
select: mock(async () => "default"),
|
|
132
|
-
input: mock(async () => "https://example.com"),
|
|
133
|
-
},
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
// Clear prompts mock call history
|
|
137
|
-
mockOptions.prompts.select.mockClear();
|
|
138
|
-
mockOptions.prompts.input.mockClear();
|
|
139
|
-
|
|
140
|
-
// Clear environment variable
|
|
141
|
-
delete process.env.DOC_DISCUSS_KIT_URL;
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
afterEach(() => {
|
|
145
|
-
// Restore original environment
|
|
146
|
-
process.env = originalEnv;
|
|
147
|
-
|
|
148
|
-
// Restore all spies
|
|
149
|
-
getAccessTokenSpy?.mockRestore();
|
|
150
|
-
getOfficialAccessTokenSpy?.mockRestore();
|
|
151
|
-
beforePublishHookSpy?.mockRestore();
|
|
152
|
-
ensureTmpDirSpy?.mockRestore();
|
|
153
|
-
getGithubRepoUrlSpy?.mockRestore();
|
|
154
|
-
loadConfigFromFileSpy?.mockRestore();
|
|
155
|
-
saveValueToConfigSpy?.mockRestore();
|
|
156
|
-
deploySpy?.mockRestore();
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// BASIC FUNCTIONALITY TESTS
|
|
160
|
-
test("should publish docs successfully with default settings", async () => {
|
|
161
|
-
loadConfigFromFileSpy.mockResolvedValue({ appUrl: "https://docsmith.aigne.io" });
|
|
162
|
-
|
|
163
|
-
const result = await publishDocs(
|
|
164
|
-
{
|
|
165
|
-
docsDir: "./docs",
|
|
166
|
-
appUrl: "https://docsmith.aigne.io",
|
|
167
|
-
boardId: "board-123",
|
|
168
|
-
},
|
|
169
|
-
mockOptions,
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
expect(ensureTmpDirSpy).toHaveBeenCalled();
|
|
173
|
-
expect(mockFsExtra.cp).toHaveBeenCalled();
|
|
174
|
-
expect(beforePublishHookSpy).toHaveBeenCalled();
|
|
175
|
-
expect(getAccessTokenSpy).toHaveBeenCalledWith("https://docsmith.aigne.io", "");
|
|
176
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalled();
|
|
177
|
-
expect(result.message).toBe("✅ Documentation published successfully!");
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// ENVIRONMENT VARIABLE TESTS
|
|
181
|
-
test("should use environment variable DOC_DISCUSS_KIT_URL when set", async () => {
|
|
182
|
-
process.env.DOC_DISCUSS_KIT_URL = "https://env.example.com";
|
|
183
|
-
|
|
184
|
-
await publishDocs(
|
|
185
|
-
{
|
|
186
|
-
docsDir: "./docs",
|
|
187
|
-
appUrl: "https://docsmith.aigne.io",
|
|
188
|
-
},
|
|
189
|
-
mockOptions,
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
expect(getAccessTokenSpy).toHaveBeenCalledWith("https://env.example.com", "");
|
|
193
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
194
|
-
expect.objectContaining({
|
|
195
|
-
appUrl: "https://env.example.com",
|
|
196
|
-
}),
|
|
197
|
-
);
|
|
198
|
-
// Should not save appUrl when using environment variable
|
|
199
|
-
expect(saveValueToConfigSpy).not.toHaveBeenCalledWith("appUrl", expect.anything());
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// USER INTERACTION TESTS
|
|
203
|
-
test("should prompt user to select platform when using default URL without config", async () => {
|
|
204
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
205
|
-
mockOptions.prompts.select.mockResolvedValue("default");
|
|
206
|
-
|
|
207
|
-
await publishDocs(
|
|
208
|
-
{
|
|
209
|
-
docsDir: "./docs",
|
|
210
|
-
appUrl: "https://docsmith.aigne.io",
|
|
211
|
-
},
|
|
212
|
-
mockOptions,
|
|
213
|
-
);
|
|
214
|
-
|
|
215
|
-
expect(mockOptions.prompts.select).toHaveBeenCalledWith(
|
|
216
|
-
expect.objectContaining({
|
|
217
|
-
message: expect.stringContaining("Select platform"),
|
|
218
|
-
choices: expect.any(Array),
|
|
219
|
-
}),
|
|
220
|
-
);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("should handle custom platform selection", async () => {
|
|
224
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
225
|
-
mockOptions.prompts.select.mockResolvedValue("custom");
|
|
226
|
-
mockOptions.prompts.input.mockResolvedValue("https://custom.example.com");
|
|
227
|
-
|
|
228
|
-
const consoleSpy = spyOn(console, "log").mockImplementation(() => {});
|
|
229
|
-
|
|
230
|
-
await publishDocs(
|
|
231
|
-
{
|
|
232
|
-
docsDir: "./docs",
|
|
233
|
-
appUrl: "https://docsmith.aigne.io",
|
|
234
|
-
},
|
|
235
|
-
mockOptions,
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
expect(consoleSpy).toHaveBeenCalled();
|
|
239
|
-
expect(mockOptions.prompts.input).toHaveBeenCalledWith({
|
|
240
|
-
message: "Please enter your website URL:",
|
|
241
|
-
validate: expect.any(Function),
|
|
242
|
-
});
|
|
243
|
-
expect(getAccessTokenSpy).toHaveBeenCalledWith("https://custom.example.com", "");
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test("should validate URL input and accept valid URLs", async () => {
|
|
247
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
248
|
-
mockOptions.prompts.select.mockResolvedValue("custom");
|
|
249
|
-
mockOptions.prompts.input.mockResolvedValue("https://valid.example.com");
|
|
250
|
-
|
|
251
|
-
await publishDocs(
|
|
252
|
-
{
|
|
253
|
-
docsDir: "./docs",
|
|
254
|
-
appUrl: "https://docsmith.aigne.io",
|
|
255
|
-
},
|
|
256
|
-
mockOptions,
|
|
257
|
-
);
|
|
258
|
-
|
|
259
|
-
const validateFn = mockOptions.prompts.input.mock.calls[0][0].validate;
|
|
260
|
-
|
|
261
|
-
expect(validateFn("https://valid.com")).toBe(true);
|
|
262
|
-
expect(validateFn("valid.com")).toBe(true); // Should work without protocol
|
|
263
|
-
expect(validateFn("")).toBe("Please enter a valid URL");
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
test("should add https protocol when not provided in URL", async () => {
|
|
267
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
268
|
-
mockOptions.prompts.select.mockResolvedValue("custom");
|
|
269
|
-
mockOptions.prompts.input.mockResolvedValue("example.com");
|
|
270
|
-
|
|
271
|
-
await publishDocs(
|
|
272
|
-
{
|
|
273
|
-
docsDir: "./docs",
|
|
274
|
-
appUrl: "https://docsmith.aigne.io",
|
|
275
|
-
},
|
|
276
|
-
mockOptions,
|
|
277
|
-
);
|
|
278
|
-
|
|
279
|
-
expect(getAccessTokenSpy).toHaveBeenCalledWith("https://example.com", "");
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
// PROJECT INFO TESTS
|
|
283
|
-
test("should use provided project info parameters", async () => {
|
|
284
|
-
await publishDocs(
|
|
285
|
-
{
|
|
286
|
-
docsDir: "./docs",
|
|
287
|
-
appUrl: "https://example.com",
|
|
288
|
-
projectName: "Test Project",
|
|
289
|
-
projectDesc: "Test Description",
|
|
290
|
-
projectLogo: "logo.png",
|
|
291
|
-
},
|
|
292
|
-
mockOptions,
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
296
|
-
expect.objectContaining({
|
|
297
|
-
boardName: "Test Project",
|
|
298
|
-
boardDesc: "Test Description",
|
|
299
|
-
boardCover: "logo.png",
|
|
300
|
-
}),
|
|
301
|
-
);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
test("should fallback to config values for project info", async () => {
|
|
305
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
306
|
-
projectName: "Config Project",
|
|
307
|
-
projectDesc: "Config Description",
|
|
308
|
-
projectLogo: "config-logo.png",
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
await publishDocs(
|
|
312
|
-
{
|
|
313
|
-
docsDir: "./docs",
|
|
314
|
-
appUrl: "https://example.com",
|
|
315
|
-
},
|
|
316
|
-
mockOptions,
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
320
|
-
expect.objectContaining({
|
|
321
|
-
boardName: "Config Project",
|
|
322
|
-
boardDesc: "Config Description",
|
|
323
|
-
boardCover: "config-logo.png",
|
|
324
|
-
}),
|
|
325
|
-
);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
test("should use default project name from current directory", async () => {
|
|
329
|
-
mockPath.basename.mockReturnValue("default-project");
|
|
330
|
-
|
|
331
|
-
await publishDocs(
|
|
332
|
-
{
|
|
333
|
-
docsDir: "./docs",
|
|
334
|
-
appUrl: "https://example.com",
|
|
335
|
-
},
|
|
336
|
-
mockOptions,
|
|
337
|
-
);
|
|
338
|
-
|
|
339
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
340
|
-
expect.objectContaining({
|
|
341
|
-
boardName: "default-project",
|
|
342
|
-
boardDesc: "",
|
|
343
|
-
boardCover: "",
|
|
344
|
-
}),
|
|
345
|
-
);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// BOARD META TESTS
|
|
349
|
-
test("should construct board meta correctly", async () => {
|
|
350
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
351
|
-
documentPurpose: ["API", "Tutorial"],
|
|
352
|
-
locale: "en",
|
|
353
|
-
translateLanguages: ["zh", "ja"],
|
|
354
|
-
lastGitHead: "abc123",
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
await publishDocs(
|
|
358
|
-
{
|
|
359
|
-
docsDir: "./docs",
|
|
360
|
-
appUrl: "https://example.com",
|
|
361
|
-
},
|
|
362
|
-
mockOptions,
|
|
363
|
-
);
|
|
364
|
-
|
|
365
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
366
|
-
expect.objectContaining({
|
|
367
|
-
boardMeta: {
|
|
368
|
-
category: ["API", "Tutorial"],
|
|
369
|
-
githubRepoUrl: "https://github.com/user/repo",
|
|
370
|
-
commitSha: "abc123",
|
|
371
|
-
languages: ["en", "zh", "ja"],
|
|
372
|
-
},
|
|
373
|
-
}),
|
|
374
|
-
);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
test("should handle duplicate languages in board meta", async () => {
|
|
378
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
379
|
-
locale: "en",
|
|
380
|
-
translateLanguages: ["en", "zh", "en"], // Duplicates
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
await publishDocs(
|
|
384
|
-
{
|
|
385
|
-
docsDir: "./docs",
|
|
386
|
-
appUrl: "https://example.com",
|
|
387
|
-
},
|
|
388
|
-
mockOptions,
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
392
|
-
expect.objectContaining({
|
|
393
|
-
boardMeta: expect.objectContaining({
|
|
394
|
-
languages: ["en", "zh"], // Duplicates removed
|
|
395
|
-
}),
|
|
396
|
-
}),
|
|
397
|
-
);
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
// CONFIG SAVING TESTS
|
|
401
|
-
test("should save appUrl when not using environment variable", async () => {
|
|
402
|
-
await publishDocs(
|
|
403
|
-
{
|
|
404
|
-
docsDir: "./docs",
|
|
405
|
-
appUrl: "https://custom.example.com",
|
|
406
|
-
},
|
|
407
|
-
mockOptions,
|
|
408
|
-
);
|
|
409
|
-
|
|
410
|
-
expect(saveValueToConfigSpy).toHaveBeenCalledWith("appUrl", "https://custom.example.com");
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
test("should save new boardId when auto-created", async () => {
|
|
414
|
-
mockPublishDocs.publishDocs.mockResolvedValue({
|
|
415
|
-
success: true,
|
|
416
|
-
boardId: "auto-created-id",
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
await publishDocs(
|
|
420
|
-
{
|
|
421
|
-
docsDir: "./docs",
|
|
422
|
-
appUrl: "https://example.com",
|
|
423
|
-
boardId: "original-id",
|
|
424
|
-
},
|
|
425
|
-
mockOptions,
|
|
426
|
-
);
|
|
427
|
-
|
|
428
|
-
expect(saveValueToConfigSpy).toHaveBeenCalledWith("boardId", "auto-created-id");
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
test("should not save boardId when it hasn't changed", async () => {
|
|
432
|
-
mockPublishDocs.publishDocs.mockResolvedValue({
|
|
433
|
-
success: true,
|
|
434
|
-
boardId: "same-id",
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
await publishDocs(
|
|
438
|
-
{
|
|
439
|
-
docsDir: "./docs",
|
|
440
|
-
appUrl: "https://example.com",
|
|
441
|
-
boardId: "same-id",
|
|
442
|
-
},
|
|
443
|
-
mockOptions,
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
expect(saveValueToConfigSpy).not.toHaveBeenCalledWith("boardId", expect.anything());
|
|
447
|
-
});
|
|
448
|
-
|
|
449
|
-
test("should handle checkCacheSession failure", async () => {
|
|
450
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
451
|
-
getOfficialAccessTokenSpy.mockResolvedValue("valid-token");
|
|
452
|
-
mockBrokerClient.checkCacheSession.mockRejectedValue(new Error("Cache session failed"));
|
|
453
|
-
mockOptions.prompts.select.mockResolvedValue("default");
|
|
454
|
-
|
|
455
|
-
const result = await publishDocs(
|
|
456
|
-
{
|
|
457
|
-
docsDir: "./docs",
|
|
458
|
-
appUrl: "https://docsmith.aigne.io",
|
|
459
|
-
},
|
|
460
|
-
mockOptions,
|
|
461
|
-
);
|
|
462
|
-
|
|
463
|
-
expect(result.message).toBe("❌ Failed to publish docs: Cache session failed");
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
test("should handle publish failure", async () => {
|
|
467
|
-
mockPublishDocs.publishDocs.mockRejectedValue(new Error("Publish failed"));
|
|
468
|
-
|
|
469
|
-
const result = await publishDocs(
|
|
470
|
-
{
|
|
471
|
-
docsDir: "./docs",
|
|
472
|
-
appUrl: "https://example.com",
|
|
473
|
-
},
|
|
474
|
-
mockOptions,
|
|
475
|
-
);
|
|
476
|
-
|
|
477
|
-
expect(result.message).toBe("❌ Failed to publish docs: Publish failed");
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
test("should handle unsuccessful publish", async () => {
|
|
481
|
-
mockPublishDocs.publishDocs.mockResolvedValue({
|
|
482
|
-
success: false,
|
|
483
|
-
boardId: "failed-id",
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
const result = await publishDocs(
|
|
487
|
-
{
|
|
488
|
-
docsDir: "./docs",
|
|
489
|
-
appUrl: "https://example.com",
|
|
490
|
-
},
|
|
491
|
-
mockOptions,
|
|
492
|
-
);
|
|
493
|
-
|
|
494
|
-
expect(result).toEqual({});
|
|
495
|
-
});
|
|
496
|
-
|
|
497
|
-
test("should clean up temporary directory on success", async () => {
|
|
498
|
-
await publishDocs(
|
|
499
|
-
{
|
|
500
|
-
docsDir: "./docs",
|
|
501
|
-
appUrl: "https://example.com",
|
|
502
|
-
},
|
|
503
|
-
mockOptions,
|
|
504
|
-
);
|
|
505
|
-
|
|
506
|
-
expect(mockFsExtra.rm).toHaveBeenCalledWith(
|
|
507
|
-
expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
508
|
-
expect.objectContaining({
|
|
509
|
-
recursive: true,
|
|
510
|
-
force: true,
|
|
511
|
-
}),
|
|
512
|
-
);
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
test("should clean up temporary directory on error", async () => {
|
|
516
|
-
mockPublishDocs.publishDocs.mockRejectedValue(new Error("Test error"));
|
|
517
|
-
|
|
518
|
-
await publishDocs(
|
|
519
|
-
{
|
|
520
|
-
docsDir: "./docs",
|
|
521
|
-
appUrl: "https://example.com",
|
|
522
|
-
},
|
|
523
|
-
mockOptions,
|
|
524
|
-
);
|
|
525
|
-
|
|
526
|
-
expect(mockFsExtra.rm).toHaveBeenCalledWith(
|
|
527
|
-
expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
528
|
-
expect.objectContaining({
|
|
529
|
-
recursive: true,
|
|
530
|
-
force: true,
|
|
531
|
-
}),
|
|
532
|
-
);
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
// FILESYSTEM OPERATION TESTS
|
|
536
|
-
test("should set up temporary directory correctly", async () => {
|
|
537
|
-
await publishDocs(
|
|
538
|
-
{
|
|
539
|
-
docsDir: "./docs",
|
|
540
|
-
appUrl: "https://example.com",
|
|
541
|
-
},
|
|
542
|
-
mockOptions,
|
|
543
|
-
);
|
|
544
|
-
|
|
545
|
-
expect(ensureTmpDirSpy).toHaveBeenCalled();
|
|
546
|
-
expect(mockFsExtra.rm).toHaveBeenCalledWith(
|
|
547
|
-
expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
548
|
-
expect.objectContaining({ recursive: true, force: true }),
|
|
549
|
-
);
|
|
550
|
-
expect(mockFsExtra.mkdir).toHaveBeenCalledWith(
|
|
551
|
-
expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
552
|
-
expect.objectContaining({ recursive: true }),
|
|
553
|
-
);
|
|
554
|
-
expect(mockFsExtra.cp).toHaveBeenCalledWith(
|
|
555
|
-
"./docs",
|
|
556
|
-
expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
557
|
-
expect.objectContaining({ recursive: true }),
|
|
558
|
-
);
|
|
559
|
-
});
|
|
560
|
-
|
|
561
|
-
test("should call beforePublishHook with correct docsDir", async () => {
|
|
562
|
-
await publishDocs(
|
|
563
|
-
{
|
|
564
|
-
docsDir: "./docs",
|
|
565
|
-
appUrl: "https://example.com",
|
|
566
|
-
},
|
|
567
|
-
mockOptions,
|
|
568
|
-
);
|
|
569
|
-
|
|
570
|
-
expect(beforePublishHookSpy).toHaveBeenCalledWith({
|
|
571
|
-
docsDir: expect.stringContaining(".aigne/doc-smith/.tmp/docs"),
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
test("should set DOC_ROOT_DIR environment variable", async () => {
|
|
576
|
-
await publishDocs(
|
|
577
|
-
{
|
|
578
|
-
docsDir: "./docs",
|
|
579
|
-
appUrl: "https://example.com",
|
|
580
|
-
},
|
|
581
|
-
mockOptions,
|
|
582
|
-
);
|
|
583
|
-
|
|
584
|
-
expect(process.env.DOC_ROOT_DIR).toContain(".aigne/doc-smith/.tmp/docs");
|
|
585
|
-
});
|
|
586
|
-
|
|
587
|
-
// EDGE CASES
|
|
588
|
-
test("should handle missing config file", async () => {
|
|
589
|
-
loadConfigFromFileSpy.mockResolvedValue(null);
|
|
590
|
-
|
|
591
|
-
const result = await publishDocs(
|
|
592
|
-
{
|
|
593
|
-
docsDir: "./docs",
|
|
594
|
-
appUrl: "https://example.com",
|
|
595
|
-
},
|
|
596
|
-
mockOptions,
|
|
597
|
-
);
|
|
598
|
-
|
|
599
|
-
expect(result.message).toBe("✅ Documentation published successfully!");
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
test("should handle empty config", async () => {
|
|
603
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
604
|
-
|
|
605
|
-
await publishDocs(
|
|
606
|
-
{
|
|
607
|
-
docsDir: "./docs",
|
|
608
|
-
appUrl: "https://example.com",
|
|
609
|
-
},
|
|
610
|
-
mockOptions,
|
|
611
|
-
);
|
|
612
|
-
|
|
613
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
614
|
-
expect.objectContaining({
|
|
615
|
-
boardMeta: {
|
|
616
|
-
category: [],
|
|
617
|
-
githubRepoUrl: "https://github.com/user/repo",
|
|
618
|
-
commitSha: "",
|
|
619
|
-
languages: [],
|
|
620
|
-
},
|
|
621
|
-
}),
|
|
622
|
-
);
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
test("should skip platform selection when appUrl is in config", async () => {
|
|
626
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
627
|
-
appUrl: "https://existing.com",
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
await publishDocs(
|
|
631
|
-
{
|
|
632
|
-
docsDir: "./docs",
|
|
633
|
-
appUrl: "https://docsmith.aigne.io", // Default URL
|
|
634
|
-
},
|
|
635
|
-
mockOptions,
|
|
636
|
-
);
|
|
637
|
-
|
|
638
|
-
expect(mockOptions.prompts.select).not.toHaveBeenCalled();
|
|
639
|
-
});
|
|
640
|
-
|
|
641
|
-
// RESUME PREVIOUS WEBSITE SETUP TESTS
|
|
642
|
-
test("should show resume option when checkoutId exists in config", async () => {
|
|
643
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
644
|
-
checkoutId: "cached-checkout-123",
|
|
645
|
-
});
|
|
646
|
-
mockBrokerClient.checkCacheSession.mockResolvedValue({
|
|
647
|
-
sessionId: "cached-checkout-123",
|
|
648
|
-
paymentLink: "https://payment.example.com",
|
|
649
|
-
});
|
|
650
|
-
mockOptions.prompts.select.mockResolvedValue("default");
|
|
651
|
-
|
|
652
|
-
await publishDocs(
|
|
653
|
-
{
|
|
654
|
-
docsDir: "./docs",
|
|
655
|
-
appUrl: "https://docsmith.aigne.io",
|
|
656
|
-
},
|
|
657
|
-
mockOptions,
|
|
658
|
-
);
|
|
659
|
-
|
|
660
|
-
expect(mockOptions.prompts.select).toHaveBeenCalledWith(
|
|
661
|
-
expect.objectContaining({
|
|
662
|
-
message: "Select platform to publish your documents:",
|
|
663
|
-
choices: expect.arrayContaining([
|
|
664
|
-
expect.objectContaining({
|
|
665
|
-
name: expect.stringContaining("Resume previous website setup"),
|
|
666
|
-
value: "new-instance-continue",
|
|
667
|
-
}),
|
|
668
|
-
]),
|
|
669
|
-
}),
|
|
670
|
-
);
|
|
671
|
-
|
|
672
|
-
// Verify the exact text content
|
|
673
|
-
const selectCall = mockOptions.prompts.select.mock.calls[0][0];
|
|
674
|
-
const resumeChoice = selectCall.choices.find(
|
|
675
|
-
(choice) => choice.value === "new-instance-continue",
|
|
676
|
-
);
|
|
677
|
-
expect(resumeChoice.name).toContain("Resume previous website setup");
|
|
678
|
-
expect(resumeChoice.name).toContain("Already paid.");
|
|
679
|
-
expect(resumeChoice.name).toContain(
|
|
680
|
-
"Continue where you left off. Your payment has already been processed.",
|
|
681
|
-
);
|
|
682
|
-
});
|
|
683
|
-
|
|
684
|
-
test("should not show resume option when no checkoutId in config", async () => {
|
|
685
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
686
|
-
mockOptions.prompts.select.mockResolvedValue("default");
|
|
687
|
-
|
|
688
|
-
await publishDocs(
|
|
689
|
-
{
|
|
690
|
-
docsDir: "./docs",
|
|
691
|
-
appUrl: "https://docsmith.aigne.io",
|
|
692
|
-
},
|
|
693
|
-
mockOptions,
|
|
694
|
-
);
|
|
695
|
-
|
|
696
|
-
expect(mockOptions.prompts.select).toHaveBeenCalledWith(
|
|
697
|
-
expect.objectContaining({
|
|
698
|
-
message: "Select platform to publish your documents:",
|
|
699
|
-
choices: expect.not.arrayContaining([
|
|
700
|
-
expect.objectContaining({
|
|
701
|
-
value: "new-instance-continue",
|
|
702
|
-
}),
|
|
703
|
-
]),
|
|
704
|
-
}),
|
|
705
|
-
);
|
|
706
|
-
});
|
|
707
|
-
|
|
708
|
-
test("should handle resume previous website setup selection", async () => {
|
|
709
|
-
deploySpy.mockResolvedValue({
|
|
710
|
-
appUrl: "https://resumed.example.com",
|
|
711
|
-
token: "resume-token",
|
|
712
|
-
});
|
|
713
|
-
|
|
714
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
715
|
-
checkoutId: "cached-checkout-123",
|
|
716
|
-
paymentUrl: "https://payment.example.com",
|
|
717
|
-
});
|
|
718
|
-
mockBrokerClient.checkCacheSession.mockResolvedValue({
|
|
719
|
-
sessionId: "cached-checkout-123",
|
|
720
|
-
paymentLink: "https://payment.example.com",
|
|
721
|
-
});
|
|
722
|
-
mockOptions.prompts.select.mockResolvedValue("new-instance-continue");
|
|
723
|
-
|
|
724
|
-
const consoleSpy = spyOn(console, "log").mockImplementation(() => {});
|
|
725
|
-
|
|
726
|
-
await publishDocs(
|
|
727
|
-
{
|
|
728
|
-
docsDir: "./docs",
|
|
729
|
-
appUrl: "https://docsmith.aigne.io",
|
|
730
|
-
},
|
|
731
|
-
mockOptions,
|
|
732
|
-
);
|
|
733
|
-
|
|
734
|
-
expect(consoleSpy).toHaveBeenCalledWith("\nResuming your previous website setup...");
|
|
735
|
-
expect(deploySpy).toHaveBeenCalledWith("cached-checkout-123", "https://payment.example.com");
|
|
736
|
-
expect(getAccessTokenSpy).toHaveBeenCalledWith("https://resumed.example.com", "resume-token");
|
|
737
|
-
|
|
738
|
-
consoleSpy.mockRestore();
|
|
739
|
-
});
|
|
740
|
-
|
|
741
|
-
test("should handle URL validation edge cases", async () => {
|
|
742
|
-
loadConfigFromFileSpy.mockResolvedValue({});
|
|
743
|
-
mockOptions.prompts.select.mockResolvedValue("custom");
|
|
744
|
-
|
|
745
|
-
await publishDocs(
|
|
746
|
-
{
|
|
747
|
-
docsDir: "./docs",
|
|
748
|
-
appUrl: "https://docsmith.aigne.io",
|
|
749
|
-
},
|
|
750
|
-
mockOptions,
|
|
751
|
-
);
|
|
752
|
-
|
|
753
|
-
const validateFn = mockOptions.prompts.input.mock.calls[0][0].validate;
|
|
754
|
-
|
|
755
|
-
expect(validateFn("")).toBe("Please enter a valid URL");
|
|
756
|
-
expect(validateFn(" ")).toBe("Please enter a valid URL");
|
|
757
|
-
expect(validateFn("http://valid.com")).toBe(true);
|
|
758
|
-
expect(validateFn("https://valid.com")).toBe(true);
|
|
759
|
-
expect(validateFn("valid.com")).toBe(true);
|
|
760
|
-
});
|
|
761
|
-
|
|
762
|
-
test("should handle parameters priority correctly", async () => {
|
|
763
|
-
// Parameters > Config > Defaults
|
|
764
|
-
loadConfigFromFileSpy.mockResolvedValue({
|
|
765
|
-
projectName: "Config Name",
|
|
766
|
-
projectDesc: "Config Desc",
|
|
767
|
-
});
|
|
768
|
-
|
|
769
|
-
await publishDocs(
|
|
770
|
-
{
|
|
771
|
-
docsDir: "./docs",
|
|
772
|
-
appUrl: "https://example.com",
|
|
773
|
-
projectName: "Param Name", // Should override config
|
|
774
|
-
// projectDesc not provided - should use config
|
|
775
|
-
},
|
|
776
|
-
mockOptions,
|
|
777
|
-
);
|
|
778
|
-
|
|
779
|
-
expect(mockPublishDocs.publishDocs).toHaveBeenCalledWith(
|
|
780
|
-
expect.objectContaining({
|
|
781
|
-
boardName: "Param Name", // From parameter
|
|
782
|
-
boardDesc: "Config Desc", // From config
|
|
783
|
-
boardCover: "", // Default (empty)
|
|
784
|
-
}),
|
|
785
|
-
);
|
|
786
|
-
});
|
|
787
|
-
});
|