@aigne/doc-smith 0.8.12-beta.7 → 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 +25 -0
- package/agents/clear/choose-contents.mjs +14 -1
- package/agents/clear/clear-media-description.mjs +129 -0
- package/agents/clear/index.yaml +3 -1
- package/agents/evaluate/code-snippet.mjs +28 -24
- package/agents/evaluate/document-structure.yaml +0 -4
- package/agents/evaluate/document.yaml +1 -5
- package/agents/generate/index.yaml +1 -0
- package/agents/init/index.mjs +10 -0
- package/agents/media/batch-generate-media-description.yaml +44 -0
- package/agents/media/generate-media-description.yaml +47 -0
- package/agents/media/load-media-description.mjs +238 -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/index.yaml +1 -0
- package/agents/update/update-document-detail.yaml +3 -1
- package/agents/utils/load-sources.mjs +103 -53
- package/agents/utils/update-branding.mjs +69 -0
- package/aigne.yaml +6 -0
- package/assets/report-template/report.html +34 -34
- package/package.json +17 -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/evaluate/document-structure.md +6 -7
- package/prompts/evaluate/document.md +16 -25
- package/prompts/media/media-description/system-prompt.md +35 -0
- package/prompts/media/media-description/user-prompt.md +8 -0
- package/prompts/structure/update/user-prompt.md +0 -4
- package/utils/constants/index.mjs +0 -107
- package/utils/file-utils.mjs +86 -0
- 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/output/structure-plan.json +0 -162
- package/.aigne/doc-smith/preferences.yml +0 -97
- package/.aigne/doc-smith/upload-cache.yaml +0 -1893
- 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 -179
- 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 -96
- package/docs/configuration.md +0 -96
- package/docs/configuration.zh-TW.md +0 -96
- package/docs/configuration.zh.md +0 -96
- package/docs/getting-started.ja.md +0 -88
- package/docs/getting-started.md +0 -88
- package/docs/getting-started.zh-TW.md +0 -88
- package/docs/getting-started.zh.md +0 -88
- package/docs/guides-cleaning-up.ja.md +0 -51
- package/docs/guides-cleaning-up.md +0 -51
- 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 -66
- 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 -151
- 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 -85
- 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 -48
- 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 -78
- 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 -95
- 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 -77
- 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 -255
- package/docs/release-notes.zh-TW.md +0 -255
- package/docs/release-notes.zh.md +0 -255
- package/media.md +0 -19
- 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,364 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { stringify } from "yaml";
|
|
3
|
-
import formatDocumentStructure from "../../../agents/utils/format-document-structure.mjs";
|
|
4
|
-
|
|
5
|
-
describe("format-document-structure", () => {
|
|
6
|
-
// EDGE CASE TESTS
|
|
7
|
-
test("should handle when both documentStructure and originalDocumentStructure are null", async () => {
|
|
8
|
-
const result = await formatDocumentStructure({
|
|
9
|
-
documentStructure: null,
|
|
10
|
-
originalDocumentStructure: null,
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
expect(result).toEqual({
|
|
14
|
-
documentStructureYaml: "",
|
|
15
|
-
documentStructure: [],
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("should handle when both documentStructure and originalDocumentStructure are undefined", async () => {
|
|
20
|
-
const result = await formatDocumentStructure({
|
|
21
|
-
documentStructure: undefined,
|
|
22
|
-
originalDocumentStructure: undefined,
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
expect(result).toEqual({
|
|
26
|
-
documentStructureYaml: "",
|
|
27
|
-
documentStructure: [],
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("should handle when both parameters are missing", async () => {
|
|
32
|
-
const result = await formatDocumentStructure({});
|
|
33
|
-
|
|
34
|
-
expect(result).toEqual({
|
|
35
|
-
documentStructureYaml: "",
|
|
36
|
-
documentStructure: [],
|
|
37
|
-
});
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("should use originalDocumentStructure when documentStructure is null", async () => {
|
|
41
|
-
const originalDocumentStructure = [
|
|
42
|
-
{
|
|
43
|
-
title: "Original Document",
|
|
44
|
-
path: "/original",
|
|
45
|
-
parentId: null,
|
|
46
|
-
description: "From original structure",
|
|
47
|
-
extraField: "should be filtered out",
|
|
48
|
-
},
|
|
49
|
-
];
|
|
50
|
-
|
|
51
|
-
const result = await formatDocumentStructure({
|
|
52
|
-
documentStructure: null,
|
|
53
|
-
originalDocumentStructure,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const expectedData = [
|
|
57
|
-
{
|
|
58
|
-
title: "Original Document",
|
|
59
|
-
path: "/original",
|
|
60
|
-
parentId: null,
|
|
61
|
-
description: "From original structure",
|
|
62
|
-
},
|
|
63
|
-
];
|
|
64
|
-
const expectedYaml = stringify(expectedData, {
|
|
65
|
-
indent: 2,
|
|
66
|
-
lineWidth: 120,
|
|
67
|
-
minContentWidth: 20,
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
71
|
-
expect(result.documentStructure).toBe(null);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test("should use originalDocumentStructure when documentStructure is undefined", async () => {
|
|
75
|
-
const originalDocumentStructure = [
|
|
76
|
-
{
|
|
77
|
-
title: "Fallback Document",
|
|
78
|
-
path: "/fallback",
|
|
79
|
-
parentId: "parent-id",
|
|
80
|
-
description: "Fallback to original",
|
|
81
|
-
},
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
const result = await formatDocumentStructure({
|
|
85
|
-
originalDocumentStructure,
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
const expectedData = [
|
|
89
|
-
{
|
|
90
|
-
title: "Fallback Document",
|
|
91
|
-
path: "/fallback",
|
|
92
|
-
parentId: "parent-id",
|
|
93
|
-
description: "Fallback to original",
|
|
94
|
-
},
|
|
95
|
-
];
|
|
96
|
-
const expectedYaml = stringify(expectedData, {
|
|
97
|
-
indent: 2,
|
|
98
|
-
lineWidth: 120,
|
|
99
|
-
minContentWidth: 20,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
103
|
-
expect(result.documentStructure).toBe(undefined);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// BASIC FUNCTIONALITY TESTS
|
|
107
|
-
test("should format empty documentation structure", async () => {
|
|
108
|
-
const result = await formatDocumentStructure({
|
|
109
|
-
documentStructure: [],
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
const expectedYaml = stringify([], {
|
|
113
|
-
indent: 2,
|
|
114
|
-
lineWidth: 120,
|
|
115
|
-
minContentWidth: 20,
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
expect(result).toEqual({
|
|
119
|
-
documentStructureYaml: expectedYaml,
|
|
120
|
-
documentStructure: [],
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("should format single item documentation structure", async () => {
|
|
125
|
-
const documentStructure = [
|
|
126
|
-
{
|
|
127
|
-
title: "Getting Started",
|
|
128
|
-
path: "/getting-started",
|
|
129
|
-
parentId: null,
|
|
130
|
-
description: "Introduction to the platform",
|
|
131
|
-
extraField: "should be ignored",
|
|
132
|
-
},
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
136
|
-
|
|
137
|
-
const expectedData = [
|
|
138
|
-
{
|
|
139
|
-
title: "Getting Started",
|
|
140
|
-
path: "/getting-started",
|
|
141
|
-
parentId: null,
|
|
142
|
-
description: "Introduction to the platform",
|
|
143
|
-
},
|
|
144
|
-
];
|
|
145
|
-
const expectedYaml = stringify(expectedData, {
|
|
146
|
-
indent: 2,
|
|
147
|
-
lineWidth: 120,
|
|
148
|
-
minContentWidth: 20,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
expect(result.documentStructure).toEqual(documentStructure);
|
|
152
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test("should format multiple items documentation structure", async () => {
|
|
156
|
-
const documentStructure = [
|
|
157
|
-
{
|
|
158
|
-
title: "API Reference",
|
|
159
|
-
path: "/api",
|
|
160
|
-
parentId: null,
|
|
161
|
-
description: "Complete API documentation",
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
title: "Authentication",
|
|
165
|
-
path: "/api/auth",
|
|
166
|
-
parentId: "/api",
|
|
167
|
-
description: "Authentication endpoints",
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
title: "Users",
|
|
171
|
-
path: "/api/users",
|
|
172
|
-
parentId: "/api",
|
|
173
|
-
description: "User management endpoints",
|
|
174
|
-
},
|
|
175
|
-
];
|
|
176
|
-
|
|
177
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
178
|
-
|
|
179
|
-
const expectedData = [
|
|
180
|
-
{
|
|
181
|
-
title: "API Reference",
|
|
182
|
-
path: "/api",
|
|
183
|
-
parentId: null,
|
|
184
|
-
description: "Complete API documentation",
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
title: "Authentication",
|
|
188
|
-
path: "/api/auth",
|
|
189
|
-
parentId: "/api",
|
|
190
|
-
description: "Authentication endpoints",
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
title: "Users",
|
|
194
|
-
path: "/api/users",
|
|
195
|
-
parentId: "/api",
|
|
196
|
-
description: "User management endpoints",
|
|
197
|
-
},
|
|
198
|
-
];
|
|
199
|
-
const expectedYaml = stringify(expectedData, {
|
|
200
|
-
indent: 2,
|
|
201
|
-
lineWidth: 120,
|
|
202
|
-
minContentWidth: 20,
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
expect(result.documentStructure).toEqual(documentStructure);
|
|
206
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
// FIELD EXTRACTION TESTS
|
|
210
|
-
test("should extract only required fields", async () => {
|
|
211
|
-
const documentStructure = [
|
|
212
|
-
{
|
|
213
|
-
title: "Test Document",
|
|
214
|
-
path: "/test",
|
|
215
|
-
parentId: "parent-123",
|
|
216
|
-
description: "Test description",
|
|
217
|
-
// Extra fields that should be filtered out
|
|
218
|
-
id: "doc-123",
|
|
219
|
-
content: "Document content",
|
|
220
|
-
metadata: { tags: ["test"] },
|
|
221
|
-
lastModified: "2024-01-01",
|
|
222
|
-
author: "John Doe",
|
|
223
|
-
},
|
|
224
|
-
];
|
|
225
|
-
|
|
226
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
227
|
-
|
|
228
|
-
const expectedData = [
|
|
229
|
-
{
|
|
230
|
-
title: "Test Document",
|
|
231
|
-
path: "/test",
|
|
232
|
-
parentId: "parent-123",
|
|
233
|
-
description: "Test description",
|
|
234
|
-
},
|
|
235
|
-
];
|
|
236
|
-
const expectedYaml = stringify(expectedData, {
|
|
237
|
-
indent: 2,
|
|
238
|
-
lineWidth: 120,
|
|
239
|
-
minContentWidth: 20,
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
243
|
-
// Verify extra fields are not in the YAML output
|
|
244
|
-
expect(result.documentStructureYaml).not.toContain("doc-123");
|
|
245
|
-
expect(result.documentStructureYaml).not.toContain("Document content");
|
|
246
|
-
expect(result.documentStructureYaml).not.toContain("John Doe");
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
test("should handle items with missing optional fields", async () => {
|
|
250
|
-
const documentStructure = [
|
|
251
|
-
{
|
|
252
|
-
title: "Required Title",
|
|
253
|
-
path: "/required-path",
|
|
254
|
-
// parentId and description are missing
|
|
255
|
-
},
|
|
256
|
-
];
|
|
257
|
-
|
|
258
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
259
|
-
|
|
260
|
-
const expectedData = [
|
|
261
|
-
{
|
|
262
|
-
title: "Required Title",
|
|
263
|
-
path: "/required-path",
|
|
264
|
-
parentId: undefined,
|
|
265
|
-
description: undefined,
|
|
266
|
-
},
|
|
267
|
-
];
|
|
268
|
-
const expectedYaml = stringify(expectedData, {
|
|
269
|
-
indent: 2,
|
|
270
|
-
lineWidth: 120,
|
|
271
|
-
minContentWidth: 20,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
test("should preserve null and undefined values", async () => {
|
|
278
|
-
const documentStructure = [
|
|
279
|
-
{
|
|
280
|
-
title: "Test Item",
|
|
281
|
-
path: "/test",
|
|
282
|
-
parentId: null,
|
|
283
|
-
description: undefined,
|
|
284
|
-
},
|
|
285
|
-
];
|
|
286
|
-
|
|
287
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
288
|
-
|
|
289
|
-
const expectedData = [
|
|
290
|
-
{
|
|
291
|
-
title: "Test Item",
|
|
292
|
-
path: "/test",
|
|
293
|
-
parentId: null,
|
|
294
|
-
description: undefined,
|
|
295
|
-
},
|
|
296
|
-
];
|
|
297
|
-
const expectedYaml = stringify(expectedData, {
|
|
298
|
-
indent: 2,
|
|
299
|
-
lineWidth: 120,
|
|
300
|
-
minContentWidth: 20,
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
expect(result.documentStructureYaml).toBe(expectedYaml);
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
test("should handle items with special characters", async () => {
|
|
307
|
-
const documentStructure = [
|
|
308
|
-
{
|
|
309
|
-
title: "Special Characters: @#$%^&*()",
|
|
310
|
-
path: "/special-chars-test",
|
|
311
|
-
parentId: null,
|
|
312
|
-
description: 'Testing with 中文, émojis 🚀, and "quotes"',
|
|
313
|
-
},
|
|
314
|
-
];
|
|
315
|
-
|
|
316
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
317
|
-
|
|
318
|
-
// Since YAML is mocked, just verify the function runs without error
|
|
319
|
-
// and returns a structure with the expected properties
|
|
320
|
-
expect(result.documentStructureYaml).toBeDefined();
|
|
321
|
-
expect(result.documentStructure).toEqual(documentStructure);
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
test("should return both yaml string and original documentation structure", async () => {
|
|
325
|
-
const documentStructure = [
|
|
326
|
-
{
|
|
327
|
-
title: "Return Test",
|
|
328
|
-
path: "/return-test",
|
|
329
|
-
parentId: null,
|
|
330
|
-
description: "Testing return values",
|
|
331
|
-
},
|
|
332
|
-
];
|
|
333
|
-
|
|
334
|
-
const result = await formatDocumentStructure({ documentStructure });
|
|
335
|
-
|
|
336
|
-
expect(result).toHaveProperty("documentStructureYaml");
|
|
337
|
-
expect(result).toHaveProperty("documentStructure");
|
|
338
|
-
expect(typeof result.documentStructureYaml).toBe("string");
|
|
339
|
-
expect(result.documentStructure).toBe(documentStructure); // Should be the same reference
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
test("should preserve original documentation structure unchanged", async () => {
|
|
343
|
-
const originalDocumentStructure = [
|
|
344
|
-
{
|
|
345
|
-
title: "Original",
|
|
346
|
-
path: "/original",
|
|
347
|
-
parentId: null,
|
|
348
|
-
description: "Original description",
|
|
349
|
-
extraField: "should remain",
|
|
350
|
-
},
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
const result = await formatDocumentStructure({
|
|
354
|
-
documentStructure: originalDocumentStructure,
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// Original should be unchanged
|
|
358
|
-
expect(originalDocumentStructure[0]).toHaveProperty("extraField");
|
|
359
|
-
expect(originalDocumentStructure[0].extraField).toBe("should remain");
|
|
360
|
-
|
|
361
|
-
// Return value should reference the same object
|
|
362
|
-
expect(result.documentStructure).toBe(originalDocumentStructure);
|
|
363
|
-
});
|
|
364
|
-
});
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
-
import * as fsPromises from "node:fs/promises";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import fs from "../../../agents/utils/fs.mjs";
|
|
5
|
-
|
|
6
|
-
describe("fs utility", () => {
|
|
7
|
-
let readFileSpy;
|
|
8
|
-
let writeFileSpy;
|
|
9
|
-
let mkdirSpy;
|
|
10
|
-
let rmSpy;
|
|
11
|
-
let readdirSpy;
|
|
12
|
-
let joinSpy;
|
|
13
|
-
let dirnameSpy;
|
|
14
|
-
|
|
15
|
-
beforeEach(() => {
|
|
16
|
-
// Spy on fs/promises methods
|
|
17
|
-
readFileSpy = spyOn(fsPromises, "readFile").mockResolvedValue("mocked file content");
|
|
18
|
-
writeFileSpy = spyOn(fsPromises, "writeFile").mockResolvedValue();
|
|
19
|
-
mkdirSpy = spyOn(fsPromises, "mkdir").mockResolvedValue();
|
|
20
|
-
rmSpy = spyOn(fsPromises, "rm").mockResolvedValue();
|
|
21
|
-
readdirSpy = spyOn(fsPromises, "readdir").mockResolvedValue([
|
|
22
|
-
{ name: "file1.txt", parentPath: "/test/root", isDirectory: () => false },
|
|
23
|
-
{ name: "subdir", parentPath: "/test/root", isDirectory: () => true },
|
|
24
|
-
]);
|
|
25
|
-
|
|
26
|
-
// Spy on path methods
|
|
27
|
-
joinSpy = spyOn(path, "join").mockImplementation((...paths) => paths.join("/"));
|
|
28
|
-
dirnameSpy = spyOn(path, "dirname").mockImplementation(
|
|
29
|
-
(path) => path.split("/").slice(0, -1).join("/") || "/",
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
afterEach(() => {
|
|
34
|
-
// Restore all spies
|
|
35
|
-
readFileSpy?.mockRestore();
|
|
36
|
-
writeFileSpy?.mockRestore();
|
|
37
|
-
mkdirSpy?.mockRestore();
|
|
38
|
-
rmSpy?.mockRestore();
|
|
39
|
-
readdirSpy?.mockRestore();
|
|
40
|
-
joinSpy?.mockRestore();
|
|
41
|
-
dirnameSpy?.mockRestore();
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// ERROR HANDLING TESTS
|
|
45
|
-
test("should throw error when rootDir is not specified", async () => {
|
|
46
|
-
await expect(
|
|
47
|
-
fs({
|
|
48
|
-
action: "read_file",
|
|
49
|
-
path: "test.txt",
|
|
50
|
-
}),
|
|
51
|
-
).rejects.toThrow("Root directory is not specified");
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("should throw error when rootDir is empty string", async () => {
|
|
55
|
-
await expect(
|
|
56
|
-
fs({
|
|
57
|
-
rootDir: "",
|
|
58
|
-
action: "read_file",
|
|
59
|
-
path: "test.txt",
|
|
60
|
-
}),
|
|
61
|
-
).rejects.toThrow("Root directory is not specified");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// READ_FILE ACTION TESTS
|
|
65
|
-
test("should read file successfully", async () => {
|
|
66
|
-
readFileSpy.mockResolvedValue("test file content");
|
|
67
|
-
|
|
68
|
-
const result = await fs({
|
|
69
|
-
rootDir: "/test/root",
|
|
70
|
-
action: "read_file",
|
|
71
|
-
path: "test.txt",
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root", "test.txt");
|
|
75
|
-
expect(readFileSpy).toHaveBeenCalledWith("/test/root/test.txt", "utf-8");
|
|
76
|
-
expect(result).toEqual({
|
|
77
|
-
status: "ok",
|
|
78
|
-
path: "/test/root/test.txt",
|
|
79
|
-
content: "test file content",
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test("should handle read file with nested path", async () => {
|
|
84
|
-
await fs({
|
|
85
|
-
rootDir: "/project",
|
|
86
|
-
action: "read_file",
|
|
87
|
-
path: "src/components/Button.tsx",
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
expect(joinSpy).toHaveBeenCalledWith("/project", "src/components/Button.tsx");
|
|
91
|
-
expect(readFileSpy).toHaveBeenCalledWith("/project/src/components/Button.tsx", "utf-8");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// WRITE_FILE ACTION TESTS
|
|
95
|
-
test("should write file successfully", async () => {
|
|
96
|
-
const result = await fs({
|
|
97
|
-
rootDir: "/test/root",
|
|
98
|
-
action: "write_file",
|
|
99
|
-
path: "output.txt",
|
|
100
|
-
content: "Hello, world!",
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
expect(dirnameSpy).toHaveBeenCalledWith("/test/root/output.txt");
|
|
104
|
-
expect(mkdirSpy).toHaveBeenCalledWith("/test/root", { recursive: true });
|
|
105
|
-
expect(writeFileSpy).toHaveBeenCalledWith("/test/root/output.txt", "Hello, world!");
|
|
106
|
-
expect(result).toEqual({
|
|
107
|
-
status: "ok",
|
|
108
|
-
path: "/test/root/output.txt",
|
|
109
|
-
content: "Hello, world!",
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("should write file with empty content when content is not provided", async () => {
|
|
114
|
-
const result = await fs({
|
|
115
|
-
rootDir: "/test/root",
|
|
116
|
-
action: "write_file",
|
|
117
|
-
path: "empty.txt",
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
expect(writeFileSpy).toHaveBeenCalledWith("/test/root/empty.txt", "");
|
|
121
|
-
expect(result.content).toBeUndefined(); // The function returns the original content parameter
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test("should create directories recursively when writing file", async () => {
|
|
125
|
-
dirnameSpy.mockReturnValue("/test/root/deep/nested");
|
|
126
|
-
|
|
127
|
-
await fs({
|
|
128
|
-
rootDir: "/test/root",
|
|
129
|
-
action: "write_file",
|
|
130
|
-
path: "deep/nested/file.txt",
|
|
131
|
-
content: "nested content",
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
expect(mkdirSpy).toHaveBeenCalledWith("/test/root/deep/nested", {
|
|
135
|
-
recursive: true,
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// DELETE_FILE ACTION TESTS
|
|
140
|
-
test("should delete file successfully", async () => {
|
|
141
|
-
const result = await fs({
|
|
142
|
-
rootDir: "/test/root",
|
|
143
|
-
action: "delete_file",
|
|
144
|
-
path: "to-delete.txt",
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root", "to-delete.txt");
|
|
148
|
-
expect(rmSpy).toHaveBeenCalledWith("/test/root/to-delete.txt", {
|
|
149
|
-
recursive: true,
|
|
150
|
-
force: true,
|
|
151
|
-
});
|
|
152
|
-
expect(result).toEqual({
|
|
153
|
-
status: "ok",
|
|
154
|
-
path: "/test/root/to-delete.txt",
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("should delete directory recursively", async () => {
|
|
159
|
-
await fs({
|
|
160
|
-
rootDir: "/project",
|
|
161
|
-
action: "delete_file",
|
|
162
|
-
path: "build",
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
expect(rmSpy).toHaveBeenCalledWith("/project/build", {
|
|
166
|
-
recursive: true,
|
|
167
|
-
force: true,
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
// LIST_DIRECTORY ACTION TESTS
|
|
172
|
-
test("should list directory entries successfully", async () => {
|
|
173
|
-
const result = await fs({
|
|
174
|
-
rootDir: "/test/root",
|
|
175
|
-
action: "list_directory",
|
|
176
|
-
path: "src",
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root", "src");
|
|
180
|
-
expect(readdirSpy).toHaveBeenCalledWith("/test/root/src", { withFileTypes: true });
|
|
181
|
-
expect(result).toEqual({
|
|
182
|
-
status: "ok",
|
|
183
|
-
entries: [
|
|
184
|
-
{ path: "/test/root/file1.txt", isDirectory: false },
|
|
185
|
-
{ path: "/test/root/subdir", isDirectory: true },
|
|
186
|
-
],
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
test("should handle empty directory listing", async () => {
|
|
191
|
-
readdirSpy.mockResolvedValue([]);
|
|
192
|
-
|
|
193
|
-
const result = await fs({
|
|
194
|
-
rootDir: "/test/root",
|
|
195
|
-
action: "list_directory",
|
|
196
|
-
path: "empty-dir",
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
expect(result.entries).toEqual([]);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
// PATH HANDLING TESTS
|
|
203
|
-
test("should handle root directory with trailing slash", async () => {
|
|
204
|
-
await fs({
|
|
205
|
-
rootDir: "/test/root/",
|
|
206
|
-
action: "read_file",
|
|
207
|
-
path: "file.txt",
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root/", "file.txt");
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
test("should handle path with leading slash", async () => {
|
|
214
|
-
await fs({
|
|
215
|
-
rootDir: "/test/root",
|
|
216
|
-
action: "read_file",
|
|
217
|
-
path: "/absolute/path.txt",
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root", "/absolute/path.txt");
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("should handle complex nested paths", async () => {
|
|
224
|
-
await fs({
|
|
225
|
-
rootDir: "/project",
|
|
226
|
-
action: "write_file",
|
|
227
|
-
path: "src/components/ui/Button/index.tsx",
|
|
228
|
-
content: "export default Button;",
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
expect(joinSpy).toHaveBeenCalledWith("/project", "src/components/ui/Button/index.tsx");
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
// UNDEFINED ACTION TEST
|
|
235
|
-
test("should return undefined for unknown action", async () => {
|
|
236
|
-
const result = await fs({
|
|
237
|
-
rootDir: "/test/root",
|
|
238
|
-
action: "unknown_action",
|
|
239
|
-
path: "test.txt",
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
expect(result).toBeUndefined();
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
// EDGE CASES
|
|
246
|
-
test("should handle special characters in paths", async () => {
|
|
247
|
-
await fs({
|
|
248
|
-
rootDir: "/test/root",
|
|
249
|
-
action: "read_file",
|
|
250
|
-
path: "文件名 with spaces & symbols!.txt",
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
expect(joinSpy).toHaveBeenCalledWith("/test/root", "文件名 with spaces & symbols!.txt");
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
test("should handle null content for write_file", async () => {
|
|
257
|
-
const result = await fs({
|
|
258
|
-
rootDir: "/test/root",
|
|
259
|
-
action: "write_file",
|
|
260
|
-
path: "null-content.txt",
|
|
261
|
-
content: null,
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
expect(writeFileSpy).toHaveBeenCalledWith("/test/root/null-content.txt", "");
|
|
265
|
-
expect(result.content).toBe(null);
|
|
266
|
-
});
|
|
267
|
-
});
|