element", () => {
- // https://on.cypress.io/select
-
- // at first, no option should be selected
- cy.get(".action-select").should("have.value", "--Select a fruit--");
-
- // Select option(s) with matching text content
- cy.get(".action-select").select("apples");
- // confirm the apples were selected
- // note that each value starts with "fr-" in our HTML
- cy.get(".action-select").should("have.value", "fr-apples");
-
- cy.get(".action-select-multiple")
- .select(["apples", "oranges", "bananas"])
- // when getting multiple values, invoke "val" method first
- .invoke("val")
- .should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
-
- // Select option(s) with matching value
- cy.get(".action-select")
- .select("fr-bananas")
- // can attach an assertion right away to the element
- .should("have.value", "fr-bananas");
-
- cy.get(".action-select-multiple")
- .select(["fr-apples", "fr-oranges", "fr-bananas"])
- .invoke("val")
- .should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
-
- // assert the selected values include oranges
- cy.get(".action-select-multiple").invoke("val").should("include", "fr-oranges");
- });
-
- it(".scrollIntoView() - scroll an element into view", () => {
- // https://on.cypress.io/scrollintoview
-
- // normally all of these buttons are hidden,
- // because they're not within
- // the viewable area of their parent
- // (we need to scroll to see them)
- cy.get("#scroll-horizontal button").should("not.be.visible");
-
- // scroll the button into view, as if the user had scrolled
- cy.get("#scroll-horizontal button").scrollIntoView().should("be.visible");
-
- cy.get("#scroll-vertical button").should("not.be.visible");
-
- // Cypress handles the scroll direction needed
- cy.get("#scroll-vertical button").scrollIntoView().should("be.visible");
-
- cy.get("#scroll-both button").should("not.be.visible");
-
- // Cypress knows to scroll to the right and down
- cy.get("#scroll-both button").scrollIntoView().should("be.visible");
- });
-
- it(".trigger() - trigger an event on a DOM element", () => {
- // https://on.cypress.io/trigger
-
- // To interact with a range input (slider)
- // we need to set its value & trigger the
- // event to signal it changed
-
- // Here, we invoke jQuery's val() method to set
- // the value and trigger the 'change' event
- cy.get(".trigger-input-range")
- .invoke("val", 25)
- .trigger("change")
- .get("input[type=range]")
- .siblings("p")
- .should("have.text", "25");
- });
-
- it("cy.scrollTo() - scroll the window or element to a position", () => {
- // https://on.cypress.io/scrollto
-
- // You can scroll to 9 specific positions of an element:
- // -----------------------------------
- // | topLeft top topRight |
- // | |
- // | |
- // | |
- // | left center right |
- // | |
- // | |
- // | |
- // | bottomLeft bottom bottomRight |
- // -----------------------------------
-
- // if you chain .scrollTo() off of cy, we will
- // scroll the entire window
- cy.scrollTo("bottom");
-
- cy.get("#scrollable-horizontal").scrollTo("right");
-
- // or you can scroll to a specific coordinate:
- // (x axis, y axis) in pixels
- cy.get("#scrollable-vertical").scrollTo(250, 250);
-
- // or you can scroll to a specific percentage
- // of the (width, height) of the element
- cy.get("#scrollable-both").scrollTo("75%", "25%");
-
- // control the easing of the scroll (default is 'swing')
- cy.get("#scrollable-vertical").scrollTo("center", { easing: "linear" });
-
- // control the duration of the scroll (in ms)
- cy.get("#scrollable-both").scrollTo("center", { duration: 2000 });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/aliasing.cy.js b/client/cypress/e2e/2-advanced-examples/aliasing.cy.js
deleted file mode 100644
index 152b8ece9..000000000
--- a/client/cypress/e2e/2-advanced-examples/aliasing.cy.js
+++ /dev/null
@@ -1,35 +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/client/cypress/e2e/2-advanced-examples/assertions.cy.js b/client/cypress/e2e/2-advanced-examples/assertions.cy.js
deleted file mode 100644
index 2bde3a9a0..000000000
--- a/client/cypress/e2e/2-advanced-examples/assertions.cy.js
+++ /dev/null
@@ -1,173 +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
- // @ts-ignore TS6133 unused variable
- 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/client/cypress/e2e/2-advanced-examples/connectors.cy.js b/client/cypress/e2e/2-advanced-examples/connectors.cy.js
deleted file mode 100644
index 3cd60d308..000000000
--- a/client/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()
-
- // https://on.cypress.io/invoke
- cy.get(".connectors-div")
- .should("be.hidden")
- // call the jquery method 'show' on the 'div.container'
- .invoke("show")
- .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/client/cypress/e2e/2-advanced-examples/cookies.cy.js b/client/cypress/e2e/2-advanced-examples/cookies.cy.js
deleted file mode 100644
index 390ee76e2..000000000
--- a/client/cypress/e2e/2-advanced-examples/cookies.cy.js
+++ /dev/null
@@ -1,79 +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", () => {
- // 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.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", () => {
- // 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");
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js b/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js
deleted file mode 100644
index 1cd9f975e..000000000
--- a/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js
+++ /dev/null
@@ -1,208 +0,0 @@
-///
-
-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
- // @ts-ignore TS7017
- 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;
- }
- );
-
- // @ts-ignore TS2339
- 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");
- });
-
- it(".preserveOnce() - preserve cookies by key", () => {
- // normally cookies are reset after each test
- cy.getCookie("fakeCookie").should("not.be.ok");
-
- // preserving a cookie will not clear it when
- // the next test starts
- cy.setCookie("lastCookie", "789XYZ");
- Cypress.Cookies.preserveOnce("lastCookie");
- });
-
- it(".defaults() - set defaults for all cookies", () => {
- // now any cookie with the name 'session_id' will
- // not be cleared before each new test runs
- Cypress.Cookies.defaults({
- preserve: "session_id"
- });
- });
-});
-
-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/client/cypress/e2e/2-advanced-examples/files.cy.js b/client/cypress/e2e/2-advanced-examples/files.cy.js
deleted file mode 100644
index ad1bef656..000000000
--- a/client/cypress/e2e/2-advanced-examples/files.cy.js
+++ /dev/null
@@ -1,86 +0,0 @@
-///
-
-/// JSON fixture file can be loaded directly using
-// the built-in JavaScript bundler
-// @ts-ignore
-const requiredExample = require("../../fixtures/example");
-
-context("Files", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/files");
- });
-
- beforeEach(() => {
- // 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.json").then((json) => {
- expect(json).to.be.an("object");
- });
- });
-
- 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/client/cypress/e2e/2-advanced-examples/local_storage.cy.js b/client/cypress/e2e/2-advanced-examples/local_storage.cy.js
deleted file mode 100644
index 7007d02bf..000000000
--- a/client/cypress/e2e/2-advanced-examples/local_storage.cy.js
+++ /dev/null
@@ -1,58 +0,0 @@
-///
-
-context("Local Storage", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/local-storage");
- });
- // Although local storage is automatically cleared
- // in between tests to maintain a clean state
- // sometimes we need to clear the local storage manually
-
- it("cy.clearLocalStorage() - clear all data in local storage", () => {
- // 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 Local Storage
- 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 Local Storage
- 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");
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/location.cy.js b/client/cypress/e2e/2-advanced-examples/location.cy.js
deleted file mode 100644
index f5e6230d6..000000000
--- a/client/cypress/e2e/2-advanced-examples/location.cy.js
+++ /dev/null
@@ -1,32 +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/client/cypress/e2e/2-advanced-examples/misc.cy.js b/client/cypress/e2e/2-advanced-examples/misc.cy.js
deleted file mode 100644
index 9ef98ae41..000000000
--- a/client/cypress/e2e/2-advanced-examples/misc.cy.js
+++ /dev/null
@@ -1,98 +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.json").its("stderr").should("be.empty");
- } else {
- cy.exec("cat cypress.json").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/client/cypress/e2e/2-advanced-examples/navigation.cy.js b/client/cypress/e2e/2-advanced-examples/navigation.cy.js
deleted file mode 100644
index a1993ee36..000000000
--- a/client/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/client/cypress/e2e/2-advanced-examples/network_requests.cy.js b/client/cypress/e2e/2-advanced-examples/network_requests.cy.js
deleted file mode 100644
index 693e5395d..000000000
--- a/client/cypress/e2e/2-advanced-examples/network_requests.cy.js
+++ /dev/null
@@ -1,165 +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/client/cypress/e2e/2-advanced-examples/querying.cy.js b/client/cypress/e2e/2-advanced-examples/querying.cy.js
deleted file mode 100644
index 35cf7c24a..000000000
--- a/client/cypress/e2e/2-advanced-examples/querying.cy.js
+++ /dev/null
@@ -1,100 +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/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js b/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
deleted file mode 100644
index 7c86af8fa..000000000
--- a/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
+++ /dev/null
@@ -1,203 +0,0 @@
-///
-// remove no check once Cypress.sinon is typed
-// https://github.com/cypress-io/cypress/issues/6720
-
-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");
- // @ts-ignore
- expect(() => greeter.greet(42)).to.throw("Invalid name");
- expect(greeter.greet).to.have.been.calledTwice;
-
- // non-matched calls goes the actual method
- // @ts-ignore
- 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 event
- * @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/client/cypress/e2e/2-advanced-examples/traversal.cy.js b/client/cypress/e2e/2-advanced-examples/traversal.cy.js
deleted file mode 100644
index e6b56fde1..000000000
--- a/client/cypress/e2e/2-advanced-examples/traversal.cy.js
+++ /dev/null
@@ -1,97 +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/client/cypress/e2e/2-advanced-examples/utilities.cy.js b/client/cypress/e2e/2-advanced-examples/utilities.cy.js
deleted file mode 100644
index c0c9e8196..000000000
--- a/client/cypress/e2e/2-advanced-examples/utilities.cy.js
+++ /dev/null
@@ -1,108 +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
- // @ts-ignore TS2351 (new Cypress.Promise)
- 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
- // @ts-ignore TS7006
- return waitOneSecond().then((str) => {
- expect(str).to.eq("foo");
- expect(waited).to.be.true;
- });
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/viewport.cy.js b/client/cypress/e2e/2-advanced-examples/viewport.cy.js
deleted file mode 100644
index 1d73b915d..000000000
--- a/client/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.json)
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/waiting.cy.js b/client/cypress/e2e/2-advanced-examples/waiting.cy.js
deleted file mode 100644
index 49915ae75..000000000
--- a/client/cypress/e2e/2-advanced-examples/waiting.cy.js
+++ /dev/null
@@ -1,31 +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/client/cypress/e2e/2-advanced-examples/window.cy.js b/client/cypress/e2e/2-advanced-examples/window.cy.js
deleted file mode 100644
index 9740ba049..000000000
--- a/client/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/client/cypress/fixtures/example.json b/client/cypress/fixtures/example.json
deleted file mode 100644
index 02e425437..000000000
--- a/client/cypress/fixtures/example.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "Using fixtures to represent data",
- "email": "hello@cypress.io",
- "body": "Fixtures are a great way to mock data for responses to routes"
-}
diff --git a/client/cypress/fixtures/profile.json b/client/cypress/fixtures/profile.json
deleted file mode 100644
index a95e88f9c..000000000
--- a/client/cypress/fixtures/profile.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "id": 8739,
- "name": "Jane",
- "email": "jane@example.com"
-}
diff --git a/client/cypress/fixtures/users.json b/client/cypress/fixtures/users.json
deleted file mode 100644
index fe51488c7..000000000
--- a/client/cypress/fixtures/users.json
+++ /dev/null
@@ -1 +0,0 @@
-[]
diff --git a/client/cypress/plugins/index.js b/client/cypress/plugins/index.js
deleted file mode 100644
index e03c48d6e..000000000
--- a/client/cypress/plugins/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-///
-// ***********************************************************
-// This example plugins/index.jsx can be used to load plugins
-//
-// You can change the location of this file or turn off loading
-// the plugins file with the 'pluginsFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/plugins-guide
-// ***********************************************************
-
-// This function is called when a project is opened or re-opened (e.g. due to
-// the project's config changing)
-
-/**
- * @type {Cypress.PluginConfig}
- */
-// eslint-disable-next-line no-unused-vars
-module.exports = (on, config) => {
- // `on` is used to hook into various events Cypress emits
- // `config` is the resolved Cypress config
-};
diff --git a/client/cypress/support/commands.js b/client/cypress/support/commands.js
deleted file mode 100644
index 81f195804..000000000
--- a/client/cypress/support/commands.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// ***********************************************
-// This example commands.js shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add('login', (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This will overwrite an existing command --
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
-
-import "@testing-library/cypress/add-commands";
diff --git a/client/cypress/support/e2e.js b/client/cypress/support/e2e.js
deleted file mode 100644
index e328a179b..000000000
--- a/client/cypress/support/e2e.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// ***********************************************************
-// This example support/index.jsx is processed and
-// loaded automatically before your test files.
-//
-// This is a great place to put global configuration and
-// behavior that modifies Cypress.
-//
-// You can change the location of this file or turn off
-// automatically serving support files with the
-// 'supportFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.js using ES2015 syntax:
-import "./commands";
-
-// Alternatively you can use CommonJS syntax:
-// require('./commands')
diff --git a/client/cypress/tsconfig.json b/client/cypress/tsconfig.json
deleted file mode 100644
index 36de33dee..000000000
--- a/client/cypress/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "compilerOptions": {
- "allowJs": true,
- "baseUrl": "../node_modules",
- "types": ["cypress"]
- },
- "include": ["**/*.*"]
-}
diff --git a/client/package-lock.json b/client/package-lock.json
index c49b5dbd4..4e1263dc6 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -16,9 +16,9 @@
"@jsreport/browser-client": "^3.1.0",
"@reduxjs/toolkit": "^2.6.1",
"@sentry/cli": "^2.42.4",
- "@sentry/react": "^9.7.0",
+ "@sentry/react": "^9.8.0",
"@sentry/vite-plugin": "^3.2.2",
- "@splitsoftware/splitio-react": "^1.13.0",
+ "@splitsoftware/splitio-react": "^2.0.1",
"@tanem/react-nprogress": "^5.0.53",
"@vitejs/plugin-react": "^4.3.4",
"antd": "^5.24.4",
@@ -55,7 +55,7 @@
"react-dom": "^18.3.1",
"react-drag-listview": "^2.0.0",
"react-grid-gallery": "^1.0.1",
- "react-grid-layout": "1.3.4",
+ "react-grid-layout": "^1.5.1",
"react-i18next": "^14.1.3",
"react-icons": "^5.5.0",
"react-image-lightbox": "^5.1.4",
@@ -3827,6 +3827,12 @@
"react": "*"
}
},
+ "node_modules/@ioredis/commands": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
+ "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==",
+ "license": "MIT"
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
@@ -5261,50 +5267,50 @@
"license": "MIT"
},
"node_modules/@sentry-internal/browser-utils": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.7.0.tgz",
- "integrity": "sha512-1wVd8mCvbeGs3wSDZFYQ9RE8I8Ii8iQ2wnHKbONk645RIT6FwSCPHlnFKWYSFVxo85Wm6SFbKcv1zvTNXUVhfQ==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.8.0.tgz",
+ "integrity": "sha512-7aQDeU9ogMLKnEBFM/vvgMMgZDkfMhoZCtX8kq65gn33L4X2B8sI5oyUj2QJtXaRSsiUjbdCaquDLqZBCaLQHA==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "9.7.0"
+ "@sentry/core": "9.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.7.0.tgz",
- "integrity": "sha512-Ld51wOfXYO90++ZGBuVF/5PAMBnVWFfvvleXRgA9VaL2hq296+tLXYVccHTgH+dZmwjJgsybDAxHdj+k1FFnmw==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.8.0.tgz",
+ "integrity": "sha512-xWiCJkD8ROuy2pnojuRLcLI6sezK399gasA5ZL4MCXdkryqZYs55Ef2Ofj4z0RdUc8gMUb81+LTqwbmbfTqNlQ==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "9.7.0"
+ "@sentry/core": "9.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.7.0.tgz",
- "integrity": "sha512-JOwwqe3JtcbkvC/hM7qr1x40lk3K5zm8r2HHVKVLzrf6cAuLF9x17R7h+0cDOHcilacbtIQQ9Fjjb63a1/iDLQ==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.8.0.tgz",
+ "integrity": "sha512-YJhhNnrsufYVIX9s5lNSFFQrBJjUtn5AxvrcnN0fvLymNg3Y73GOUpFmhTxyELjQneKiOViClxjoWSVAN7sqQA==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "9.7.0",
- "@sentry/core": "9.7.0"
+ "@sentry-internal/browser-utils": "9.8.0",
+ "@sentry/core": "9.8.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.7.0.tgz",
- "integrity": "sha512-E/XESnVLV+CUyrucrxK2kHpEKTDrz7LTBwjnt3FDHA8MfwMRX+np0sYjvcIRWAG4xxBOYBGlWD2+n0Y2pqYa2Q==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.8.0.tgz",
+ "integrity": "sha512-/6ELOnyCOItvqv2Os29JhE8ydDds3xibMQ+FomsSkClQdC4bbc/L74nm/fdXVpJkMswtjksiTwZo1nYTS3JsIw==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/replay": "9.7.0",
- "@sentry/core": "9.7.0"
+ "@sentry-internal/replay": "9.8.0",
+ "@sentry/core": "9.8.0"
},
"engines": {
"node": ">=18"
@@ -5320,16 +5326,16 @@
}
},
"node_modules/@sentry/browser": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.7.0.tgz",
- "integrity": "sha512-G2AZuWAfatv30rFWYcbAZNnty9826ld8k+EucYLtDGN0uBdHXX9XT/x7/C8dprtV16jGWzrfvMza8C7Z4uj8BA==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.8.0.tgz",
+ "integrity": "sha512-iFM4PGLc6qCb0GaHnA5Uy09k25RXVSepAgS574cm1CH7II1wrRjTozKnPKROW89WDMuxoTOL7Tk7qPGCyWmA4g==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/browser-utils": "9.7.0",
- "@sentry-internal/feedback": "9.7.0",
- "@sentry-internal/replay": "9.7.0",
- "@sentry-internal/replay-canvas": "9.7.0",
- "@sentry/core": "9.7.0"
+ "@sentry-internal/browser-utils": "9.8.0",
+ "@sentry-internal/feedback": "9.8.0",
+ "@sentry-internal/replay": "9.8.0",
+ "@sentry-internal/replay-canvas": "9.8.0",
+ "@sentry/core": "9.8.0"
},
"engines": {
"node": ">=18"
@@ -5685,22 +5691,22 @@
}
},
"node_modules/@sentry/core": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.7.0.tgz",
- "integrity": "sha512-EprjtU7F6eltB4Nx8fzWFXsfAC/6yNGuKo2bHKeIAmNufjD0X4ifz+iB3d0pKuwsn9jQbLrQTIGwKdTO3dstFw==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.8.0.tgz",
+ "integrity": "sha512-EnN2yLWCbWjooWBPzwlXdZoJG/Bqn3ymbuXX++DUJuBGjSmtixQeTf/hKeVzj4zbib3BbbYsNBasRVjq8Rk5ng==",
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/react": {
- "version": "9.7.0",
- "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.7.0.tgz",
- "integrity": "sha512-qD3Jb1/fvofdw5+aC/ARJNu1lVO6Ndoma15V+jjKH+rBaYAXftkboUvhTzvpAM8o1tw3jbioJDQlmIHehUzjzg==",
+ "version": "9.8.0",
+ "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.8.0.tgz",
+ "integrity": "sha512-P/Lhiso8504Jza4NH3BQlP3WbnSaUsCNk21acYY3sb1lHKnpPjvWZT61D1nFIh+hisdQO6oLjTTr2O1opT43jQ==",
"license": "MIT",
"dependencies": {
- "@sentry/browser": "9.7.0",
- "@sentry/core": "9.7.0",
+ "@sentry/browser": "9.8.0",
+ "@sentry/core": "9.8.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
@@ -5748,15 +5754,13 @@
"license": "MIT"
},
"node_modules/@splitsoftware/splitio": {
- "version": "10.28.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.28.0.tgz",
- "integrity": "sha512-hzBnBZHmUTXvyMBbVTDUYtspLHjyjb/YqKtetNh7pAvkmj37vOXyXfF50Of5jr3Qmvdo0YFbKvMIOEXlXSGWaQ==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-11.0.3.tgz",
+ "integrity": "sha512-UtoixGfICCj52FfaVdI186Czw0qCvvEyCw/OtJVTsgM4Zq0k2mY8yKzQ7tSB/HJtzbUVnuPoxkwEcj0479stmg==",
"license": "Apache-2.0",
"dependencies": {
- "@splitsoftware/splitio-commons": "1.17.0",
- "@types/google.analytics": "0.0.40",
- "@types/ioredis": "^4.28.0",
- "bloom-filters": "^3.0.0",
+ "@splitsoftware/splitio-commons": "2.0.2",
+ "bloom-filters": "^3.0.4",
"ioredis": "^4.28.0",
"js-yaml": "^3.13.1",
"node-fetch": "^2.7.0",
@@ -5764,16 +5768,16 @@
"unfetch": "^4.2.0"
},
"engines": {
- "node": ">=6",
- "npm": ">=3"
+ "node": ">=14.0.0"
}
},
"node_modules/@splitsoftware/splitio-commons": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.0.tgz",
- "integrity": "sha512-rvP+0LGUN92bcTytiqyVxq9UzBG5kTkIYjU7b7AU2awBUYgM0bqT3xhQ9/MJ/2fsBbqC6QIsxoKDOz9pMgbAQw==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.2.tgz",
+ "integrity": "sha512-r2m3kwWnSuROT+7zTzhWBrM0DMRBGJNQcTyvXw8zLPPmBs/PnmAnxCy7uRpfMHOGbP9Q3Iju0bU/H5dG8svyiw==",
"license": "Apache-2.0",
"dependencies": {
+ "@types/ioredis": "^4.28.0",
"tslib": "^2.3.1"
},
"peerDependencies": {
@@ -5786,18 +5790,18 @@
}
},
"node_modules/@splitsoftware/splitio-react": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.13.0.tgz",
- "integrity": "sha512-P6TZyffkm2/g0QOxmZqAh5NG3mTOfrrfzjLkMl1FSFkRxP/fw3z43seWIQShPGEWWs0y/lRX9NqM93OgcGdS7A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.0.1.tgz",
+ "integrity": "sha512-Jky3o46w+CO2+x6TN3kzQ4CoASKX4PqtDqSTHY6n5JXBC2CqhlXuvODoMYXKzolOsndku+aL7+Mlavbn7b+2lw==",
"license": "Apache-2.0",
"dependencies": {
- "@splitsoftware/splitio": "10.28.0",
+ "@splitsoftware/splitio": "11.0.3",
"memoize-one": "^5.1.1",
"shallowequal": "^1.1.0",
"tslib": "^2.3.1"
},
"peerDependencies": {
- "react": ">=16.3.0"
+ "react": ">=16.8.0"
}
},
"node_modules/@splitsoftware/splitio-react/node_modules/memoize-one": {
@@ -6079,12 +6083,6 @@
"@types/estree": "*"
}
},
- "node_modules/@types/google.analytics": {
- "version": "0.0.40",
- "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz",
- "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==",
- "license": "MIT"
- },
"node_modules/@types/hast": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
@@ -11634,11 +11632,12 @@
}
},
"node_modules/ioredis": {
- "version": "4.28.5",
- "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz",
- "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.29.1.tgz",
+ "integrity": "sha512-iq4u3AC9h9/P/gBXH1cUR7Ln0exKexqMaYDwUaoZJzkvvgJs9W5+CLQFS0APyG8uyvJJjn6q6Vx7LwmZQu3h5A==",
"license": "MIT",
"dependencies": {
+ "@ioredis/commands": "^1.0.2",
"cluster-key-slot": "^1.1.0",
"debug": "^4.3.1",
"denque": "^1.1.0",
@@ -11646,7 +11645,6 @@
"lodash.flatten": "^4.4.0",
"lodash.isarguments": "^3.1.0",
"p-map": "^2.1.0",
- "redis-commands": "1.7.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^2.1.0"
@@ -12765,13 +12763,6 @@
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==",
"license": "MIT"
},
- "node_modules/lodash.isequal": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
- "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
- "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.",
- "license": "MIT"
- },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
@@ -15677,22 +15668,38 @@
}
},
"node_modules/react-grid-layout": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.3.4.tgz",
- "integrity": "sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==",
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/react-grid-layout/-/react-grid-layout-1.5.1.tgz",
+ "integrity": "sha512-4Fr+kKMk0+m1HL/BWfHxi/lRuaOmDNNKQDcu7m12+NEYcen20wIuZFo789u3qWCyvUsNUxCiyf0eKq4WiJSNYw==",
"license": "MIT",
"dependencies": {
- "clsx": "^1.1.1",
- "lodash.isequal": "^4.0.0",
+ "clsx": "^2.0.0",
+ "fast-equals": "^4.0.3",
"prop-types": "^15.8.1",
- "react-draggable": "^4.0.0",
- "react-resizable": "^3.0.4"
+ "react-draggable": "^4.4.5",
+ "react-resizable": "^3.0.5",
+ "resize-observer-polyfill": "^1.5.1"
},
"peerDependencies": {
"react": ">= 16.3.0",
"react-dom": ">= 16.3.0"
}
},
+ "node_modules/react-grid-layout/node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/react-grid-layout/node_modules/fast-equals": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz",
+ "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==",
+ "license": "MIT"
+ },
"node_modules/react-i18next": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz",
@@ -16070,12 +16077,6 @@
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"license": "MIT"
},
- "node_modules/redis-commands": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
- "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==",
- "license": "MIT"
- },
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
diff --git a/client/package.json b/client/package.json
index 37a326023..7a5a33996 100644
--- a/client/package.json
+++ b/client/package.json
@@ -15,9 +15,9 @@
"@jsreport/browser-client": "^3.1.0",
"@reduxjs/toolkit": "^2.6.1",
"@sentry/cli": "^2.42.4",
- "@sentry/react": "^9.7.0",
+ "@sentry/react": "^9.8.0",
"@sentry/vite-plugin": "^3.2.2",
- "@splitsoftware/splitio-react": "^1.13.0",
+ "@splitsoftware/splitio-react": "^2.0.1",
"@tanem/react-nprogress": "^5.0.53",
"@vitejs/plugin-react": "^4.3.4",
"antd": "^5.24.4",
@@ -54,7 +54,7 @@
"react-dom": "^18.3.1",
"react-drag-listview": "^2.0.0",
"react-grid-gallery": "^1.0.1",
- "react-grid-layout": "1.3.4",
+ "react-grid-layout": "^1.5.1",
"react-i18next": "^14.1.3",
"react-icons": "^5.5.0",
"react-image-lightbox": "^5.1.4",
diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx
index d6f3a53fd..7bef36b4a 100644
--- a/client/src/App/App.container.jsx
+++ b/client/src/App/App.container.jsx
@@ -1,14 +1,14 @@
import { ApolloProvider } from "@apollo/client";
-import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react";
+import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react";
import { ConfigProvider } from "antd";
import enLocale from "antd/es/locale/en_US";
-import React from "react";
+import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
import client from "../utils/GraphQLClient";
import App from "./App";
import * as Sentry from "@sentry/react";
-
import themeProvider from "./themeProvider";
import { Userpilot } from "userpilot";
@@ -17,13 +17,28 @@ if (import.meta.env.DEV) {
Userpilot.initialize("NX-69145f08");
}
+// Base Split configuration
const config = {
core: {
authorizationKey: import.meta.env.VITE_APP_SPLIT_API,
- key: "anon"
+ key: "anon" // Default key, overridden dynamically by SplitClientProvider
}
};
-export const factory = SplitSdk(config);
+
+// Custom provider to manage the Split client key based on imexshopid from Redux
+function SplitClientProvider({ children }) {
+ const imexshopid = useSelector((state) => state.user.imexshopid); // Access imexshopid from Redux store
+ const splitClient = useSplitClient({ key: imexshopid || "anon" }); // Use imexshopid or fallback to "anon"
+
+ useEffect(() => {
+ if (splitClient && imexshopid) {
+ // Log readiness for debugging; no need for ready() since isReady is available
+ console.log(`Split client initialized with key: ${imexshopid}, isReady: ${splitClient.isReady}`);
+ }
+ }, [splitClient, imexshopid]);
+
+ return children;
+}
function AppContainer() {
const { t } = useTranslation();
@@ -31,7 +46,6 @@ function AppContainer() {
return (
-
-
+
+
+
+
diff --git a/client/src/redux/user/user.actions.js b/client/src/redux/user/user.actions.js
index f5393b6e9..01ba22534 100644
--- a/client/src/redux/user/user.actions.js
+++ b/client/src/redux/user/user.actions.js
@@ -118,3 +118,8 @@ export const setCurrentEula = (eula) => ({
export const acceptEula = () => ({
type: UserActionTypes.EULA_ACCEPTED
});
+
+export const setImexShopId = (imexshopid) => ({
+ type: UserActionTypes.SET_IMEX_SHOP_ID,
+ payload: imexshopid
+});
diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js
index c117bd1c9..0042115ff 100644
--- a/client/src/redux/user/user.reducer.js
+++ b/client/src/redux/user/user.reducer.js
@@ -121,6 +121,11 @@ const userReducer = (state = INITIAL_STATE, action) => {
};
case UserActionTypes.SET_AUTH_LEVEL:
return { ...state, authLevel: action.payload };
+ case UserActionTypes.SET_IMEX_SHOP_ID:
+ return {
+ ...state,
+ imexshopid: action.payload
+ };
default:
return state;
}
diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js
index a8c0ffd0b..f2017c72c 100644
--- a/client/src/redux/user/user.sagas.js
+++ b/client/src/redux/user/user.sagas.js
@@ -15,7 +15,6 @@ import { getToken } from "firebase/messaging";
import i18next from "i18next";
import LogRocket from "logrocket";
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
-import { factory } from "../../App/App.container";
import {
analytics,
auth,
@@ -35,6 +34,7 @@ import {
sendPasswordResetFailure,
sendPasswordResetSuccess,
setAuthlevel,
+ setImexShopId,
setInstanceConflict,
setInstanceId,
setLocalFingerprint,
@@ -318,7 +318,8 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
console.log(error);
}
- factory.client(payload.imexshopid);
+ // Dispatch the imexshopid to Redux store
+ yield put(setImexShopId(payload.imexshopid));
const authRecord = payload.associations.filter((a) => a.useremail.toLowerCase() === userEmail.toLowerCase());
diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js
index 59a290ee5..d9cd6fe62 100644
--- a/client/src/redux/user/user.types.js
+++ b/client/src/redux/user/user.types.js
@@ -32,6 +32,7 @@ const UserActionTypes = {
CHECK_ACTION_CODE_SUCCESS: "CHECK_ACTION_CODE_SUCCESS",
CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE",
SET_CURRENT_EULA: "SET_CURRENT_EULA",
- EULA_ACCEPTED: "EULA_ACCEPTED"
+ EULA_ACCEPTED: "EULA_ACCEPTED",
+ SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID"
};
export default UserActionTypes;