new: pkg: add test cases to back-end w/ real database connection in it #10
This commit is contained in:
265
docs/testing/FACTORIES.md
Normal file
265
docs/testing/FACTORIES.md
Normal file
@@ -0,0 +1,265 @@
|
||||
# Foundry Factories for MineSeeker
|
||||
|
||||
Factory classes for creating test data. For general Foundry usage, see [Zenstruck Foundry Docs](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html).
|
||||
|
||||
---
|
||||
|
||||
## Available Factories
|
||||
|
||||
All factories are in `tests/Factory/`:
|
||||
|
||||
| Factory | Entity | Use For |
|
||||
|---------|--------|---------|
|
||||
| `UserFactory` | `User` | Registered users with auth |
|
||||
| `GamerFactory` | `Gamer` | Anonymous/guest players |
|
||||
| `PlayedGameFactory` | `PlayedGame` | Game records |
|
||||
| `StepFactory` | `Step` | Individual game moves |
|
||||
| `GridFactory` | `Grid` | 16×16 game grids |
|
||||
| `GridRowFactory` | `GridRow` | Grid row data |
|
||||
| `WebAuthnCredentialFactory` | `WebAuthnCredential` | Passkey credentials |
|
||||
| `ContactMessageFactory` | `ContactMessage` | Contact form messages |
|
||||
|
||||
---
|
||||
|
||||
## Quick Examples
|
||||
|
||||
### UserFactory
|
||||
|
||||
```php
|
||||
// Basic user
|
||||
$user = UserFactory::createOne();
|
||||
|
||||
// Unverified user
|
||||
$user = UserFactory::createOne(['isVerified' => false]);
|
||||
|
||||
// Admin user
|
||||
$user = UserFactory::createOne(['roles' => ['ROLE_ADMIN']]);
|
||||
|
||||
// Multiple users
|
||||
UserFactory::createMany(5);
|
||||
```
|
||||
|
||||
### GamerFactory
|
||||
|
||||
```php
|
||||
// Anonymous gamer
|
||||
$gamer = GamerFactory::new()->anonymous()->create();
|
||||
```
|
||||
|
||||
### PlayedGameFactory
|
||||
|
||||
```php
|
||||
// Game with registered players
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->create();
|
||||
|
||||
// Game with anonymous players
|
||||
$game = PlayedGameFactory::new()
|
||||
->withAnonymousPlayers()
|
||||
->create();
|
||||
|
||||
// Red wins
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->redWins()
|
||||
->create();
|
||||
|
||||
// Blue wins
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->blueWins()
|
||||
->create();
|
||||
|
||||
// Resigned game
|
||||
$game = PlayedGameFactory::new()
|
||||
->resigned('red')
|
||||
->create();
|
||||
```
|
||||
|
||||
### StepFactory
|
||||
|
||||
```php
|
||||
// Mine hit
|
||||
$step = StepFactory::new()
|
||||
->forPlayer('red')
|
||||
->mine()
|
||||
->create(['playedGame' => $game]);
|
||||
|
||||
// Safe cell
|
||||
$step = StepFactory::new()
|
||||
->forPlayer('blue')
|
||||
->safe()
|
||||
->create(['playedGame' => $game]);
|
||||
|
||||
// With revealed cells
|
||||
$step = StepFactory::new()
|
||||
->withRevealedCells([
|
||||
['row' => 5, 'col' => 5],
|
||||
['row' => 5, 'col' => 6],
|
||||
])
|
||||
->create(['playedGame' => $game]);
|
||||
```
|
||||
|
||||
### GridFactory
|
||||
|
||||
```php
|
||||
// Full 16×16 grid
|
||||
$grid = GridFactory::createOne(['playedGame' => $game]);
|
||||
|
||||
// Automatically creates 16 rows
|
||||
self::assertCount(16, $grid->gridRow);
|
||||
```
|
||||
|
||||
### WebAuthnCredentialFactory
|
||||
|
||||
```php
|
||||
// Basic credential
|
||||
$credential = WebAuthnCredentialFactory::createOne(['user' => $user]);
|
||||
|
||||
// Named credential, recently used
|
||||
$credential = WebAuthnCredentialFactory::new()
|
||||
->withName('YubiKey 5C')
|
||||
->recentlyUsed()
|
||||
->create(['user' => $user]);
|
||||
```
|
||||
|
||||
### ContactMessageFactory
|
||||
|
||||
```php
|
||||
// Basic message
|
||||
$message = ContactMessageFactory::createOne();
|
||||
|
||||
// Without consent
|
||||
$message = ContactMessageFactory::new()
|
||||
->withoutConsent()
|
||||
->create();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Factory API Reference
|
||||
|
||||
### Common Methods (All Factories)
|
||||
|
||||
```php
|
||||
// Create single entity
|
||||
Factory::createOne([
|
||||
'property' => 'value',
|
||||
]);
|
||||
|
||||
// Create multiple
|
||||
Factory::createMany(5);
|
||||
|
||||
// Create with factory methods
|
||||
Factory::new()
|
||||
->customMethod()
|
||||
->create(['property' => 'value']);
|
||||
|
||||
// Access repository
|
||||
Factory::repository()->findAll();
|
||||
Factory::repository()->count([]);
|
||||
Factory::repository()->findBy(['field' => 'value']);
|
||||
```
|
||||
|
||||
### PlayedGameFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withRegisteredPlayers()` | Creates game with 2 registered users |
|
||||
| `withAnonymousPlayers()` | Creates game with 2 anonymous gamers |
|
||||
| `withMixedPlayers()` | One registered, one anonymous |
|
||||
| `redWins()` | Red has 26 points |
|
||||
| `blueWins()` | Blue has 26 points |
|
||||
| `resigned(string $player)` | Set resignation ('red' or 'blue') |
|
||||
|
||||
### StepFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `forPlayer(string $player)` | Set player ('red' or 'blue') |
|
||||
| `mine()` | Step hits a mine |
|
||||
| `safe()` | Step reveals safe cell |
|
||||
| `withRevealedCells(array $cells)` | Set revealed cells array |
|
||||
|
||||
### GamerFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `anonymous()` | Set username as "Guest_12345" |
|
||||
|
||||
### WebAuthnCredentialFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withName(string $name)` | Set credential name |
|
||||
| `recentlyUsed()` | Set lastUsedAt to now |
|
||||
|
||||
### ContactMessageFactory Methods
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `withoutConsent()` | Set consent to false |
|
||||
| `anonymous()` | Remove IP address |
|
||||
|
||||
---
|
||||
|
||||
## MineSeeker-Specific Patterns
|
||||
|
||||
### Complete Game Setup
|
||||
|
||||
```php
|
||||
// Create full game with steps and grid
|
||||
$game = PlayedGameFactory::new()
|
||||
->withRegisteredPlayers()
|
||||
->create();
|
||||
|
||||
// Add steps
|
||||
StepFactory::createMany(10, [
|
||||
'playedGame' => $game,
|
||||
'player' => 'red',
|
||||
]);
|
||||
|
||||
// Add grid
|
||||
$grid = GridFactory::createOne(['playedGame' => $game]);
|
||||
```
|
||||
|
||||
### Testing Battle History
|
||||
|
||||
```php
|
||||
// Create multiple finished games for a user
|
||||
$user = UserFactory::createOne();
|
||||
|
||||
PlayedGameFactory::new()
|
||||
->redWins()
|
||||
->create(['red' => $user]);
|
||||
|
||||
PlayedGameFactory::new()
|
||||
->blueWins()
|
||||
->create(['blue' => $user]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Database Isolation
|
||||
|
||||
Tests automatically run in isolated transactions:
|
||||
|
||||
```php
|
||||
public function testDatabaseIsolation(): void
|
||||
{
|
||||
UserFactory::createMany(5);
|
||||
self::assertCount(5, UserFactory::repository()->findAll());
|
||||
|
||||
// Automatically rolled back after test
|
||||
}
|
||||
```
|
||||
|
||||
No manual cleanup needed. Each test starts with a clean database.
|
||||
|
||||
---
|
||||
|
||||
## External Resources
|
||||
|
||||
- **[Zenstruck Foundry Documentation](https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html)** - Complete Foundry guide
|
||||
- **[DAMA Doctrine Test Bundle](https://github.com/dmaicher/doctrine-test-bundle)** - Transaction isolation details
|
||||
Reference in New Issue
Block a user