@salesforcedevs/sfdocs-e2e 1.0.12-e2e-topic-version-5 → 1.0.12-e2e-topic-version-7

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.
@@ -89,10 +89,14 @@ const chrome = resolvedChromeDriverVersion ? { version: resolvedChromeDriverVers
89
89
  const drivers = {
90
90
  // ChromeDriver 115+ is distributed via Chrome for Testing:
91
91
  // https://googlechromelabs.github.io/chrome-for-testing/
92
- chrome,
93
- firefox: { version: '0.35.0' }, // https://github.com/mozilla/geckodriver/releases - 0.30.0+ supports ARM64 Mac
92
+ chrome
94
93
  };
95
94
 
95
+ // selenium-standalone's own default (4.9.0) doesn't support the `-I` driver flag it
96
+ // unconditionally passes on Selenium 4.x, so the server exits immediately on start.
97
+ // Pinning a version that does support it (4.18.1) avoids that crash.
98
+ const seleniumServerVersion = process.env.SELENIUM_VERSION || '4.18.1';
99
+
96
100
  exports.config = {
97
101
  //
98
102
  // ====================
@@ -188,8 +192,8 @@ exports.config = {
188
192
  [
189
193
  'selenium-standalone',
190
194
  {
191
- installArgs: { drivers }, // drivers to install
192
- args: { drivers }, // drivers to use
195
+ installArgs: { version: seleniumServerVersion, drivers }, // drivers to install
196
+ args: { version: seleniumServerVersion, drivers }, // drivers to use
193
197
  },
194
198
  ],
195
199
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforcedevs/sfdocs-e2e",
3
- "version": "1.0.12-e2e-topic-version-5",
3
+ "version": "1.0.12-e2e-topic-version-7",
4
4
  "description": "E2E test suite for SFDocs static portal pages (SSG)",
5
5
  "license": "ISC",
6
6
  "bin": {
@@ -149,17 +149,9 @@ describe('Component Specification', () => {
149
149
  'div.container div.sidebar-content dx-tree',
150
150
  );
151
151
 
152
- const getItemText = async (item: WebdriverIO.Element) => {
153
- const link = await item.shadow$('a');
154
- const tiles = await link.$$('dx-tree-tile');
155
- const tileLink = await tiles[0].shadow$('a.tile.sidebar-item');
156
- const label = await tileLink.$('span.tile-label');
157
- return (await label.getText()).trim();
158
- };
159
-
160
152
  const firstItem = (await sidebarTrees[0].shadow$$('dx-tree-item'))[0];
161
153
  const firstChildItem = (await firstItem.shadow$$('dx-tree-item'))[0];
162
- const firstChildText = await getItemText(firstChildItem);
154
+ const firstChildText = await page.getTreeItemLabel(firstChildItem);
163
155
 
164
156
  expect(firstChildText).toBe('Accordion');
165
157
  });
@@ -264,18 +256,10 @@ describe('Component Specification', () => {
264
256
  'div.container div.sidebar-content dx-tree',
265
257
  );
266
258
 
267
- const getItemText = async (item: WebdriverIO.Element) => {
268
- const link = await item.shadow$('a');
269
- const tiles = await link.$$('dx-tree-tile');
270
- const tileLink = await tiles[0].shadow$('a.tile.sidebar-item');
271
- const label = await tileLink.$('span.tile-label');
272
- return (await label.getText()).trim();
273
- };
274
-
275
259
  const auraItem = (await sidebarTrees[1].shadow$$('dx-tree-item'))[0];
276
260
  const lightningItem = (await auraItem.shadow$$('dx-tree-item'))[0];
277
261
  const componentsItem = (await lightningItem.shadow$$('dx-tree-item'))[0];
278
- const firstComponentText = await getItemText(
262
+ const firstComponentText = await page.getTreeItemLabel(
279
263
  (
280
264
  await componentsItem.shadow$$('dx-tree-item')
281
265
  )[0],
@@ -19,72 +19,23 @@ class DocsPage extends Page {
19
19
  return (await $('doc-unified-content-layout')).$('div.markdown-content h1');
20
20
  }
21
21
 
22
- private async getSidebar(): Promise<WebdriverIO.Element> {
23
- return (await $('>>>doc-content-layout')).shadow$('div > dx-sidebar-old');
24
- }
25
-
26
- async waitForSidebar(): Promise<void> {
27
- await (await this.getSidebar()).waitForDisplayed();
28
- }
29
-
30
- async getSidebarTrees(): Promise<WebdriverIO.ElementArray> {
31
- const sidebar = await this.getSidebar();
32
- return sidebar.shadow$$('div.container div.sidebar-content dx-tree');
33
- }
34
-
35
- private async getTreeTile(treeItem: WebdriverIO.Element): Promise<WebdriverIO.Element> {
36
- return this.getTreeItemTile(treeItem);
37
- }
38
-
39
- private async getTreeItemLabel(treeItem: WebdriverIO.Element): Promise<string> {
40
- const treeTile = await this.getTreeTile(treeItem);
41
- const label = await treeTile.shadow$('span.tile-label');
42
- return (await label.getText()).trim();
43
- }
44
-
45
- private async findTreeItemByLabel(
46
- treeItem: WebdriverIO.Element,
47
- label: string,
48
- ): Promise<WebdriverIO.Element | null> {
49
- if ((await this.getTreeItemLabel(treeItem)) === label) {
50
- return treeItem;
51
- }
52
-
53
- const children = await treeItem.shadow$$('dx-tree-item');
54
- for (const child of children) {
55
- const match = await this.findTreeItemByLabel(child, label);
56
- if (match) {
57
- return match;
58
- }
59
- }
60
- return null;
61
- }
62
-
63
22
  async getSidebarTile(label: string): Promise<WebdriverIO.Element> {
64
- const trees = await this.getSidebarTrees();
65
- for (const tree of trees) {
66
- const rootItem = await tree.shadow$('dx-tree-item');
67
- const match = await this.findTreeItemByLabel(rootItem, label);
68
- if (match) {
69
- return match;
70
- }
71
- }
72
- throw new Error(`No sidebar tile found with label "${label}"`);
23
+ return this.getSidebarTreeItemByLabel(label);
73
24
  }
74
25
 
75
26
  async getTileForwardArrow(label: string): Promise<WebdriverIO.Element> {
76
27
  const treeItem = await this.getSidebarTile(label);
77
- return (await this.getTreeTile(treeItem)).shadow$('.tile-forward-arrow');
28
+ return (await this.getTreeItemTile(treeItem)).shadow$('.tile-forward-arrow');
78
29
  }
79
30
 
80
31
  async getTileExternalLinkIcon(label: string): Promise<WebdriverIO.Element> {
81
32
  const treeItem = await this.getSidebarTile(label);
82
- return (await this.getTreeTile(treeItem)).shadow$('.tile-external-link-icon');
33
+ return (await this.getTreeItemTile(treeItem)).shadow$('.tile-external-link-icon');
83
34
  }
84
35
 
85
36
  async getTileAnchor(label: string): Promise<WebdriverIO.Element> {
86
37
  const treeItem = await this.getSidebarTile(label);
87
- return (await this.getTreeTile(treeItem)).shadow$('a');
38
+ return (await this.getTreeItemTile(treeItem)).shadow$('a');
88
39
  }
89
40
 
90
41
  async getRedocBackLink(): Promise<WebdriverIO.Element> {
@@ -118,8 +69,16 @@ class DocsPage extends Page {
118
69
  }
119
70
 
120
71
  async selectLanguage(displayText: string): Promise<void> {
72
+ const picker = await this.getLanguagePicker();
73
+ // A hidden mobile/desktop duplicate of the footer nav can overlap this button at the
74
+ // same screen coordinates, so a native pointer click risks getting intercepted by it.
75
+ await browser.execute((el: { click: () => void }) => el.click(), picker);
76
+
121
77
  const options = await $$('>>>dx-dropdown-option');
122
- for (const option of options) {
78
+ const isDisplayed = await Promise.all(options.map((option) => option.isDisplayed()));
79
+ const visibleOptions = options.filter((_, index) => isDisplayed[index]);
80
+
81
+ for (const option of visibleOptions) {
123
82
  const link = await option.shadow$('a.option');
124
83
  if ((await link.getText()).trim() === displayText) {
125
84
  await browser.execute((el: { click: () => void }) => el.click(), link);
@@ -88,19 +88,63 @@ export default class Page {
88
88
  return treeItem.shadow$('dx-tree-tile');
89
89
  }
90
90
 
91
+ async getSidebar(): Promise<WebdriverIO.Element> {
92
+ return (await $('>>>doc-content-layout')).shadow$('div > dx-sidebar-old');
93
+ }
94
+
95
+ async waitForSidebar(): Promise<void> {
96
+ await (await this.getSidebar()).waitForDisplayed();
97
+ }
98
+
99
+ async getSidebarTrees(): Promise<WebdriverIO.ElementArray> {
100
+ const sidebar = await this.getSidebar();
101
+ return sidebar.shadow$$('div.container div.sidebar-content dx-tree');
102
+ }
103
+
104
+ async getTreeItemLabel(treeItem: WebdriverIO.Element): Promise<string> {
105
+ const tile = await this.getTreeItemTile(treeItem);
106
+ const label = await tile.shadow$('span.tile-label');
107
+ return (await label.getText()).trim();
108
+ }
109
+
110
+ async findTreeItemByLabel(
111
+ treeItem: WebdriverIO.Element,
112
+ label: string,
113
+ ): Promise<WebdriverIO.Element | null> {
114
+ if ((await this.getTreeItemLabel(treeItem)) === label) {
115
+ return treeItem;
116
+ }
117
+
118
+ const children = await treeItem.shadow$$('dx-tree-item');
119
+ for (const child of children) {
120
+ const match = await this.findTreeItemByLabel(child, label);
121
+ if (match) {
122
+ return match;
123
+ }
124
+ }
125
+ return null;
126
+ }
127
+
128
+ async getSidebarTreeItemByLabel(label: string): Promise<WebdriverIO.Element> {
129
+ const trees = await this.getSidebarTrees();
130
+ for (const tree of trees) {
131
+ const rootItem = await tree.shadow$('dx-tree-item');
132
+ const match = await this.findTreeItemByLabel(rootItem, label);
133
+ if (match) {
134
+ return match;
135
+ }
136
+ }
137
+ throw new Error(`No sidebar tree item found with label "${label}"`);
138
+ }
139
+
91
140
  /**
92
141
  * Options render in a single shared overlay, one per picker on the page, hidden until their
93
142
  * own dropdown opens — filtering to visible ones scopes this to whichever just opened.
94
143
  */
95
144
  async getVersionOptions(): Promise<WebdriverIO.Element[]> {
96
145
  const allOptions = await $$('>>>doc-version-picker dx-dropdown-option');
97
- const visible: WebdriverIO.Element[] = [];
98
- for (const option of allOptions) {
99
- if (await option.isDisplayed()) {
100
- visible.push(option);
101
- }
102
- }
103
- return visible;
146
+ const isDisplayed = await Promise.all(allOptions.map((option) => option.isDisplayed()));
147
+ return allOptions.filter((_, index) => isDisplayed[index]);
104
148
  }
105
149
 
106
150
  async waitForSpinnerToDisappear(element: WebdriverIO.Element): Promise<void> {
@@ -28,7 +28,6 @@ export class ReferencePage extends Page {
28
28
  const versionPicker = await this.getVersionPickerBtn();
29
29
  await versionPicker.click();
30
30
  const versionOptions = await $$('>>>doc-version-picker dx-dropdown-option');
31
- await versionOptions[1].waitForClickable();
32
31
  await versionOptions[1].click();
33
32
  }
34
33
 
@@ -24,53 +24,8 @@ export default class TopicVersionPage extends Page {
24
24
  });
25
25
  }
26
26
 
27
- // --- Sidebar tree traversal (mirrors docs.page.ts's private helpers, exposed here so
28
- // individual rows and their pickers can be located directly) ---
29
-
30
- async getSidebar(): Promise<WebdriverIO.Element> {
31
- return (await $('>>>doc-content-layout')).shadow$('div > dx-sidebar-old');
32
- }
33
-
34
- async waitForSidebar(): Promise<void> {
35
- await (await this.getSidebar()).waitForDisplayed();
36
- }
37
-
38
- private async getTreeItemLabel(treeItem: WebdriverIO.Element): Promise<string> {
39
- const tile = await this.getTreeItemTile(treeItem);
40
- const label = await tile.shadow$('span.tile-label');
41
- return (await label.getText()).trim();
42
- }
43
-
44
- private async findTreeItemByLabel(
45
- treeItem: WebdriverIO.Element,
46
- label: string,
47
- ): Promise<WebdriverIO.Element | null> {
48
- if ((await this.getTreeItemLabel(treeItem)) === label) {
49
- return treeItem;
50
- }
51
-
52
- const children = await treeItem.shadow$$('dx-tree-item');
53
- for (const child of children) {
54
- const match = await this.findTreeItemByLabel(child, label);
55
- if (match) {
56
- return match;
57
- }
58
- }
59
- return null;
60
- }
61
-
62
- /** Locates a sidebar tree row (dx-tree-item) by its visible label. */
63
27
  async getSidebarTreeItem(label: string): Promise<WebdriverIO.Element> {
64
- const sidebar = await this.getSidebar();
65
- const trees = await sidebar.shadow$$('div.container div.sidebar-content dx-tree');
66
- for (const tree of trees) {
67
- const rootItem = await tree.shadow$('dx-tree-item');
68
- const match = await this.findTreeItemByLabel(rootItem, label);
69
- if (match) {
70
- return match;
71
- }
72
- }
73
- throw new Error(`No sidebar tree item found with label "${label}"`);
28
+ return this.getSidebarTreeItemByLabel(label);
74
29
  }
75
30
 
76
31
  /** The sidebar row's own doc-version-picker (small variant), or null if it has none. */
@@ -113,11 +68,10 @@ export default class TopicVersionPage extends Page {
113
68
  }
114
69
 
115
70
  /**
116
- * The markdown-topic analog of `getRedocVersionBanner`. TODO: unconfirmed whether markdown
117
- * topics render this banner at all yet — only the Redoc spec-page banner is confirmed shipped.
71
+ * The markdown-topic analog of `getRedocVersionBanner`.
118
72
  */
119
73
  async getMarkdownVersionBanner(): Promise<WebdriverIO.Element | null> {
120
- const banner = await $('>>>doc-content-layout .doc-phase-wrapper doc-phase');
74
+ const banner = await $('>>>doc-content-layout doc-phase[slot="version-banner"]');
121
75
  return (await banner.isExisting()) ? banner : null;
122
76
  }
123
77
 
@@ -171,7 +125,6 @@ export default class TopicVersionPage extends Page {
171
125
  return (await label.getText()).trim();
172
126
  }
173
127
 
174
- /** Opens the picker and clicks the option whose label matches exactly. */
175
128
  async selectVersionByLabel(picker: WebdriverIO.Element, label: string): Promise<void> {
176
129
  await this.openPicker(picker);
177
130
  const options = await this.getVersionOptions();
@@ -187,9 +187,11 @@ describe('Redoc API Reference page', () => {
187
187
 
188
188
  it('should show arrow button after OAS reference titles', async () => {
189
189
  const sideBarContent = await refPage.getSidebarItems();
190
- const treeItem = await sideBarContent[1].shadow$('dx-tree-item');
191
- const tile = await refPage.getTreeItemTile(treeItem);
192
- const arrowIcon = await tile.shadow$(
190
+
191
+ const secondItem = sideBarContent[1];
192
+ const treeItem = await secondItem.shadow$('dx-tree-item');
193
+ const treeTile = await refPage.getTreeItemTile(treeItem);
194
+ const arrowIcon = await treeTile.shadow$(
193
195
  'a > div[role="heading"] > div.tile-forward-arrow',
194
196
  );
195
197
 
@@ -106,11 +106,9 @@ describe('Reference Versioning', () => {
106
106
  const versionBtn = await $('>>>.version-picker-button');
107
107
  await versionBtn.waitForDisplayed();
108
108
  await versionBtn.click();
109
- const versionOptions = await $$('>>>doc-version-picker dx-dropdown-option');
109
+ const versionOptions = await referencePage.getVersionOptions();
110
110
 
111
111
  expect(versionOptions.length).toEqual(2);
112
- await versionOptions[0].waitForClickable();
113
- await versionOptions[1].waitForClickable();
114
112
  expect(await (await versionOptions[0].shadow$('div>div')).getText()).toEqual('0.1.3');
115
113
  expect(await (await versionOptions[1].shadow$('div>div')).getText()).toEqual('0.1.2');
116
114
  });
@@ -120,34 +118,26 @@ describe('Reference Versioning', () => {
120
118
  const searchBox = await dxInput.shadow$('input');
121
119
 
122
120
  await searchBox.click();
123
- await browser.keys('/cart-coupons');
121
+ await browser.keys('coupon');
122
+ await browser.pause(1000);
124
123
 
125
124
  const dxTreeItems = await $$('>>>dx-tree-item');
126
125
 
127
- expect(dxTreeItems.length > 2).toBeTruthy();
128
-
129
- await (await dxTreeItems[2]).click();
126
+ await dxTreeItems[2].click();
130
127
 
131
128
  const versionBtn = await $('>>>.version-picker-button');
132
129
 
133
130
  await versionBtn.waitForDisplayed();
134
131
  await versionBtn.click();
135
132
 
136
- const versionOptions = await $$('>>>doc-version-picker dx-dropdown-option');
133
+ const versionOptions = await referencePage.getVersionOptions();
137
134
 
138
135
  await versionOptions[1].waitForClickable();
139
136
  await versionOptions[1].click();
140
137
  await referencePage.waitForSpecBasedReferencePageLoad();
141
138
 
142
- // The outer container can display before Redoc finishes populating its content, so wait
143
- // for each element directly rather than reading them immediately.
144
- const apiTitleElement = await $('>>>div.api-title span');
145
- await apiTitleElement.waitForDisplayed();
146
- const apiVersionElement = await $('>>>p.version span');
147
- await apiVersionElement.waitForDisplayed();
148
-
149
- const apiTitle = await apiTitleElement.getText();
150
- const apiVersion = await apiVersionElement.getText();
139
+ const apiTitle = await (await $('>>>div.api-title span')).getText();
140
+ const apiVersion = await (await $('>>>p.version span')).getText();
151
141
 
152
142
  expect(apiTitle).toEqual('Salesforce Connect API');
153
143
  expect(apiVersion).toEqual('53.0');
@@ -159,9 +149,7 @@ describe('Reference Versioning', () => {
159
149
  await versionPicker.waitForDisplayed();
160
150
  await versionPicker.click();
161
151
 
162
- const versionOptions = await $$('>>>doc-version-picker dx-dropdown-option');
163
-
164
- await versionOptions[1].waitForClickable();
152
+ const versionOptions = await referencePage.getVersionOptions();
165
153
  const selectedVersionText = await (await versionOptions[1].shadow$('div>div')).getText();
166
154
 
167
155
  await versionOptions[1].click();
@@ -3,7 +3,7 @@ import TopicVersionPage from '../pageobjects/topic-version.page';
3
3
 
4
4
  // Fixtures live in the `docs-content-type-example` project, kept in sync between this monorepo's
5
5
  // local `packages/example-repository` and the remote `salesforcedocs/example-repository`'s
6
- // `mh/topic-level-version` branch.
6
+ // `nd/e2e-topic-version` branch (pinned in example-portal/docsportal.config.js).
7
7
  const BASE = '/docs/docs-content-type-example';
8
8
 
9
9
  let page: TopicVersionPage;
@@ -39,10 +39,7 @@ describe('Topic-level versioning > versioned markdown topic', () => {
39
39
  await page.waitForMarkdownTopicLoad();
40
40
 
41
41
  expect(await (await $('>>>h1')).getText()).toEqual('OAuth 1.0');
42
- await browser.waitUntil(
43
- async () => (await browser.getUrl()).includes(`${BASE}/v1/oauth.html`),
44
- { timeoutMsg: 'expected URL to contain /v1/oauth.html' },
45
- );
42
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/oauth.html`);
46
43
  });
47
44
 
48
45
  it('should return to the canonical URL when the latest version is reselected', async () => {
@@ -60,9 +57,7 @@ describe('Topic-level versioning > versioned markdown topic', () => {
60
57
  expect(await (await $('>>>h1')).getText()).toEqual('OAuth 2.0');
61
58
  });
62
59
 
63
- // TODO: unconfirmed whether markdown topics render this banner at all yet (only Redoc spec
64
- // pages are confirmed to). Enable once verified.
65
- it.skip('should show the "Newer Version Available" banner when the version is not latest', async () => {
60
+ it('should show the "Newer Version Available" banner when the version is not latest', async () => {
66
61
  page = new TopicVersionPage(`${BASE}/v1/oauth.html`);
67
62
  page.open();
68
63
  await page.waitForMarkdownTopicLoad();
@@ -96,10 +91,7 @@ describe('Topic-level versioning > versioned parent with versioned child subtree
96
91
  await page.selectVersionByLabel(picker!, "SU'26");
97
92
  await page.waitForMarkdownTopicLoad();
98
93
 
99
- await browser.waitUntil(
100
- async () => (await browser.getUrl()).includes(`${BASE}/v1/android.html`),
101
- { timeoutMsg: 'expected URL to contain /v1/android.html' },
102
- );
94
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/android.html`);
103
95
  expect(await (await $('>>>h1')).getText()).toEqual('Android SDK v1');
104
96
 
105
97
  // Sibling child (iOS SDK) should also have moved to the v1 URL, not just this one.
@@ -117,7 +109,7 @@ describe('Topic-level versioning > versioned parent with versioned child subtree
117
109
  page.open();
118
110
  await page.waitForMarkdownTopicLoad();
119
111
 
120
- page = new TopicVersionPage(`${BASE}/android.html`);
112
+ page = new TopicVersionPage(`${BASE}/v2/android.html`);
121
113
  page.open();
122
114
  await page.waitForMarkdownTopicLoad();
123
115
 
@@ -153,10 +145,7 @@ describe('Topic-level versioning > versioned parent with own content, subtopics
153
145
  await page.waitForMarkdownTopicLoad();
154
146
 
155
147
  expect(await (await $('>>>h1')).getText()).toEqual('Errors and Rate Limits (v1)');
156
- await browser.waitUntil(
157
- async () => (await browser.getUrl()).includes(`${BASE}/v1/errors-and-rate-limits.html`),
158
- { timeoutMsg: 'expected URL to contain /v1/errors-and-rate-limits.html' },
159
- );
148
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/errors-and-rate-limits.html`);
160
149
  });
161
150
 
162
151
  it('should switch the markdown subtopics when the version changes', async () => {
@@ -169,10 +158,7 @@ describe('Topic-level versioning > versioned parent with own content, subtopics
169
158
  await page.waitForMarkdownTopicLoad();
170
159
 
171
160
  expect(await (await $('>>>h1')).getText()).toEqual('Common Error Codes (v1)');
172
- await browser.waitUntil(
173
- async () => (await browser.getUrl()).includes(`${BASE}/v1/extra-child-a.html`),
174
- { timeoutMsg: 'expected URL to contain /v1/extra-child-a.html' },
175
- );
161
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/extra-child-a.html`);
176
162
  });
177
163
 
178
164
  it('should switch the spec (Redoc) subtopic to the matching version when the version changes', async () => {
@@ -185,10 +171,7 @@ describe('Topic-level versioning > versioned parent with own content, subtopics
185
171
  await child.click();
186
172
  await page.waitForRedocTopicLoad();
187
173
 
188
- await browser.waitUntil(
189
- async () => (await browser.getUrl()).includes(`${BASE}/v1/new-sample-api`),
190
- { timeoutMsg: 'expected URL to contain /v1/new-sample-api' },
191
- );
174
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/new-sample-api`);
192
175
  // v1's spec lacks the `GET /errors/{code}` operation that only v2 has — its absence
193
176
  // confirms the v1 spec asset loaded, since both versions share the same spec title.
194
177
  const getErrorCodeOperation = await $('a[href*="operation/getErrorCode"]');
@@ -235,10 +218,7 @@ describe('Topic-level versioning > standalone Redoc reference', () => {
235
218
  await page.selectVersionByLabel(picker!, "SP'26");
236
219
  await page.waitForRedocTopicLoad();
237
220
 
238
- await browser.waitUntil(
239
- async () => (await browser.getUrl()).includes(`${BASE}/v1/widgets-api-reference`),
240
- { timeoutMsg: 'expected URL to contain /v1/widgets-api-reference' },
241
- );
221
+ expect(await browser.getUrl()).toContain(`${BASE}/v1/widgets-api-reference`);
242
222
  const apiInfo = await $('>>>div.api-info');
243
223
  expect(await apiInfo.getText()).toContain('1.0.0');
244
224
  });