Tell us what’s happening:
I have finished the user stories of the tic-tac-toe challenge in the new fullstack courses but can’t get the automated tests to pass.
- My event handler returns immediately if an unavailable square is clicked and there is no state change/rerender yet test 8 fails.
- There is a message in my component indicating the winner (or draw), yet tests 10 and 11 fail.
- The event handler returns immediately if the game ended and there is no state change/rerender yet test 9 fails.
- The state toggles the “active player” between X and O meaning that those symbols are entered alternately, yet test 7 fails.
I am used to sometimes rewriting correct code to see how the tests respond but with this challenge I really can’t tell what is actually tested. If the test condition is “no change”, there must be some deeper misalignment between my approach to the challenge an the assumptions by the tests. Taking a very close look at the example project also didn’t help.
- Test 7: All subsequent clicks of a
button.square
element should alternate between displayingX
andO
within the element.- Test 8: Clicking on an already used
button.square
element should result in no change.- Test 9: Clicking on a
button.square
element after the game has ended should result in no change.- Test 10: The game should display a message indicating the winner to be
X
orO
.- Test 11: The game should display a message indicating a draw.
I know there are other tic-tac-toe related posts but most of them are from other courses and I’m not having issues with the challenge itself, but with the validation, so I figured a new post in the forum is justified.
Your code so far
/* file: index.jsx */
const { useState } = React;
const winning_combinations = [
[0,1,2],[3,4,5],[6,7,8],[0,3,6],
[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
export function Board() {
const [state, setState] = useState({
selections: Array(9).fill(null),
activePlayer: "X"
});
const [msg, setMsg] = useState("");
const HandleClick = (key) => {
if (state.selections[key] || msg !== "") {
return /* not a valid key or game ended */
}
setState(s => {
const cp = [...s.selections];
cp[key] = s.activePlayer;
const draw = cp.every(x => x !== null);
const winner = winning_combinations.some(
combo => combo.every(
key => cp[key] === s.activePlayer));
if (winner) {
setMsg("Winner: " + s.activePlayer);
} else if (draw) {
setMsg("It's a Draw");
}
return {
activePlayer: s.activePlayer === "X" ? "O" : "X",
selections: cp
};
})
}
const reset = () => {
setState({
selections: Array(9).fill(null),
activePlayer: "X"
});
setMsg("");
}
return <>
<h1>Tic Tac Toe</h1>
<div className="msg status">{msg}</div>
<div className="squares">
{state.selections.map((x, i) =>
<button className="square" onClick={
() => HandleClick(i)} key={i}>{x}</button>
)}
</div>
<button type="reset" id="reset"
onClick={reset}>Reset</button>
</>;
}
<!-- file: index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tic-Tac-Toe</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.development.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.26.5/babel.min.js"></script>
<script
data-plugins="transform-modules-umd"
type="text/babel"
src="index.jsx"
></script>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="root"></div>
<script
data-plugins="transform-modules-umd"
type="text/babel"
data-presets="react"
data-type="module"
>
import { Board } from './index.jsx';
ReactDOM.createRoot(document.getElementById('root')).render(<Board />);
</script>
</body>
</html>
/* file: styles.css */
.squares {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 1rem;
width: 11rem;
height: 11rem;
}
.square {
cursor: pointer;
border-radius: 5px;
border: 1px solid;
}
button:hover {
outline: 2px solid orange;
}
body {
background: #333;
color: #ddd;
font-family: Arial, sans-serif;
}
button[type="reset"] {
width: 11rem;
margin-top: 1rem;
border-radius: 5px;
padding: .5rem;
font-size: 1.5rem;
}
.msg {
margin-bottom: 1rem;
font-size: 1.5rem;
}
Your browser information:
User Agent is: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36
Challenge Information:
Build a Tic-Tac-Toe Game - Build a Tic-Tac-Toe Game