37 |
--------------------------------------------------------------------------------
/cypress/integration/2-advanced-examples/misc.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context("Misc", () => {
4 | beforeEach(() => {
5 | cy.visit("https://example.cypress.io/commands/misc");
6 | });
7 |
8 | it(".end() - end the command chain", () => {
9 | // https://on.cypress.io/end
10 |
11 | // cy.end is useful when you want to end a chain of commands
12 | // and force Cypress to re-query from the root element
13 | cy.get(".misc-table").within(() => {
14 | // ends the current chain and yields null
15 | cy.contains("Cheryl").click().end();
16 |
17 | // queries the entire table again
18 | cy.contains("Charles").click();
19 | });
20 | });
21 |
22 | it("cy.exec() - execute a system command", () => {
23 | // execute a system command.
24 | // so you can take actions necessary for
25 | // your test outside the scope of Cypress.
26 | // https://on.cypress.io/exec
27 |
28 | // we can use Cypress.platform string to
29 | // select appropriate command
30 | // https://on.cypress/io/platform
31 | cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
32 |
33 | // on CircleCI Windows build machines we have a failure to run bash shell
34 | // https://github.com/cypress-io/cypress/issues/5169
35 | // so skip some of the tests by passing flag "--env circle=true"
36 | const isCircleOnWindows =
37 | Cypress.platform === "win32" && Cypress.env("circle");
38 |
39 | if (isCircleOnWindows) {
40 | cy.log("Skipping test on CircleCI");
41 |
42 | return;
43 | }
44 |
45 | // cy.exec problem on Shippable CI
46 | // https://github.com/cypress-io/cypress/issues/6718
47 | const isShippable =
48 | Cypress.platform === "linux" && Cypress.env("shippable");
49 |
50 | if (isShippable) {
51 | cy.log("Skipping test on ShippableCI");
52 |
53 | return;
54 | }
55 |
56 | cy.exec("echo Jane Lane").its("stdout").should("contain", "Jane Lane");
57 |
58 | if (Cypress.platform === "win32") {
59 | cy.exec("print cypress.json").its("stderr").should("be.empty");
60 | } else {
61 | cy.exec("cat cypress.json").its("stderr").should("be.empty");
62 |
63 | cy.exec("pwd").its("code").should("eq", 0);
64 | }
65 | });
66 |
67 | it("cy.focused() - get the DOM element that has focus", () => {
68 | // https://on.cypress.io/focused
69 | cy.get(".misc-form").find("#name").click();
70 | cy.focused().should("have.id", "name");
71 |
72 | cy.get(".misc-form").find("#description").click();
73 | cy.focused().should("have.id", "description");
74 | });
75 |
76 | context("Cypress.Screenshot", function () {
77 | it("cy.screenshot() - take a screenshot", () => {
78 | // https://on.cypress.io/screenshot
79 | cy.screenshot("my-image");
80 | });
81 |
82 | it("Cypress.Screenshot.defaults() - change default config of screenshots", function () {
83 | Cypress.Screenshot.defaults({
84 | blackout: [".foo"],
85 | capture: "viewport",
86 | clip: { x: 0, y: 0, width: 200, height: 200 },
87 | scale: false,
88 | disableTimersAndAnimations: true,
89 | screenshotOnRunFailure: true,
90 | onBeforeScreenshot() {},
91 | onAfterScreenshot() {},
92 | });
93 | });
94 | });
95 |
96 | it("cy.wrap() - wrap an object", () => {
97 | // https://on.cypress.io/wrap
98 | cy.wrap({ foo: "bar" })
99 | .should("have.property", "foo")
100 | .and("include", "bar");
101 | });
102 | });
103 |
--------------------------------------------------------------------------------
/cypress/integration/2-advanced-examples/utilities.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context("Utilities", () => {
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)
22 | .should("not.have.class", "active")
23 | .click()
24 | .should("have.class", "active");
25 | });
26 |
27 | it("Cypress.Blob - blob utilities and base64 string conversion", () => {
28 | // https://on.cypress.io/blob
29 | cy.get(".utility-blob").then(($div) => {
30 | // https://github.com/nolanlawson/blob-util#imgSrcToDataURL
31 | // get the dataUrl string for the javascript-logo
32 | return Cypress.Blob.imgSrcToDataURL(
33 | "https://example.cypress.io/assets/img/javascript-logo.png",
34 | undefined,
35 | "anonymous"
36 | ).then((dataUrl) => {
37 | // create an element and set its src to the dataUrl
38 | let img = Cypress.$("", { src: dataUrl });
39 |
40 | // need to explicitly return cy here since we are initially returning
41 | // the Cypress.Blob.imgSrcToDataURL promise to our test
42 | // append the image
43 | $div.append(img);
44 |
45 | cy.get(".utility-blob img").click().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
86 | */
87 | function waitOneSecond() {
88 | // return a promise that resolves after 1 second
89 | // @ts-ignore TS2351 (new Cypress.Promise)
90 | return new Cypress.Promise((resolve, reject) => {
91 | setTimeout(() => {
92 | // set waited to true
93 | waited = true;
94 |
95 | // resolve with 'foo' string
96 | resolve("foo");
97 | }, 1000);
98 | });
99 | }
100 |
101 | cy.then(() => {
102 | // return a promise to cy.then() that
103 | // is awaited until it resolves
104 | // @ts-ignore TS7006
105 | return waitOneSecond().then((str) => {
106 | expect(str).to.eq("foo");
107 | expect(waited).to.be.true;
108 | });
109 | });
110 | });
111 | });
112 |
--------------------------------------------------------------------------------
/cypress/integration/2-advanced-examples/querying.spec.js:
--------------------------------------------------------------------------------
1 | ///
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").contains("bananas").should("have.class", "third");
45 |
46 | // we can pass a regexp to `.contains()`
47 | cy.get(".query-list").contains(/^b\w+/).should("have.class", "third");
48 |
49 | cy.get(".query-list").contains("apples").should("have.class", "first");
50 |
51 | // passing a selector to contains will
52 | // yield the selector containing the text
53 | cy.get("#querying")
54 | .contains("ul", "oranges")
55 | .should("have.class", "query-list");
56 |
57 | cy.get(".query-button").contains("Save Form").should("have.class", "btn");
58 | });
59 |
60 | it(".within() - query DOM elements within a specific element", () => {
61 | // https://on.cypress.io/within
62 | cy.get(".query-form").within(() => {
63 | cy.get("input:first").should("have.attr", "placeholder", "Email");
64 | cy.get("input:last").should("have.attr", "placeholder", "Password");
65 | });
66 | });
67 |
68 | it("cy.root() - query the root DOM element", () => {
69 | // https://on.cypress.io/root
70 |
71 | // By default, root is the document
72 | cy.root().should("match", "html");
73 |
74 | cy.get(".query-ul").within(() => {
75 | // In this within, the root is now the ul DOM element
76 | cy.root().should("have.class", "query-ul");
77 | });
78 | });
79 |
80 | it("best practices - selecting elements", () => {
81 | // https://on.cypress.io/best-practices#Selecting-Elements
82 | cy.get("[data-cy=best-practices-selecting-elements]").within(() => {
83 | // Worst - too generic, no context
84 | cy.get("button").click();
85 |
86 | // Bad. Coupled to styling. Highly subject to change.
87 | cy.get(".btn.btn-large").click();
88 |
89 | // Average. Coupled to the `name` attribute which has HTML semantics.
90 | cy.get("[name=submission]").click();
91 |
92 | // Better. But still coupled to styling or JS event listeners.
93 | cy.get("#main").click();
94 |
95 | // Slightly better. Uses an ID but also ensures the element
96 | // has an ARIA role attribute
97 | cy.get("#main[role=button]").click();
98 |
99 | // Much better. But still coupled to text content that may change.
100 | cy.contains("Submit").click();
101 |
102 | // Best. Insulated from all changes.
103 | cy.get("[data-cy=submit]").click();
104 | });
105 | });
106 | });
107 |
--------------------------------------------------------------------------------
/cypress/integration/2-advanced-examples/traversal.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context("Traversal", () => {
4 | beforeEach(() => {
5 | cy.visit("https://example.cypress.io/commands/traversal");
6 | });
7 |
8 | it(".children() - get child DOM elements", () => {
9 | // https://on.cypress.io/children
10 | cy.get(".traversal-breadcrumb")
11 | .children(".active")
12 | .should("contain", "Data");
13 | });
14 |
15 | it(".closest() - get closest ancestor DOM element", () => {
16 | // https://on.cypress.io/closest
17 | cy.get(".traversal-badge").closest("ul").should("have.class", "list-group");
18 | });
19 |
20 | it(".eq() - get a DOM element at a specific index", () => {
21 | // https://on.cypress.io/eq
22 | cy.get(".traversal-list>li").eq(1).should("contain", "siamese");
23 | });
24 |
25 | it(".filter() - get DOM elements that match the selector", () => {
26 | // https://on.cypress.io/filter
27 | cy.get(".traversal-nav>li").filter(".active").should("contain", "About");
28 | });
29 |
30 | it(".find() - get descendant DOM elements of the selector", () => {
31 | // https://on.cypress.io/find
32 | cy.get(".traversal-pagination")
33 | .find("li")
34 | .find("a")
35 | .should("have.length", 7);
36 | });
37 |
38 | it(".first() - get first DOM element", () => {
39 | // https://on.cypress.io/first
40 | cy.get(".traversal-table td").first().should("contain", "1");
41 | });
42 |
43 | it(".last() - get last DOM element", () => {
44 | // https://on.cypress.io/last
45 | cy.get(".traversal-buttons .btn").last().should("contain", "Submit");
46 | });
47 |
48 | it(".next() - get next sibling DOM element", () => {
49 | // https://on.cypress.io/next
50 | cy.get(".traversal-ul")
51 | .contains("apples")
52 | .next()
53 | .should("contain", "oranges");
54 | });
55 |
56 | it(".nextAll() - get all next sibling DOM elements", () => {
57 | // https://on.cypress.io/nextall
58 | cy.get(".traversal-next-all")
59 | .contains("oranges")
60 | .nextAll()
61 | .should("have.length", 3);
62 | });
63 |
64 | it(".nextUntil() - get next sibling DOM elements until next el", () => {
65 | // https://on.cypress.io/nextuntil
66 | cy.get("#veggies").nextUntil("#nuts").should("have.length", 3);
67 | });
68 |
69 | it(".not() - remove DOM elements from set of DOM elements", () => {
70 | // https://on.cypress.io/not
71 | cy.get(".traversal-disabled .btn")
72 | .not("[disabled]")
73 | .should("not.contain", "Disabled");
74 | });
75 |
76 | it(".parent() - get parent DOM element from DOM elements", () => {
77 | // https://on.cypress.io/parent
78 | cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus");
79 | });
80 |
81 | it(".parents() - get parent DOM elements from DOM elements", () => {
82 | // https://on.cypress.io/parents
83 | cy.get(".traversal-cite").parents().should("match", "blockquote");
84 | });
85 |
86 | it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => {
87 | // https://on.cypress.io/parentsuntil
88 | cy.get(".clothes-nav")
89 | .find(".active")
90 | .parentsUntil(".clothes-nav")
91 | .should("have.length", 2);
92 | });
93 |
94 | it(".prev() - get previous sibling DOM element", () => {
95 | // https://on.cypress.io/prev
96 | cy.get(".birds").find(".active").prev().should("contain", "Lorikeets");
97 | });
98 |
99 | it(".prevAll() - get all previous sibling DOM elements", () => {
100 | // https://on.cypress.io/prevall
101 | cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2);
102 | });
103 |
104 | it(".prevUntil() - get all previous sibling DOM elements until el", () => {
105 | // https://on.cypress.io/prevuntil
106 | cy.get(".foods-list")
107 | .find("#nuts")
108 | .prevUntil("#veggies")
109 | .should("have.length", 3);
110 | });
111 |
112 | it(".siblings() - get all sibling DOM elements", () => {
113 | // https://on.cypress.io/siblings
114 | cy.get(".traversal-pills .active").siblings().should("have.length", 2);
115 | });
116 | });
117 |
--------------------------------------------------------------------------------
/cypress/integration/2-advanced-examples/assertions.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | context("Assertions", () => {
4 | beforeEach(() => {
5 | cy.visit("https://example.cypress.io/commands/assertions");
6 | });
7 |
8 | describe("Implicit Assertions", () => {
9 | it(".should() - make an assertion about the current subject", () => {
10 | // https://on.cypress.io/should
11 | cy.get(".assertion-table")
12 | .find("tbody tr:last")
13 | .should("have.class", "success")
14 | .find("td")
15 | .first()
16 | // checking the text of the
element in various ways
17 | .should("have.text", "Column content")
18 | .should("contain", "Column content")
19 | .should("have.html", "Column content")
20 | // chai-jquery uses "is()" to check if element matches selector
21 | .should("match", "td")
22 | // to match text content against a regular expression
23 | // first need to invoke jQuery method text()
24 | // and then match using regular expression
25 | .invoke("text")
26 | .should("match", /column content/i);
27 |
28 | // a better way to check element's text content against a regular expression
29 | // is to use "cy.contains"
30 | // https://on.cypress.io/contains
31 | cy.get(".assertion-table")
32 | .find("tbody tr:last")
33 | // finds first
element with text content matching regular expression
34 | .contains("td", /column content/i)
35 | .should("be.visible");
36 |
37 | // for more information about asserting element's text
38 | // see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
39 | });
40 |
41 | it(".and() - chain multiple assertions together", () => {
42 | // https://on.cypress.io/and
43 | cy.get(".assertions-link")
44 | .should("have.class", "active")
45 | .and("have.attr", "href")
46 | .and("include", "cypress.io");
47 | });
48 | });
49 |
50 | describe("Explicit Assertions", () => {
51 | // https://on.cypress.io/assertions
52 | it("expect - make an assertion about a specified subject", () => {
53 | // We can use Chai's BDD style assertions
54 | expect(true).to.be.true;
55 | const o = { foo: "bar" };
56 |
57 | expect(o).to.equal(o);
58 | expect(o).to.deep.equal({ foo: "bar" });
59 | // matching text using regular expression
60 | expect("FooBar").to.match(/bar$/i);
61 | });
62 |
63 | it("pass your own callback function to should()", () => {
64 | // Pass a function to should that can have any number
65 | // of explicit assertions within it.
66 | // The ".should(cb)" function will be retried
67 | // automatically until it passes all your explicit assertions or times out.
68 | cy.get(".assertions-p")
69 | .find("p")
70 | .should(($p) => {
71 | // https://on.cypress.io/$
72 | // return an array of texts from all of the p's
73 | // @ts-ignore TS6133 unused variable
74 | const texts = $p.map((i, el) => Cypress.$(el).text());
75 |
76 | // jquery map returns jquery object
77 | // and .get() convert this to simple array
78 | const paragraphs = texts.get();
79 |
80 | // array should have length of 3
81 | expect(paragraphs, "has 3 paragraphs").to.have.length(3);
82 |
83 | // use second argument to expect(...) to provide clear
84 | // message with each assertion
85 | expect(paragraphs, "has expected text in each paragraph").to.deep.eq([
86 | "Some text from first p",
87 | "More text from second p",
88 | "And even more text from third p",
89 | ]);
90 | });
91 | });
92 |
93 | it("finds element by class name regex", () => {
94 | cy.get(".docs-header")
95 | .find("div")
96 | // .should(cb) callback function will be retried
97 | .should(($div) => {
98 | expect($div).to.have.length(1);
99 |
100 | const className = $div[0].className;
101 |
102 | expect(className).to.match(/heading-/);
103 | })
104 | // .then(cb) callback is not retried,
105 | // it either passes or fails
106 | .then(($div) => {
107 | expect($div, "text content").to.have.text("Introduction");
108 | });
109 | });
110 |
111 | it("can throw any error", () => {
112 | cy.get(".docs-header")
113 | .find("div")
114 | .should(($div) => {
115 | if ($div.length !== 1) {
116 | // you can throw your own errors
117 | throw new Error("Did not find 1 element");
118 | }
119 |
120 | const className = $div[0].className;
121 |
122 | if (!className.match(/heading-/)) {
123 | throw new Error(`Could not find class "heading-" in ${className}`);
124 | }
125 | });
126 | });
127 |
128 | it("matches unknown text between two elements", () => {
129 | /**
130 | * Text from the first element.
131 | * @type {string}
132 | */
133 | let text;
134 |
135 | /**
136 | * Normalizes passed text,
137 | * useful before comparing text with spaces and different capitalization.
138 | * @param {string} s Text to normalize
139 | */
140 | const normalizeText = (s) => s.replace(/\s/g, "").toLowerCase();
141 |
142 | cy.get(".two-elements")
143 | .find(".first")
144 | .then(($first) => {
145 | // save text from the first element
146 | text = normalizeText($first.text());
147 | });
148 |
149 | cy.get(".two-elements")
150 | .find(".second")
151 | .should(($div) => {
152 | // we can massage text before comparing
153 | const secondText = normalizeText($div.text());
154 |
155 | expect(secondText, "second text").to.equal(text);
156 | });
157 | });
158 |
159 | it("assert - assert shape of an object", () => {
160 | const person = {
161 | name: "Joe",
162 | age: 20,
163 | };
164 |
165 | assert.isObject(person, "value is object");
166 | });
167 |
168 | it("retries the should callback until assertions pass", () => {
169 | cy.get("#random-number").should(($div) => {
170 | const n = parseFloat($div.text());
171 |
172 | expect(n).to.be.gte(1).and.be.lte(10);
173 | });
174 | });
175 | });
176 | });
177 |
--------------------------------------------------------------------------------
/cypress/integration/1-getting-started/todo.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | // Welcome to Cypress!
4 | //
5 | // This spec file contains a variety of sample tests
6 | // for a todo list app that are designed to demonstrate
7 | // the power of writing tests in Cypress.
8 | //
9 | // To learn more about how Cypress works and
10 | // what makes it such an awesome testing tool,
11 | // please read our getting started guide:
12 | // https://on.cypress.io/introduction-to-cypress
13 |
14 | describe("example to-do app", () => {
15 | beforeEach(() => {
16 | // Cypress starts out with a blank slate for each test
17 | // so we must tell it to visit our website with the `cy.visit()` command.
18 | // Since we want to visit the same URL at the start of all our tests,
19 | // we include it in our beforeEach function so that it runs before each test
20 | cy.visit("https://example.cypress.io/todo");
21 | });
22 |
23 | it("displays two todo items by default", () => {
24 | // We use the `cy.get()` command to get all elements that match the selector.
25 | // Then, we use `should` to assert that there are two matched items,
26 | // which are the two default items.
27 | cy.get(".todo-list li").should("have.length", 2);
28 |
29 | // We can go even further and check that the default todos each contain
30 | // the correct text. We use the `first` and `last` functions
31 | // to get just the first and last matched elements individually,
32 | // and then perform an assertion with `should`.
33 | cy.get(".todo-list li").first().should("have.text", "Pay electric bill");
34 | cy.get(".todo-list li").last().should("have.text", "Walk the dog");
35 | });
36 |
37 | it("can add new todo items", () => {
38 | // We'll store our item text in a variable so we can reuse it
39 | const newItem = "Feed the cat";
40 |
41 | // Let's get the input element and use the `type` command to
42 | // input our new list item. After typing the content of our item,
43 | // we need to type the enter key as well in order to submit the input.
44 | // This input has a data-test attribute so we'll use that to select the
45 | // element in accordance with best practices:
46 | // https://on.cypress.io/selecting-elements
47 | cy.get("[data-test=new-todo]").type(`${newItem}{enter}`);
48 |
49 | // Now that we've typed our new item, let's check that it actually was added to the list.
50 | // Since it's the newest item, it should exist as the last element in the list.
51 | // In addition, with the two default items, we should have a total of 3 elements in the list.
52 | // Since assertions yield the element that was asserted on,
53 | // we can chain both of these assertions together into a single statement.
54 | cy.get(".todo-list li")
55 | .should("have.length", 3)
56 | .last()
57 | .should("have.text", newItem);
58 | });
59 |
60 | it("can check off an item as completed", () => {
61 | // In addition to using the `get` command to get an element by selector,
62 | // we can also use the `contains` command to get an element by its contents.
63 | // However, this will yield the