@salesforcedevs/sfdocs-e2e 1.0.9-alpha-check-3 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bin/publish.sh +5 -2
- package/bin/run-e2e.js +1 -0
- package/common-wdio.conf.js +20 -9
- package/package.json +3 -2
- package/portal-wdio.conf.js +5 -0
- package/src/content-repo/specs/homepage.test.ts +1 -1
- package/src/shared/pageobjects/api-redoc-reference.page.ts +5 -0
- package/src/shared/pageobjects/page.ts +3 -3
- package/src/shared/pageobjects/reference.page.ts +9 -0
- package/src/shared/specs/contentActionToolbar.test.ts +59 -0
- package/src/shared/specs/guides.test.ts +1 -1
- package/src/shared/specs/internalLinks.test.ts +70 -0
- package/src/shared/specs/layout-tests.ts +5 -3
- package/src/shared/specs/liquid-advanced.test.ts +56 -0
- package/src/shared/specs/liquid.test.ts +224 -0
- package/src/shared/specs/redoc-reference.test.ts +143 -0
- package/src/shared/specs/reference.test.ts +6 -1
- package/src/shared/specs/video.test.ts +4 -1
- package/static-dsc-portal-wdio.conf.js +49 -0
- package/static-portal-wdio.conf.js +2 -7
- package/wdio.conf.js +1 -0
package/README.md
CHANGED
package/bin/publish.sh
CHANGED
|
@@ -3,7 +3,6 @@ set -euo pipefail
|
|
|
3
3
|
|
|
4
4
|
VERSION="${1:?Usage: publish.sh <version> [--tag <tag>]}"
|
|
5
5
|
shift
|
|
6
|
-
TAG_ARGS=("$@")
|
|
7
6
|
|
|
8
7
|
cp package.json .package.json.bak
|
|
9
8
|
|
|
@@ -25,4 +24,8 @@ node -e "
|
|
|
25
24
|
require('fs').writeFileSync('package.json', JSON.stringify(p, null, 2) + '\n');
|
|
26
25
|
"
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
if [ "$#" -gt 0 ]; then
|
|
28
|
+
yarn publish --new-version "$VERSION" "$@"
|
|
29
|
+
else
|
|
30
|
+
yarn publish --new-version "$VERSION"
|
|
31
|
+
fi
|
package/bin/run-e2e.js
CHANGED
|
@@ -56,6 +56,7 @@ Environment Variables:
|
|
|
56
56
|
const configName = parsedArgs.config || 'static-portal';
|
|
57
57
|
const configMap = {
|
|
58
58
|
'static-portal': 'static-portal-wdio.conf.js',
|
|
59
|
+
'static-dsc-portal': 'static-dsc-portal-wdio.conf.js',
|
|
59
60
|
portal: 'portal-wdio.conf.js',
|
|
60
61
|
search: 'search-wdio.conf.js',
|
|
61
62
|
};
|
package/common-wdio.conf.js
CHANGED
|
@@ -80,6 +80,7 @@ const defaultCapabilities = [
|
|
|
80
80
|
},
|
|
81
81
|
];
|
|
82
82
|
const defaultMochaTimeoutInterval = 200000; //increased timeout because its taking more time to load for references file
|
|
83
|
+
const isGithubActions = Boolean(process.env.GITHUB_ACTIONS);
|
|
83
84
|
|
|
84
85
|
// Resolve ChromeDriver version: env var → Chrome for Testing API lookup → latest
|
|
85
86
|
const resolvedChromeDriverVersion = resolveChromedriverVersion();
|
|
@@ -181,15 +182,25 @@ exports.config = {
|
|
|
181
182
|
// Services take over a specific job you don't want to take care of. They enhance
|
|
182
183
|
// your test setup with almost no effort. Unlike plugins, they don't add new
|
|
183
184
|
// commands. Instead, they hook themselves up into the test process.
|
|
184
|
-
services:
|
|
185
|
-
[
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
185
|
+
services: isGithubActions
|
|
186
|
+
? []
|
|
187
|
+
: [
|
|
188
|
+
[
|
|
189
|
+
'selenium-standalone',
|
|
190
|
+
{
|
|
191
|
+
installArgs: { drivers }, // drivers to install
|
|
192
|
+
args: { drivers }, // drivers to use
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
],
|
|
196
|
+
...(isGithubActions
|
|
197
|
+
? {
|
|
198
|
+
protocol: 'http',
|
|
199
|
+
hostname: '127.0.0.1',
|
|
200
|
+
port: 4444,
|
|
201
|
+
path: '/wd/hub',
|
|
202
|
+
}
|
|
203
|
+
: {}),
|
|
193
204
|
|
|
194
205
|
// Framework you want to run your specs with.
|
|
195
206
|
// The following are supported: Mocha, Jasmine, and Cucumber
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforcedevs/sfdocs-e2e",
|
|
3
|
-
"version": "1.0.9
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "E2E test suite for SFDocs static portal pages (SSG)",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"bin": {
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
"test:e2e": "TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=./tsconfig.json wdio wdio.conf.js",
|
|
17
17
|
"test:e2e:portal": "TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=./tsconfig.json wdio portal-wdio.conf.js",
|
|
18
18
|
"test:e2e:static:portal": "TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=./tsconfig.json wdio static-portal-wdio.conf.js",
|
|
19
|
+
"test:e2e:static:dsc:portal": "TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=./tsconfig.json wdio static-dsc-portal-wdio.conf.js",
|
|
19
20
|
"test:scope-search": "TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT=./tsconfig.json wdio search-wdio.conf.js",
|
|
20
21
|
"release:alpha:e2e": "f() { bash bin/publish.sh $1 --tag alpha; }; f",
|
|
21
22
|
"release:e2e": "f() { bash bin/publish.sh $1; }; f"
|
|
22
23
|
},
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@sa11y/wdio": "^
|
|
25
|
+
"@sa11y/wdio": "^8.0.0",
|
|
25
26
|
"@wdio/allure-reporter": "^7.19.0",
|
|
26
27
|
"@wdio/cli": "^7.19.0",
|
|
27
28
|
"@wdio/local-runner": "^7.19.0",
|
package/portal-wdio.conf.js
CHANGED
|
@@ -4,4 +4,9 @@ exports.config = {
|
|
|
4
4
|
...BASE_CONFIG.config,
|
|
5
5
|
baseUrl: process.env.E2E_BASE_URL || 'http://localhost:3001',
|
|
6
6
|
specs: ['./src/portal/specs/**/*.test.ts', './src/shared/specs/*.test.ts'],
|
|
7
|
+
exclude: [
|
|
8
|
+
'./src/shared/specs/contentActionToolbar.test.ts',
|
|
9
|
+
// Advanced liquid tests require previewFuture — not enabled in portal builds
|
|
10
|
+
'./src/shared/specs/liquid-advanced.test.ts',
|
|
11
|
+
],
|
|
7
12
|
};
|
|
@@ -13,7 +13,7 @@ describe('Homepage', () => {
|
|
|
13
13
|
it('should show the expected number of projects', async () => {
|
|
14
14
|
const projectCards = await HomePage.projectCards;
|
|
15
15
|
|
|
16
|
-
expect(projectCards.length).toEqual(
|
|
16
|
+
expect(projectCards.length).toEqual(21);
|
|
17
17
|
});
|
|
18
18
|
|
|
19
19
|
// it('is accessible', () => {
|
|
@@ -35,6 +35,11 @@ class ApiRedocReferencePage extends Page {
|
|
|
35
35
|
const lnbItems = await scrollbarContainer.$$('ul[role="menu"] > li');
|
|
36
36
|
return lnbItems[index];
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
async getProjectHeader(): Promise<WebdriverIO.Element> {
|
|
40
|
+
const sidebar = await this.getSidebar();
|
|
41
|
+
return sidebar.$('div.redoc-project-header');
|
|
42
|
+
}
|
|
38
43
|
}
|
|
39
44
|
|
|
40
45
|
export default ApiRedocReferencePage;
|
|
@@ -44,15 +44,15 @@ export default class Page {
|
|
|
44
44
|
);
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
async getHeader(): Promise<WebdriverIO.Element> {
|
|
48
|
-
return await $(
|
|
47
|
+
async getHeader(headerTag = 'dx-global-header'): Promise<WebdriverIO.Element> {
|
|
48
|
+
return await $(headerTag);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
async getHeaderTitle(): Promise<WebdriverIO.Element> {
|
|
52
52
|
return (await $('>>>header')).$('h4');
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
async getGlobalSearchBox(headerTag = 'dx-header'): Promise<WebdriverIO.Element> {
|
|
55
|
+
async getGlobalSearchBox(headerTag = 'dx-global-header'): Promise<WebdriverIO.Element> {
|
|
56
56
|
return (await $(headerTag)).shadow$('dx-header-search');
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -38,4 +38,13 @@ export class ReferencePage extends Page {
|
|
|
38
38
|
async getSidebarContent(): Promise<WebdriverIO.Element> {
|
|
39
39
|
return $('>>>div .sidebar-item-selected');
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
async getSidebar(): Promise<WebdriverIO.Element> {
|
|
43
|
+
return (await $('>>>doc-content-layout')).shadow$('div > dx-sidebar-old');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getSidebarItems(): Promise<WebdriverIO.ElementArray> {
|
|
47
|
+
const sidebar = await this.getSidebar();
|
|
48
|
+
return sidebar.shadow$$('div.container div.sidebar-content dx-tree');
|
|
49
|
+
}
|
|
41
50
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import GuidePage from '../pageobjects/guide.page';
|
|
2
|
+
import { ReferencePage } from '../pageobjects/reference.page';
|
|
3
|
+
|
|
4
|
+
const EN_US_GUIDE_PATH = '/docs/service/vscode-maintainer/guide/vscode-overview.html';
|
|
5
|
+
const EN_US_MARKDOWN_REFERENCE_PATH =
|
|
6
|
+
'/docs/commerce/flexible-references/references/shopper-manual-ref/quick-start.html';
|
|
7
|
+
const NON_MARKDOWN_REFERENCE_PATH = '/docs/test-metamind-oas-api/references/1mkfx9?meta=Summary';
|
|
8
|
+
const NON_EN_US_MARKDOWN_REFERENCE_PATH =
|
|
9
|
+
'/docs/commerce/ja-jp/flex-references-loc/references/manual-ref/commerce-cloud-api-overview.html';
|
|
10
|
+
|
|
11
|
+
async function expectToolbarButtons(toolbar: WebdriverIO.Element): Promise<void> {
|
|
12
|
+
const toolbarButtons = await toolbar.shadow$$('dx-button.toolbar-button');
|
|
13
|
+
expect(toolbarButtons.length).toBe(3);
|
|
14
|
+
|
|
15
|
+
const labels = await Promise.all(
|
|
16
|
+
toolbarButtons.map(async (button) => (await button.getText()).trim()),
|
|
17
|
+
);
|
|
18
|
+
expect(labels).toEqual(
|
|
19
|
+
expect.arrayContaining(['Copy as Markdown', 'View as Markdown', 'Copy URL to Markdown']),
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe('Content action toolbar scenarios', () => {
|
|
24
|
+
it('Markdown guide should have the toolbar', async () => {
|
|
25
|
+
const page = new GuidePage(EN_US_GUIDE_PATH);
|
|
26
|
+
page.open();
|
|
27
|
+
await page.waitPageLoad();
|
|
28
|
+
|
|
29
|
+
const toolbar = await $('>>>doc-content-action-toolbar');
|
|
30
|
+
await toolbar.waitForDisplayed();
|
|
31
|
+
await expectToolbarButtons(toolbar);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('Markdown reference should have the toolbar', async () => {
|
|
35
|
+
const referencePage = new ReferencePage(EN_US_MARKDOWN_REFERENCE_PATH);
|
|
36
|
+
referencePage.open();
|
|
37
|
+
await referencePage.waitForMarkdownBasedReferencePageLoad();
|
|
38
|
+
|
|
39
|
+
const toolbar = await $('>>>doc-content-action-toolbar');
|
|
40
|
+
await toolbar.waitForDisplayed();
|
|
41
|
+
await expectToolbarButtons(toolbar);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("Non-markdown reference shouldn't have toolbar", async () => {
|
|
45
|
+
const referencePage = new ReferencePage(NON_MARKDOWN_REFERENCE_PATH);
|
|
46
|
+
referencePage.open();
|
|
47
|
+
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
48
|
+
|
|
49
|
+
const toolbar = await $('>>>doc-content-action-toolbar');
|
|
50
|
+
expect(await toolbar.isExisting()).toBeFalsy();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("Non en-us locale page shouldn't have toolbar", async () => {
|
|
54
|
+
const nonEnUsReferencePage = new ReferencePage(NON_EN_US_MARKDOWN_REFERENCE_PATH);
|
|
55
|
+
nonEnUsReferencePage.open();
|
|
56
|
+
await nonEnUsReferencePage.waitForMarkdownBasedReferencePageLoad();
|
|
57
|
+
expect(await (await $('>>>doc-content-action-toolbar')).isExisting()).toBeFalsy();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -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')
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import GuidePage from '../pageobjects/guide.page';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* E2E tests for internal link resolution (internalReferencePlugin + referenceLinkTransformerPlugin).
|
|
5
|
+
* Covered: relative .md → .html resolution, guide-to-guide links, reference-to-guide links,
|
|
6
|
+
* external links.
|
|
7
|
+
**/
|
|
8
|
+
describe('Internal link resolution', () => {
|
|
9
|
+
const UPDATE_ORDER_STATES_PAGE =
|
|
10
|
+
'/docs/commerce/test-cc-orders-api/guide/update-order-states.html';
|
|
11
|
+
const QUICK_START_PAGE = '/docs/commerce/test-cc-orders-api/guide/quick-start.html';
|
|
12
|
+
const REFERENCE_PAGE =
|
|
13
|
+
'/docs/success/sfdocs/references/markdown-cheatsheet/markdown-cheatsheet.html#how-to-link-between-overviews-guides-and-references';
|
|
14
|
+
|
|
15
|
+
let page: GuidePage;
|
|
16
|
+
|
|
17
|
+
it('should resolve relative guide link correctly', async () => {
|
|
18
|
+
page = new GuidePage(UPDATE_ORDER_STATES_PAGE);
|
|
19
|
+
page.open();
|
|
20
|
+
await page.waitPageLoad();
|
|
21
|
+
|
|
22
|
+
const ordersApiLink = await $('a.internal-link-guide[href*="orders-api-overview"]');
|
|
23
|
+
await ordersApiLink.waitForDisplayed();
|
|
24
|
+
const href = await ordersApiLink.getAttribute('href');
|
|
25
|
+
expect(href).not.toMatch(/\.md(?:\?|#|$)/);
|
|
26
|
+
expect(href).toContain('orders-api-overview.html');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should resolve guide linking in same folder correctly', async () => {
|
|
30
|
+
page = new GuidePage(QUICK_START_PAGE);
|
|
31
|
+
page.open();
|
|
32
|
+
await page.waitPageLoad();
|
|
33
|
+
|
|
34
|
+
await (await $('>>> doc-heading[hash="see-also"]')).waitForDisplayed();
|
|
35
|
+
|
|
36
|
+
const understandTheBasicsLink = await $('=Understand the Basics');
|
|
37
|
+
await understandTheBasicsLink.waitForDisplayed();
|
|
38
|
+
const href = await understandTheBasicsLink.getAttribute('href');
|
|
39
|
+
expect(href).not.toMatch(/\.md(?:\?|#|$)/);
|
|
40
|
+
expect(href).toContain('understand-the-basics.html');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should have html link for reference to guide linking', async () => {
|
|
44
|
+
page = new GuidePage(REFERENCE_PAGE);
|
|
45
|
+
page.open();
|
|
46
|
+
await page.waitPageLoad();
|
|
47
|
+
|
|
48
|
+
await (
|
|
49
|
+
await $('>>> doc-heading[hash="how-to-link-between-overviews-guides-and-references"]')
|
|
50
|
+
).waitForDisplayed();
|
|
51
|
+
|
|
52
|
+
const threeContentTypesLink = await $('=three content types');
|
|
53
|
+
await threeContentTypesLink.waitForDisplayed();
|
|
54
|
+
const href = await threeContentTypesLink.getAttribute('href');
|
|
55
|
+
expect(href).toContain('guide');
|
|
56
|
+
expect(href).toMatch(/\.html(?:#|$|\?)/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should treat external links as external', async () => {
|
|
60
|
+
page = new GuidePage(REFERENCE_PAGE);
|
|
61
|
+
page.open();
|
|
62
|
+
await page.waitPageLoad();
|
|
63
|
+
|
|
64
|
+
const externalLinks = await $$('a.external-link-guide');
|
|
65
|
+
expect(externalLinks.length).toBeGreaterThan(0);
|
|
66
|
+
for (const link of externalLinks) {
|
|
67
|
+
expect(await link.getAttribute('target')).toBe('_blank');
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
@@ -7,7 +7,7 @@ import Page from '../pageobjects/page';
|
|
|
7
7
|
* @param givenPage : This is the current page for which we need to test chrome.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
export default function layoutTest(givenPage: Page, headerTag = 'dx-header') {
|
|
10
|
+
export default function layoutTest(givenPage: Page, headerTag = 'dx-global-header') {
|
|
11
11
|
let page: Page;
|
|
12
12
|
describe('Basic layout testing > ', () => {
|
|
13
13
|
beforeEach(async () => {
|
|
@@ -15,10 +15,12 @@ export default function layoutTest(givenPage: Page, headerTag = 'dx-header') {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('should display header', async () => {
|
|
18
|
-
const header = await $(
|
|
18
|
+
const header = await $(headerTag);
|
|
19
19
|
await header.waitForDisplayed();
|
|
20
20
|
expect(await header.isDisplayed()).toBeTruthy();
|
|
21
|
-
|
|
21
|
+
if (headerTag === 'dx-global-header') {
|
|
22
|
+
expect(await header.getText()).toContain('Developers');
|
|
23
|
+
}
|
|
22
24
|
});
|
|
23
25
|
|
|
24
26
|
it.skip('should display global search box', async () => {
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import GuidePage from '../pageobjects/guide.page';
|
|
2
|
+
|
|
3
|
+
let page: GuidePage;
|
|
4
|
+
let liquidEnabled = false;
|
|
5
|
+
|
|
6
|
+
describe('Liquid Template Rendering — Advanced', () => {
|
|
7
|
+
before(async () => {
|
|
8
|
+
try {
|
|
9
|
+
page = new GuidePage('/docs/liquid-project/guide/liquid-quickstart.html');
|
|
10
|
+
await browser.url(page.path);
|
|
11
|
+
await page.waitPageLoad();
|
|
12
|
+
|
|
13
|
+
const content = await $('>>>doc-content-layout');
|
|
14
|
+
const text = await content.getText();
|
|
15
|
+
|
|
16
|
+
liquidEnabled = text.includes('Hello from data.yaml');
|
|
17
|
+
} catch (e) {
|
|
18
|
+
liquidEnabled = false;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
if (liquidEnabled) {
|
|
24
|
+
page = new GuidePage('/docs/liquid-project/guide/liquid-quickstart.html');
|
|
25
|
+
await browser.url(page.path);
|
|
26
|
+
await page.waitPageLoad();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('Should render future block content when previewFuture is enabled', async function () {
|
|
31
|
+
if (!liquidEnabled) {
|
|
32
|
+
this.skip();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const content = await $('>>>doc-content-layout');
|
|
36
|
+
const text = await content.getText();
|
|
37
|
+
|
|
38
|
+
expect(text.includes('Coming Soon')).toBeTruthy();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('Should render the future topic page when previewFuture is enabled', async function () {
|
|
42
|
+
if (!liquidEnabled) {
|
|
43
|
+
this.skip();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const futurePage = new GuidePage('/docs/liquid-project/guide/future-topic.html');
|
|
47
|
+
await browser.url(futurePage.path);
|
|
48
|
+
await futurePage.waitPageLoad();
|
|
49
|
+
|
|
50
|
+
const content = await $('>>>doc-content-layout');
|
|
51
|
+
const text = await content.getText();
|
|
52
|
+
|
|
53
|
+
expect(text.includes('Future Feature')).toBeTruthy();
|
|
54
|
+
expect(text.includes('previewFuture')).toBeTruthy();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import GuidePage from '../pageobjects/guide.page';
|
|
2
|
+
|
|
3
|
+
let page: GuidePage;
|
|
4
|
+
let liquidEnabled = false;
|
|
5
|
+
|
|
6
|
+
describe('Liquid Template Rendering', () => {
|
|
7
|
+
before(async () => {
|
|
8
|
+
try {
|
|
9
|
+
page = new GuidePage('/docs/liquid-project/guide/liquid-quickstart.html');
|
|
10
|
+
await browser.url(page.path);
|
|
11
|
+
await page.waitPageLoad();
|
|
12
|
+
|
|
13
|
+
const content = await $('>>>doc-content-layout');
|
|
14
|
+
const text = await content.getText();
|
|
15
|
+
const html = await content.getHTML();
|
|
16
|
+
|
|
17
|
+
const hasLiquidOutput = text.includes('Hello from data.yaml');
|
|
18
|
+
const hasRawSyntax =
|
|
19
|
+
html.includes('{% assign') ||
|
|
20
|
+
html.includes('{% include') ||
|
|
21
|
+
html.includes('{{ data.greeting }}');
|
|
22
|
+
|
|
23
|
+
if (hasRawSyntax) {
|
|
24
|
+
liquidEnabled = false;
|
|
25
|
+
} else if (hasLiquidOutput) {
|
|
26
|
+
liquidEnabled = true;
|
|
27
|
+
} else {
|
|
28
|
+
liquidEnabled = false;
|
|
29
|
+
}
|
|
30
|
+
} catch (e) {
|
|
31
|
+
liquidEnabled = false;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
beforeEach(async () => {
|
|
36
|
+
if (liquidEnabled) {
|
|
37
|
+
page = new GuidePage('/docs/liquid-project/guide/liquid-quickstart.html');
|
|
38
|
+
await browser.url(page.path);
|
|
39
|
+
await page.waitPageLoad();
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('Should render Liquid variables from frontmatter and data.yaml', async function () {
|
|
44
|
+
if (!liquidEnabled) {
|
|
45
|
+
this.skip();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const content = await $('>>>doc-content-layout');
|
|
49
|
+
const text = await content.getText();
|
|
50
|
+
|
|
51
|
+
expect(text.includes('GitHub for writers')).toBeTruthy();
|
|
52
|
+
expect(text.includes('Hello from data.yaml')).toBeTruthy();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('Should render repository-level variables from content-config.yml', async function () {
|
|
56
|
+
if (!liquidEnabled) {
|
|
57
|
+
this.skip();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const content = await $('>>>doc-content-layout');
|
|
61
|
+
const text = await content.getText();
|
|
62
|
+
const html = await content.getHTML();
|
|
63
|
+
|
|
64
|
+
expect(text.includes('Salesforce Platform')).toBeTruthy();
|
|
65
|
+
expect(text.includes('62.0')).toBeTruthy();
|
|
66
|
+
expect(text.includes('sf')).toBeTruthy();
|
|
67
|
+
expect(html.includes('{{ variables.platform')).toBeFalsy();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('Should render included templates from shared directory', async function () {
|
|
71
|
+
if (!liquidEnabled) {
|
|
72
|
+
this.skip();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const content = await $('>>>doc-content-layout');
|
|
76
|
+
const html = await content.getHTML();
|
|
77
|
+
|
|
78
|
+
expect(html.includes('AccountId') || html.includes('Type:')).toBeTruthy();
|
|
79
|
+
expect(html.includes('Properties:')).toBeTruthy();
|
|
80
|
+
expect(html.includes('Special Access Rules')).toBeTruthy();
|
|
81
|
+
expect(html.includes('{% include')).toBeFalsy();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('Should render loops over data arrays', async function () {
|
|
85
|
+
if (!liquidEnabled) {
|
|
86
|
+
this.skip();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const content = await $('>>>doc-content-layout');
|
|
90
|
+
const html = await content.getHTML();
|
|
91
|
+
const text = await content.getText();
|
|
92
|
+
|
|
93
|
+
expect(text.includes('create()')).toBeTruthy();
|
|
94
|
+
expect(text.includes('query()')).toBeTruthy();
|
|
95
|
+
expect(text.includes('update()')).toBeTruthy();
|
|
96
|
+
|
|
97
|
+
const listItems = await content.$$('li');
|
|
98
|
+
expect(listItems.length).toBeGreaterThan(5);
|
|
99
|
+
|
|
100
|
+
expect(text.includes('supported_calls')).toBeFalsy();
|
|
101
|
+
expect(html.includes('for call in supported_calls')).toBeFalsy();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('Should resolve {{ }} outputs inside code blocks but keep {% %} tags literal', async function () {
|
|
105
|
+
if (!liquidEnabled) {
|
|
106
|
+
this.skip();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const codeBlockElement = await $('>>>.code-block-content');
|
|
110
|
+
const codeBlock = await codeBlockElement.shadow$('code');
|
|
111
|
+
|
|
112
|
+
expect(await codeBlock.isExisting()).toBeTruthy();
|
|
113
|
+
|
|
114
|
+
const codeText = await codeBlock.getText();
|
|
115
|
+
expect(codeText.includes('{{ data.greeting }}')).toBeFalsy();
|
|
116
|
+
expect(codeText.includes('{{ topic }}')).toBeFalsy();
|
|
117
|
+
expect(codeText.includes('Hello from data.yaml')).toBeTruthy();
|
|
118
|
+
expect(codeText.includes('GitHub for writers')).toBeTruthy();
|
|
119
|
+
expect(codeText.includes('{% for item in items %}')).toBeTruthy();
|
|
120
|
+
expect(codeText.includes('{{ item }}')).toBeTruthy();
|
|
121
|
+
|
|
122
|
+
const content = await $('>>>doc-content-layout');
|
|
123
|
+
const text = await content.getText();
|
|
124
|
+
expect(text.includes('Visit')).toBeTruthy();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('Should render capture blocks from included files', async function () {
|
|
128
|
+
if (!liquidEnabled) {
|
|
129
|
+
this.skip();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const content = await $('>>>doc-content-layout');
|
|
133
|
+
const html = await content.getHTML();
|
|
134
|
+
const text = await content.getText();
|
|
135
|
+
|
|
136
|
+
expect(text.includes('My Heading')).toBeTruthy();
|
|
137
|
+
expect(text.includes('This is content for ID1.')).toBeTruthy();
|
|
138
|
+
expect(text.includes('Another Heading')).toBeTruthy();
|
|
139
|
+
expect(text.includes('Content for ID2.')).toBeTruthy();
|
|
140
|
+
|
|
141
|
+
expect(html.includes('{%- capture')).toBeFalsy();
|
|
142
|
+
expect(html.includes('{% endcapture')).toBeFalsy();
|
|
143
|
+
expect(html.includes('{{ id1 }}')).toBeFalsy();
|
|
144
|
+
expect(html.includes('{{ id2 }}')).toBeFalsy();
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('Should render englishonly block content in production', async function () {
|
|
148
|
+
if (!liquidEnabled) {
|
|
149
|
+
this.skip();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const content = await $('>>>doc-content-layout');
|
|
153
|
+
const text = await content.getText();
|
|
154
|
+
const html = await content.getHTML();
|
|
155
|
+
|
|
156
|
+
expect(text.includes('This feature is currently only available in English')).toBeTruthy();
|
|
157
|
+
expect(html.includes('{% englishonly')).toBeFalsy();
|
|
158
|
+
expect(html.includes('{% endenglishonly')).toBeFalsy();
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('Should render liquid.data string format — single YAML file on root context', async function () {
|
|
162
|
+
if (!liquidEnabled) {
|
|
163
|
+
this.skip();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const content = await $('>>>doc-content-layout');
|
|
167
|
+
const text = await content.getText();
|
|
168
|
+
|
|
169
|
+
expect(text.includes('Hello from data.yaml')).toBeTruthy();
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('Should render liquid.data object format — multiple YAML files each under a named key', async function () {
|
|
173
|
+
if (!liquidEnabled) {
|
|
174
|
+
this.skip();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const multiDataPage = new GuidePage('/docs/liquid-project/guide/multi-data.html');
|
|
178
|
+
await browser.url(multiDataPage.path);
|
|
179
|
+
await multiDataPage.waitPageLoad();
|
|
180
|
+
|
|
181
|
+
const content = await $('>>>doc-content-layout');
|
|
182
|
+
const text = await content.getText();
|
|
183
|
+
const html = await content.getHTML();
|
|
184
|
+
|
|
185
|
+
expect(text.includes('Sample data file to check the multi-include')).toBeTruthy();
|
|
186
|
+
expect(html.includes('{{ two.summary }}')).toBeFalsy();
|
|
187
|
+
expect(html.includes('{{ data.one.summary }}')).toBeFalsy();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('Should render the englishonly topic page', async function () {
|
|
191
|
+
if (!liquidEnabled) {
|
|
192
|
+
this.skip();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const englishOnlyPage = new GuidePage('/docs/liquid-project/guide/english-only-topic.html');
|
|
196
|
+
await browser.url(englishOnlyPage.path);
|
|
197
|
+
await englishOnlyPage.waitPageLoad();
|
|
198
|
+
|
|
199
|
+
const content = await $('>>>doc-content-layout');
|
|
200
|
+
const text = await content.getText();
|
|
201
|
+
|
|
202
|
+
expect(text.includes('English-Only Topic')).toBeTruthy();
|
|
203
|
+
expect(text.includes('filters: [englishonly]')).toBeTruthy();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('Should render a file with no Liquid syntax as plain markdown', async function () {
|
|
207
|
+
if (!liquidEnabled) {
|
|
208
|
+
this.skip();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const plainPage = new GuidePage(
|
|
212
|
+
'/docs/liquid-project/guide/liquid-learning-resources.html',
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
await browser.url(plainPage.path);
|
|
216
|
+
await plainPage.waitPageLoad();
|
|
217
|
+
|
|
218
|
+
const content = await $('>>>doc-content-layout');
|
|
219
|
+
const text = await content.getText();
|
|
220
|
+
|
|
221
|
+
expect(text.includes('Liquid Resource')).toBeTruthy();
|
|
222
|
+
expect(text.includes('Liquid is a templating language supported in SFDocs')).toBeTruthy();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { it } from 'mocha';
|
|
2
2
|
import RedocApisPage from '../pageobjects/api-redoc-reference.page';
|
|
3
3
|
import OverviewPage from '../pageobjects/overview.page';
|
|
4
|
+
import { ReferencePage } from '../pageobjects/reference.page';
|
|
4
5
|
import {
|
|
5
6
|
waitAndGetDocPhaseParentInRedocReferencesPage,
|
|
6
7
|
assertDocPhaseUnavailability,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
} from '../pageobjects/doc-phase-config';
|
|
10
11
|
|
|
11
12
|
let page: RedocApisPage;
|
|
13
|
+
let refPage: ReferencePage;
|
|
12
14
|
describe('Redoc API Reference page', () => {
|
|
13
15
|
describe('check layouts', () => {
|
|
14
16
|
before(async () => {
|
|
@@ -167,4 +169,145 @@ describe('Redoc API Reference page', () => {
|
|
|
167
169
|
expect(await heading.isDisplayedInViewport()).toBe(true);
|
|
168
170
|
});
|
|
169
171
|
});
|
|
172
|
+
|
|
173
|
+
describe('Flexible References with Redoc Rendering', () => {
|
|
174
|
+
describe('All references view', () => {
|
|
175
|
+
before(async () => {
|
|
176
|
+
refPage = new ReferencePage('docs/service/multi-oas-redoc/references');
|
|
177
|
+
refPage.open();
|
|
178
|
+
|
|
179
|
+
await refPage.waitForMarkdownBasedReferencePageLoad();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('should display all reference titles in LNB', async () => {
|
|
183
|
+
const treeItems = await refPage.getSidebarItems();
|
|
184
|
+
|
|
185
|
+
expect(treeItems.length).toEqual(3);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it('should show arrow button after OAS reference titles', async () => {
|
|
189
|
+
const sideBarContent = await refPage.getSidebarItems();
|
|
190
|
+
|
|
191
|
+
const secondItem = sideBarContent[1];
|
|
192
|
+
const treeItem = await secondItem.shadow$('dx-tree-item');
|
|
193
|
+
const treeTile = await treeItem.shadow$('a > dx-tree-tile');
|
|
194
|
+
const arrowIcon = await treeTile.shadow$(
|
|
195
|
+
'a > div[role="heading"] > div.tile-forward-arrow',
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
expect(await arrowIcon.isExisting()).toBeTruthy();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('Navigation and content verification', () => {
|
|
203
|
+
it('should display markdown content when first reference is clicked', async () => {
|
|
204
|
+
const sideBarContent = await refPage.getSidebarItems();
|
|
205
|
+
const firstItem = sideBarContent[0];
|
|
206
|
+
const treeItem = await firstItem.shadow$('dx-tree-item');
|
|
207
|
+
await treeItem.click();
|
|
208
|
+
|
|
209
|
+
const contentLayout = await $('>>>doc-content-layout');
|
|
210
|
+
await contentLayout.waitForDisplayed();
|
|
211
|
+
|
|
212
|
+
expect(await contentLayout.isDisplayed()).toBeTruthy();
|
|
213
|
+
|
|
214
|
+
const heading = await $('>>>h1');
|
|
215
|
+
const headingText = await heading.getText();
|
|
216
|
+
|
|
217
|
+
expect(headingText).toEqual('Metamind API references');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('should display Redoc UI when OAS reference is clicked', async () => {
|
|
221
|
+
await browser.url('/docs/service/multi-oas-redoc/references');
|
|
222
|
+
await refPage.waitForMarkdownBasedReferencePageLoad();
|
|
223
|
+
|
|
224
|
+
const sideBarContent = await refPage.getSidebarItems();
|
|
225
|
+
const secondItem = sideBarContent[1];
|
|
226
|
+
const treeItem = await secondItem.shadow$('dx-tree-item');
|
|
227
|
+
await treeItem.click();
|
|
228
|
+
|
|
229
|
+
const redocContainer = await $('doc-redoc-reference > .redoc-container');
|
|
230
|
+
await redocContainer.waitForDisplayed({ timeout: 30000 });
|
|
231
|
+
|
|
232
|
+
expect(await redocContainer.isDisplayed()).toBeTruthy();
|
|
233
|
+
|
|
234
|
+
page = new RedocApisPage(
|
|
235
|
+
'docs/service/multi-oas-redoc/references/redoc-orders-multiple',
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
it('should have the correct api info title', async () => {
|
|
240
|
+
const apiTitle = await page.getApiTitle();
|
|
241
|
+
const titleText = await apiTitle.getText();
|
|
242
|
+
|
|
243
|
+
expect(titleText).toMatch('Einstein Vision and Einstein Language');
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it('should display current reference title and "All References" with back arrow in LNB', async () => {
|
|
247
|
+
const projectHeaderContainer = await page.getProjectHeader();
|
|
248
|
+
|
|
249
|
+
const backButton = await projectHeaderContainer.$('a.redoc-project-back');
|
|
250
|
+
const allReference = await backButton.$('span.redoc-project-title');
|
|
251
|
+
const specTitle = await projectHeaderContainer.$('h2.redoc-spec-title');
|
|
252
|
+
|
|
253
|
+
expect(await allReference.getText()).toEqual('All Reference');
|
|
254
|
+
expect(await backButton.isExisting()).toBeTruthy();
|
|
255
|
+
expect(await specTitle.getText()).toEqual('Orders API');
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe('Navigation back to all references', () => {
|
|
260
|
+
before(async () => {
|
|
261
|
+
page = new RedocApisPage(
|
|
262
|
+
'docs/service/multi-oas-redoc/references/redoc-orders-multiple',
|
|
263
|
+
);
|
|
264
|
+
page.open();
|
|
265
|
+
await page.waitPageLoad();
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it('should navigate back to main URL when back arrow is clicked', async () => {
|
|
269
|
+
const projectHeaderContainer = await page.getProjectHeader();
|
|
270
|
+
const backButton = await projectHeaderContainer.$('a.redoc-project-back');
|
|
271
|
+
|
|
272
|
+
await backButton.click();
|
|
273
|
+
|
|
274
|
+
const contentLayout = await $('>>>doc-content-layout');
|
|
275
|
+
await contentLayout.waitForDisplayed();
|
|
276
|
+
|
|
277
|
+
const currentUrl = await browser.getUrl();
|
|
278
|
+
|
|
279
|
+
expect(currentUrl).toContain('/docs/service/multi-oas-redoc/references');
|
|
280
|
+
expect(currentUrl).not.toContain('redoc-orders-multiple');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('should display all references in LNB after navigating back', async () => {
|
|
284
|
+
refPage = new ReferencePage('/docs/service/multi-oas-redoc/references');
|
|
285
|
+
const treeItems = await refPage.getSidebarItems();
|
|
286
|
+
|
|
287
|
+
expect(treeItems.length).toEqual(3);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('should navigate to third reference when clicked', async () => {
|
|
291
|
+
const sideBarContent = await refPage.getSidebarItems();
|
|
292
|
+
const thirdItem = sideBarContent[2];
|
|
293
|
+
const treeItem = await thirdItem.shadow$('dx-tree-item');
|
|
294
|
+
await treeItem.click();
|
|
295
|
+
|
|
296
|
+
const redocContainer = await $('doc-redoc-reference > .redoc-container');
|
|
297
|
+
await redocContainer.waitForDisplayed({ timeout: 30000 });
|
|
298
|
+
|
|
299
|
+
expect(await redocContainer.isDisplayed()).toBeTruthy();
|
|
300
|
+
expect(await browser.getUrl()).toContain('redoc-quip-admin-api');
|
|
301
|
+
|
|
302
|
+
page = new RedocApisPage(
|
|
303
|
+
'docs/service/multi-oas-redoc/references/redoc-quip-admin-api',
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
const apiTitle = await page.getApiTitle();
|
|
307
|
+
const titleText = await apiTitle.getText();
|
|
308
|
+
|
|
309
|
+
expect(titleText).toMatch('Quip Admin API');
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
});
|
|
170
313
|
});
|
|
@@ -9,6 +9,7 @@ describe('API Pages', () => {
|
|
|
9
9
|
beforeEach(async () => {
|
|
10
10
|
referencePage = new ReferencePage('/docs/commerce/test-cc-orders-api/references');
|
|
11
11
|
referencePage.open();
|
|
12
|
+
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
12
13
|
});
|
|
13
14
|
|
|
14
15
|
layoutTest(referencePage, 'doc-header');
|
|
@@ -85,6 +86,7 @@ describe('Reference Versioning', () => {
|
|
|
85
86
|
beforeEach(async () => {
|
|
86
87
|
referencePage = new ReferencePage('/docs/c-cart-apis/references/ref1?meta=Summary');
|
|
87
88
|
referencePage.open();
|
|
89
|
+
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
88
90
|
});
|
|
89
91
|
|
|
90
92
|
it('should check for the presence of version picker dropdown', async () => {
|
|
@@ -133,7 +135,7 @@ describe('Reference Versioning', () => {
|
|
|
133
135
|
|
|
134
136
|
await versionOptions[1].waitForClickable();
|
|
135
137
|
await versionOptions[1].click();
|
|
136
|
-
await
|
|
138
|
+
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
137
139
|
|
|
138
140
|
const apiTitle = await (await $('>>>div.api-title span')).getText();
|
|
139
141
|
const apiVersion = await (await $('>>>p.version span')).getText();
|
|
@@ -179,8 +181,10 @@ describe('Reference Versioning', () => {
|
|
|
179
181
|
|
|
180
182
|
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
181
183
|
await referencePage.selectVersion();
|
|
184
|
+
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
182
185
|
|
|
183
186
|
const container = await $('>>>div.title-area div');
|
|
187
|
+
await container.waitForDisplayed();
|
|
184
188
|
const apiTitle = await container.getText();
|
|
185
189
|
|
|
186
190
|
expect(apiTitle).toEqual('createBasket');
|
|
@@ -274,6 +278,7 @@ describe('Spec-Based Flexible References', () => {
|
|
|
274
278
|
await referencePage.waitForSpecBasedReferencePageLoad();
|
|
275
279
|
|
|
276
280
|
const container = await $('>>>div.title-area div');
|
|
281
|
+
await container.waitForDisplayed();
|
|
277
282
|
const apiTitle = await container.getText();
|
|
278
283
|
|
|
279
284
|
expect(apiTitle).toEqual('getBasket');
|
|
@@ -24,8 +24,11 @@ describe('Video Plugin Scenarios ', () => {
|
|
|
24
24
|
expect(await videoTitle?.getText()).toBe('Video from YouTube');
|
|
25
25
|
const videoContainer = await videoRootElement?.$('.video-plugin-container');
|
|
26
26
|
const iframeElement = await videoContainer?.$('iframe');
|
|
27
|
+
// The video plugin normalizes the YouTube host to www.youtube.com to
|
|
28
|
+
// avoid a cross-origin redirect that would drop the iframe's fullscreen
|
|
29
|
+
// grant (W-23222416). The authored src is `https://youtube.com/...`.
|
|
27
30
|
expect(await iframeElement?.getAttribute('src')).toBe(
|
|
28
|
-
'https://youtube.com/embed/di6iwHhrH6s',
|
|
31
|
+
'https://www.youtube.com/embed/di6iwHhrH6s',
|
|
29
32
|
);
|
|
30
33
|
});
|
|
31
34
|
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebdriverIO configuration for E2E tests on Static Portal Pages (SSG) on DSC
|
|
3
|
+
*
|
|
4
|
+
* Prerequisites:
|
|
5
|
+
* 1. Build static pages: yarn build:static:portal
|
|
6
|
+
* 2. Start static server: yarn start:static:portal (runs on port 3000)
|
|
7
|
+
* 3. Run tests: yarn test:e2e:static:portal
|
|
8
|
+
*/
|
|
9
|
+
const BASE_CONFIG = require('./common-wdio.conf');
|
|
10
|
+
|
|
11
|
+
exports.config = {
|
|
12
|
+
...BASE_CONFIG.config,
|
|
13
|
+
// Static pages are served on port 3000 by default; override via E2E_BASE_URL env var
|
|
14
|
+
baseUrl: process.env.E2E_BASE_URL || 'http://localhost:3000',
|
|
15
|
+
|
|
16
|
+
// Reuse the same portal specs - static pages have the same URL structure
|
|
17
|
+
specs: ['./src/portal/specs/**/*.test.ts', './src/shared/specs/*.test.ts'],
|
|
18
|
+
|
|
19
|
+
// Exclude tests that require dynamic server features or pages not in static build
|
|
20
|
+
exclude: [
|
|
21
|
+
'./src/portal/specs/docs.api.test.ts',
|
|
22
|
+
'./src/portal/specs/docs.test.ts',
|
|
23
|
+
'./src/shared/specs/banner.test.ts',
|
|
24
|
+
],
|
|
25
|
+
|
|
26
|
+
// Output directory for static test results
|
|
27
|
+
outputDir: './_results_/static-portal',
|
|
28
|
+
|
|
29
|
+
// Override reporters to use separate output directories
|
|
30
|
+
reporters: [
|
|
31
|
+
'spec',
|
|
32
|
+
[
|
|
33
|
+
require('wdio-video-reporter'),
|
|
34
|
+
{
|
|
35
|
+
saveAllVideos: false,
|
|
36
|
+
videoSlowdownMultiplier: 3,
|
|
37
|
+
outputDir: './_results_/static-portal/videos',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
[
|
|
41
|
+
'allure',
|
|
42
|
+
{
|
|
43
|
+
outputDir: './_results_/static-portal/allure-raw',
|
|
44
|
+
disableWebdriverStepsReporting: true,
|
|
45
|
+
disableWebdriverScreenshotsReporting: false,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
],
|
|
49
|
+
};
|
|
@@ -18,19 +18,14 @@ exports.config = {
|
|
|
18
18
|
|
|
19
19
|
// Exclude tests that require dynamic server features or pages not in static build
|
|
20
20
|
exclude: [
|
|
21
|
+
// Advanced liquid tests require previewFuture, variables — not in static build
|
|
22
|
+
'./src/shared/specs/liquid-advanced.test.ts',
|
|
21
23
|
// /docs/apis landing page doesn't exist in static builds
|
|
22
24
|
'./src/portal/specs/docs.api.test.ts',
|
|
23
25
|
// /docs landing page doesn't exist in static builds
|
|
24
26
|
'./src/portal/specs/docs.test.ts',
|
|
25
27
|
],
|
|
26
28
|
|
|
27
|
-
// Skip footer tests - footer is not available in static builds
|
|
28
|
-
mochaOpts: {
|
|
29
|
-
...BASE_CONFIG.config.mochaOpts,
|
|
30
|
-
grep: 'should display footer',
|
|
31
|
-
invert: true,
|
|
32
|
-
},
|
|
33
|
-
|
|
34
29
|
// Output directory for static test results
|
|
35
30
|
outputDir: './_results_/static-portal',
|
|
36
31
|
|
package/wdio.conf.js
CHANGED