@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,1470 +0,0 @@
|
|
|
1
|
-
import { afterAll, afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test";
|
|
2
|
-
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
-
import path, { dirname } from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import loadSources from "../../../agents/utils/load-sources.mjs";
|
|
6
|
-
|
|
7
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
|
|
9
|
-
describe("load-sources", () => {
|
|
10
|
-
let testDir;
|
|
11
|
-
let tempDir;
|
|
12
|
-
|
|
13
|
-
beforeEach(async () => {
|
|
14
|
-
// Create test directory structure with unique name to avoid conflicts
|
|
15
|
-
const uniqueId = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
16
|
-
testDir = path.join(__dirname, `test-content-generator-${uniqueId}`);
|
|
17
|
-
tempDir = path.join(testDir, "temp");
|
|
18
|
-
|
|
19
|
-
await mkdir(testDir, { recursive: true });
|
|
20
|
-
await mkdir(tempDir, { recursive: true });
|
|
21
|
-
await mkdir(path.join(testDir, "src"), { recursive: true });
|
|
22
|
-
await mkdir(path.join(testDir, "docs"), { recursive: true });
|
|
23
|
-
await mkdir(path.join(testDir, "node_modules"), { recursive: true });
|
|
24
|
-
await mkdir(path.join(testDir, "test"), { recursive: true });
|
|
25
|
-
|
|
26
|
-
// Create multi-level directory structure under src
|
|
27
|
-
await mkdir(path.join(testDir, "src/components"), { recursive: true });
|
|
28
|
-
await mkdir(path.join(testDir, "src/components/ui"), { recursive: true });
|
|
29
|
-
await mkdir(path.join(testDir, "src/utils/helpers"), { recursive: true });
|
|
30
|
-
await mkdir(path.join(testDir, "src/services/api"), { recursive: true });
|
|
31
|
-
await mkdir(path.join(testDir, "src/config"), { recursive: true });
|
|
32
|
-
|
|
33
|
-
// Create test files in root and src
|
|
34
|
-
await writeFile(path.join(testDir, "package.json"), JSON.stringify({ name: "test" }));
|
|
35
|
-
await writeFile(path.join(testDir, "README.md"), "# Test Project");
|
|
36
|
-
await writeFile(path.join(testDir, "src/index.js"), "console.log('hello');");
|
|
37
|
-
await writeFile(path.join(testDir, "src/utils.js"), "export function test() {}");
|
|
38
|
-
|
|
39
|
-
// Create files in multi-level directories
|
|
40
|
-
await writeFile(path.join(testDir, "src/components/Button.js"), "export class Button {}");
|
|
41
|
-
await writeFile(path.join(testDir, "src/components/ui/Modal.js"), "export class Modal {}");
|
|
42
|
-
await writeFile(path.join(testDir, "src/components/ui/Input.js"), "export class Input {}");
|
|
43
|
-
await writeFile(
|
|
44
|
-
path.join(testDir, "src/utils/helpers/format.js"),
|
|
45
|
-
"export function format() {}",
|
|
46
|
-
);
|
|
47
|
-
await writeFile(
|
|
48
|
-
path.join(testDir, "src/utils/helpers/validate.js"),
|
|
49
|
-
"export function validate() {}",
|
|
50
|
-
);
|
|
51
|
-
await writeFile(path.join(testDir, "src/services/api/client.js"), "export class ApiClient {}");
|
|
52
|
-
await writeFile(
|
|
53
|
-
path.join(testDir, "src/services/api/endpoints.js"),
|
|
54
|
-
"export const endpoints = {}",
|
|
55
|
-
);
|
|
56
|
-
await writeFile(path.join(testDir, "src/config/database.js"), "export const dbConfig = {}");
|
|
57
|
-
await writeFile(path.join(testDir, "src/config/app.js"), "export const appConfig = {}");
|
|
58
|
-
|
|
59
|
-
// Create some non-JS files to test filtering
|
|
60
|
-
await writeFile(path.join(testDir, "src/components/ui/styles.css"), "/* styles */");
|
|
61
|
-
await writeFile(
|
|
62
|
-
path.join(testDir, "src/config/settings.json"),
|
|
63
|
-
JSON.stringify({ theme: "dark" }),
|
|
64
|
-
);
|
|
65
|
-
await writeFile(path.join(testDir, "src/utils/helpers/data.yaml"), "version: 1.0");
|
|
66
|
-
|
|
67
|
-
// Create test files
|
|
68
|
-
await writeFile(path.join(testDir, "test/test.js"), "describe('test', () => {});");
|
|
69
|
-
|
|
70
|
-
// Create files with _test pattern to test the new exclusion
|
|
71
|
-
await writeFile(path.join(testDir, "src/server_test.go"), "func TestServer() {}");
|
|
72
|
-
await writeFile(path.join(testDir, "src/user_test.js"), "describe('user', () => {});");
|
|
73
|
-
await writeFile(path.join(testDir, "src/api_test.ts"), "describe('api', () => {});");
|
|
74
|
-
await writeFile(path.join(testDir, "src/utils_test.py"), "def test_utils(): pass");
|
|
75
|
-
await writeFile(
|
|
76
|
-
path.join(testDir, "src/components/Button_test.jsx"),
|
|
77
|
-
"test('button', () => {});",
|
|
78
|
-
);
|
|
79
|
-
await writeFile(
|
|
80
|
-
path.join(testDir, "src/utils/helpers/format_test.js"),
|
|
81
|
-
"test('format', () => {});",
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
await mkdir(path.join(testDir, "node_modules/some-package"), {
|
|
85
|
-
recursive: true,
|
|
86
|
-
});
|
|
87
|
-
await writeFile(path.join(testDir, "node_modules/some-package/package.json"), "{}");
|
|
88
|
-
await writeFile(path.join(testDir, "temp/temp.txt"), "temp file");
|
|
89
|
-
await writeFile(path.join(testDir, "ignore.txt"), "should be ignored");
|
|
90
|
-
|
|
91
|
-
// Create .gitignore file
|
|
92
|
-
await writeFile(
|
|
93
|
-
path.join(testDir, ".gitignore"),
|
|
94
|
-
"node_modules/\n" + "temp/\n" + "ignore.txt\n" + "*.log\n",
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
afterEach(async () => {
|
|
99
|
-
// Clean up test directory with comprehensive handling
|
|
100
|
-
try {
|
|
101
|
-
await rm(testDir, { recursive: true, force: true });
|
|
102
|
-
} catch {
|
|
103
|
-
// Try multiple cleanup strategies
|
|
104
|
-
try {
|
|
105
|
-
const { chmod, readdir, unlink } = await import("node:fs/promises");
|
|
106
|
-
|
|
107
|
-
// Reset permissions recursively
|
|
108
|
-
const resetPermissions = async (dir) => {
|
|
109
|
-
try {
|
|
110
|
-
await chmod(dir, 0o755);
|
|
111
|
-
const entries = await readdir(dir, { withFileTypes: true });
|
|
112
|
-
for (const entry of entries) {
|
|
113
|
-
const fullPath = path.join(dir, entry.name);
|
|
114
|
-
if (entry.isDirectory()) {
|
|
115
|
-
await resetPermissions(fullPath);
|
|
116
|
-
} else {
|
|
117
|
-
try {
|
|
118
|
-
await chmod(fullPath, 0o644);
|
|
119
|
-
} catch {
|
|
120
|
-
// Try to remove symbolic links directly
|
|
121
|
-
try {
|
|
122
|
-
await unlink(fullPath);
|
|
123
|
-
} catch {
|
|
124
|
-
// Ignore individual file cleanup failures
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
} catch {
|
|
130
|
-
// Ignore permission reset failures
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
await resetPermissions(testDir);
|
|
135
|
-
await rm(testDir, { recursive: true, force: true });
|
|
136
|
-
} catch {
|
|
137
|
-
// Final fallback - try to remove with system command
|
|
138
|
-
try {
|
|
139
|
-
const { exec } = await import("node:child_process");
|
|
140
|
-
const { promisify } = await import("node:util");
|
|
141
|
-
const execAsync = promisify(exec);
|
|
142
|
-
await execAsync(`rm -rf "${testDir}"`);
|
|
143
|
-
} catch {
|
|
144
|
-
// Ignore final cleanup failures - test isolation is more important than perfect cleanup
|
|
145
|
-
console.warn(`Warning: Could not fully clean up test directory: ${testDir}`);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("should load files with default patterns", async () => {
|
|
152
|
-
const result = await loadSources({
|
|
153
|
-
sourcesPath: testDir,
|
|
154
|
-
useDefaultPatterns: true,
|
|
155
|
-
outputDir: tempDir,
|
|
156
|
-
docsDir: path.join(testDir, "docs"),
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
expect(result.files).toBeDefined();
|
|
160
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
161
|
-
|
|
162
|
-
// Should include package.json, README.md, src files
|
|
163
|
-
const filePaths = result.files;
|
|
164
|
-
expect(filePaths.some((element) => element.includes("package.json"))).toBe(true);
|
|
165
|
-
expect(filePaths.some((element) => element.includes("README.md"))).toBe(true);
|
|
166
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
167
|
-
|
|
168
|
-
// Should exclude node_modules, temp, test files
|
|
169
|
-
expect(filePaths.some((element) => element.includes("node_modules"))).toBe(false);
|
|
170
|
-
expect(filePaths.some((element) => element.includes("temp/"))).toBe(false);
|
|
171
|
-
expect(filePaths.some((element) => element.includes("test/test.js"))).toBe(false);
|
|
172
|
-
expect(filePaths.some((element) => element.includes("ignore.txt"))).toBe(false);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("should load files with custom patterns", async () => {
|
|
176
|
-
const result = await loadSources({
|
|
177
|
-
sourcesPath: testDir,
|
|
178
|
-
includePatterns: ["*.js", "*.json"],
|
|
179
|
-
excludePatterns: ["test/*"],
|
|
180
|
-
useDefaultPatterns: false,
|
|
181
|
-
outputDir: tempDir,
|
|
182
|
-
docsDir: path.join(testDir, "docs"),
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
expect(result.files).toBeDefined();
|
|
186
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
187
|
-
|
|
188
|
-
const filePaths = result.files;
|
|
189
|
-
expect(filePaths.some((element) => element.includes("package.json"))).toBe(true);
|
|
190
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
191
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
192
|
-
|
|
193
|
-
// Should exclude test files
|
|
194
|
-
expect(filePaths.some((element) => element.includes("test/test.js"))).toBe(false);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test("should respect .gitignore patterns", async () => {
|
|
198
|
-
const result = await loadSources({
|
|
199
|
-
sourcesPath: testDir,
|
|
200
|
-
includePatterns: ["*"],
|
|
201
|
-
excludePatterns: [],
|
|
202
|
-
useDefaultPatterns: false,
|
|
203
|
-
outputDir: tempDir,
|
|
204
|
-
docsDir: path.join(testDir, "docs"),
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
expect(result.files).toBeDefined();
|
|
208
|
-
|
|
209
|
-
const filePaths = result.files;
|
|
210
|
-
|
|
211
|
-
// Should exclude files listed in .gitignore
|
|
212
|
-
expect(filePaths.some((element) => element.includes("node_modules"))).toBe(false);
|
|
213
|
-
expect(filePaths.some((element) => element.includes("temp/"))).toBe(false);
|
|
214
|
-
expect(filePaths.some((element) => element.includes("ignore.txt"))).toBe(false);
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test("should handle path-based patterns", async () => {
|
|
218
|
-
const result = await loadSources({
|
|
219
|
-
sourcesPath: testDir,
|
|
220
|
-
includePatterns: ["src/**/*.js"],
|
|
221
|
-
excludePatterns: ["**/test/**"],
|
|
222
|
-
useDefaultPatterns: false,
|
|
223
|
-
outputDir: tempDir,
|
|
224
|
-
docsDir: path.join(testDir, "docs"),
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
expect(result.files).toBeDefined();
|
|
228
|
-
|
|
229
|
-
const filePaths = result.files;
|
|
230
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
231
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
232
|
-
|
|
233
|
-
// Should exclude test files
|
|
234
|
-
expect(filePaths.some((element) => element.includes("test/test.js"))).toBe(false);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
test("should handle multiple source paths", async () => {
|
|
238
|
-
const result = await loadSources({
|
|
239
|
-
sourcesPath: [testDir, path.join(testDir, "src")],
|
|
240
|
-
includePatterns: ["*.js"],
|
|
241
|
-
useDefaultPatterns: false,
|
|
242
|
-
outputDir: tempDir,
|
|
243
|
-
docsDir: path.join(testDir, "docs"),
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
expect(result.files).toBeDefined();
|
|
247
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
248
|
-
|
|
249
|
-
const filePaths = result.files;
|
|
250
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
251
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
test("should handle non-existent directories gracefully", async () => {
|
|
255
|
-
const result = await loadSources({
|
|
256
|
-
sourcesPath: path.join(testDir, "non-existent"),
|
|
257
|
-
useDefaultPatterns: true,
|
|
258
|
-
outputDir: tempDir,
|
|
259
|
-
docsDir: path.join(testDir, "docs"),
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
expect(result.files).toBeDefined();
|
|
263
|
-
expect(result.files.length).toBe(0);
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
test("should merge user patterns with default patterns", async () => {
|
|
267
|
-
const result = await loadSources({
|
|
268
|
-
sourcesPath: testDir,
|
|
269
|
-
includePatterns: ["*.txt"],
|
|
270
|
-
excludePatterns: ["docs/*"],
|
|
271
|
-
useDefaultPatterns: true,
|
|
272
|
-
outputDir: tempDir,
|
|
273
|
-
docsDir: path.join(testDir, "docs"),
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
expect(result.files).toBeDefined();
|
|
277
|
-
|
|
278
|
-
const filePaths = result.files;
|
|
279
|
-
|
|
280
|
-
// Should include default patterns (package.json, README.md, etc.)
|
|
281
|
-
expect(filePaths.some((element) => element.includes("package.json"))).toBe(true);
|
|
282
|
-
expect(filePaths.some((element) => element.includes("README.md"))).toBe(true);
|
|
283
|
-
|
|
284
|
-
// Should exclude user exclude patterns
|
|
285
|
-
expect(filePaths.some((element) => element.includes("docs/"))).toBe(false);
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
test("should handle multi-level directory structure", async () => {
|
|
289
|
-
const result = await loadSources({
|
|
290
|
-
sourcesPath: testDir,
|
|
291
|
-
includePatterns: ["**/*.js"],
|
|
292
|
-
excludePatterns: [],
|
|
293
|
-
useDefaultPatterns: false,
|
|
294
|
-
outputDir: tempDir,
|
|
295
|
-
docsDir: path.join(testDir, "docs"),
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
expect(result.files).toBeDefined();
|
|
299
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
300
|
-
|
|
301
|
-
const filePaths = result.files;
|
|
302
|
-
|
|
303
|
-
// Should include files from all levels
|
|
304
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
305
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
306
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
307
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Modal.js"))).toBe(true);
|
|
308
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Input.js"))).toBe(true);
|
|
309
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/format.js"))).toBe(true);
|
|
310
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/validate.js"))).toBe(
|
|
311
|
-
true,
|
|
312
|
-
);
|
|
313
|
-
expect(filePaths.some((element) => element.includes("src/services/api/client.js"))).toBe(true);
|
|
314
|
-
expect(filePaths.some((element) => element.includes("src/services/api/endpoints.js"))).toBe(
|
|
315
|
-
true,
|
|
316
|
-
);
|
|
317
|
-
expect(filePaths.some((element) => element.includes("src/config/database.js"))).toBe(true);
|
|
318
|
-
expect(filePaths.some((element) => element.includes("src/config/app.js"))).toBe(true);
|
|
319
|
-
|
|
320
|
-
// Should exclude non-JS files
|
|
321
|
-
expect(filePaths.some((element) => element.includes("styles.css"))).toBe(false);
|
|
322
|
-
expect(filePaths.some((element) => element.includes("settings.json"))).toBe(false);
|
|
323
|
-
expect(filePaths.some((element) => element.includes("data.yaml"))).toBe(false);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
test("should filter by specific subdirectories", async () => {
|
|
327
|
-
const result = await loadSources({
|
|
328
|
-
sourcesPath: testDir,
|
|
329
|
-
includePatterns: ["src/components/**/*.js", "src/utils/**/*.js"],
|
|
330
|
-
excludePatterns: ["src/components/ui/*.js"],
|
|
331
|
-
useDefaultPatterns: false,
|
|
332
|
-
outputDir: tempDir,
|
|
333
|
-
docsDir: path.join(testDir, "docs"),
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
expect(result.files).toBeDefined();
|
|
337
|
-
|
|
338
|
-
const filePaths = result.files;
|
|
339
|
-
|
|
340
|
-
// Should include files from specified subdirectories
|
|
341
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
342
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/format.js"))).toBe(true);
|
|
343
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/validate.js"))).toBe(
|
|
344
|
-
true,
|
|
345
|
-
);
|
|
346
|
-
|
|
347
|
-
// Should exclude files from excluded subdirectories
|
|
348
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Modal.js"))).toBe(false);
|
|
349
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Input.js"))).toBe(false);
|
|
350
|
-
|
|
351
|
-
// Should exclude files from other directories
|
|
352
|
-
expect(filePaths.some((element) => element.includes("src/services/api/client.js"))).toBe(false);
|
|
353
|
-
expect(filePaths.some((element) => element.includes("src/config/database.js"))).toBe(false);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
test("should handle mixed file types in multi-level directories", async () => {
|
|
357
|
-
const result = await loadSources({
|
|
358
|
-
sourcesPath: testDir,
|
|
359
|
-
includePatterns: ["**/*.js", "**/*.json", "**/*.yaml"],
|
|
360
|
-
excludePatterns: ["**/node_modules/**"],
|
|
361
|
-
useDefaultPatterns: false,
|
|
362
|
-
outputDir: tempDir,
|
|
363
|
-
docsDir: path.join(testDir, "docs"),
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
expect(result.files).toBeDefined();
|
|
367
|
-
|
|
368
|
-
const filePaths = result.files;
|
|
369
|
-
|
|
370
|
-
// Should include JS files from all levels
|
|
371
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
372
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/format.js"))).toBe(true);
|
|
373
|
-
|
|
374
|
-
// Should include JSON and YAML files
|
|
375
|
-
expect(filePaths.some((element) => element.includes("src/config/settings.json"))).toBe(true);
|
|
376
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/data.yaml"))).toBe(true);
|
|
377
|
-
|
|
378
|
-
// Should exclude CSS files
|
|
379
|
-
expect(filePaths.some((element) => element.includes("styles.css"))).toBe(false);
|
|
380
|
-
|
|
381
|
-
// Should exclude node_modules
|
|
382
|
-
expect(filePaths.some((element) => element.includes("node_modules"))).toBe(false);
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
test("should exclude files with _test pattern using default patterns", async () => {
|
|
386
|
-
const result = await loadSources({
|
|
387
|
-
sourcesPath: testDir,
|
|
388
|
-
useDefaultPatterns: true,
|
|
389
|
-
outputDir: tempDir,
|
|
390
|
-
docsDir: path.join(testDir, "docs"),
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
expect(result.files).toBeDefined();
|
|
394
|
-
|
|
395
|
-
const filePaths = result.files;
|
|
396
|
-
|
|
397
|
-
// For now, let's verify that regular files are still included
|
|
398
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
399
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
400
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
401
|
-
|
|
402
|
-
// And verify that some expected exclusions are working
|
|
403
|
-
expect(filePaths.some((element) => element.includes("node_modules"))).toBe(false);
|
|
404
|
-
expect(filePaths.some((element) => element.includes("temp/"))).toBe(false);
|
|
405
|
-
expect(filePaths.some((element) => element.includes("test/test.js"))).toBe(false);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
test("should handle glob patterns in sourcesPath", async () => {
|
|
409
|
-
const result = await loadSources({
|
|
410
|
-
sourcesPath: [`${testDir}/src/**/*.js`],
|
|
411
|
-
useDefaultPatterns: false,
|
|
412
|
-
outputDir: tempDir,
|
|
413
|
-
docsDir: path.join(testDir, "docs"),
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
expect(result.files).toBeDefined();
|
|
417
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
418
|
-
|
|
419
|
-
const filePaths = result.files;
|
|
420
|
-
|
|
421
|
-
// Should include JS files from src directory and subdirectories
|
|
422
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
423
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
424
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
425
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Modal.js"))).toBe(true);
|
|
426
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/format.js"))).toBe(true);
|
|
427
|
-
|
|
428
|
-
// Should exclude non-JS files and files outside src
|
|
429
|
-
expect(filePaths.some((element) => element.includes("package.json"))).toBe(false);
|
|
430
|
-
expect(filePaths.some((element) => element.includes("README.md"))).toBe(false);
|
|
431
|
-
expect(filePaths.some((element) => element.includes("styles.css"))).toBe(false);
|
|
432
|
-
});
|
|
433
|
-
|
|
434
|
-
test("should handle multiple glob patterns in sourcesPath", async () => {
|
|
435
|
-
const result = await loadSources({
|
|
436
|
-
sourcesPath: [`${testDir}/src/**/*.js`, `${testDir}/*.json`, `${testDir}/*.md`],
|
|
437
|
-
useDefaultPatterns: false,
|
|
438
|
-
outputDir: tempDir,
|
|
439
|
-
docsDir: path.join(testDir, "docs"),
|
|
440
|
-
});
|
|
441
|
-
|
|
442
|
-
expect(result.files).toBeDefined();
|
|
443
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
444
|
-
|
|
445
|
-
const filePaths = result.files;
|
|
446
|
-
|
|
447
|
-
// Should include JS files from src directory
|
|
448
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
449
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
450
|
-
|
|
451
|
-
// Should include JSON files from root
|
|
452
|
-
expect(filePaths.some((element) => element.includes("package.json"))).toBe(true);
|
|
453
|
-
|
|
454
|
-
// Should include Markdown files from root
|
|
455
|
-
expect(filePaths.some((element) => element.includes("README.md"))).toBe(true);
|
|
456
|
-
|
|
457
|
-
// Should exclude CSS files
|
|
458
|
-
expect(filePaths.some((element) => element.includes("styles.css"))).toBe(false);
|
|
459
|
-
});
|
|
460
|
-
|
|
461
|
-
test("should handle glob pattern with specific file extensions", async () => {
|
|
462
|
-
const result = await loadSources({
|
|
463
|
-
sourcesPath: [`${testDir}/src/**/*.{js,json,yaml}`],
|
|
464
|
-
useDefaultPatterns: false,
|
|
465
|
-
outputDir: tempDir,
|
|
466
|
-
docsDir: path.join(testDir, "docs"),
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
expect(result.files).toBeDefined();
|
|
470
|
-
|
|
471
|
-
const filePaths = result.files;
|
|
472
|
-
|
|
473
|
-
// Should include JS files
|
|
474
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
475
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(true);
|
|
476
|
-
|
|
477
|
-
// Should include JSON files
|
|
478
|
-
expect(filePaths.some((element) => element.includes("src/config/settings.json"))).toBe(true);
|
|
479
|
-
|
|
480
|
-
// Should include YAML files
|
|
481
|
-
expect(filePaths.some((element) => element.includes("src/utils/helpers/data.yaml"))).toBe(true);
|
|
482
|
-
|
|
483
|
-
// Should exclude CSS files
|
|
484
|
-
expect(filePaths.some((element) => element.includes("styles.css"))).toBe(false);
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
test("should handle glob pattern that matches no files", async () => {
|
|
488
|
-
const result = await loadSources({
|
|
489
|
-
sourcesPath: [`${testDir}/nonexistent/**/*.xyz`],
|
|
490
|
-
useDefaultPatterns: false,
|
|
491
|
-
outputDir: tempDir,
|
|
492
|
-
docsDir: path.join(testDir, "docs"),
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
expect(result.files).toBeDefined();
|
|
496
|
-
expect(result.files.length).toBe(0);
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
test("should handle mixed regular paths and glob patterns", async () => {
|
|
500
|
-
const result = await loadSources({
|
|
501
|
-
sourcesPath: [testDir, `${testDir}/src/**/*.js`],
|
|
502
|
-
includePatterns: ["*.md"],
|
|
503
|
-
useDefaultPatterns: false,
|
|
504
|
-
outputDir: tempDir,
|
|
505
|
-
docsDir: path.join(testDir, "docs"),
|
|
506
|
-
});
|
|
507
|
-
|
|
508
|
-
expect(result.files).toBeDefined();
|
|
509
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
510
|
-
|
|
511
|
-
const filePaths = result.files;
|
|
512
|
-
|
|
513
|
-
// Should include markdown files from directory scan
|
|
514
|
-
expect(filePaths.some((element) => element.includes("README.md"))).toBe(true);
|
|
515
|
-
|
|
516
|
-
// Should include JS files from glob pattern
|
|
517
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
518
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
test("should handle glob patterns with wildcards and character classes", async () => {
|
|
522
|
-
const result = await loadSources({
|
|
523
|
-
sourcesPath: [`${testDir}/src/**/[Bb]utton.js`, `${testDir}/src/**/?odal.js`],
|
|
524
|
-
useDefaultPatterns: false,
|
|
525
|
-
outputDir: tempDir,
|
|
526
|
-
docsDir: path.join(testDir, "docs"),
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
expect(result.files).toBeDefined();
|
|
530
|
-
|
|
531
|
-
const filePaths = result.files;
|
|
532
|
-
|
|
533
|
-
// Should match Button.js with character class
|
|
534
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
535
|
-
|
|
536
|
-
// Should match Modal.js with single character wildcard
|
|
537
|
-
expect(filePaths.some((element) => element.includes("src/components/ui/Modal.js"))).toBe(true);
|
|
538
|
-
|
|
539
|
-
// Should not match other files
|
|
540
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(false);
|
|
541
|
-
expect(filePaths.some((element) => element.includes("src/utils.js"))).toBe(false);
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
describe("Configuration integration tests", () => {
|
|
545
|
-
test("should handle YAML config-like sourcesPath input", async () => {
|
|
546
|
-
const yamlConfigInput = {
|
|
547
|
-
sourcesPath: ["./src", "./lib", "**/*.{js,ts,jsx,tsx}"],
|
|
548
|
-
docsDir: "./docs",
|
|
549
|
-
useDefaultPatterns: true,
|
|
550
|
-
outputDir: tempDir,
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
const result = await loadSources(yamlConfigInput);
|
|
554
|
-
|
|
555
|
-
expect(result.files).toBeDefined();
|
|
556
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
557
|
-
|
|
558
|
-
const filePaths = result.files;
|
|
559
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
test("should handle config with empty sourcesPath array - ACTUALLY WORKS", async () => {
|
|
563
|
-
// This test shows that empty arrays are actually handled correctly
|
|
564
|
-
const result = await loadSources({
|
|
565
|
-
sourcesPath: [],
|
|
566
|
-
useDefaultPatterns: true,
|
|
567
|
-
outputDir: tempDir,
|
|
568
|
-
docsDir: path.join(testDir, "docs"),
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
expect(result.files).toBeDefined();
|
|
572
|
-
expect(result.files.length).toBe(0);
|
|
573
|
-
expect(result.files.length).toBe(0);
|
|
574
|
-
|
|
575
|
-
// Empty arrays are handled gracefully - this is correct behavior
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
test("should filter invalid path elements gracefully - EXPOSES ROBUSTNESS BUG", async () => {
|
|
579
|
-
// ROBUSTNESS BUG TEST: Function should handle invalid elements gracefully
|
|
580
|
-
const mixedArray = ["./src", null, undefined, "./lib", ""];
|
|
581
|
-
|
|
582
|
-
// This test expects the function to filter out invalid elements and work with valid ones
|
|
583
|
-
const result = await loadSources({
|
|
584
|
-
sourcesPath: mixedArray,
|
|
585
|
-
useDefaultPatterns: true,
|
|
586
|
-
outputDir: tempDir,
|
|
587
|
-
docsDir: path.join(testDir, "docs"),
|
|
588
|
-
});
|
|
589
|
-
|
|
590
|
-
// Should successfully process valid paths and ignore invalid ones
|
|
591
|
-
expect(result.files).toBeDefined();
|
|
592
|
-
// This test will FAIL because the function crashes instead of filtering
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
test("should handle config with undefined sourcesPath - ACTUALLY WORKS", async () => {
|
|
596
|
-
// This test shows undefined sourcesPath is actually handled correctly
|
|
597
|
-
const result = await loadSources({
|
|
598
|
-
sourcesPath: undefined,
|
|
599
|
-
useDefaultPatterns: true,
|
|
600
|
-
outputDir: tempDir,
|
|
601
|
-
docsDir: path.join(testDir, "docs"),
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
expect(result.files).toBeDefined();
|
|
605
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
606
|
-
expect(result.files.length).toBe(0);
|
|
607
|
-
|
|
608
|
-
// undefined is handled gracefully by skipping sourcesPath processing
|
|
609
|
-
});
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
describe("Function robustness issues - EXPOSES INPUT HANDLING PROBLEMS", () => {
|
|
613
|
-
test("should handle invalid inputs gracefully - EXPOSES POOR ERROR HANDLING", async () => {
|
|
614
|
-
// ROBUSTNESS TEST: Function should validate inputs and provide helpful errors
|
|
615
|
-
const invalidInputs = [
|
|
616
|
-
{ value: [null], description: "array with null element", shouldFail: true },
|
|
617
|
-
{ value: [undefined], description: "array with undefined element", shouldFail: true },
|
|
618
|
-
{ value: ["", null], description: "mixed array with null", shouldFail: true },
|
|
619
|
-
];
|
|
620
|
-
|
|
621
|
-
for (const { value: invalidInput, shouldFail } of invalidInputs) {
|
|
622
|
-
if (shouldFail) {
|
|
623
|
-
// These should provide helpful error messages, not crash unexpectedly
|
|
624
|
-
const result = await loadSources({
|
|
625
|
-
sourcesPath: invalidInput,
|
|
626
|
-
useDefaultPatterns: true,
|
|
627
|
-
outputDir: tempDir,
|
|
628
|
-
docsDir: path.join(testDir, "docs"),
|
|
629
|
-
});
|
|
630
|
-
expect(result.files).toBeDefined();
|
|
631
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
632
|
-
expect(result.files.length).toBe(0);
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
// Test inputs that should work but be handled gracefully
|
|
637
|
-
const shouldWorkInputs = [
|
|
638
|
-
null, // Should be treated like undefined
|
|
639
|
-
"", // Should be treated like undefined
|
|
640
|
-
123, // Should provide helpful error
|
|
641
|
-
{}, // Should provide helpful error
|
|
642
|
-
[""], // Should filter out empty strings
|
|
643
|
-
];
|
|
644
|
-
|
|
645
|
-
for (const validInput of shouldWorkInputs) {
|
|
646
|
-
// These tests expect graceful handling but may FAIL due to poor input validation
|
|
647
|
-
const result = await loadSources({
|
|
648
|
-
sourcesPath: validInput,
|
|
649
|
-
useDefaultPatterns: true,
|
|
650
|
-
outputDir: tempDir,
|
|
651
|
-
docsDir: path.join(testDir, "docs"),
|
|
652
|
-
});
|
|
653
|
-
|
|
654
|
-
expect(result.files).toBeDefined();
|
|
655
|
-
// Some of these tests will FAIL, exposing input validation issues
|
|
656
|
-
}
|
|
657
|
-
});
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
describe("File system edge cases", () => {
|
|
661
|
-
test("should handle symbolic links", async () => {
|
|
662
|
-
// Skip on systems that don't support symlinks
|
|
663
|
-
try {
|
|
664
|
-
const { symlink } = await import("node:fs/promises");
|
|
665
|
-
const symlinkPath = path.join(testDir, "symlink-to-src");
|
|
666
|
-
await symlink(path.join(testDir, "src"), symlinkPath);
|
|
667
|
-
|
|
668
|
-
const result = await loadSources({
|
|
669
|
-
sourcesPath: symlinkPath,
|
|
670
|
-
includePatterns: ["*.js"],
|
|
671
|
-
useDefaultPatterns: false,
|
|
672
|
-
outputDir: tempDir,
|
|
673
|
-
docsDir: path.join(testDir, "docs"),
|
|
674
|
-
});
|
|
675
|
-
|
|
676
|
-
expect(result.files).toBeDefined();
|
|
677
|
-
const filePaths = result.files;
|
|
678
|
-
expect(filePaths.some((element) => element.includes("index.js"))).toBe(true);
|
|
679
|
-
} catch {
|
|
680
|
-
// Skip test on systems that don't support symlinks
|
|
681
|
-
expect(true).toBe(true);
|
|
682
|
-
}
|
|
683
|
-
});
|
|
684
|
-
|
|
685
|
-
test("should handle very deep directory structures", async () => {
|
|
686
|
-
// Create deep nested structure
|
|
687
|
-
const deepPath = path.join(testDir, "a/b/c/d/e/f/g/h");
|
|
688
|
-
await mkdir(deepPath, { recursive: true });
|
|
689
|
-
await writeFile(path.join(deepPath, "deep.js"), "console.log('deep');");
|
|
690
|
-
|
|
691
|
-
const content = await readFile(path.join(deepPath, "deep.js"), "utf8");
|
|
692
|
-
console.log("deep content", content);
|
|
693
|
-
|
|
694
|
-
const result = await loadSources({
|
|
695
|
-
sourcesPath: testDir,
|
|
696
|
-
includePatterns: ["**/*.js"],
|
|
697
|
-
useDefaultPatterns: false,
|
|
698
|
-
outputDir: tempDir,
|
|
699
|
-
docsDir: path.join(testDir, "docs"),
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
expect(result.files).toBeDefined();
|
|
703
|
-
const filePaths = result.files;
|
|
704
|
-
expect(filePaths.some((element) => element.includes("a/b/c/d/e/f/g/h/deep.js"))).toBe(true);
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
test("should handle files with unusual names", async () => {
|
|
708
|
-
// Create files with special characters in names
|
|
709
|
-
await writeFile(path.join(testDir, "file with spaces.js"), "console.log('spaces');");
|
|
710
|
-
await writeFile(path.join(testDir, "file-with-dashes.js"), "console.log('dashes');");
|
|
711
|
-
await writeFile(
|
|
712
|
-
path.join(testDir, "file_with_underscores.js"),
|
|
713
|
-
"console.log('underscores');",
|
|
714
|
-
);
|
|
715
|
-
await writeFile(path.join(testDir, "file.with.dots.js"), "console.log('dots');");
|
|
716
|
-
await writeFile(path.join(testDir, "文件中文名.js"), "console.log('chinese');");
|
|
717
|
-
|
|
718
|
-
const result = await loadSources({
|
|
719
|
-
sourcesPath: testDir,
|
|
720
|
-
includePatterns: ["*.js"],
|
|
721
|
-
excludePatterns: ["**/test/**", "*_test*"],
|
|
722
|
-
useDefaultPatterns: false,
|
|
723
|
-
outputDir: tempDir,
|
|
724
|
-
docsDir: path.join(testDir, "docs"),
|
|
725
|
-
});
|
|
726
|
-
|
|
727
|
-
expect(result.files).toBeDefined();
|
|
728
|
-
const filePaths = result.files;
|
|
729
|
-
|
|
730
|
-
expect(filePaths.some((element) => element.includes("file with spaces.js"))).toBe(true);
|
|
731
|
-
expect(filePaths.some((element) => element.includes("file-with-dashes.js"))).toBe(true);
|
|
732
|
-
expect(filePaths.some((element) => element.includes("file_with_underscores.js"))).toBe(true);
|
|
733
|
-
expect(filePaths.some((element) => element.includes("file.with.dots.js"))).toBe(true);
|
|
734
|
-
expect(filePaths.some((element) => element.includes("文件中文名.js"))).toBe(true);
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
test("should handle empty directories", async () => {
|
|
738
|
-
const emptyDir = path.join(testDir, "empty");
|
|
739
|
-
await mkdir(emptyDir, { recursive: true });
|
|
740
|
-
|
|
741
|
-
const result = await loadSources({
|
|
742
|
-
sourcesPath: emptyDir,
|
|
743
|
-
useDefaultPatterns: true,
|
|
744
|
-
outputDir: tempDir,
|
|
745
|
-
docsDir: path.join(testDir, "docs"),
|
|
746
|
-
});
|
|
747
|
-
|
|
748
|
-
expect(result.files).toBeDefined();
|
|
749
|
-
expect(result.files.length).toBe(0);
|
|
750
|
-
});
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
describe("Pattern matching edge cases", () => {
|
|
754
|
-
test("should handle negation patterns correctly", async () => {
|
|
755
|
-
const result = await loadSources({
|
|
756
|
-
sourcesPath: testDir,
|
|
757
|
-
includePatterns: ["**/*.js"],
|
|
758
|
-
excludePatterns: ["!src/components/**"], // Negation should include
|
|
759
|
-
useDefaultPatterns: false,
|
|
760
|
-
outputDir: tempDir,
|
|
761
|
-
docsDir: path.join(testDir, "docs"),
|
|
762
|
-
});
|
|
763
|
-
|
|
764
|
-
expect(result.files).toBeDefined();
|
|
765
|
-
const filePaths = result.files;
|
|
766
|
-
|
|
767
|
-
// Should still exclude test files by default gitignore/patterns
|
|
768
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(true);
|
|
769
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(true);
|
|
770
|
-
});
|
|
771
|
-
|
|
772
|
-
test("should handle conflicting include/exclude patterns", async () => {
|
|
773
|
-
const result = await loadSources({
|
|
774
|
-
sourcesPath: testDir,
|
|
775
|
-
includePatterns: ["src/**/*.js"], // Include all JS in src
|
|
776
|
-
excludePatterns: ["src/**/*.js"], // But exclude all JS in src
|
|
777
|
-
useDefaultPatterns: false,
|
|
778
|
-
outputDir: tempDir,
|
|
779
|
-
docsDir: path.join(testDir, "docs"),
|
|
780
|
-
});
|
|
781
|
-
|
|
782
|
-
expect(result.files).toBeDefined();
|
|
783
|
-
const filePaths = result.files;
|
|
784
|
-
|
|
785
|
-
// Exclude should win over include
|
|
786
|
-
expect(filePaths.some((element) => element.includes("src/index.js"))).toBe(false);
|
|
787
|
-
expect(filePaths.some((element) => element.includes("src/components/Button.js"))).toBe(false);
|
|
788
|
-
});
|
|
789
|
-
|
|
790
|
-
test("should handle case sensitivity in patterns", async () => {
|
|
791
|
-
// Create files with different cases
|
|
792
|
-
await writeFile(path.join(testDir, "CamelCase.js"), "console.log('CamelCase');");
|
|
793
|
-
await writeFile(path.join(testDir, "lowercase.js"), "console.log('lowercase');");
|
|
794
|
-
await writeFile(path.join(testDir, "UPPERCASE.JS"), "console.log('UPPERCASE');");
|
|
795
|
-
|
|
796
|
-
const result = await loadSources({
|
|
797
|
-
sourcesPath: testDir,
|
|
798
|
-
includePatterns: ["*.[jJ][sS]"], // Case insensitive for extension
|
|
799
|
-
useDefaultPatterns: false,
|
|
800
|
-
outputDir: tempDir,
|
|
801
|
-
docsDir: path.join(testDir, "docs"),
|
|
802
|
-
});
|
|
803
|
-
|
|
804
|
-
expect(result.files).toBeDefined();
|
|
805
|
-
const filePaths = result.files;
|
|
806
|
-
|
|
807
|
-
expect(filePaths.some((element) => element.includes("CamelCase.js"))).toBe(true);
|
|
808
|
-
expect(filePaths.some((element) => element.includes("lowercase.js"))).toBe(true);
|
|
809
|
-
expect(filePaths.some((element) => element.includes("UPPERCASE.JS"))).toBe(true);
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
test("should handle extremely complex glob patterns", async () => {
|
|
813
|
-
const result = await loadSources({
|
|
814
|
-
sourcesPath: testDir,
|
|
815
|
-
includePatterns: [
|
|
816
|
-
"src/**/!(test|spec)*{.js,.ts,.jsx,.tsx}", // Complex negation with alternatives
|
|
817
|
-
"**/@(components|utils|services)/**/*.{js,ts}", // At-patterns with alternatives
|
|
818
|
-
],
|
|
819
|
-
useDefaultPatterns: false,
|
|
820
|
-
outputDir: tempDir,
|
|
821
|
-
docsDir: path.join(testDir, "docs"),
|
|
822
|
-
});
|
|
823
|
-
|
|
824
|
-
expect(result.files).toBeDefined();
|
|
825
|
-
// Just verify it doesn't crash and returns some results
|
|
826
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
827
|
-
});
|
|
828
|
-
});
|
|
829
|
-
|
|
830
|
-
describe("Performance and scale tests", () => {
|
|
831
|
-
test("should handle large number of patterns efficiently", async () => {
|
|
832
|
-
const manyPatterns = Array(100)
|
|
833
|
-
.fill(0)
|
|
834
|
-
.map((_, i) => `**/*${i}*.js`);
|
|
835
|
-
|
|
836
|
-
const startTime = Date.now();
|
|
837
|
-
const result = await loadSources({
|
|
838
|
-
sourcesPath: testDir,
|
|
839
|
-
includePatterns: manyPatterns,
|
|
840
|
-
useDefaultPatterns: false,
|
|
841
|
-
outputDir: tempDir,
|
|
842
|
-
docsDir: path.join(testDir, "docs"),
|
|
843
|
-
});
|
|
844
|
-
const endTime = Date.now();
|
|
845
|
-
|
|
846
|
-
expect(result.files).toBeDefined();
|
|
847
|
-
expect(endTime - startTime).toBeLessThan(5000); // Should complete within 5 seconds
|
|
848
|
-
});
|
|
849
|
-
|
|
850
|
-
test("should handle very long paths", async () => {
|
|
851
|
-
const longDirName = "a".repeat(100);
|
|
852
|
-
const longPath = path.join(testDir, longDirName);
|
|
853
|
-
await mkdir(longPath, { recursive: true });
|
|
854
|
-
await writeFile(path.join(longPath, "file.js"), "console.log('long path');");
|
|
855
|
-
|
|
856
|
-
const result = await loadSources({
|
|
857
|
-
sourcesPath: testDir,
|
|
858
|
-
includePatterns: ["**/*.js"],
|
|
859
|
-
useDefaultPatterns: false,
|
|
860
|
-
outputDir: tempDir,
|
|
861
|
-
docsDir: path.join(testDir, "docs"),
|
|
862
|
-
});
|
|
863
|
-
|
|
864
|
-
expect(result.files).toBeDefined();
|
|
865
|
-
const filePaths = result.files;
|
|
866
|
-
expect(filePaths.some((element) => element.includes(longDirName))).toBe(true);
|
|
867
|
-
});
|
|
868
|
-
});
|
|
869
|
-
|
|
870
|
-
describe("Error handling and resilience", () => {
|
|
871
|
-
test("should handle permission denied gracefully", async () => {
|
|
872
|
-
// This test may not work on all systems, so we wrap in try-catch
|
|
873
|
-
try {
|
|
874
|
-
const restrictedDir = path.join(testDir, "restricted");
|
|
875
|
-
await mkdir(restrictedDir, { recursive: true, mode: 0o000 });
|
|
876
|
-
|
|
877
|
-
const result = await loadSources({
|
|
878
|
-
sourcesPath: restrictedDir,
|
|
879
|
-
useDefaultPatterns: true,
|
|
880
|
-
outputDir: tempDir,
|
|
881
|
-
docsDir: path.join(testDir, "docs"),
|
|
882
|
-
});
|
|
883
|
-
|
|
884
|
-
expect(result.files).toBeDefined();
|
|
885
|
-
// Should handle gracefully without crashing
|
|
886
|
-
} catch {
|
|
887
|
-
// Skip on systems where permission tests don't work
|
|
888
|
-
expect(true).toBe(true);
|
|
889
|
-
}
|
|
890
|
-
});
|
|
891
|
-
|
|
892
|
-
test("should handle malformed glob patterns", async () => {
|
|
893
|
-
const result = await loadSources({
|
|
894
|
-
sourcesPath: [`${testDir}/[unclosed`, `${testDir}/**/{unclosed`],
|
|
895
|
-
useDefaultPatterns: false,
|
|
896
|
-
outputDir: tempDir,
|
|
897
|
-
docsDir: path.join(testDir, "docs"),
|
|
898
|
-
});
|
|
899
|
-
|
|
900
|
-
expect(result.files).toBeDefined();
|
|
901
|
-
// Should not crash, even with malformed patterns
|
|
902
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
903
|
-
});
|
|
904
|
-
|
|
905
|
-
test("should handle circular symbolic links", async () => {
|
|
906
|
-
try {
|
|
907
|
-
const { symlink, unlink } = await import("node:fs/promises");
|
|
908
|
-
const link1 = path.join(testDir, "link1");
|
|
909
|
-
const link2 = path.join(testDir, "link2");
|
|
910
|
-
|
|
911
|
-
// Create circular links
|
|
912
|
-
await symlink(link2, link1);
|
|
913
|
-
await symlink(link1, link2);
|
|
914
|
-
|
|
915
|
-
const result = await loadSources({
|
|
916
|
-
sourcesPath: testDir,
|
|
917
|
-
includePatterns: ["**/*"],
|
|
918
|
-
useDefaultPatterns: false,
|
|
919
|
-
outputDir: tempDir,
|
|
920
|
-
docsDir: path.join(testDir, "docs"),
|
|
921
|
-
});
|
|
922
|
-
|
|
923
|
-
expect(result.files).toBeDefined();
|
|
924
|
-
// Should handle circular links without infinite loop
|
|
925
|
-
|
|
926
|
-
// Clean up circular links immediately to prevent interference with other tests
|
|
927
|
-
try {
|
|
928
|
-
await unlink(link1);
|
|
929
|
-
} catch {
|
|
930
|
-
// Ignore cleanup errors since they don't affect test results
|
|
931
|
-
}
|
|
932
|
-
try {
|
|
933
|
-
await unlink(link2);
|
|
934
|
-
} catch {
|
|
935
|
-
// Ignore cleanup errors since they don't affect test results
|
|
936
|
-
}
|
|
937
|
-
} catch {
|
|
938
|
-
// Skip on systems that don't support symlinks
|
|
939
|
-
expect(true).toBe(true);
|
|
940
|
-
}
|
|
941
|
-
});
|
|
942
|
-
});
|
|
943
|
-
|
|
944
|
-
describe("Integration with generateYAML output", () => {
|
|
945
|
-
test("should process typical generateYAML sourcesPath configurations", async () => {
|
|
946
|
-
const typicalConfigs = [
|
|
947
|
-
["./src", "./lib"],
|
|
948
|
-
["**/*.{js,ts,jsx,tsx}"],
|
|
949
|
-
["src/**/*.js", "lib/**/*.ts", "docs/**/*.md"],
|
|
950
|
-
["./", "!node_modules", "!dist"],
|
|
951
|
-
];
|
|
952
|
-
|
|
953
|
-
for (const sourcesPathConfig of typicalConfigs) {
|
|
954
|
-
const result = await loadSources({
|
|
955
|
-
sourcesPath: sourcesPathConfig,
|
|
956
|
-
useDefaultPatterns: true,
|
|
957
|
-
outputDir: tempDir,
|
|
958
|
-
docsDir: path.join(testDir, "docs"),
|
|
959
|
-
});
|
|
960
|
-
|
|
961
|
-
expect(result.files).toBeDefined();
|
|
962
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
963
|
-
// Should not crash with any typical config
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
});
|
|
967
|
-
|
|
968
|
-
describe("File type handling and media assets", () => {
|
|
969
|
-
test("should handle individual files as sourcesPath", async () => {
|
|
970
|
-
// Test line 41: stats.isFile() branch
|
|
971
|
-
const singleFile = path.join(testDir, "single-file.js");
|
|
972
|
-
await writeFile(singleFile, "console.log('single file');");
|
|
973
|
-
|
|
974
|
-
const result = await loadSources({
|
|
975
|
-
sourcesPath: singleFile,
|
|
976
|
-
useDefaultPatterns: false,
|
|
977
|
-
outputDir: tempDir,
|
|
978
|
-
docsDir: path.join(testDir, "docs"),
|
|
979
|
-
});
|
|
980
|
-
|
|
981
|
-
expect(result.files).toBeDefined();
|
|
982
|
-
expect(result.files.length).toBe(1);
|
|
983
|
-
expect(result.files[0]).toContain("single-file.js");
|
|
984
|
-
});
|
|
985
|
-
|
|
986
|
-
test("should process media files correctly", async () => {
|
|
987
|
-
// Create media files to test lines 151-159
|
|
988
|
-
const mediaDir = path.join(testDir, "media");
|
|
989
|
-
await mkdir(mediaDir, { recursive: true });
|
|
990
|
-
|
|
991
|
-
await writeFile(path.join(mediaDir, "image.jpg"), "fake image data");
|
|
992
|
-
await writeFile(path.join(mediaDir, "video.mp4"), "fake video data");
|
|
993
|
-
await writeFile(path.join(mediaDir, "logo.svg"), "<svg></svg>");
|
|
994
|
-
await writeFile(path.join(mediaDir, "animation.webp"), "fake webp data");
|
|
995
|
-
|
|
996
|
-
const result = await loadSources({
|
|
997
|
-
sourcesPath: mediaDir,
|
|
998
|
-
includePatterns: ["**/*"],
|
|
999
|
-
useDefaultPatterns: false,
|
|
1000
|
-
outputDir: tempDir,
|
|
1001
|
-
docsDir: path.join(testDir, "docs"),
|
|
1002
|
-
});
|
|
1003
|
-
|
|
1004
|
-
expect(result.assetsContent).toBeDefined();
|
|
1005
|
-
expect(result.assetsContent).toContain("Available Media Assets");
|
|
1006
|
-
expect(result.assetsContent).toContain("image.jpg");
|
|
1007
|
-
expect(result.assetsContent).toContain("video.mp4");
|
|
1008
|
-
expect(result.assetsContent).toContain("logo.svg");
|
|
1009
|
-
expect(result.assetsContent).toContain('type: "image"');
|
|
1010
|
-
expect(result.assetsContent).toContain('type: "video"');
|
|
1011
|
-
|
|
1012
|
-
// Test media file processing logic (lines 243-266)
|
|
1013
|
-
expect(result.assetsContent).toContain("```yaml");
|
|
1014
|
-
expect(result.assetsContent).toContain("assets:");
|
|
1015
|
-
});
|
|
1016
|
-
|
|
1017
|
-
test("should handle glob pattern errors gracefully", async () => {
|
|
1018
|
-
const invalidGlobPattern = "./invalid/**/*.{unclosed";
|
|
1019
|
-
|
|
1020
|
-
const result = await loadSources({
|
|
1021
|
-
sourcesPath: [invalidGlobPattern],
|
|
1022
|
-
useDefaultPatterns: false,
|
|
1023
|
-
outputDir: tempDir,
|
|
1024
|
-
docsDir: path.join(testDir, "docs"),
|
|
1025
|
-
});
|
|
1026
|
-
|
|
1027
|
-
expect(result.files).toBeDefined();
|
|
1028
|
-
expect(Array.isArray(result.files)).toBe(true);
|
|
1029
|
-
// Should handle gracefully without crashing
|
|
1030
|
-
});
|
|
1031
|
-
});
|
|
1032
|
-
|
|
1033
|
-
describe("Document path and documentation structure handling", () => {
|
|
1034
|
-
test("should load existing documentation structure", async () => {
|
|
1035
|
-
const documentStructure = {
|
|
1036
|
-
sections: ["Introduction", "API", "Examples"],
|
|
1037
|
-
lastUpdated: new Date().toISOString(),
|
|
1038
|
-
};
|
|
1039
|
-
|
|
1040
|
-
await writeFile(path.join(tempDir, "structure-plan.json"), JSON.stringify(documentStructure));
|
|
1041
|
-
|
|
1042
|
-
const result = await loadSources({
|
|
1043
|
-
sourcesPath: testDir,
|
|
1044
|
-
includePatterns: ["*.js"],
|
|
1045
|
-
useDefaultPatterns: false,
|
|
1046
|
-
outputDir: tempDir,
|
|
1047
|
-
docsDir: path.join(testDir, "docs"),
|
|
1048
|
-
});
|
|
1049
|
-
|
|
1050
|
-
expect(result.originalDocumentStructure).toEqual(documentStructure);
|
|
1051
|
-
});
|
|
1052
|
-
|
|
1053
|
-
test("should handle malformed documentation structure JSON", async () => {
|
|
1054
|
-
await writeFile(path.join(tempDir, "structure-plan.json"), "{ invalid json content");
|
|
1055
|
-
|
|
1056
|
-
const result = await loadSources({
|
|
1057
|
-
sourcesPath: testDir,
|
|
1058
|
-
includePatterns: ["*.js"],
|
|
1059
|
-
useDefaultPatterns: false,
|
|
1060
|
-
outputDir: tempDir,
|
|
1061
|
-
docsDir: path.join(testDir, "docs"),
|
|
1062
|
-
});
|
|
1063
|
-
|
|
1064
|
-
expect(result.originalDocumentStructure).toBeUndefined();
|
|
1065
|
-
});
|
|
1066
|
-
|
|
1067
|
-
test("should handle non-ENOENT errors when reading documentation structure JSON", async () => {
|
|
1068
|
-
// Import fs promises module to spy on
|
|
1069
|
-
const fsPromises = await import("node:fs/promises");
|
|
1070
|
-
|
|
1071
|
-
// Get the original readFile function
|
|
1072
|
-
const originalReadFile = fsPromises.readFile;
|
|
1073
|
-
|
|
1074
|
-
// Create a spy that only throws error for structure-plan.json
|
|
1075
|
-
const readFileSpy = spyOn(fsPromises, "readFile").mockImplementation((filePath, encoding) => {
|
|
1076
|
-
if (filePath.includes("structure-plan.json")) {
|
|
1077
|
-
const error = new Error("Permission denied");
|
|
1078
|
-
error.code = "EACCES";
|
|
1079
|
-
throw error;
|
|
1080
|
-
}
|
|
1081
|
-
// For all other files, use the original readFile
|
|
1082
|
-
return originalReadFile(filePath, encoding);
|
|
1083
|
-
});
|
|
1084
|
-
|
|
1085
|
-
try {
|
|
1086
|
-
const result = await loadSources({
|
|
1087
|
-
sourcesPath: testDir,
|
|
1088
|
-
includePatterns: ["*.js"],
|
|
1089
|
-
useDefaultPatterns: false,
|
|
1090
|
-
outputDir: tempDir,
|
|
1091
|
-
docsDir: path.join(testDir, "docs"),
|
|
1092
|
-
});
|
|
1093
|
-
|
|
1094
|
-
expect(result.originalDocumentStructure).toBeUndefined();
|
|
1095
|
-
} finally {
|
|
1096
|
-
// Restore the original readFile function
|
|
1097
|
-
readFileSpy.mockRestore();
|
|
1098
|
-
}
|
|
1099
|
-
});
|
|
1100
|
-
|
|
1101
|
-
test("should handle non-ENOENT errors when reading docPath file", async () => {
|
|
1102
|
-
// Import fs promises module to spy on
|
|
1103
|
-
const fsPromises = await import("node:fs/promises");
|
|
1104
|
-
|
|
1105
|
-
// Get the original readFile function
|
|
1106
|
-
const originalReadFile = fsPromises.readFile;
|
|
1107
|
-
|
|
1108
|
-
// Create a spy that only throws error for the specific docPath file
|
|
1109
|
-
const readFileSpy = spyOn(fsPromises, "readFile").mockImplementation((filePath, encoding) => {
|
|
1110
|
-
// Check if this is the docPath file (api-overview.md)
|
|
1111
|
-
if (filePath.includes("api-overview.md")) {
|
|
1112
|
-
const error = new Error("Permission denied");
|
|
1113
|
-
error.code = "EACCES";
|
|
1114
|
-
throw error;
|
|
1115
|
-
}
|
|
1116
|
-
// For all other files, use the original readFile
|
|
1117
|
-
return originalReadFile(filePath, encoding);
|
|
1118
|
-
});
|
|
1119
|
-
|
|
1120
|
-
try {
|
|
1121
|
-
const result = await loadSources({
|
|
1122
|
-
sourcesPath: testDir,
|
|
1123
|
-
"doc-path": "/api/overview",
|
|
1124
|
-
includePatterns: ["*.js"],
|
|
1125
|
-
useDefaultPatterns: false,
|
|
1126
|
-
outputDir: tempDir,
|
|
1127
|
-
docsDir: path.join(testDir, "docs"),
|
|
1128
|
-
});
|
|
1129
|
-
|
|
1130
|
-
expect(result.content).toBeUndefined();
|
|
1131
|
-
} finally {
|
|
1132
|
-
// Restore the original readFile function
|
|
1133
|
-
readFileSpy.mockRestore();
|
|
1134
|
-
}
|
|
1135
|
-
});
|
|
1136
|
-
|
|
1137
|
-
test("should handle non-ENOENT errors when reading boardId-based docPath file", async () => {
|
|
1138
|
-
// Import fs promises module to spy on
|
|
1139
|
-
const fsPromises = await import("node:fs/promises");
|
|
1140
|
-
|
|
1141
|
-
// Get the original readFile function
|
|
1142
|
-
const originalReadFile = fsPromises.readFile;
|
|
1143
|
-
|
|
1144
|
-
// Create a spy that only throws error for the boardId file
|
|
1145
|
-
const readFileSpy = spyOn(fsPromises, "readFile").mockImplementation((filePath, encoding) => {
|
|
1146
|
-
// First call will fail for the original format (board123-api-overview.md)
|
|
1147
|
-
// Second call should fail for the boardId format (api-overview.md)
|
|
1148
|
-
if (filePath.includes("board123-api-overview.md")) {
|
|
1149
|
-
const error = new Error("File not found");
|
|
1150
|
-
error.code = "ENOENT";
|
|
1151
|
-
throw error;
|
|
1152
|
-
}
|
|
1153
|
-
if (filePath.includes("api-overview.md") && !filePath.includes("board123-")) {
|
|
1154
|
-
const error = new Error("Permission denied");
|
|
1155
|
-
error.code = "EACCES";
|
|
1156
|
-
throw error;
|
|
1157
|
-
}
|
|
1158
|
-
// For all other files, use the original readFile
|
|
1159
|
-
return originalReadFile(filePath, encoding);
|
|
1160
|
-
});
|
|
1161
|
-
|
|
1162
|
-
try {
|
|
1163
|
-
const result = await loadSources({
|
|
1164
|
-
sourcesPath: testDir,
|
|
1165
|
-
"doc-path": "board123-api-overview",
|
|
1166
|
-
boardId: "board123",
|
|
1167
|
-
includePatterns: ["*.js"],
|
|
1168
|
-
useDefaultPatterns: false,
|
|
1169
|
-
outputDir: tempDir,
|
|
1170
|
-
docsDir: path.join(testDir, "docs"),
|
|
1171
|
-
});
|
|
1172
|
-
|
|
1173
|
-
expect(result.content).toBeUndefined();
|
|
1174
|
-
} finally {
|
|
1175
|
-
// Restore the original readFile function
|
|
1176
|
-
readFileSpy.mockRestore();
|
|
1177
|
-
}
|
|
1178
|
-
});
|
|
1179
|
-
|
|
1180
|
-
test("should load document content by docPath", async () => {
|
|
1181
|
-
const docsDir = path.join(testDir, "docs");
|
|
1182
|
-
const docContent = "# API Documentation\n\nThis is the API documentation content.";
|
|
1183
|
-
|
|
1184
|
-
await writeFile(path.join(docsDir, "api-overview.md"), docContent);
|
|
1185
|
-
|
|
1186
|
-
const result = await loadSources({
|
|
1187
|
-
sourcesPath: testDir,
|
|
1188
|
-
"doc-path": "/api/overview",
|
|
1189
|
-
includePatterns: ["*.md"],
|
|
1190
|
-
useDefaultPatterns: false,
|
|
1191
|
-
outputDir: tempDir,
|
|
1192
|
-
docsDir: docsDir,
|
|
1193
|
-
});
|
|
1194
|
-
|
|
1195
|
-
expect(result.content).toBe(docContent);
|
|
1196
|
-
});
|
|
1197
|
-
|
|
1198
|
-
test("should handle boardId-based doc path format", async () => {
|
|
1199
|
-
const docsDir = path.join(testDir, "docs");
|
|
1200
|
-
const docContent = "# Board specific documentation";
|
|
1201
|
-
|
|
1202
|
-
await writeFile(path.join(docsDir, "user-guide.md"), docContent);
|
|
1203
|
-
|
|
1204
|
-
const result = await loadSources({
|
|
1205
|
-
sourcesPath: testDir,
|
|
1206
|
-
"doc-path": "board123-user-guide",
|
|
1207
|
-
boardId: "board123",
|
|
1208
|
-
includePatterns: ["*.md"],
|
|
1209
|
-
useDefaultPatterns: false,
|
|
1210
|
-
outputDir: tempDir,
|
|
1211
|
-
docsDir: docsDir,
|
|
1212
|
-
});
|
|
1213
|
-
|
|
1214
|
-
expect(result.content).toBe(docContent);
|
|
1215
|
-
});
|
|
1216
|
-
|
|
1217
|
-
test("should handle non-existent doc path gracefully", async () => {
|
|
1218
|
-
const result = await loadSources({
|
|
1219
|
-
sourcesPath: testDir,
|
|
1220
|
-
"doc-path": "/non-existent/doc",
|
|
1221
|
-
includePatterns: ["*.md"],
|
|
1222
|
-
useDefaultPatterns: false,
|
|
1223
|
-
outputDir: tempDir,
|
|
1224
|
-
docsDir: path.join(testDir, "docs"),
|
|
1225
|
-
});
|
|
1226
|
-
|
|
1227
|
-
expect(result.content).toBeUndefined();
|
|
1228
|
-
});
|
|
1229
|
-
|
|
1230
|
-
test("should handle includePatterns empty gracefully", async () => {
|
|
1231
|
-
const docsDir = path.join(testDir, "docs");
|
|
1232
|
-
const docContent = "# API Documentation\n\nThis is the API documentation content.";
|
|
1233
|
-
|
|
1234
|
-
await writeFile(path.join(docsDir, "api-overview.md"), docContent);
|
|
1235
|
-
|
|
1236
|
-
const result = await loadSources({
|
|
1237
|
-
sourcesPath: testDir,
|
|
1238
|
-
"doc-path": "/api/overview",
|
|
1239
|
-
includePatterns: null,
|
|
1240
|
-
useDefaultPatterns: false,
|
|
1241
|
-
outputDir: tempDir,
|
|
1242
|
-
docsDir: docsDir,
|
|
1243
|
-
});
|
|
1244
|
-
|
|
1245
|
-
expect(result.files?.length).toBe(0);
|
|
1246
|
-
});
|
|
1247
|
-
});
|
|
1248
|
-
|
|
1249
|
-
describe("Token and line counting", () => {
|
|
1250
|
-
test("should count tokens and lines in source content", async () => {
|
|
1251
|
-
// Create files with known content for counting
|
|
1252
|
-
await writeFile(
|
|
1253
|
-
path.join(testDir, "count-test.js"),
|
|
1254
|
-
"// This file has words and lines\nconst message = 'hello world';\nconsole.log(message);\n\n// Another comment\nfunction test() {\n return true;\n}",
|
|
1255
|
-
);
|
|
1256
|
-
|
|
1257
|
-
const result = await loadSources({
|
|
1258
|
-
sourcesPath: testDir,
|
|
1259
|
-
includePatterns: ["count-test.js"],
|
|
1260
|
-
useDefaultPatterns: false,
|
|
1261
|
-
outputDir: tempDir,
|
|
1262
|
-
docsDir: path.join(testDir, "docs"),
|
|
1263
|
-
});
|
|
1264
|
-
|
|
1265
|
-
expect(result.totalTokens).toBeGreaterThan(0);
|
|
1266
|
-
expect(result.totalLines).toBeGreaterThan(0);
|
|
1267
|
-
expect(typeof result.totalTokens).toBe("number");
|
|
1268
|
-
expect(typeof result.totalLines).toBe("number");
|
|
1269
|
-
});
|
|
1270
|
-
});
|
|
1271
|
-
|
|
1272
|
-
describe("Media file path and metadata processing", () => {
|
|
1273
|
-
test("should correctly process media file relativePath, fileName, and description", async () => {
|
|
1274
|
-
// Create media files in a specific structure to test the exact logic
|
|
1275
|
-
const mediaSubDir = path.join(testDir, "assets", "images");
|
|
1276
|
-
await mkdir(mediaSubDir, { recursive: true });
|
|
1277
|
-
|
|
1278
|
-
const imageFile = path.join(mediaSubDir, "company-logo.png");
|
|
1279
|
-
const videoFile = path.join(mediaSubDir, "demo-video.mp4");
|
|
1280
|
-
const svgFile = path.join(mediaSubDir, "icon-arrow.svg");
|
|
1281
|
-
|
|
1282
|
-
await writeFile(imageFile, "fake png data");
|
|
1283
|
-
await writeFile(videoFile, "fake video data");
|
|
1284
|
-
await writeFile(svgFile, "<svg>fake svg</svg>");
|
|
1285
|
-
|
|
1286
|
-
const docsDir = path.join(testDir, "docs");
|
|
1287
|
-
|
|
1288
|
-
const result = await loadSources({
|
|
1289
|
-
sourcesPath: mediaSubDir,
|
|
1290
|
-
includePatterns: ["**/*"],
|
|
1291
|
-
useDefaultPatterns: false,
|
|
1292
|
-
outputDir: tempDir,
|
|
1293
|
-
docsDir: docsDir,
|
|
1294
|
-
});
|
|
1295
|
-
|
|
1296
|
-
expect(result.assetsContent).toBeDefined();
|
|
1297
|
-
|
|
1298
|
-
// Check that relativePath calculation worked (line 151)
|
|
1299
|
-
expect(result.assetsContent).toContain("../assets/images/company-logo.png");
|
|
1300
|
-
expect(result.assetsContent).toContain("../assets/images/demo-video.mp4");
|
|
1301
|
-
expect(result.assetsContent).toContain("../assets/images/icon-arrow.svg");
|
|
1302
|
-
|
|
1303
|
-
// Check that fileName extraction worked (line 152)
|
|
1304
|
-
expect(result.assetsContent).toContain('name: "company-logo.png"');
|
|
1305
|
-
expect(result.assetsContent).toContain('name: "demo-video.mp4"');
|
|
1306
|
-
expect(result.assetsContent).toContain('name: "icon-arrow.svg"');
|
|
1307
|
-
|
|
1308
|
-
// Test with complex filenames to ensure path.parse works correctly
|
|
1309
|
-
const complexFile = path.join(mediaSubDir, "my-complex.file-name.with.dots.jpg");
|
|
1310
|
-
await writeFile(complexFile, "fake jpg data");
|
|
1311
|
-
|
|
1312
|
-
const result2 = await loadSources({
|
|
1313
|
-
sourcesPath: mediaSubDir,
|
|
1314
|
-
includePatterns: ["my-complex.file-name.with.dots.jpg"],
|
|
1315
|
-
useDefaultPatterns: false,
|
|
1316
|
-
outputDir: tempDir,
|
|
1317
|
-
docsDir: docsDir,
|
|
1318
|
-
});
|
|
1319
|
-
|
|
1320
|
-
expect(result2.assetsContent).toContain('name: "my-complex.file-name.with.dots.jpg"');
|
|
1321
|
-
expect(result2.assetsContent).toContain(
|
|
1322
|
-
"../assets/images/my-complex.file-name.with.dots.jpg",
|
|
1323
|
-
);
|
|
1324
|
-
});
|
|
1325
|
-
|
|
1326
|
-
test("should handle media files with same docsDir path correctly", async () => {
|
|
1327
|
-
// Test when media files are in the same directory as docsDir
|
|
1328
|
-
const docsDir = path.join(testDir, "docs");
|
|
1329
|
-
const mediaFile = path.join(docsDir, "logo.png");
|
|
1330
|
-
|
|
1331
|
-
await writeFile(mediaFile, "fake logo data");
|
|
1332
|
-
|
|
1333
|
-
const result = await loadSources({
|
|
1334
|
-
sourcesPath: docsDir,
|
|
1335
|
-
includePatterns: ["*.png"],
|
|
1336
|
-
useDefaultPatterns: false,
|
|
1337
|
-
outputDir: tempDir,
|
|
1338
|
-
docsDir: docsDir,
|
|
1339
|
-
});
|
|
1340
|
-
|
|
1341
|
-
// When file is in docsDir, relativePath should be just the filename
|
|
1342
|
-
expect(result.assetsContent).toContain('path: "logo.png"');
|
|
1343
|
-
expect(result.assetsContent).toContain('name: "logo.png"');
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
|
-
test("should handle media files in parent directory relative to docsDir", async () => {
|
|
1347
|
-
// Test when media files are in parent directory of docsDir
|
|
1348
|
-
const docsDir = path.join(testDir, "documentation");
|
|
1349
|
-
await mkdir(docsDir, { recursive: true });
|
|
1350
|
-
|
|
1351
|
-
const mediaFile = path.join(testDir, "header-image.jpg");
|
|
1352
|
-
await writeFile(mediaFile, "fake header data");
|
|
1353
|
-
|
|
1354
|
-
const result = await loadSources({
|
|
1355
|
-
sourcesPath: testDir,
|
|
1356
|
-
includePatterns: ["header-image.jpg"],
|
|
1357
|
-
useDefaultPatterns: false,
|
|
1358
|
-
outputDir: tempDir,
|
|
1359
|
-
docsDir: docsDir,
|
|
1360
|
-
});
|
|
1361
|
-
|
|
1362
|
-
// When file is in parent of docsDir, relativePath should use ../
|
|
1363
|
-
expect(result.assetsContent).toContain('path: "../header-image.jpg"');
|
|
1364
|
-
expect(result.assetsContent).toContain('name: "header-image.jpg"');
|
|
1365
|
-
});
|
|
1366
|
-
});
|
|
1367
|
-
|
|
1368
|
-
describe("Edge cases and error handling", () => {
|
|
1369
|
-
test("should handle empty media files list", async () => {
|
|
1370
|
-
const result = await loadSources({
|
|
1371
|
-
sourcesPath: testDir,
|
|
1372
|
-
includePatterns: ["*.js"], // Only include non-media files
|
|
1373
|
-
useDefaultPatterns: false,
|
|
1374
|
-
outputDir: tempDir,
|
|
1375
|
-
docsDir: path.join(testDir, "docs"),
|
|
1376
|
-
});
|
|
1377
|
-
|
|
1378
|
-
expect(result.assetsContent).toBeDefined();
|
|
1379
|
-
expect(result.assetsContent).toContain("Available Media Assets");
|
|
1380
|
-
// Should have basic header even with no media files
|
|
1381
|
-
});
|
|
1382
|
-
|
|
1383
|
-
test("should handle mixed source and media files", async () => {
|
|
1384
|
-
// Create mixed content
|
|
1385
|
-
await writeFile(path.join(testDir, "mixed-test.js"), "console.log('code');");
|
|
1386
|
-
await writeFile(path.join(testDir, "mixed-image.png"), "fake png data");
|
|
1387
|
-
await writeFile(path.join(testDir, "mixed-doc.md"), "# Documentation");
|
|
1388
|
-
|
|
1389
|
-
const result = await loadSources({
|
|
1390
|
-
sourcesPath: testDir,
|
|
1391
|
-
includePatterns: ["mixed-*"],
|
|
1392
|
-
useDefaultPatterns: false,
|
|
1393
|
-
outputDir: tempDir,
|
|
1394
|
-
docsDir: path.join(testDir, "docs"),
|
|
1395
|
-
});
|
|
1396
|
-
|
|
1397
|
-
expect(result.files.length).toBeGreaterThan(0);
|
|
1398
|
-
expect(result.assetsContent).toContain("mixed-image.png");
|
|
1399
|
-
|
|
1400
|
-
// Verify both source files and media files are processed
|
|
1401
|
-
const sourceFiles = result.files;
|
|
1402
|
-
expect(sourceFiles.some((f) => f.includes("mixed-test.js"))).toBe(true);
|
|
1403
|
-
expect(sourceFiles.some((f) => f.includes("mixed-doc.md"))).toBe(true);
|
|
1404
|
-
});
|
|
1405
|
-
|
|
1406
|
-
test("should handle various media file types", async () => {
|
|
1407
|
-
const mediaTypes = [
|
|
1408
|
-
{ name: "test.jpg", type: "image" },
|
|
1409
|
-
{ name: "test.jpeg", type: "image" },
|
|
1410
|
-
{ name: "test.png", type: "image" },
|
|
1411
|
-
{ name: "test.gif", type: "image" },
|
|
1412
|
-
{ name: "test.webp", type: "image" },
|
|
1413
|
-
{ name: "test.svg", type: "image" },
|
|
1414
|
-
{ name: "test.mp4", type: "video" },
|
|
1415
|
-
{ name: "test.mov", type: "video" },
|
|
1416
|
-
{ name: "test.avi", type: "video" },
|
|
1417
|
-
{ name: "test.webm", type: "video" },
|
|
1418
|
-
];
|
|
1419
|
-
|
|
1420
|
-
// Create all media file types
|
|
1421
|
-
for (const media of mediaTypes) {
|
|
1422
|
-
await writeFile(path.join(testDir, media.name), `fake ${media.type} data`);
|
|
1423
|
-
}
|
|
1424
|
-
|
|
1425
|
-
const result = await loadSources({
|
|
1426
|
-
sourcesPath: testDir,
|
|
1427
|
-
includePatterns: ["test.*"],
|
|
1428
|
-
useDefaultPatterns: false,
|
|
1429
|
-
outputDir: tempDir,
|
|
1430
|
-
docsDir: path.join(testDir, "docs"),
|
|
1431
|
-
});
|
|
1432
|
-
|
|
1433
|
-
// Verify all media types are properly categorized
|
|
1434
|
-
for (const media of mediaTypes) {
|
|
1435
|
-
expect(result.assetsContent).toContain(media.name);
|
|
1436
|
-
expect(result.assetsContent).toContain(`type: "${media.type}"`);
|
|
1437
|
-
}
|
|
1438
|
-
});
|
|
1439
|
-
});
|
|
1440
|
-
|
|
1441
|
-
// Global cleanup to ensure test directories are fully removed
|
|
1442
|
-
afterAll(async () => {
|
|
1443
|
-
// Clean up all test-content-generator directories (including unique ones)
|
|
1444
|
-
try {
|
|
1445
|
-
const { readdir } = await import("node:fs/promises");
|
|
1446
|
-
const entries = await readdir(__dirname, { withFileTypes: true });
|
|
1447
|
-
|
|
1448
|
-
for (const entry of entries) {
|
|
1449
|
-
if (entry.isDirectory() && entry.name.startsWith("test-content-generator")) {
|
|
1450
|
-
const testDirToClean = path.join(__dirname, entry.name);
|
|
1451
|
-
try {
|
|
1452
|
-
await rm(testDirToClean, { recursive: true, force: true });
|
|
1453
|
-
} catch {
|
|
1454
|
-
// Try with system command as fallback
|
|
1455
|
-
try {
|
|
1456
|
-
const { exec } = await import("node:child_process");
|
|
1457
|
-
const { promisify } = await import("node:util");
|
|
1458
|
-
const execAsync = promisify(exec);
|
|
1459
|
-
await execAsync(`rm -rf "${testDirToClean}"`);
|
|
1460
|
-
} catch {
|
|
1461
|
-
console.warn(`Warning: Could not fully clean up test directory: ${testDirToClean}`);
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
} catch (error) {
|
|
1467
|
-
console.warn(`Warning: Could not clean up test directories: ${error.message}`);
|
|
1468
|
-
}
|
|
1469
|
-
});
|
|
1470
|
-
});
|