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.
Files changed (45) hide show
  1. package/.github/workflows/jest.yml +12 -0
  2. package/CONTRIBUTING.md +39 -0
  3. package/LICENSE.md +21 -0
  4. package/README.md +197 -0
  5. package/assets/choose-spec-pattern-demo.gif +0 -0
  6. package/assets/cypress-cli-select-animated.gif +0 -0
  7. package/assets/print-selected-demo.png +0 -0
  8. package/assets/run-help.gif +0 -0
  9. package/assets/run-spec-tag.gif +0 -0
  10. package/assets/run-spec-title.gif +0 -0
  11. package/cypress/e2e/1-getting-started/todo.cy.js +143 -0
  12. package/cypress/e2e/2-advanced-examples/actions.cy.js +321 -0
  13. package/cypress/e2e/2-advanced-examples/aliasing.cy.js +39 -0
  14. package/cypress/e2e/2-advanced-examples/assertions.cy.js +176 -0
  15. package/cypress/e2e/2-advanced-examples/connectors.cy.js +98 -0
  16. package/cypress/e2e/2-advanced-examples/cookies.cy.js +118 -0
  17. package/cypress/e2e/2-advanced-examples/cypress_api.cy.js +211 -0
  18. package/cypress/e2e/2-advanced-examples/location.cy.js +32 -0
  19. package/cypress/e2e/2-advanced-examples/misc.cy.js +90 -0
  20. package/cypress/e2e/2-advanced-examples/navigation.cy.js +55 -0
  21. package/cypress/e2e/2-advanced-examples/network_requests.cy.js +163 -0
  22. package/cypress/e2e/2-advanced-examples/querying.cy.js +114 -0
  23. package/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +220 -0
  24. package/cypress/e2e/2-advanced-examples/storage.cy.js +117 -0
  25. package/cypress/e2e/2-advanced-examples/traversal.cy.js +126 -0
  26. package/cypress/e2e/2-advanced-examples/utilities.cy.js +109 -0
  27. package/cypress/e2e/2-advanced-examples/viewport.cy.js +58 -0
  28. package/cypress/e2e/2-advanced-examples/waiting.cy.js +30 -0
  29. package/cypress/e2e/2-advanced-examples/window.cy.js +22 -0
  30. package/cypress/support/commands.js +25 -0
  31. package/cypress/support/component-index.html +14 -0
  32. package/cypress/support/component.js +24 -0
  33. package/cypress/support/e2e.js +19 -0
  34. package/cypress.config.js +25 -0
  35. package/cypress.new.config.js +26 -0
  36. package/index.js +586 -0
  37. package/package.json +46 -0
  38. package/src/components/Clock.cy.js +13 -0
  39. package/src/components/Stepper.cy.js +13 -0
  40. package/src/sortable-list.js +82 -0
  41. package/tapes/run-help.tape +94 -0
  42. package/tapes/run-spec-tag.tape +163 -0
  43. package/tapes/run-spec-title.tape +191 -0
  44. package/tests/cli-component.spec.js +409 -0
  45. 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
+ });