Move all files to php/pest/

This commit is contained in:
Oliver Davies 2025-09-29 23:09:31 +01:00
parent a62c22030e
commit 8784174d85
23 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
use App\Anagram;
it('selects the correct anagrams for a word', function () {
$matches = Anagram::forWord(
'listen',
['enlists', 'google', 'inlets', 'banana']
);
assertSame(['inlets'], $matches->toArray());
});

View file

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
use App\Bob;
it('replies with a standard response', function (): void {
$input = 'Foo bar';
$expected = Bob::RESPONSE_DEFAULT;
assertSame($expected, Bob::saySomethingTo($input)->getResponse());
});
it('replies if you address him without saying anything', function (): void {
$input = '';
$expected = Bob::RESPONSE_SAY_NOTHING;
assertSame($expected, Bob::saySomethingTo($input)->getResponse());
});
it('replies to a question', function (): void {
$input = 'How are you?';
$expected = Bob::RESPONSE_QUESTION;
assertSame($expected, Bob::saySomethingTo($input)->getResponse());
});
it('replies to yelling', function (): void {
$input = 'Go to bed!';
$expected = Bob::RESPONSE_YELLING;
assertSame($expected, Bob::saySomethingTo($input)->getResponse());
});
it('replies to yelling a question', function (): void {
$input = 'Are you OK?!';
$expected = Bob::RESPONSE_YELLING_QUESTION;
assertSame($expected, Bob::saySomethingTo($input)->getResponse());
});

View file

@ -0,0 +1,134 @@
<?php
declare(strict_types=1);
use App\BowlingGame;
use Assert\Assert;
use Assert\AssertionFailedException;
beforeEach(function (): void {
$this->game = new BowlingGame();
});
it('counts an empty game', function (): void {
foreach (range(1, 20) as $roll) {
$this->game->roll(0);
}
assertSame(0, $this->game->getScore());
});
it('counts all single pins', function (): void {
foreach (range(1, 20) as $roll) {
$this->game->roll(1);
}
assertSame(20, $this->game->getScore());
});
it('adds a roll one bonus for a spare', function (): void {
$this->game->roll(5);
$this->game->roll(5); // Spare
$this->game->roll(2);
foreach (range(1, 17) as $roll) {
$this->game->roll(0);
}
assertSame(14, $this->game->getScore());
});
it('adds a two roll bonus for a strike', function (): void {
$this->game->roll(10); // Strike
$this->game->roll(3);
$this->game->roll(6);
foreach (range(1, 16) as $roll) {
$this->game->roll(0);
}
assertSame(28, $this->game->getScore());
});
it('adds an extra ball for a spare on the final frame', function (): void {
foreach (range(1, 18) as $roll) {
$this->game->roll(0);
}
$this->game->roll(7);
$this->game->roll(3); // Spare
$this->game->roll(5);
assertSame(15, $this->game->getScore());
});
it('adds an two extra balls for a strike on the final frame', function (): void {
foreach (range(1, 18) as $roll) {
$this->game->roll(0);
}
$this->game->roll(10); // Strike
$this->game->roll(4);
$this->game->roll(2);
assertSame(16, $this->game->getScore());
});
it('scores a perfect game', function (): void {
foreach (range(1, 12) as $roll) {
$this->game->roll(10);
}
assertSame(300, $this->game->getScore());
});
it('scores a normal game', function (): void {
$this->game->roll(4);
$this->game->roll(3);
$this->game->roll(10);
$this->game->roll(4);
$this->game->roll(1);
$this->game->roll(0);
$this->game->roll(2);
$this->game->roll(3);
$this->game->roll(7);
$this->game->roll(8);
$this->game->roll(1);
$this->game->roll(10);
$this->game->roll(0);
$this->game->roll(7);
$this->game->roll(1);
$this->game->roll(5);
$this->game->roll(10);
$this->game->roll(6);
$this->game->roll(1);
assertSame(103, $this->game->getScore());
});
it('cannot knock down a negative pins', function (): void {
$this->game->roll(-1);
})->throws(
AssertionFailedException::class,
'You cannot knock down a negative number of pins. Knocked down -1.'
);
it('cannot knock down more than 10 pins in a roll', function (): void {
$this->game->roll(12);
})->throws(
AssertionFailedException::class,
'You can only knock down a maximum of 10 pins in a roll. Knocked down 12.'
);

View file

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
use function App\flattenArray;
it('flattens an array', function (
array $input,
array $expected
): void {
$result = flattenArray($input);
assertSame($expected, $result);
})->with([
[
'input' => [1, 2, 3],
'expected' => [1, 2, 3],
],
[
'input' => [1, [2, 3, null, 4], [null], 5],
'expected' => [1, 2, 3, 4, 5],
],
[
'input' => [1, [2, [[3]], [4, [[5]]], 6, 7], 8],
'expected' => [1, 2, 3, 4, 5, 6, 7, 8],
],
[
'input' => [null, [[[null]]], null, null, [[null, null], null], null],
'expected' => [],
]
]);

View file

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
use App\GradeSchool;
use Assert\AssertionFailedException;
beforeEach(function (): void {
$this->school = new GradeSchool();
});
it('gets all students', function (): void {
$this->school->addStudentToGrade('Anna', 1);
$this->school->addStudentToGrade('Jim', 2);
$this->school->addStudentToGrade('Charlie', 3);
$expected = [
['grade' => 1, 'students' => ['Anna']],
['grade' => 2, 'students' => ['Jim']],
['grade' => 3, 'students' => ['Charlie']],
];
assertSame($expected, $this->school->getAllStudents()->toArray());
});
it('can get students by grade', function (): void {
$this->school->addStudentToGrade('Jim', 2);
assertSame(['Jim'], $this->school->getStudentsByGrade(2)->toArray());
});
it('should order grades numerically', function (): void {
$this->school->addStudentToGrade('Anna', 1);
$this->school->addStudentToGrade('Charlie', 3);
$this->school->addStudentToGrade('Jim', 2);
$this->school->addStudentToGrade('Harry', 4);
$expected = [
['grade' => 1, 'students' => ['Anna']],
['grade' => 2, 'students' => ['Jim']],
['grade' => 3, 'students' => ['Charlie']],
['grade' => 4, 'students' => ['Harry']],
];
assertSame($expected, $this->school->getAllStudents()->toArray());
});
it('names within a grade are ordered alphabetically', function (): void {
$this->school->addStudentToGrade('Charlie', 1);
$this->school->addStudentToGrade('Barb', 1);
$this->school->addStudentToGrade('Anna', 1);
$this->school->addStudentToGrade('Peter', 2);
$this->school->addStudentToGrade('Alex', 2);
$this->school->addStudentToGrade('Zoe', 2);
$expected = [
[
'grade' => 1,
'students' => ['Anna', 'Barb', 'Charlie'],
],
[
'grade' => 2,
'students' => ['Alex', 'Peter', 'Zoe'],
]
];
assertSame($expected, $this->school->getAllStudents()->toArray());
});
test('name cannot be empty', function (): void {
$this->school->addStudentToGrade('', 1);
})->throws(
AssertionFailedException::class,
'Name cannot be blank'
);
test('grade cannot be zero or negative', function (int $grade): void {
$this->school->addStudentToGrade('Fred', $grade);
})->with([0, -1])->throws(
AssertionFailedException::class,
'Grade must be greater than or equal to 1'
);

View file

@ -0,0 +1,19 @@
<?php
use function App\isPangram;
it('determines if a string is a pangram', function (
string $input,
bool $expected
) {
assertSame($expected, isPangram($input));
})->with([
[
'input' => 'hello word',
'expected' => false,
],
[
'input' => 'The quick brown fox jumps over the lazy dog',
'expected' => true,
]
]);

View file

@ -0,0 +1,72 @@
<?php
use Assert\AssertionFailedException;
beforeEach(function () {
$this->game = new App\RockPaperScissorsGame();
});
it('throws an exception for an empty first move', function () {
$this->game->firstMove('');
})->throws(AssertionFailedException::class, 'You must specify a move.');
it('throws an exception for an empty second move', function () {
$this->game->secondMove('');
})->throws(AssertionFailedException::class, 'You must specify a move.');
it('throws an exception if an invalid first move is entered', function () {
$this->game->firstMove('banana');
})->throws(AssertionFailedException::class, 'You must enter a valid move. banana given.');
it('throws an exception if an invalid second move is entered', function () {
$this->game->secondMove('apple');
})->throws(AssertionFailedException::class, 'You must enter a valid move. apple given.');
it('returns the result of two different valid moves', function (
string $firstMove,
string $secondMove,
string $winner
) {
$this->game
->firstMove($firstMove)
->secondMove($secondMove);
assertSame($winner, $this->game->getWinner());
})->with([
[
'firstMove' => 'rock',
'secondMove' => 'paper',
'winner' => 'paper',
],
[
'firstMove' => 'paper',
'secondMove' => 'rock',
'winner' => 'paper',
],
[
'firstMove' => 'rock',
'secondMove' => 'scissors',
'winner' => 'scissors',
],
[
'firstMove' => 'scissors',
'secondMove' => 'rock',
'winner' => 'scissors',
],
[
'firstMove' => 'scissors',
'secondMove' => 'paper',
'winner' => 'scissors',
],
[
'firstMove' => 'paper',
'secondMove' => 'scissors',
'winner' => 'scissors',
],
]);
test('it returns null if there is a tie', function (string $move) {
$this->game->firstMove($move)->secondMove($move);
assertNull($this->game->getWinner());
})->with(['rock', 'paper', 'scissors']);

View file

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
use App\RomanNumeralsConverter;
use Assert\AssertionFailedException;
it('converts numbers to roman numerals', function (int $number, string $expected): void {
assertSame($expected, RomanNumeralsConverter::convert($number));
})->with([
[1, 'I'],
[2, 'II'],
[3, 'III'],
[4, 'IV'],
[5, 'V'],
[9, 'IX'],
[10, 'X'],
[15, 'XV'],
[19, 'XIX'],
[20, 'XX'],
[21, 'XXI'],
[40, 'XL'],
[50, 'L'],
[80, 'LXXX'],
[90, 'XC'],
[100, 'C'],
[110, 'CX'],
[400, 'CD'],
[500, 'D'],
[700, 'DCC'],
[900, 'CM'],
[1000, 'M'],
[1986, 'MCMLXXXVI'],
[1990, 'MCMXC'],
[2020, 'MMXX'],
]);
it('cannot convert negative numbers', function (): void {
RomanNumeralsConverter::convert(-1);
})->throws(AssertionFailedException::class, 'Cannot convert negative numbers');