From c0007e0c3af9e407cbfb49ebc351b16881927328 Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 24 Aug 2026 15:54:24 +0100 Subject: [PATCH 1/3] move files out of tasks dir --- .../buttons-and-counter/src/app.js | 31 ++++++++++ .../buttons-and-counter/test/app.test.js | 56 +++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 dom-merge-conflict/buttons-and-counter/src/app.js create mode 100644 dom-merge-conflict/buttons-and-counter/test/app.test.js diff --git a/dom-merge-conflict/buttons-and-counter/src/app.js b/dom-merge-conflict/buttons-and-counter/src/app.js new file mode 100644 index 0000000..af608eb --- /dev/null +++ b/dom-merge-conflict/buttons-and-counter/src/app.js @@ -0,0 +1,31 @@ +//increments the number in a node's text +function increment(node) { + let current = node.textContent; + node.textContent = Number(current) + 1; +} + +export function App() { + const body = document.createElement("body"); + + const header = document.createElement("header"); + header.innerHTML = ` +

Number Counter

+

A simple counter. Press increment to increase the count by one.

+ `; + body.appendChild(header); + + const main = document.createElement("main"); + main.innerHTML = ` +

0

+ + `; + body.appendChild(main); + + const button = body.querySelector("#increment"); + const counter = body.querySelector("#counter"); + button.addEventListener("click", () => { + increment(counter); + }); + + return body; +} diff --git a/dom-merge-conflict/buttons-and-counter/test/app.test.js b/dom-merge-conflict/buttons-and-counter/test/app.test.js new file mode 100644 index 0000000..1139e45 --- /dev/null +++ b/dom-merge-conflict/buttons-and-counter/test/app.test.js @@ -0,0 +1,56 @@ +/** + * @jest-environment jsdom + */ + +import { getByTestId, getByRole } from "@testing-library/dom"; +import "@testing-library/jest-dom"; + +import { App } from "../src/app"; + +describe("button and counter", () => { + let container = App(); + + // Reset the App before each test + beforeEach(() => { + container = App(); + }); + + test("contains description paragraph with mention of 'increment' in header", () => { + expect( + container.querySelector("header").querySelector("p") + ).toHaveTextContent(/increment/i); + }); + + test("counter starts at 0", () => { + expect(getByTestId(container, "counter")).toHaveTextContent(/^0$/); + }); + + test("pressing Increment increases the counter", () => { + const button = getByRole(container, "button", { + name: "Increment", + }); + button.click(); + button.click(); + + expect(getByTestId(container, "counter")).toHaveTextContent(/^2$/); + }); + + describe.skip("decrement button", () => { + test("pressing Decrement decreases the counter", () => { + const button = getByRole(container, "button", { + name: "Decrement", + }); + button.click(); + button.click(); + button.click(); + + expect(getByTestId(container, "counter")).toHaveTextContent(/^-3$/); + }); + + test("contains description paragraph with mention of 'decrement' in header", () => { + expect( + container.querySelector("header").querySelector("p") + ).toHaveTextContent(/decrement/i); + }); + }); +}); From 0fa91a8b227aefc29dd83a97ed67de271da4aaa5 Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 24 Aug 2026 15:54:49 +0100 Subject: [PATCH 2/3] move instruction out of tasks dir and make more specific --- .../buttons-and-counter/instructions.md | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 dom-merge-conflict/buttons-and-counter/instructions.md diff --git a/dom-merge-conflict/buttons-and-counter/instructions.md b/dom-merge-conflict/buttons-and-counter/instructions.md new file mode 100644 index 0000000..2135d3c --- /dev/null +++ b/dom-merge-conflict/buttons-and-counter/instructions.md @@ -0,0 +1,52 @@ +# Buttons and Counter + +This app currently features a button that increments a counter. + +## Task for Person A + +Create and switch to a new branch named `split-app-components`: + +``` +git switch -c split-app-components +``` + +### Task + +Split the `header`, `main` into separate components from `app.js`. + +- Separate the components into new functions that live in their own files. +- Make sure to use those functions in `app.js` so the end result remains the same, and tests still run. +- Remember - tests are your friend, run them before, during and after you've wrote some code. Use them to guide you. + +### Tests + +There are three tests that are _not_ skipped (lines 18 - 36 ihn `app.test.js`), use these tests to check your changes still let the app function as expected. + +### Result + +- You should end up with an `app.js` file, a `header.js` file, and a `main.js` file in your `src` directory. +- All tests should pass. + +## Task for Person B + +Create and switch to a new branch named `add-decrement-button`: + +``` +git switch -c add-decrement-button +``` + +### Task + +Implement a decrement button. + +- Read the skipped tests (lines 38-53 in `app.test.js`) before you start. You will use these tests to guide you. +- Write your code in `app.js` +- Update the description of the app in the `header` element. + +### Tests + +Tests (lines 38-53 in `app.test.js`) are pre-written but skipped, un-skip them and run the tests before, during and after you write your code. + +### Result + +Your `app.js` file will now contain a button that decrements the counter and all the tests will run and pass. From d9b8e0ff5cd8b782a7d0bb32be0af9ffe4d7eab6 Mon Sep 17 00:00:00 2001 From: Poonam Rajput Date: Mon, 24 Aug 2026 15:55:09 +0100 Subject: [PATCH 3/3] removing additional tasks and unnesting from tasks dir --- .../tasks/buttons-and-counter/instructions.md | 23 -- .../tasks/buttons-and-counter/src/app.js | 31 --- .../buttons-and-counter/test/app.test.js | 56 ----- .../conditional-rendering/instructions.md | 32 --- .../src/profilePreview.js | 22 -- .../test/profilePreview.test.js | 95 ------- .../optimistic-rendering/instructions.md | 23 -- .../tasks/optimistic-rendering/src/voter.js | 30 --- .../optimistic-rendering/test/voter.test.js | 195 --------------- .../tasks/processing-page/instructions.md | 36 --- .../processing-page/src/processingPage.js | 29 --- .../test/processingPage.test.js | 235 ------------------ 12 files changed, 807 deletions(-) delete mode 100644 dom-merge-conflict/tasks/buttons-and-counter/instructions.md delete mode 100644 dom-merge-conflict/tasks/buttons-and-counter/src/app.js delete mode 100644 dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js delete mode 100644 dom-merge-conflict/tasks/conditional-rendering/instructions.md delete mode 100644 dom-merge-conflict/tasks/conditional-rendering/src/profilePreview.js delete mode 100644 dom-merge-conflict/tasks/conditional-rendering/test/profilePreview.test.js delete mode 100644 dom-merge-conflict/tasks/optimistic-rendering/instructions.md delete mode 100644 dom-merge-conflict/tasks/optimistic-rendering/src/voter.js delete mode 100644 dom-merge-conflict/tasks/optimistic-rendering/test/voter.test.js delete mode 100644 dom-merge-conflict/tasks/processing-page/instructions.md delete mode 100644 dom-merge-conflict/tasks/processing-page/src/processingPage.js delete mode 100644 dom-merge-conflict/tasks/processing-page/test/processingPage.test.js diff --git a/dom-merge-conflict/tasks/buttons-and-counter/instructions.md b/dom-merge-conflict/tasks/buttons-and-counter/instructions.md deleted file mode 100644 index b06f35f..0000000 --- a/dom-merge-conflict/tasks/buttons-and-counter/instructions.md +++ /dev/null @@ -1,23 +0,0 @@ -# Buttons and Counter - -This app currently features a button that increments a counter. - -## Task for Person 1 - -Create and switch to a new branch named `split-app-components`: - -``` -git switch -c split-app-components -``` - -Split the header, main into separate components. You should end up with an `app.js` file, a `header.js` file, and a `main.js` file in your `src` directory. - -## Task for Person 2 - -Create and switch to a new branch named `add-decrement-button`: - -``` -git switch -c add-decrement-button -``` - -Unskip the tests that describe the decrement button, then in the app add the new decrement button. Make sure to update the description of the app in the header. diff --git a/dom-merge-conflict/tasks/buttons-and-counter/src/app.js b/dom-merge-conflict/tasks/buttons-and-counter/src/app.js deleted file mode 100644 index af608eb..0000000 --- a/dom-merge-conflict/tasks/buttons-and-counter/src/app.js +++ /dev/null @@ -1,31 +0,0 @@ -//increments the number in a node's text -function increment(node) { - let current = node.textContent; - node.textContent = Number(current) + 1; -} - -export function App() { - const body = document.createElement("body"); - - const header = document.createElement("header"); - header.innerHTML = ` -

Number Counter

-

A simple counter. Press increment to increase the count by one.

- `; - body.appendChild(header); - - const main = document.createElement("main"); - main.innerHTML = ` -

0

- - `; - body.appendChild(main); - - const button = body.querySelector("#increment"); - const counter = body.querySelector("#counter"); - button.addEventListener("click", () => { - increment(counter); - }); - - return body; -} diff --git a/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js b/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js deleted file mode 100644 index 1139e45..0000000 --- a/dom-merge-conflict/tasks/buttons-and-counter/test/app.test.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @jest-environment jsdom - */ - -import { getByTestId, getByRole } from "@testing-library/dom"; -import "@testing-library/jest-dom"; - -import { App } from "../src/app"; - -describe("button and counter", () => { - let container = App(); - - // Reset the App before each test - beforeEach(() => { - container = App(); - }); - - test("contains description paragraph with mention of 'increment' in header", () => { - expect( - container.querySelector("header").querySelector("p") - ).toHaveTextContent(/increment/i); - }); - - test("counter starts at 0", () => { - expect(getByTestId(container, "counter")).toHaveTextContent(/^0$/); - }); - - test("pressing Increment increases the counter", () => { - const button = getByRole(container, "button", { - name: "Increment", - }); - button.click(); - button.click(); - - expect(getByTestId(container, "counter")).toHaveTextContent(/^2$/); - }); - - describe.skip("decrement button", () => { - test("pressing Decrement decreases the counter", () => { - const button = getByRole(container, "button", { - name: "Decrement", - }); - button.click(); - button.click(); - button.click(); - - expect(getByTestId(container, "counter")).toHaveTextContent(/^-3$/); - }); - - test("contains description paragraph with mention of 'decrement' in header", () => { - expect( - container.querySelector("header").querySelector("p") - ).toHaveTextContent(/decrement/i); - }); - }); -}); diff --git a/dom-merge-conflict/tasks/conditional-rendering/instructions.md b/dom-merge-conflict/tasks/conditional-rendering/instructions.md deleted file mode 100644 index 273feb1..0000000 --- a/dom-merge-conflict/tasks/conditional-rendering/instructions.md +++ /dev/null @@ -1,32 +0,0 @@ -# Conditional Rendering - -This component is currently a profile preview showing a person's image and name. -The argument profile is an object of form: - -``` -{ - pictureSrc : String, - name : String, - bio : String -} -``` - -## Task for Person 1 - -Create and switch to a new branch named `preview-not-available`: - -``` -git switch -c preview-not-available -``` - -Unskip the tests describing the available option. Update the component so that it takes an optional options argument which is an object that contains the available property. Check the tests to see how the `options` object is passed to the `ProfilePreview` component. When this property is false, the preview should not render any information other than a text saying "Profile preview unavailable". When this property is true, continue to render the profile as before. By default, available should be true. - -## Task for Person 2 - -Create and switch to a new branch named `preview-short-form`: - -``` -git switch -c preview-short-form -``` - -Unskip the tests describing the short form option. Update the component so that it takes an optional options argument which is an object that contains the shortForm property. Check the tests to see how the `options` object is passed to the `ProfilePreview` component. When this property is false, continue to render all the profile information. When this property is true, render all the profile information other than the bio. By default shortForm should be false. diff --git a/dom-merge-conflict/tasks/conditional-rendering/src/profilePreview.js b/dom-merge-conflict/tasks/conditional-rendering/src/profilePreview.js deleted file mode 100644 index b1778b4..0000000 --- a/dom-merge-conflict/tasks/conditional-rendering/src/profilePreview.js +++ /dev/null @@ -1,22 +0,0 @@ -export function ProfilePreview(profile) { - const preview = document.createElement("aside"); - - const picture = document.createElement("img"); - picture.src = profile.pictureSrc; - picture.alt = ""; - picture.dataset.testid = "profilePicture"; - - const name = document.createElement("p"); - name.textContent = profile.name; - name.dataset.testid = "profileName"; - - const bio = document.createElement("p"); - bio.textContent = profile.bio; - bio.dataset.testid = "profileBio"; - - preview.appendChild(picture); - preview.appendChild(name); - preview.appendChild(bio); - - return preview; -} diff --git a/dom-merge-conflict/tasks/conditional-rendering/test/profilePreview.test.js b/dom-merge-conflict/tasks/conditional-rendering/test/profilePreview.test.js deleted file mode 100644 index 8e50cec..0000000 --- a/dom-merge-conflict/tasks/conditional-rendering/test/profilePreview.test.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @jest-environment jsdom - */ - -import { getByTestId } from "@testing-library/dom"; -import "@testing-library/jest-dom"; - -import { ProfilePreview } from "../src/profilePreview"; - -describe("profile preview", () => { - describe("default options", () => { - test("contains profile info", () => { - const profile = { - pictureSrc: "/test", - name: "John Doe", - bio: "Lorem ipsum dolor sit amet.", - }; - //Freeze the object so that we can reference the properties in test and assume they are the same as above. - Object.freeze(profile); - - const container = ProfilePreview(profile); - - const image = getByTestId(container, "profilePicture"); - const name = getByTestId(container, "profileName"); - const bio = getByTestId(container, "profileBio"); - - expect(image.src).toContain(profile.pictureSrc); - expect(name).toHaveTextContent(profile.name); - expect(bio).toHaveTextContent(profile.bio); - expect(container.childElementCount).toBe(3); - }); - }); - - describe.skip("available option", () => { - test("only notice that preview is unavailable is displayed with shortform on, available off", () => { - const profile = { - pictureSrc: "/null", - name: "N/A", - bio: "N/A", - }; - Object.freeze(profile); - - const container = ProfilePreview(profile, { - available: false, - shortForm: true, - }); - - expect(container.childElementCount).toBe(1); - expect(container.children[0]).toHaveTextContent( - "Profile preview unavailable" - ); - }); - - test("only notice that preview is unavailable is displayed with shortform off, available off", () => { - const profile = { - pictureSrc: "/null", - name: "N/A", - bio: "N/A", - }; - Object.freeze(profile); - - const container = ProfilePreview(profile, { - available: false, - shortForm: false, - }); - - expect(container.childElementCount).toBe(1); - expect(container.children[0]).toHaveTextContent( - "Profile preview unavailable" - ); - }); - }); - - describe.skip("short form option", () => { - test("contains profile info except the bio with shortform on", () => { - const profile = { - pictureSrc: "/picture", - name: "Jane Doe", - bio: "Duis porta neque sed eros.", - }; - Object.freeze(profile); - - const container = ProfilePreview(profile, { - shortForm: true, - }); - - const image = getByTestId(container, "profilePicture"); - const name = getByTestId(container, "profileName"); - - expect(image.src).toContain(profile.pictureSrc); - expect(name).toHaveTextContent(profile.name); - expect(container.childElementCount).toBe(2); - }); - }); -}); diff --git a/dom-merge-conflict/tasks/optimistic-rendering/instructions.md b/dom-merge-conflict/tasks/optimistic-rendering/instructions.md deleted file mode 100644 index 747c940..0000000 --- a/dom-merge-conflict/tasks/optimistic-rendering/instructions.md +++ /dev/null @@ -1,23 +0,0 @@ -# Optimistic rendering - -This component is currently a like button, that updates once the promise from updateVote() is resolved and gives an error when it is rejected. - -## Task for Person 1 - -Create and switch to a new branch named `render-like-optimistically`: - -``` -git switch -c render-like-optimistically -``` - -Render the like optimistically, that is change the component to a liked state before the promise is resolved. If the promise rejects, then render the component back to its old state. Unskip the tests that describe optimistic rendering to test your implementation. - -## Task for Person 2 - -Create and switch to a new branch named `change-button-appearance`: - -``` -git switch -c change-button-appearance -``` - -Change the button content to an image that has a source of "/media/like". When liked, the component should render the image that has a source of "/media/liked" Be sure to add appropriate alt text. Unskip the tests that describe the like as a image to test your implementation. diff --git a/dom-merge-conflict/tasks/optimistic-rendering/src/voter.js b/dom-merge-conflict/tasks/optimistic-rendering/src/voter.js deleted file mode 100644 index 0186989..0000000 --- a/dom-merge-conflict/tasks/optimistic-rendering/src/voter.js +++ /dev/null @@ -1,30 +0,0 @@ -export function Voter(updateVote) { - const container = document.createElement("div"); - - const button = document.createElement("button"); - button.textContent = "Like"; - - const errorMessage = document.createElement("p"); - - container.appendChild(button); - - button.addEventListener("click", () => { - errorMessage.remove(); - - updateVote() - .then(() => { - const message = document.createElement("p"); - message.textContent = "Liked"; - - container.appendChild(message); - button.remove(); - }) - .catch(() => { - errorMessage.textContent = - "We could not process your vote, please try again later."; - container.appendChild(errorMessage); - }); - }); - - return container; -} diff --git a/dom-merge-conflict/tasks/optimistic-rendering/test/voter.test.js b/dom-merge-conflict/tasks/optimistic-rendering/test/voter.test.js deleted file mode 100644 index 5e310fd..0000000 --- a/dom-merge-conflict/tasks/optimistic-rendering/test/voter.test.js +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @jest-environment jsdom - */ - -import { - queryByAltText, - getByRole, - queryByRole, - queryByText, - queryAllByText, -} from "@testing-library/dom"; -import "@testing-library/jest-dom"; - -import { Voter } from "../src/voter"; - -describe("like button", () => { - describe("intial state", () => { - const pending = new Promise(() => {}); - - const container = Voter(() => pending); - - test("starts with like button", () => { - const button = queryByRole(container, "button", { - name: /like/i, - }); - - expect(button).not.toBeNull(); - }); - - test("starts with 1 child", () => { - expect(container.childElementCount).toBe(1); - }); - }); - - describe("resolved state", () => { - let resolve = null; - let container = null; - - beforeEach(() => { - resolve = Promise.resolve(); - container = Voter(() => resolve); - - const button = getByRole(container, "button"); - button.click(); - }); - - test("ends with 1 child", () => { - expect.assertions(1); - - return resolve.then(() => { - expect(container.childElementCount).toBe(1); - }); - }); - - test("ends with no button", async () => { - expect.assertions(1); - - return resolve.then(() => { - expect(queryByRole(container, "button")).toBeNull(); - }); - }); - }); - - describe("rejected state", () => { - let reject = null; - let container = null; - - beforeEach(() => { - reject = Promise.reject(); - container = Voter(() => reject); - - const button = queryByRole(container, "button"); - button.click(); - }); - - test("displays error message", () => { - expect.assertions(1); - - return reject.catch(() => { - const errorMessage = queryByText( - container, - /we could not process your vote/i - ); - - expect(errorMessage).not.toBeNull(); - }); - }); - - test("has two children after fail", () => { - expect.assertions(1); - - return reject.catch(() => { - expect(container.childElementCount).toBe(2); - }); - }); - - test("has button after fail", () => { - expect.assertions(1); - - return reject.catch(() => { - const button = queryByRole(container, "button"); - - expect(button).not.toBeNull(); - }); - }); - - test("pressing button after fail instantly removes error message", () => { - expect.assertions(2); - - return reject.catch(() => { - const button = queryByRole(container, "button"); - - button.click(); - - const errorMessage = queryByText( - container, - /we could not process your vote/i - ); - - expect(errorMessage).toBeNull(); - expect(container.childElementCount).toBe(1); - }); - }); - }); - - describe.skip("optimistic rendering", () => { - let pending = null; - let container = null; - - beforeEach(() => { - pending = new Promise(() => {}); - container = Voter(() => pending); - - const button = queryByRole(container, "button"); - button.click(); - }); - - test("there is 1 child immediately after click", () => { - expect(container.childElementCount).toBe(1); - }); - - test("there is no button immediately after click", () => { - const button = queryByRole(container, "button"); - - expect(button).toBeNull(); - }); - }); - - describe.skip("button as an image", () => { - let resolve = null; - let container = null; - - beforeEach(() => { - resolve = Promise.resolve(); - container = Voter(() => resolve); - }); - - test("component contains no text content", () => { - const button = queryByRole(container, "button"); - button.click(); - - const text = queryAllByText(container, /(\s|\S)/i); - - expect(text).toHaveLength(0); - }); - - test("contains no empty paragraphs components", () => { - const button = queryByRole(container, "button"); - button.click(); - - const paragraphs = container.querySelectorAll("p"); - - expect(paragraphs).toHaveLength(0); - }); - - test("button icon uses /media/like as src", () => { - const icon = queryByAltText(container, /like/i); - - expect(icon.src).toMatch(/media\/like$/i); - }); - - test("once resolved icon uses /media/liked as src", () => { - expect.assertions(1); - - const button = queryByRole(container, "button"); - button.click(); - - return resolve.then(() => { - const icon = queryByAltText(container, /liked/i); - - expect(icon.src).toMatch(/media\/liked$/i); - }); - }); - }); -}); diff --git a/dom-merge-conflict/tasks/processing-page/instructions.md b/dom-merge-conflict/tasks/processing-page/instructions.md deleted file mode 100644 index 28e08bf..0000000 --- a/dom-merge-conflict/tasks/processing-page/instructions.md +++ /dev/null @@ -1,36 +0,0 @@ -# Processing Page - -This component currently features a processing page which changes after the completion of some promises. -Below you can see how the functions that return promises depend on each other. "→" means that the result of the previous promise is passed into the next function: - -``` -verifyServersideKey → verifyLocalKey -``` - -``` -verifyBrowser → verifyVersion -``` - -``` -verifyStableConnection -``` - -## Task for Person 1 - -Create and switch to a new branch named `add-progress-bar`: - -``` -git switch -c add-progress-bar -``` - -Unskip the tests describing the progress bar. Then implement a progress bar underneath the current message that increments its value for each promise resolved. - -## Task for Person 2 - -Create and switch to a new branch named `change-promise-logic`: - -``` -git switch -c change-promise-logic -``` - -Unskip the tests describing promises running concurrently. Update the component so that the operations that are independent of each other run concurrently. diff --git a/dom-merge-conflict/tasks/processing-page/src/processingPage.js b/dom-merge-conflict/tasks/processing-page/src/processingPage.js deleted file mode 100644 index 3ce8e76..0000000 --- a/dom-merge-conflict/tasks/processing-page/src/processingPage.js +++ /dev/null @@ -1,29 +0,0 @@ -export function ProcessingPage({ - verifyServersideKey, - verifyLocalKey, - verifyBrowser, - verifyVersion, - verifyStableConnection, -}) { - const container = document.createElement("div"); - - const info = document.createElement("p"); - info.textContent = - "Please wait while we verify your details, browser, and internet connection."; - info.dataset.testid = "info"; - container.appendChild(info); - - verifyServersideKey() - .then((res) => verifyLocalKey(res)) - .then(() => verifyBrowser()) - .then((res) => verifyVersion(res)) - .then(() => verifyStableConnection()) - .then(() => { - info.textContent = "Verification successful."; - }) - .catch(() => { - info.textContent = "Verification failed."; - }); - - return container; -} diff --git a/dom-merge-conflict/tasks/processing-page/test/processingPage.test.js b/dom-merge-conflict/tasks/processing-page/test/processingPage.test.js deleted file mode 100644 index ac090d1..0000000 --- a/dom-merge-conflict/tasks/processing-page/test/processingPage.test.js +++ /dev/null @@ -1,235 +0,0 @@ -/** - * @jest-environment jsdom - */ - -import "@testing-library/jest-dom"; - -import { ProcessingPage } from "../src/processingPage"; -import { getByRole, getByTestId } from "@testing-library/dom"; - -//waitForPromises is used to wait for next event loop in node.js which allows for all promises to be handled in the component being tested. -function waitForPromises() { - return new Promise(process.nextTick); -} - -describe("processing page", () => { - // The MockHelper will be an object that contain {promise, callback, resolve, reject}. callback is required by LoadingPage - let verifyServersideKeyMockHelper = null; - let verifyLocalKeyMockHelper = null; - let verifyBrowserMockHelper = null; - let verifyVersionMockHelper = null; - let verifyStableConnectionMockHelper = null; - let container = null; - - function generateMockHelper() { - let resolve, reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - const callback = () => promise; - return { resolve, reject, promise, callback }; - } - - beforeEach(() => { - verifyServersideKeyMockHelper = generateMockHelper(); - verifyLocalKeyMockHelper = generateMockHelper(); - verifyBrowserMockHelper = generateMockHelper(); - verifyVersionMockHelper = generateMockHelper(); - verifyStableConnectionMockHelper = generateMockHelper(); - - container = ProcessingPage({ - verifyServersideKey: verifyServersideKeyMockHelper.callback, - verifyLocalKey: verifyLocalKeyMockHelper.callback, - verifyBrowser: verifyBrowserMockHelper.callback, - verifyVersion: verifyVersionMockHelper.callback, - verifyStableConnection: verifyStableConnectionMockHelper.callback, - }); - }); - - describe("default", () => { - test("the info text initially displays a message to wait", () => { - expect(getByTestId(container, "info")).toHaveTextContent(/^please wait/i); - }); - - test("the info text does not change if the verifyLocalKey promise resolves by itself", () => { - expect.assertions(1); - - verifyLocalKeyMockHelper.resolve(); - - return waitForPromises().then(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^please wait/i - ); - }); - }); - - test("the info text does not change if the verifyLocalKey promise rejects by itself", () => { - expect.assertions(1); - - verifyLocalKeyMockHelper.reject(); - - return waitForPromises() - .then(() => verifyLocalKeyMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^please wait/i - ); - }); - }); - - test("the info text does not change if the verifyVersion promise resolves by itself", () => { - expect.assertions(1); - - verifyVersionMockHelper.resolve(); - - return waitForPromises().then(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^please wait/i - ); - }); - }); - - test("the info text does not change if the verifyVersion promise rejects by itself", () => { - expect.assertions(1); - - verifyVersionMockHelper.reject(); - - return waitForPromises() - .then(() => verifyVersionMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^please wait/i - ); - }); - }); - - test("the info text indicates success in verification when all promises are resolved", () => { - expect.assertions(1); - - verifyServersideKeyMockHelper.resolve(); - verifyLocalKeyMockHelper.resolve(); - verifyBrowserMockHelper.resolve(); - verifyVersionMockHelper.resolve(); - verifyStableConnectionMockHelper.resolve(); - - return waitForPromises().then(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification successful/i - ); - }); - }); - }); - - describe.skip("progress bar", () => { - test("progress bar is initially at 0 and has a max of 5", () => { - const progressbar = getByRole(container, "progressbar"); - - expect(progressbar.value).toBe(0); - expect(progressbar.max).toBe(5); - }); - - test("progress bar increments for each completed task", () => { - expect.assertions(1); - - verifyServersideKeyMockHelper.resolve(); - verifyLocalKeyMockHelper.resolve(); - verifyBrowserMockHelper.resolve(); - verifyVersionMockHelper.resolve(); - - return waitForPromises().then(() => { - const progressbar = getByRole(container, "progressbar"); - - expect(progressbar.value).toBe(4); - }); - }); - - test("progress bar does not increment when promises that are dependent on other promises resolve", () => { - expect.assertions(1); - - verifyServersideKeyMockHelper.resolve(); - verifyLocalKeyMockHelper.resolve(); - verifyVersionMockHelper.resolve(); - - return waitForPromises().then(() => { - const progressbar = getByRole(container, "progressbar"); - - expect(progressbar.value).toBe(2); - }); - }); - }); - - describe.skip("run independent promises concurrently", () => { - test("info text indicates failure when verifyStableConnection rejects", () => { - expect.assertions(1); - - verifyStableConnectionMockHelper.reject(); - - return waitForPromises() - .then(() => verifyStableConnectionMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification failed/i - ); - }); - }); - - test("info text indicates failure when verifyServersideKey rejects", () => { - expect.assertions(1); - - verifyServersideKeyMockHelper.reject(); - - return waitForPromises() - .then(() => verifyServersideKeyMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification failed/i - ); - }); - }); - - test("info text indicates failure when verifyBrowser rejects", () => { - expect.assertions(1); - - verifyBrowserMockHelper.reject(); - - return waitForPromises() - .then(() => verifyBrowserMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification failed/i - ); - }); - }); - - test("info text indicates failure when verifyLocalKey rejects after verifyServerSideKey resolves", () => { - expect.assertions(1); - - verifyServersideKeyMockHelper.resolve(); - verifyLocalKeyMockHelper.reject(); - - return waitForPromises() - .then(() => verifyLocalKeyMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification failed/i - ); - }); - }); - - test("info text indicates faiulre when verifyVersion reject after verifyBrowser resolves", () => { - expect.assertions(1); - - verifyBrowserMockHelper.resolve(); - verifyVersionMockHelper.reject(); - - return waitForPromises() - .then(() => verifyVersionMockHelper.promise) - .catch(() => { - expect(getByTestId(container, "info")).toHaveTextContent( - /^verification failed/i - ); - }); - }); - }); -});