@qavajs/cypress 0.1.0
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/CHANGELOG.md +15 -0
- package/README.md +50 -0
- package/defineQavajs.js +2 -0
- package/index.js +9 -0
- package/lib/actions.js +274 -0
- package/lib/conditionExpect.js +54 -0
- package/lib/defineQavajs.js +4 -0
- package/lib/execute.js +69 -0
- package/lib/memory.js +171 -0
- package/lib/mouseActions.js +58 -0
- package/lib/setup.js +46 -0
- package/lib/storage.js +59 -0
- package/lib/types.js +32 -0
- package/lib/utils.js +49 -0
- package/lib/validation.js +259 -0
- package/lib/valueExpect.js +84 -0
- package/lib/valueValidation.js +192 -0
- package/package.json +25 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { When } from '@qavajs/cypress-runner-adapter';
|
|
2
|
+
import { parseCoords } from './utils';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Press mouse key
|
|
6
|
+
* @param {string} button - button to press (left, right, middle)
|
|
7
|
+
* @example When I press left mouse button
|
|
8
|
+
*/
|
|
9
|
+
When('I press {mouseButton} mouse button on {string}', function (buttons, coords) {
|
|
10
|
+
const [x, y] = parseCoords(this.value(coords));
|
|
11
|
+
cy.get('body')
|
|
12
|
+
.trigger('mouseenter', x, y)
|
|
13
|
+
.trigger('mouseover', x, y)
|
|
14
|
+
.trigger('mousemove', x, y)
|
|
15
|
+
.trigger('mousedown', x, y, { buttons });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Release mouse key
|
|
20
|
+
* @param {string} button - button to release (left, right, middle)
|
|
21
|
+
* @example When I release left mouse button
|
|
22
|
+
*/
|
|
23
|
+
When('I release {mouseButton} mouse button on {string}', function (button, coords) {
|
|
24
|
+
const [x, y] = parseCoords(this.value(coords));
|
|
25
|
+
cy.get('body')
|
|
26
|
+
.trigger('mouseenter', x, y)
|
|
27
|
+
.trigger('mouseover', x, y)
|
|
28
|
+
.trigger('mousemove', x, y)
|
|
29
|
+
.trigger('mouseup', x, y, { button });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Move mouse to coordinates
|
|
34
|
+
* @param {string} coords - x, y coordinates to move
|
|
35
|
+
* @example When I move mouse to '10, 15'
|
|
36
|
+
*/
|
|
37
|
+
When('I move mouse to {string}', function (coords){
|
|
38
|
+
const [x, y] = parseCoords(this.value(coords));
|
|
39
|
+
cy.get('body')
|
|
40
|
+
.trigger('mouseenter', x, y)
|
|
41
|
+
.trigger('mouseover', x, y)
|
|
42
|
+
.trigger('mousemove', x, y);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Scroll mouse wheel by x, y offset
|
|
47
|
+
* @param {string} coords - x, y offset to scroll
|
|
48
|
+
* @example When I scroll mouse wheel by '0, 15'
|
|
49
|
+
*/
|
|
50
|
+
When('I scroll mouse wheel by {string} on {string}', function (offset, coords) {
|
|
51
|
+
const [x, y] = parseCoords(this.value(coords));
|
|
52
|
+
const [deltaX, deltaY] = parseCoords(this.value(offset));
|
|
53
|
+
cy.get('body')
|
|
54
|
+
.trigger('mouseenter', x, y)
|
|
55
|
+
.trigger('mouseover', x, y)
|
|
56
|
+
.trigger('mousemove', x, y)
|
|
57
|
+
.trigger('wheel', x, y, { deltaX, deltaY });
|
|
58
|
+
});
|
package/lib/setup.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {po} from '@qavajs/po-cypress';
|
|
2
|
+
import App from '../test-e2e/page_object';
|
|
3
|
+
import memory from '@qavajs/memory';
|
|
4
|
+
import Memory from '../test-e2e/memory';
|
|
5
|
+
import { setWorldConstructor } from '@qavajs/cypress-runner-adapter';
|
|
6
|
+
|
|
7
|
+
export class QavajsCypressWorld {
|
|
8
|
+
|
|
9
|
+
constructor() {
|
|
10
|
+
po.init(cy, { logger: { log: (value) => {
|
|
11
|
+
const [displayName, message] = value.split(/\s->\s/);
|
|
12
|
+
Cypress.log({
|
|
13
|
+
displayName,
|
|
14
|
+
message
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
po.register(window.pageObject);
|
|
20
|
+
memory.register(window.memory);
|
|
21
|
+
memory.setLogger({ log: (value) => {
|
|
22
|
+
const [displayName, message] = value.split(/\s->\s/);
|
|
23
|
+
Cypress.log({
|
|
24
|
+
displayName,
|
|
25
|
+
message
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
this.po = po;
|
|
30
|
+
this.memory = memory;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
element(alias) {
|
|
34
|
+
return this.po.getElement(this.memory.getValue(alias));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
value(expression) {
|
|
38
|
+
return this.memory.getValue(expression);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
setValue(key, value) {
|
|
42
|
+
this.memory.setValue(key, value);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
setWorldConstructor(QavajsCypressWorld);
|
package/lib/storage.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { When } from '@qavajs/cypress-runner-adapter';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Set cookie
|
|
5
|
+
* @param {string} cookie - cookie name
|
|
6
|
+
* @param {string} value - value to set
|
|
7
|
+
* @example I set 'userID' cookie 'user1'
|
|
8
|
+
* @example I set 'userID' cookie '$userIdCookie'
|
|
9
|
+
*/
|
|
10
|
+
When('I set {string} cookie as {string}', function (cookie, value) {
|
|
11
|
+
const cookieValue = this.value(value);
|
|
12
|
+
const cookieObject = typeof cookieValue === 'object' ? cookieValue : { value: cookieValue };
|
|
13
|
+
cy.setCookie(cookie, cookieObject.value, cookieObject);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Save cookie value to memory
|
|
18
|
+
* @param {string} cookie - cookie name
|
|
19
|
+
* @param {string} key - memory key
|
|
20
|
+
* @example I save value of 'auth' cookie as 'authCookie'
|
|
21
|
+
*/
|
|
22
|
+
When('I save value of {string} cookie as {string}', function (cookie, key) {
|
|
23
|
+
const cookieName = this.value(cookie);
|
|
24
|
+
cy.getCookie(cookieName).then((cookie) => {
|
|
25
|
+
this.setValue(key, cookie);
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set value of local/session storage
|
|
32
|
+
* @param {string} storageKey - local/session storage key to set value
|
|
33
|
+
* @param {string} storageType - storage type (local or session)
|
|
34
|
+
* @param {string} value - value to set
|
|
35
|
+
* @example I set 'username' local storage value as 'user1'
|
|
36
|
+
* @example I set '$sessionStorageKey' session storage value as '$sessionStorageValue'
|
|
37
|
+
*/
|
|
38
|
+
When('I set {string} {word} storage value as {string}', function (storageKey, storageType, value) {
|
|
39
|
+
const resolvedValue = this.value(value);
|
|
40
|
+
cy.window().then((win) => {
|
|
41
|
+
console.log(win)
|
|
42
|
+
win[storageType + 'Storage'].setItem(storageKey, resolvedValue);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Save value of local/session storage to memory
|
|
48
|
+
* @param {string} storageKey - local/session storage key to set value
|
|
49
|
+
* @param {string} storageType - storage type (local or session)
|
|
50
|
+
* @param {string} key - memory key
|
|
51
|
+
* @example I save value of 'username' local storage as 'localStorageValue'
|
|
52
|
+
* @example I save value of '$sessionStorageKey' session storage value as 'sessionStorageValue'
|
|
53
|
+
*/
|
|
54
|
+
When('I save value of {string} {word} storage as {string}', function (storageKey, storageType, key) {
|
|
55
|
+
const resolvedStorageKey = this.value(storageKey);
|
|
56
|
+
cy.window().then((win) => {
|
|
57
|
+
this.setValue(key, win[storageType + 'Storage'].getItem(resolvedStorageKey));
|
|
58
|
+
});
|
|
59
|
+
});
|
package/lib/types.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineParameterType } from '@qavajs/cypress-runner-adapter';
|
|
2
|
+
|
|
3
|
+
defineParameterType({
|
|
4
|
+
name: 'validation',
|
|
5
|
+
regexp: /((?:is |do |does |to )?(not |to not )?(?:to )?(?:be )?(equal|strictly equal|deeply equal|have member|match|contain|above|below|greater than|less than|have type)(?:s|es)?)/,
|
|
6
|
+
useForSnippets: false
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
defineParameterType({
|
|
10
|
+
name: 'conditionExpect',
|
|
11
|
+
regexp: /((not )?to (?:be )?(present|clickable|visible|invisible|enabled|disabled|in viewport))/,
|
|
12
|
+
useForSnippets: false
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
defineParameterType({
|
|
16
|
+
name: 'poType',
|
|
17
|
+
regexp: /(element|collection)/,
|
|
18
|
+
useForSnippets: false
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
defineParameterType({
|
|
22
|
+
name: 'mouseButton',
|
|
23
|
+
regexp: /(left|right|middle)/,
|
|
24
|
+
transformer: button => ({ left: 1, right: 2, middle: 4 }[button]),
|
|
25
|
+
useForSnippets: false
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
defineParameterType({
|
|
29
|
+
name: 'browserButton',
|
|
30
|
+
regexp: /(back|forward)/,
|
|
31
|
+
useForSnippets: false
|
|
32
|
+
});
|
package/lib/utils.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse 'x, y' string to coordinates array
|
|
3
|
+
* @param {string} coords - 'x, y' string
|
|
4
|
+
* @return {number[]} - coords array
|
|
5
|
+
*/
|
|
6
|
+
export function parseCoords(coords) {
|
|
7
|
+
return coords.split(/\s?,\s?/).map(c => parseFloat(c ?? 0))
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function equalOrIncludes(value, argument) {
|
|
11
|
+
return Array.isArray(value)
|
|
12
|
+
? value.includes(argument)
|
|
13
|
+
: value === argument;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function throwTimeoutError(fn, message) {
|
|
17
|
+
try {
|
|
18
|
+
await fn()
|
|
19
|
+
} catch (err) {
|
|
20
|
+
if (err.message.includes('exceeded while waiting on the predicate')) {
|
|
21
|
+
throw new Error(message);
|
|
22
|
+
}
|
|
23
|
+
throw err
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Transform key-value data table to JS object
|
|
29
|
+
* @param ctx
|
|
30
|
+
* @param dataTable
|
|
31
|
+
* @return {Object}
|
|
32
|
+
*/
|
|
33
|
+
export async function dataTable2Object(ctx, dataTable) {
|
|
34
|
+
const obj = {};
|
|
35
|
+
for (const [key, value] of dataTable.raw()) {
|
|
36
|
+
obj[key] = await ctx.value(value);
|
|
37
|
+
}
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Transform key-value data table to array
|
|
43
|
+
* @param ctx
|
|
44
|
+
* @param dataTable
|
|
45
|
+
* @return {any[]}
|
|
46
|
+
*/
|
|
47
|
+
export function dataTable2Array(ctx, dataTable) {
|
|
48
|
+
return dataTable.raw().map(([value]) => ctx.value(value));
|
|
49
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { Then } from '@qavajs/cypress-runner-adapter';
|
|
2
|
+
import { getValidation } from './valueExpect';
|
|
3
|
+
import { getConditionExpect } from './conditionExpect';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Verify element condition
|
|
7
|
+
* @param {string} alias - element to wait condition
|
|
8
|
+
* @param {string} condition - wait condition
|
|
9
|
+
* @example I expect 'Header' to be visible
|
|
10
|
+
* @example I expect 'Loading' not to be present
|
|
11
|
+
* @example I expect 'Search Bar > Submit Button' to be clickable
|
|
12
|
+
*/
|
|
13
|
+
Then('I expect {string} {conditionExpect}', function (alias, condition) {
|
|
14
|
+
const chainer = getConditionExpect(condition);
|
|
15
|
+
const element = this.element(alias);
|
|
16
|
+
element.should(chainer)
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Verify that text of element satisfies condition
|
|
21
|
+
* @param {string} alias - element to get text
|
|
22
|
+
* @param {string} validationType - validation
|
|
23
|
+
* @param {string} value - expected result
|
|
24
|
+
* @example I expect text of '#1 of Search Results' equals to 'google'
|
|
25
|
+
* @example I expect text of '#2 of Search Results' does not contain 'yandex'
|
|
26
|
+
*/
|
|
27
|
+
Then(
|
|
28
|
+
'I expect text of {string} {validation} {string}',
|
|
29
|
+
function (alias, validationType, value) {
|
|
30
|
+
const expectedValue = this.value(value);
|
|
31
|
+
const element = this.element(alias);
|
|
32
|
+
const validation = getValidation(validationType);
|
|
33
|
+
element.should((e) => {
|
|
34
|
+
validation(e.text(), expectedValue);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Verify that value of element satisfies condition
|
|
41
|
+
* @param {string} alias - element to get text
|
|
42
|
+
* @param {string} validationType - validation
|
|
43
|
+
* @param {string} value - expected result
|
|
44
|
+
* @example I expect value of '#1 of Search Results' equals to 'google'
|
|
45
|
+
* @example I expect value of '#2 of Search Results' does not contain 'yandex'
|
|
46
|
+
*/
|
|
47
|
+
Then(
|
|
48
|
+
'I expect value of {string} {validation} {string}',
|
|
49
|
+
function (alias, validationType, value) {
|
|
50
|
+
const expectedValue = this.value(value);
|
|
51
|
+
const element = this.element(alias);
|
|
52
|
+
const validation = getValidation(validationType);
|
|
53
|
+
element.should((e) => {
|
|
54
|
+
validation(e.val(), expectedValue);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Verify that property of element satisfies condition
|
|
61
|
+
* @param {string} property - element to verify
|
|
62
|
+
* @param {string} alias - element to verify
|
|
63
|
+
* @param {string} validationType - validation
|
|
64
|
+
* @param {string} value - expected value
|
|
65
|
+
* @example I expect 'value' property of 'Search Input' to be equal 'text'
|
|
66
|
+
* @example I expect 'innerHTML' property of 'Label' to contain '<b>'
|
|
67
|
+
*/
|
|
68
|
+
Then(
|
|
69
|
+
'I expect {string} property of {string} {validation} {string}',
|
|
70
|
+
function (property, alias, validationType, value) {
|
|
71
|
+
const propertyName = this.value(property);
|
|
72
|
+
const expectedValue = this.value(value);
|
|
73
|
+
const element = this.element(alias);
|
|
74
|
+
const validation = getValidation(validationType);
|
|
75
|
+
element.should((e) => {
|
|
76
|
+
validation(e.prop(propertyName), expectedValue);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Verify that attribute of element satisfies condition
|
|
83
|
+
* @param {string} attribute - element to verify
|
|
84
|
+
* @param {string} alias - element to verify
|
|
85
|
+
* @param {string} validationType - validation
|
|
86
|
+
* @param {string} value - expected value
|
|
87
|
+
* @example I expect 'href' attribute of 'Home Link' to contain '/home'
|
|
88
|
+
*/
|
|
89
|
+
Then(
|
|
90
|
+
'I expect {string} attribute of {string} {validation} {string}',
|
|
91
|
+
function (attribute, alias, validationType, value) {
|
|
92
|
+
const attributeName = this.value(attribute);
|
|
93
|
+
const expectedValue = this.value(value);
|
|
94
|
+
const element = this.element(alias);
|
|
95
|
+
const validation = getValidation(validationType);
|
|
96
|
+
element.should((e) => {
|
|
97
|
+
validation(e.attr(attributeName), expectedValue);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Verify that current url satisfies condition
|
|
104
|
+
* @param {string} validationType - validation
|
|
105
|
+
* @param {string} expected - expected value
|
|
106
|
+
* @example I expect current url contains 'wikipedia'
|
|
107
|
+
* @example I expect current url equals 'https://wikipedia.org'
|
|
108
|
+
*/
|
|
109
|
+
Then(
|
|
110
|
+
'I expect current url {validation} {string}',
|
|
111
|
+
function (validationType, expected) {
|
|
112
|
+
const validation = getValidation(validationType);
|
|
113
|
+
const expectedUrl = this.value(expected);
|
|
114
|
+
cy.url().should((actualUrl) => {
|
|
115
|
+
validation(actualUrl, expectedUrl);
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Verify that number of element in collection satisfies condition
|
|
122
|
+
* @param {string} alias - collection to verify
|
|
123
|
+
* @param {string} validationType - validation
|
|
124
|
+
* @param {string} value - expected value
|
|
125
|
+
* @example I expect number of elements in 'Search Results' collection to be equal '50'
|
|
126
|
+
* @example I expect number of elements in 'Search Results' collection to be above '49'
|
|
127
|
+
* @example I expect number of elements in 'Search Results' collection to be below '51'
|
|
128
|
+
*/
|
|
129
|
+
Then(
|
|
130
|
+
'I expect number of elements in {string} collection {validation} {string}',
|
|
131
|
+
function (alias, validationType, value) {
|
|
132
|
+
const expectedValue = this.value(value);
|
|
133
|
+
const collection = this.element(alias);
|
|
134
|
+
const validation = getValidation(validationType);
|
|
135
|
+
collection.should((collection) => {
|
|
136
|
+
validation(collection.length, expectedValue);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Verify that page title satisfies condition
|
|
143
|
+
* @param {string} validationType - validation
|
|
144
|
+
* @param {string} expected - expected value
|
|
145
|
+
* @example I expect page title equals 'Wikipedia'
|
|
146
|
+
*/
|
|
147
|
+
Then(
|
|
148
|
+
'I expect page title {validation} {string}',
|
|
149
|
+
function (validationType, expected) {
|
|
150
|
+
const validation = getValidation(validationType);
|
|
151
|
+
const expectedTitle = this.value(expected);
|
|
152
|
+
cy.title().should((actualTitle) => {
|
|
153
|
+
validation(actualTitle, expectedTitle);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Verify that all texts in collection satisfy condition
|
|
160
|
+
* @param {string} alias - collection to get texts
|
|
161
|
+
* @param {string} validationType - validation
|
|
162
|
+
* @param {string} value - expected result
|
|
163
|
+
* @example I expect text of every element in 'Search Results' collection equals to 'google'
|
|
164
|
+
* @example I expect text of every element in 'Search Results' collection does not contain 'yandex'
|
|
165
|
+
*/
|
|
166
|
+
Then(
|
|
167
|
+
'I expect text of every element in {string} collection {validation} {string}',
|
|
168
|
+
function (alias, validationType, value) {
|
|
169
|
+
const expectedValue = this.value(value);
|
|
170
|
+
const collection = this.element(alias);
|
|
171
|
+
const validation = getValidation(validationType);
|
|
172
|
+
collection.each((element) => {
|
|
173
|
+
validation(element.text(), expectedValue);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Verify that all particular attributes in collection satisfy condition
|
|
180
|
+
* @param {string} alias - collection to get attrs
|
|
181
|
+
* @param {string} validationType - validation
|
|
182
|
+
* @param {string} value - expected result
|
|
183
|
+
* @example I expect 'href' attribute of every element in 'Search Results' collection to contain 'google'
|
|
184
|
+
*/
|
|
185
|
+
Then(
|
|
186
|
+
'I expect {string} attribute of every element in {string} collection {validation} {string}',
|
|
187
|
+
function (attribute, alias, validationType, value) {
|
|
188
|
+
const expectedValue = this.value(value);
|
|
189
|
+
const collection = this.element(alias);
|
|
190
|
+
const validation = getValidation(validationType);
|
|
191
|
+
collection.each((element) => {
|
|
192
|
+
validation(element.attr(attribute), expectedValue);
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Verify that all particular properties in collection satisfy condition
|
|
199
|
+
* @param {string} alias - collection to get props
|
|
200
|
+
* @param {string} validationType - validation
|
|
201
|
+
* @param {string} value - expected result
|
|
202
|
+
* @example I expect 'href' property of every element in 'Search Results' collection to contain 'google'
|
|
203
|
+
*/
|
|
204
|
+
Then(
|
|
205
|
+
'I expect {string} property of every element in {string} collection {validation} {string}',
|
|
206
|
+
function (property, alias, validationType, value) {
|
|
207
|
+
const expectedValue = this.value(value);
|
|
208
|
+
const collection = this.element(alias);
|
|
209
|
+
const validation = getValidation(validationType);
|
|
210
|
+
collection.each((element) => {
|
|
211
|
+
validation(element.prop(property), expectedValue);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Verify that css property of element satisfies condition
|
|
218
|
+
* @param {string} property - element to verify
|
|
219
|
+
* @param {string} alias - element to verify
|
|
220
|
+
* @param {string} validationType - validation
|
|
221
|
+
* @param {string} value - expected value
|
|
222
|
+
* @example I expect 'color' css property of 'Search Input' to be equal 'rgb(42, 42, 42)'
|
|
223
|
+
* @example I expect 'font-family' css property of 'Label' to contain 'Fira'
|
|
224
|
+
*/
|
|
225
|
+
Then(
|
|
226
|
+
'I expect {string} css property of {string} {validation} {string}',
|
|
227
|
+
function (property, alias, validationType, value) {
|
|
228
|
+
const propertyName = this.value(property);
|
|
229
|
+
const expectedValue = this.value(value);
|
|
230
|
+
const element = this.element(alias);
|
|
231
|
+
const validation = getValidation(validationType);
|
|
232
|
+
element.should((e) => {
|
|
233
|
+
validation(e.css(propertyName), expectedValue);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Verify that text of an alert meets expectation
|
|
240
|
+
* @param {string} validationType - validation
|
|
241
|
+
* @param {string} value - expected text value
|
|
242
|
+
* @example I expect text of alert does not contain 'coffee'
|
|
243
|
+
*/
|
|
244
|
+
Then(
|
|
245
|
+
'I expect text of alert {validation} {string}',
|
|
246
|
+
function (validationType, expectedValue) {
|
|
247
|
+
const validation = getValidation(validationType);
|
|
248
|
+
const alertHandler = new Cypress.Promise((resolve, reject) => {
|
|
249
|
+
cy.on('window:alert', (alertText)=> {
|
|
250
|
+
resolve(alertText)
|
|
251
|
+
});
|
|
252
|
+
cy.on('window:confirm', (alertText)=> {
|
|
253
|
+
resolve(alertText)
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
return alertHandler.then(alertText => { validation(alertText, expectedValue) })
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
chai.Assertion.addMethod('notStrictEqual', function (ER) {
|
|
2
|
+
const obj = this._obj;
|
|
3
|
+
|
|
4
|
+
this.assert(
|
|
5
|
+
obj == ER,
|
|
6
|
+
'expected #{this} to equal #{exp}',
|
|
7
|
+
'expected #{this} to not equal #{exp}',
|
|
8
|
+
ER,
|
|
9
|
+
obj
|
|
10
|
+
);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const validations = {
|
|
14
|
+
EQUAL: 'equal',
|
|
15
|
+
DEEPLY_EQUAL: 'deeply equal',
|
|
16
|
+
STRICTLY_EQUAL: 'strictly equal',
|
|
17
|
+
HAVE_MEMBERS: 'have member',
|
|
18
|
+
MATCH: 'match',
|
|
19
|
+
CONTAIN: 'contain',
|
|
20
|
+
ABOVE: 'above',
|
|
21
|
+
BELOW: 'below',
|
|
22
|
+
GREATER: 'greater than',
|
|
23
|
+
LESS: 'less than',
|
|
24
|
+
HAVE_TYPE: 'have type',
|
|
25
|
+
INCLUDE_MEMBERS: 'include member',
|
|
26
|
+
HAVE_PROPERTY: 'have property'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const isClause = '(?:is |do |does |to )?';
|
|
30
|
+
const notClause = '(?<reverse>not |to not )?';
|
|
31
|
+
const toBeClause = '(?:to )?(?:be )?';
|
|
32
|
+
const validationClause = `(?:(?<validation>${Object.values(validations).join('|')})(?:s|es)?)`;
|
|
33
|
+
|
|
34
|
+
export const validationExtractRegexp = new RegExp(`^${isClause}${notClause}${toBeClause}${validationClause}$`);
|
|
35
|
+
export const validationRegexp = new RegExp(`(${isClause}${notClause}${toBeClause}${validationClause})`);
|
|
36
|
+
|
|
37
|
+
const aboveFn = (expectClause, ER) => expectClause.above(toNumber(ER));
|
|
38
|
+
const belowFn = (expectClause, ER) => expectClause.below(toNumber(ER));
|
|
39
|
+
const validationFns = {
|
|
40
|
+
[validations.EQUAL]: (expectClause, ER) => expectClause.notStrictEqual(ER),
|
|
41
|
+
[validations.STRICTLY_EQUAL]: (expectClause, ER) => expectClause.equal(ER),
|
|
42
|
+
[validations.DEEPLY_EQUAL]: (expectClause, ER) => expectClause.eql(ER),
|
|
43
|
+
[validations.HAVE_MEMBERS]: (expectClause, ER) => expectClause.have.members(ER),
|
|
44
|
+
[validations.MATCH]: (expectClause, ER) => expectClause.match(toRegexp(ER)),
|
|
45
|
+
[validations.CONTAIN]: (expectClause, ER) => expectClause.contain(ER),
|
|
46
|
+
[validations.ABOVE]: aboveFn,
|
|
47
|
+
[validations.BELOW]: belowFn,
|
|
48
|
+
[validations.GREATER]: aboveFn,
|
|
49
|
+
[validations.LESS]: belowFn,
|
|
50
|
+
[validations.HAVE_TYPE]: (expectClause, ER) => expectClause.a(ER),
|
|
51
|
+
[validations.INCLUDE_MEMBERS]: (expectClause, ER) => expectClause.include.members(ER),
|
|
52
|
+
[validations.HAVE_PROPERTY]: (expectClause, ER) => expectClause.have.property(ER),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Basic verification function
|
|
57
|
+
* @param {Object} object with all needed data for validation
|
|
58
|
+
*/
|
|
59
|
+
export function verify({ AR, ER, validation, reverse }) {
|
|
60
|
+
const expectClause = reverse ? expect(AR).to.not : expect(AR).to;
|
|
61
|
+
const validate = validationFns[validation];
|
|
62
|
+
validate(expectClause, ER);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getValidation(validationType) {
|
|
66
|
+
const match = validationExtractRegexp.exec(validationType);
|
|
67
|
+
if (!match) throw new Error(`validation '${validationType}' is not supported`);
|
|
68
|
+
const { reverse, validation } = match.groups;
|
|
69
|
+
return function (AR, ER) {
|
|
70
|
+
verify({ AR, ER, validation, reverse: Boolean(reverse) });
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function toNumber(n) {
|
|
75
|
+
const parsedNumber = parseFloat(n);
|
|
76
|
+
if (Number.isNaN(parsedNumber)) {
|
|
77
|
+
throw new Error(`${n} is not a number`);
|
|
78
|
+
}
|
|
79
|
+
return parsedNumber
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function toRegexp(r) {
|
|
83
|
+
return r instanceof RegExp ? r : RegExp(r)
|
|
84
|
+
}
|