diff --git a/.gitignore b/.gitignore
index 45c1abce..103c6c18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
# testing
/coverage
+/cypress/screenshots
# next.js
/.next/
diff --git a/cypress/e2e/2-advanced-examples/aliasing.cy.js b/cypress/e2e/2-advanced-examples/aliasing.cy.js
deleted file mode 100644
index cbf76104..00000000
--- a/cypress/e2e/2-advanced-examples/aliasing.cy.js
+++ /dev/null
@@ -1,43 +0,0 @@
-///
-
-context("Aliasing", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/aliasing");
- });
-
- it(".as() - alias a DOM element for later use", () => {
- // https://on.cypress.io/as
-
- // Alias a DOM element for use later
- // We don't have to traverse to the element
- // later in our code, we reference it with @
-
- cy.get(".as-table")
- .find("tbody>tr")
- .first()
- .find("td")
- .first()
- .find("button")
- .as("firstBtn");
-
- // when we reference the alias, we place an
- // @ in front of its name
- cy.get("@firstBtn").click();
-
- cy.get("@firstBtn")
- .should("have.class", "btn-success")
- .and("contain", "Changed");
- });
-
- it(".as() - alias a route for later use", () => {
- // Alias the route to wait for its response
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // https://on.cypress.io/wait
- cy.wait("@getComment").its("response.statusCode").should("eq", 200);
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/assertions.cy.js b/cypress/e2e/2-advanced-examples/assertions.cy.js
deleted file mode 100644
index a93512cc..00000000
--- a/cypress/e2e/2-advanced-examples/assertions.cy.js
+++ /dev/null
@@ -1,175 +0,0 @@
-///
-
-context("Assertions", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/assertions");
- });
-
- describe("Implicit Assertions", () => {
- it(".should() - make an assertion about the current subject", () => {
- // https://on.cypress.io/should
- cy.get(".assertion-table")
- .find("tbody tr:last")
- .should("have.class", "success")
- .find("td")
- .first()
- // checking the text of the
element in various ways
- .should("have.text", "Column content")
- .should("contain", "Column content")
- .should("have.html", "Column content")
- // chai-jquery uses "is()" to check if element matches selector
- .should("match", "td")
- // to match text content against a regular expression
- // first need to invoke jQuery method text()
- // and then match using regular expression
- .invoke("text")
- .should("match", /column content/i);
-
- // a better way to check element's text content against a regular expression
- // is to use "cy.contains"
- // https://on.cypress.io/contains
- cy.get(".assertion-table")
- .find("tbody tr:last")
- // finds first
element with text content matching regular expression
- .contains("td", /column content/i)
- .should("be.visible");
-
- // for more information about asserting element's text
- // see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
- });
-
- it(".and() - chain multiple assertions together", () => {
- // https://on.cypress.io/and
- cy.get(".assertions-link")
- .should("have.class", "active")
- .and("have.attr", "href")
- .and("include", "cypress.io");
- });
- });
-
- describe("Explicit Assertions", () => {
- // https://on.cypress.io/assertions
- it("expect - make an assertion about a specified subject", () => {
- // We can use Chai's BDD style assertions
- expect(true).to.be.true;
- const o = { foo: "bar" };
-
- expect(o).to.equal(o);
- expect(o).to.deep.equal({ foo: "bar" });
- // matching text using regular expression
- expect("FooBar").to.match(/bar$/i);
- });
-
- it("pass your own callback function to should()", () => {
- // Pass a function to should that can have any number
- // of explicit assertions within it.
- // The ".should(cb)" function will be retried
- // automatically until it passes all your explicit assertions or times out.
- cy.get(".assertions-p")
- .find("p")
- .should(($p) => {
- // https://on.cypress.io/$
- // return an array of texts from all of the p's
- const texts = $p.map((i, el) => Cypress.$(el).text());
-
- // jquery map returns jquery object
- // and .get() convert this to simple array
- const paragraphs = texts.get();
-
- // array should have length of 3
- expect(paragraphs, "has 3 paragraphs").to.have.length(3);
-
- // use second argument to expect(...) to provide clear
- // message with each assertion
- expect(paragraphs, "has expected text in each paragraph").to.deep.eq([
- "Some text from first p",
- "More text from second p",
- "And even more text from third p",
- ]);
- });
- });
-
- it("finds element by class name regex", () => {
- cy.get(".docs-header")
- .find("div")
- // .should(cb) callback function will be retried
- .should(($div) => {
- expect($div).to.have.length(1);
-
- const className = $div[0].className;
-
- expect(className).to.match(/heading-/);
- })
- // .then(cb) callback is not retried,
- // it either passes or fails
- .then(($div) => {
- expect($div, "text content").to.have.text("Introduction");
- });
- });
-
- it("can throw any error", () => {
- cy.get(".docs-header")
- .find("div")
- .should(($div) => {
- if ($div.length !== 1) {
- // you can throw your own errors
- throw new Error("Did not find 1 element");
- }
-
- const className = $div[0].className;
-
- if (!className.match(/heading-/)) {
- throw new Error(`Could not find class "heading-" in ${className}`);
- }
- });
- });
-
- it("matches unknown text between two elements", () => {
- /**
- * Text from the first element.
- * @type {string}
- */
- let text;
-
- /**
- * Normalizes passed text,
- * useful before comparing text with spaces and different capitalization.
- * @param {string} s Text to normalize
- */
- const normalizeText = (s) => s.replace(/\s/g, "").toLowerCase();
-
- cy.get(".two-elements")
- .find(".first")
- .then(($first) => {
- // save text from the first element
- text = normalizeText($first.text());
- });
-
- cy.get(".two-elements")
- .find(".second")
- .should(($div) => {
- // we can massage text before comparing
- const secondText = normalizeText($div.text());
-
- expect(secondText, "second text").to.equal(text);
- });
- });
-
- it("assert - assert shape of an object", () => {
- const person = {
- name: "Joe",
- age: 20,
- };
-
- assert.isObject(person, "value is object");
- });
-
- it("retries the should callback until assertions pass", () => {
- cy.get("#random-number").should(($div) => {
- const n = parseFloat($div.text());
-
- expect(n).to.be.gte(1).and.be.lte(10);
- });
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/connectors.cy.js b/cypress/e2e/2-advanced-examples/connectors.cy.js
deleted file mode 100644
index aaabcd13..00000000
--- a/cypress/e2e/2-advanced-examples/connectors.cy.js
+++ /dev/null
@@ -1,96 +0,0 @@
-///
-
-context("Connectors", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/connectors");
- });
-
- it(".each() - iterate over an array of elements", () => {
- // https://on.cypress.io/each
- cy.get(".connectors-each-ul>li").each(($el, index, $list) => {
- console.log($el, index, $list);
- });
- });
-
- it(".its() - get properties on the current subject", () => {
- // https://on.cypress.io/its
- cy.get(".connectors-its-ul>li")
- // calls the 'length' property yielding that value
- .its("length")
- .should("be.gt", 2);
- });
-
- it(".invoke() - invoke a function on the current subject", () => {
- // our div is hidden in our script.js
- // $('.connectors-div').hide()
- cy.get(".connectors-div").should("be.hidden");
-
- // https://on.cypress.io/invoke
- // call the jquery method 'show' on the 'div.container'
- cy.get(".connectors-div").invoke("show");
-
- cy.get(".connectors-div").should("be.visible");
- });
-
- it(".spread() - spread an array as individual args to callback function", () => {
- // https://on.cypress.io/spread
- const arr = ["foo", "bar", "baz"];
-
- cy.wrap(arr).spread((foo, bar, baz) => {
- expect(foo).to.eq("foo");
- expect(bar).to.eq("bar");
- expect(baz).to.eq("baz");
- });
- });
-
- describe(".then()", () => {
- it("invokes a callback function with the current subject", () => {
- // https://on.cypress.io/then
- cy.get(".connectors-list > li").then(($lis) => {
- expect($lis, "3 items").to.have.length(3);
- expect($lis.eq(0), "first item").to.contain("Walk the dog");
- expect($lis.eq(1), "second item").to.contain("Feed the cat");
- expect($lis.eq(2), "third item").to.contain("Write JavaScript");
- });
- });
-
- it("yields the returned value to the next command", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
-
- return 2;
- })
- .then((num) => {
- expect(num).to.equal(2);
- });
- });
-
- it("yields the original subject without return", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
- // note that nothing is returned from this callback
- })
- .then((num) => {
- // this callback receives the original unchanged value 1
- expect(num).to.equal(1);
- });
- });
-
- it("yields the value yielded by the last Cypress command inside", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
- // note how we run a Cypress command
- // the result yielded by this Cypress command
- // will be passed to the second ".then"
- cy.wrap(2);
- })
- .then((num) => {
- // this callback receives the value yielded by "cy.wrap(2)"
- expect(num).to.equal(2);
- });
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/cookies.cy.js b/cypress/e2e/2-advanced-examples/cookies.cy.js
deleted file mode 100644
index d497107e..00000000
--- a/cypress/e2e/2-advanced-examples/cookies.cy.js
+++ /dev/null
@@ -1,122 +0,0 @@
-///
-
-context("Cookies", () => {
- beforeEach(() => {
- Cypress.Cookies.debug(true);
-
- cy.visit("https://example.cypress.io/commands/cookies");
-
- // clear cookies again after visiting to remove
- // any 3rd party cookies picked up such as cloudflare
- cy.clearCookies();
- });
-
- it("cy.getCookie() - get a browser cookie", () => {
- // https://on.cypress.io/getcookie
- cy.get("#getCookie .set-a-cookie").click();
-
- // cy.getCookie() yields a cookie object
- cy.getCookie("token").should("have.property", "value", "123ABC");
- });
-
- it("cy.getCookies() - get browser cookies for the current domain", () => {
- // https://on.cypress.io/getcookies
- cy.getCookies().should("be.empty");
-
- cy.get("#getCookies .set-a-cookie").click();
-
- // cy.getCookies() yields an array of cookies
- cy.getCookies()
- .should("have.length", 1)
- .should((cookies) => {
- // each cookie has these properties
- expect(cookies[0]).to.have.property("name", "token");
- expect(cookies[0]).to.have.property("value", "123ABC");
- expect(cookies[0]).to.have.property("httpOnly", false);
- expect(cookies[0]).to.have.property("secure", false);
- expect(cookies[0]).to.have.property("domain");
- expect(cookies[0]).to.have.property("path");
- });
- });
-
- it("cy.getAllCookies() - get all browser cookies", () => {
- // https://on.cypress.io/getallcookies
- cy.getAllCookies().should("be.empty");
-
- cy.setCookie("key", "value");
- cy.setCookie("key", "value", { domain: ".example.com" });
-
- // cy.getAllCookies() yields an array of cookies
- cy.getAllCookies()
- .should("have.length", 2)
- .should((cookies) => {
- // each cookie has these properties
- expect(cookies[0]).to.have.property("name", "key");
- expect(cookies[0]).to.have.property("value", "value");
- expect(cookies[0]).to.have.property("httpOnly", false);
- expect(cookies[0]).to.have.property("secure", false);
- expect(cookies[0]).to.have.property("domain");
- expect(cookies[0]).to.have.property("path");
-
- expect(cookies[1]).to.have.property("name", "key");
- expect(cookies[1]).to.have.property("value", "value");
- expect(cookies[1]).to.have.property("httpOnly", false);
- expect(cookies[1]).to.have.property("secure", false);
- expect(cookies[1]).to.have.property("domain", ".example.com");
- expect(cookies[1]).to.have.property("path");
- });
- });
-
- it("cy.setCookie() - set a browser cookie", () => {
- // https://on.cypress.io/setcookie
- cy.getCookies().should("be.empty");
-
- cy.setCookie("foo", "bar");
-
- // cy.getCookie() yields a cookie object
- cy.getCookie("foo").should("have.property", "value", "bar");
- });
-
- it("cy.clearCookie() - clear a browser cookie", () => {
- // https://on.cypress.io/clearcookie
- cy.getCookie("token").should("be.null");
-
- cy.get("#clearCookie .set-a-cookie").click();
-
- cy.getCookie("token").should("have.property", "value", "123ABC");
-
- // cy.clearCookies() yields null
- cy.clearCookie("token").should("be.null");
-
- cy.getCookie("token").should("be.null");
- });
-
- it("cy.clearCookies() - clear browser cookies for the current domain", () => {
- // https://on.cypress.io/clearcookies
- cy.getCookies().should("be.empty");
-
- cy.get("#clearCookies .set-a-cookie").click();
-
- cy.getCookies().should("have.length", 1);
-
- // cy.clearCookies() yields null
- cy.clearCookies();
-
- cy.getCookies().should("be.empty");
- });
-
- it("cy.clearAllCookies() - clear all browser cookies", () => {
- // https://on.cypress.io/clearallcookies
- cy.getAllCookies().should("be.empty");
-
- cy.setCookie("key", "value");
- cy.setCookie("key", "value", { domain: ".example.com" });
-
- cy.getAllCookies().should("have.length", 2);
-
- // cy.clearAllCookies() yields null
- cy.clearAllCookies();
-
- cy.getAllCookies().should("be.empty");
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/cypress_api.cy.js b/cypress/e2e/2-advanced-examples/cypress_api.cy.js
deleted file mode 100644
index 2d5e7bf3..00000000
--- a/cypress/e2e/2-advanced-examples/cypress_api.cy.js
+++ /dev/null
@@ -1,197 +0,0 @@
-///
-
-context("Cypress APIs", () => {
- context("Cypress.Commands", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/custom-commands
-
- it(".add() - create a custom command", () => {
- Cypress.Commands.add(
- "console",
- {
- prevSubject: true,
- },
- (subject, method) => {
- // the previous subject is automatically received
- // and the commands arguments are shifted
-
- // allow us to change the console method used
- method = method || "log";
-
- // log the subject to the console
- console[method]("The subject is", subject);
-
- // whatever we return becomes the new subject
- // we don't want to change the subject so
- // we return whatever was passed in
- return subject;
- },
- );
-
- cy.get("button")
- .console("info")
- .then(($button) => {
- // subject is still $button
- });
- });
- });
-
- context("Cypress.Cookies", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/cookies
- it(".debug() - enable or disable debugging", () => {
- Cypress.Cookies.debug(true);
-
- // Cypress will now log in the console when
- // cookies are set or cleared
- cy.setCookie("fakeCookie", "123ABC");
- cy.clearCookie("fakeCookie");
- cy.setCookie("fakeCookie", "123ABC");
- cy.clearCookie("fakeCookie");
- cy.setCookie("fakeCookie", "123ABC");
- });
- });
-
- context("Cypress.arch", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get CPU architecture name of underlying OS", () => {
- // https://on.cypress.io/arch
- expect(Cypress.arch).to.exist;
- });
- });
-
- context("Cypress.config()", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get and set configuration options", () => {
- // https://on.cypress.io/config
- let myConfig = Cypress.config();
-
- expect(myConfig).to.have.property("animationDistanceThreshold", 5);
- expect(myConfig).to.have.property("baseUrl", null);
- expect(myConfig).to.have.property("defaultCommandTimeout", 4000);
- expect(myConfig).to.have.property("requestTimeout", 5000);
- expect(myConfig).to.have.property("responseTimeout", 30000);
- expect(myConfig).to.have.property("viewportHeight", 660);
- expect(myConfig).to.have.property("viewportWidth", 1000);
- expect(myConfig).to.have.property("pageLoadTimeout", 60000);
- expect(myConfig).to.have.property("waitForAnimations", true);
-
- expect(Cypress.config("pageLoadTimeout")).to.eq(60000);
-
- // this will change the config for the rest of your tests!
- Cypress.config("pageLoadTimeout", 20000);
-
- expect(Cypress.config("pageLoadTimeout")).to.eq(20000);
-
- Cypress.config("pageLoadTimeout", 60000);
- });
- });
-
- context("Cypress.dom", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/dom
- it(".isHidden() - determine if a DOM element is hidden", () => {
- let hiddenP = Cypress.$(".dom-p p.hidden").get(0);
- let visibleP = Cypress.$(".dom-p p.visible").get(0);
-
- // our first paragraph has css class 'hidden'
- expect(Cypress.dom.isHidden(hiddenP)).to.be.true;
- expect(Cypress.dom.isHidden(visibleP)).to.be.false;
- });
- });
-
- context("Cypress.env()", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // We can set environment variables for highly dynamic values
-
- // https://on.cypress.io/environment-variables
- it("Get environment variables", () => {
- // https://on.cypress.io/env
- // set multiple environment variables
- Cypress.env({
- host: "veronica.dev.local",
- api_server: "http://localhost:8888/v1/",
- });
-
- // get environment variable
- expect(Cypress.env("host")).to.eq("veronica.dev.local");
-
- // set environment variable
- Cypress.env("api_server", "http://localhost:8888/v2/");
- expect(Cypress.env("api_server")).to.eq("http://localhost:8888/v2/");
-
- // get all environment variable
- expect(Cypress.env()).to.have.property("host", "veronica.dev.local");
- expect(Cypress.env()).to.have.property(
- "api_server",
- "http://localhost:8888/v2/",
- );
- });
- });
-
- context("Cypress.log", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Control what is printed to the Command Log", () => {
- // https://on.cypress.io/cypress-log
- });
- });
-
- context("Cypress.platform", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get underlying OS name", () => {
- // https://on.cypress.io/platform
- expect(Cypress.platform).to.be.exist;
- });
- });
-
- context("Cypress.version", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get current version of Cypress being run", () => {
- // https://on.cypress.io/version
- expect(Cypress.version).to.be.exist;
- });
- });
-
- context("Cypress.spec", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get current spec information", () => {
- // https://on.cypress.io/spec
- // wrap the object so we can inspect it easily by clicking in the command log
- cy.wrap(Cypress.spec).should("include.keys", [
- "name",
- "relative",
- "absolute",
- ]);
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/files.cy.js b/cypress/e2e/2-advanced-examples/files.cy.js
deleted file mode 100644
index d161b309..00000000
--- a/cypress/e2e/2-advanced-examples/files.cy.js
+++ /dev/null
@@ -1,87 +0,0 @@
-///
-
-/// JSON fixture file can be loaded directly using
-// the built-in JavaScript bundler
-const requiredExample = require("../../fixtures/example");
-
-context("Files", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/files");
-
- // load example.json fixture file and store
- // in the test context object
- cy.fixture("example.json").as("example");
- });
-
- it("cy.fixture() - load a fixture", () => {
- // https://on.cypress.io/fixture
-
- // Instead of writing a response inline you can
- // use a fixture file's content.
-
- // when application makes an Ajax request matching "GET **/comments/*"
- // Cypress will intercept it and reply with the object in `example.json` fixture
- cy.intercept("GET", "**/comments/*", { fixture: "example.json" }).as(
- "getComment",
- );
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".fixture-btn").click();
-
- cy.wait("@getComment")
- .its("response.body")
- .should("have.property", "name")
- .and("include", "Using fixtures to represent data");
- });
-
- it("cy.fixture() or require - load a fixture", function () {
- // we are inside the "function () { ... }"
- // callback and can use test context object "this"
- // "this.example" was loaded in "beforeEach" function callback
- expect(this.example, "fixture in the test context").to.deep.equal(
- requiredExample,
- );
-
- // or use "cy.wrap" and "should('deep.equal', ...)" assertion
- cy.wrap(this.example).should("deep.equal", requiredExample);
- });
-
- it("cy.readFile() - read file contents", () => {
- // https://on.cypress.io/readfile
-
- // You can read a file and yield its contents
- // The filePath is relative to your project's root.
- cy.readFile(Cypress.config("configFile")).then((config) => {
- expect(config).to.be.an("string");
- });
- });
-
- it("cy.writeFile() - write to a file", () => {
- // https://on.cypress.io/writefile
-
- // You can write to a file
-
- // Use a response from a request to automatically
- // generate a fixture file for use later
- cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
- cy.writeFile("cypress/fixtures/users.json", response.body);
- });
-
- cy.fixture("users").should((users) => {
- expect(users[0].name).to.exist;
- });
-
- // JavaScript arrays and objects are stringified
- // and formatted into text.
- cy.writeFile("cypress/fixtures/profile.json", {
- id: 8739,
- name: "Jane",
- email: "jane@example.com",
- });
-
- cy.fixture("profile").should((profile) => {
- expect(profile.name).to.eq("Jane");
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/location.cy.js b/cypress/e2e/2-advanced-examples/location.cy.js
deleted file mode 100644
index 6f797f14..00000000
--- a/cypress/e2e/2-advanced-examples/location.cy.js
+++ /dev/null
@@ -1,34 +0,0 @@
-///
-
-context("Location", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/location");
- });
-
- it("cy.hash() - get the current URL hash", () => {
- // https://on.cypress.io/hash
- cy.hash().should("be.empty");
- });
-
- it("cy.location() - get window.location", () => {
- // https://on.cypress.io/location
- cy.location().should((location) => {
- expect(location.hash).to.be.empty;
- expect(location.href).to.eq(
- "https://example.cypress.io/commands/location",
- );
- expect(location.host).to.eq("example.cypress.io");
- expect(location.hostname).to.eq("example.cypress.io");
- expect(location.origin).to.eq("https://example.cypress.io");
- expect(location.pathname).to.eq("/commands/location");
- expect(location.port).to.eq("");
- expect(location.protocol).to.eq("https:");
- expect(location.search).to.be.empty;
- });
- });
-
- it("cy.url() - get the current URL", () => {
- // https://on.cypress.io/url
- cy.url().should("eq", "https://example.cypress.io/commands/location");
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/misc.cy.js b/cypress/e2e/2-advanced-examples/misc.cy.js
deleted file mode 100644
index fc6df9aa..00000000
--- a/cypress/e2e/2-advanced-examples/misc.cy.js
+++ /dev/null
@@ -1,106 +0,0 @@
-///
-
-context("Misc", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/misc");
- });
-
- it(".end() - end the command chain", () => {
- // https://on.cypress.io/end
-
- // cy.end is useful when you want to end a chain of commands
- // and force Cypress to re-query from the root element
- cy.get(".misc-table").within(() => {
- // ends the current chain and yields null
- cy.contains("Cheryl").click().end();
-
- // queries the entire table again
- cy.contains("Charles").click();
- });
- });
-
- it("cy.exec() - execute a system command", () => {
- // execute a system command.
- // so you can take actions necessary for
- // your test outside the scope of Cypress.
- // https://on.cypress.io/exec
-
- // we can use Cypress.platform string to
- // select appropriate command
- // https://on.cypress/io/platform
- cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
-
- // on CircleCI Windows build machines we have a failure to run bash shell
- // https://github.com/cypress-io/cypress/issues/5169
- // so skip some of the tests by passing flag "--env circle=true"
- const isCircleOnWindows =
- Cypress.platform === "win32" && Cypress.env("circle");
-
- if (isCircleOnWindows) {
- cy.log("Skipping test on CircleCI");
-
- return;
- }
-
- // cy.exec problem on Shippable CI
- // https://github.com/cypress-io/cypress/issues/6718
- const isShippable =
- Cypress.platform === "linux" && Cypress.env("shippable");
-
- if (isShippable) {
- cy.log("Skipping test on ShippableCI");
-
- return;
- }
-
- cy.exec("echo Jane Lane").its("stdout").should("contain", "Jane Lane");
-
- if (Cypress.platform === "win32") {
- cy.exec(`print ${Cypress.config("configFile")}`)
- .its("stderr")
- .should("be.empty");
- } else {
- cy.exec(`cat ${Cypress.config("configFile")}`)
- .its("stderr")
- .should("be.empty");
-
- cy.exec("pwd").its("code").should("eq", 0);
- }
- });
-
- it("cy.focused() - get the DOM element that has focus", () => {
- // https://on.cypress.io/focused
- cy.get(".misc-form").find("#name").click();
- cy.focused().should("have.id", "name");
-
- cy.get(".misc-form").find("#description").click();
- cy.focused().should("have.id", "description");
- });
-
- context("Cypress.Screenshot", function () {
- it("cy.screenshot() - take a screenshot", () => {
- // https://on.cypress.io/screenshot
- cy.screenshot("my-image");
- });
-
- it("Cypress.Screenshot.defaults() - change default config of screenshots", function () {
- Cypress.Screenshot.defaults({
- blackout: [".foo"],
- capture: "viewport",
- clip: { x: 0, y: 0, width: 200, height: 200 },
- scale: false,
- disableTimersAndAnimations: true,
- screenshotOnRunFailure: true,
- onBeforeScreenshot() {},
- onAfterScreenshot() {},
- });
- });
- });
-
- it("cy.wrap() - wrap an object", () => {
- // https://on.cypress.io/wrap
- cy.wrap({ foo: "bar" })
- .should("have.property", "foo")
- .and("include", "bar");
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/navigation.cy.js b/cypress/e2e/2-advanced-examples/navigation.cy.js
deleted file mode 100644
index 2bdae554..00000000
--- a/cypress/e2e/2-advanced-examples/navigation.cy.js
+++ /dev/null
@@ -1,56 +0,0 @@
-///
-
-context("Navigation", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io");
- cy.get(".navbar-nav").contains("Commands").click();
- cy.get(".dropdown-menu").contains("Navigation").click();
- });
-
- it("cy.go() - go back or forward in the browser's history", () => {
- // https://on.cypress.io/go
-
- cy.location("pathname").should("include", "navigation");
-
- cy.go("back");
- cy.location("pathname").should("not.include", "navigation");
-
- cy.go("forward");
- cy.location("pathname").should("include", "navigation");
-
- // clicking back
- cy.go(-1);
- cy.location("pathname").should("not.include", "navigation");
-
- // clicking forward
- cy.go(1);
- cy.location("pathname").should("include", "navigation");
- });
-
- it("cy.reload() - reload the page", () => {
- // https://on.cypress.io/reload
- cy.reload();
-
- // reload the page without using the cache
- cy.reload(true);
- });
-
- it("cy.visit() - visit a remote url", () => {
- // https://on.cypress.io/visit
-
- // Visit any sub-domain of your current domain
-
- // Pass options to the visit
- cy.visit("https://example.cypress.io/commands/navigation", {
- timeout: 50000, // increase total time for the visit to resolve
- onBeforeLoad(contentWindow) {
- // contentWindow is the remote page's window object
- expect(typeof contentWindow === "object").to.be.true;
- },
- onLoad(contentWindow) {
- // contentWindow is the remote page's window object
- expect(typeof contentWindow === "object").to.be.true;
- },
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/network_requests.cy.js b/cypress/e2e/2-advanced-examples/network_requests.cy.js
deleted file mode 100644
index 0d49015f..00000000
--- a/cypress/e2e/2-advanced-examples/network_requests.cy.js
+++ /dev/null
@@ -1,184 +0,0 @@
-///
-
-context("Network Requests", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/network-requests");
- });
-
- // Manage HTTP requests in your app
-
- it("cy.request() - make an XHR request", () => {
- // https://on.cypress.io/request
- cy.request("https://jsonplaceholder.cypress.io/comments").should(
- (response) => {
- expect(response.status).to.eq(200);
- // the server sometimes gets an extra comment posted from another machine
- // which gets returned as 1 extra object
- expect(response.body)
- .to.have.property("length")
- .and.be.oneOf([500, 501]);
- expect(response).to.have.property("headers");
- expect(response).to.have.property("duration");
- },
- );
- });
-
- it("cy.request() - verify response using BDD syntax", () => {
- cy.request("https://jsonplaceholder.cypress.io/comments").then(
- (response) => {
- // https://on.cypress.io/assertions
- expect(response).property("status").to.equal(200);
- expect(response)
- .property("body")
- .to.have.property("length")
- .and.be.oneOf([500, 501]);
- expect(response).to.include.keys("headers", "duration");
- },
- );
- });
-
- it("cy.request() with query parameters", () => {
- // will execute request
- // https://jsonplaceholder.cypress.io/comments?postId=1&id=3
- cy.request({
- url: "https://jsonplaceholder.cypress.io/comments",
- qs: {
- postId: 1,
- id: 3,
- },
- })
- .its("body")
- .should("be.an", "array")
- .and("have.length", 1)
- .its("0") // yields first element of the array
- .should("contain", {
- postId: 1,
- id: 3,
- });
- });
-
- it("cy.request() - pass result to the second request", () => {
- // first, let's find out the userId of the first user we have
- cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
- .its("body") // yields the response object
- .its("0") // yields the first element of the returned list
- // the above two commands its('body').its('0')
- // can be written as its('body.0')
- // if you do not care about TypeScript checks
- .then((user) => {
- expect(user).property("id").to.be.a("number");
- // make a new post on behalf of the user
- cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
- userId: user.id,
- title: "Cypress Test Runner",
- body: "Fast, easy and reliable testing for anything that runs in a browser.",
- });
- })
- // note that the value here is the returned value of the 2nd request
- // which is the new post object
- .then((response) => {
- expect(response).property("status").to.equal(201); // new entity created
- expect(response).property("body").to.contain({
- title: "Cypress Test Runner",
- });
-
- // we don't know the exact post id - only that it will be > 100
- // since JSONPlaceholder has built-in 100 posts
- expect(response.body)
- .property("id")
- .to.be.a("number")
- .and.to.be.gt(100);
-
- // we don't know the user id here - since it was in above closure
- // so in this test just confirm that the property is there
- expect(response.body).property("userId").to.be.a("number");
- });
- });
-
- it("cy.request() - save response in the shared test context", () => {
- // https://on.cypress.io/variables-and-aliases
- cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
- .its("body")
- .its("0") // yields the first element of the returned list
- .as("user") // saves the object in the test context
- .then(function () {
- // NOTE đŸ‘€
- // By the time this callback runs the "as('user')" command
- // has saved the user object in the test context.
- // To access the test context we need to use
- // the "function () { ... }" callback form,
- // otherwise "this" points at a wrong or undefined object!
- cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
- userId: this.user.id,
- title: "Cypress Test Runner",
- body: "Fast, easy and reliable testing for anything that runs in a browser.",
- })
- .its("body")
- .as("post"); // save the new post from the response
- })
- .then(function () {
- // When this callback runs, both "cy.request" API commands have finished
- // and the test context has "user" and "post" objects set.
- // Let's verify them.
- expect(this.post, "post has the right user id")
- .property("userId")
- .to.equal(this.user.id);
- });
- });
-
- it("cy.intercept() - route responses to matching requests", () => {
- // https://on.cypress.io/intercept
-
- let message = "whoa, this comment does not exist";
-
- // Listen to GET to comments/1
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // https://on.cypress.io/wait
- cy.wait("@getComment")
- .its("response.statusCode")
- .should("be.oneOf", [200, 304]);
-
- // Listen to POST to comments
- cy.intercept("POST", "**/comments").as("postComment");
-
- // we have code that posts a comment when
- // the button is clicked in scripts.js
- cy.get(".network-post").click();
- cy.wait("@postComment").should(({ request, response }) => {
- expect(request.body).to.include("email");
- expect(request.headers).to.have.property("content-type");
- expect(response && response.body).to.have.property(
- "name",
- "Using POST in cy.intercept()",
- );
- });
-
- // Stub a response to PUT comments/ ****
- cy.intercept(
- {
- method: "PUT",
- url: "**/comments/*",
- },
- {
- statusCode: 404,
- body: { error: message },
- headers: { "access-control-allow-origin": "*" },
- delayMs: 500,
- },
- ).as("putComment");
-
- // we have code that puts a comment when
- // the button is clicked in scripts.js
- cy.get(".network-put").click();
-
- cy.wait("@putComment");
-
- // our 404 statusCode logic in scripts.js executed
- cy.get(".network-put-comment").should("contain", message);
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/querying.cy.js b/cypress/e2e/2-advanced-examples/querying.cy.js
deleted file mode 100644
index 3bdef3e8..00000000
--- a/cypress/e2e/2-advanced-examples/querying.cy.js
+++ /dev/null
@@ -1,106 +0,0 @@
-///
-
-context("Querying", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/querying");
- });
-
- // The most commonly used query is 'cy.get()', you can
- // think of this like the '$' in jQuery
-
- it("cy.get() - query DOM elements", () => {
- // https://on.cypress.io/get
-
- cy.get("#query-btn").should("contain", "Button");
-
- cy.get(".query-btn").should("contain", "Button");
-
- cy.get("#querying .well>button:first").should("contain", "Button");
- // ↲
- // Use CSS selectors just like jQuery
-
- cy.get('[data-test-id="test-example"]').should("have.class", "example");
-
- // 'cy.get()' yields jQuery object, you can get its attribute
- // by invoking `.attr()` method
- cy.get('[data-test-id="test-example"]')
- .invoke("attr", "data-test-id")
- .should("equal", "test-example");
-
- // or you can get element's CSS property
- cy.get('[data-test-id="test-example"]')
- .invoke("css", "position")
- .should("equal", "static");
-
- // or use assertions directly during 'cy.get()'
- // https://on.cypress.io/assertions
- cy.get('[data-test-id="test-example"]')
- .should("have.attr", "data-test-id", "test-example")
- .and("have.css", "position", "static");
- });
-
- it("cy.contains() - query DOM elements with matching content", () => {
- // https://on.cypress.io/contains
- cy.get(".query-list").contains("bananas").should("have.class", "third");
-
- // we can pass a regexp to `.contains()`
- cy.get(".query-list").contains(/^b\w+/).should("have.class", "third");
-
- cy.get(".query-list").contains("apples").should("have.class", "first");
-
- // passing a selector to contains will
- // yield the selector containing the text
- cy.get("#querying")
- .contains("ul", "oranges")
- .should("have.class", "query-list");
-
- cy.get(".query-button").contains("Save Form").should("have.class", "btn");
- });
-
- it(".within() - query DOM elements within a specific element", () => {
- // https://on.cypress.io/within
- cy.get(".query-form").within(() => {
- cy.get("input:first").should("have.attr", "placeholder", "Email");
- cy.get("input:last").should("have.attr", "placeholder", "Password");
- });
- });
-
- it("cy.root() - query the root DOM element", () => {
- // https://on.cypress.io/root
-
- // By default, root is the document
- cy.root().should("match", "html");
-
- cy.get(".query-ul").within(() => {
- // In this within, the root is now the ul DOM element
- cy.root().should("have.class", "query-ul");
- });
- });
-
- it("best practices - selecting elements", () => {
- // https://on.cypress.io/best-practices#Selecting-Elements
- cy.get("[data-cy=best-practices-selecting-elements]").within(() => {
- // Worst - too generic, no context
- cy.get("button").click();
-
- // Bad. Coupled to styling. Highly subject to change.
- cy.get(".btn.btn-large").click();
-
- // Average. Coupled to the `name` attribute which has HTML semantics.
- cy.get("[name=submission]").click();
-
- // Better. But still coupled to styling or JS event listeners.
- cy.get("#main").click();
-
- // Slightly better. Uses an ID but also ensures the element
- // has an ARIA role attribute
- cy.get("#main[role=button]").click();
-
- // Much better. But still coupled to text content that may change.
- cy.contains("Submit").click();
-
- // Best. Insulated from all changes.
- cy.get("[data-cy=submit]").click();
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js b/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
deleted file mode 100644
index c4080a9b..00000000
--- a/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
+++ /dev/null
@@ -1,213 +0,0 @@
-///
-
-context("Spies, Stubs, and Clock", () => {
- it("cy.spy() - wrap a method in a spy", () => {
- // https://on.cypress.io/spy
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- foo() {},
- };
-
- const spy = cy.spy(obj, "foo").as("anyArgs");
-
- obj.foo();
-
- expect(spy).to.be.called;
- });
-
- it("cy.spy() retries until assertions pass", () => {
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- /**
- * Prints the argument passed
- * @param x {any}
- */
- foo(x) {
- console.log("obj.foo called with", x);
- },
- };
-
- cy.spy(obj, "foo").as("foo");
-
- setTimeout(() => {
- obj.foo("first");
- }, 500);
-
- setTimeout(() => {
- obj.foo("second");
- }, 2500);
-
- cy.get("@foo").should("have.been.calledTwice");
- });
-
- it("cy.stub() - create a stub and/or replace a function with stub", () => {
- // https://on.cypress.io/stub
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- /**
- * prints both arguments to the console
- * @param a {string}
- * @param b {string}
- */
- foo(a, b) {
- console.log("a", a, "b", b);
- },
- };
-
- const stub = cy.stub(obj, "foo").as("foo");
-
- obj.foo("foo", "bar");
-
- expect(stub).to.be.called;
- });
-
- it("cy.clock() - control time in the browser", () => {
- // https://on.cypress.io/clock
-
- // create the date in UTC so its always the same
- // no matter what local timezone the browser is running in
- const now = new Date(Date.UTC(2017, 2, 14)).getTime();
-
- cy.clock(now);
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
- cy.get("#clock-div").click().should("have.text", "1489449600");
- });
-
- it("cy.tick() - move time in the browser", () => {
- // https://on.cypress.io/tick
-
- // create the date in UTC so its always the same
- // no matter what local timezone the browser is running in
- const now = new Date(Date.UTC(2017, 2, 14)).getTime();
-
- cy.clock(now);
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
- cy.get("#tick-div").click().should("have.text", "1489449600");
-
- cy.tick(10000); // 10 seconds passed
- cy.get("#tick-div").click().should("have.text", "1489449610");
- });
-
- it("cy.stub() matches depending on arguments", () => {
- // see all possible matchers at
- // https://sinonjs.org/releases/latest/matchers/
- const greeter = {
- /**
- * Greets a person
- * @param {string} name
- */
- greet(name) {
- return `Hello, ${name}!`;
- },
- };
-
- cy.stub(greeter, "greet")
- .callThrough() // if you want non-matched calls to call the real method
- .withArgs(Cypress.sinon.match.string)
- .returns("Hi")
- .withArgs(Cypress.sinon.match.number)
- .throws(new Error("Invalid name"));
-
- expect(greeter.greet("World")).to.equal("Hi");
- expect(() => greeter.greet(42)).to.throw("Invalid name");
- expect(greeter.greet).to.have.been.calledTwice;
-
- // non-matched calls goes the actual method
- expect(greeter.greet()).to.equal("Hello, undefined!");
- });
-
- it("matches call arguments using Sinon matchers", () => {
- // see all possible matchers at
- // https://sinonjs.org/releases/latest/matchers/
- const calculator = {
- /**
- * returns the sum of two arguments
- * @param a {number}
- * @param b {number}
- */
- add(a, b) {
- return a + b;
- },
- };
-
- const spy = cy.spy(calculator, "add").as("add");
-
- expect(calculator.add(2, 3)).to.equal(5);
-
- // if we want to assert the exact values used during the call
- expect(spy).to.be.calledWith(2, 3);
-
- // let's confirm "add" method was called with two numbers
- expect(spy).to.be.calledWith(
- Cypress.sinon.match.number,
- Cypress.sinon.match.number,
- );
-
- // alternatively, provide the value to match
- expect(spy).to.be.calledWith(
- Cypress.sinon.match(2),
- Cypress.sinon.match(3),
- );
-
- // match any value
- expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3);
-
- // match any value from a list
- expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3);
-
- /**
- * Returns true if the given number is even
- * @param {number} x
- */
- const isEven = (x) => x % 2 === 0;
-
- // expect the value to pass a custom predicate function
- // the second argument to "sinon.match(predicate, message)" is
- // shown if the predicate does not pass and assertion fails
- expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, "isEven"), 3);
-
- /**
- * Returns a function that checks if a given number is larger than the limit
- * @param {number} limit
- * @returns {(x: number) => boolean}
- */
- const isGreaterThan = (limit) => (x) => x > limit;
-
- /**
- * Returns a function that checks if a given number is less than the limit
- * @param {number} limit
- * @returns {(x: number) => boolean}
- */
- const isLessThan = (limit) => (x) => x < limit;
-
- // you can combine several matchers using "and", "or"
- expect(spy).to.be.calledWith(
- Cypress.sinon.match.number,
- Cypress.sinon
- .match(isGreaterThan(2), "> 2")
- .and(Cypress.sinon.match(isLessThan(4), "< 4")),
- );
-
- expect(spy).to.be.calledWith(
- Cypress.sinon.match.number,
- Cypress.sinon
- .match(isGreaterThan(200), "> 200")
- .or(Cypress.sinon.match(3)),
- );
-
- // matchers can be used from BDD assertions
- cy.get("@add").should(
- "have.been.calledWith",
- Cypress.sinon.match.number,
- Cypress.sinon.match(3),
- );
-
- // you can alias matchers for shorter test code
- const { match: M } = Cypress.sinon;
-
- cy.get("@add").should("have.been.calledWith", M.number, M(3));
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/storage.cy.js b/cypress/e2e/2-advanced-examples/storage.cy.js
deleted file mode 100644
index f9277940..00000000
--- a/cypress/e2e/2-advanced-examples/storage.cy.js
+++ /dev/null
@@ -1,116 +0,0 @@
-///
-
-context("Local Storage / Session Storage", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/storage");
- });
- // Although localStorage is automatically cleared
- // in between tests to maintain a clean state
- // sometimes we need to clear localStorage manually
-
- it("cy.clearLocalStorage() - clear all data in localStorage for the current origin", () => {
- // https://on.cypress.io/clearlocalstorage
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // clearLocalStorage() yields the localStorage object
- cy.clearLocalStorage().should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.be.null;
- expect(ls.getItem("prop3")).to.be.null;
- });
-
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // Clear key matching string in localStorage
- cy.clearLocalStorage("prop1").should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.eq("blue");
- expect(ls.getItem("prop3")).to.eq("magenta");
- });
-
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // Clear keys matching regex in localStorage
- cy.clearLocalStorage(/prop1|2/).should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.be.null;
- expect(ls.getItem("prop3")).to.eq("magenta");
- });
- });
-
- it("cy.getAllLocalStorage() - get all data in localStorage for all origins", () => {
- // https://on.cypress.io/getalllocalstorage
- cy.get(".ls-btn").click();
-
- // getAllLocalStorage() yields a map of origins to localStorage values
- cy.getAllLocalStorage().should((storageMap) => {
- expect(storageMap).to.deep.equal({
- // other origins will also be present if localStorage is set on them
- "https://example.cypress.io": {
- prop1: "red",
- prop2: "blue",
- prop3: "magenta",
- },
- });
- });
- });
-
- it("cy.clearAllLocalStorage() - clear all data in localStorage for all origins", () => {
- // https://on.cypress.io/clearalllocalstorage
- cy.get(".ls-btn").click();
-
- // clearAllLocalStorage() yields null
- cy.clearAllLocalStorage().should(() => {
- expect(sessionStorage.getItem("prop1")).to.be.null;
- expect(sessionStorage.getItem("prop2")).to.be.null;
- expect(sessionStorage.getItem("prop3")).to.be.null;
- });
- });
-
- it("cy.getAllSessionStorage() - get all data in sessionStorage for all origins", () => {
- // https://on.cypress.io/getallsessionstorage
- cy.get(".ls-btn").click();
-
- // getAllSessionStorage() yields a map of origins to sessionStorage values
- cy.getAllSessionStorage().should((storageMap) => {
- expect(storageMap).to.deep.equal({
- // other origins will also be present if sessionStorage is set on them
- "https://example.cypress.io": {
- prop4: "cyan",
- prop5: "yellow",
- prop6: "black",
- },
- });
- });
- });
-
- it("cy.clearAllSessionStorage() - clear all data in sessionStorage for all origins", () => {
- // https://on.cypress.io/clearallsessionstorage
- cy.get(".ls-btn").click();
-
- // clearAllSessionStorage() yields null
- cy.clearAllSessionStorage().should(() => {
- expect(sessionStorage.getItem("prop4")).to.be.null;
- expect(sessionStorage.getItem("prop5")).to.be.null;
- expect(sessionStorage.getItem("prop6")).to.be.null;
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/traversal.cy.js b/cypress/e2e/2-advanced-examples/traversal.cy.js
deleted file mode 100644
index 2ee4b9bf..00000000
--- a/cypress/e2e/2-advanced-examples/traversal.cy.js
+++ /dev/null
@@ -1,116 +0,0 @@
-///
-
-context("Traversal", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/traversal");
- });
-
- it(".children() - get child DOM elements", () => {
- // https://on.cypress.io/children
- cy.get(".traversal-breadcrumb")
- .children(".active")
- .should("contain", "Data");
- });
-
- it(".closest() - get closest ancestor DOM element", () => {
- // https://on.cypress.io/closest
- cy.get(".traversal-badge").closest("ul").should("have.class", "list-group");
- });
-
- it(".eq() - get a DOM element at a specific index", () => {
- // https://on.cypress.io/eq
- cy.get(".traversal-list>li").eq(1).should("contain", "siamese");
- });
-
- it(".filter() - get DOM elements that match the selector", () => {
- // https://on.cypress.io/filter
- cy.get(".traversal-nav>li").filter(".active").should("contain", "About");
- });
-
- it(".find() - get descendant DOM elements of the selector", () => {
- // https://on.cypress.io/find
- cy.get(".traversal-pagination")
- .find("li")
- .find("a")
- .should("have.length", 7);
- });
-
- it(".first() - get first DOM element", () => {
- // https://on.cypress.io/first
- cy.get(".traversal-table td").first().should("contain", "1");
- });
-
- it(".last() - get last DOM element", () => {
- // https://on.cypress.io/last
- cy.get(".traversal-buttons .btn").last().should("contain", "Submit");
- });
-
- it(".next() - get next sibling DOM element", () => {
- // https://on.cypress.io/next
- cy.get(".traversal-ul")
- .contains("apples")
- .next()
- .should("contain", "oranges");
- });
-
- it(".nextAll() - get all next sibling DOM elements", () => {
- // https://on.cypress.io/nextall
- cy.get(".traversal-next-all")
- .contains("oranges")
- .nextAll()
- .should("have.length", 3);
- });
-
- it(".nextUntil() - get next sibling DOM elements until next el", () => {
- // https://on.cypress.io/nextuntil
- cy.get("#veggies").nextUntil("#nuts").should("have.length", 3);
- });
-
- it(".not() - remove DOM elements from set of DOM elements", () => {
- // https://on.cypress.io/not
- cy.get(".traversal-disabled .btn")
- .not("[disabled]")
- .should("not.contain", "Disabled");
- });
-
- it(".parent() - get parent DOM element from DOM elements", () => {
- // https://on.cypress.io/parent
- cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus");
- });
-
- it(".parents() - get parent DOM elements from DOM elements", () => {
- // https://on.cypress.io/parents
- cy.get(".traversal-cite").parents().should("match", "blockquote");
- });
-
- it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => {
- // https://on.cypress.io/parentsuntil
- cy.get(".clothes-nav")
- .find(".active")
- .parentsUntil(".clothes-nav")
- .should("have.length", 2);
- });
-
- it(".prev() - get previous sibling DOM element", () => {
- // https://on.cypress.io/prev
- cy.get(".birds").find(".active").prev().should("contain", "Lorikeets");
- });
-
- it(".prevAll() - get all previous sibling DOM elements", () => {
- // https://on.cypress.io/prevall
- cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2);
- });
-
- it(".prevUntil() - get all previous sibling DOM elements until el", () => {
- // https://on.cypress.io/prevuntil
- cy.get(".foods-list")
- .find("#nuts")
- .prevUntil("#veggies")
- .should("have.length", 3);
- });
-
- it(".siblings() - get all sibling DOM elements", () => {
- // https://on.cypress.io/siblings
- cy.get(".traversal-pills .active").siblings().should("have.length", 2);
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/utilities.cy.js b/cypress/e2e/2-advanced-examples/utilities.cy.js
deleted file mode 100644
index aa271b62..00000000
--- a/cypress/e2e/2-advanced-examples/utilities.cy.js
+++ /dev/null
@@ -1,109 +0,0 @@
-///
-
-context("Utilities", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/utilities");
- });
-
- it("Cypress._ - call a lodash method", () => {
- // https://on.cypress.io/_
- cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
- let ids = Cypress._.chain(response.body).map("id").take(3).value();
-
- expect(ids).to.deep.eq([1, 2, 3]);
- });
- });
-
- it("Cypress.$ - call a jQuery method", () => {
- // https://on.cypress.io/$
- let $li = Cypress.$(".utility-jquery li:first");
-
- cy.wrap($li)
- .should("not.have.class", "active")
- .click()
- .should("have.class", "active");
- });
-
- it("Cypress.Blob - blob utilities and base64 string conversion", () => {
- // https://on.cypress.io/blob
- cy.get(".utility-blob").then(($div) => {
- // https://github.com/nolanlawson/blob-util#imgSrcToDataURL
- // get the dataUrl string for the javascript-logo
- return Cypress.Blob.imgSrcToDataURL(
- "https://example.cypress.io/assets/img/javascript-logo.png",
- undefined,
- "anonymous",
- ).then((dataUrl) => {
- // create an element and set its src to the dataUrl
- let img = Cypress.$("", { src: dataUrl });
-
- // need to explicitly return cy here since we are initially returning
- // the Cypress.Blob.imgSrcToDataURL promise to our test
- // append the image
- $div.append(img);
-
- cy.get(".utility-blob img").click().should("have.attr", "src", dataUrl);
- });
- });
- });
-
- it("Cypress.minimatch - test out glob patterns against strings", () => {
- // https://on.cypress.io/minimatch
- let matching = Cypress.minimatch("/users/1/comments", "/users/*/comments", {
- matchBase: true,
- });
-
- expect(matching, "matching wildcard").to.be.true;
-
- matching = Cypress.minimatch("/users/1/comments/2", "/users/*/comments", {
- matchBase: true,
- });
-
- expect(matching, "comments").to.be.false;
-
- // ** matches against all downstream path segments
- matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/**", {
- matchBase: true,
- });
-
- expect(matching, "comments").to.be.true;
-
- // whereas * matches only the next path segment
-
- matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/*", {
- matchBase: false,
- });
-
- expect(matching, "comments").to.be.false;
- });
-
- it("Cypress.Promise - instantiate a bluebird promise", () => {
- // https://on.cypress.io/promise
- let waited = false;
-
- /**
- * @return Bluebird
- */
- function waitOneSecond() {
- // return a promise that resolves after 1 second
- return new Cypress.Promise((resolve, reject) => {
- setTimeout(() => {
- // set waited to true
- waited = true;
-
- // resolve with 'foo' string
- resolve("foo");
- }, 1000);
- });
- }
-
- cy.then(() => {
- // return a promise to cy.then() that
- // is awaited until it resolves
- return waitOneSecond().then((str) => {
- expect(str).to.eq("foo");
- expect(waited).to.be.true;
- });
- });
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/viewport.cy.js b/cypress/e2e/2-advanced-examples/viewport.cy.js
deleted file mode 100644
index 2d0644ab..00000000
--- a/cypress/e2e/2-advanced-examples/viewport.cy.js
+++ /dev/null
@@ -1,59 +0,0 @@
-///
-
-context("Viewport", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/viewport");
- });
-
- it("cy.viewport() - set the viewport size and dimension", () => {
- // https://on.cypress.io/viewport
-
- cy.get("#navbar").should("be.visible");
- cy.viewport(320, 480);
-
- // the navbar should have collapse since our screen is smaller
- cy.get("#navbar").should("not.be.visible");
- cy.get(".navbar-toggle").should("be.visible").click();
- cy.get(".nav").find("a").should("be.visible");
-
- // lets see what our app looks like on a super large screen
- cy.viewport(2999, 2999);
-
- // cy.viewport() accepts a set of preset sizes
- // to easily set the screen to a device's width and height
-
- // We added a cy.wait() between each viewport change so you can see
- // the change otherwise it is a little too fast to see :)
-
- cy.viewport("macbook-15");
- cy.wait(200);
- cy.viewport("macbook-13");
- cy.wait(200);
- cy.viewport("macbook-11");
- cy.wait(200);
- cy.viewport("ipad-2");
- cy.wait(200);
- cy.viewport("ipad-mini");
- cy.wait(200);
- cy.viewport("iphone-6+");
- cy.wait(200);
- cy.viewport("iphone-6");
- cy.wait(200);
- cy.viewport("iphone-5");
- cy.wait(200);
- cy.viewport("iphone-4");
- cy.wait(200);
- cy.viewport("iphone-3");
- cy.wait(200);
-
- // cy.viewport() accepts an orientation for all presets
- // the default orientation is 'portrait'
- cy.viewport("ipad-2", "portrait");
- cy.wait(200);
- cy.viewport("iphone-4", "landscape");
- cy.wait(200);
-
- // The viewport will be reset back to the default dimensions
- // in between tests (the default can be set in cypress.config.{js|ts})
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/waiting.cy.js b/cypress/e2e/2-advanced-examples/waiting.cy.js
deleted file mode 100644
index 7e9feeb0..00000000
--- a/cypress/e2e/2-advanced-examples/waiting.cy.js
+++ /dev/null
@@ -1,33 +0,0 @@
-///
-
-context("Waiting", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/waiting");
- });
- // BE CAREFUL of adding unnecessary wait times.
- // https://on.cypress.io/best-practices#Unnecessary-Waiting
-
- // https://on.cypress.io/wait
- it("cy.wait() - wait for a specific amount of time", () => {
- cy.get(".wait-input1").type("Wait 1000ms after typing");
- cy.wait(1000);
- cy.get(".wait-input2").type("Wait 1000ms after typing");
- cy.wait(1000);
- cy.get(".wait-input3").type("Wait 1000ms after typing");
- cy.wait(1000);
- });
-
- it("cy.wait() - wait for a specific route", () => {
- // Listen to GET to comments/1
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // wait for GET comments/1
- cy.wait("@getComment")
- .its("response.statusCode")
- .should("be.oneOf", [200, 304]);
- });
-});
diff --git a/cypress/e2e/2-advanced-examples/window.cy.js b/cypress/e2e/2-advanced-examples/window.cy.js
deleted file mode 100644
index 9740ba04..00000000
--- a/cypress/e2e/2-advanced-examples/window.cy.js
+++ /dev/null
@@ -1,22 +0,0 @@
-///
-
-context("Window", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/window");
- });
-
- it("cy.window() - get the global window object", () => {
- // https://on.cypress.io/window
- cy.window().should("have.property", "top");
- });
-
- it("cy.document() - get the document object", () => {
- // https://on.cypress.io/document
- cy.document().should("have.property", "charset").and("eq", "UTF-8");
- });
-
- it("cy.title() - get the title", () => {
- // https://on.cypress.io/title
- cy.title().should("include", "Kitchen Sink");
- });
-});
diff --git a/cypress/fixtures/profile.json b/cypress/fixtures/profile.json
index a95e88f9..b6c355ca 100644
--- a/cypress/fixtures/profile.json
+++ b/cypress/fixtures/profile.json
@@ -2,4 +2,4 @@
"id": 8739,
"name": "Jane",
"email": "jane@example.com"
-}
+}
\ No newline at end of file
diff --git a/cypress/fixtures/users.json b/cypress/fixtures/users.json
index 82a0056b..79b699aa 100644
--- a/cypress/fixtures/users.json
+++ b/cypress/fixtures/users.json
@@ -229,4 +229,4 @@
"bs": "target end-to-end models"
}
}
-]
+]
\ No newline at end of file
diff --git a/cypress/screenshots/2-advanced-examples/misc.cy.js/my-image.png b/cypress/screenshots/2-advanced-examples/misc.cy.js/my-image.png
deleted file mode 100644
index 2fcaf653..00000000
Binary files a/cypress/screenshots/2-advanced-examples/misc.cy.js/my-image.png and /dev/null differ
diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json
new file mode 100644
index 00000000..03852b63
--- /dev/null
+++ b/cypress/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "es5",
+ "dom"
+ ],
+ "types": [
+ "cypress",
+ "node"
+ ]
+ },
+ "include": [
+ "../node_modules/cypress",
+ "**/*.ts"
+ ]
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index f9b741d1..bcf7f8e1 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"@heroicons/react": "^2.0.18",
"@reduxjs/toolkit": "^1.9.5",
"next": "13.4.12",
+ "next-themes": "^0.2.1",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-redux": "^8.1.2",
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index f6ee4da7..3e4b51a2 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,7 +1,7 @@
import "./globals.css";
import type { Metadata } from "next";
import { Inter } from "next/font/google";
-import { StoreProvider, Navbar } from "@/components";
+import { StoreProvider, Navbar, ThemeProvider } from "@/components";
export const metadata: Metadata = {
title: "Create Next App",
@@ -21,10 +21,20 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
-
+
-
- {children}
+
+
+ {children}
+
);
diff --git a/src/components/ModeToggle.tsx b/src/components/ModeToggle.tsx
new file mode 100644
index 00000000..16147eef
--- /dev/null
+++ b/src/components/ModeToggle.tsx
@@ -0,0 +1,35 @@
+"use client";
+
+import { useTheme } from "next-themes";
+import { SunIcon, MoonIcon } from "@heroicons/react/20/solid";
+import { ChangeEvent, useEffect, useState } from "react";
+
+export default function ModeToggle() {
+ const [mounted, setMounted] = useState(false);
+ const { setTheme, theme } = useTheme();
+
+ useEffect(() => {
+ setMounted(true);
+ }, []);
+
+ if (!mounted) {
+ return null;
+ }
+
+ const toggleTheme = (e: ChangeEvent) => {
+ setTheme(e.target.checked === true ? "light" : "dark");
+ };
+
+ return (
+
+ );
+}
diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx
new file mode 100644
index 00000000..71bbd00b
--- /dev/null
+++ b/src/components/ThemeProvider.tsx
@@ -0,0 +1,11 @@
+"use client";
+
+import * as React from "react";
+import { ThemeProvider as NextThemesProvider } from "next-themes";
+import { type ThemeProviderProps } from "next-themes/dist/types";
+
+function ThemeProvider({ children, ...props }: ThemeProviderProps) {
+ return {children};
+}
+
+export default ThemeProvider;
diff --git a/src/components/index.ts b/src/components/index.ts
index 7c17c28d..ea26fdb1 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -1,5 +1,7 @@
export { default as StoreProvider } from "./StoreProvider";
export { default as Avatar } from "./Avatar";
export { default as Button } from "./Button";
+export { default as ModeToggle } from "./ModeToggle";
+export { default as ThemeProvider } from "./ThemeProvider";
export { default as Banner } from "./Banner";
export * from "./navbar";
diff --git a/src/components/navbar/Navbar.tsx b/src/components/navbar/Navbar.tsx
index f83d2fd5..bbf7cbe7 100644
--- a/src/components/navbar/Navbar.tsx
+++ b/src/components/navbar/Navbar.tsx
@@ -1,17 +1,18 @@
-import { Avatar, Bell, ChinguMenu, DropDown } from "@/components";
+import { Avatar, Bell, ChinguMenu, DropDown, ModeToggle } from "@/components";
const name = "Yorick";
const notificationCount = 4;
export default function Navbar() {
return (
-