pict-section-inlinedocumentation 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/README.md +107 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +83 -0
- package/docs/_cover.md +15 -0
- package/docs/_sidebar.md +24 -0
- package/docs/_topbar.md +8 -0
- package/docs/_version.json +7 -0
- package/docs/api-reference.md +185 -0
- package/docs/architecture.md +103 -0
- package/docs/css/docuserve.css +327 -0
- package/docs/embedding-level1-sidebar.md +92 -0
- package/docs/embedding-level2-routes.md +86 -0
- package/docs/embedding-level3-tooltips.md +97 -0
- package/docs/embedding-level4-autogen.md +126 -0
- package/docs/index.html +39 -0
- package/docs/overview.md +42 -0
- package/docs/quickstart.md +95 -0
- package/docs/reference.md +73 -0
- package/docs/retold-catalog.json +181 -0
- package/docs/retold-keyword-index.json +4374 -0
- package/example_applications/basic/docs/README.md +40 -0
- package/example_applications/basic/docs/_sidebar.md +4 -0
- package/example_applications/basic/docs/_topics.json +10 -0
- package/example_applications/basic/docs/advanced-topics.md +47 -0
- package/example_applications/basic/docs/getting-started.md +70 -0
- package/example_applications/basic/index.html +100 -0
- package/example_applications/bookshop/.quackage.json +10 -0
- package/example_applications/bookshop/Pict-Application-Bookshop-Configuration.json +15 -0
- package/example_applications/bookshop/Pict-Application-Bookshop.js +218 -0
- package/example_applications/bookshop/data/BookshopData.json +65 -0
- package/example_applications/bookshop/data/pict_documentation_topics.json +46 -0
- package/example_applications/bookshop/docs/_sidebar.md +6 -0
- package/example_applications/bookshop/docs/book-detail.md +21 -0
- package/example_applications/bookshop/docs/book-list.md +21 -0
- package/example_applications/bookshop/docs/search-filter.md +18 -0
- package/example_applications/bookshop/docs/store.md +29 -0
- package/example_applications/bookshop/docs/welcome.md +23 -0
- package/example_applications/bookshop/html/index.html +236 -0
- package/example_applications/bookshop/package.json +34 -0
- package/example_applications/bookshop/views/PictView-Bookshop-BookList.js +324 -0
- package/example_applications/bookshop/views/PictView-Bookshop-HelpToggle.js +44 -0
- package/example_applications/bookshop/views/PictView-Bookshop-Store.js +271 -0
- package/package.json +55 -0
- package/source/Pict-Section-InlineDocumentation.js +10 -0
- package/source/providers/Pict-Provider-InlineDocumentation.js +1995 -0
- package/source/views/Pict-View-InlineDocumentation-Content.js +542 -0
- package/source/views/Pict-View-InlineDocumentation-Layout.js +206 -0
- package/source/views/Pict-View-InlineDocumentation-Nav.js +475 -0
- package/source/views/Pict-View-InlineDocumentation-TopicManager.js +1623 -0
- package/test/Browser_Integration_tests.js +1449 -0
- package/test/Pict-Section-InlineDocumentation_test.js +1285 -0
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
const libPict = require('pict');
|
|
2
|
+
const libInlineDocumentation = require('../source/Pict-Section-InlineDocumentation.js');
|
|
3
|
+
|
|
4
|
+
const libAssert = require('assert');
|
|
5
|
+
|
|
6
|
+
suite
|
|
7
|
+
(
|
|
8
|
+
'Pict-Section-InlineDocumentation',
|
|
9
|
+
() =>
|
|
10
|
+
{
|
|
11
|
+
setup(() => { });
|
|
12
|
+
|
|
13
|
+
suite
|
|
14
|
+
(
|
|
15
|
+
'Module Exports',
|
|
16
|
+
() =>
|
|
17
|
+
{
|
|
18
|
+
test
|
|
19
|
+
(
|
|
20
|
+
'Module should export the provider as the default export',
|
|
21
|
+
(fDone) =>
|
|
22
|
+
{
|
|
23
|
+
libAssert.strictEqual(typeof libInlineDocumentation, 'function', 'Default export should be a constructor');
|
|
24
|
+
libAssert.ok(libInlineDocumentation.default_configuration, 'Should export default_configuration');
|
|
25
|
+
libAssert.strictEqual(libInlineDocumentation.default_configuration.ProviderIdentifier, 'Pict-InlineDocumentation');
|
|
26
|
+
return fDone();
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
test
|
|
30
|
+
(
|
|
31
|
+
'Module should export view classes',
|
|
32
|
+
(fDone) =>
|
|
33
|
+
{
|
|
34
|
+
libAssert.strictEqual(typeof libInlineDocumentation.InlineDocumentationLayoutView, 'function', 'Should export layout view');
|
|
35
|
+
libAssert.strictEqual(typeof libInlineDocumentation.InlineDocumentationContentView, 'function', 'Should export content view');
|
|
36
|
+
libAssert.strictEqual(typeof libInlineDocumentation.InlineDocumentationNavView, 'function', 'Should export nav view');
|
|
37
|
+
return fDone();
|
|
38
|
+
}
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
suite
|
|
44
|
+
(
|
|
45
|
+
'Provider Registration',
|
|
46
|
+
() =>
|
|
47
|
+
{
|
|
48
|
+
test
|
|
49
|
+
(
|
|
50
|
+
'Provider should register with Pict and instantiate views',
|
|
51
|
+
(fDone) =>
|
|
52
|
+
{
|
|
53
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
54
|
+
|
|
55
|
+
let tmpProvider = tmpPict.addProvider(
|
|
56
|
+
'Pict-InlineDocumentation',
|
|
57
|
+
libInlineDocumentation.default_configuration,
|
|
58
|
+
libInlineDocumentation);
|
|
59
|
+
|
|
60
|
+
libAssert.ok(tmpProvider, 'Provider should be created');
|
|
61
|
+
libAssert.ok(tmpPict.providers['Pict-InlineDocumentation'], 'Provider should be registered');
|
|
62
|
+
|
|
63
|
+
// Views should be registered
|
|
64
|
+
libAssert.ok(tmpPict.views['InlineDoc-Layout'], 'Layout view should be registered');
|
|
65
|
+
libAssert.ok(tmpPict.views['InlineDoc-Content'], 'Content view should be registered');
|
|
66
|
+
libAssert.ok(tmpPict.views['InlineDoc-Nav'], 'Nav view should be registered');
|
|
67
|
+
|
|
68
|
+
// Content provider should be registered
|
|
69
|
+
libAssert.ok(tmpPict.providers['Pict-Content'], 'Content provider should be registered');
|
|
70
|
+
|
|
71
|
+
return fDone();
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
test
|
|
76
|
+
(
|
|
77
|
+
'Provider should have expected API methods',
|
|
78
|
+
(fDone) =>
|
|
79
|
+
{
|
|
80
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
81
|
+
|
|
82
|
+
let tmpProvider = tmpPict.addProvider(
|
|
83
|
+
'Pict-InlineDocumentation',
|
|
84
|
+
libInlineDocumentation.default_configuration,
|
|
85
|
+
libInlineDocumentation);
|
|
86
|
+
|
|
87
|
+
libAssert.strictEqual(typeof tmpProvider.initializeDocumentation, 'function', 'Should have initializeDocumentation');
|
|
88
|
+
libAssert.strictEqual(typeof tmpProvider.loadDocument, 'function', 'Should have loadDocument');
|
|
89
|
+
libAssert.strictEqual(typeof tmpProvider.setTopic, 'function', 'Should have setTopic');
|
|
90
|
+
libAssert.strictEqual(typeof tmpProvider.clearTopic, 'function', 'Should have clearTopic');
|
|
91
|
+
libAssert.strictEqual(typeof tmpProvider.setDocsBaseURL, 'function', 'Should have setDocsBaseURL');
|
|
92
|
+
libAssert.strictEqual(typeof tmpProvider.getNavigationHistory, 'function', 'Should have getNavigationHistory');
|
|
93
|
+
libAssert.strictEqual(typeof tmpProvider.navigateBack, 'function', 'Should have navigateBack');
|
|
94
|
+
|
|
95
|
+
return fDone();
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
suite
|
|
102
|
+
(
|
|
103
|
+
'State Management',
|
|
104
|
+
() =>
|
|
105
|
+
{
|
|
106
|
+
test
|
|
107
|
+
(
|
|
108
|
+
'setDocsBaseURL should update state and clear cache',
|
|
109
|
+
(fDone) =>
|
|
110
|
+
{
|
|
111
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
112
|
+
|
|
113
|
+
let tmpProvider = tmpPict.addProvider(
|
|
114
|
+
'Pict-InlineDocumentation',
|
|
115
|
+
libInlineDocumentation.default_configuration,
|
|
116
|
+
libInlineDocumentation);
|
|
117
|
+
|
|
118
|
+
tmpProvider.setDocsBaseURL('https://example.com/docs/');
|
|
119
|
+
|
|
120
|
+
libAssert.strictEqual(
|
|
121
|
+
tmpPict.AppData.InlineDocumentation.DocsBaseURL,
|
|
122
|
+
'https://example.com/docs/');
|
|
123
|
+
|
|
124
|
+
return fDone();
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
test
|
|
129
|
+
(
|
|
130
|
+
'getNavigationHistory should return empty array initially',
|
|
131
|
+
(fDone) =>
|
|
132
|
+
{
|
|
133
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
134
|
+
|
|
135
|
+
let tmpProvider = tmpPict.addProvider(
|
|
136
|
+
'Pict-InlineDocumentation',
|
|
137
|
+
libInlineDocumentation.default_configuration,
|
|
138
|
+
libInlineDocumentation);
|
|
139
|
+
|
|
140
|
+
let tmpHistory = tmpProvider.getNavigationHistory();
|
|
141
|
+
libAssert.ok(Array.isArray(tmpHistory), 'Should return an array');
|
|
142
|
+
libAssert.strictEqual(tmpHistory.length, 0, 'Should be empty initially');
|
|
143
|
+
|
|
144
|
+
return fDone();
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
suite
|
|
151
|
+
(
|
|
152
|
+
'Sidebar Parsing',
|
|
153
|
+
() =>
|
|
154
|
+
{
|
|
155
|
+
test
|
|
156
|
+
(
|
|
157
|
+
'Should parse _sidebar.md format into groups and items',
|
|
158
|
+
(fDone) =>
|
|
159
|
+
{
|
|
160
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
161
|
+
|
|
162
|
+
let tmpProvider = tmpPict.addProvider(
|
|
163
|
+
'Pict-InlineDocumentation',
|
|
164
|
+
libInlineDocumentation.default_configuration,
|
|
165
|
+
libInlineDocumentation);
|
|
166
|
+
|
|
167
|
+
let tmpSidebar = '- [Home](README.md)\n'
|
|
168
|
+
+ '- Guide\n'
|
|
169
|
+
+ ' - [Getting Started](getting-started.md)\n'
|
|
170
|
+
+ ' - [Advanced](advanced-topics.md)\n';
|
|
171
|
+
|
|
172
|
+
let tmpGroups = tmpProvider._parseSidebarMarkdown(tmpSidebar);
|
|
173
|
+
|
|
174
|
+
libAssert.strictEqual(tmpGroups.length, 2, 'Should have 2 groups');
|
|
175
|
+
|
|
176
|
+
// First group: Home (link)
|
|
177
|
+
libAssert.strictEqual(tmpGroups[0].Name, 'Home');
|
|
178
|
+
libAssert.strictEqual(tmpGroups[0].Path, 'README.md');
|
|
179
|
+
libAssert.strictEqual(tmpGroups[0].Items.length, 0);
|
|
180
|
+
|
|
181
|
+
// Second group: Guide (plain text header with children)
|
|
182
|
+
libAssert.strictEqual(tmpGroups[1].Name, 'Guide');
|
|
183
|
+
libAssert.strictEqual(tmpGroups[1].Path, '');
|
|
184
|
+
libAssert.strictEqual(tmpGroups[1].Items.length, 2);
|
|
185
|
+
libAssert.strictEqual(tmpGroups[1].Items[0].Name, 'Getting Started');
|
|
186
|
+
libAssert.strictEqual(tmpGroups[1].Items[0].Path, 'getting-started.md');
|
|
187
|
+
libAssert.strictEqual(tmpGroups[1].Items[1].Name, 'Advanced');
|
|
188
|
+
libAssert.strictEqual(tmpGroups[1].Items[1].Path, 'advanced-topics.md');
|
|
189
|
+
|
|
190
|
+
return fDone();
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
test
|
|
195
|
+
(
|
|
196
|
+
'Should handle leading slashes and ./ in paths',
|
|
197
|
+
(fDone) =>
|
|
198
|
+
{
|
|
199
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
200
|
+
|
|
201
|
+
let tmpProvider = tmpPict.addProvider(
|
|
202
|
+
'Pict-InlineDocumentation',
|
|
203
|
+
libInlineDocumentation.default_configuration,
|
|
204
|
+
libInlineDocumentation);
|
|
205
|
+
|
|
206
|
+
let tmpSidebar = '- [Page One](/page-one.md)\n'
|
|
207
|
+
+ '- [Page Two](./page-two.md)\n';
|
|
208
|
+
|
|
209
|
+
let tmpGroups = tmpProvider._parseSidebarMarkdown(tmpSidebar);
|
|
210
|
+
|
|
211
|
+
libAssert.strictEqual(tmpGroups.length, 2);
|
|
212
|
+
libAssert.strictEqual(tmpGroups[0].Path, 'page-one.md');
|
|
213
|
+
libAssert.strictEqual(tmpGroups[1].Path, 'page-two.md');
|
|
214
|
+
|
|
215
|
+
return fDone();
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
);
|
|
220
|
+
|
|
221
|
+
suite
|
|
222
|
+
(
|
|
223
|
+
'Link Resolution',
|
|
224
|
+
() =>
|
|
225
|
+
{
|
|
226
|
+
test
|
|
227
|
+
(
|
|
228
|
+
'Should resolve external links with target blank',
|
|
229
|
+
(fDone) =>
|
|
230
|
+
{
|
|
231
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
232
|
+
|
|
233
|
+
let tmpProvider = tmpPict.addProvider(
|
|
234
|
+
'Pict-InlineDocumentation',
|
|
235
|
+
libInlineDocumentation.default_configuration,
|
|
236
|
+
libInlineDocumentation);
|
|
237
|
+
|
|
238
|
+
let tmpResolver = tmpProvider._createLinkResolver();
|
|
239
|
+
let tmpResult = tmpResolver('https://example.com', 'Example');
|
|
240
|
+
|
|
241
|
+
libAssert.strictEqual(tmpResult.href, 'https://example.com');
|
|
242
|
+
libAssert.strictEqual(tmpResult.target, '_blank');
|
|
243
|
+
libAssert.strictEqual(tmpResult.rel, 'noopener');
|
|
244
|
+
|
|
245
|
+
return fDone();
|
|
246
|
+
}
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
test
|
|
250
|
+
(
|
|
251
|
+
'Should resolve internal links with doc path data',
|
|
252
|
+
(fDone) =>
|
|
253
|
+
{
|
|
254
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
255
|
+
|
|
256
|
+
let tmpProvider = tmpPict.addProvider(
|
|
257
|
+
'Pict-InlineDocumentation',
|
|
258
|
+
libInlineDocumentation.default_configuration,
|
|
259
|
+
libInlineDocumentation);
|
|
260
|
+
|
|
261
|
+
let tmpResolver = tmpProvider._createLinkResolver();
|
|
262
|
+
let tmpResult = tmpResolver('getting-started.md', 'Getting Started');
|
|
263
|
+
|
|
264
|
+
libAssert.strictEqual(tmpResult.href, 'javascript:void(0)');
|
|
265
|
+
libAssert.ok(tmpResult.rel.indexOf('pict-inline-doc-link:getting-started.md') >= 0);
|
|
266
|
+
|
|
267
|
+
return fDone();
|
|
268
|
+
}
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
suite
|
|
274
|
+
(
|
|
275
|
+
'Image Resolution',
|
|
276
|
+
() =>
|
|
277
|
+
{
|
|
278
|
+
test
|
|
279
|
+
(
|
|
280
|
+
'Should resolve relative images against doc URL',
|
|
281
|
+
(fDone) =>
|
|
282
|
+
{
|
|
283
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
284
|
+
|
|
285
|
+
let tmpProvider = tmpPict.addProvider(
|
|
286
|
+
'Pict-InlineDocumentation',
|
|
287
|
+
libInlineDocumentation.default_configuration,
|
|
288
|
+
libInlineDocumentation);
|
|
289
|
+
|
|
290
|
+
let tmpResolver = tmpProvider._createImageResolver('https://example.com/docs/guide/page.md');
|
|
291
|
+
|
|
292
|
+
let tmpResult = tmpResolver('diagram.png', 'Diagram');
|
|
293
|
+
libAssert.strictEqual(tmpResult, 'https://example.com/docs/guide/diagram.png');
|
|
294
|
+
|
|
295
|
+
return fDone();
|
|
296
|
+
}
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
test
|
|
300
|
+
(
|
|
301
|
+
'Should leave absolute image URLs unchanged',
|
|
302
|
+
(fDone) =>
|
|
303
|
+
{
|
|
304
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
305
|
+
|
|
306
|
+
let tmpProvider = tmpPict.addProvider(
|
|
307
|
+
'Pict-InlineDocumentation',
|
|
308
|
+
libInlineDocumentation.default_configuration,
|
|
309
|
+
libInlineDocumentation);
|
|
310
|
+
|
|
311
|
+
let tmpResolver = tmpProvider._createImageResolver('https://example.com/docs/page.md');
|
|
312
|
+
|
|
313
|
+
let tmpAbsolute = tmpResolver('https://cdn.example.com/image.png', 'Image');
|
|
314
|
+
libAssert.strictEqual(tmpAbsolute, 'https://cdn.example.com/image.png');
|
|
315
|
+
|
|
316
|
+
let tmpData = tmpResolver('data:image/png;base64,abc', 'Data');
|
|
317
|
+
libAssert.strictEqual(tmpData, 'data:image/png;base64,abc');
|
|
318
|
+
|
|
319
|
+
return fDone();
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
suite
|
|
326
|
+
(
|
|
327
|
+
'Error Handling',
|
|
328
|
+
() =>
|
|
329
|
+
{
|
|
330
|
+
test
|
|
331
|
+
(
|
|
332
|
+
'loadDocument should callback with error for empty path',
|
|
333
|
+
(fDone) =>
|
|
334
|
+
{
|
|
335
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
336
|
+
|
|
337
|
+
let tmpProvider = tmpPict.addProvider(
|
|
338
|
+
'Pict-InlineDocumentation',
|
|
339
|
+
libInlineDocumentation.default_configuration,
|
|
340
|
+
libInlineDocumentation);
|
|
341
|
+
|
|
342
|
+
tmpProvider.loadDocument('', (pError) =>
|
|
343
|
+
{
|
|
344
|
+
libAssert.ok(pError, 'Should return an error');
|
|
345
|
+
return fDone();
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
test
|
|
351
|
+
(
|
|
352
|
+
'setTopic should warn for unknown topic',
|
|
353
|
+
(fDone) =>
|
|
354
|
+
{
|
|
355
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
356
|
+
|
|
357
|
+
let tmpProvider = tmpPict.addProvider(
|
|
358
|
+
'Pict-InlineDocumentation',
|
|
359
|
+
libInlineDocumentation.default_configuration,
|
|
360
|
+
libInlineDocumentation);
|
|
361
|
+
|
|
362
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
363
|
+
|
|
364
|
+
// Should not throw
|
|
365
|
+
tmpProvider.setTopic('nonexistent-topic');
|
|
366
|
+
|
|
367
|
+
return fDone();
|
|
368
|
+
}
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
suite
|
|
374
|
+
(
|
|
375
|
+
'Route Matching',
|
|
376
|
+
() =>
|
|
377
|
+
{
|
|
378
|
+
test
|
|
379
|
+
(
|
|
380
|
+
'Should match exact routes',
|
|
381
|
+
(fDone) =>
|
|
382
|
+
{
|
|
383
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
384
|
+
|
|
385
|
+
let tmpProvider = tmpPict.addProvider(
|
|
386
|
+
'Pict-InlineDocumentation',
|
|
387
|
+
libInlineDocumentation.default_configuration,
|
|
388
|
+
libInlineDocumentation);
|
|
389
|
+
|
|
390
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
391
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
392
|
+
'TOPIC-A': { TopicCode: 'TOPIC-A', Routes: ['/books'] },
|
|
393
|
+
'TOPIC-B': { TopicCode: 'TOPIC-B', Routes: ['/settings'] }
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books'), 'TOPIC-A');
|
|
397
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/settings'), 'TOPIC-B');
|
|
398
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/unknown'), null);
|
|
399
|
+
|
|
400
|
+
return fDone();
|
|
401
|
+
}
|
|
402
|
+
);
|
|
403
|
+
|
|
404
|
+
test
|
|
405
|
+
(
|
|
406
|
+
'Should match wildcard routes',
|
|
407
|
+
(fDone) =>
|
|
408
|
+
{
|
|
409
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
410
|
+
|
|
411
|
+
let tmpProvider = tmpPict.addProvider(
|
|
412
|
+
'Pict-InlineDocumentation',
|
|
413
|
+
libInlineDocumentation.default_configuration,
|
|
414
|
+
libInlineDocumentation);
|
|
415
|
+
|
|
416
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
417
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
418
|
+
'STORE': { TopicCode: 'STORE', Routes: ['/books/store/*'] }
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books/store/123'), 'STORE');
|
|
422
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books/store/123/details'), 'STORE');
|
|
423
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books/store'), 'STORE');
|
|
424
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books'), null);
|
|
425
|
+
|
|
426
|
+
return fDone();
|
|
427
|
+
}
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
test
|
|
431
|
+
(
|
|
432
|
+
'Should prefer longest matching pattern',
|
|
433
|
+
(fDone) =>
|
|
434
|
+
{
|
|
435
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
436
|
+
|
|
437
|
+
let tmpProvider = tmpPict.addProvider(
|
|
438
|
+
'Pict-InlineDocumentation',
|
|
439
|
+
libInlineDocumentation.default_configuration,
|
|
440
|
+
libInlineDocumentation);
|
|
441
|
+
|
|
442
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
443
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
444
|
+
'BOOKS': { TopicCode: 'BOOKS', Routes: ['/books/*'] },
|
|
445
|
+
'STORE': { TopicCode: 'STORE', Routes: ['/books/store/*'] }
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
// /books/store/5 matches both, but STORE has longer prefix
|
|
449
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books/store/5'), 'STORE');
|
|
450
|
+
// /books/catalog matches only BOOKS
|
|
451
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/books/catalog'), 'BOOKS');
|
|
452
|
+
|
|
453
|
+
return fDone();
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
test
|
|
458
|
+
(
|
|
459
|
+
'Should handle topics without Routes array',
|
|
460
|
+
(fDone) =>
|
|
461
|
+
{
|
|
462
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
463
|
+
|
|
464
|
+
let tmpProvider = tmpPict.addProvider(
|
|
465
|
+
'Pict-InlineDocumentation',
|
|
466
|
+
libInlineDocumentation.default_configuration,
|
|
467
|
+
libInlineDocumentation);
|
|
468
|
+
|
|
469
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
470
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
471
|
+
'NO-ROUTES': { TopicCode: 'NO-ROUTES', TopicHelpFilePath: 'test.md' },
|
|
472
|
+
'HAS-ROUTES': { TopicCode: 'HAS-ROUTES', Routes: ['/test'] }
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/test'), 'HAS-ROUTES');
|
|
476
|
+
libAssert.strictEqual(tmpProvider.resolveHelpForRoute('/other'), null);
|
|
477
|
+
|
|
478
|
+
return fDone();
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
|
|
482
|
+
test
|
|
483
|
+
(
|
|
484
|
+
'navigateToRoute should return true for matched routes',
|
|
485
|
+
(fDone) =>
|
|
486
|
+
{
|
|
487
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
488
|
+
|
|
489
|
+
let tmpProvider = tmpPict.addProvider(
|
|
490
|
+
'Pict-InlineDocumentation',
|
|
491
|
+
libInlineDocumentation.default_configuration,
|
|
492
|
+
libInlineDocumentation);
|
|
493
|
+
|
|
494
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
495
|
+
tmpPict.AppData.InlineDocumentation.NavigationHistory = [];
|
|
496
|
+
tmpPict.AppData.InlineDocumentation.CurrentPath = '';
|
|
497
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
498
|
+
'FOUND': { TopicCode: 'FOUND', TopicHelpFilePath: 'found.md', Routes: ['/found'] }
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
// navigateToRoute calls loadTopicDocument which calls loadDocument
|
|
502
|
+
// which will fail to fetch, but that's fine — we're testing the return value
|
|
503
|
+
libAssert.strictEqual(tmpProvider.navigateToRoute('/found'), true);
|
|
504
|
+
libAssert.strictEqual(tmpProvider.navigateToRoute('/not-found'), false);
|
|
505
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.CurrentRoute, '/not-found');
|
|
506
|
+
|
|
507
|
+
return fDone();
|
|
508
|
+
}
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
suite
|
|
514
|
+
(
|
|
515
|
+
'Edit Mode',
|
|
516
|
+
() =>
|
|
517
|
+
{
|
|
518
|
+
test
|
|
519
|
+
(
|
|
520
|
+
'setEditEnabled should update state',
|
|
521
|
+
(fDone) =>
|
|
522
|
+
{
|
|
523
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
524
|
+
|
|
525
|
+
let tmpProvider = tmpPict.addProvider(
|
|
526
|
+
'Pict-InlineDocumentation',
|
|
527
|
+
libInlineDocumentation.default_configuration,
|
|
528
|
+
libInlineDocumentation);
|
|
529
|
+
|
|
530
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
531
|
+
// EditEnabled is only initialized by initializeDocumentation,
|
|
532
|
+
// but setEditEnabled creates it if missing
|
|
533
|
+
tmpProvider.setEditEnabled(false);
|
|
534
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.EditEnabled, false);
|
|
535
|
+
|
|
536
|
+
tmpProvider.setEditEnabled(true);
|
|
537
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.EditEnabled, true);
|
|
538
|
+
|
|
539
|
+
tmpProvider.setEditEnabled(false);
|
|
540
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.EditEnabled, false);
|
|
541
|
+
|
|
542
|
+
return fDone();
|
|
543
|
+
}
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
test
|
|
547
|
+
(
|
|
548
|
+
'Provider should have edit API methods',
|
|
549
|
+
(fDone) =>
|
|
550
|
+
{
|
|
551
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
552
|
+
|
|
553
|
+
let tmpProvider = tmpPict.addProvider(
|
|
554
|
+
'Pict-InlineDocumentation',
|
|
555
|
+
libInlineDocumentation.default_configuration,
|
|
556
|
+
libInlineDocumentation);
|
|
557
|
+
|
|
558
|
+
libAssert.strictEqual(typeof tmpProvider.setEditEnabled, 'function');
|
|
559
|
+
libAssert.strictEqual(typeof tmpProvider.toggleEdit, 'function');
|
|
560
|
+
libAssert.strictEqual(typeof tmpProvider.beginEdit, 'function');
|
|
561
|
+
libAssert.strictEqual(typeof tmpProvider.cancelEdit, 'function');
|
|
562
|
+
libAssert.strictEqual(typeof tmpProvider.saveEdit, 'function');
|
|
563
|
+
|
|
564
|
+
return fDone();
|
|
565
|
+
}
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
test
|
|
569
|
+
(
|
|
570
|
+
'Provider should have route API methods',
|
|
571
|
+
(fDone) =>
|
|
572
|
+
{
|
|
573
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
574
|
+
|
|
575
|
+
let tmpProvider = tmpPict.addProvider(
|
|
576
|
+
'Pict-InlineDocumentation',
|
|
577
|
+
libInlineDocumentation.default_configuration,
|
|
578
|
+
libInlineDocumentation);
|
|
579
|
+
|
|
580
|
+
libAssert.strictEqual(typeof tmpProvider.resolveHelpForRoute, 'function');
|
|
581
|
+
libAssert.strictEqual(typeof tmpProvider.navigateToRoute, 'function');
|
|
582
|
+
|
|
583
|
+
return fDone();
|
|
584
|
+
}
|
|
585
|
+
);
|
|
586
|
+
|
|
587
|
+
test
|
|
588
|
+
(
|
|
589
|
+
'Cache should store both html and markdown',
|
|
590
|
+
(fDone) =>
|
|
591
|
+
{
|
|
592
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
593
|
+
|
|
594
|
+
let tmpProvider = tmpPict.addProvider(
|
|
595
|
+
'Pict-InlineDocumentation',
|
|
596
|
+
libInlineDocumentation.default_configuration,
|
|
597
|
+
libInlineDocumentation);
|
|
598
|
+
|
|
599
|
+
// Manually populate cache to test format
|
|
600
|
+
tmpProvider._ContentCache['test.md'] = { html: '<p>test</p>', markdown: '# test' };
|
|
601
|
+
|
|
602
|
+
let tmpEntry = tmpProvider._ContentCache['test.md'];
|
|
603
|
+
libAssert.ok(tmpEntry.html, 'Cache entry should have html');
|
|
604
|
+
libAssert.ok(tmpEntry.markdown, 'Cache entry should have markdown');
|
|
605
|
+
libAssert.strictEqual(tmpEntry.html, '<p>test</p>');
|
|
606
|
+
libAssert.strictEqual(tmpEntry.markdown, '# test');
|
|
607
|
+
|
|
608
|
+
return fDone();
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
);
|
|
613
|
+
|
|
614
|
+
suite
|
|
615
|
+
(
|
|
616
|
+
'Topic CRUD',
|
|
617
|
+
() =>
|
|
618
|
+
{
|
|
619
|
+
test
|
|
620
|
+
(
|
|
621
|
+
'getTopicList should return array of topic summaries',
|
|
622
|
+
(fDone) =>
|
|
623
|
+
{
|
|
624
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
625
|
+
|
|
626
|
+
let tmpProvider = tmpPict.addProvider(
|
|
627
|
+
'Pict-InlineDocumentation',
|
|
628
|
+
libInlineDocumentation.default_configuration,
|
|
629
|
+
libInlineDocumentation);
|
|
630
|
+
|
|
631
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
632
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
633
|
+
'TOPIC-A': { TopicCode: 'TOPIC-A', TopicTitle: 'Topic Alpha', TopicHelpFilePath: 'alpha.md', Routes: ['/alpha', '/alpha/*'] },
|
|
634
|
+
'TOPIC-B': { TopicCode: 'TOPIC-B', TopicTitle: 'Topic Beta', TopicHelpFilePath: 'beta.md', Routes: [] }
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
let tmpList = tmpProvider.getTopicList();
|
|
638
|
+
|
|
639
|
+
libAssert.ok(Array.isArray(tmpList), 'Should return an array');
|
|
640
|
+
libAssert.strictEqual(tmpList.length, 2, 'Should have 2 topics');
|
|
641
|
+
libAssert.strictEqual(tmpList[0].TopicCode, 'TOPIC-A');
|
|
642
|
+
libAssert.strictEqual(tmpList[0].TopicTitle, 'Topic Alpha');
|
|
643
|
+
libAssert.strictEqual(tmpList[0].TopicHelpFilePath, 'alpha.md');
|
|
644
|
+
libAssert.strictEqual(tmpList[0].RouteCount, 2);
|
|
645
|
+
libAssert.strictEqual(tmpList[1].RouteCount, 0);
|
|
646
|
+
|
|
647
|
+
return fDone();
|
|
648
|
+
}
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
test
|
|
652
|
+
(
|
|
653
|
+
'getTopicList should return empty array when no topics',
|
|
654
|
+
(fDone) =>
|
|
655
|
+
{
|
|
656
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
657
|
+
|
|
658
|
+
let tmpProvider = tmpPict.addProvider(
|
|
659
|
+
'Pict-InlineDocumentation',
|
|
660
|
+
libInlineDocumentation.default_configuration,
|
|
661
|
+
libInlineDocumentation);
|
|
662
|
+
|
|
663
|
+
let tmpList = tmpProvider.getTopicList();
|
|
664
|
+
libAssert.ok(Array.isArray(tmpList));
|
|
665
|
+
libAssert.strictEqual(tmpList.length, 0);
|
|
666
|
+
|
|
667
|
+
return fDone();
|
|
668
|
+
}
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
test
|
|
672
|
+
(
|
|
673
|
+
'updateTopic should merge only specified fields',
|
|
674
|
+
(fDone) =>
|
|
675
|
+
{
|
|
676
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
677
|
+
|
|
678
|
+
let tmpProvider = tmpPict.addProvider(
|
|
679
|
+
'Pict-InlineDocumentation',
|
|
680
|
+
libInlineDocumentation.default_configuration,
|
|
681
|
+
libInlineDocumentation);
|
|
682
|
+
|
|
683
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
684
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
685
|
+
'MY-TOPIC': { TopicCode: 'MY-TOPIC', TopicTitle: 'Original', TopicHelpFilePath: 'orig.md', Routes: ['/orig'] }
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
let tmpResult = tmpProvider.updateTopic('MY-TOPIC', { TopicTitle: 'Updated Title' });
|
|
689
|
+
|
|
690
|
+
libAssert.strictEqual(tmpResult, true);
|
|
691
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].TopicTitle, 'Updated Title');
|
|
692
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].TopicHelpFilePath, 'orig.md');
|
|
693
|
+
libAssert.deepStrictEqual(tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].Routes, ['/orig']);
|
|
694
|
+
|
|
695
|
+
return fDone();
|
|
696
|
+
}
|
|
697
|
+
);
|
|
698
|
+
|
|
699
|
+
test
|
|
700
|
+
(
|
|
701
|
+
'updateTopic should return false for nonexistent topic',
|
|
702
|
+
(fDone) =>
|
|
703
|
+
{
|
|
704
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
705
|
+
|
|
706
|
+
let tmpProvider = tmpPict.addProvider(
|
|
707
|
+
'Pict-InlineDocumentation',
|
|
708
|
+
libInlineDocumentation.default_configuration,
|
|
709
|
+
libInlineDocumentation);
|
|
710
|
+
|
|
711
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
712
|
+
tmpPict.AppData.InlineDocumentation.Topics = {};
|
|
713
|
+
|
|
714
|
+
libAssert.strictEqual(tmpProvider.updateTopic('NOPE', { TopicTitle: 'Test' }), false);
|
|
715
|
+
|
|
716
|
+
return fDone();
|
|
717
|
+
}
|
|
718
|
+
);
|
|
719
|
+
|
|
720
|
+
test
|
|
721
|
+
(
|
|
722
|
+
'removeTopic should delete topic and clear active if matched',
|
|
723
|
+
(fDone) =>
|
|
724
|
+
{
|
|
725
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
726
|
+
|
|
727
|
+
let tmpProvider = tmpPict.addProvider(
|
|
728
|
+
'Pict-InlineDocumentation',
|
|
729
|
+
libInlineDocumentation.default_configuration,
|
|
730
|
+
libInlineDocumentation);
|
|
731
|
+
|
|
732
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
733
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
734
|
+
'REMOVE-ME': { TopicCode: 'REMOVE-ME', TopicTitle: 'Doomed' }
|
|
735
|
+
};
|
|
736
|
+
tmpPict.AppData.InlineDocumentation.Topic = 'REMOVE-ME';
|
|
737
|
+
|
|
738
|
+
let tmpResult = tmpProvider.removeTopic('REMOVE-ME');
|
|
739
|
+
|
|
740
|
+
libAssert.strictEqual(tmpResult, true);
|
|
741
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.Topics['REMOVE-ME'], undefined);
|
|
742
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.Topic, null);
|
|
743
|
+
|
|
744
|
+
return fDone();
|
|
745
|
+
}
|
|
746
|
+
);
|
|
747
|
+
|
|
748
|
+
test
|
|
749
|
+
(
|
|
750
|
+
'removeTopic should return false for nonexistent topic',
|
|
751
|
+
(fDone) =>
|
|
752
|
+
{
|
|
753
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
754
|
+
|
|
755
|
+
let tmpProvider = tmpPict.addProvider(
|
|
756
|
+
'Pict-InlineDocumentation',
|
|
757
|
+
libInlineDocumentation.default_configuration,
|
|
758
|
+
libInlineDocumentation);
|
|
759
|
+
|
|
760
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
761
|
+
tmpPict.AppData.InlineDocumentation.Topics = {};
|
|
762
|
+
|
|
763
|
+
libAssert.strictEqual(tmpProvider.removeTopic('NOPE'), false);
|
|
764
|
+
|
|
765
|
+
return fDone();
|
|
766
|
+
}
|
|
767
|
+
);
|
|
768
|
+
|
|
769
|
+
test
|
|
770
|
+
(
|
|
771
|
+
'removeRouteFromTopic should splice route from array',
|
|
772
|
+
(fDone) =>
|
|
773
|
+
{
|
|
774
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
775
|
+
|
|
776
|
+
let tmpProvider = tmpPict.addProvider(
|
|
777
|
+
'Pict-InlineDocumentation',
|
|
778
|
+
libInlineDocumentation.default_configuration,
|
|
779
|
+
libInlineDocumentation);
|
|
780
|
+
|
|
781
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
782
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
783
|
+
'TOPIC-X': { TopicCode: 'TOPIC-X', Routes: ['/one', '/two', '/three'] }
|
|
784
|
+
};
|
|
785
|
+
|
|
786
|
+
libAssert.strictEqual(tmpProvider.removeRouteFromTopic('TOPIC-X', '/two'), true);
|
|
787
|
+
libAssert.deepStrictEqual(tmpPict.AppData.InlineDocumentation.Topics['TOPIC-X'].Routes, ['/one', '/three']);
|
|
788
|
+
libAssert.strictEqual(tmpProvider.removeRouteFromTopic('TOPIC-X', '/two'), false);
|
|
789
|
+
|
|
790
|
+
return fDone();
|
|
791
|
+
}
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
test
|
|
795
|
+
(
|
|
796
|
+
'saveTopics should call onTopicsSave callback',
|
|
797
|
+
(fDone) =>
|
|
798
|
+
{
|
|
799
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
800
|
+
|
|
801
|
+
let tmpProvider = tmpPict.addProvider(
|
|
802
|
+
'Pict-InlineDocumentation',
|
|
803
|
+
libInlineDocumentation.default_configuration,
|
|
804
|
+
libInlineDocumentation);
|
|
805
|
+
|
|
806
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
807
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
808
|
+
'TEST': { TopicCode: 'TEST', TopicTitle: 'Test' }
|
|
809
|
+
};
|
|
810
|
+
|
|
811
|
+
let tmpSavedTopics = null;
|
|
812
|
+
tmpProvider._onTopicsSave = (pTopics, fCallback) =>
|
|
813
|
+
{
|
|
814
|
+
tmpSavedTopics = pTopics;
|
|
815
|
+
fCallback(null);
|
|
816
|
+
};
|
|
817
|
+
|
|
818
|
+
tmpProvider.saveTopics((pError) =>
|
|
819
|
+
{
|
|
820
|
+
libAssert.strictEqual(pError, null);
|
|
821
|
+
libAssert.ok(tmpSavedTopics);
|
|
822
|
+
libAssert.ok(tmpSavedTopics['TEST']);
|
|
823
|
+
return fDone();
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
);
|
|
827
|
+
|
|
828
|
+
test
|
|
829
|
+
(
|
|
830
|
+
'saveTopics should succeed without callback handler',
|
|
831
|
+
(fDone) =>
|
|
832
|
+
{
|
|
833
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
834
|
+
|
|
835
|
+
let tmpProvider = tmpPict.addProvider(
|
|
836
|
+
'Pict-InlineDocumentation',
|
|
837
|
+
libInlineDocumentation.default_configuration,
|
|
838
|
+
libInlineDocumentation);
|
|
839
|
+
|
|
840
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
841
|
+
tmpPict.AppData.InlineDocumentation.Topics = {};
|
|
842
|
+
|
|
843
|
+
tmpProvider.saveTopics((pError) =>
|
|
844
|
+
{
|
|
845
|
+
libAssert.strictEqual(pError, null);
|
|
846
|
+
return fDone();
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
|
|
851
|
+
test
|
|
852
|
+
(
|
|
853
|
+
'setTopicManagerEnabled should update state',
|
|
854
|
+
(fDone) =>
|
|
855
|
+
{
|
|
856
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
857
|
+
|
|
858
|
+
let tmpProvider = tmpPict.addProvider(
|
|
859
|
+
'Pict-InlineDocumentation',
|
|
860
|
+
libInlineDocumentation.default_configuration,
|
|
861
|
+
libInlineDocumentation);
|
|
862
|
+
|
|
863
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
864
|
+
|
|
865
|
+
tmpProvider.setTopicManagerEnabled(true);
|
|
866
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.TopicManagerEnabled, true);
|
|
867
|
+
|
|
868
|
+
tmpProvider.setTopicManagerEnabled(false);
|
|
869
|
+
libAssert.strictEqual(tmpPict.AppData.InlineDocumentation.TopicManagerEnabled, false);
|
|
870
|
+
|
|
871
|
+
return fDone();
|
|
872
|
+
}
|
|
873
|
+
);
|
|
874
|
+
|
|
875
|
+
test
|
|
876
|
+
(
|
|
877
|
+
'Provider should have topic CRUD API methods',
|
|
878
|
+
(fDone) =>
|
|
879
|
+
{
|
|
880
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
881
|
+
|
|
882
|
+
let tmpProvider = tmpPict.addProvider(
|
|
883
|
+
'Pict-InlineDocumentation',
|
|
884
|
+
libInlineDocumentation.default_configuration,
|
|
885
|
+
libInlineDocumentation);
|
|
886
|
+
|
|
887
|
+
libAssert.strictEqual(typeof tmpProvider.getTopicList, 'function');
|
|
888
|
+
libAssert.strictEqual(typeof tmpProvider.updateTopic, 'function');
|
|
889
|
+
libAssert.strictEqual(typeof tmpProvider.removeTopic, 'function');
|
|
890
|
+
libAssert.strictEqual(typeof tmpProvider.removeRouteFromTopic, 'function');
|
|
891
|
+
libAssert.strictEqual(typeof tmpProvider.saveTopics, 'function');
|
|
892
|
+
libAssert.strictEqual(typeof tmpProvider.setTopicManagerEnabled, 'function');
|
|
893
|
+
|
|
894
|
+
return fDone();
|
|
895
|
+
}
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
test
|
|
899
|
+
(
|
|
900
|
+
'TopicManager view should be registered',
|
|
901
|
+
(fDone) =>
|
|
902
|
+
{
|
|
903
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
904
|
+
|
|
905
|
+
tmpPict.addProvider(
|
|
906
|
+
'Pict-InlineDocumentation',
|
|
907
|
+
libInlineDocumentation.default_configuration,
|
|
908
|
+
libInlineDocumentation);
|
|
909
|
+
|
|
910
|
+
libAssert.ok(tmpPict.views['InlineDoc-TopicManager'], 'TopicManager view should be registered');
|
|
911
|
+
|
|
912
|
+
return fDone();
|
|
913
|
+
}
|
|
914
|
+
);
|
|
915
|
+
|
|
916
|
+
test
|
|
917
|
+
(
|
|
918
|
+
'Module should export TopicManager view class',
|
|
919
|
+
(fDone) =>
|
|
920
|
+
{
|
|
921
|
+
libAssert.strictEqual(typeof libInlineDocumentation.InlineDocumentationTopicManagerView, 'function');
|
|
922
|
+
return fDone();
|
|
923
|
+
}
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
);
|
|
927
|
+
|
|
928
|
+
suite
|
|
929
|
+
(
|
|
930
|
+
'Wildcard Builder Helpers',
|
|
931
|
+
() =>
|
|
932
|
+
{
|
|
933
|
+
test
|
|
934
|
+
(
|
|
935
|
+
'getRouteSegments should split route into segments',
|
|
936
|
+
(fDone) =>
|
|
937
|
+
{
|
|
938
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
939
|
+
|
|
940
|
+
let tmpProvider = tmpPict.addProvider(
|
|
941
|
+
'Pict-InlineDocumentation',
|
|
942
|
+
libInlineDocumentation.default_configuration,
|
|
943
|
+
libInlineDocumentation);
|
|
944
|
+
|
|
945
|
+
let tmpSegments = tmpProvider.getRouteSegments('/books/detail/5');
|
|
946
|
+
|
|
947
|
+
libAssert.strictEqual(tmpSegments.length, 3);
|
|
948
|
+
|
|
949
|
+
libAssert.strictEqual(tmpSegments[0].Segment, 'books');
|
|
950
|
+
libAssert.strictEqual(tmpSegments[0].Path, '/books');
|
|
951
|
+
libAssert.strictEqual(tmpSegments[0].WildcardPattern, '/books/*');
|
|
952
|
+
libAssert.strictEqual(tmpSegments[0].Index, 0);
|
|
953
|
+
|
|
954
|
+
libAssert.strictEqual(tmpSegments[1].Segment, 'detail');
|
|
955
|
+
libAssert.strictEqual(tmpSegments[1].Path, '/books/detail');
|
|
956
|
+
libAssert.strictEqual(tmpSegments[1].WildcardPattern, '/books/detail/*');
|
|
957
|
+
libAssert.strictEqual(tmpSegments[1].Index, 1);
|
|
958
|
+
|
|
959
|
+
libAssert.strictEqual(tmpSegments[2].Segment, '5');
|
|
960
|
+
libAssert.strictEqual(tmpSegments[2].Path, '/books/detail/5');
|
|
961
|
+
libAssert.strictEqual(tmpSegments[2].WildcardPattern, '/books/detail/5/*');
|
|
962
|
+
libAssert.strictEqual(tmpSegments[2].Index, 2);
|
|
963
|
+
|
|
964
|
+
return fDone();
|
|
965
|
+
}
|
|
966
|
+
);
|
|
967
|
+
|
|
968
|
+
test
|
|
969
|
+
(
|
|
970
|
+
'getRouteSegments should return empty array for empty/invalid input',
|
|
971
|
+
(fDone) =>
|
|
972
|
+
{
|
|
973
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
974
|
+
|
|
975
|
+
let tmpProvider = tmpPict.addProvider(
|
|
976
|
+
'Pict-InlineDocumentation',
|
|
977
|
+
libInlineDocumentation.default_configuration,
|
|
978
|
+
libInlineDocumentation);
|
|
979
|
+
|
|
980
|
+
libAssert.deepStrictEqual(tmpProvider.getRouteSegments(''), []);
|
|
981
|
+
libAssert.deepStrictEqual(tmpProvider.getRouteSegments(null), []);
|
|
982
|
+
libAssert.deepStrictEqual(tmpProvider.getRouteSegments(undefined), []);
|
|
983
|
+
libAssert.deepStrictEqual(tmpProvider.getRouteSegments('/'), []);
|
|
984
|
+
|
|
985
|
+
return fDone();
|
|
986
|
+
}
|
|
987
|
+
);
|
|
988
|
+
|
|
989
|
+
test
|
|
990
|
+
(
|
|
991
|
+
'buildWildcardPattern should create correct patterns',
|
|
992
|
+
(fDone) =>
|
|
993
|
+
{
|
|
994
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
995
|
+
|
|
996
|
+
let tmpProvider = tmpPict.addProvider(
|
|
997
|
+
'Pict-InlineDocumentation',
|
|
998
|
+
libInlineDocumentation.default_configuration,
|
|
999
|
+
libInlineDocumentation);
|
|
1000
|
+
|
|
1001
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('/books/detail/5', 0), '/books/*');
|
|
1002
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('/books/detail/5', 1), '/books/detail/*');
|
|
1003
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('/books/detail/5', 2), '/books/detail/5/*');
|
|
1004
|
+
|
|
1005
|
+
return fDone();
|
|
1006
|
+
}
|
|
1007
|
+
);
|
|
1008
|
+
|
|
1009
|
+
test
|
|
1010
|
+
(
|
|
1011
|
+
'buildWildcardPattern should return empty string for invalid input',
|
|
1012
|
+
(fDone) =>
|
|
1013
|
+
{
|
|
1014
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1015
|
+
|
|
1016
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1017
|
+
'Pict-InlineDocumentation',
|
|
1018
|
+
libInlineDocumentation.default_configuration,
|
|
1019
|
+
libInlineDocumentation);
|
|
1020
|
+
|
|
1021
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('', 0), '');
|
|
1022
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('/books', -1), '');
|
|
1023
|
+
libAssert.strictEqual(tmpProvider.buildWildcardPattern('/books', 5), '');
|
|
1024
|
+
|
|
1025
|
+
return fDone();
|
|
1026
|
+
}
|
|
1027
|
+
);
|
|
1028
|
+
|
|
1029
|
+
test
|
|
1030
|
+
(
|
|
1031
|
+
'getTopicsForRoute should return all matching topics sorted by match length',
|
|
1032
|
+
(fDone) =>
|
|
1033
|
+
{
|
|
1034
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1035
|
+
|
|
1036
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1037
|
+
'Pict-InlineDocumentation',
|
|
1038
|
+
libInlineDocumentation.default_configuration,
|
|
1039
|
+
libInlineDocumentation);
|
|
1040
|
+
|
|
1041
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1042
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1043
|
+
'BOOKS': { TopicCode: 'BOOKS', Routes: ['/books/*'] },
|
|
1044
|
+
'STORE': { TopicCode: 'STORE', Routes: ['/books/store/*'] },
|
|
1045
|
+
'SETTINGS': { TopicCode: 'SETTINGS', Routes: ['/settings'] }
|
|
1046
|
+
};
|
|
1047
|
+
|
|
1048
|
+
let tmpMatches = tmpProvider.getTopicsForRoute('/books/store/5');
|
|
1049
|
+
|
|
1050
|
+
libAssert.strictEqual(tmpMatches.length, 2);
|
|
1051
|
+
libAssert.strictEqual(tmpMatches[0].TopicCode, 'STORE');
|
|
1052
|
+
libAssert.strictEqual(tmpMatches[1].TopicCode, 'BOOKS');
|
|
1053
|
+
|
|
1054
|
+
return fDone();
|
|
1055
|
+
}
|
|
1056
|
+
);
|
|
1057
|
+
}
|
|
1058
|
+
);
|
|
1059
|
+
|
|
1060
|
+
suite
|
|
1061
|
+
(
|
|
1062
|
+
'Tooltip Content',
|
|
1063
|
+
() =>
|
|
1064
|
+
{
|
|
1065
|
+
test
|
|
1066
|
+
(
|
|
1067
|
+
'getTooltipContent should return content from active topic',
|
|
1068
|
+
(fDone) =>
|
|
1069
|
+
{
|
|
1070
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1071
|
+
|
|
1072
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1073
|
+
'Pict-InlineDocumentation',
|
|
1074
|
+
libInlineDocumentation.default_configuration,
|
|
1075
|
+
libInlineDocumentation);
|
|
1076
|
+
|
|
1077
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1078
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1079
|
+
'HELP-TOPIC': {
|
|
1080
|
+
TopicCode: 'HELP-TOPIC',
|
|
1081
|
+
TopicTitle: 'Help',
|
|
1082
|
+
Tooltips: {
|
|
1083
|
+
'field_name': { Content: '**Bold** help text' },
|
|
1084
|
+
'empty_tip': { Content: '' }
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
tmpPict.AppData.InlineDocumentation.Topic = 'HELP-TOPIC';
|
|
1089
|
+
|
|
1090
|
+
libAssert.strictEqual(tmpProvider.getTooltipContent('field_name'), '**Bold** help text');
|
|
1091
|
+
libAssert.strictEqual(tmpProvider.getTooltipContent('empty_tip'), null);
|
|
1092
|
+
libAssert.strictEqual(tmpProvider.getTooltipContent('nonexistent'), null);
|
|
1093
|
+
|
|
1094
|
+
return fDone();
|
|
1095
|
+
}
|
|
1096
|
+
);
|
|
1097
|
+
|
|
1098
|
+
test
|
|
1099
|
+
(
|
|
1100
|
+
'getTooltipContent should return null when no active topic',
|
|
1101
|
+
(fDone) =>
|
|
1102
|
+
{
|
|
1103
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1104
|
+
|
|
1105
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1106
|
+
'Pict-InlineDocumentation',
|
|
1107
|
+
libInlineDocumentation.default_configuration,
|
|
1108
|
+
libInlineDocumentation);
|
|
1109
|
+
|
|
1110
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1111
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1112
|
+
'HELP-TOPIC': {
|
|
1113
|
+
TopicCode: 'HELP-TOPIC',
|
|
1114
|
+
Tooltips: { 'tip': { Content: 'Some content' } }
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
tmpPict.AppData.InlineDocumentation.Topic = null;
|
|
1118
|
+
|
|
1119
|
+
libAssert.strictEqual(tmpProvider.getTooltipContent('tip'), null);
|
|
1120
|
+
|
|
1121
|
+
return fDone();
|
|
1122
|
+
}
|
|
1123
|
+
);
|
|
1124
|
+
|
|
1125
|
+
test
|
|
1126
|
+
(
|
|
1127
|
+
'getTooltipContent should return null when topic has no Tooltips',
|
|
1128
|
+
(fDone) =>
|
|
1129
|
+
{
|
|
1130
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1131
|
+
|
|
1132
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1133
|
+
'Pict-InlineDocumentation',
|
|
1134
|
+
libInlineDocumentation.default_configuration,
|
|
1135
|
+
libInlineDocumentation);
|
|
1136
|
+
|
|
1137
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1138
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1139
|
+
'NO-TIPS': { TopicCode: 'NO-TIPS', TopicTitle: 'No Tips' }
|
|
1140
|
+
};
|
|
1141
|
+
tmpPict.AppData.InlineDocumentation.Topic = 'NO-TIPS';
|
|
1142
|
+
|
|
1143
|
+
libAssert.strictEqual(tmpProvider.getTooltipContent('anything'), null);
|
|
1144
|
+
|
|
1145
|
+
return fDone();
|
|
1146
|
+
}
|
|
1147
|
+
);
|
|
1148
|
+
|
|
1149
|
+
test
|
|
1150
|
+
(
|
|
1151
|
+
'setTooltipContent should create Tooltips hash lazily',
|
|
1152
|
+
(fDone) =>
|
|
1153
|
+
{
|
|
1154
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1155
|
+
|
|
1156
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1157
|
+
'Pict-InlineDocumentation',
|
|
1158
|
+
libInlineDocumentation.default_configuration,
|
|
1159
|
+
libInlineDocumentation);
|
|
1160
|
+
|
|
1161
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1162
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1163
|
+
'MY-TOPIC': { TopicCode: 'MY-TOPIC', TopicTitle: 'Test' }
|
|
1164
|
+
};
|
|
1165
|
+
tmpPict.AppData.InlineDocumentation.Topic = 'MY-TOPIC';
|
|
1166
|
+
|
|
1167
|
+
let tmpResult = tmpProvider.setTooltipContent('new_tip', 'Hello world');
|
|
1168
|
+
|
|
1169
|
+
libAssert.strictEqual(tmpResult, true);
|
|
1170
|
+
libAssert.ok(tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].Tooltips);
|
|
1171
|
+
libAssert.strictEqual(
|
|
1172
|
+
tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].Tooltips['new_tip'].Content,
|
|
1173
|
+
'Hello world');
|
|
1174
|
+
|
|
1175
|
+
return fDone();
|
|
1176
|
+
}
|
|
1177
|
+
);
|
|
1178
|
+
|
|
1179
|
+
test
|
|
1180
|
+
(
|
|
1181
|
+
'setTooltipContent should remove entry when content is null',
|
|
1182
|
+
(fDone) =>
|
|
1183
|
+
{
|
|
1184
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1185
|
+
|
|
1186
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1187
|
+
'Pict-InlineDocumentation',
|
|
1188
|
+
libInlineDocumentation.default_configuration,
|
|
1189
|
+
libInlineDocumentation);
|
|
1190
|
+
|
|
1191
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1192
|
+
tmpPict.AppData.InlineDocumentation.Topics = {
|
|
1193
|
+
'MY-TOPIC': {
|
|
1194
|
+
TopicCode: 'MY-TOPIC',
|
|
1195
|
+
Tooltips: { 'old_tip': { Content: 'Remove me' } }
|
|
1196
|
+
}
|
|
1197
|
+
};
|
|
1198
|
+
tmpPict.AppData.InlineDocumentation.Topic = 'MY-TOPIC';
|
|
1199
|
+
|
|
1200
|
+
libAssert.strictEqual(tmpProvider.setTooltipContent('old_tip', null), true);
|
|
1201
|
+
libAssert.strictEqual(
|
|
1202
|
+
tmpPict.AppData.InlineDocumentation.Topics['MY-TOPIC'].Tooltips['old_tip'],
|
|
1203
|
+
undefined);
|
|
1204
|
+
|
|
1205
|
+
return fDone();
|
|
1206
|
+
}
|
|
1207
|
+
);
|
|
1208
|
+
|
|
1209
|
+
test
|
|
1210
|
+
(
|
|
1211
|
+
'setTooltipContent should return false when no active topic',
|
|
1212
|
+
(fDone) =>
|
|
1213
|
+
{
|
|
1214
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1215
|
+
|
|
1216
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1217
|
+
'Pict-InlineDocumentation',
|
|
1218
|
+
libInlineDocumentation.default_configuration,
|
|
1219
|
+
libInlineDocumentation);
|
|
1220
|
+
|
|
1221
|
+
tmpProvider.setDocsBaseURL('/docs/');
|
|
1222
|
+
tmpPict.AppData.InlineDocumentation.Topics = {};
|
|
1223
|
+
tmpPict.AppData.InlineDocumentation.Topic = null;
|
|
1224
|
+
|
|
1225
|
+
libAssert.strictEqual(tmpProvider.setTooltipContent('tip', 'content'), false);
|
|
1226
|
+
|
|
1227
|
+
return fDone();
|
|
1228
|
+
}
|
|
1229
|
+
);
|
|
1230
|
+
|
|
1231
|
+
test
|
|
1232
|
+
(
|
|
1233
|
+
'clearTooltipBindings should empty the bindings array',
|
|
1234
|
+
(fDone) =>
|
|
1235
|
+
{
|
|
1236
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1237
|
+
|
|
1238
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1239
|
+
'Pict-InlineDocumentation',
|
|
1240
|
+
libInlineDocumentation.default_configuration,
|
|
1241
|
+
libInlineDocumentation);
|
|
1242
|
+
|
|
1243
|
+
tmpProvider._ActiveTooltipBindings.push(
|
|
1244
|
+
{
|
|
1245
|
+
Element: null,
|
|
1246
|
+
Key: 'test',
|
|
1247
|
+
Type: 'attribute',
|
|
1248
|
+
TooltipHandle: null,
|
|
1249
|
+
ClickHandler: null,
|
|
1250
|
+
InjectedIcon: null,
|
|
1251
|
+
OriginalDisplay: undefined
|
|
1252
|
+
});
|
|
1253
|
+
|
|
1254
|
+
libAssert.strictEqual(tmpProvider._ActiveTooltipBindings.length, 1);
|
|
1255
|
+
tmpProvider.clearTooltipBindings();
|
|
1256
|
+
libAssert.strictEqual(tmpProvider._ActiveTooltipBindings.length, 0);
|
|
1257
|
+
|
|
1258
|
+
return fDone();
|
|
1259
|
+
}
|
|
1260
|
+
);
|
|
1261
|
+
|
|
1262
|
+
test
|
|
1263
|
+
(
|
|
1264
|
+
'Provider should have tooltip API methods',
|
|
1265
|
+
(fDone) =>
|
|
1266
|
+
{
|
|
1267
|
+
let tmpPict = new libPict({ Product: 'InlineDocTest' });
|
|
1268
|
+
|
|
1269
|
+
let tmpProvider = tmpPict.addProvider(
|
|
1270
|
+
'Pict-InlineDocumentation',
|
|
1271
|
+
libInlineDocumentation.default_configuration,
|
|
1272
|
+
libInlineDocumentation);
|
|
1273
|
+
|
|
1274
|
+
libAssert.strictEqual(typeof tmpProvider.getTooltipContent, 'function');
|
|
1275
|
+
libAssert.strictEqual(typeof tmpProvider.setTooltipContent, 'function');
|
|
1276
|
+
libAssert.strictEqual(typeof tmpProvider.clearTooltipBindings, 'function');
|
|
1277
|
+
libAssert.strictEqual(typeof tmpProvider.scanTooltips, 'function');
|
|
1278
|
+
|
|
1279
|
+
return fDone();
|
|
1280
|
+
}
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
);
|