mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-01-09 15:06:15 -05:00
fix(curriculum):strengthen draw condition check test in tic-tac-toelab (#60960)
Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com>
This commit is contained in:
@@ -18,6 +18,31 @@ demoType: onClick
|
||||
4. You should create a `button#reset` element that resets the game when clicked.
|
||||
5. A message should be displayed indicating either `X` or `O` as the winner, or neither if the result is a draw.
|
||||
|
||||
# --before-all--
|
||||
|
||||
```js
|
||||
let clock = __FakeTimers.install();
|
||||
|
||||
async function reset(assert) {
|
||||
const reset = document.querySelector("#reset");
|
||||
assert.exists(reset, "button#reset should exist");
|
||||
reset.click();
|
||||
clock.tick(50);
|
||||
}
|
||||
|
||||
// Gets the text of the document excluding that of the matching selector.
|
||||
function getInnerTextExcept(removingSelector) {
|
||||
const body = document.body.cloneNode(true);
|
||||
|
||||
const squareElements = body.querySelectorAll(`${removingSelector},script`);
|
||||
squareElements.forEach(element => {
|
||||
element.parentNode.removeChild(element)
|
||||
});
|
||||
|
||||
return body.innerText;
|
||||
}
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
You should export a `Board` component.
|
||||
@@ -99,7 +124,7 @@ async () => {
|
||||
const el = document.querySelector("button.square");
|
||||
el.click();
|
||||
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
try {
|
||||
assert.include(el.textContent, "X");
|
||||
@@ -117,7 +142,7 @@ async () => {
|
||||
// NOTE: This test is intentionally high-up, because the latter tests rely on the functionality.
|
||||
const el = document.querySelector("button.square");
|
||||
el.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
try {
|
||||
await reset(assert);
|
||||
@@ -136,10 +161,10 @@ async () => {
|
||||
await reset(assert);
|
||||
const els = document.querySelectorAll("button.square");
|
||||
els[0].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
els[1].click();
|
||||
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
try {
|
||||
assert.include(els[1].textContent, "O");
|
||||
@@ -160,7 +185,7 @@ async () => {
|
||||
for (let i = 3; i < els.length + 3; i++) {
|
||||
const wrappedI = i % els.length;
|
||||
els[wrappedI].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
assert.include(els[wrappedI].textContent, (i - 3) % 2 === 0 ? "X" : "O");
|
||||
}
|
||||
} catch(e) {
|
||||
@@ -181,9 +206,9 @@ async () => {
|
||||
const wrappedI = i % els.length;
|
||||
// Click button twice to ensure it does not change
|
||||
els[wrappedI].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
els[wrappedI].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
assert.include(els[wrappedI].textContent, (i - 3) % 2 === 0 ? "X" : "O");
|
||||
}
|
||||
} catch(e) {
|
||||
@@ -204,12 +229,12 @@ async () => {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const x = els[i];
|
||||
x.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
assert.include(x.textContent, "X");
|
||||
|
||||
const o = els[i + 3];
|
||||
o.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
if (i === 2) {
|
||||
assert.notInclude(o.textContent, "O");
|
||||
} else {
|
||||
@@ -237,16 +262,16 @@ async () => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const x = els[i];
|
||||
x.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
const o = els[i + 3];
|
||||
o.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
}
|
||||
|
||||
const preXWin = getInnerTextExcept("button.square");
|
||||
// Click winning button for X
|
||||
els[2].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
const postXWin = getInnerTextExcept("button.square");
|
||||
assert.notEqual(preXWin, postXWin);
|
||||
@@ -256,18 +281,18 @@ async () => {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const x = els[i];
|
||||
x.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
const o = els[i + 3];
|
||||
o.click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
}
|
||||
els[6].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
const preOWin = getInnerTextExcept("button.square");
|
||||
// Click winning button for O
|
||||
els[5].click();
|
||||
await delay(50);
|
||||
clock.tick(50);
|
||||
|
||||
const postOWin = getInnerTextExcept("button.square");
|
||||
assert.notEqual(preOWin, postOWin);
|
||||
@@ -291,18 +316,28 @@ async () => {
|
||||
await reset(assert);
|
||||
const els = document.querySelectorAll("button.square");
|
||||
try {
|
||||
for (let i = 3; i < els.length + 2; i++) {
|
||||
const wrappedI = i % els.length;
|
||||
els[wrappedI].click();
|
||||
await delay(50);
|
||||
//use already known draw states
|
||||
const drawMoves = [0, 1, 2, 4, 3, 5, 7, 6, 8];
|
||||
|
||||
const snapshot1 = getInnerTextExcept("button.square");
|
||||
els[drawMoves[0]].click();
|
||||
clock.tick(50);
|
||||
|
||||
const snapshot2 = getInnerTextExcept("button.square");
|
||||
for (let i = 1; i < drawMoves.length - 1; i++) {
|
||||
els[drawMoves[i]].click();
|
||||
clock.tick(50);
|
||||
}
|
||||
|
||||
const pre = getInnerTextExcept("button.square");
|
||||
els[2].click();
|
||||
await delay(50);
|
||||
const snapshot3 = getInnerTextExcept("button.square");
|
||||
els[drawMoves[drawMoves.length - 1]].click();
|
||||
clock.tick(50);
|
||||
|
||||
const snapshot4 = getInnerTextExcept("button.square");
|
||||
assert.notEqual(snapshot4, snapshot1);
|
||||
assert.notEqual(snapshot4, snapshot2);
|
||||
assert.notEqual(snapshot4, snapshot3);
|
||||
|
||||
const post = getInnerTextExcept("button.square");
|
||||
assert.notEqual(pre, post);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
throw e;
|
||||
@@ -310,30 +345,11 @@ async () => {
|
||||
}
|
||||
```
|
||||
|
||||
# --before-all--
|
||||
Uninstall the clock, ignore this test
|
||||
|
||||
```js
|
||||
async function delay(time) {
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
|
||||
async function reset(assert) {
|
||||
const reset = document.querySelector("#reset");
|
||||
assert.exists(reset, "button#reset should exist");
|
||||
reset.click();
|
||||
await delay(50);
|
||||
}
|
||||
|
||||
// Gets the text of the document excluding that of the matching selector.
|
||||
function getInnerTextExcept(removingSelector) {
|
||||
const body = document.body.cloneNode(true);
|
||||
|
||||
const squareElements = body.querySelectorAll(`${removingSelector},script`);
|
||||
squareElements.forEach(element => {
|
||||
element.parentNode.removeChild(element)
|
||||
});
|
||||
|
||||
return body.innerText;
|
||||
async () => {
|
||||
clock.uninstall()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user