-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathindex.ts
More file actions
129 lines (115 loc) · 4.83 KB
/
index.ts
File metadata and controls
129 lines (115 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import type { MatcherContext } from 'expect'
import type { BottomBarPanel, TreeItem, Workbench } from 'wdio-vscode-service'
import type { STATUS } from '../helpers/index.js'
export interface ExpectedTreeItem {
text: string
status: StatusStrings
children?: ExpectedTreeItem[]
}
export type StatusStrings = (typeof STATUS)[keyof typeof STATUS]
class MismatchTreeStructureError extends Error {
constructor(public assertionMessage: () => string) {
super('Mismatch')
}
}
async function expectTreeToMatchStructure(
this: MatcherContext,
receivedTree: TreeItem[],
expectedTree: ExpectedTreeItem[],
level = 0,
index = 0
) {
try {
if (expectedTree.length !== receivedTree.length) {
throw new MismatchTreeStructureError(
() =>
`Mismatch the number of items at (${index} : ${level})` +
` Expected: ${this.utils.printExpected(expectedTree.length)}` +
` Received: ${this.utils.printReceived(receivedTree.length)}`
)
}
for (const [index, item] of Object.entries(receivedTree)) {
const rootLabel = await item.getLabel()
const expectItem = expectedTree[Number(index)]
if (typeof expectItem.text === 'undefined' || typeof expectItem.status === 'undefined') {
throw new MismatchTreeStructureError(() => `The expected values are not set (${index} : ${level})`)
}
const labelRegex = new RegExp(expectItem.text)
if (!labelRegex.test(rootLabel)) {
throw new MismatchTreeStructureError(
() =>
`Mismatch the label of items at (${index} : ${level})` +
` Expected: ${this.utils.printExpected(expectItem.text)}` +
` Received: ${this.utils.printReceived(rootLabel)}`
)
}
const receivedStatus = rootLabel.match(/\(([^)]+)\)/)
if (!receivedStatus || receivedStatus[1] !== expectItem.status) {
throw new MismatchTreeStructureError(
() =>
`Mismatch the status of items at (${index} : ${level})` +
` Expected: ${this.utils.printExpected(expectItem.status)}` +
` Received: ${this.utils.printReceived(receivedStatus![1])}` +
` (${rootLabel})`
)
}
if (!(await item.isExpanded())) {
await item.expand()
}
const children = await item.getChildren()
const expectedChildren = expectItem.children
if (children && expectedChildren) {
await expectTreeToMatchStructure.call(this, children, expectedChildren, level + 1, Number(index))
}
}
return {
pass: true,
message: () => 'All ok.',
}
} catch (error) {
if (level > 0) {
throw error
}
const message = error instanceof MismatchTreeStructureError ? error.assertionMessage : () => String(error)
return {
pass: false,
message,
}
}
}
try {
if (typeof expect !== 'undefined' && expect.extend) {
expect.extend({
async toMatchTreeStructure(tree: TreeItem[], expectedStructure: ExpectedTreeItem[]) {
return await expectTreeToMatchStructure.call(this as unknown as MatcherContext, tree, expectedStructure)
},
async hasExpectedLog(workbench: Workbench, expectedLog: RegExp | string) {
const bottomBar = workbench.getBottomBar()
const outputView = await bottomBar.openOutputView()
await outputView.selectChannel('WebdriverIO')
await clickGlobalAction(bottomBar, bottomBar.locators.maximize)
const logs = await outputView.getText()
const regexp = typeof expectedLog === 'string' ? new RegExp(expectedLog) : expectedLog
const pass = logs.some((log) => regexp.test(log))
await clickGlobalAction(bottomBar, bottomBar.locators.restore)
const message = pass ? 'The log outputs include expected text.' : 'The expected text is not included'
return { pass, message: () => message }
},
})
}
} catch (error) {
console.warn('Failed to extend expect:', error)
}
async function clickGlobalAction(bottomBar: BottomBarPanel, label: string) {
let action
try {
action = (await bottomBar.elem
.$(bottomBar.locators.globalActions)
.$(`.//a[contains(@aria-label, '${label}') and @role='checkbox']`)) as WebdriverIO.Element
} catch {
// the panel is already maximized
}
if (action) {
await action.click({})
}
}