@aigne/doc-smith 0.8.12-beta.8 → 0.8.12
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 +15 -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,431 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from "bun:test";
|
|
2
|
-
import prefs from "../../../agents/prefs/index.mjs";
|
|
3
|
-
|
|
4
|
-
// Import internal utils for selective spying
|
|
5
|
-
import * as preferencesUtils from "../../../utils/preferences-utils.mjs";
|
|
6
|
-
|
|
7
|
-
describe("prefs", () => {
|
|
8
|
-
let mockOptions;
|
|
9
|
-
|
|
10
|
-
// Spies for internal utils
|
|
11
|
-
let readPreferencesSpy;
|
|
12
|
-
let removeRuleSpy;
|
|
13
|
-
let writePreferencesSpy;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
mock.restore();
|
|
17
|
-
|
|
18
|
-
mockOptions = {
|
|
19
|
-
prompts: {
|
|
20
|
-
checkbox: mock(async () => []),
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// Set up spies for internal utils
|
|
25
|
-
readPreferencesSpy = spyOn(preferencesUtils, "readPreferences").mockReturnValue({ rules: [] });
|
|
26
|
-
removeRuleSpy = spyOn(preferencesUtils, "removeRule").mockReturnValue(true);
|
|
27
|
-
writePreferencesSpy = spyOn(preferencesUtils, "writePreferences").mockImplementation(() => {});
|
|
28
|
-
|
|
29
|
-
// Clear prompts mock call history
|
|
30
|
-
mockOptions.prompts.checkbox.mockClear();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
afterEach(() => {
|
|
34
|
-
// Restore all spies
|
|
35
|
-
readPreferencesSpy?.mockRestore();
|
|
36
|
-
removeRuleSpy?.mockRestore();
|
|
37
|
-
writePreferencesSpy?.mockRestore();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("should return help message when no action specified", async () => {
|
|
41
|
-
const result = await prefs({}, mockOptions);
|
|
42
|
-
|
|
43
|
-
expect(result).toBeDefined();
|
|
44
|
-
expect(result.message).toBe("Please choose an action: --list, --remove, or --toggle.");
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
// LIST PREFERENCES TESTS
|
|
48
|
-
describe("list preferences", () => {
|
|
49
|
-
test("should return no preferences message when list is empty", async () => {
|
|
50
|
-
readPreferencesSpy.mockReturnValue({ rules: [] });
|
|
51
|
-
|
|
52
|
-
const result = await prefs({ list: true }, mockOptions);
|
|
53
|
-
|
|
54
|
-
expect(result.message).toBe("No saved preferences found.");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("should format preferences list with active rules", async () => {
|
|
58
|
-
const mockRules = [
|
|
59
|
-
{
|
|
60
|
-
id: "rule1",
|
|
61
|
-
scope: "global",
|
|
62
|
-
rule: "Use TypeScript for new files",
|
|
63
|
-
active: true,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: "rule2",
|
|
67
|
-
scope: "structure",
|
|
68
|
-
rule: "Organize imports alphabetically",
|
|
69
|
-
active: false,
|
|
70
|
-
},
|
|
71
|
-
];
|
|
72
|
-
|
|
73
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
74
|
-
|
|
75
|
-
const result = await prefs({ list: true }, mockOptions);
|
|
76
|
-
|
|
77
|
-
expect(result.message).toContain("# User Preferences");
|
|
78
|
-
expect(result.message).toContain("🟢 [global] rule1");
|
|
79
|
-
expect(result.message).toContain("⚪ [structure] rule2");
|
|
80
|
-
expect(result.message).toContain("Use TypeScript for new files");
|
|
81
|
-
expect(result.message).toContain("Organize imports alphabetically");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test("should include paths information when available", async () => {
|
|
85
|
-
const mockRules = [
|
|
86
|
-
{
|
|
87
|
-
id: "rule1",
|
|
88
|
-
scope: "document",
|
|
89
|
-
rule: "Add JSDoc comments",
|
|
90
|
-
active: true,
|
|
91
|
-
paths: ["src/**/*.js", "lib/**/*.ts"],
|
|
92
|
-
},
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
96
|
-
|
|
97
|
-
const result = await prefs({ list: true }, mockOptions);
|
|
98
|
-
|
|
99
|
-
expect(result.message).toContain("Paths: src/**/*.js, lib/**/*.ts");
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("should truncate long rules in list", async () => {
|
|
103
|
-
const longRule = "A".repeat(150); // Longer than 120 chars
|
|
104
|
-
const mockRules = [
|
|
105
|
-
{
|
|
106
|
-
id: "rule1",
|
|
107
|
-
scope: "global",
|
|
108
|
-
rule: longRule,
|
|
109
|
-
active: true,
|
|
110
|
-
},
|
|
111
|
-
];
|
|
112
|
-
|
|
113
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
114
|
-
|
|
115
|
-
const result = await prefs({ list: true }, mockOptions);
|
|
116
|
-
|
|
117
|
-
expect(result.message).toContain(`${"A".repeat(120)}...`);
|
|
118
|
-
expect(result.message).not.toContain(longRule);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
// REMOVE PREFERENCES TESTS
|
|
123
|
-
describe("remove preferences", () => {
|
|
124
|
-
test("should remove preferences by provided IDs", async () => {
|
|
125
|
-
removeRuleSpy.mockReturnValue(true);
|
|
126
|
-
|
|
127
|
-
const result = await prefs({ remove: true, id: ["rule1", "rule2"] }, mockOptions);
|
|
128
|
-
|
|
129
|
-
expect(removeRuleSpy).toHaveBeenCalledWith("rule1");
|
|
130
|
-
expect(removeRuleSpy).toHaveBeenCalledWith("rule2");
|
|
131
|
-
expect(result.message).toBe("Successfully removed 2 preferences.");
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("should handle partial failures when removing", async () => {
|
|
135
|
-
removeRuleSpy.mockReturnValueOnce(true).mockReturnValueOnce(false);
|
|
136
|
-
|
|
137
|
-
const result = await prefs({ remove: true, id: ["rule1", "rule2"] }, mockOptions);
|
|
138
|
-
|
|
139
|
-
expect(result.message).toBe("Successfully removed 1 preferences, 1 failed.");
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("should return message when no preferences exist for removal", async () => {
|
|
143
|
-
readPreferencesSpy.mockReturnValue({ rules: [] });
|
|
144
|
-
|
|
145
|
-
const result = await prefs({ remove: true }, mockOptions);
|
|
146
|
-
|
|
147
|
-
expect(result.message).toBe("No preferences available to remove.");
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test("should prompt for interactive selection when no IDs provided", async () => {
|
|
151
|
-
const mockRules = [
|
|
152
|
-
{
|
|
153
|
-
id: "rule1",
|
|
154
|
-
scope: "global",
|
|
155
|
-
rule: "Use TypeScript for new files",
|
|
156
|
-
active: true,
|
|
157
|
-
},
|
|
158
|
-
];
|
|
159
|
-
|
|
160
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
161
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
162
|
-
|
|
163
|
-
const result = await prefs({ remove: true }, mockOptions);
|
|
164
|
-
|
|
165
|
-
expect(mockOptions.prompts.checkbox).toHaveBeenCalledWith({
|
|
166
|
-
message: "Choose preferences to delete:",
|
|
167
|
-
choices: expect.arrayContaining([
|
|
168
|
-
expect.objectContaining({
|
|
169
|
-
name: expect.stringContaining("🟢 [global] Use TypeScript for new files"),
|
|
170
|
-
value: "rule1",
|
|
171
|
-
}),
|
|
172
|
-
]),
|
|
173
|
-
validate: expect.any(Function),
|
|
174
|
-
});
|
|
175
|
-
expect(result.message).toBe("Successfully removed 1 preferences.");
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
test("should handle validation error in interactive selection", async () => {
|
|
179
|
-
const mockRules = [
|
|
180
|
-
{
|
|
181
|
-
id: "rule1",
|
|
182
|
-
scope: "global",
|
|
183
|
-
rule: "Test rule",
|
|
184
|
-
active: true,
|
|
185
|
-
},
|
|
186
|
-
];
|
|
187
|
-
|
|
188
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
189
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
190
|
-
|
|
191
|
-
await prefs({ remove: true }, mockOptions);
|
|
192
|
-
|
|
193
|
-
const validateFn = mockOptions.prompts.checkbox.mock.calls[0][0].validate;
|
|
194
|
-
|
|
195
|
-
expect(validateFn([])).toBe("Please choose at least one preference to delete");
|
|
196
|
-
expect(validateFn(["rule1"])).toBe(true);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("should return message when no preferences selected", async () => {
|
|
200
|
-
const mockRules = [
|
|
201
|
-
{
|
|
202
|
-
id: "rule1",
|
|
203
|
-
scope: "global",
|
|
204
|
-
rule: "Test rule",
|
|
205
|
-
active: true,
|
|
206
|
-
},
|
|
207
|
-
];
|
|
208
|
-
|
|
209
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
210
|
-
mockOptions.prompts.checkbox.mockResolvedValue([]);
|
|
211
|
-
|
|
212
|
-
const result = await prefs({ remove: true }, mockOptions);
|
|
213
|
-
|
|
214
|
-
expect(result.message).toBe("No preferences selected for deletion.");
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test("should truncate long rules in interactive choices", async () => {
|
|
218
|
-
const longRule = "A".repeat(80); // Longer than 60 chars
|
|
219
|
-
const mockRules = [
|
|
220
|
-
{
|
|
221
|
-
id: "rule1",
|
|
222
|
-
scope: "global",
|
|
223
|
-
rule: longRule,
|
|
224
|
-
active: true,
|
|
225
|
-
},
|
|
226
|
-
];
|
|
227
|
-
|
|
228
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
229
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
230
|
-
|
|
231
|
-
await prefs({ remove: true }, mockOptions);
|
|
232
|
-
|
|
233
|
-
const choices = mockOptions.prompts.checkbox.mock.calls[0][0].choices;
|
|
234
|
-
expect(choices[0].name).toContain(`${"A".repeat(60)}...`);
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// TOGGLE PREFERENCES TESTS
|
|
239
|
-
describe("toggle preferences", () => {
|
|
240
|
-
test("should toggle preferences by provided IDs", async () => {
|
|
241
|
-
const mockRules = [
|
|
242
|
-
{
|
|
243
|
-
id: "rule1",
|
|
244
|
-
scope: "global",
|
|
245
|
-
rule: "Test rule 1",
|
|
246
|
-
active: true,
|
|
247
|
-
},
|
|
248
|
-
{
|
|
249
|
-
id: "rule2",
|
|
250
|
-
scope: "structure",
|
|
251
|
-
rule: "Test rule 2",
|
|
252
|
-
active: false,
|
|
253
|
-
},
|
|
254
|
-
];
|
|
255
|
-
|
|
256
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
257
|
-
|
|
258
|
-
const result = await prefs({ toggle: true, id: ["rule1", "rule2"] }, mockOptions);
|
|
259
|
-
|
|
260
|
-
expect(writePreferencesSpy).toHaveBeenCalled();
|
|
261
|
-
expect(result.message).toBe("Successfully toggled 2 preferences.");
|
|
262
|
-
|
|
263
|
-
// Check that the active status was toggled
|
|
264
|
-
const writtenPrefs = writePreferencesSpy.mock.calls[0][0];
|
|
265
|
-
expect(writtenPrefs.rules[0].active).toBe(false); // was true, now false
|
|
266
|
-
expect(writtenPrefs.rules[1].active).toBe(true); // was false, now true
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test("should handle non-existent rule IDs", async () => {
|
|
270
|
-
const mockRules = [
|
|
271
|
-
{
|
|
272
|
-
id: "rule1",
|
|
273
|
-
scope: "global",
|
|
274
|
-
rule: "Test rule",
|
|
275
|
-
active: true,
|
|
276
|
-
},
|
|
277
|
-
];
|
|
278
|
-
|
|
279
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
280
|
-
|
|
281
|
-
const result = await prefs({ toggle: true, id: ["rule1", "nonexistent"] }, mockOptions);
|
|
282
|
-
|
|
283
|
-
expect(result.message).toBe("Successfully toggled 1 preferences, 1 failed.");
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
test("should return message when no preferences exist for toggling", async () => {
|
|
287
|
-
readPreferencesSpy.mockReturnValue({ rules: [] });
|
|
288
|
-
|
|
289
|
-
const result = await prefs({ toggle: true }, mockOptions);
|
|
290
|
-
|
|
291
|
-
expect(result.message).toBe("No preferences available to toggle.");
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
test("should prompt for interactive selection when no IDs provided", async () => {
|
|
295
|
-
const mockRules = [
|
|
296
|
-
{
|
|
297
|
-
id: "rule1",
|
|
298
|
-
scope: "global",
|
|
299
|
-
rule: "Use TypeScript",
|
|
300
|
-
active: false,
|
|
301
|
-
},
|
|
302
|
-
];
|
|
303
|
-
|
|
304
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
305
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
306
|
-
|
|
307
|
-
const result = await prefs({ toggle: true }, mockOptions);
|
|
308
|
-
|
|
309
|
-
expect(mockOptions.prompts.checkbox).toHaveBeenCalledWith({
|
|
310
|
-
message: "Choose preferences to enable/disable:",
|
|
311
|
-
choices: expect.arrayContaining([
|
|
312
|
-
expect.objectContaining({
|
|
313
|
-
name: expect.stringContaining("⚪ [global] Use TypeScript"),
|
|
314
|
-
value: "rule1",
|
|
315
|
-
}),
|
|
316
|
-
]),
|
|
317
|
-
validate: expect.any(Function),
|
|
318
|
-
});
|
|
319
|
-
expect(result.message).toBe("Successfully toggled 1 preferences.");
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
test("should handle validation error in toggle interactive selection", async () => {
|
|
323
|
-
const mockRules = [
|
|
324
|
-
{
|
|
325
|
-
id: "rule1",
|
|
326
|
-
scope: "global",
|
|
327
|
-
rule: "Test rule",
|
|
328
|
-
active: true,
|
|
329
|
-
},
|
|
330
|
-
];
|
|
331
|
-
|
|
332
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
333
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
334
|
-
|
|
335
|
-
await prefs({ toggle: true }, mockOptions);
|
|
336
|
-
|
|
337
|
-
const validateFn = mockOptions.prompts.checkbox.mock.calls[0][0].validate;
|
|
338
|
-
|
|
339
|
-
expect(validateFn([])).toBe("Please choose at least one preference to toggle");
|
|
340
|
-
expect(validateFn(["rule1"])).toBe(true);
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
test("should return message when no preferences selected for toggling", async () => {
|
|
344
|
-
const mockRules = [
|
|
345
|
-
{
|
|
346
|
-
id: "rule1",
|
|
347
|
-
scope: "global",
|
|
348
|
-
rule: "Test rule",
|
|
349
|
-
active: true,
|
|
350
|
-
},
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
354
|
-
mockOptions.prompts.checkbox.mockResolvedValue([]);
|
|
355
|
-
|
|
356
|
-
const result = await prefs({ toggle: true }, mockOptions);
|
|
357
|
-
|
|
358
|
-
expect(result.message).toBe("No preferences selected to toggle.");
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
// EDGE CASES
|
|
363
|
-
test("should handle empty ID array", async () => {
|
|
364
|
-
await prefs({ remove: true, id: [] }, mockOptions);
|
|
365
|
-
|
|
366
|
-
expect(readPreferencesSpy).toHaveBeenCalled();
|
|
367
|
-
// Should fall back to interactive selection
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
test("should handle null ID array", async () => {
|
|
371
|
-
await prefs({ toggle: true, id: null }, mockOptions);
|
|
372
|
-
|
|
373
|
-
expect(readPreferencesSpy).toHaveBeenCalled();
|
|
374
|
-
// Should fall back to interactive selection
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
test("should handle mixed success/failure in operations", async () => {
|
|
378
|
-
removeRuleSpy.mockReturnValueOnce(true).mockReturnValueOnce(false).mockReturnValueOnce(true);
|
|
379
|
-
|
|
380
|
-
const result = await prefs({ remove: true, id: ["rule1", "rule2", "rule3"] }, mockOptions);
|
|
381
|
-
|
|
382
|
-
expect(result.message).toBe("Successfully removed 2 preferences, 1 failed.");
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
test("should handle all operations with same rule format", async () => {
|
|
386
|
-
const mockRules = [
|
|
387
|
-
{
|
|
388
|
-
id: "rule1",
|
|
389
|
-
scope: "translation",
|
|
390
|
-
rule: "Translate technical terms consistently",
|
|
391
|
-
active: true,
|
|
392
|
-
paths: ["docs/**/*.md"],
|
|
393
|
-
},
|
|
394
|
-
];
|
|
395
|
-
|
|
396
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
397
|
-
|
|
398
|
-
// Test list
|
|
399
|
-
const listResult = await prefs({ list: true }, mockOptions);
|
|
400
|
-
expect(listResult.message).toContain("🟢 [translation] rule1");
|
|
401
|
-
expect(listResult.message).toContain("Paths: docs/**/*.md");
|
|
402
|
-
|
|
403
|
-
// Test remove
|
|
404
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
405
|
-
const removeResult = await prefs({ remove: true }, mockOptions);
|
|
406
|
-
expect(removeResult.message).toContain("Successfully removed 1 preferences.");
|
|
407
|
-
|
|
408
|
-
// Test toggle
|
|
409
|
-
mockOptions.prompts.checkbox.mockResolvedValue(["rule1"]);
|
|
410
|
-
const toggleResult = await prefs({ toggle: true }, mockOptions);
|
|
411
|
-
expect(toggleResult.message).toContain("Successfully toggled 1 preferences.");
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
test("should handle checkbox returning null", async () => {
|
|
415
|
-
const mockRules = [
|
|
416
|
-
{
|
|
417
|
-
id: "rule1",
|
|
418
|
-
scope: "global",
|
|
419
|
-
rule: "Test rule",
|
|
420
|
-
active: true,
|
|
421
|
-
},
|
|
422
|
-
];
|
|
423
|
-
|
|
424
|
-
readPreferencesSpy.mockReturnValue({ rules: mockRules });
|
|
425
|
-
mockOptions.prompts.checkbox.mockResolvedValue(null);
|
|
426
|
-
|
|
427
|
-
const result = await prefs({ remove: true }, mockOptions);
|
|
428
|
-
|
|
429
|
-
expect(result.message).toBe("No preferences selected for deletion.");
|
|
430
|
-
});
|
|
431
|
-
});
|