Skip to content

Commit

Permalink
feat: add random tests (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
zsuh022 authored Aug 22, 2024
1 parent cdd4b22 commit f321624
Show file tree
Hide file tree
Showing 7 changed files with 323 additions and 17 deletions.
17 changes: 0 additions & 17 deletions frontend/tests/chimptest.test.js

This file was deleted.

48 changes: 48 additions & 0 deletions tests/Chimptest.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import Chimptest from './Chimptest';

describe('Chimptest', () => {
beforeEach(() => {
document.body.innerHTML = '<div id="tiles"></div>';
});

it('should generate random tiles on load', () => {
render(<Chimptest />);
expect(document.querySelectorAll('.tile').length).toBe(4);
});

it('should handle correct tile clicks', () => {
render(<Chimptest />);
const tiles = document.querySelectorAll('.tile');
fireEvent.click(tiles[0]);
expect(tiles[0].style.backgroundColor).toBe('transparent');
});

it('should handle incorrect tile clicks and increase strikes', () => {
render(<Chimptest />);
const tiles = document.querySelectorAll('.tile');
fireEvent.click(tiles[1]); // Click wrong tile
expect(screen.getByText('Strikes: 1/3')).toBeInTheDocument();
});

it('should trigger game over after 3 strikes', () => {
render(<Chimptest />);
const tiles = document.querySelectorAll('.tile');
fireEvent.click(tiles[1]);
fireEvent.click(tiles[1]);
fireEvent.click(tiles[1]);
expect(screen.getByText('Game Over')).toBeInTheDocument();
});

it('should reset the game on "Try Again" click', () => {
render(<Chimptest />);
const tiles = document.querySelectorAll('.tile');
fireEvent.click(tiles[1]);
fireEvent.click(tiles[1]);
fireEvent.click(tiles[1]);

fireEvent.click(screen.getByText('Try Again?'));
expect(screen.getByText('Strikes: 0/3')).toBeInTheDocument();
});
});
80 changes: 80 additions & 0 deletions tests/ColourPuzzle.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import ColourPuzzle from './ColourPuzzle';
import { BrowserRouter } from 'react-router-dom';

vi.mock('./ColourPuzzleHelper', () => {
return {
__esModule: true,
default: vi.fn().mockImplementation(() => ({
getRandomOrderArray: vi.fn(() => [1, 2, 3, 4]),
})),
};
});

vi.mock('./HackPuzzle', () => ({
__esModule: true,
default: ({ onSolutionCalculated }) => {
onSolutionCalculated('blue square');
return <div>Mock HackPuzzle</div>;
},
}));

vi.mock('./OrderCards', () => ({
__esModule: true,
default: () => <div>Mock OrderCards</div>,
}));

describe('ColourPuzzle', () => {
const originalLocation = window.location;

beforeEach(() => {
window.location = {
...originalLocation,
search: '?time=10',
};
});

afterEach(() => {
window.location = originalLocation;
});

it('should display order cards initially', () => {
render(
<BrowserRouter>
<ColourPuzzle />
</BrowserRouter>
);
expect(screen.getByText('Mock OrderCards')).toBeInTheDocument();
});

it('should display "Time ran out" screen when time is over', () => {
vi.useFakeTimers();

render(
<BrowserRouter>
<ColourPuzzle />
</BrowserRouter>
);

vi.advanceTimersByTime(13000); // 3 seconds for hiding + 10 seconds puzzle display

expect(screen.getByText('Time ran out. You lost.')).toBeInTheDocument();

vi.useRealTimers();
});

it('should display "You Won" screen when puzzle is solved', () => {
render(
<BrowserRouter>
<ColourPuzzle />
</BrowserRouter>
);

fireEvent.change(screen.getByPlaceholderText('eg. blue square...'), {
target: { value: 'blue square' },
});

expect(screen.getByText('You Won')).toBeInTheDocument();
});
});
38 changes: 38 additions & 0 deletions tests/ColourPuzzleInfo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { describe, it, expect } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import ColourPuzzleInfo from './ColourPuzzleInfo';

describe('ColourPuzzleInfo', () => {
it('should render initial puzzle display time', () => {
render(
<BrowserRouter>
<ColourPuzzleInfo />
</BrowserRouter>
);
expect(screen.getByText('10s')).toBeInTheDocument();
});

it('should change selected time on button click', () => {
render(
<BrowserRouter>
<ColourPuzzleInfo />
</BrowserRouter>
);

const button5s = screen.getByText('5s');
fireEvent.click(button5s);

expect(button5s).toHaveClass('selected');
});

it('should link to the correct start URL', () => {
render(
<BrowserRouter>
<ColourPuzzleInfo />
</BrowserRouter>
);

expect(screen.getByText('Play').closest('a')).toHaveAttribute('href', 'start?time=10');
});
});
49 changes: 49 additions & 0 deletions tests/Game1.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { describe, it, expect, vi, fireEvent } from 'vitest';
import { render, screen } from '@testing-library/react';
import Game1 from './Game1';

describe('Game1', () => {
beforeEach(() => {
document.body.innerHTML = `
<div id="dino" style="top: 150px"></div>
<div id="cactus" style="left: 200px; animation-play-state: running;"></div>
`;
});

it('should trigger jump on keydown', () => {
render(<Game1 />);
fireEvent.keyDown(document, { key: ' ' });
const dino = document.getElementById('dino');
expect(dino.classList.contains('jump')).toBe(true);
});

it('should detect collision and set game over', () => {
render(<Game1 />);
const cactus = document.getElementById('cactus');
cactus.style.left = '100px';
const dino = document.getElementById('dino');
dino.style.top = '140px';

// let collision detection run
vi.advanceTimersByTime(100);

expect(screen.getByText('Game Over. Play again.')).toBeInTheDocument();
expect(cactus.style.animationPlayState).toBe('paused');
});

it('should restart game when game over button is clicked', () => {
render(<Game1 />);
fireEvent.keyDown(document, { key: ' ' });
const cactus = document.getElementById('cactus');
cactus.style.left = '100px';
const dino = document.getElementById('dino');
dino.style.top = '140px';

// trigger game over
vi.advanceTimersByTime(100);

fireEvent.click(screen.getByText('Game Over. Play again.'));

expect(window.location.reload).toHaveBeenCalled();
});
});
47 changes: 47 additions & 0 deletions tests/HackPuzzle.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, it, expect, vi } from 'vitest';
import { render, screen } from '@testing-library/react';
import HackPuzzle from './HackPuzzle';
import ColourPuzzleHelper from './ColourPuzzleHelper';

vi.mock('./ColourPuzzleHelper', () => {
return {
__esModule: true,
default: vi.fn().mockImplementation(() => ({
getRandomShades: vi.fn(() => ["#ffffff", "#000000", "#ff0000", "#00ff00"]),
getRandomShapes: vi.fn(() => ["circle", "square", "triangle", "rectangle"]),
getRandomColours: vi.fn(() => ["red", "green", "blue", "yellow"]),
getRandomOrderArray: vi.fn(() => [1, 2, 3, 4]),
getRandomQuestions: vi.fn(() => ["background-colour", "shape-type"]),
getColorName: vi.fn(hex => {
const colors = {
"#ffffff": "white",
"#000000": "black",
"#ff0000": "red",
"#00ff00": "green",
};
return colors[hex];
}),
})),
};
});

describe('HackPuzzle', () => {
const mockSolutionCalculated = vi.fn();

beforeEach(() => {
mockSolutionCalculated.mockClear();
});

it('should calculate the correct solution and call onSolutionCalculated', () => {
render(<HackPuzzle onSolutionCalculated={mockSolutionCalculated} randomOrderArray={[1, 2, 3, 4]} />);

expect(mockSolutionCalculated).toHaveBeenCalledTimes(1);
expect(mockSolutionCalculated).toHaveBeenCalledWith("white square");
});

it('should render the correct questions based on randomQuestions', () => {
render(<HackPuzzle onSolutionCalculated={mockSolutionCalculated} randomOrderArray={[1, 2, 3, 4]} />);

expect(screen.getByText(/background-colour\(1\) and shape-type\(2\)/)).toBeInTheDocument();
});
});
61 changes: 61 additions & 0 deletions tests/ReactionGame.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { describe, it, expect, vi, act } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import ReactionGame from './ReactionGame';

describe('ReactionGame', () => {
const mockOnReactionComplete = vi.fn();

beforeEach(() => {
mockOnReactionComplete.mockClear();
});

it('should render with initial blue color and correct message', () => {
render(<ReactionGame onReactionComplete={mockOnReactionComplete} />);
const messageElement = screen.getByText('Click this when you are ready.');
expect(messageElement).toBeInTheDocument();
expect(messageElement.closest('div')).toHaveClass('blue');
});

it('should turn red and show wait message when clicked on blue', () => {
render(<ReactionGame onReactionComplete={mockOnReactionComplete} />);
const cardElement = screen.getByText('Click this when you are ready.').closest('div');

fireEvent.click(cardElement);

expect(cardElement).toHaveClass('red');
expect(screen.getByText('Wait for green...')).toBeInTheDocument();
});

it('should reset to blue and show early click message when clicked on red', () => {
render(<ReactionGame onReactionComplete={mockOnReactionComplete} />);
const cardElement = screen.getByText('Click this when you are ready.').closest('div');

// turns red
fireEvent.click(cardElement);
// click while red, should reset to blue
fireEvent.click(cardElement);

expect(cardElement).toHaveClass('blue');
expect(screen.getByText('Sorry, too early! Click this when you are ready.')).toBeInTheDocument();
});

it('should calculate reaction time and call onReactionComplete when clicked on green', () => {
render(<ReactionGame onReactionComplete={mockOnReactionComplete} />);
const cardElement = screen.getByText('Click this when you are ready.').closest('div');

// turns red
fireEvent.click(cardElement);

act(() => {
// simulate the random delay before green
vi.advanceTimersByTime(1500);
});

// click while green
fireEvent.click(cardElement);

expect(mockOnReactionComplete).toHaveBeenCalledTimes(1);
expect(mockOnReactionComplete.mock.calls[0][0]).toBeGreaterThan(0);
expect(screen.getByText(/Your reaction time is \d+ ms\. Click this when you are ready\./)).toBeInTheDocument();
});
});

0 comments on commit f321624

Please sign in to comment.