cypress-cli-select 1.0.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/.github/workflows/jest.yml +12 -0
- package/CONTRIBUTING.md +39 -0
- package/LICENSE.md +21 -0
- package/README.md +197 -0
- package/assets/choose-spec-pattern-demo.gif +0 -0
- package/assets/cypress-cli-select-animated.gif +0 -0
- package/assets/print-selected-demo.png +0 -0
- package/assets/run-help.gif +0 -0
- package/assets/run-spec-tag.gif +0 -0
- package/assets/run-spec-title.gif +0 -0
- package/cypress/e2e/1-getting-started/todo.cy.js +143 -0
- package/cypress/e2e/2-advanced-examples/actions.cy.js +321 -0
- package/cypress/e2e/2-advanced-examples/aliasing.cy.js +39 -0
- package/cypress/e2e/2-advanced-examples/assertions.cy.js +176 -0
- package/cypress/e2e/2-advanced-examples/connectors.cy.js +98 -0
- package/cypress/e2e/2-advanced-examples/cookies.cy.js +118 -0
- package/cypress/e2e/2-advanced-examples/cypress_api.cy.js +211 -0
- package/cypress/e2e/2-advanced-examples/location.cy.js +32 -0
- package/cypress/e2e/2-advanced-examples/misc.cy.js +90 -0
- package/cypress/e2e/2-advanced-examples/navigation.cy.js +55 -0
- package/cypress/e2e/2-advanced-examples/network_requests.cy.js +163 -0
- package/cypress/e2e/2-advanced-examples/querying.cy.js +114 -0
- package/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +220 -0
- package/cypress/e2e/2-advanced-examples/storage.cy.js +117 -0
- package/cypress/e2e/2-advanced-examples/traversal.cy.js +126 -0
- package/cypress/e2e/2-advanced-examples/utilities.cy.js +109 -0
- package/cypress/e2e/2-advanced-examples/viewport.cy.js +58 -0
- package/cypress/e2e/2-advanced-examples/waiting.cy.js +30 -0
- package/cypress/e2e/2-advanced-examples/window.cy.js +22 -0
- package/cypress/support/commands.js +25 -0
- package/cypress/support/component-index.html +14 -0
- package/cypress/support/component.js +24 -0
- package/cypress/support/e2e.js +19 -0
- package/cypress.config.js +25 -0
- package/cypress.new.config.js +26 -0
- package/index.js +586 -0
- package/package.json +46 -0
- package/src/components/Clock.cy.js +13 -0
- package/src/components/Stepper.cy.js +13 -0
- package/src/sortable-list.js +82 -0
- package/tapes/run-help.tape +94 -0
- package/tapes/run-spec-tag.tape +163 -0
- package/tapes/run-spec-title.tape +191 -0
- package/tests/cli-component.spec.js +409 -0
- package/tests/cli-e2e.spec.js +439 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Querying', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/querying')
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
// The most commonly used query is 'cy.get()', you can
|
|
9
|
+
// think of this like the '$' in jQuery
|
|
10
|
+
|
|
11
|
+
it('cy.get() - query DOM elements', () => {
|
|
12
|
+
// https://on.cypress.io/get
|
|
13
|
+
|
|
14
|
+
cy.get('#query-btn').should('contain', 'Button')
|
|
15
|
+
|
|
16
|
+
cy.get('.query-btn').should('contain', 'Button')
|
|
17
|
+
|
|
18
|
+
cy.get('#querying .well>button:first').should('contain', 'Button')
|
|
19
|
+
// ↲
|
|
20
|
+
// Use CSS selectors just like jQuery
|
|
21
|
+
|
|
22
|
+
cy.get('[data-test-id="test-example"]').should('have.class', 'example')
|
|
23
|
+
|
|
24
|
+
// 'cy.get()' yields jQuery object, you can get its attribute
|
|
25
|
+
// by invoking `.attr()` method
|
|
26
|
+
cy.get('[data-test-id="test-example"]')
|
|
27
|
+
.invoke('attr', 'data-test-id')
|
|
28
|
+
.should('equal', 'test-example')
|
|
29
|
+
|
|
30
|
+
// or you can get element's CSS property
|
|
31
|
+
cy.get('[data-test-id="test-example"]')
|
|
32
|
+
.invoke('css', 'position')
|
|
33
|
+
.should('equal', 'static')
|
|
34
|
+
|
|
35
|
+
// or use assertions directly during 'cy.get()'
|
|
36
|
+
// https://on.cypress.io/assertions
|
|
37
|
+
cy.get('[data-test-id="test-example"]')
|
|
38
|
+
.should('have.attr', 'data-test-id', 'test-example')
|
|
39
|
+
.and('have.css', 'position', 'static')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('cy.contains() - query DOM elements with matching content', () => {
|
|
43
|
+
// https://on.cypress.io/contains
|
|
44
|
+
cy.get('.query-list')
|
|
45
|
+
.contains('bananas')
|
|
46
|
+
.should('have.class', 'third')
|
|
47
|
+
|
|
48
|
+
// we can pass a regexp to `.contains()`
|
|
49
|
+
cy.get('.query-list')
|
|
50
|
+
.contains(/^b\w+/)
|
|
51
|
+
.should('have.class', 'third')
|
|
52
|
+
|
|
53
|
+
cy.get('.query-list')
|
|
54
|
+
.contains('apples')
|
|
55
|
+
.should('have.class', 'first')
|
|
56
|
+
|
|
57
|
+
// passing a selector to contains will
|
|
58
|
+
// yield the selector containing the text
|
|
59
|
+
cy.get('#querying')
|
|
60
|
+
.contains('ul', 'oranges')
|
|
61
|
+
.should('have.class', 'query-list')
|
|
62
|
+
|
|
63
|
+
cy.get('.query-button')
|
|
64
|
+
.contains('Save Form')
|
|
65
|
+
.should('have.class', 'btn')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('.within() - query DOM elements within a specific element', () => {
|
|
69
|
+
// https://on.cypress.io/within
|
|
70
|
+
cy.get('.query-form').within(() => {
|
|
71
|
+
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
|
|
72
|
+
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('cy.root() - query the root DOM element', () => {
|
|
77
|
+
// https://on.cypress.io/root
|
|
78
|
+
|
|
79
|
+
// By default, root is the document
|
|
80
|
+
cy.root().should('match', 'html')
|
|
81
|
+
|
|
82
|
+
cy.get('.query-ul').within(() => {
|
|
83
|
+
// In this within, the root is now the ul DOM element
|
|
84
|
+
cy.root().should('have.class', 'query-ul')
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('best practices - selecting elements', () => {
|
|
89
|
+
// https://on.cypress.io/best-practices#Selecting-Elements
|
|
90
|
+
cy.get('[data-cy=best-practices-selecting-elements]').within(() => {
|
|
91
|
+
// Worst - too generic, no context
|
|
92
|
+
cy.get('button').click()
|
|
93
|
+
|
|
94
|
+
// Bad. Coupled to styling. Highly subject to change.
|
|
95
|
+
cy.get('.btn.btn-large').click()
|
|
96
|
+
|
|
97
|
+
// Average. Coupled to the `name` attribute which has HTML semantics.
|
|
98
|
+
cy.get('[name=submission]').click()
|
|
99
|
+
|
|
100
|
+
// Better. But still coupled to styling or JS event listeners.
|
|
101
|
+
cy.get('#main').click()
|
|
102
|
+
|
|
103
|
+
// Slightly better. Uses an ID but also ensures the element
|
|
104
|
+
// has an ARIA role attribute
|
|
105
|
+
cy.get('#main[role=button]').click()
|
|
106
|
+
|
|
107
|
+
// Much better. But still coupled to text content that may change.
|
|
108
|
+
cy.contains('Submit').click()
|
|
109
|
+
|
|
110
|
+
// Best. Insulated from all changes.
|
|
111
|
+
cy.get('[data-cy=submit]').click()
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
})
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context("Spies, Stubs, and Clock", () => {
|
|
4
|
+
it("cy.spy() - wrap a method in a spy", () => {
|
|
5
|
+
// https://on.cypress.io/spy
|
|
6
|
+
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
|
7
|
+
|
|
8
|
+
const obj = {
|
|
9
|
+
foo() {},
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const spy = cy.spy(obj, "foo").as("anyArgs");
|
|
13
|
+
|
|
14
|
+
obj.foo();
|
|
15
|
+
|
|
16
|
+
expect(spy).to.be.called;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it(
|
|
20
|
+
"cy.spy() retries until assertions pass",
|
|
21
|
+
{ tags: ["@smoke", "@p2"] },
|
|
22
|
+
() => {
|
|
23
|
+
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
|
24
|
+
|
|
25
|
+
const obj = {
|
|
26
|
+
/**
|
|
27
|
+
* Prints the argument passed
|
|
28
|
+
* @param x {any}
|
|
29
|
+
*/
|
|
30
|
+
foo(x) {
|
|
31
|
+
console.log("obj.foo called with", x);
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
cy.spy(obj, "foo").as("foo");
|
|
36
|
+
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
obj.foo("first");
|
|
39
|
+
}, 500);
|
|
40
|
+
|
|
41
|
+
setTimeout(() => {
|
|
42
|
+
obj.foo("second");
|
|
43
|
+
}, 2500);
|
|
44
|
+
|
|
45
|
+
cy.get("@foo").should("have.been.calledTwice");
|
|
46
|
+
},
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
it("cy.stub() - create a stub and/or replace a function with stub", () => {
|
|
50
|
+
// https://on.cypress.io/stub
|
|
51
|
+
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
|
52
|
+
|
|
53
|
+
const obj = {
|
|
54
|
+
/**
|
|
55
|
+
* prints both arguments to the console
|
|
56
|
+
* @param a {string}
|
|
57
|
+
* @param b {string}
|
|
58
|
+
*/
|
|
59
|
+
foo(a, b) {
|
|
60
|
+
console.log("a", a, "b", b);
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const stub = cy.stub(obj, "foo").as("foo");
|
|
65
|
+
|
|
66
|
+
obj.foo("foo", "bar");
|
|
67
|
+
|
|
68
|
+
expect(stub).to.be.called;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("cy.clock() - control time in the browser", () => {
|
|
72
|
+
// https://on.cypress.io/clock
|
|
73
|
+
|
|
74
|
+
// create the date in UTC so it's always the same
|
|
75
|
+
// no matter what local timezone the browser is running in
|
|
76
|
+
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
|
|
77
|
+
|
|
78
|
+
cy.clock(now);
|
|
79
|
+
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
|
80
|
+
cy.get("#clock-div").click();
|
|
81
|
+
cy.get("#clock-div").should("have.text", "1489449600");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it("cy.tick() - move time in the browser", () => {
|
|
85
|
+
// https://on.cypress.io/tick
|
|
86
|
+
|
|
87
|
+
// create the date in UTC so it's always the same
|
|
88
|
+
// no matter what local timezone the browser is running in
|
|
89
|
+
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
|
|
90
|
+
|
|
91
|
+
cy.clock(now);
|
|
92
|
+
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
|
93
|
+
cy.get("#tick-div").click();
|
|
94
|
+
cy.get("#tick-div").should("have.text", "1489449600");
|
|
95
|
+
|
|
96
|
+
cy.tick(10000); // 10 seconds passed
|
|
97
|
+
cy.get("#tick-div").click();
|
|
98
|
+
cy.get("#tick-div").should("have.text", "1489449610");
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it("cy.stub() matches depending on arguments", () => {
|
|
102
|
+
// see all possible matchers at
|
|
103
|
+
// https://sinonjs.org/releases/latest/matchers/
|
|
104
|
+
const greeter = {
|
|
105
|
+
/**
|
|
106
|
+
* Greets a person
|
|
107
|
+
* @param {string} name
|
|
108
|
+
*/
|
|
109
|
+
greet(name) {
|
|
110
|
+
return `Hello, ${name}!`;
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
cy.stub(greeter, "greet")
|
|
115
|
+
.callThrough() // if you want non-matched calls to call the real method
|
|
116
|
+
.withArgs(Cypress.sinon.match.string)
|
|
117
|
+
.returns("Hi")
|
|
118
|
+
.withArgs(Cypress.sinon.match.number)
|
|
119
|
+
.throws(new Error("Invalid name"));
|
|
120
|
+
|
|
121
|
+
expect(greeter.greet("World")).to.equal("Hi");
|
|
122
|
+
expect(() => greeter.greet(42)).to.throw("Invalid name");
|
|
123
|
+
expect(greeter.greet).to.have.been.calledTwice;
|
|
124
|
+
|
|
125
|
+
// non-matched calls goes the actual method
|
|
126
|
+
expect(greeter.greet()).to.equal("Hello, undefined!");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("matches call arguments using Sinon matchers", () => {
|
|
130
|
+
// see all possible matchers at
|
|
131
|
+
// https://sinonjs.org/releases/latest/matchers/
|
|
132
|
+
const calculator = {
|
|
133
|
+
/**
|
|
134
|
+
* returns the sum of two arguments
|
|
135
|
+
* @param a {number}
|
|
136
|
+
* @param b {number}
|
|
137
|
+
*/
|
|
138
|
+
add(a, b) {
|
|
139
|
+
return a + b;
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
const spy = cy.spy(calculator, "add").as("add");
|
|
144
|
+
|
|
145
|
+
expect(calculator.add(2, 3)).to.equal(5);
|
|
146
|
+
|
|
147
|
+
// if we want to assert the exact values used during the call
|
|
148
|
+
expect(spy).to.be.calledWith(2, 3);
|
|
149
|
+
|
|
150
|
+
// let's confirm "add" method was called with two numbers
|
|
151
|
+
expect(spy).to.be.calledWith(
|
|
152
|
+
Cypress.sinon.match.number,
|
|
153
|
+
Cypress.sinon.match.number,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
// alternatively, provide the value to match
|
|
157
|
+
expect(spy).to.be.calledWith(
|
|
158
|
+
Cypress.sinon.match(2),
|
|
159
|
+
Cypress.sinon.match(3),
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// match any value
|
|
163
|
+
expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3);
|
|
164
|
+
|
|
165
|
+
// match any value from a list
|
|
166
|
+
expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3);
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Returns true if the given number is even
|
|
170
|
+
* @param {number} x
|
|
171
|
+
*/
|
|
172
|
+
const isEven = (x) => x % 2 === 0;
|
|
173
|
+
|
|
174
|
+
// expect the value to pass a custom predicate function
|
|
175
|
+
// the second argument to "sinon.match(predicate, message)" is
|
|
176
|
+
// shown if the predicate does not pass and assertion fails
|
|
177
|
+
expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, "isEven"), 3);
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Returns a function that checks if a given number is larger than the limit
|
|
181
|
+
* @param {number} limit
|
|
182
|
+
* @returns {(x: number) => boolean}
|
|
183
|
+
*/
|
|
184
|
+
const isGreaterThan = (limit) => (x) => x > limit;
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Returns a function that checks if a given number is less than the limit
|
|
188
|
+
* @param {number} limit
|
|
189
|
+
* @returns {(x: number) => boolean}
|
|
190
|
+
*/
|
|
191
|
+
const isLessThan = (limit) => (x) => x < limit;
|
|
192
|
+
|
|
193
|
+
// you can combine several matchers using "and", "or"
|
|
194
|
+
expect(spy).to.be.calledWith(
|
|
195
|
+
Cypress.sinon.match.number,
|
|
196
|
+
Cypress.sinon
|
|
197
|
+
.match(isGreaterThan(2), "> 2")
|
|
198
|
+
.and(Cypress.sinon.match(isLessThan(4), "< 4")),
|
|
199
|
+
);
|
|
200
|
+
|
|
201
|
+
expect(spy).to.be.calledWith(
|
|
202
|
+
Cypress.sinon.match.number,
|
|
203
|
+
Cypress.sinon
|
|
204
|
+
.match(isGreaterThan(200), "> 200")
|
|
205
|
+
.or(Cypress.sinon.match(3)),
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// matchers can be used from BDD assertions
|
|
209
|
+
cy.get("@add").should(
|
|
210
|
+
"have.been.calledWith",
|
|
211
|
+
Cypress.sinon.match.number,
|
|
212
|
+
Cypress.sinon.match(3),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
// you can alias matchers for shorter test code
|
|
216
|
+
const { match: M } = Cypress.sinon;
|
|
217
|
+
|
|
218
|
+
cy.get("@add").should("have.been.calledWith", M.number, M(3));
|
|
219
|
+
});
|
|
220
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context('Local Storage / Session Storage', () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit('https://example.cypress.io/commands/storage')
|
|
6
|
+
})
|
|
7
|
+
// Although localStorage is automatically cleared
|
|
8
|
+
// in between tests to maintain a clean state
|
|
9
|
+
// sometimes we need to clear localStorage manually
|
|
10
|
+
|
|
11
|
+
it('cy.clearLocalStorage() - clear all data in localStorage for the current origin', () => {
|
|
12
|
+
// https://on.cypress.io/clearlocalstorage
|
|
13
|
+
cy.get('.ls-btn').click()
|
|
14
|
+
cy.get('.ls-btn').should(() => {
|
|
15
|
+
expect(localStorage.getItem('prop1')).to.eq('red')
|
|
16
|
+
expect(localStorage.getItem('prop2')).to.eq('blue')
|
|
17
|
+
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
cy.clearLocalStorage()
|
|
21
|
+
cy.getAllLocalStorage().should(() => {
|
|
22
|
+
expect(localStorage.getItem('prop1')).to.be.null
|
|
23
|
+
expect(localStorage.getItem('prop2')).to.be.null
|
|
24
|
+
expect(localStorage.getItem('prop3')).to.be.null
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
cy.get('.ls-btn').click()
|
|
28
|
+
cy.get('.ls-btn').should(() => {
|
|
29
|
+
expect(localStorage.getItem('prop1')).to.eq('red')
|
|
30
|
+
expect(localStorage.getItem('prop2')).to.eq('blue')
|
|
31
|
+
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
// Clear key matching string in localStorage
|
|
35
|
+
cy.clearLocalStorage('prop1')
|
|
36
|
+
cy.getAllLocalStorage().should(() => {
|
|
37
|
+
expect(localStorage.getItem('prop1')).to.be.null
|
|
38
|
+
expect(localStorage.getItem('prop2')).to.eq('blue')
|
|
39
|
+
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
cy.get('.ls-btn').click()
|
|
43
|
+
cy.get('.ls-btn').should(() => {
|
|
44
|
+
expect(localStorage.getItem('prop1')).to.eq('red')
|
|
45
|
+
expect(localStorage.getItem('prop2')).to.eq('blue')
|
|
46
|
+
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
// Clear keys matching regex in localStorage
|
|
50
|
+
cy.clearLocalStorage(/prop1|2/)
|
|
51
|
+
cy.getAllLocalStorage().should(() => {
|
|
52
|
+
expect(localStorage.getItem('prop1')).to.be.null
|
|
53
|
+
expect(localStorage.getItem('prop2')).to.be.null
|
|
54
|
+
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('cy.getAllLocalStorage() - get all data in localStorage for all origins', () => {
|
|
59
|
+
// https://on.cypress.io/getalllocalstorage
|
|
60
|
+
cy.get('.ls-btn').click()
|
|
61
|
+
|
|
62
|
+
// getAllLocalStorage() yields a map of origins to localStorage values
|
|
63
|
+
cy.getAllLocalStorage().should((storageMap) => {
|
|
64
|
+
expect(storageMap).to.deep.equal({
|
|
65
|
+
// other origins will also be present if localStorage is set on them
|
|
66
|
+
'https://example.cypress.io': {
|
|
67
|
+
'prop1': 'red',
|
|
68
|
+
'prop2': 'blue',
|
|
69
|
+
'prop3': 'magenta',
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('cy.clearAllLocalStorage() - clear all data in localStorage for all origins', () => {
|
|
76
|
+
// https://on.cypress.io/clearalllocalstorage
|
|
77
|
+
cy.get('.ls-btn').click()
|
|
78
|
+
|
|
79
|
+
// clearAllLocalStorage() yields null
|
|
80
|
+
cy.clearAllLocalStorage()
|
|
81
|
+
cy.getAllLocalStorage().should(() => {
|
|
82
|
+
expect(localStorage.getItem('prop1')).to.be.null
|
|
83
|
+
expect(localStorage.getItem('prop2')).to.be.null
|
|
84
|
+
expect(localStorage.getItem('prop3')).to.be.null
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('cy.getAllSessionStorage() - get all data in sessionStorage for all origins', () => {
|
|
89
|
+
// https://on.cypress.io/getallsessionstorage
|
|
90
|
+
cy.get('.ls-btn').click()
|
|
91
|
+
|
|
92
|
+
// getAllSessionStorage() yields a map of origins to sessionStorage values
|
|
93
|
+
cy.getAllSessionStorage().should((storageMap) => {
|
|
94
|
+
expect(storageMap).to.deep.equal({
|
|
95
|
+
// other origins will also be present if sessionStorage is set on them
|
|
96
|
+
'https://example.cypress.io': {
|
|
97
|
+
'prop4': 'cyan',
|
|
98
|
+
'prop5': 'yellow',
|
|
99
|
+
'prop6': 'black',
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('cy.clearAllSessionStorage() - clear all data in sessionStorage for all origins', () => {
|
|
106
|
+
// https://on.cypress.io/clearallsessionstorage
|
|
107
|
+
cy.get('.ls-btn').click()
|
|
108
|
+
|
|
109
|
+
// clearAllSessionStorage() yields null
|
|
110
|
+
cy.clearAllSessionStorage()
|
|
111
|
+
cy.getAllSessionStorage().should(() => {
|
|
112
|
+
expect(sessionStorage.getItem('prop4')).to.be.null
|
|
113
|
+
expect(sessionStorage.getItem('prop5')).to.be.null
|
|
114
|
+
expect(sessionStorage.getItem('prop6')).to.be.null
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
})
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context("Traversal", () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit("https://example.cypress.io/commands/traversal");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it(
|
|
9
|
+
".children() - get child DOM elements",
|
|
10
|
+
{ requiredTags: "@nightly" },
|
|
11
|
+
() => {
|
|
12
|
+
// https://on.cypress.io/children
|
|
13
|
+
cy.get(".traversal-breadcrumb")
|
|
14
|
+
.children(".active")
|
|
15
|
+
.should("contain", "Data");
|
|
16
|
+
},
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
it(
|
|
20
|
+
".closest() - get closest ancestor DOM element",
|
|
21
|
+
{ tags: ["@p3", "@sanity"] },
|
|
22
|
+
() => {
|
|
23
|
+
// https://on.cypress.io/closest
|
|
24
|
+
cy.get(".traversal-badge")
|
|
25
|
+
.closest("ul")
|
|
26
|
+
.should("have.class", "list-group");
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
it(".eq() - get a DOM element at a specific index", () => {
|
|
31
|
+
// https://on.cypress.io/eq
|
|
32
|
+
cy.get(".traversal-list>li").eq(1).should("contain", "siamese");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it(".filter() - get DOM elements that match the selector", () => {
|
|
36
|
+
// https://on.cypress.io/filter
|
|
37
|
+
cy.get(".traversal-nav>li").filter(".active").should("contain", "About");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it(".find() - get descendant DOM elements of the selector", () => {
|
|
41
|
+
// https://on.cypress.io/find
|
|
42
|
+
cy.get(".traversal-pagination")
|
|
43
|
+
.find("li")
|
|
44
|
+
.find("a")
|
|
45
|
+
.should("have.length", 7);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it(".first() - get first DOM element", () => {
|
|
49
|
+
// https://on.cypress.io/first
|
|
50
|
+
cy.get(".traversal-table td").first().should("contain", "1");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it(".last() - get last DOM element", () => {
|
|
54
|
+
// https://on.cypress.io/last
|
|
55
|
+
cy.get(".traversal-buttons .btn").last().should("contain", "Submit");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it(".next() - get next sibling DOM element", () => {
|
|
59
|
+
// https://on.cypress.io/next
|
|
60
|
+
cy.get(".traversal-ul")
|
|
61
|
+
.contains("apples")
|
|
62
|
+
.next()
|
|
63
|
+
.should("contain", "oranges");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it(".nextAll() - get all next sibling DOM elements", () => {
|
|
67
|
+
// https://on.cypress.io/nextall
|
|
68
|
+
cy.get(".traversal-next-all")
|
|
69
|
+
.contains("oranges")
|
|
70
|
+
.nextAll()
|
|
71
|
+
.should("have.length", 3);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it(".nextUntil() - get next sibling DOM elements until next el", () => {
|
|
75
|
+
// https://on.cypress.io/nextuntil
|
|
76
|
+
cy.get("#veggies").nextUntil("#nuts").should("have.length", 3);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it(".not() - remove DOM elements from set of DOM elements", () => {
|
|
80
|
+
// https://on.cypress.io/not
|
|
81
|
+
cy.get(".traversal-disabled .btn")
|
|
82
|
+
.not("[disabled]")
|
|
83
|
+
.should("not.contain", "Disabled");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it(".parent() - get parent DOM element from DOM elements", () => {
|
|
87
|
+
// https://on.cypress.io/parent
|
|
88
|
+
cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus");
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it(".parents() - get parent DOM elements from DOM elements", () => {
|
|
92
|
+
// https://on.cypress.io/parents
|
|
93
|
+
cy.get(".traversal-cite").parents().should("match", "blockquote");
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => {
|
|
97
|
+
// https://on.cypress.io/parentsuntil
|
|
98
|
+
cy.get(".clothes-nav")
|
|
99
|
+
.find(".active")
|
|
100
|
+
.parentsUntil(".clothes-nav")
|
|
101
|
+
.should("have.length", 2);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it(".prev() - get previous sibling DOM element", () => {
|
|
105
|
+
// https://on.cypress.io/prev
|
|
106
|
+
cy.get(".birds").find(".active").prev().should("contain", "Lorikeets");
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it(".prevAll() - get all previous sibling DOM elements", () => {
|
|
110
|
+
// https://on.cypress.io/prevall
|
|
111
|
+
cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it(".prevUntil() - get all previous sibling DOM elements until el", () => {
|
|
115
|
+
// https://on.cypress.io/prevuntil
|
|
116
|
+
cy.get(".foods-list")
|
|
117
|
+
.find("#nuts")
|
|
118
|
+
.prevUntil("#veggies")
|
|
119
|
+
.should("have.length", 3);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it(".siblings() - get all sibling DOM elements", () => {
|
|
123
|
+
// https://on.cypress.io/siblings
|
|
124
|
+
cy.get(".traversal-pills .active").siblings().should("have.length", 2);
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
context("Utilities", { tags: "@p1" }, () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.visit("https://example.cypress.io/utilities");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("Cypress._ - call a lodash method", () => {
|
|
9
|
+
// https://on.cypress.io/_
|
|
10
|
+
cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
|
|
11
|
+
let ids = Cypress._.chain(response.body).map("id").take(3).value();
|
|
12
|
+
|
|
13
|
+
expect(ids).to.deep.eq([1, 2, 3]);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("Cypress.$ - call a jQuery method", () => {
|
|
18
|
+
// https://on.cypress.io/$
|
|
19
|
+
let $li = Cypress.$(".utility-jquery li:first");
|
|
20
|
+
|
|
21
|
+
cy.wrap($li).should("not.have.class", "active");
|
|
22
|
+
cy.wrap($li).click();
|
|
23
|
+
cy.wrap($li).should("have.class", "active");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("Cypress.Blob - blob utilities and base64 string conversion", () => {
|
|
27
|
+
// https://on.cypress.io/blob
|
|
28
|
+
cy.get(".utility-blob").then(($div) => {
|
|
29
|
+
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
|
|
30
|
+
// get the dataUrl string for the javascript-logo
|
|
31
|
+
return Cypress.Blob.imgSrcToDataURL(
|
|
32
|
+
"https://example.cypress.io/assets/img/javascript-logo.png",
|
|
33
|
+
undefined,
|
|
34
|
+
"anonymous",
|
|
35
|
+
).then((dataUrl) => {
|
|
36
|
+
// create an <img> element and set its src to the dataUrl
|
|
37
|
+
let img = Cypress.$("<img />", { src: dataUrl });
|
|
38
|
+
|
|
39
|
+
// need to explicitly return cy here since we are initially returning
|
|
40
|
+
// the Cypress.Blob.imgSrcToDataURL promise to our test
|
|
41
|
+
// append the image
|
|
42
|
+
$div.append(img);
|
|
43
|
+
|
|
44
|
+
cy.get(".utility-blob img").click();
|
|
45
|
+
cy.get(".utility-blob img").should("have.attr", "src", dataUrl);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it("Cypress.minimatch - test out glob patterns against strings", () => {
|
|
51
|
+
// https://on.cypress.io/minimatch
|
|
52
|
+
let matching = Cypress.minimatch("/users/1/comments", "/users/*/comments", {
|
|
53
|
+
matchBase: true,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(matching, "matching wildcard").to.be.true;
|
|
57
|
+
|
|
58
|
+
matching = Cypress.minimatch("/users/1/comments/2", "/users/*/comments", {
|
|
59
|
+
matchBase: true,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
expect(matching, "comments").to.be.false;
|
|
63
|
+
|
|
64
|
+
// ** matches against all downstream path segments
|
|
65
|
+
matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/**", {
|
|
66
|
+
matchBase: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(matching, "comments").to.be.true;
|
|
70
|
+
|
|
71
|
+
// whereas * matches only the next path segment
|
|
72
|
+
|
|
73
|
+
matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/*", {
|
|
74
|
+
matchBase: false,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
expect(matching, "comments").to.be.false;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("Cypress.Promise - instantiate a bluebird promise", () => {
|
|
81
|
+
// https://on.cypress.io/promise
|
|
82
|
+
let waited = false;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @return Bluebird<string>
|
|
86
|
+
*/
|
|
87
|
+
function waitOneSecond() {
|
|
88
|
+
// return a promise that resolves after 1 second
|
|
89
|
+
return new Cypress.Promise((resolve, reject) => {
|
|
90
|
+
setTimeout(() => {
|
|
91
|
+
// set waited to true
|
|
92
|
+
waited = true;
|
|
93
|
+
|
|
94
|
+
// resolve with 'foo' string
|
|
95
|
+
resolve("foo");
|
|
96
|
+
}, 1000);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
cy.then(() => {
|
|
101
|
+
// return a promise to cy.then() that
|
|
102
|
+
// is awaited until it resolves
|
|
103
|
+
return waitOneSecond().then((str) => {
|
|
104
|
+
expect(str).to.eq("foo");
|
|
105
|
+
expect(waited).to.be.true;
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|