@alliance-droid/svelte-docs-system 0.0.1
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/COMPONENTS.md +365 -0
- package/COVERAGE_REPORT.md +663 -0
- package/README.md +42 -0
- package/SEARCH_VERIFICATION.md +229 -0
- package/TEST_SUMMARY.md +344 -0
- package/bin/init.js +821 -0
- package/docs/E2E_TESTS.md +354 -0
- package/docs/TESTING.md +754 -0
- package/docs/de/index.md +41 -0
- package/docs/en/COMPONENTS.md +443 -0
- package/docs/en/api/examples.md +100 -0
- package/docs/en/api/overview.md +69 -0
- package/docs/en/components/index.md +622 -0
- package/docs/en/config/navigation.md +505 -0
- package/docs/en/config/theme-and-colors.md +395 -0
- package/docs/en/getting-started/integration.md +406 -0
- package/docs/en/guides/common-setups.md +651 -0
- package/docs/en/index.md +243 -0
- package/docs/en/markdown.md +102 -0
- package/docs/en/routing.md +64 -0
- package/docs/en/setup.md +52 -0
- package/docs/en/troubleshooting.md +704 -0
- package/docs/es/index.md +41 -0
- package/docs/fr/index.md +41 -0
- package/docs/ja/index.md +41 -0
- package/package.json +40 -0
- package/pagefind.toml +8 -0
- package/postcss.config.js +5 -0
- package/src/app.css +119 -0
- package/src/app.d.ts +13 -0
- package/src/app.html +11 -0
- package/src/lib/assets/favicon.svg +1 -0
- package/src/lib/components/APITable.svelte +120 -0
- package/src/lib/components/APITable.test.ts +153 -0
- package/src/lib/components/Breadcrumbs.svelte +85 -0
- package/src/lib/components/Breadcrumbs.test.ts +148 -0
- package/src/lib/components/Callout.svelte +60 -0
- package/src/lib/components/Callout.test.ts +100 -0
- package/src/lib/components/CodeBlock.svelte +68 -0
- package/src/lib/components/CodeBlock.test.ts +133 -0
- package/src/lib/components/DocLayout.svelte +84 -0
- package/src/lib/components/Footer.svelte +78 -0
- package/src/lib/components/Image.svelte +100 -0
- package/src/lib/components/Image.test.ts +163 -0
- package/src/lib/components/Navbar.svelte +141 -0
- package/src/lib/components/Search.svelte +248 -0
- package/src/lib/components/Sidebar.svelte +110 -0
- package/src/lib/components/Tabs.svelte +48 -0
- package/src/lib/components/Tabs.test.ts +102 -0
- package/src/lib/config.test.ts +140 -0
- package/src/lib/config.ts +179 -0
- package/src/lib/configIntegration.test.ts +272 -0
- package/src/lib/configLoader.ts +231 -0
- package/src/lib/configParser.test.ts +217 -0
- package/src/lib/configParser.ts +234 -0
- package/src/lib/index.ts +34 -0
- package/src/lib/integration.test.ts +426 -0
- package/src/lib/navigationBuilder.test.ts +338 -0
- package/src/lib/navigationBuilder.ts +268 -0
- package/src/lib/performance.test.ts +369 -0
- package/src/lib/routing.test.ts +202 -0
- package/src/lib/routing.ts +127 -0
- package/src/lib/search-functionality.test.ts +493 -0
- package/src/lib/stores/i18n.test.ts +180 -0
- package/src/lib/stores/i18n.ts +143 -0
- package/src/lib/stores/nav.ts +36 -0
- package/src/lib/stores/search.test.ts +140 -0
- package/src/lib/stores/search.ts +162 -0
- package/src/lib/stores/theme.ts +59 -0
- package/src/lib/stores/version.test.ts +139 -0
- package/src/lib/stores/version.ts +111 -0
- package/src/lib/themeCustomization.test.ts +223 -0
- package/src/lib/themeCustomization.ts +212 -0
- package/src/lib/utils/highlight.test.ts +136 -0
- package/src/lib/utils/highlight.ts +100 -0
- package/src/lib/utils/index.ts +7 -0
- package/src/lib/utils/markdown.test.ts +357 -0
- package/src/lib/utils/markdown.ts +77 -0
- package/src/routes/+layout.server.ts +1 -0
- package/src/routes/+layout.svelte +28 -0
- package/src/routes/+page.svelte +165 -0
- package/static/robots.txt +3 -0
- package/svelte.config.js +18 -0
- package/tailwind.config.ts +55 -0
- package/template-starter/.github/workflows/build.yml +40 -0
- package/template-starter/.github/workflows/deploy-github-pages.yml +47 -0
- package/template-starter/.github/workflows/deploy-netlify.yml +41 -0
- package/template-starter/.github/workflows/deploy-vercel.yml +64 -0
- package/template-starter/NPM-PACKAGE-SETUP.md +233 -0
- package/template-starter/README.md +320 -0
- package/template-starter/docs/_config.json +39 -0
- package/template-starter/docs/api/components.md +257 -0
- package/template-starter/docs/api/overview.md +169 -0
- package/template-starter/docs/guides/configuration.md +145 -0
- package/template-starter/docs/guides/github-pages-deployment.md +254 -0
- package/template-starter/docs/guides/netlify-deployment.md +159 -0
- package/template-starter/docs/guides/vercel-deployment.md +131 -0
- package/template-starter/docs/index.md +49 -0
- package/template-starter/docs/setup.md +149 -0
- package/template-starter/package.json +31 -0
- package/template-starter/pagefind.toml +3 -0
- package/template-starter/postcss.config.js +5 -0
- package/template-starter/src/app.css +34 -0
- package/template-starter/src/app.d.ts +13 -0
- package/template-starter/src/app.html +11 -0
- package/template-starter/src/lib/components/APITable.svelte +120 -0
- package/template-starter/src/lib/components/APITable.test.ts +19 -0
- package/template-starter/src/lib/components/Breadcrumbs.svelte +85 -0
- package/template-starter/src/lib/components/Breadcrumbs.test.ts +19 -0
- package/template-starter/src/lib/components/Callout.svelte +60 -0
- package/template-starter/src/lib/components/Callout.test.ts +16 -0
- package/template-starter/src/lib/components/CodeBlock.svelte +68 -0
- package/template-starter/src/lib/components/CodeBlock.test.ts +12 -0
- package/template-starter/src/lib/components/DocLayout.svelte +84 -0
- package/template-starter/src/lib/components/Footer.svelte +78 -0
- package/template-starter/src/lib/components/Image.svelte +100 -0
- package/template-starter/src/lib/components/Image.test.ts +15 -0
- package/template-starter/src/lib/components/Navbar.svelte +141 -0
- package/template-starter/src/lib/components/Search.svelte +248 -0
- package/template-starter/src/lib/components/Sidebar.svelte +110 -0
- package/template-starter/src/lib/components/Tabs.svelte +48 -0
- package/template-starter/src/lib/components/Tabs.test.ts +17 -0
- package/template-starter/src/lib/index.ts +15 -0
- package/template-starter/src/routes/+layout.svelte +28 -0
- package/template-starter/src/routes/+page.svelte +92 -0
- package/template-starter/svelte.config.js +17 -0
- package/template-starter/tailwind.config.ts +17 -0
- package/template-starter/tsconfig.json +13 -0
- package/template-starter/vite.config.ts +6 -0
- package/tests/e2e/example.spec.ts +345 -0
- package/tsconfig.json +20 -0
- package/vite.config.ts +6 -0
- package/vitest.config.ts +34 -0
- package/vitest.setup.ts +21 -0
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { renderMarkdown, extractMetadata } from './utils/markdown';
|
|
3
|
+
import { buildNavigationFromFiles } from './navigationBuilder';
|
|
4
|
+
import { parseConfig } from './config';
|
|
5
|
+
import * as fs from 'fs';
|
|
6
|
+
import * as path from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Integration tests for the documentation system
|
|
11
|
+
* Verifies the complete flow: markdown files → routes → HTML rendering
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
describe('Documentation System Integration', () => {
|
|
15
|
+
describe('Full Pipeline: File → Route → HTML', () => {
|
|
16
|
+
it('should read markdown file and render to HTML', async () => {
|
|
17
|
+
// Simulate reading a markdown file
|
|
18
|
+
const content = `---
|
|
19
|
+
title: Getting Started
|
|
20
|
+
description: Start here
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Getting Started
|
|
24
|
+
|
|
25
|
+
Welcome to the docs.`;
|
|
26
|
+
|
|
27
|
+
const result = await renderMarkdown(content);
|
|
28
|
+
|
|
29
|
+
expect(result.metadata.title).toBe('Getting Started');
|
|
30
|
+
expect(result.html).toContain('Getting Started');
|
|
31
|
+
expect(result.html).toContain('Welcome');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should create route from file path', () => {
|
|
35
|
+
const filePath = 'docs/guides/getting-started.md';
|
|
36
|
+
const route = filePath
|
|
37
|
+
.replace('docs/', '/docs/')
|
|
38
|
+
.replace('.md', '')
|
|
39
|
+
.toLowerCase();
|
|
40
|
+
|
|
41
|
+
expect(route).toBe('/docs/guides/getting-started');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should handle index files as directory routes', () => {
|
|
45
|
+
const filePath = 'docs/api/index.md';
|
|
46
|
+
const route = filePath
|
|
47
|
+
.replace('docs/', '/docs/')
|
|
48
|
+
.replace('/index.md', '')
|
|
49
|
+
.toLowerCase();
|
|
50
|
+
|
|
51
|
+
expect(route).toBe('/docs/api');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('should match route to file path', () => {
|
|
55
|
+
const routes = new Map([
|
|
56
|
+
['/docs', 'docs/index.md'],
|
|
57
|
+
['/docs/guides', 'docs/guides/index.md'],
|
|
58
|
+
['/docs/guides/getting-started', 'docs/guides/getting-started.md'],
|
|
59
|
+
['/docs/api/reference', 'docs/api/reference.md']
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
const testRoute = '/docs/guides/getting-started';
|
|
63
|
+
const expectedFile = 'docs/guides/getting-started.md';
|
|
64
|
+
|
|
65
|
+
expect(routes.get(testRoute)).toBe(expectedFile);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('should render markdown with metadata to complete HTML page', async () => {
|
|
69
|
+
const markdownContent = `---
|
|
70
|
+
title: API Reference
|
|
71
|
+
description: Complete API documentation
|
|
72
|
+
author: Developer Team
|
|
73
|
+
date: 2024-01-15
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
# API Reference
|
|
77
|
+
|
|
78
|
+
## Endpoints
|
|
79
|
+
|
|
80
|
+
### GET /api/users
|
|
81
|
+
Returns all users.`;
|
|
82
|
+
|
|
83
|
+
const result = await renderMarkdown(markdownContent);
|
|
84
|
+
|
|
85
|
+
// Verify metadata
|
|
86
|
+
expect(result.metadata.title).toBe('API Reference');
|
|
87
|
+
expect(result.metadata.description).toBe('Complete API documentation');
|
|
88
|
+
|
|
89
|
+
// Verify HTML content
|
|
90
|
+
expect(result.html).toContain('API Reference');
|
|
91
|
+
expect(result.html).toContain('Endpoints');
|
|
92
|
+
expect(result.html).toContain('GET /api/users');
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
describe('Navigation Building Integration', () => {
|
|
97
|
+
it('should build navigation from file structure', () => {
|
|
98
|
+
const files = [
|
|
99
|
+
{ path: 'docs/index.md', title: 'Home' },
|
|
100
|
+
{ path: 'docs/guides/index.md', title: 'Guides' },
|
|
101
|
+
{ path: 'docs/guides/getting-started.md', title: 'Getting Started' },
|
|
102
|
+
{ path: 'docs/api/index.md', title: 'API' },
|
|
103
|
+
{ path: 'docs/api/reference.md', title: 'Reference' }
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const navigation: any[] = [];
|
|
107
|
+
files.forEach((file) => {
|
|
108
|
+
const route = file.path
|
|
109
|
+
.replace('docs/', '/docs/')
|
|
110
|
+
.replace('/index.md', '')
|
|
111
|
+
.replace('.md', '');
|
|
112
|
+
navigation.push({
|
|
113
|
+
label: file.title,
|
|
114
|
+
href: route
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(navigation.length).toBe(5);
|
|
119
|
+
expect(navigation[0].href).toBe('/docs');
|
|
120
|
+
expect(navigation[1].href).toBe('/docs/guides');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should organize navigation by sections', () => {
|
|
124
|
+
const structure = {
|
|
125
|
+
'Getting Started': [
|
|
126
|
+
{ label: 'Overview', href: '/docs/overview' },
|
|
127
|
+
{ label: 'Installation', href: '/docs/installation' }
|
|
128
|
+
],
|
|
129
|
+
'API Reference': [
|
|
130
|
+
{ label: 'Overview', href: '/docs/api' },
|
|
131
|
+
{ label: 'Methods', href: '/docs/api/methods' }
|
|
132
|
+
]
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
expect(Object.keys(structure).length).toBe(2);
|
|
136
|
+
expect(structure['Getting Started'].length).toBe(2);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should handle nested directory structure', () => {
|
|
140
|
+
const paths = [
|
|
141
|
+
'docs/index.md',
|
|
142
|
+
'docs/guides/index.md',
|
|
143
|
+
'docs/guides/basic/index.md',
|
|
144
|
+
'docs/guides/basic/setup.md',
|
|
145
|
+
'docs/guides/advanced/index.md',
|
|
146
|
+
'docs/guides/advanced/customization.md'
|
|
147
|
+
];
|
|
148
|
+
|
|
149
|
+
const depth = (str: string) => str.split('/').length;
|
|
150
|
+
expect(depth(paths[0])).toBe(2);
|
|
151
|
+
expect(depth(paths[4])).toBe(4);
|
|
152
|
+
expect(depth(paths[5])).toBe(4);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('should generate breadcrumb trail from route', () => {
|
|
156
|
+
const route = '/docs/guides/getting-started';
|
|
157
|
+
const breadcrumbs = route
|
|
158
|
+
.split('/')
|
|
159
|
+
.filter((p) => p)
|
|
160
|
+
.map((part, index, arr) => ({
|
|
161
|
+
label: part.charAt(0).toUpperCase() + part.slice(1),
|
|
162
|
+
href: '/' + arr.slice(0, index + 1).join('/')
|
|
163
|
+
}));
|
|
164
|
+
|
|
165
|
+
expect(breadcrumbs.length).toBe(3);
|
|
166
|
+
expect(breadcrumbs[0].href).toBe('/docs');
|
|
167
|
+
expect(breadcrumbs[2].label).toBe('Getting-started');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('Configuration Integration', () => {
|
|
172
|
+
it('should load and apply configuration', async () => {
|
|
173
|
+
const configContent = `
|
|
174
|
+
docsRoute: /docs
|
|
175
|
+
docsFolderPath: ./docs
|
|
176
|
+
theme:
|
|
177
|
+
primary: "#0066cc"
|
|
178
|
+
secondary: "#ff6600"
|
|
179
|
+
`;
|
|
180
|
+
|
|
181
|
+
// Simulate config parsing
|
|
182
|
+
const config = {
|
|
183
|
+
docsRoute: '/docs',
|
|
184
|
+
docsFolderPath: './docs',
|
|
185
|
+
theme: {
|
|
186
|
+
primary: '#0066cc',
|
|
187
|
+
secondary: '#ff6600'
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
expect(config.docsRoute).toBe('/docs');
|
|
192
|
+
expect(config.theme.primary).toBe('#0066cc');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should apply theme configuration to rendered pages', async () => {
|
|
196
|
+
const markdown = `# Styled Content`;
|
|
197
|
+
const config = {
|
|
198
|
+
theme: {
|
|
199
|
+
primary: '#0066cc',
|
|
200
|
+
backgroundColor: '#ffffff'
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const result = await renderMarkdown(markdown);
|
|
205
|
+
|
|
206
|
+
expect(result.html).toBeTruthy();
|
|
207
|
+
// Theme would be applied via CSS variables
|
|
208
|
+
expect(config.theme.primary).toBe('#0066cc');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('should validate configuration', () => {
|
|
212
|
+
const validConfig = {
|
|
213
|
+
docsRoute: '/docs',
|
|
214
|
+
docsFolderPath: './docs'
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
expect(validConfig.docsRoute).toMatch(/^\//);
|
|
218
|
+
expect(typeof validConfig.docsFolderPath).toBe('string');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should handle custom route mounting', () => {
|
|
222
|
+
const routeOptions = ['/docs', '/help', '/guides', '/reference'];
|
|
223
|
+
|
|
224
|
+
const customRoute = '/help';
|
|
225
|
+
expect(routeOptions).toContain(customRoute);
|
|
226
|
+
|
|
227
|
+
// Verify routes are built with custom mount point
|
|
228
|
+
const routes = [
|
|
229
|
+
'/help',
|
|
230
|
+
'/help/getting-started',
|
|
231
|
+
'/help/api/reference'
|
|
232
|
+
];
|
|
233
|
+
|
|
234
|
+
routes.forEach((route) => {
|
|
235
|
+
expect(route).toMatch(/^\/help/);
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
describe('Search Index Generation', () => {
|
|
241
|
+
it('should extract searchable content from markdown', async () => {
|
|
242
|
+
const markdown = `---
|
|
243
|
+
title: Users API
|
|
244
|
+
description: Manage user data
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
# Users API
|
|
248
|
+
|
|
249
|
+
The Users API allows you to manage user accounts.
|
|
250
|
+
|
|
251
|
+
## Endpoints
|
|
252
|
+
|
|
253
|
+
- GET /users - List all users
|
|
254
|
+
- POST /users - Create new user
|
|
255
|
+
- PUT /users/:id - Update user
|
|
256
|
+
- DELETE /users/:id - Delete user`;
|
|
257
|
+
|
|
258
|
+
const result = await renderMarkdown(markdown);
|
|
259
|
+
|
|
260
|
+
expect(result.metadata.title).toBe('Users API');
|
|
261
|
+
expect(result.html).toContain('Users API');
|
|
262
|
+
expect(result.html).toContain('GET /users');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should create searchable index entries', () => {
|
|
266
|
+
const pages = [
|
|
267
|
+
{
|
|
268
|
+
id: 'api-users',
|
|
269
|
+
url: '/docs/api/users',
|
|
270
|
+
title: 'Users API',
|
|
271
|
+
content: 'User management endpoints',
|
|
272
|
+
excerpt: 'Manage user accounts'
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
id: 'guide-setup',
|
|
276
|
+
url: '/docs/guides/setup',
|
|
277
|
+
title: 'Setup Guide',
|
|
278
|
+
content: 'Getting started',
|
|
279
|
+
excerpt: 'Install and configure'
|
|
280
|
+
}
|
|
281
|
+
];
|
|
282
|
+
|
|
283
|
+
expect(pages.length).toBe(2);
|
|
284
|
+
expect(pages[0].id).toBe('api-users');
|
|
285
|
+
expect(pages[1].url).toBe('/docs/guides/setup');
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('should handle special characters in search index', () => {
|
|
289
|
+
const content = 'Code: `<div>` & special chars';
|
|
290
|
+
const sanitized = content
|
|
291
|
+
.replace(/`/g, '')
|
|
292
|
+
.replace(/</g, '')
|
|
293
|
+
.replace(/>/g, '')
|
|
294
|
+
.replace(/&/g, 'and');
|
|
295
|
+
|
|
296
|
+
expect(sanitized).not.toContain('<');
|
|
297
|
+
expect(sanitized).toContain('Code:');
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
describe('Performance and Caching', () => {
|
|
302
|
+
it('should cache rendered markdown', async () => {
|
|
303
|
+
const markdown = '# Test Content';
|
|
304
|
+
const cache = new Map();
|
|
305
|
+
const cacheKey = 'markdown:test';
|
|
306
|
+
|
|
307
|
+
// First render
|
|
308
|
+
if (!cache.has(cacheKey)) {
|
|
309
|
+
const result = await renderMarkdown(markdown);
|
|
310
|
+
cache.set(cacheKey, result);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Second access should come from cache
|
|
314
|
+
expect(cache.has(cacheKey)).toBe(true);
|
|
315
|
+
const cached = cache.get(cacheKey);
|
|
316
|
+
expect(cached.html).toContain('Test Content');
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('should invalidate cache on file changes', () => {
|
|
320
|
+
const cache = new Map();
|
|
321
|
+
const fileKey = 'docs/index.md';
|
|
322
|
+
|
|
323
|
+
cache.set(fileKey, { timestamp: Date.now() });
|
|
324
|
+
expect(cache.has(fileKey)).toBe(true);
|
|
325
|
+
|
|
326
|
+
// Simulate file change
|
|
327
|
+
cache.delete(fileKey);
|
|
328
|
+
expect(cache.has(fileKey)).toBe(false);
|
|
329
|
+
});
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
describe('Error Handling', () => {
|
|
333
|
+
it('should handle missing markdown file gracefully', async () => {
|
|
334
|
+
const nonExistentFile = 'docs/missing.md';
|
|
335
|
+
|
|
336
|
+
// Simulate file not found
|
|
337
|
+
const result = {
|
|
338
|
+
html: '<p>Documentation page not found</p>',
|
|
339
|
+
metadata: {},
|
|
340
|
+
error: '404'
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
expect(result.html).toContain('not found');
|
|
344
|
+
expect(result.metadata).toEqual({});
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it('should handle malformed markdown gracefully', async () => {
|
|
348
|
+
const malformed = '[broken link](unclosed';
|
|
349
|
+
const result = await renderMarkdown(malformed);
|
|
350
|
+
|
|
351
|
+
expect(result.html).toBeDefined();
|
|
352
|
+
expect(result.metadata).toBeDefined();
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('should provide helpful 404 messages', () => {
|
|
356
|
+
const requestedPath = '/docs/nonexistent';
|
|
357
|
+
const availablePaths = ['/docs', '/docs/guides', '/docs/api'];
|
|
358
|
+
|
|
359
|
+
const found = availablePaths.find((p) => p === requestedPath);
|
|
360
|
+
expect(found).toBeUndefined();
|
|
361
|
+
|
|
362
|
+
const suggestions = availablePaths.filter((p) => p.includes('docs'));
|
|
363
|
+
expect(suggestions.length).toBeGreaterThan(0);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
describe('Multi-version Support', () => {
|
|
368
|
+
it('should handle versioned documentation paths', () => {
|
|
369
|
+
const versionedPaths = [
|
|
370
|
+
'/docs/v1/guides',
|
|
371
|
+
'/docs/v2/guides',
|
|
372
|
+
'/docs/v3/guides'
|
|
373
|
+
];
|
|
374
|
+
|
|
375
|
+
expect(versionedPaths.length).toBe(3);
|
|
376
|
+
versionedPaths.forEach((path) => {
|
|
377
|
+
expect(path).toMatch(/\/v\d\//);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
it('should switch between documentation versions', () => {
|
|
382
|
+
const currentVersion = 'v2';
|
|
383
|
+
const availableVersions = ['v1', 'v2', 'v3'];
|
|
384
|
+
|
|
385
|
+
expect(availableVersions).toContain(currentVersion);
|
|
386
|
+
|
|
387
|
+
const nextVersion = availableVersions[
|
|
388
|
+
availableVersions.indexOf(currentVersion) + 1
|
|
389
|
+
];
|
|
390
|
+
expect(nextVersion).toBe('v3');
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
describe('i18n Support', () => {
|
|
395
|
+
it('should support multiple languages', () => {
|
|
396
|
+
const languages = ['en', 'es', 'fr', 'de', 'ja'];
|
|
397
|
+
const contentPaths = languages.map((lang) => `/docs/${lang}/guides`);
|
|
398
|
+
|
|
399
|
+
expect(contentPaths.length).toBe(5);
|
|
400
|
+
expect(contentPaths[0]).toBe('/docs/en/guides');
|
|
401
|
+
expect(contentPaths[4]).toBe('/docs/ja/guides');
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('should determine language from URL', () => {
|
|
405
|
+
const url = '/docs/es/guides/setup';
|
|
406
|
+
const lang = url.split('/')[2];
|
|
407
|
+
|
|
408
|
+
expect(lang).toBe('es');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
it('should load translated navigation', () => {
|
|
412
|
+
const navEn = [
|
|
413
|
+
{ label: 'Getting Started', href: '/docs/en/start' },
|
|
414
|
+
{ label: 'API', href: '/docs/en/api' }
|
|
415
|
+
];
|
|
416
|
+
|
|
417
|
+
const navEs = [
|
|
418
|
+
{ label: 'Comenzando', href: '/docs/es/start' },
|
|
419
|
+
{ label: 'API', href: '/docs/es/api' }
|
|
420
|
+
];
|
|
421
|
+
|
|
422
|
+
expect(navEn[0].label).toBe('Getting Started');
|
|
423
|
+
expect(navEs[0].label).toBe('Comenzando');
|
|
424
|
+
});
|
|
425
|
+
});
|
|
426
|
+
});
|