Skip to content

Commit 7f6a7e0

Browse files
authored
test: add E2E for multi workspace scenario (#51)
## Proposed changes Add E2E scenario for the multi workspace use case. ## Types of changes [//]: # 'What types of changes does your code introduce to WebdriverIO?' [//]: # '_Put an `x` in the boxes that apply_' - [ ] Polish (an improvement for an existing feature) - [ ] Bugfix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update (improvements to the project's docs) - [X] Internal updates (everything related to internal scripts, governance documentation and CI files) ## Checklist [//]: # "_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._" - [X] I have read the [CONTRIBUTING](https://github.com/webdriverio/vscode-webdriverio/blob/main/CONTRIBUTION.md) doc - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] I have added the necessary documentation (if appropriate) - [ ] I have added proper type definitions for new commands (if appropriate) ## Further comments [//]: # 'If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...' ### Reviewers: @webdriverio/project-committers
1 parent f4067f7 commit 7f6a7e0

14 files changed

Lines changed: 248 additions & 27 deletions

e2e/helpers/constants.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as cucumber from './cucumber.ts'
12
import { STATUS } from './index.ts'
23

34
function createExpectedNotRun(targetFramework: 'mocha' | 'jasmine') {
@@ -90,3 +91,59 @@ export function createExpected(targetFramework: 'mocha' | 'jasmine') {
9091
runPartially: [createExpectedRunPartially(targetFramework)],
9192
}
9293
}
94+
95+
export function createWorkspaceExpected() {
96+
return {
97+
notRun: [
98+
{
99+
text: 'cucumber',
100+
status: STATUS.NOT_YET_RUN,
101+
children: [cucumber.createExpectedNotRun()],
102+
},
103+
{
104+
text: 'jasmine',
105+
status: STATUS.NOT_YET_RUN,
106+
children: [createExpectedNotRun('jasmine')],
107+
},
108+
{
109+
text: 'mocha',
110+
status: STATUS.NOT_YET_RUN,
111+
children: [createExpectedNotRun('mocha')],
112+
},
113+
],
114+
runAll: [
115+
{
116+
text: 'cucumber',
117+
status: STATUS.PASSED,
118+
children: [cucumber.createExpectedRunAll()],
119+
},
120+
{
121+
text: 'jasmine',
122+
status: STATUS.FAILED,
123+
children: [createExpectedRunAll('jasmine')],
124+
},
125+
{
126+
text: 'mocha',
127+
status: STATUS.FAILED,
128+
children: [createExpectedRunAll('mocha')],
129+
},
130+
],
131+
runPartially: [
132+
{
133+
text: 'cucumber',
134+
status: STATUS.NOT_YET_RUN,
135+
children: [cucumber.createExpectedNotRun()],
136+
},
137+
{
138+
text: 'jasmine',
139+
status: STATUS.PASSED,
140+
children: [createExpectedRunPartially('jasmine')],
141+
},
142+
{
143+
text: 'mocha',
144+
status: STATUS.NOT_YET_RUN,
145+
children: [createExpectedNotRun('mocha')],
146+
},
147+
],
148+
}
149+
}

e2e/helpers/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,12 @@ export async function clickTitleActionButton(titlePart: ViewTitlePart, label: st
115115
}
116116
}
117117
}
118+
119+
export async function collapseAllTests(testingSection: DefaultTreeSection) {
120+
const items = (await testingSection.getVisibleItems()).reverse()
121+
for (const item of items) {
122+
if ((await item.isExpandable()) && (await item.isExpanded())) {
123+
await item.collapse()
124+
}
125+
}
126+
}

e2e/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"test:e2e:mocha": "cross-env VSCODE_WDIO_E2E_FRAMEWORK=mocha xvfb-maybe pnpm run wdio",
1515
"test:e2e:jasmine": "cross-env VSCODE_WDIO_E2E_FRAMEWORK=jasmine xvfb-maybe pnpm run wdio",
1616
"test:e2e:cucumber": "cross-env VSCODE_WDIO_E2E_FRAMEWORK=cucumber xvfb-maybe pnpm run wdio",
17+
"test:e2e:workspace": "cross-env VSCODE_WDIO_E2E_FRAMEWORK=workspace xvfb-maybe pnpm run wdio",
1718
"test:smoke": "run-s test:smoke:*",
1819
"test:smoke:update-config": "xvfb-maybe wdio run ./wdioSmoke.conf.ts",
1920
"wdio": "wdio run ./wdio.conf.ts"
@@ -25,6 +26,7 @@
2526
"@wdio/local-runner": "^9.13.0",
2627
"@wdio/mocha-framework": "^9.13.0",
2728
"@wdio/spec-reporter": "^9.13.0",
29+
"@wdio/types": "^9.15.0",
2830
"chai": "^5.2.0",
2931
"expect": "^29.7.0",
3032
"semver": "^7.7.2",

e2e/tests/basic.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
clearAllTestResults,
77
clickTitleActionButton,
88
clickTreeItemButton,
9+
collapseAllTests,
910
getTestingSection,
1011
openTestingView,
1112
waitForResolved,
@@ -30,12 +31,8 @@ describe(`VS Code Extension Testing with ${targetFramework}`, function () {
3031
sideBarView = workbench.getSideBar()
3132

3233
const testingSection = await getTestingSection(sideBarView.getContent())
33-
const items = (await testingSection.getVisibleItems()).reverse()
34-
for (const item of items) {
35-
if ((await item.isExpandable()) && (await item.isExpanded())) {
36-
await item.collapse()
37-
}
38-
}
34+
await collapseAllTests(testingSection)
35+
3936
await browser.waitUntil(async () => (await testingSection.getVisibleItems()).length === 1)
4037
})
4138

e2e/tests/basicCucumber.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
clearAllTestResults,
77
clickTitleActionButton,
88
clickTreeItemButton,
9+
collapseAllTests,
910
getTestingSection,
1011
openTestingView,
1112
waitForResolved,
@@ -30,12 +31,8 @@ describe(`VS Code Extension Testing with ${targetFramework}`, function () {
3031
sideBarView = workbench.getSideBar()
3132

3233
const testingSection = await getTestingSection(sideBarView.getContent())
33-
const items = (await testingSection.getVisibleItems()).reverse()
34-
for (const item of items) {
35-
if ((await item.isExpandable()) && (await item.isExpanded())) {
36-
await item.collapse()
37-
}
38-
}
34+
await collapseAllTests(testingSection)
35+
3936
await browser.waitUntil(async () => (await testingSection.getVisibleItems()).length === 1)
4037
})
4138

e2e/tests/basicWorkspace.spec.ts

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import { browser, expect } from '@wdio/globals'
2+
import { createWorkspaceExpected } from 'helpers/constants.ts'
3+
4+
import {
5+
STATUS,
6+
clearAllTestResults,
7+
collapseAllTests,
8+
clickTitleActionButton,
9+
clickTreeItemButton,
10+
getTestingSection,
11+
openTestingView,
12+
waitForResolved,
13+
waitForTestStatus,
14+
} from '../helpers/index.ts'
15+
import type { SideBarView, ViewControl, Workbench } from 'wdio-vscode-service'
16+
17+
const expected = createWorkspaceExpected()
18+
19+
describe('VS Code Extension Testing with Workspace', function () {
20+
this.retries(3)
21+
let workbench: Workbench
22+
let testingViewControl: ViewControl
23+
let sideBarView: SideBarView<any>
24+
25+
beforeEach(async function () {
26+
workbench = await browser.getWorkbench()
27+
testingViewControl = await openTestingView(workbench)
28+
sideBarView = workbench.getSideBar()
29+
30+
const testingSection = await getTestingSection(sideBarView.getContent())
31+
await collapseAllTests(testingSection)
32+
await browser.waitUntil(async () => (await testingSection.getVisibleItems()).length === 3)
33+
})
34+
35+
afterEach(async function () {
36+
await clearAllTestResults(workbench)
37+
})
38+
39+
it('should be displayed the testing screen at the sideBar', async function () {
40+
expect(await testingViewControl.getTitle()).toBe('Testing')
41+
expect(await sideBarView.getTitlePart().getTitle()).toBe('TESTING')
42+
})
43+
44+
it('should resolve defined tests correctly', async function () {
45+
const testingSection = await getTestingSection(sideBarView.getContent())
46+
const items = await testingSection.getVisibleItems()
47+
48+
await waitForResolved(browser, items[0])
49+
50+
expect(items.length).toBe(expected.notRun.length)
51+
52+
/**
53+
* Because of the small screen size of the CI environment,
54+
* the tree is expanded and asserted per workspace.
55+
*/
56+
for (let index = 0; index < expected.notRun.length; index++) {
57+
await expect([items[index]]).toMatchTreeStructure([expected.notRun[index]])
58+
59+
await collapseAllTests(testingSection)
60+
}
61+
})
62+
63+
it('should run at top Level', async function () {
64+
const testingSection = await getTestingSection(sideBarView.getContent())
65+
const items = await testingSection.getVisibleItems()
66+
67+
await waitForResolved(browser, items[0])
68+
69+
await clickTitleActionButton(sideBarView.getTitlePart(), 'Run Tests')
70+
71+
expect(items.length).toBe(expected.runAll.length)
72+
73+
await waitForTestStatus(browser, items[0], STATUS.PASSED)
74+
await waitForTestStatus(browser, items[1], STATUS.FAILED)
75+
await waitForTestStatus(browser, items[2], STATUS.FAILED)
76+
77+
/**
78+
* Because of the small screen size of the CI environment,
79+
* the tree is expanded and asserted per workspace.
80+
*/
81+
for (let index = 0; index < expected.runAll.length; index++) {
82+
await expect([items[index]]).toMatchTreeStructure([expected.runAll[index]])
83+
84+
await collapseAllTests(testingSection)
85+
}
86+
})
87+
88+
it('should run at not top Level', async function () {
89+
const testingSection = await getTestingSection(sideBarView.getContent())
90+
const items = await testingSection.getVisibleItems()
91+
92+
await waitForResolved(browser, items[0])
93+
await waitForResolved(browser, items[0])
94+
95+
const target = await items[1]
96+
.getChildren()
97+
.then((items) => items[0].getChildren())
98+
.then((items) => items[0].getChildren())
99+
.then((items) => items[0].getChildren())
100+
.then((items) => items[1])
101+
102+
await clickTreeItemButton(browser, target, 'Run Test')
103+
104+
expect(items.length).toBe(expected.runPartially.length)
105+
await waitForTestStatus(browser, items[1], STATUS.PASSED)
106+
107+
/**
108+
* Because of the small screen size of the CI environment,
109+
* the tree is expanded and asserted per workspace.
110+
*/
111+
for (let index = 0; index < expected.runPartially.length; index++) {
112+
await expect([items[index]]).toMatchTreeStructure([expected.runPartially[index]])
113+
114+
await collapseAllTests(testingSection)
115+
}
116+
})
117+
})

e2e/tests/updateConfig.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
STATUS,
99
clearAllTestResults,
1010
clickTreeItemButton,
11+
collapseAllTests,
1112
getTestingSection,
1213
openTestingView,
1314
waitForResolved,
@@ -32,12 +33,8 @@ describe('VS Code Extension Testing (Update config)', function () {
3233
sideBarView = workbench.getSideBar()
3334

3435
const testingSection = await getTestingSection(sideBarView.getContent())
35-
const items = (await testingSection.getVisibleItems()).reverse()
36-
for (const item of items) {
37-
if ((await item.isExpandable()) && (await item.isExpanded())) {
38-
await item.collapse()
39-
}
40-
}
36+
await collapseAllTests(testingSection)
37+
4138
await browser.waitUntil(async () => (await testingSection.getVisibleItems()).length === 1)
4239
})
4340

e2e/tests/updateSpec.spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
STATUS,
99
clearAllTestResults,
1010
clickTreeItemButton,
11+
collapseAllTests,
1112
getTestingSection,
1213
openTestingView,
1314
waitForResolved,
@@ -36,12 +37,8 @@ describe('VS Code Extension Testing (Update config)', function () {
3637
sideBarView = workbench.getSideBar()
3738

3839
const testingSection = await getTestingSection(sideBarView.getContent())
39-
const items = (await testingSection.getVisibleItems()).reverse()
40-
for (const item of items) {
41-
if ((await item.isExpandable()) && (await item.isExpanded())) {
42-
await item.collapse()
43-
}
44-
}
40+
await collapseAllTests(testingSection)
41+
4542
await browser.waitUntil(async () => (await testingSection.getVisibleItems()).length === 1)
4643
})
4744

e2e/wdio.conf.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import * as url from 'node:url'
44
import { minVersion } from 'semver'
55

66
import pkg from '../packages/vscode-webdriverio/package.json' with { type: 'json' }
7+
import type { Frameworks } from '@wdio/types'
8+
9+
type TestTargets = 'workspace' | 'mocha' | 'jasmine' | 'cucumber'
710

811
const __dirname = path.dirname(url.fileURLToPath(import.meta.url))
9-
const target = process.env.VSCODE_WDIO_E2E_FRAMEWORK || 'mocha'
12+
const target = (process.env.VSCODE_WDIO_E2E_FRAMEWORK || 'mocha') as TestTargets
1013

1114
const minimumVersion = minVersion(pkg.engines.vscode)?.version || 'stable'
1215

@@ -16,7 +19,19 @@ const version = isCompatibilityMode ? minimumVersion : 'stable'
1619
const outputDir = path.join(__dirname, 'logs', [isCompatibilityMode ? 'compatibility' : 'e2e', target].join('-'))
1720
process.env.VSCODE_WDIO_TRACE_LOG_PATH = outputDir
1821

19-
const specs = target === 'cucumber' ? ['./tests/basicCucumber.spec.ts'] : ['./tests/basic.spec.ts']
22+
function defineSpecs(target: TestTargets) {
23+
switch (target) {
24+
case 'cucumber':
25+
return ['./tests/basicCucumber.spec.ts']
26+
case 'workspace':
27+
return ['./tests/basicWorkspace.spec.ts']
28+
default:
29+
return ['./tests/basic.spec.ts']
30+
}
31+
}
32+
33+
const specs = defineSpecs(target)
34+
let screenshotCount = 0
2035

2136
export function createBaseConfig(workspacePath: string): WebdriverIO.Config {
2237
return {
@@ -55,10 +70,17 @@ export function createBaseConfig(workspacePath: string): WebdriverIO.Config {
5570
timeout: 6000000,
5671
require: ['assertions/index.ts'],
5772
},
73+
afterTest: async function (_test:unknown, _context:unknown, result: Frameworks.TestResult) {
74+
if (!result.passed) {
75+
await browser.saveScreenshot(path.join(outputDir, `screenshot-${screenshotCount++}.png`))
76+
}
77+
},
5878
}
5979
}
6080

81+
const workspace = target === 'workspace' ? '../samples/e2e/wdio.code-workspace' : `../samples/e2e/${target}`
82+
6183
export const config: WebdriverIO.Config = {
62-
...createBaseConfig(`../samples/e2e/${target}`),
84+
...createBaseConfig(workspace),
6385
specs,
6486
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)