@winning-test/component 0.0.79 → 0.0.81
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/package.json +5 -5
- package/rpes5.6/component/BlockComponent.js +234 -0
- package/rpes5.6/component/ButtonComponent.js +23 -0
- package/rpes5.6/component/CheckboxComponent.js +53 -0
- package/rpes5.6/component/Component.js +77 -0
- package/rpes5.6/component/DialogComponent.js +23 -0
- package/rpes5.6/component/InputComponent.js +31 -0
- package/rpes5.6/component/ListComponent.js +53 -0
- package/rpes5.6/component/MessageComponent.js +23 -0
- package/rpes5.6/component/RadioComponent.js +44 -0
- package/rpes5.6/component/SelectComponent.js +76 -0
- package/rpes5.6/component/SwitchComponent.js +50 -0
- package/rpes5.6/component/TableComponent.js +104 -0
- package/rpes5.6/component/TextComponent.js +23 -0
- package/rpes5.6/component/TextareaComponent.js +27 -0
- package/rpes5.6/component/TopMenuComponent.js +33 -0
- package/rpes5.6/page/Page.js +199 -0
- package/rpes5.6/test/component.test.js +114 -0
- package/rpes5.6/test/component.test.json +13 -0
- package/rpes5.6/test/func.js +87 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@winning-test/component",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.81",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "",
|
|
6
6
|
"scripts": {
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"author": "",
|
|
14
14
|
"license": "ISC",
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@types/jest": "^29.5.
|
|
17
|
-
"@winning-test/autotest-webui": "^0.1.
|
|
18
|
-
"chromedriver": "^118.0.
|
|
19
|
-
"jest": "^29.
|
|
16
|
+
"@types/jest": "^29.5.6",
|
|
17
|
+
"@winning-test/autotest-webui": "^0.1.52",
|
|
18
|
+
"chromedriver": "^118.0.1",
|
|
19
|
+
"jest": "^29.7.0"
|
|
20
20
|
}
|
|
21
21
|
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 块组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class BlockComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 块组件
|
|
9
|
+
* @param {Browser} browser
|
|
10
|
+
* @param {String} xpath xpath
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, xpath) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.xpath = xpath;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
return this.xpath;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 获取块组件
|
|
23
|
+
* @param {String} id id
|
|
24
|
+
* @param {String} xpath xpath
|
|
25
|
+
* @returns 块组件
|
|
26
|
+
*/
|
|
27
|
+
blockComponent(id, xpath) {
|
|
28
|
+
let that = this;
|
|
29
|
+
class _BlockComponent extends BlockComponent {
|
|
30
|
+
_createRootXpath() {
|
|
31
|
+
return that.getXpath();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return new _BlockComponent(this.browser, id, xpath);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 获取按钮组件
|
|
39
|
+
* @param {String} text 文本
|
|
40
|
+
* @returns 按钮组件
|
|
41
|
+
*/
|
|
42
|
+
buttonComponent(text) {
|
|
43
|
+
let that = this;
|
|
44
|
+
class ButtonComponent extends require("./ButtonComponent") {
|
|
45
|
+
_createRootXpath() {
|
|
46
|
+
return that.getXpath();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return new ButtonComponent(this.browser, text);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 获取复选框组件
|
|
54
|
+
* @param {String} label 标签
|
|
55
|
+
* @returns 复选框组件
|
|
56
|
+
*/
|
|
57
|
+
checkboxComponent(label) {
|
|
58
|
+
let that = this;
|
|
59
|
+
class CheckboxComponent extends require("./CheckboxComponent") {
|
|
60
|
+
_createRootXpath() {
|
|
61
|
+
return that.getXpath();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return new CheckboxComponent(this.browser, label);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 获取对话框组件
|
|
69
|
+
* @param {String} title 标题
|
|
70
|
+
* @returns 对话框组件
|
|
71
|
+
*/
|
|
72
|
+
dialogComponent(title) {
|
|
73
|
+
let that = this;
|
|
74
|
+
class DialogComponent extends require("./DialogComponent") {
|
|
75
|
+
_createRootXpath() {
|
|
76
|
+
return that.getXpath();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return new DialogComponent(this.browser, title);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 获取输入框组件
|
|
84
|
+
* @param {String} placeholder 背景文字
|
|
85
|
+
* @param {String} label 标签
|
|
86
|
+
* @returns 输入框组件
|
|
87
|
+
*/
|
|
88
|
+
inputComponent(placeholder, label) {
|
|
89
|
+
let that = this;
|
|
90
|
+
class InputComponent extends require("./InputComponent") {
|
|
91
|
+
_createRootXpath() {
|
|
92
|
+
return that.getXpath();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return new InputComponent(this.browser, placeholder, label);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 获取列表组件
|
|
101
|
+
* @returns 列表组件
|
|
102
|
+
*/
|
|
103
|
+
listComponent() {
|
|
104
|
+
let that = this;
|
|
105
|
+
class ListComponent extends require("./ListComponent") {
|
|
106
|
+
_createRootXpath() {
|
|
107
|
+
return that.getXpath();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return new ListComponent(this.browser);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 获取消息组件
|
|
115
|
+
* @param {Stirng} text 文本
|
|
116
|
+
* @returns 消息组件
|
|
117
|
+
*/
|
|
118
|
+
messageComponent(text) {
|
|
119
|
+
let that = this;
|
|
120
|
+
class MessageComponent extends require("./MessageComponent") {
|
|
121
|
+
_createRootXpath() {
|
|
122
|
+
return that.getXpath();
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return new MessageComponent(this.browser, text);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 获取单选组件
|
|
130
|
+
* @param {Stirng} label 标签
|
|
131
|
+
* @returns 单选组件
|
|
132
|
+
*/
|
|
133
|
+
radioComponent(label) {
|
|
134
|
+
let that = this;
|
|
135
|
+
class RadioComponent extends require("./RadioComponent") {
|
|
136
|
+
_createRootXpath() {
|
|
137
|
+
return that.getXpath();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return new RadioComponent(this.browser, label);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 获取选择器组件
|
|
145
|
+
* @param {String} placeholder 背景文字
|
|
146
|
+
* @param {String} label 标签
|
|
147
|
+
* @returns 选择器组件
|
|
148
|
+
*/
|
|
149
|
+
selectComponent(placeholder, label) {
|
|
150
|
+
let that = this;
|
|
151
|
+
class SelectComponent extends require("./SelectComponent") {
|
|
152
|
+
_createRootXpath() {
|
|
153
|
+
return that.getXpath();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return new SelectComponent(this.browser, placeholder, label);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 获取开关组件
|
|
161
|
+
* @param {String} label 标签
|
|
162
|
+
* @returns 开关组件
|
|
163
|
+
*/
|
|
164
|
+
switchComponent(label) {
|
|
165
|
+
let that = this;
|
|
166
|
+
class SwitchComponent extends require("./SwitchComponent") {
|
|
167
|
+
_createRootXpath() {
|
|
168
|
+
return that.getXpath();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return new SwitchComponent(this.browser, label);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 获取表格组件
|
|
176
|
+
* @returns 表格组件
|
|
177
|
+
*/
|
|
178
|
+
tableComponent() {
|
|
179
|
+
let that = this;
|
|
180
|
+
class TableComponent extends require("./TableComponent") {
|
|
181
|
+
_createRootXpath() {
|
|
182
|
+
return that.getXpath();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return new TableComponent(this.browser);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* 获取多行文本输入组件
|
|
190
|
+
* @param {String} textarea 多行文本输入
|
|
191
|
+
* @returns 多行文本输入组件
|
|
192
|
+
*/
|
|
193
|
+
textareaComponent(placeholder, label) {
|
|
194
|
+
let that = this;
|
|
195
|
+
class TextareaComponent extends require("./TextareaComponent") {
|
|
196
|
+
_createRootXpath() {
|
|
197
|
+
return that.getXpath();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return new TextareaComponent(this.browser, placeholder, label);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 获取文本组件
|
|
205
|
+
* @param {String} text 文本
|
|
206
|
+
* @returns 文本组件
|
|
207
|
+
*/
|
|
208
|
+
textComponent(text) {
|
|
209
|
+
let that = this;
|
|
210
|
+
class TextComponent extends require("./TextComponent") {
|
|
211
|
+
_createRootXpath() {
|
|
212
|
+
return that.getXpath();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return new TextComponent(this.browser, text);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* 获取顶部菜单组件
|
|
220
|
+
* @returns 顶部菜单组件
|
|
221
|
+
*/
|
|
222
|
+
topMenuComponent() {
|
|
223
|
+
let that = this;
|
|
224
|
+
class TopMenuComponent extends require("./TopMenuComponent") {
|
|
225
|
+
_createRootXpath() {
|
|
226
|
+
return that.getXpath();
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return new TopMenuComponent(this.browser);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
module.exports = BlockComponent;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 按钮组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class ButtonComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 按钮组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} text 文本
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, text) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.text = text;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
return `//*[normalize-space(text())='${this.text}']/ancestor-or-self::button`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = ButtonComponent;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 复选框组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class CheckboxComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 复选框组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} label 标签
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, label) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.label = label;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
if (this.label) {
|
|
19
|
+
return `//*[normalize-space(text())='${this.label}']/..//input[@type='checkbox']`;
|
|
20
|
+
}
|
|
21
|
+
return "//input[@type='checkbox']";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 选择
|
|
26
|
+
*/
|
|
27
|
+
async select() {
|
|
28
|
+
if (!(await (await this.browser.findElement(this.getXpath())).isSelected())) {
|
|
29
|
+
await (await this.browser.findElement(this.getXpath())).click();
|
|
30
|
+
await this.browser.sleep(CheckboxComponent.delayTime);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 取消选择
|
|
36
|
+
*/
|
|
37
|
+
async unselect() {
|
|
38
|
+
if (await (await this.browser.findElement(this.getXpath())).isSelected()) {
|
|
39
|
+
await (await this.browser.findElement(this.getXpath())).click();
|
|
40
|
+
await this.browser.sleep(CheckboxComponent.delayTime);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 选择状态
|
|
46
|
+
*/
|
|
47
|
+
async isSelected() {
|
|
48
|
+
return await (await this.browser.findElement(this.getXpath())).isSelected();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = CheckboxComponent;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class Component extends require("@winning-test/autotest-webui/src/Component") {
|
|
6
|
+
|
|
7
|
+
static delayTime = 200;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 组件
|
|
11
|
+
* @param {Browser} browser
|
|
12
|
+
*/
|
|
13
|
+
constructor(browser) {
|
|
14
|
+
super(browser)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
getXpath() {
|
|
18
|
+
return `${super.getXpath()}[not (ancestor-or-self::*[contains(@style,'display: none')])]`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async click() {
|
|
22
|
+
await super.click();
|
|
23
|
+
await this.browser.sleep(Component.delayTime);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async doubleClick() {
|
|
27
|
+
await super.doubleClick();
|
|
28
|
+
await this.browser.sleep(Component.delayTime);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async input(...agrs) {
|
|
32
|
+
await super.input(...agrs);
|
|
33
|
+
await this.browser.sleep(Component.delayTime);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async clear() {
|
|
37
|
+
await super.clear();
|
|
38
|
+
await this.browser.sleep(Component.delayTime);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async getText() {
|
|
42
|
+
await this.browser.sleep(Component.delayTime);
|
|
43
|
+
return await super.getText();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getValue() {
|
|
47
|
+
await this.browser.sleep(Component.delayTime);
|
|
48
|
+
return await super.getValue();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async getAttribute(attributeName) {
|
|
52
|
+
await this.browser.sleep(Component.delayTime);
|
|
53
|
+
return await super.getAttribute(attributeName);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async waitUntilBeDisabled() {
|
|
57
|
+
await super.waitUntilBeDisabled();
|
|
58
|
+
await this.browser.sleep(Component.delayTime);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async waitUntilBeEnabled() {
|
|
62
|
+
await super.waitUntilBeEnabled();
|
|
63
|
+
await this.browser.sleep(Component.delayTime);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async waitUntilBeNotVisible() {
|
|
67
|
+
await super.waitUntilBeNotVisible();
|
|
68
|
+
await this.browser.sleep(Component.delayTime);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async waitUntilBeVisible() {
|
|
72
|
+
await super.waitUntilBeVisible();
|
|
73
|
+
await this.browser.sleep(Component.delayTime);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = Component;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对话框组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class DialogComponent extends require("./BlockComponent") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 对话框组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} title 标题
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, title) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.title = title;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
return `//*[contains(normalize-space(text()),'${this.title}')]/ancestor::*[@class='w-modal' or @role='dialog']`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = DialogComponent;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 输入框组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class InputComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 输入框组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} placeholder 背景文字
|
|
11
|
+
* @param {String} label 标签
|
|
12
|
+
*/
|
|
13
|
+
constructor(browser, placeholder, label) {
|
|
14
|
+
super(browser);
|
|
15
|
+
this.placeholder = placeholder;
|
|
16
|
+
this.label = label;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_createXpath() {
|
|
20
|
+
if (this.placeholder) {
|
|
21
|
+
return `//input[@placeholder='${this.placeholder}']`;
|
|
22
|
+
}
|
|
23
|
+
if (this.label) {
|
|
24
|
+
return `//*[normalize-space(text())='${this.label}']/ancestor-or-self::label/..//input`;
|
|
25
|
+
}
|
|
26
|
+
return "//input[@type='text']"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = InputComponent;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 列表组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class ListComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 列表组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
*/
|
|
11
|
+
constructor(browser) {
|
|
12
|
+
super(browser);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_createXpath() {
|
|
16
|
+
return `//ul[contains(@class, 'w-select-dropdown')]`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 选择列表
|
|
21
|
+
* @param {...String} items 列表项
|
|
22
|
+
*/
|
|
23
|
+
async select(...items) {
|
|
24
|
+
let xpath = `${this.getXpath()}`;
|
|
25
|
+
await this.browser.waitUntilElementBeVisible(xpath);
|
|
26
|
+
for (let i = 0; i < items.length; i++) {
|
|
27
|
+
let item = items[i];
|
|
28
|
+
xpath = `${this.getXpath()}//*[normalize-space(text())='${item}']/ancestor-or-self::li`;
|
|
29
|
+
await this.browser.waitUntilElementBeVisible(xpath);
|
|
30
|
+
await (await this.browser.findElement(xpath)).scrollIntoView();
|
|
31
|
+
await (await this.browser.findElement(xpath)).click();
|
|
32
|
+
await this.browser.sleep(ListComponent.delayTime);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 获取列表项
|
|
38
|
+
* @returns 列表项
|
|
39
|
+
*/
|
|
40
|
+
async getListItems() {
|
|
41
|
+
let ret = [];
|
|
42
|
+
let xpath = `${this.getXpath()}//li`;
|
|
43
|
+
let elements = await this.browser.findElements(xpath);
|
|
44
|
+
for (let i = 0; i < elements.length; i++) {
|
|
45
|
+
let element = elements[i];
|
|
46
|
+
ret.push(await element.getText(true));
|
|
47
|
+
}
|
|
48
|
+
return ret;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
module.exports = ListComponent;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 消息组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class MeaasgeComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 消息组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} text 文本
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, text) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.text = text;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
return `//*[contains(text(),'${this.text}')]/ancestor::*[@role='alert']`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = MeaasgeComponent;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单选框组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class RadioComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 单选框组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} label 标签
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, label) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.label = label;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
if (this.label) {
|
|
19
|
+
return `//*[normalize-space(text())='${this.label}']/..//input[@type='radio']`;
|
|
20
|
+
}
|
|
21
|
+
return "//input[@type='radio']";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 选择
|
|
26
|
+
*/
|
|
27
|
+
async select() {
|
|
28
|
+
if (!(await (await this.browser.findElement(this.getXpath())).isSelected())) {
|
|
29
|
+
await (await this.browser.findElement(this.getXpath())).click();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 取消选择
|
|
35
|
+
*/
|
|
36
|
+
async unselect() {
|
|
37
|
+
if (await (await this.browser.findElement(this.getXpath())).isSelected()) {
|
|
38
|
+
await (await this.browser.findElement(this.getXpath())).click();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = RadioComponent;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 选择器组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class SelectComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 选择器组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} placeholder 背景文字
|
|
11
|
+
* @param {String} label 标签
|
|
12
|
+
*/
|
|
13
|
+
constructor(browser, placeholder, label) {
|
|
14
|
+
super(browser);
|
|
15
|
+
this.placeholder = placeholder;
|
|
16
|
+
this.label = label;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_createXpath() {
|
|
20
|
+
if (this.placeholder) {
|
|
21
|
+
return `//input[@placeholder='${this.placeholder}']`;
|
|
22
|
+
}
|
|
23
|
+
if (this.label) {
|
|
24
|
+
return `//*[normalize-space(text())='${this.label}']/ancestor-or-self::label/..//input`;
|
|
25
|
+
}
|
|
26
|
+
return "//input[@type='text']";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 选择选项
|
|
31
|
+
* @param {...String} items 选项
|
|
32
|
+
*/
|
|
33
|
+
async select(...items) {
|
|
34
|
+
let count = 2;
|
|
35
|
+
while (count > 0) {
|
|
36
|
+
try {
|
|
37
|
+
await this._select(...items);
|
|
38
|
+
if (items.length > 1){ // 多选不检查value
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
const value = await this.getValue();
|
|
42
|
+
if (!(value && items.join().indexOf(value) !== -1)) {
|
|
43
|
+
throw new Error(`选择${items}失败`);
|
|
44
|
+
}
|
|
45
|
+
break;
|
|
46
|
+
} catch (error) {
|
|
47
|
+
if (count > 1) {
|
|
48
|
+
count--;
|
|
49
|
+
await this.browser.sleep(500);
|
|
50
|
+
} else {
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
await this.browser.sleep(SelectComponent.delayTime);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async _select(...items) {
|
|
59
|
+
class ListComponent extends require("./ListComponent") {
|
|
60
|
+
_createXpath() {
|
|
61
|
+
return "//*[@class='w-scrollbar']"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let xpath = this.getXpath();
|
|
65
|
+
await (await this.browser.findElement(xpath)).click();
|
|
66
|
+
let listComponent = new ListComponent(this.browser);
|
|
67
|
+
await listComponent.select(...items);
|
|
68
|
+
if (items.length > 1) {
|
|
69
|
+
xpath = this.getXpath();
|
|
70
|
+
await (await this.browser.findElement(xpath)).click();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = SelectComponent;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 开关组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class SwitchComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 开关组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} label 标签
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, label) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.label = label;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
if(this.label){
|
|
19
|
+
return `//*[normalize-space(text())='${this.label}']//following-sibling::div//input[@type='checkbox']`;
|
|
20
|
+
}
|
|
21
|
+
return "//input[@type='checkbox' and @class='w-switch__input']";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 打开
|
|
26
|
+
*/
|
|
27
|
+
async on() {
|
|
28
|
+
let xpath = this.getXpath();
|
|
29
|
+
let checked = Boolean(await (await this.browser.findElement(xpath)).getAttribute("checked"));
|
|
30
|
+
if (!checked) {
|
|
31
|
+
await (await this.browser.findElement(xpath)).click();
|
|
32
|
+
await this.browser.sleep(SwitchComponent.delayTime);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 关闭
|
|
38
|
+
*/
|
|
39
|
+
async off() {
|
|
40
|
+
let xpath = this.getXpath();
|
|
41
|
+
let checked = Boolean(await (await this.browser.findElement(xpath)).getAttribute("checked"));
|
|
42
|
+
if (checked) {
|
|
43
|
+
await (await this.browser.findElement(xpath)).click();
|
|
44
|
+
await this.browser.sleep(SwitchComponent.delayTime);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = SwitchComponent;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表格组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class TableComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 表格组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
*/
|
|
11
|
+
constructor(browser) {
|
|
12
|
+
super(browser);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
_createRootXpath() {
|
|
16
|
+
return "";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_createXpath() {
|
|
20
|
+
return "//*[contains(@class,'w-table ')]";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_createHeaderXapth() {
|
|
24
|
+
return "//*[contains(@class,'w-table__header-wrapper')]//thead";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
_createBodyXapth() {
|
|
28
|
+
return "//*[contains(@class,'w-table__body-wrapper')]//tbody";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 获取表格数据
|
|
33
|
+
* @returns 表格数据
|
|
34
|
+
*/
|
|
35
|
+
async getTableData() {
|
|
36
|
+
let ret = [];
|
|
37
|
+
let xpath = `(${this.getXpath()}${this._createBodyXapth()}//tr)[1]`;
|
|
38
|
+
await this.browser.waitUntilElementBeVisible(xpath);
|
|
39
|
+
await this.browser.sleep(TableComponent.delayTime);
|
|
40
|
+
// 处理表头
|
|
41
|
+
if (!this._createHeaderXapth()) {
|
|
42
|
+
return ret;
|
|
43
|
+
}
|
|
44
|
+
xpath = `(${this.getXpath()}${this._createHeaderXapth()}//tr)[1]/th`;
|
|
45
|
+
let titles = await this.browser.findElements(xpath);
|
|
46
|
+
for (let i = 0; i < titles.length; i++) {
|
|
47
|
+
titles[i] = ((await titles[i].getText(true)).replaceAll("\n", "")).trim();
|
|
48
|
+
}
|
|
49
|
+
// 处理表体
|
|
50
|
+
xpath = `${this.getXpath()}${this._createBodyXapth()}//tr[contains(@class, 'w-table__row')]`;
|
|
51
|
+
let trs = await this.browser.findElements(xpath);
|
|
52
|
+
for (let i = 0; i < trs.length; i++) {
|
|
53
|
+
xpath = `(${this.getXpath()}${this._createBodyXapth()}//tr[contains(@class, 'w-table__row')])[${i + 1}]/td`;
|
|
54
|
+
let tds = await this.browser.findElements(xpath);
|
|
55
|
+
let row = {};
|
|
56
|
+
for (let j = 0; j < tds.length; j++) {
|
|
57
|
+
let title = titles[j]
|
|
58
|
+
if (title) {
|
|
59
|
+
let text = (await tds[j].getText(true)).replaceAll("\n", " ");
|
|
60
|
+
row[title] = text;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
ret.push(row);
|
|
64
|
+
}
|
|
65
|
+
ret = ret.filter(row => {
|
|
66
|
+
let isDelete = true;
|
|
67
|
+
Object.keys(row).forEach(key => {
|
|
68
|
+
if (row[key] !== "") {
|
|
69
|
+
isDelete = false;
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
return !isDelete;
|
|
73
|
+
})
|
|
74
|
+
return ret;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 获取块组件
|
|
80
|
+
* @param {Number} rowNumber 行号
|
|
81
|
+
* @param {Number} columnNumber 列号
|
|
82
|
+
* @returns 块组件
|
|
83
|
+
*/
|
|
84
|
+
blockComponent(rowNumber, columnNumber) {
|
|
85
|
+
let that = this;
|
|
86
|
+
class _BlockComponent extends require("./BlockComponent") {
|
|
87
|
+
_createRootXpath() {
|
|
88
|
+
return "";
|
|
89
|
+
}
|
|
90
|
+
_createXpath() {
|
|
91
|
+
if (columnNumber) {
|
|
92
|
+
return `${that.getXpath()}${that._createBodyXapth()}//tr[${rowNumber}]/td[${columnNumber}]`;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return `${that.getXpath()}${that._createBodyXapth()}//tr[${rowNumber}]`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return new _BlockComponent(this.browser, null);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = TableComponent;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 文本组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class TextComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 文本组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} text 文本
|
|
11
|
+
*/
|
|
12
|
+
constructor(browser, text) {
|
|
13
|
+
super(browser);
|
|
14
|
+
this.text = text;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
_createXpath() {
|
|
18
|
+
return `//*[normalize-space(text())='${this.text}']`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = TextComponent;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多行输入框组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class TextareaComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 多行输入框组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
* @param {String} placeholder 背景文字
|
|
11
|
+
* @param {String} label 标签
|
|
12
|
+
*/
|
|
13
|
+
constructor(browser, label) {
|
|
14
|
+
super(browser);
|
|
15
|
+
this.label = label;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
_createXpath() {
|
|
19
|
+
if (this.label) {
|
|
20
|
+
return `//*[normalize-space(text())='${this.label}']/ancestor-or-self::label/..//textarea`;
|
|
21
|
+
}
|
|
22
|
+
return "//textarea"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = TextareaComponent;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 顶部菜单组件类
|
|
3
|
+
* @作者 MaoJJ
|
|
4
|
+
*/
|
|
5
|
+
class TopMenuComponent extends require("./Component") {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 顶部菜单组件
|
|
9
|
+
* @param {Browser} browser 浏览器
|
|
10
|
+
*/
|
|
11
|
+
constructor(browser, firstItem) {
|
|
12
|
+
super(browser);
|
|
13
|
+
this.firstItem = firstItem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
_createXpath() {
|
|
17
|
+
return `//*[normalize-space(text())='${this.firstItem}']/ancestor::*[contains(@class,'nav-box-item')]`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 选择菜单
|
|
22
|
+
* @param {String} menuItem 菜单项
|
|
23
|
+
*/
|
|
24
|
+
async select(menuItem) {
|
|
25
|
+
let xpath = `${this.getXpath()}//*[normalize-space(text())='${menuItem}']/ancestor::*[contains(@class,'w-menu-item')]`;
|
|
26
|
+
await (await this.browser.findElement(xpath)).click();
|
|
27
|
+
await this.browser.sleep(TopMenuComponent.delayTime);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = TopMenuComponent;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
const BlockComponent = require("../component/BlockComponent");
|
|
2
|
+
const ButtonComponent = require("../component/ButtonComponent");
|
|
3
|
+
const CheckboxComponent = require("../component/CheckboxComponent");
|
|
4
|
+
const DialogComponent = require("../component/DialogComponent");
|
|
5
|
+
const InputComponent = require("../component/InputComponent");
|
|
6
|
+
const ListComponent = require("../component/ListComponent");
|
|
7
|
+
const MessageComponent = require("../component/MessageComponent");
|
|
8
|
+
const RadioComponent = require("../component/RadioComponent");
|
|
9
|
+
const SelectComponent = require("../component/SelectComponent");
|
|
10
|
+
const SwitchComponent = require("../component/SwitchComponent");
|
|
11
|
+
const TableComponent = require("../component/TableComponent");
|
|
12
|
+
const TextareaComponent = require("../component/TextareaComponent");
|
|
13
|
+
const TextComponent = require("../component/TextComponent");
|
|
14
|
+
const TopMenuComponent = require("../component/TopMenuComponent");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 页面类
|
|
18
|
+
*/
|
|
19
|
+
class Page extends require("@winning-test/autotest-webui").Page {
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 页面类
|
|
23
|
+
* @param {Browser} browser 浏览器
|
|
24
|
+
*/
|
|
25
|
+
constructor(browser) {
|
|
26
|
+
super(browser);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 获取块组件
|
|
31
|
+
* @param {String} xpath xpath
|
|
32
|
+
* @returns 块组件
|
|
33
|
+
*/
|
|
34
|
+
blockComponent(xpath) {
|
|
35
|
+
return new BlockComponent(this.browser, xpath);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 获取按钮组件
|
|
40
|
+
* @param {String} text 文本
|
|
41
|
+
* @returns 按钮组件
|
|
42
|
+
*/
|
|
43
|
+
buttonComponent(text) {
|
|
44
|
+
return new ButtonComponent(this.browser, text);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 获取复选框组件
|
|
49
|
+
* @param {String} label 标签
|
|
50
|
+
* @returns 复选框组件
|
|
51
|
+
*/
|
|
52
|
+
checkboxComponent(label) {
|
|
53
|
+
return new CheckboxComponent(this.browser, label);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 获取对话框组件
|
|
58
|
+
* @param {String} title 标题
|
|
59
|
+
* @returns 对话框组件
|
|
60
|
+
*/
|
|
61
|
+
dialogComponent(title) {
|
|
62
|
+
return new DialogComponent(this.browser, title);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 获取输入框组件
|
|
67
|
+
* @param {String} placeholder 背景文字
|
|
68
|
+
* @param {String} label 标签
|
|
69
|
+
* @returns 输入框组件
|
|
70
|
+
*/
|
|
71
|
+
inputComponent(placeholder, label) {
|
|
72
|
+
return new InputComponent(this.browser, placeholder, label);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 获取列表组件
|
|
78
|
+
* @returns 列表组件
|
|
79
|
+
*/
|
|
80
|
+
listComponent() {
|
|
81
|
+
return new ListComponent(this.browser);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 获取消息组件
|
|
86
|
+
* @param {Stirng} text 文本
|
|
87
|
+
* @returns 消息组件
|
|
88
|
+
*/
|
|
89
|
+
messageComponent(text) {
|
|
90
|
+
return new MessageComponent(this.browser, text);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 获取单选组件
|
|
95
|
+
* @param {String} label 标签
|
|
96
|
+
* @returns 单选组件
|
|
97
|
+
*/
|
|
98
|
+
radioComponent(label) {
|
|
99
|
+
return new RadioComponent(this.browser, label);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 获取选择器组件
|
|
104
|
+
* @param {String} placeholder 背景文字
|
|
105
|
+
* @param {String} label 标签
|
|
106
|
+
* @returns 选择器组件
|
|
107
|
+
*/
|
|
108
|
+
selectComponent(placeholder, label) {
|
|
109
|
+
return new SelectComponent(this.browser, placeholder, label);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 获取开关组件
|
|
114
|
+
* @param {String} label 标签
|
|
115
|
+
* @returns 开关组件
|
|
116
|
+
*/
|
|
117
|
+
switchComponent(label) {
|
|
118
|
+
return new SwitchComponent(this.browser, label);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 获取表格组件
|
|
123
|
+
* @returns 表格组件
|
|
124
|
+
*/
|
|
125
|
+
tableComponent() {
|
|
126
|
+
return new TableComponent(this.browser);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* 获取多行文本输入组件
|
|
131
|
+
* @param {String} placeholder 背景文字
|
|
132
|
+
* @param {String} label 标签
|
|
133
|
+
* @returns 多行文本输入组件
|
|
134
|
+
*/
|
|
135
|
+
textareaComponent(label) {
|
|
136
|
+
return new TextareaComponent(this.browser, label);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 获取文本组件
|
|
141
|
+
* @param {String} text 文本
|
|
142
|
+
* @returns 文本组件
|
|
143
|
+
*/
|
|
144
|
+
textComponent(text) {
|
|
145
|
+
return new TextComponent(this.browser, text);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 获取顶部菜单组件
|
|
150
|
+
* @returns 顶部菜单组件
|
|
151
|
+
*/
|
|
152
|
+
topMenuComponent(firstItem) {
|
|
153
|
+
return new TopMenuComponent(this.browser, firstItem);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* 等待加载
|
|
158
|
+
*/
|
|
159
|
+
async loading() {
|
|
160
|
+
try {
|
|
161
|
+
const xpath = "//*[@class='w-loading-mask' and (not (ancestor-or-self::*[contains(@style,'display: none')]))]";
|
|
162
|
+
if (await this.browser.isDisplayed(xpath, 500)) {
|
|
163
|
+
await this.browser.waitUntilElementBeNotVisible(xpath);
|
|
164
|
+
}
|
|
165
|
+
await this.browser.sleep(500);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* 获取菜单组件
|
|
173
|
+
* @param {String} firstItem 大菜单项
|
|
174
|
+
* @returns 顶部菜单组件
|
|
175
|
+
*/
|
|
176
|
+
menuComponent(firstItem) {
|
|
177
|
+
let that = this;
|
|
178
|
+
class MenuComponent extends require("../component/TopMenuComponent") {
|
|
179
|
+
constructor(browser, firstItem) {
|
|
180
|
+
super(browser, firstItem);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 选择菜单
|
|
185
|
+
* @param {String} menuItem 菜单项
|
|
186
|
+
*/
|
|
187
|
+
async select(menuItem) {
|
|
188
|
+
super.select(menuItem);
|
|
189
|
+
that.loading();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
return new MenuComponent(that.browser, firstItem)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.exports = Page;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const { Browser, Key } = require("@winning-test/autotest-webui");
|
|
2
|
+
const config = require("./component.test.json");
|
|
3
|
+
const Page = require("../page/Page")
|
|
4
|
+
const browser = new Browser();
|
|
5
|
+
const func = require("./func");
|
|
6
|
+
|
|
7
|
+
beforeAll(async () => {
|
|
8
|
+
await browser.maximize();
|
|
9
|
+
await browser.get(config.url.login);
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
test.only("input/button/message", async () => {
|
|
13
|
+
const page = new Page(browser);
|
|
14
|
+
await page.inputComponent("请输入用户名").input(config.体检登录.user.admincs.用户名);
|
|
15
|
+
await page.inputComponent("请输入密码").input(config.体检登录.user.admincs.密码);
|
|
16
|
+
await page.buttonComponent("登 录").click();
|
|
17
|
+
await page.messageComponent("登录成功").waitUntilBeVisible();
|
|
18
|
+
await page.loading();
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
test("topMenu/table/dialog", async () => {
|
|
22
|
+
const page = new Page(browser);
|
|
23
|
+
await page.topMenuComponent("数据维护").select("机构配置");
|
|
24
|
+
await page.inputComponent("请输入").input("体检登记-是否自动打印个人码");
|
|
25
|
+
await page.buttonComponent('查询').click();
|
|
26
|
+
await page.loading();
|
|
27
|
+
await page.tableComponent().blockComponent(1,6).buttonComponent("修改").click();
|
|
28
|
+
await page.dialogComponent("修改机构配置").inputComponent(null, "配置项值").input(Key.CONTROL, 'a', Key.DELETE);
|
|
29
|
+
await page.dialogComponent("修改机构配置").inputComponent(null, "配置项值").input("2");
|
|
30
|
+
await page.dialogComponent("修改机构配置").buttonComponent('保存').click();
|
|
31
|
+
await page.dialogComponent("修改机构配置").waitUntilBeNotVisible();
|
|
32
|
+
await page.messageComponent("保存成功").waitUntilBeVisible();
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
test("select/input(date)/block", async () => {
|
|
36
|
+
const page = new Page(browser);
|
|
37
|
+
await page.topMenuComponent("体检登记").select("个人登记");
|
|
38
|
+
await page.buttonComponent('登记').click();
|
|
39
|
+
await page.dialogComponent('个人登记').inputComponent("请输入姓名").input(`自动化测试${func.today('MMDD')}${func.stringPad(func.dailyCount(),3)}`);
|
|
40
|
+
await page.dialogComponent("个人登记").inputComponent("请输入证件号码").input(func.idcard(), Key.ENTER);
|
|
41
|
+
await page.dialogComponent('个人登记').inputComponent("","体检日期").input(Key.CONTROL, 'a', Key.DELETE);
|
|
42
|
+
await page.dialogComponent('个人登记').inputComponent("","体检日期").input(func.dateOffset(func.today()), Key.ENTER);
|
|
43
|
+
await page.dialogComponent('个人登记').selectComponent("","体检套餐").select("自动化套餐");
|
|
44
|
+
await page.inputComponent("", "电话号码").input(func.phone());
|
|
45
|
+
await page.buttonComponent('保存').click();
|
|
46
|
+
await page.messageComponent('体检登记保存成功').waitUntilBeVisible();
|
|
47
|
+
await page.blockComponent(`//button[@aria-label='Close']`).click();
|
|
48
|
+
await page.dialogComponent('个人登记').waitUntilBeNotVisible();
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("table/input(date)/check", async () => {
|
|
52
|
+
const page = new Page(browser);
|
|
53
|
+
await page.topMenuComponent("体检登记").select("个人登记");
|
|
54
|
+
await page.inputComponent("开始日期").input(Key.CONTROL, 'a');
|
|
55
|
+
await page.inputComponent("开始日期").input(func.today(), Key.ENTER);
|
|
56
|
+
await page.inputComponent("结束日期").input(Key.CONTROL, 'a');
|
|
57
|
+
await page.inputComponent("结束日期").input(func.dateOffset(func.today(), 3), Key.ENTER);
|
|
58
|
+
await page.buttonComponent("查询").click();
|
|
59
|
+
await page.loading();
|
|
60
|
+
let tableData = await page.tableComponent().getTableData();
|
|
61
|
+
console.log(tableData);
|
|
62
|
+
await page.tableComponent().blockComponent(1,1).checkboxComponent().select();
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
test("text/table/radio/textarea", async () => {
|
|
67
|
+
const page = new Page(browser);
|
|
68
|
+
await page.topMenuComponent("医生工作站").select("分科检查");
|
|
69
|
+
await page.buttonComponent('查询').click();
|
|
70
|
+
await page.loading();
|
|
71
|
+
await page.tableComponent().blockComponent(1,10).textComponent('详情').click();
|
|
72
|
+
await page.textComponent("查询成功").waitUntilBeVisible();
|
|
73
|
+
await page.textareaComponent("小结").input(
|
|
74
|
+
'********************************************************'+
|
|
75
|
+
'********************************************************'+
|
|
76
|
+
'********************************************************'+
|
|
77
|
+
'********************************************************');
|
|
78
|
+
await page.radioComponent("每天").select();
|
|
79
|
+
await page.browser.sleep(2000);
|
|
80
|
+
await page.radioComponent("每周一次以上").select();
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
test.only("check/radio/select", async () => {
|
|
85
|
+
const page = new Page(browser);
|
|
86
|
+
await page.topMenuComponent("医生工作站").select("分科检查");
|
|
87
|
+
await page.buttonComponent('查询').click();
|
|
88
|
+
await page.loading();
|
|
89
|
+
await page.tableComponent().blockComponent(1,10).textComponent('详情').click();
|
|
90
|
+
await page.textComponent("查询成功").waitUntilBeVisible();
|
|
91
|
+
await page.buttonComponent("健康调查").click();
|
|
92
|
+
await page.dialogComponent("健康调查").waitUntilBeVisible();
|
|
93
|
+
await page.dialogComponent("健康调查").selectComponent(null, '学历').select('专科');
|
|
94
|
+
await page.checkboxComponent("教师").select();
|
|
95
|
+
await page.blockComponent(`//label[text()='过敏史']/../self::*`).checkboxComponent('青霉素').select();
|
|
96
|
+
await page.radioComponent('可自理').select();
|
|
97
|
+
await page.blockComponent(`//label[text()='运动功能评估']/../self::*`).radioComponent('可顺利完成').select();
|
|
98
|
+
|
|
99
|
+
let jzTable = page.blockComponent(`//p[contains(text(),'家族史')]/following-sibling::table`);
|
|
100
|
+
await jzTable.blockComponent(`//tr[2]/td[2]`).checkboxComponent().select();
|
|
101
|
+
await jzTable.blockComponent(`//tr[2]/td[4]`).checkboxComponent().select();
|
|
102
|
+
await jzTable.blockComponent(`//tr[3]/td[3]`).checkboxComponent().select();
|
|
103
|
+
await jzTable.blockComponent(`//tr[3]/td[5]`).checkboxComponent().select();
|
|
104
|
+
|
|
105
|
+
let mxTable = page.blockComponent(`//p[contains(text(),'慢性疾病')]/following-sibling::table`);
|
|
106
|
+
await mxTable.blockComponent(`//tr[2]/td[3]`).radioComponent().select();
|
|
107
|
+
await mxTable.blockComponent(`//tr[3]/td[4]`).radioComponent("不规律用药").select();
|
|
108
|
+
await mxTable.blockComponent(`//tr[3]/td[2]`).inputComponent(`请选择年`).input(func.today('YYYY'),Key.ENTER);
|
|
109
|
+
|
|
110
|
+
let ysTable = page.blockComponent(`//p[contains(text(),'饮食、生活行为')]/following-sibling::table`);
|
|
111
|
+
await ysTable.blockComponent(`//label[text()='是否饮酒:']/following-sibling::*`).radioComponent(`是`).select();
|
|
112
|
+
await ysTable.radioComponent(`啤酒`).select();
|
|
113
|
+
await ysTable.checkboxComponent(`嗜油`).select();
|
|
114
|
+
})
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const request = require("@winning-test/autotest-api").Request;
|
|
2
|
+
const Random = require("mockjs").Random;
|
|
3
|
+
const sd = require("silly-datetime");
|
|
4
|
+
|
|
5
|
+
const func = {
|
|
6
|
+
|
|
7
|
+
idcard: function (sex = "M", birthday = "1984-12-29") {
|
|
8
|
+
const response = request.post("http://172.16.9.53/api/getIdcard", {
|
|
9
|
+
sex,
|
|
10
|
+
birthday
|
|
11
|
+
}, { "content-type": "application/json; charset=utf-8" });
|
|
12
|
+
return JSON.parse(response.text).data;
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
phone: function () {
|
|
16
|
+
const prefix = ["133", "153", "180", "181", "189", "177", "173", "149", "130", "131", "132", "155", "156",
|
|
17
|
+
"145", "185", "186", "176", "175", "135", "136", "137", "138", "139", "150", "151", "152", "157", "158",
|
|
18
|
+
"159", "182", "183", "184", "187", "188", "147", "178"];
|
|
19
|
+
const phone = Random.pick(prefix) + String(Math.round(Math.random() * 99999999)).padStart(8, "0");
|
|
20
|
+
return phone;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
cname: function () {
|
|
24
|
+
return Random.cname();
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
address: function () {
|
|
28
|
+
const address = `${Random.cword(2)}${Random.pick(["小区", "社区", "家园", "公寓", "花园"])}${Random.integer(1, 50)}号楼${Random.integer(1, 5)}单元${Random.integer(1, 20)}室`
|
|
29
|
+
return address;
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
today: function (format = "YYYY-MM-DD") {
|
|
33
|
+
let now = new Date();
|
|
34
|
+
now = sd.format(now, format);
|
|
35
|
+
return now;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
dateOffset(date, dayOffset = 0, monthOffset = 0, format = "YYYY-MM-DD") {
|
|
39
|
+
date = new Date(date);
|
|
40
|
+
dayOffset = Number(dayOffset);
|
|
41
|
+
monthOffset = Number(monthOffset);
|
|
42
|
+
date.setDate(date.getDate() + dayOffset);
|
|
43
|
+
date.setMonth(date.getMonth() + monthOffset);
|
|
44
|
+
return sd.format(date, format);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
stringPad(str, length = 3, fillString = "0") {
|
|
48
|
+
let ret = String(str).padStart(length, fillString);
|
|
49
|
+
return ret;
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
guid: function () {
|
|
53
|
+
return Random.guid();
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
random: function (func, ...args) {
|
|
57
|
+
return Random[func](...args);
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
dailyCount() {
|
|
61
|
+
let today = sd.format(new Date(), "YYYYMMDD");
|
|
62
|
+
let response = request.post('http://172.16.9.53/api/cacheData/hash/get', {
|
|
63
|
+
"key": "winex-region",
|
|
64
|
+
"field": today
|
|
65
|
+
}, {
|
|
66
|
+
"content-type": "application/json; charset=utf-8"
|
|
67
|
+
});
|
|
68
|
+
response = JSON.parse(response.text);
|
|
69
|
+
let count = response.data || 1;
|
|
70
|
+
response = request.post('http://172.16.9.53/api/cacheData/hash/set', {
|
|
71
|
+
"key": "winex-region",
|
|
72
|
+
"field": today,
|
|
73
|
+
"value": count + 1
|
|
74
|
+
}, {
|
|
75
|
+
"content-type": "application/json; charset=utf-8"
|
|
76
|
+
});
|
|
77
|
+
return count;
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
resourceDir() {
|
|
81
|
+
const path = require("path");
|
|
82
|
+
return path.join(__dirname, "..\\resource");
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
module.exports = func;
|
|
87
|
+
|