@salesforcedevs/sfdocs-e2e 1.0.10-alpha → 1.0.11-toolbar.0
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/package.json +1 -1
- package/portal-wdio.conf.js +5 -0
- package/src/content-repo/pageobjects/home.page.ts +6 -35
- package/src/content-repo/specs/guideAndReferencePage.test.ts +17 -31
- package/src/content-repo/specs/homepage.test.ts +35 -20
- package/src/content-repo/specs/navHeader.test.ts +3 -6
- package/src/content-repo/specs/sitemap.test.ts +84 -0
- package/src/portal/specs/docs.api.test.ts +0 -43
- package/src/shared/pageobjects/api-redoc-reference.page.ts +5 -0
- package/src/shared/pageobjects/content-action-toolbar.ts +104 -0
- package/src/shared/pageobjects/docs-content-layout.ts +6 -7
- package/src/shared/pageobjects/docs.page.ts +128 -0
- package/src/shared/pageobjects/page.ts +0 -16
- package/src/shared/pageobjects/reference.page.ts +9 -0
- package/src/shared/specs/contentActionToolbar.test.ts +164 -0
- package/src/shared/specs/docsContentType.test.ts +615 -0
- package/src/shared/specs/guides.test.ts +1 -1
- package/src/shared/specs/liquid-advanced.test.ts +110 -0
- package/src/shared/specs/liquid.test.ts +192 -22
- package/src/shared/specs/redoc-reference.test.ts +143 -0
- package/src/shared/specs/video.test.ts +4 -1
- package/static-dsc-portal-wdio.conf.js +1 -0
- package/static-portal-wdio.conf.js +2 -0
- package/wdio.conf.js +1 -0
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
import DocsPage from '../pageobjects/docs.page';
|
|
2
|
+
import layoutTest from './layout-tests';
|
|
3
|
+
|
|
4
|
+
let page: DocsPage;
|
|
5
|
+
|
|
6
|
+
describe('Docs content type', () => {
|
|
7
|
+
beforeEach(async () => {
|
|
8
|
+
page = new DocsPage('/docs/docs-content-type-example/get-started.html');
|
|
9
|
+
page.open();
|
|
10
|
+
await page.waitPageLoad();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
layoutTest(page, 'doc-header');
|
|
14
|
+
|
|
15
|
+
it('should render all the sidebar tree items properly', async () => {
|
|
16
|
+
await page.waitForSidebar();
|
|
17
|
+
const trees = await page.getSidebarTrees();
|
|
18
|
+
|
|
19
|
+
expect(trees.length).toBeGreaterThan(10);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('shows a forward-arrow icon on the spec entry but not on a markdown topic', async () => {
|
|
23
|
+
await page.waitForSidebar();
|
|
24
|
+
const specArrow = await page.getTileForwardArrow('Widgets API Reference');
|
|
25
|
+
const markdownArrow = await page.getTileForwardArrow('Widget Concepts');
|
|
26
|
+
|
|
27
|
+
expect(await specArrow.isExisting()).toBe(true);
|
|
28
|
+
expect(await markdownArrow.isExisting()).toBe(false);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('shows a new-window icon on the external-link sidebar entry', async () => {
|
|
32
|
+
await page.waitForSidebar();
|
|
33
|
+
const externalIcon = await page.getTileExternalLinkIcon('Salesforce Developers');
|
|
34
|
+
|
|
35
|
+
expect(await externalIcon.isExisting()).toBe(true);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('navigates to a topic whose URL slug is overridden by its TOC id', async () => {
|
|
39
|
+
await page.waitForSidebar();
|
|
40
|
+
const tile = await page.getSidebarTile('Widget Concepts');
|
|
41
|
+
await tile.click();
|
|
42
|
+
await page.waitPageLoad();
|
|
43
|
+
|
|
44
|
+
expect(await browser.getUrl()).toContain('widget-concepts.html');
|
|
45
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Widget Concepts');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('expands a parent-only section and navigates to its child topic', async () => {
|
|
49
|
+
await page.waitForSidebar();
|
|
50
|
+
const parentTile = await page.getSidebarTile('Authentication');
|
|
51
|
+
await parentTile.click();
|
|
52
|
+
|
|
53
|
+
const childTile = await page.getSidebarTile('Generate API Tokens');
|
|
54
|
+
await childTile.waitForDisplayed();
|
|
55
|
+
await childTile.click();
|
|
56
|
+
await page.waitPageLoad();
|
|
57
|
+
|
|
58
|
+
expect(await browser.getUrl()).toContain('child-one.html');
|
|
59
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Generate API Tokens');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('navigates to a parent topic that has its own content, then to its nested child', async () => {
|
|
63
|
+
await page.waitForSidebar();
|
|
64
|
+
const parentTile = await page.getSidebarTile('Use the Widgets API');
|
|
65
|
+
await parentTile.click();
|
|
66
|
+
await page.waitPageLoad();
|
|
67
|
+
|
|
68
|
+
expect(await browser.getUrl()).toContain('parent-overview.html');
|
|
69
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Use the Widgets API');
|
|
70
|
+
|
|
71
|
+
const childTile = await page.getSidebarTile('List and Search Widgets');
|
|
72
|
+
await childTile.waitForDisplayed();
|
|
73
|
+
await childTile.click();
|
|
74
|
+
await page.waitPageLoad();
|
|
75
|
+
|
|
76
|
+
expect(await browser.getUrl()).toContain('subtopic-one.html');
|
|
77
|
+
expect(await (await page.getContentHeading()).getText()).toContain(
|
|
78
|
+
'List and Search Widgets',
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('navigates to a nested topic and a nested spec that are pulled in via tocRefs in the TOC', async () => {
|
|
83
|
+
await page.waitForSidebar();
|
|
84
|
+
const parentTile = await page.getSidebarTile('Errors and Rate Limits');
|
|
85
|
+
await parentTile.click();
|
|
86
|
+
await page.waitPageLoad();
|
|
87
|
+
|
|
88
|
+
expect(await browser.getUrl()).toContain('parent-with-refs.html');
|
|
89
|
+
expect(await (await page.getContentHeading()).getText()).toContain(
|
|
90
|
+
'Errors and Rate Limits',
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const topicTile = await page.getSidebarTile('Common Error Codes');
|
|
94
|
+
await topicTile.waitForDisplayed();
|
|
95
|
+
await topicTile.click();
|
|
96
|
+
await page.waitPageLoad();
|
|
97
|
+
|
|
98
|
+
expect(await browser.getUrl()).toContain('extra-child-a.html');
|
|
99
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Common Error Codes');
|
|
100
|
+
|
|
101
|
+
const specTile = await page.getSidebarTile('Another Spec API');
|
|
102
|
+
await specTile.click();
|
|
103
|
+
await page.waitForRedocLoad();
|
|
104
|
+
|
|
105
|
+
expect(await (await page.getRedocApiTitle()).getText()).toContain('Widget Errors API');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('resolves a markdown topic requested without the .html extension', async () => {
|
|
109
|
+
page = new DocsPage('/docs/docs-content-type-example/get-started');
|
|
110
|
+
page.open();
|
|
111
|
+
await page.waitPageLoad();
|
|
112
|
+
|
|
113
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Get Started');
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('renders a topic nested several levels deep in the TOC', async () => {
|
|
117
|
+
page = new DocsPage('/docs/docs-deep-nesting-example/introduction.html');
|
|
118
|
+
page.open();
|
|
119
|
+
await page.waitPageLoad();
|
|
120
|
+
|
|
121
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Introduction');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('sets the current page as the last breadcrumb in the hierarchy', async () => {
|
|
125
|
+
page = new DocsPage('/docs/docs-content-type-example/child-one.html');
|
|
126
|
+
page.open();
|
|
127
|
+
await page.waitPageLoad();
|
|
128
|
+
|
|
129
|
+
expect(await page.getCurrentBreadcrumbLabel()).toBe('Generate API Tokens');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('returns to the originating topic when the redoc back link is clicked', async () => {
|
|
133
|
+
await page.waitForSidebar();
|
|
134
|
+
const parentTile = await page.getSidebarTile('Use the Widgets API');
|
|
135
|
+
await parentTile.click();
|
|
136
|
+
await page.waitPageLoad();
|
|
137
|
+
|
|
138
|
+
const childTile = await page.getSidebarTile('List and Search Widgets');
|
|
139
|
+
await childTile.waitForDisplayed();
|
|
140
|
+
await childTile.click();
|
|
141
|
+
await page.waitPageLoad();
|
|
142
|
+
expect(await browser.getUrl()).toContain('subtopic-one.html');
|
|
143
|
+
|
|
144
|
+
const specTile = await page.getSidebarTile('Widgets API Reference');
|
|
145
|
+
await specTile.click();
|
|
146
|
+
await page.waitForRedocLoad();
|
|
147
|
+
|
|
148
|
+
const backLink = await page.getRedocBackLink();
|
|
149
|
+
await backLink.waitForDisplayed();
|
|
150
|
+
await backLink.click();
|
|
151
|
+
await page.waitPageLoad();
|
|
152
|
+
|
|
153
|
+
expect(await browser.getUrl()).toContain('subtopic-one.html');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('renders the beta banner on a topic with releasePhase set to beta', async () => {
|
|
157
|
+
page = new DocsPage('/docs/docs-content-type-example/beta-bulk-import.html');
|
|
158
|
+
page.open();
|
|
159
|
+
await page.waitPageLoad();
|
|
160
|
+
|
|
161
|
+
const docPhase = await $('>>>doc-phase');
|
|
162
|
+
const title = await docPhase.shadow$('.doc-phase-title');
|
|
163
|
+
const body = await docPhase.shadow$('.doc-phase-body');
|
|
164
|
+
|
|
165
|
+
expect(await title.getText()).toBe('Beta');
|
|
166
|
+
expect(await body.getText()).toContain(
|
|
167
|
+
'This beta feature is made available on an AS IS basis',
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe('Docs content type > internal links', () => {
|
|
173
|
+
beforeEach(async () => {
|
|
174
|
+
page = new DocsPage('/docs/docs-content-type-example/internal-linking.html');
|
|
175
|
+
page.open();
|
|
176
|
+
await page.waitPageLoad();
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('rewrites a relative .md link to its published .html url', async () => {
|
|
180
|
+
const link = await $('>>>a.internal-link-guide[href*="get-started"]');
|
|
181
|
+
await link.waitForDisplayed();
|
|
182
|
+
const href = await link.getAttribute('href');
|
|
183
|
+
|
|
184
|
+
expect(href).not.toContain('.md');
|
|
185
|
+
expect(href).toContain('get-started.html');
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('rewrites a link to an id-overridden topic to its overridden slug', async () => {
|
|
189
|
+
const link = await $('>>>a.internal-link-guide[href*="widget-concepts"]');
|
|
190
|
+
await link.waitForDisplayed();
|
|
191
|
+
const href = await link.getAttribute('href');
|
|
192
|
+
|
|
193
|
+
expect(href).not.toContain('clickable-topic');
|
|
194
|
+
expect(href).toContain('widget-concepts.html');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('Docs content type > spec (Redoc) topic', () => {
|
|
199
|
+
beforeEach(async () => {
|
|
200
|
+
page = new DocsPage('/docs/docs-content-type-example/sample-api');
|
|
201
|
+
page.open();
|
|
202
|
+
await page.waitForRedocLoad();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('renders the spec title in the Redoc view', async () => {
|
|
206
|
+
const apiTitle = await page.getRedocApiTitle();
|
|
207
|
+
|
|
208
|
+
expect(await apiTitle.getText()).toContain('Sample Widgets API');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('shows a back link labelled with the project title', async () => {
|
|
212
|
+
const backLink = await page.getRedocBackLink();
|
|
213
|
+
await backLink.waitForDisplayed();
|
|
214
|
+
|
|
215
|
+
expect(await backLink.isDisplayed()).toBeTruthy();
|
|
216
|
+
expect(await (await page.getRedocProjectTitle()).getText()).not.toBe('');
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it('falls back to the landing topic when the back link is clicked on a directly opened spec', async () => {
|
|
220
|
+
await browser.reloadSession();
|
|
221
|
+
page = new DocsPage('/docs/docs-content-type-example/sample-api');
|
|
222
|
+
page.open();
|
|
223
|
+
await page.waitForRedocLoad();
|
|
224
|
+
|
|
225
|
+
const backLink = await page.getRedocBackLink();
|
|
226
|
+
await backLink.waitForDisplayed();
|
|
227
|
+
await backLink.click();
|
|
228
|
+
await page.waitPageLoad();
|
|
229
|
+
|
|
230
|
+
expect(await browser.getUrl()).toContain('get-started.html');
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
describe('Docs content type > locale picker', () => {
|
|
235
|
+
it('shows the language picker on a markdown topic of a localized project', async () => {
|
|
236
|
+
page = new DocsPage('/docs/docs-content-type-example/widget-concepts.html');
|
|
237
|
+
page.open();
|
|
238
|
+
await page.waitPageLoad();
|
|
239
|
+
await page.waitForSidebar();
|
|
240
|
+
|
|
241
|
+
const languagePicker = await page.getLanguagePicker();
|
|
242
|
+
await languagePicker.waitForDisplayed();
|
|
243
|
+
|
|
244
|
+
expect(await languagePicker.isDisplayed()).toBeTruthy();
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
it('shows the language picker on a spec topic of a localized project', async () => {
|
|
248
|
+
page = new DocsPage('/docs/docs-content-type-example/sample-api');
|
|
249
|
+
page.open();
|
|
250
|
+
await page.waitForRedocLoad();
|
|
251
|
+
|
|
252
|
+
const languagePicker = await page.getLanguagePicker();
|
|
253
|
+
await languagePicker.waitForDisplayed();
|
|
254
|
+
|
|
255
|
+
expect(await languagePicker.isDisplayed()).toBeTruthy();
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('re-renders the spec in the selected locale when switching language on a spec page', async () => {
|
|
259
|
+
page = new DocsPage('/docs/docs-content-type-example/sample-api');
|
|
260
|
+
page.open();
|
|
261
|
+
await page.waitForRedocLoad();
|
|
262
|
+
|
|
263
|
+
await page.selectLanguage('日本語');
|
|
264
|
+
await page.waitForRedocLoad();
|
|
265
|
+
|
|
266
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
267
|
+
expect(await (await page.getRedocApiTitle()).getText()).not.toBe('');
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('keeps the selected locale when navigating to the spec view and back', async () => {
|
|
271
|
+
page = new DocsPage('/docs/docs-content-type-example/get-started.html');
|
|
272
|
+
page.open();
|
|
273
|
+
await page.waitPageLoad();
|
|
274
|
+
await page.waitForSidebar();
|
|
275
|
+
|
|
276
|
+
await page.selectLanguage('日本語');
|
|
277
|
+
await page.waitPageLoad();
|
|
278
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
279
|
+
|
|
280
|
+
const specTile = await page.getSidebarTile('ウィジェット API リファレンス');
|
|
281
|
+
await specTile.click();
|
|
282
|
+
await page.waitForRedocLoad();
|
|
283
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
284
|
+
|
|
285
|
+
const backLink = await page.getRedocBackLink();
|
|
286
|
+
await backLink.waitForDisplayed();
|
|
287
|
+
await backLink.click();
|
|
288
|
+
await page.waitPageLoad();
|
|
289
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
describe('Docs content type > localized (ja-jp) rendering', () => {
|
|
294
|
+
it('renders the Japanese body and sidebar on a ja-jp markdown topic', async () => {
|
|
295
|
+
page = new DocsPage('/docs/ja-jp/docs-content-type-example/get-started.html');
|
|
296
|
+
page.open();
|
|
297
|
+
await page.waitPageLoad();
|
|
298
|
+
await page.waitForSidebar();
|
|
299
|
+
|
|
300
|
+
expect(await (await page.getContentHeading()).getText()).toContain(
|
|
301
|
+
'ウィジェット サービスを始める',
|
|
302
|
+
);
|
|
303
|
+
// Sidebar tiles are localized — the Japanese "Widget Concepts" label resolves.
|
|
304
|
+
const tile = await page.getSidebarTile('ウィジェットの概念');
|
|
305
|
+
expect(await tile.isExisting()).toBe(true);
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('renders the Redoc view from a ja-jp spec URL', async () => {
|
|
309
|
+
page = new DocsPage('/docs/ja-jp/docs-content-type-example/sample-api');
|
|
310
|
+
page.open();
|
|
311
|
+
await page.waitForRedocLoad();
|
|
312
|
+
|
|
313
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
314
|
+
expect(await (await page.getRedocApiTitle()).getText()).not.toBe('');
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
describe('Docs content type > englishonly filter', () => {
|
|
319
|
+
it('serves the englishonly topic in English', async () => {
|
|
320
|
+
page = new DocsPage('/docs/docs-content-type-example/us-compliance-notes.html');
|
|
321
|
+
page.open();
|
|
322
|
+
await page.waitPageLoad();
|
|
323
|
+
|
|
324
|
+
expect(await (await page.getContentHeading()).getText()).toContain('US Compliance Notes');
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe('Docs content type > language picker round-trip', () => {
|
|
329
|
+
it('switches a markdown topic between English and Japanese and back', async () => {
|
|
330
|
+
page = new DocsPage('/docs/docs-content-type-example/get-started.html');
|
|
331
|
+
page.open();
|
|
332
|
+
await page.waitPageLoad();
|
|
333
|
+
await page.waitForSidebar();
|
|
334
|
+
|
|
335
|
+
await page.selectLanguage('日本語');
|
|
336
|
+
await page.waitPageLoad();
|
|
337
|
+
expect(await browser.getUrl()).toContain('/ja-jp/');
|
|
338
|
+
expect(await browser.getUrl()).toContain('get-started.html');
|
|
339
|
+
expect(await (await page.getContentHeading()).getText()).toContain(
|
|
340
|
+
'ウィジェット サービスを始める',
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
await page.selectLanguage('English');
|
|
344
|
+
await page.waitPageLoad();
|
|
345
|
+
expect(await browser.getUrl()).not.toContain('/ja-jp/');
|
|
346
|
+
expect(await browser.getUrl()).toContain('get-started.html');
|
|
347
|
+
expect(await (await page.getContentHeading()).getText()).toContain('Get Started');
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
describe('Docs content type > external link', () => {
|
|
352
|
+
it('exposes the real href and opens the external link in a new tab', async () => {
|
|
353
|
+
page = new DocsPage('/docs/docs-content-type-example/get-started.html');
|
|
354
|
+
page.open();
|
|
355
|
+
await page.waitPageLoad();
|
|
356
|
+
await page.waitForSidebar();
|
|
357
|
+
|
|
358
|
+
const tile = await page.getSidebarTile('Salesforce Developers');
|
|
359
|
+
const anchor = await tile.shadow$('a');
|
|
360
|
+
expect(await anchor.getAttribute('href')).toContain('https://developer.salesforce.com');
|
|
361
|
+
expect(await anchor.getAttribute('target')).toBe('_blank');
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
describe('Docs content type > Liquid templating', () => {
|
|
366
|
+
beforeEach(async () => {
|
|
367
|
+
page = new DocsPage('/docs/docs-content-type-example/liquid-widgets.html');
|
|
368
|
+
page.open();
|
|
369
|
+
await page.waitPageLoad();
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
it('resolves frontmatter assigns and liquid.data values in the body', async () => {
|
|
373
|
+
const content = await $('>>>doc-content-layout');
|
|
374
|
+
const text = await content.getText();
|
|
375
|
+
const html = await content.getHTML();
|
|
376
|
+
|
|
377
|
+
expect(text).toContain('Widget Automation');
|
|
378
|
+
expect(text).toContain('Hello from the docs liquid data file');
|
|
379
|
+
expect(html).not.toContain('{% assign');
|
|
380
|
+
expect(html).not.toContain('{{ feature }}');
|
|
381
|
+
expect(html).not.toContain('{{ data.tagline }}');
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
it('resolves repository-level variables from content-config.yml', async () => {
|
|
385
|
+
const content = await $('>>>doc-content-layout');
|
|
386
|
+
const text = await content.getText();
|
|
387
|
+
const html = await content.getHTML();
|
|
388
|
+
|
|
389
|
+
expect(text).toContain('Salesforce Platform');
|
|
390
|
+
expect(text).toContain('62.0');
|
|
391
|
+
expect(html).not.toContain('{{ variables.platform');
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it('renders a loop over a liquid.data array', async () => {
|
|
395
|
+
const content = await $('>>>doc-content-layout');
|
|
396
|
+
const text = await content.getText();
|
|
397
|
+
const html = await content.getHTML();
|
|
398
|
+
|
|
399
|
+
expect(text).toContain('createWidget()');
|
|
400
|
+
expect(text).toContain('updateWidget()');
|
|
401
|
+
expect(text).toContain('deleteWidget()');
|
|
402
|
+
expect(html).not.toContain('for operation in data.operations');
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('resolves output expressions inside code blocks but keeps tags literal', async () => {
|
|
406
|
+
const codeBlockElement = await $('>>>.code-block-content');
|
|
407
|
+
const codeBlock = await codeBlockElement.shadow$('code');
|
|
408
|
+
|
|
409
|
+
expect(await codeBlock.isExisting()).toBeTruthy();
|
|
410
|
+
|
|
411
|
+
const codeText = await codeBlock.getText();
|
|
412
|
+
// {{ }} outputs resolve even inside code blocks.
|
|
413
|
+
expect(codeText).not.toContain('{{ data.tagline }}');
|
|
414
|
+
expect(codeText).toContain('Hello from the docs liquid data file');
|
|
415
|
+
expect(codeText).toContain('Widget Automation');
|
|
416
|
+
// {% %} tags stay literal inside code blocks.
|
|
417
|
+
expect(codeText).toContain('for op in ops');
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
it('renders a shared partial pulled in via include and its capture blocks', async () => {
|
|
421
|
+
const content = await $('>>>doc-content-layout');
|
|
422
|
+
const text = await content.getText();
|
|
423
|
+
const html = await content.getHTML();
|
|
424
|
+
|
|
425
|
+
expect(text).toContain('Reusable Tip');
|
|
426
|
+
expect(text).toContain('Widgets are created and managed through the Widgets API');
|
|
427
|
+
expect(text).toContain('Reusable Note');
|
|
428
|
+
expect(text).toContain('Every widget has a unique identifier');
|
|
429
|
+
// Dash-form tags are the fixture's real (resolved) tags; the bare "{% include %}"
|
|
430
|
+
// in the prose renders as literal inline code, so assert on the dash form only.
|
|
431
|
+
expect(html).not.toContain('{%- include');
|
|
432
|
+
expect(html).not.toContain('{%- capture');
|
|
433
|
+
expect(html).not.toContain('{{ liquid-widgets-reuse-tip }}');
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
describe('Docs content type > Liquid data object format', () => {
|
|
438
|
+
it('loads multiple data files each under a named key', async () => {
|
|
439
|
+
page = new DocsPage('/docs/docs-content-type-example/liquid-multi-data.html');
|
|
440
|
+
page.open();
|
|
441
|
+
await page.waitPageLoad();
|
|
442
|
+
|
|
443
|
+
const content = await $('>>>doc-content-layout');
|
|
444
|
+
const text = await content.getText();
|
|
445
|
+
const html = await content.getHTML();
|
|
446
|
+
|
|
447
|
+
expect(text).toContain('Hello from the docs liquid data file');
|
|
448
|
+
expect(text).toContain('Second data file loaded under a named key');
|
|
449
|
+
expect(html).not.toContain('{{ data.one.tagline }}');
|
|
450
|
+
expect(html).not.toContain('{{ two.summary }}');
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
describe('Docs content type > Liquid templating (ja-jp)', () => {
|
|
455
|
+
let jaLiquidEnabled = false;
|
|
456
|
+
const widgetsPath = '/docs/ja-jp/docs-content-type-example/liquid-widgets.html';
|
|
457
|
+
|
|
458
|
+
before(async () => {
|
|
459
|
+
try {
|
|
460
|
+
page = new DocsPage(widgetsPath);
|
|
461
|
+
page.open();
|
|
462
|
+
await page.waitPageLoad();
|
|
463
|
+
|
|
464
|
+
const content = await $('>>>doc-content-layout');
|
|
465
|
+
const text = await content.getText();
|
|
466
|
+
const html = await content.getHTML();
|
|
467
|
+
|
|
468
|
+
const hasLiquidOutput = text.includes(
|
|
469
|
+
'ドキュメント Liquid データ ファイルからこんにちは',
|
|
470
|
+
);
|
|
471
|
+
const hasRawSyntax = html.includes('{% assign') || html.includes('{{ data.tagline }}');
|
|
472
|
+
|
|
473
|
+
jaLiquidEnabled = hasLiquidOutput && !hasRawSyntax;
|
|
474
|
+
} catch (e) {
|
|
475
|
+
jaLiquidEnabled = false;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
beforeEach(async () => {
|
|
480
|
+
if (jaLiquidEnabled) {
|
|
481
|
+
page = new DocsPage(widgetsPath);
|
|
482
|
+
page.open();
|
|
483
|
+
await page.waitPageLoad();
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
it('resolves frontmatter assigns and liquid.data values in a localized topic', async function () {
|
|
488
|
+
if (!jaLiquidEnabled) {
|
|
489
|
+
this.skip();
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
const content = await $('>>>doc-content-layout');
|
|
493
|
+
const text = await content.getText();
|
|
494
|
+
const html = await content.getHTML();
|
|
495
|
+
|
|
496
|
+
expect(text).toContain('ウィジェット オートメーション');
|
|
497
|
+
expect(text).toContain('ドキュメント Liquid データ ファイルからこんにちは');
|
|
498
|
+
expect(html).not.toContain('{% assign');
|
|
499
|
+
expect(html).not.toContain('{{ data.tagline }}');
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it('resolves repository-level variables in a localized topic', async function () {
|
|
503
|
+
if (!jaLiquidEnabled) {
|
|
504
|
+
this.skip();
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const content = await $('>>>doc-content-layout');
|
|
508
|
+
const text = await content.getText();
|
|
509
|
+
const html = await content.getHTML();
|
|
510
|
+
|
|
511
|
+
expect(text).toContain('Salesforce Platform');
|
|
512
|
+
expect(text).toContain('62.0');
|
|
513
|
+
expect(html).not.toContain('{{ variables.platform');
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
it('renders a loop and an included partial capture block in a localized topic', async function () {
|
|
517
|
+
if (!jaLiquidEnabled) {
|
|
518
|
+
this.skip();
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const content = await $('>>>doc-content-layout');
|
|
522
|
+
const text = await content.getText();
|
|
523
|
+
const html = await content.getHTML();
|
|
524
|
+
|
|
525
|
+
expect(text).toContain('createWidget()');
|
|
526
|
+
expect(text).toContain('再利用可能なヒント');
|
|
527
|
+
expect(text).toContain('ウィジェットは Widgets API を通じて作成および管理されます');
|
|
528
|
+
expect(html).not.toContain('for operation in data.operations');
|
|
529
|
+
expect(html).not.toContain('{%- include');
|
|
530
|
+
expect(html).not.toContain('{%- capture');
|
|
531
|
+
});
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
describe('Docs content type > Liquid data object format (ja-jp)', () => {
|
|
535
|
+
let jaLiquidEnabled = false;
|
|
536
|
+
const multiDataPath = '/docs/ja-jp/docs-content-type-example/liquid-multi-data.html';
|
|
537
|
+
|
|
538
|
+
before(async () => {
|
|
539
|
+
try {
|
|
540
|
+
page = new DocsPage(multiDataPath);
|
|
541
|
+
page.open();
|
|
542
|
+
await page.waitPageLoad();
|
|
543
|
+
|
|
544
|
+
const content = await $('>>>doc-content-layout');
|
|
545
|
+
const text = await content.getText();
|
|
546
|
+
const html = await content.getHTML();
|
|
547
|
+
|
|
548
|
+
const hasLiquidOutput = text.includes(
|
|
549
|
+
'ドキュメント Liquid データ ファイルからこんにちは',
|
|
550
|
+
);
|
|
551
|
+
const hasRawSyntax =
|
|
552
|
+
html.includes('{{ data.one.tagline }}') || html.includes('{{ two.summary }}');
|
|
553
|
+
|
|
554
|
+
jaLiquidEnabled = hasLiquidOutput && !hasRawSyntax;
|
|
555
|
+
} catch (e) {
|
|
556
|
+
jaLiquidEnabled = false;
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
it('loads multiple data files each under a named key in a localized topic', async function () {
|
|
561
|
+
if (!jaLiquidEnabled) {
|
|
562
|
+
this.skip();
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
page = new DocsPage(multiDataPath);
|
|
566
|
+
page.open();
|
|
567
|
+
await page.waitPageLoad();
|
|
568
|
+
|
|
569
|
+
const content = await $('>>>doc-content-layout');
|
|
570
|
+
const text = await content.getText();
|
|
571
|
+
const html = await content.getHTML();
|
|
572
|
+
|
|
573
|
+
expect(text).toContain('ドキュメント Liquid データ ファイルからこんにちは');
|
|
574
|
+
expect(text).toContain('名前付きキーの下に読み込まれる 2 番目のデータ ファイル');
|
|
575
|
+
expect(html).not.toContain('{{ data.one.tagline }}');
|
|
576
|
+
expect(html).not.toContain('{{ two.summary }}');
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
describe('Docs content type > error routes', () => {
|
|
581
|
+
const expectNotFoundPage = async (): Promise<void> => {
|
|
582
|
+
const errorComponent = await $('dx-error');
|
|
583
|
+
await errorComponent.waitForDisplayed();
|
|
584
|
+
|
|
585
|
+
expect(await browser.getTitle()).toEqual('404 Error | Salesforce Developers');
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
it('renders the 404 page for a markdown topic that does not exist', async () => {
|
|
589
|
+
page = new DocsPage('/docs/docs-content-type-example/no-such-topic.html');
|
|
590
|
+
page.open();
|
|
591
|
+
|
|
592
|
+
await expectNotFoundPage();
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
it('renders the 404 page for a spec topic that does not exist', async () => {
|
|
596
|
+
page = new DocsPage('/docs/docs-content-type-example/no-such-spec');
|
|
597
|
+
page.open();
|
|
598
|
+
|
|
599
|
+
await expectNotFoundPage();
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
it('renders the 404 page for the original filename of an id-overridden topic', async () => {
|
|
603
|
+
page = new DocsPage('/docs/docs-content-type-example/clickable-topic.html');
|
|
604
|
+
page.open();
|
|
605
|
+
|
|
606
|
+
await expectNotFoundPage();
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
it('renders the 404 page for an unknown docs project', async () => {
|
|
610
|
+
page = new DocsPage('/docs/no-such-docs-project/get-started.html');
|
|
611
|
+
page.open();
|
|
612
|
+
|
|
613
|
+
await expectNotFoundPage();
|
|
614
|
+
});
|
|
615
|
+
});
|
|
@@ -64,7 +64,7 @@ describe('Test Guides page components functionality> ', () => {
|
|
|
64
64
|
const sidebar = await (await $('doc-content-layout')).shadow$('div > dx-sidebar-old');
|
|
65
65
|
const sideBarContent = await sidebar.shadow$$('div.container div.sidebar-content dx-tree');
|
|
66
66
|
|
|
67
|
-
expect(sideBarContent.length).toEqual(
|
|
67
|
+
expect(sideBarContent.length).toEqual(6);
|
|
68
68
|
|
|
69
69
|
const nextStepOption = await (
|
|
70
70
|
await sideBarContent[3].shadow$('dx-tree-item')
|