@badisi/wdio-harness 3.1.3 → 3.1.5
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/build.mjs +77 -0
- package/package.json +17 -4
- package/{WebdriverIOHarnessEnvironment.js → src/WebdriverIOHarnessEnvironment.ts} +31 -12
- package/{WebdriverIOTestElement.js → src/WebdriverIOTestElement.ts} +146 -59
- package/{index.js → src/index.ts} +18 -5
- package/tsconfig.json +36 -0
- package/LICENSE +0 -21
- package/README.md +0 -109
- package/WebdriverIOHarnessEnvironment.d.ts +0 -34
- package/WebdriverIOTestElement.d.ts +0 -91
- package/index.d.ts +0 -31
package/build.mjs
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/naming-convention, no-underscore-dangle */
|
|
2
|
+
|
|
3
|
+
import colors from '@colors/colors/safe.js';
|
|
4
|
+
import { existsSync, mkdirSync, rmSync, readFileSync, writeFileSync } from 'fs';
|
|
5
|
+
import { dirname, resolve as pathResolve } from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import { exec } from 'child_process';
|
|
8
|
+
import cpy from 'cpy';
|
|
9
|
+
|
|
10
|
+
const { green, magenta } = colors;
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
const DIST_PATH = pathResolve(__dirname, '../../dist');
|
|
14
|
+
|
|
15
|
+
const log = str => console.log(magenta(str));
|
|
16
|
+
|
|
17
|
+
const execCmd = (cmd, opts) => new Promise((resolve, reject) => {
|
|
18
|
+
exec(cmd, opts, (err, stdout, stderr) => {
|
|
19
|
+
if (err) {
|
|
20
|
+
console.error(stdout, stderr);
|
|
21
|
+
return reject(err);
|
|
22
|
+
}
|
|
23
|
+
return resolve(stdout);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const cleanDir = path => new Promise(resolve => {
|
|
28
|
+
const exists = existsSync(path);
|
|
29
|
+
if (exists) {
|
|
30
|
+
rmSync(path, { recursive: true, cwd: __dirname });
|
|
31
|
+
}
|
|
32
|
+
// Gives time to rmSync to unlock the file on Windows
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
mkdirSync(path, { recursive: true, cwd: __dirname });
|
|
35
|
+
resolve();
|
|
36
|
+
}, exists ? 1000 : 0);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const copyAssets = async () => {
|
|
40
|
+
await cpy('../../README.md', DIST_PATH, { flat: true });
|
|
41
|
+
await cpy('../../LICENSE', DIST_PATH, { flat: true });
|
|
42
|
+
await cpy('package.json', DIST_PATH, { flat: true });
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const customizePackageJson = () => {
|
|
46
|
+
const pkgJsonPath = pathResolve(DIST_PATH, 'package.json');
|
|
47
|
+
const pkgJson = JSON.parse(readFileSync(pkgJsonPath, { encoding: 'utf8' }));
|
|
48
|
+
delete pkgJson.scripts;
|
|
49
|
+
delete pkgJson.devDependencies;
|
|
50
|
+
delete pkgJson.publishConfig;
|
|
51
|
+
writeFileSync(pkgJsonPath, JSON.stringify(pkgJson, null, 4), { encoding: 'utf8' });
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const build = async () => {
|
|
55
|
+
log('> Cleaning..');
|
|
56
|
+
await cleanDir(DIST_PATH);
|
|
57
|
+
|
|
58
|
+
log('> Building library..');
|
|
59
|
+
await execCmd('tsc --project tsconfig.json', { cwd: __dirname });
|
|
60
|
+
|
|
61
|
+
log('> Copying assets..');
|
|
62
|
+
await copyAssets();
|
|
63
|
+
|
|
64
|
+
log('> Customizing package.json..');
|
|
65
|
+
customizePackageJson();
|
|
66
|
+
|
|
67
|
+
log(`> ${green('Done!')}\n`);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
void (async () => {
|
|
71
|
+
try {
|
|
72
|
+
await build();
|
|
73
|
+
} catch (err) {
|
|
74
|
+
console.error(err);
|
|
75
|
+
process.exit(1);
|
|
76
|
+
}
|
|
77
|
+
})();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@badisi/wdio-harness",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.5",
|
|
4
4
|
"description": "WebdriverIO support for Angular component test harnesses.",
|
|
5
5
|
"homepage": "https://github.com/badisi/wdio-harness",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,15 +12,15 @@
|
|
|
12
12
|
"typings": "index.d.ts",
|
|
13
13
|
"exports": {
|
|
14
14
|
".": {
|
|
15
|
-
"types": "./index.d.ts",
|
|
16
15
|
"import": "./index.js",
|
|
16
|
+
"types": "./index.d.ts",
|
|
17
17
|
"default": "./index.js"
|
|
18
18
|
},
|
|
19
19
|
"./package.json": "./package.json"
|
|
20
20
|
},
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
|
-
"url": "https://github.com/badisi/wdio-harness.git"
|
|
23
|
+
"url": "git+https://github.com/badisi/wdio-harness.git"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"angular",
|
|
@@ -35,6 +35,10 @@
|
|
|
35
35
|
"webdriver",
|
|
36
36
|
"webdriverio"
|
|
37
37
|
],
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "node ./build.mjs",
|
|
40
|
+
"release": "npm publish ../../dist"
|
|
41
|
+
},
|
|
38
42
|
"engines": {
|
|
39
43
|
"node": "^16.14.0 || >=18.10.0"
|
|
40
44
|
},
|
|
@@ -45,5 +49,14 @@
|
|
|
45
49
|
},
|
|
46
50
|
"dependencies": {
|
|
47
51
|
"@colors/colors": "^1.6.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@angular/cdk": "^18.1.4",
|
|
55
|
+
"@wdio/logger": "^8.38.0",
|
|
56
|
+
"webdriverio": "^8.40.2",
|
|
57
|
+
"cpy": "^11.1.0"
|
|
58
|
+
},
|
|
59
|
+
"publishConfig": {
|
|
60
|
+
"access": "public"
|
|
48
61
|
}
|
|
49
|
-
}
|
|
62
|
+
}
|
|
@@ -1,60 +1,79 @@
|
|
|
1
|
-
import { HarnessEnvironment } from '@angular/cdk/testing';
|
|
1
|
+
import { ComponentHarness, ComponentHarnessConstructor, HarnessEnvironment } from '@angular/cdk/testing';
|
|
2
2
|
import logger from '@wdio/logger';
|
|
3
|
+
|
|
3
4
|
import { WebdriverIOTestElement } from './WebdriverIOTestElement.js';
|
|
5
|
+
|
|
4
6
|
import colors from '@colors/colors/safe.js';
|
|
5
7
|
const { magenta, green } = colors;
|
|
8
|
+
|
|
6
9
|
/** Registers the environment logger. */
|
|
7
10
|
const log = logger('wdio-harness');
|
|
11
|
+
|
|
8
12
|
/**
|
|
9
13
|
* A `HarnessEnvironment` implementation for WebdriverIO.
|
|
10
14
|
*/
|
|
11
|
-
export class WebdriverIOHarnessEnvironment extends HarnessEnvironment {
|
|
15
|
+
export class WebdriverIOHarnessEnvironment extends HarnessEnvironment<WebdriverIO.Element> {
|
|
12
16
|
/**
|
|
13
17
|
* Keep a reference to the `document` element because `rawRootElement`
|
|
14
18
|
* will be the root element of the harness's environment.
|
|
15
19
|
*/
|
|
16
|
-
documentRoot;
|
|
17
|
-
|
|
20
|
+
private documentRoot: WebdriverIO.Element;
|
|
21
|
+
|
|
22
|
+
protected constructor(
|
|
23
|
+
rawRootElement: WebdriverIO.Element,
|
|
24
|
+
options: { documentRoot: WebdriverIO.Element; }
|
|
25
|
+
) {
|
|
18
26
|
super(rawRootElement);
|
|
19
27
|
this.documentRoot = options.documentRoot;
|
|
20
28
|
}
|
|
29
|
+
|
|
21
30
|
/** Creates a `HarnessLoader` rooted at the document root. */
|
|
22
|
-
static async loader(documentRoot) {
|
|
31
|
+
static async loader(documentRoot: WebdriverIO.Element): Promise<WebdriverIOHarnessEnvironment> {
|
|
23
32
|
return new WebdriverIOHarnessEnvironment(documentRoot, { documentRoot });
|
|
24
33
|
}
|
|
34
|
+
|
|
25
35
|
/**
|
|
26
36
|
* Flushes change detection and async tasks captured in the Angular zone.
|
|
27
37
|
* In most cases it should not be necessary to call this manually. However, there may be some edge
|
|
28
38
|
* cases where it is needed to fully flush animation events.
|
|
29
39
|
*/
|
|
30
|
-
async forceStabilize() {
|
|
40
|
+
async forceStabilize(): Promise<void> {
|
|
31
41
|
/* await browser.executeAsyncScript(`
|
|
32
42
|
const done = arguments[0];
|
|
33
43
|
window.requestAnimationFrame(done);
|
|
34
44
|
`, []);*/
|
|
35
45
|
}
|
|
36
|
-
|
|
46
|
+
|
|
47
|
+
async waitForTasksOutsideAngular(): Promise<void> {
|
|
37
48
|
throw new Error('Method not implemented.');
|
|
38
49
|
}
|
|
50
|
+
|
|
39
51
|
/** Creates a `ComponentHarness` for the given harness type with the given raw host element. */
|
|
40
|
-
createComponentHarness
|
|
52
|
+
createComponentHarness<T extends ComponentHarness>(
|
|
53
|
+
harnessType: ComponentHarnessConstructor<T>,
|
|
54
|
+
element: WebdriverIO.Element
|
|
55
|
+
): T {
|
|
41
56
|
return super.createComponentHarness(harnessType, element);
|
|
42
57
|
}
|
|
58
|
+
|
|
43
59
|
/** Gets a list of all elements matching the given selector under this environment's root element. */
|
|
44
|
-
async getAllRawElements(selector) {
|
|
60
|
+
protected async getAllRawElements(selector: string): Promise<WebdriverIO.Element[]> {
|
|
45
61
|
log.info(`${magenta('GET_ALL_RAW_ELEMENTS')} ${green(selector.toString())}`);
|
|
46
62
|
return [...(await this.rawRootElement.$$(selector))];
|
|
47
63
|
}
|
|
64
|
+
|
|
48
65
|
/** Gets the root element for the document. */
|
|
49
|
-
getDocumentRoot() {
|
|
66
|
+
protected getDocumentRoot(): WebdriverIO.Element {
|
|
50
67
|
return this.documentRoot;
|
|
51
68
|
}
|
|
69
|
+
|
|
52
70
|
/** Creates a `TestElement` from a raw element. */
|
|
53
|
-
createTestElement(element) {
|
|
71
|
+
protected createTestElement(element: WebdriverIO.Element): WebdriverIOTestElement {
|
|
54
72
|
return new WebdriverIOTestElement(element);
|
|
55
73
|
}
|
|
74
|
+
|
|
56
75
|
/** Creates a `HarnessLoader` rooted at the given raw element. */
|
|
57
|
-
createEnvironment(element) {
|
|
76
|
+
protected createEnvironment(element: WebdriverIO.Element): HarnessEnvironment<WebdriverIO.Element> {
|
|
58
77
|
return new WebdriverIOHarnessEnvironment(element, {
|
|
59
78
|
documentRoot: this.documentRoot
|
|
60
79
|
});
|
|
@@ -1,18 +1,30 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
_getTextWithExcludedElements,
|
|
3
|
+
ElementDimensions,
|
|
4
|
+
EventData,
|
|
5
|
+
ModifierKeys,
|
|
6
|
+
TestElement,
|
|
7
|
+
TestKey,
|
|
8
|
+
TextOptions,
|
|
9
|
+
ComponentHarness
|
|
10
|
+
} from '@angular/cdk/testing';
|
|
2
11
|
import { browser } from '@wdio/globals';
|
|
3
12
|
import logger from '@wdio/logger';
|
|
13
|
+
|
|
4
14
|
import colors from '@colors/colors/safe.js';
|
|
5
15
|
const { magenta, green } = colors;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
16
|
+
|
|
17
|
+
enum Button {
|
|
18
|
+
LEFT = 'left',
|
|
19
|
+
MIDDLE = 'middle',
|
|
20
|
+
RIGHT = 'right'
|
|
21
|
+
}
|
|
22
|
+
|
|
12
23
|
/** Registers the element logger. */
|
|
13
24
|
const log = logger('wdio-harness');
|
|
25
|
+
|
|
14
26
|
/** Maps the `TestKey` constants to WebdriverIO's `Key` constants. */
|
|
15
|
-
const keyMap = {
|
|
27
|
+
const keyMap: Record<number, string> = {
|
|
16
28
|
[TestKey.BACKSPACE]: 'Backspace',
|
|
17
29
|
[TestKey.TAB]: 'Tab',
|
|
18
30
|
[TestKey.ENTER]: 'Enter',
|
|
@@ -45,12 +57,23 @@ const keyMap = {
|
|
|
45
57
|
[TestKey.META]: 'Meta',
|
|
46
58
|
[TestKey.COMMA]: ','
|
|
47
59
|
};
|
|
48
|
-
|
|
60
|
+
|
|
61
|
+
/** Module augmentation to expose the host element as a public api */
|
|
62
|
+
declare module '@angular/cdk/testing' {
|
|
63
|
+
interface ComponentHarness {
|
|
64
|
+
element(): WebdriverIO.Element;
|
|
65
|
+
}
|
|
66
|
+
interface TestElement {
|
|
67
|
+
element(): WebdriverIO.Element;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
ComponentHarness.prototype.element = function (this: ComponentHarness): WebdriverIO.Element {
|
|
49
71
|
return this.locatorFactory.rootElement.element();
|
|
50
72
|
};
|
|
73
|
+
|
|
51
74
|
/** Converts a `ModifierKeys` object to a list of WebdriverIO `Key`s. */
|
|
52
|
-
const toWebdriverIOModifierKeys = (modifiers) => {
|
|
53
|
-
const result = [];
|
|
75
|
+
const toWebdriverIOModifierKeys = (modifiers: ModifierKeys): string[] => {
|
|
76
|
+
const result: string[] = [];
|
|
54
77
|
if (modifiers.control) {
|
|
55
78
|
result.push(keyMap[TestKey.CONTROL]);
|
|
56
79
|
}
|
|
@@ -65,87 +88,130 @@ const toWebdriverIOModifierKeys = (modifiers) => {
|
|
|
65
88
|
}
|
|
66
89
|
return result;
|
|
67
90
|
};
|
|
91
|
+
|
|
68
92
|
/**
|
|
69
93
|
* A `TestElement` implementation for WebdriverIO.
|
|
70
94
|
*/
|
|
71
|
-
export class WebdriverIOTestElement {
|
|
72
|
-
hostElement
|
|
73
|
-
|
|
74
|
-
this.hostElement = hostElement;
|
|
75
|
-
}
|
|
95
|
+
export class WebdriverIOTestElement implements TestElement {
|
|
96
|
+
constructor(readonly hostElement: WebdriverIO.Element) { }
|
|
97
|
+
|
|
76
98
|
/** Return the host element. */
|
|
77
|
-
element() {
|
|
99
|
+
element(): WebdriverIO.Element {
|
|
78
100
|
return this.hostElement;
|
|
79
101
|
}
|
|
102
|
+
|
|
80
103
|
/** Blur the element. */
|
|
81
|
-
async blur() {
|
|
104
|
+
async blur(): Promise<void> {
|
|
82
105
|
this.logAction('BLUR');
|
|
83
106
|
return browser.executeScript('arguments[0].blur()', [this.hostElement]);
|
|
84
107
|
}
|
|
108
|
+
|
|
85
109
|
/** Clear the element's input (for input and textarea elements only). */
|
|
86
|
-
async clear() {
|
|
110
|
+
async clear(): Promise<void> {
|
|
87
111
|
this.logAction('CLEAR');
|
|
88
112
|
return this.hostElement.clearValue();
|
|
89
113
|
}
|
|
90
|
-
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Click the element at the default location for the current environment. If you need to guarantee
|
|
117
|
+
* the element is clicked at a specific location, consider using `click('center')` or
|
|
118
|
+
* `click(x, y)` instead.
|
|
119
|
+
*/
|
|
120
|
+
async click(modifiers?: ModifierKeys): Promise<void>;
|
|
121
|
+
/** Click the element at the element's center. */
|
|
122
|
+
async click(location: 'center', modifiers?: ModifierKeys): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* Click the element at the specified coordinates relative to the top-left of the element.
|
|
125
|
+
* @param relativeX Coordinate within the element, along the X-axis at which to click.
|
|
126
|
+
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
|
|
127
|
+
* @param modifiers Modifier keys held while clicking
|
|
128
|
+
*/
|
|
129
|
+
async click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
|
|
130
|
+
async click(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise<void> {
|
|
91
131
|
this.logAction('CLICK');
|
|
92
132
|
return this.dispatchClickEventSequence(args, Button.LEFT);
|
|
93
133
|
}
|
|
94
|
-
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Right clicks on the element at the specified coordinates relative to the top-left of it.
|
|
137
|
+
* @param relativeX Coordinate within the element, along the X-axis at which to click.
|
|
138
|
+
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
|
|
139
|
+
* @param modifiers Modifier keys held while clicking
|
|
140
|
+
*/
|
|
141
|
+
async rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
|
|
142
|
+
async rightClick(...args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?]): Promise<void> {
|
|
95
143
|
this.logAction('RIGHT_CLICK');
|
|
96
144
|
return this.dispatchClickEventSequence(args, Button.RIGHT);
|
|
97
145
|
}
|
|
146
|
+
|
|
98
147
|
/** Focus the element. */
|
|
99
|
-
async focus() {
|
|
148
|
+
async focus(): Promise<void> {
|
|
100
149
|
this.logAction('FOCUS');
|
|
101
150
|
return browser.executeScript('arguments[0].focus()', [this.hostElement]);
|
|
102
151
|
}
|
|
152
|
+
|
|
103
153
|
/** Get the computed value of the given CSS property for the element. */
|
|
104
|
-
async getCssValue(property) {
|
|
154
|
+
async getCssValue(property: string): Promise<string> {
|
|
105
155
|
this.logAction('GET_CSS_VALUE');
|
|
106
156
|
return (await this.hostElement.getCSSProperty(property)).value ?? '';
|
|
107
157
|
}
|
|
158
|
+
|
|
108
159
|
/** Hovers the mouse over the element. */
|
|
109
|
-
async hover() {
|
|
160
|
+
async hover(): Promise<void> {
|
|
110
161
|
this.logAction('HOVER');
|
|
111
162
|
return this.hostElement.moveTo();
|
|
112
163
|
}
|
|
164
|
+
|
|
113
165
|
/** Moves the mouse away from the element. */
|
|
114
|
-
async mouseAway() {
|
|
166
|
+
async mouseAway(): Promise<void> {
|
|
115
167
|
this.logAction('MOUSE_AWAY');
|
|
116
168
|
return this.hostElement.moveTo({ xOffset: -1, yOffset: -1 });
|
|
117
169
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Sends the given string to the input as a series of key presses. Also fires input events
|
|
173
|
+
* and attempts to add the string to the Element's value.
|
|
174
|
+
*/
|
|
175
|
+
async sendKeys(...keys: (string | TestKey)[]): Promise<void>;
|
|
176
|
+
/**
|
|
177
|
+
* Sends the given string to the input as a series of key presses. Also fires input events
|
|
178
|
+
* and attempts to add the string to the Element's value.
|
|
179
|
+
*/
|
|
180
|
+
async sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
|
|
181
|
+
async sendKeys(...modifiersAndKeys: any[]): Promise<void> {
|
|
182
|
+
let modifiers: ModifierKeys;
|
|
183
|
+
let rest: (string | TestKey)[];
|
|
184
|
+
|
|
121
185
|
const first = modifiersAndKeys[0];
|
|
122
186
|
if (first !== undefined && typeof first !== 'string' && typeof first !== 'number') {
|
|
123
187
|
modifiers = first;
|
|
124
188
|
rest = modifiersAndKeys.slice(1);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
189
|
+
} else {
|
|
127
190
|
modifiers = {};
|
|
128
191
|
rest = modifiersAndKeys;
|
|
129
192
|
}
|
|
193
|
+
|
|
130
194
|
const KeyNULL = String.fromCharCode(57344);
|
|
131
195
|
const modifierKeys = toWebdriverIOModifierKeys(modifiers);
|
|
132
196
|
const keys = rest
|
|
133
197
|
.map(k => (typeof k === 'string' ? k.split('') : [keyMap[k]]))
|
|
134
198
|
.reduce((arr, k) => arr.concat(k), [])
|
|
135
199
|
.reduce((arr, k) => {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
200
|
+
if (modifierKeys.length > 0) {
|
|
201
|
+
return arr.concat(...modifierKeys, k, KeyNULL);
|
|
202
|
+
}
|
|
203
|
+
return arr.concat(k);
|
|
204
|
+
}, [] as string[]);
|
|
205
|
+
|
|
141
206
|
this.logAction('SEND_KEYS', `[${keys.join(', ')}]`);
|
|
142
207
|
if (keys.length !== 0) {
|
|
143
208
|
await this.focus();
|
|
144
209
|
return browser.keys(keys);
|
|
145
210
|
}
|
|
146
211
|
}
|
|
212
|
+
|
|
147
213
|
/** Gets the text from the element. */
|
|
148
|
-
async text(options) {
|
|
214
|
+
async text(options?: TextOptions): Promise<string> {
|
|
149
215
|
this.logAction('TEXT', `{ exclude: ${options?.exclude} }`);
|
|
150
216
|
if (options?.exclude) {
|
|
151
217
|
return browser.executeScript(`
|
|
@@ -160,55 +226,66 @@ export class WebdriverIOTestElement {
|
|
|
160
226
|
// We don't go through WebdriverIO's `getText`, because it excludes text from hidden elements.
|
|
161
227
|
return browser.executeScript(`return (arguments[0].textContent ?? '').trim()`, [this.hostElement]);
|
|
162
228
|
}
|
|
229
|
+
|
|
163
230
|
/** Gets the value for the given attribute from the element. */
|
|
164
|
-
async getAttribute(name) {
|
|
231
|
+
async getAttribute(name: string): Promise<string | null> {
|
|
165
232
|
this.logAction('GET_ATTRIBUTE', name);
|
|
166
233
|
return this.hostElement.getAttribute(name);
|
|
167
234
|
}
|
|
235
|
+
|
|
168
236
|
/** Checks whether the element has the given class. */
|
|
169
|
-
async hasClass(name) {
|
|
237
|
+
async hasClass(name: string): Promise<boolean> {
|
|
170
238
|
this.logAction('HAS_CLASS', name);
|
|
171
239
|
const classes = (await this.getAttribute('class')) || '';
|
|
172
240
|
return new Set(classes.split(/\s+/).filter(c => c)).has(name);
|
|
173
241
|
}
|
|
242
|
+
|
|
174
243
|
/** Gets the dimensions of the element. */
|
|
175
|
-
async getDimensions() {
|
|
244
|
+
async getDimensions(): Promise<ElementDimensions> {
|
|
176
245
|
this.logAction('GET_DIMENSIONS');
|
|
177
246
|
const { width, height } = await this.hostElement.getSize();
|
|
178
247
|
const { x: left, y: top } = await this.hostElement.getLocation();
|
|
179
248
|
return { width, height, left, top };
|
|
180
249
|
}
|
|
250
|
+
|
|
181
251
|
/** Gets the value of a property of an element. */
|
|
182
|
-
async getProperty(name) {
|
|
252
|
+
async getProperty(name: string): Promise<any> {
|
|
183
253
|
this.logAction('GET_PROPERTY', name);
|
|
184
254
|
return this.hostElement.getProperty(name);
|
|
185
255
|
}
|
|
256
|
+
|
|
186
257
|
/** Checks whether this element matches the given selector. */
|
|
187
|
-
async matchesSelector(selector) {
|
|
258
|
+
async matchesSelector(selector: string): Promise<boolean> {
|
|
188
259
|
this.logAction('MATCHES_SELECTOR', selector);
|
|
189
260
|
return browser.executeScript(`
|
|
190
261
|
return (Element.prototype.matches ?? Element.prototype.msMatchesSelector).call(arguments[0], arguments[1])
|
|
191
262
|
`, [this.hostElement, selector]);
|
|
192
263
|
}
|
|
264
|
+
|
|
193
265
|
/** Checks whether the element is focused. */
|
|
194
|
-
async isFocused() {
|
|
266
|
+
async isFocused(): Promise<boolean> {
|
|
195
267
|
this.logAction('IS_FOCUSED');
|
|
196
268
|
return this.hostElement.isFocused();
|
|
197
269
|
}
|
|
270
|
+
|
|
198
271
|
/** Sets the value of a property of an input. */
|
|
199
|
-
async setInputValue(value) {
|
|
272
|
+
async setInputValue(value: string): Promise<void> {
|
|
200
273
|
this.logAction('SET_INPUT_VALUE', value);
|
|
201
274
|
return this.hostElement.setValue(value);
|
|
202
275
|
}
|
|
276
|
+
|
|
203
277
|
/** Selects the options at the specified indexes inside of a native `select` element. */
|
|
204
|
-
async selectOptions(...optionIndexes) {
|
|
278
|
+
async selectOptions(...optionIndexes: number[]): Promise<void> {
|
|
205
279
|
this.logAction('SELECT_OPTIONS', `[${optionIndexes.join(', ')}]`);
|
|
280
|
+
|
|
206
281
|
const options = await this.hostElement.$$('option');
|
|
207
282
|
const indexes = new Set(optionIndexes); // Convert to a set to remove duplicates.
|
|
283
|
+
|
|
208
284
|
if (options.length && indexes.size) {
|
|
209
285
|
// Reset the value so all the selected states are cleared. We can
|
|
210
286
|
// reuse the input-specific method since the logic is the same.
|
|
211
287
|
await this.setInputValue('');
|
|
288
|
+
|
|
212
289
|
for (let i = 0; i < options.length; i++) {
|
|
213
290
|
if (indexes.has(i)) {
|
|
214
291
|
// We have to hold the control key while clicking on options so that multiple can be
|
|
@@ -220,8 +297,9 @@ export class WebdriverIOTestElement {
|
|
|
220
297
|
}
|
|
221
298
|
}
|
|
222
299
|
}
|
|
300
|
+
|
|
223
301
|
/** Dispatches an event with a particular name. */
|
|
224
|
-
async dispatchEvent(name, data) {
|
|
302
|
+
async dispatchEvent(name: string, data?: Record<string, EventData>): Promise<void> {
|
|
225
303
|
this.logAction('DISPATCH_EVENT', name);
|
|
226
304
|
return browser.executeScript(`
|
|
227
305
|
const event = document.createEvent('Event');
|
|
@@ -232,36 +310,44 @@ export class WebdriverIOTestElement {
|
|
|
232
310
|
arguments[1]['dispatchEvent'](event);
|
|
233
311
|
`, [name, this.hostElement, data]);
|
|
234
312
|
}
|
|
313
|
+
|
|
235
314
|
/** Performs a key-down action. */
|
|
236
|
-
async keyDown(value) {
|
|
315
|
+
async keyDown(value: string): Promise<void> {
|
|
237
316
|
this.logAction('KEY_DOWN:', value);
|
|
238
317
|
return browser.performActions([{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
318
|
+
id: 'keyboard',
|
|
319
|
+
type: 'key',
|
|
320
|
+
actions: [{ type: 'keyDown', value }],
|
|
321
|
+
}]);
|
|
243
322
|
}
|
|
323
|
+
|
|
244
324
|
/** Performs a key-up action. */
|
|
245
|
-
async keyUp(value) {
|
|
325
|
+
async keyUp(value: string): Promise<void> {
|
|
246
326
|
this.logAction('KEY_UP:', value);
|
|
247
327
|
return browser.performActions([{
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
328
|
+
id: 'keyboard',
|
|
329
|
+
type: 'key',
|
|
330
|
+
actions: [{ type: 'keyUp', value }],
|
|
331
|
+
}]);
|
|
252
332
|
}
|
|
333
|
+
|
|
253
334
|
// --- HELPER(s) ---
|
|
335
|
+
|
|
254
336
|
/** Dispatches all the events that are part of a click event sequence. */
|
|
255
|
-
async dispatchClickEventSequence(
|
|
256
|
-
|
|
337
|
+
private async dispatchClickEventSequence(
|
|
338
|
+
args: [ModifierKeys?] | ['center', ModifierKeys?] | [number, number, ModifierKeys?], button: Button,
|
|
339
|
+
) {
|
|
340
|
+
let modifiers: ModifierKeys = {};
|
|
257
341
|
if (args.length && typeof args[args.length - 1] === 'object') {
|
|
258
|
-
modifiers = args.pop();
|
|
342
|
+
modifiers = args.pop() as ModifierKeys;
|
|
259
343
|
}
|
|
260
344
|
const modifierKeys = toWebdriverIOModifierKeys(modifiers);
|
|
345
|
+
|
|
261
346
|
// Omitting the offset argument to mouseMove results in clicking the center.
|
|
262
347
|
// This is the default behavior we want, so we use an empty array of offsetArgs if
|
|
263
348
|
// no args remain after popping the modifiers from the args passed to this function.
|
|
264
349
|
const offsetArgs = (args.length === 2 ? { xOffset: Number(args[0]), yOffset: Number(args[1]) } : undefined);
|
|
350
|
+
|
|
265
351
|
await this.hostElement.moveTo(offsetArgs);
|
|
266
352
|
for (const modifierKey of modifierKeys) {
|
|
267
353
|
this.keyDown(modifierKey);
|
|
@@ -271,8 +357,9 @@ export class WebdriverIOTestElement {
|
|
|
271
357
|
this.keyUp(modifierKey);
|
|
272
358
|
}
|
|
273
359
|
}
|
|
360
|
+
|
|
274
361
|
/** Writes info to the console outputs. */
|
|
275
|
-
logAction(action, args) {
|
|
362
|
+
private logAction(action: string, args?: string): void {
|
|
276
363
|
log.info(`${magenta(action)} ${green(this.hostElement.selector.toString())} ${args ? args : ''}`);
|
|
277
364
|
}
|
|
278
365
|
}
|
|
@@ -1,14 +1,20 @@
|
|
|
1
|
+
import { ComponentHarness, ComponentHarnessConstructor, HarnessQuery } from '@angular/cdk/testing';
|
|
1
2
|
import { browser, $ } from '@wdio/globals';
|
|
3
|
+
|
|
2
4
|
import { WebdriverIOHarnessEnvironment } from './WebdriverIOHarnessEnvironment.js';
|
|
5
|
+
|
|
3
6
|
/**
|
|
4
7
|
* Searches for all instances of the component corresponding to the given harness type under the
|
|
5
8
|
* `HarnessLoader`'s root element, and returns a list of `ComponentHarness` for each instance.
|
|
6
9
|
* @param query A query for a harness to create
|
|
7
10
|
* @return A list of instances of the given harness type
|
|
8
11
|
*/
|
|
9
|
-
export const getAllHarnesses = async
|
|
12
|
+
export const getAllHarnesses = async <T extends ComponentHarness>(
|
|
13
|
+
query: HarnessQuery<T>
|
|
14
|
+
): Promise<T[]> => {
|
|
10
15
|
return (await createHarnessEnvironment()).getAllHarnesses(query);
|
|
11
16
|
};
|
|
17
|
+
|
|
12
18
|
/**
|
|
13
19
|
* Searches for an instance of the component corresponding to the given harness type or host element
|
|
14
20
|
* under the `HarnessLoader`'s root element, and returns a `ComponentHarness` for that instance. If
|
|
@@ -19,26 +25,33 @@ export const getAllHarnesses = async (query) => {
|
|
|
19
25
|
* @return An instance of the given harness type
|
|
20
26
|
* @throws If a matching component instance can't be found
|
|
21
27
|
*/
|
|
22
|
-
export const getHarness = async
|
|
28
|
+
export const getHarness = async <T extends ComponentHarness>(
|
|
29
|
+
query: HarnessQuery<T>,
|
|
30
|
+
element?: WebdriverIO.Element
|
|
31
|
+
): Promise<T> => {
|
|
23
32
|
const env = await createHarnessEnvironment(element);
|
|
24
33
|
if (element) {
|
|
25
|
-
return env.createComponentHarness(query
|
|
34
|
+
return env.createComponentHarness(query as ComponentHarnessConstructor<T>, element);
|
|
26
35
|
}
|
|
27
36
|
return env.getHarness(query);
|
|
28
37
|
};
|
|
38
|
+
|
|
29
39
|
/**
|
|
30
40
|
* Returns a base harness environment instance.
|
|
31
41
|
* @return An HarnessLoader instance for the current HTML document, rooted at the document's root element
|
|
32
42
|
*/
|
|
33
|
-
export const createHarnessEnvironment = async (
|
|
43
|
+
export const createHarnessEnvironment = async (
|
|
44
|
+
rootElement?: WebdriverIO.Element
|
|
45
|
+
): Promise<WebdriverIOHarnessEnvironment> => {
|
|
34
46
|
return WebdriverIOHarnessEnvironment.loader(rootElement || await $('body'));
|
|
35
47
|
};
|
|
48
|
+
|
|
36
49
|
/**
|
|
37
50
|
* Returns a promise that resolves when the application is "stable".
|
|
38
51
|
* The promise might be rejected due to timeouts, or async tasks in the client
|
|
39
52
|
* app that never finish (timers, etc).
|
|
40
53
|
*/
|
|
41
|
-
export const waitForAngular = async () => {
|
|
54
|
+
export const waitForAngular = async (): Promise<void> => {
|
|
42
55
|
await browser.waitUntil(() => browser.executeScript(`
|
|
43
56
|
return Array.isArray(window.frameworkStabilizers)
|
|
44
57
|
`, []));
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"baseUrl": "src",
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "../../dist/",
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"target": "es2022",
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"lib": [
|
|
10
|
+
"es2020",
|
|
11
|
+
"dom"
|
|
12
|
+
],
|
|
13
|
+
"allowJs": true,
|
|
14
|
+
"allowSyntheticDefaultImports": true,
|
|
15
|
+
"esModuleInterop": true,
|
|
16
|
+
"declaration": true,
|
|
17
|
+
"inlineSourceMap": false,
|
|
18
|
+
"listEmittedFiles": false,
|
|
19
|
+
"listFiles": false,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"pretty": true,
|
|
22
|
+
"skipLibCheck": true,
|
|
23
|
+
"strict": true,
|
|
24
|
+
"traceResolution": false,
|
|
25
|
+
"importHelpers": true,
|
|
26
|
+
"strictPropertyInitialization": true,
|
|
27
|
+
"noUnusedLocals": true,
|
|
28
|
+
"types": [
|
|
29
|
+
"node"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"compileOnSave": false,
|
|
33
|
+
"include": [
|
|
34
|
+
"src/**/*.ts"
|
|
35
|
+
]
|
|
36
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2021 Badisi
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
<h1 align="center">
|
|
2
|
-
@badisi/wdio-harness
|
|
3
|
-
</h1>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<i>🔬 <a href="https://webdriver.io" alt="wdio">WebdriverIO</a> support for Angular component test harnesses.</i><br/>
|
|
7
|
-
</p>
|
|
8
|
-
|
|
9
|
-
<p align="center">
|
|
10
|
-
<a href="https://www.npmjs.com/package/@badisi/wdio-harness">
|
|
11
|
-
<img src="https://img.shields.io/npm/v/@badisi/wdio-harness.svg?color=blue&logo=npm" alt="npm version" /></a>
|
|
12
|
-
<a href="https://npmcharts.com/compare/@badisi/wdio-harness?minimal=true">
|
|
13
|
-
<img src="https://img.shields.io/npm/dw/@badisi/wdio-harness.svg?color=7986CB&logo=npm" alt="npm donwloads" /></a>
|
|
14
|
-
<a href="https://github.com/badisi/wdio-harness/blob/main/LICENSE">
|
|
15
|
-
<img src="https://img.shields.io/npm/l/@badisi/wdio-harness.svg?color=ff69b4" alt="license" /></a>
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
<p align="center">
|
|
19
|
-
<a href="https://github.com/Badisi/wdio-harness/actions/workflows/ci_tests.yml">
|
|
20
|
-
<img src="https://github.com/Badisi/wdio-harness/actions/workflows/ci_tests.yml/badge.svg" alt="build status" /></a>
|
|
21
|
-
<a href="https://github.com/badisi/wdio-harness/blob/main/CONTRIBUTING.md#-submitting-a-pull-request-pr">
|
|
22
|
-
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome" /></a>
|
|
23
|
-
</p>
|
|
24
|
-
|
|
25
|
-
<hr/>
|
|
26
|
-
|
|
27
|
-
#### Component test harnesses
|
|
28
|
-
|
|
29
|
-
> A component harness is a class that lets a test interact with a component via a supported API. Each harness's API interacts with a component the same way a user would. By using the harness API, a test insulates itself against updates to the internals of a component, such as changing its DOM structure. The idea for component harnesses comes from the [PageObject](https://martinfowler.com/bliki/PageObject.html) pattern commonly used for integration testing.
|
|
30
|
-
|
|
31
|
-
[More info](https://material.angular.io/cdk/test-harnesses/overview)
|
|
32
|
-
|
|
33
|
-
<hr/>
|
|
34
|
-
|
|
35
|
-
## Installation
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
npm install @badisi/wdio-harness --save-dev
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
```sh
|
|
42
|
-
yarn add @badisi/wdio-harness --dev
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## Usage
|
|
47
|
-
|
|
48
|
-
__Methods__
|
|
49
|
-
|
|
50
|
-
- `createHarnessEnvironment(rootElement)` - gets a HarnessLoader instance from a given element (defaults to body)
|
|
51
|
-
- `getHarness(harnessType, element)` - searches for an harness instance from a given ComponentHarness class and element
|
|
52
|
-
- `getHarness(harnessType)` - searches for an harness instance from a given ComponentHarness class
|
|
53
|
-
- `getHarness(query)` - searches for an harness instance from a given HarnessPredicate
|
|
54
|
-
- `getAllHarnesses(query)` - acts like getHarness, but returns an array of harness instances
|
|
55
|
-
- `waitForAngular()` - waits for Angular to finish bootstrapping
|
|
56
|
-
|
|
57
|
-
__Example__
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
import { MatDatepickerInputHarness } from '@angular/material/datepicker/testing';
|
|
61
|
-
import { getHarness } from '@badisi/wdio-harness';
|
|
62
|
-
|
|
63
|
-
describe('Angular Material Harness', () => {
|
|
64
|
-
beforeEach(async () => {
|
|
65
|
-
await browser.url('http://localhost:4200');
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('MatDatePicker', async () => {
|
|
69
|
-
const datepicker = await getHarness(MatDatepickerInputHarness.with({ selector: '#demo-datepicker-input' }));
|
|
70
|
-
|
|
71
|
-
await datepicker.setValue('9/27/1954');
|
|
72
|
-
expect(await datepicker.getValue()).withContext('Date should be 9/27/1954').toBe('9/27/1954');
|
|
73
|
-
|
|
74
|
-
await datepicker.openCalendar();
|
|
75
|
-
const calendar = await datepicker.getCalendar();
|
|
76
|
-
await calendar.next();
|
|
77
|
-
await calendar.selectCell({ text: '20' });
|
|
78
|
-
expect(await datepicker.getValue()).withContext('Date should be 10/20/1954').toBe('10/20/1954');
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
More examples [here][examples].
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
## Development
|
|
87
|
-
|
|
88
|
-
See the [developer docs][developer].
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
## Contributing
|
|
92
|
-
|
|
93
|
-
#### > Want to Help ?
|
|
94
|
-
|
|
95
|
-
Want to file a bug, contribute some code or improve documentation ? Excellent!
|
|
96
|
-
|
|
97
|
-
But please read up first on the guidelines for [contributing][contributing], and learn about submission process, coding rules and more.
|
|
98
|
-
|
|
99
|
-
#### > Code of Conduct
|
|
100
|
-
|
|
101
|
-
Please read and follow the [Code of Conduct][codeofconduct] and help me keep this project open and inclusive.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
[developer]: https://github.com/badisi/wdio-harness/blob/main/DEVELOPER.md
|
|
107
|
-
[contributing]: https://github.com/badisi/wdio-harness/blob/main/CONTRIBUTING.md
|
|
108
|
-
[codeofconduct]: https://github.com/badisi/wdio-harness/blob/main/CODE_OF_CONDUCT.md
|
|
109
|
-
[examples]: https://github.com/badisi/wdio-harness/blob/main/projects/tests-e2e/harness.e2e.ts
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { ComponentHarness, ComponentHarnessConstructor, HarnessEnvironment } from '@angular/cdk/testing';
|
|
2
|
-
import { WebdriverIOTestElement } from './WebdriverIOTestElement.js';
|
|
3
|
-
/**
|
|
4
|
-
* A `HarnessEnvironment` implementation for WebdriverIO.
|
|
5
|
-
*/
|
|
6
|
-
export declare class WebdriverIOHarnessEnvironment extends HarnessEnvironment<WebdriverIO.Element> {
|
|
7
|
-
/**
|
|
8
|
-
* Keep a reference to the `document` element because `rawRootElement`
|
|
9
|
-
* will be the root element of the harness's environment.
|
|
10
|
-
*/
|
|
11
|
-
private documentRoot;
|
|
12
|
-
protected constructor(rawRootElement: WebdriverIO.Element, options: {
|
|
13
|
-
documentRoot: WebdriverIO.Element;
|
|
14
|
-
});
|
|
15
|
-
/** Creates a `HarnessLoader` rooted at the document root. */
|
|
16
|
-
static loader(documentRoot: WebdriverIO.Element): Promise<WebdriverIOHarnessEnvironment>;
|
|
17
|
-
/**
|
|
18
|
-
* Flushes change detection and async tasks captured in the Angular zone.
|
|
19
|
-
* In most cases it should not be necessary to call this manually. However, there may be some edge
|
|
20
|
-
* cases where it is needed to fully flush animation events.
|
|
21
|
-
*/
|
|
22
|
-
forceStabilize(): Promise<void>;
|
|
23
|
-
waitForTasksOutsideAngular(): Promise<void>;
|
|
24
|
-
/** Creates a `ComponentHarness` for the given harness type with the given raw host element. */
|
|
25
|
-
createComponentHarness<T extends ComponentHarness>(harnessType: ComponentHarnessConstructor<T>, element: WebdriverIO.Element): T;
|
|
26
|
-
/** Gets a list of all elements matching the given selector under this environment's root element. */
|
|
27
|
-
protected getAllRawElements(selector: string): Promise<WebdriverIO.Element[]>;
|
|
28
|
-
/** Gets the root element for the document. */
|
|
29
|
-
protected getDocumentRoot(): WebdriverIO.Element;
|
|
30
|
-
/** Creates a `TestElement` from a raw element. */
|
|
31
|
-
protected createTestElement(element: WebdriverIO.Element): WebdriverIOTestElement;
|
|
32
|
-
/** Creates a `HarnessLoader` rooted at the given raw element. */
|
|
33
|
-
protected createEnvironment(element: WebdriverIO.Element): HarnessEnvironment<WebdriverIO.Element>;
|
|
34
|
-
}
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { ElementDimensions, EventData, ModifierKeys, TestElement, TestKey, TextOptions } from '@angular/cdk/testing';
|
|
2
|
-
/** Module augmentation to expose the host element as a public api */
|
|
3
|
-
declare module '@angular/cdk/testing' {
|
|
4
|
-
interface ComponentHarness {
|
|
5
|
-
element(): WebdriverIO.Element;
|
|
6
|
-
}
|
|
7
|
-
interface TestElement {
|
|
8
|
-
element(): WebdriverIO.Element;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* A `TestElement` implementation for WebdriverIO.
|
|
13
|
-
*/
|
|
14
|
-
export declare class WebdriverIOTestElement implements TestElement {
|
|
15
|
-
readonly hostElement: WebdriverIO.Element;
|
|
16
|
-
constructor(hostElement: WebdriverIO.Element);
|
|
17
|
-
/** Return the host element. */
|
|
18
|
-
element(): WebdriverIO.Element;
|
|
19
|
-
/** Blur the element. */
|
|
20
|
-
blur(): Promise<void>;
|
|
21
|
-
/** Clear the element's input (for input and textarea elements only). */
|
|
22
|
-
clear(): Promise<void>;
|
|
23
|
-
/**
|
|
24
|
-
* Click the element at the default location for the current environment. If you need to guarantee
|
|
25
|
-
* the element is clicked at a specific location, consider using `click('center')` or
|
|
26
|
-
* `click(x, y)` instead.
|
|
27
|
-
*/
|
|
28
|
-
click(modifiers?: ModifierKeys): Promise<void>;
|
|
29
|
-
/** Click the element at the element's center. */
|
|
30
|
-
click(location: 'center', modifiers?: ModifierKeys): Promise<void>;
|
|
31
|
-
/**
|
|
32
|
-
* Click the element at the specified coordinates relative to the top-left of the element.
|
|
33
|
-
* @param relativeX Coordinate within the element, along the X-axis at which to click.
|
|
34
|
-
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
|
|
35
|
-
* @param modifiers Modifier keys held while clicking
|
|
36
|
-
*/
|
|
37
|
-
click(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
|
|
38
|
-
/**
|
|
39
|
-
* Right clicks on the element at the specified coordinates relative to the top-left of it.
|
|
40
|
-
* @param relativeX Coordinate within the element, along the X-axis at which to click.
|
|
41
|
-
* @param relativeY Coordinate within the element, along the Y-axis at which to click.
|
|
42
|
-
* @param modifiers Modifier keys held while clicking
|
|
43
|
-
*/
|
|
44
|
-
rightClick(relativeX: number, relativeY: number, modifiers?: ModifierKeys): Promise<void>;
|
|
45
|
-
/** Focus the element. */
|
|
46
|
-
focus(): Promise<void>;
|
|
47
|
-
/** Get the computed value of the given CSS property for the element. */
|
|
48
|
-
getCssValue(property: string): Promise<string>;
|
|
49
|
-
/** Hovers the mouse over the element. */
|
|
50
|
-
hover(): Promise<void>;
|
|
51
|
-
/** Moves the mouse away from the element. */
|
|
52
|
-
mouseAway(): Promise<void>;
|
|
53
|
-
/**
|
|
54
|
-
* Sends the given string to the input as a series of key presses. Also fires input events
|
|
55
|
-
* and attempts to add the string to the Element's value.
|
|
56
|
-
*/
|
|
57
|
-
sendKeys(...keys: (string | TestKey)[]): Promise<void>;
|
|
58
|
-
/**
|
|
59
|
-
* Sends the given string to the input as a series of key presses. Also fires input events
|
|
60
|
-
* and attempts to add the string to the Element's value.
|
|
61
|
-
*/
|
|
62
|
-
sendKeys(modifiers: ModifierKeys, ...keys: (string | TestKey)[]): Promise<void>;
|
|
63
|
-
/** Gets the text from the element. */
|
|
64
|
-
text(options?: TextOptions): Promise<string>;
|
|
65
|
-
/** Gets the value for the given attribute from the element. */
|
|
66
|
-
getAttribute(name: string): Promise<string | null>;
|
|
67
|
-
/** Checks whether the element has the given class. */
|
|
68
|
-
hasClass(name: string): Promise<boolean>;
|
|
69
|
-
/** Gets the dimensions of the element. */
|
|
70
|
-
getDimensions(): Promise<ElementDimensions>;
|
|
71
|
-
/** Gets the value of a property of an element. */
|
|
72
|
-
getProperty(name: string): Promise<any>;
|
|
73
|
-
/** Checks whether this element matches the given selector. */
|
|
74
|
-
matchesSelector(selector: string): Promise<boolean>;
|
|
75
|
-
/** Checks whether the element is focused. */
|
|
76
|
-
isFocused(): Promise<boolean>;
|
|
77
|
-
/** Sets the value of a property of an input. */
|
|
78
|
-
setInputValue(value: string): Promise<void>;
|
|
79
|
-
/** Selects the options at the specified indexes inside of a native `select` element. */
|
|
80
|
-
selectOptions(...optionIndexes: number[]): Promise<void>;
|
|
81
|
-
/** Dispatches an event with a particular name. */
|
|
82
|
-
dispatchEvent(name: string, data?: Record<string, EventData>): Promise<void>;
|
|
83
|
-
/** Performs a key-down action. */
|
|
84
|
-
keyDown(value: string): Promise<void>;
|
|
85
|
-
/** Performs a key-up action. */
|
|
86
|
-
keyUp(value: string): Promise<void>;
|
|
87
|
-
/** Dispatches all the events that are part of a click event sequence. */
|
|
88
|
-
private dispatchClickEventSequence;
|
|
89
|
-
/** Writes info to the console outputs. */
|
|
90
|
-
private logAction;
|
|
91
|
-
}
|
package/index.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { ComponentHarness, HarnessQuery } from '@angular/cdk/testing';
|
|
2
|
-
import { WebdriverIOHarnessEnvironment } from './WebdriverIOHarnessEnvironment.js';
|
|
3
|
-
/**
|
|
4
|
-
* Searches for all instances of the component corresponding to the given harness type under the
|
|
5
|
-
* `HarnessLoader`'s root element, and returns a list of `ComponentHarness` for each instance.
|
|
6
|
-
* @param query A query for a harness to create
|
|
7
|
-
* @return A list of instances of the given harness type
|
|
8
|
-
*/
|
|
9
|
-
export declare const getAllHarnesses: <T extends ComponentHarness>(query: HarnessQuery<T>) => Promise<T[]>;
|
|
10
|
-
/**
|
|
11
|
-
* Searches for an instance of the component corresponding to the given harness type or host element
|
|
12
|
-
* under the `HarnessLoader`'s root element, and returns a `ComponentHarness` for that instance. If
|
|
13
|
-
* multiple matching components are found, a harness for the first one is returned. If no matching
|
|
14
|
-
* component is found, an error is thrown.
|
|
15
|
-
* @param query A query for a harness to create
|
|
16
|
-
* @param element A raw host element for a harness to create
|
|
17
|
-
* @return An instance of the given harness type
|
|
18
|
-
* @throws If a matching component instance can't be found
|
|
19
|
-
*/
|
|
20
|
-
export declare const getHarness: <T extends ComponentHarness>(query: HarnessQuery<T>, element?: WebdriverIO.Element) => Promise<T>;
|
|
21
|
-
/**
|
|
22
|
-
* Returns a base harness environment instance.
|
|
23
|
-
* @return An HarnessLoader instance for the current HTML document, rooted at the document's root element
|
|
24
|
-
*/
|
|
25
|
-
export declare const createHarnessEnvironment: (rootElement?: WebdriverIO.Element) => Promise<WebdriverIOHarnessEnvironment>;
|
|
26
|
-
/**
|
|
27
|
-
* Returns a promise that resolves when the application is "stable".
|
|
28
|
-
* The promise might be rejected due to timeouts, or async tasks in the client
|
|
29
|
-
* app that never finish (timers, etc).
|
|
30
|
-
*/
|
|
31
|
-
export declare const waitForAngular: () => Promise<void>;
|