| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- <?php
- /*
- * Copyright 2026 Alessandro Chiapparini <sprint_planer_web@chiapparini.org>
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * See the LICENSE file in the project root for the full license text.
- */
- declare(strict_types=1);
- namespace App\Tests\Db;
- use PDO;
- use PHPUnit\Framework\TestCase;
- /**
- * Phase 12: verify migration 002 backfills active_days_mask from the legacy
- * free-form max_working_days values, and clamps half-day values to whole
- * integers in 0..5 without dropping rows or widening beyond Mo–Fr.
- *
- * We start from a 001-only schema (no active_days_mask column), hand-insert
- * a row per legacy value we care about, then apply 002 and read back.
- */
- final class MigrationBackfillTest extends TestCase
- {
- private function makeLegacyDb(): PDO
- {
- $pdo = new PDO('sqlite::memory:', null, null, [
- PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
- PDO::ATTR_EMULATE_PREPARES => false,
- ]);
- $pdo->exec('PRAGMA foreign_keys = ON');
- $sql = file_get_contents(__DIR__ . '/../../migrations/001_init.sql');
- $this->assertNotFalse($sql, 'read 001_init.sql');
- $pdo->exec($sql);
- return $pdo;
- }
- /** @return list<array{legacyDays:float, expectedMask:int, expectedDays:float}> */
- public static function cases(): array
- {
- return [
- // whole numbers 0..5 stay as themselves
- ['legacyDays' => 0.0, 'expectedMask' => 0, 'expectedDays' => 0.0],
- ['legacyDays' => 1.0, 'expectedMask' => 0b1, 'expectedDays' => 1.0],
- ['legacyDays' => 3.0, 'expectedMask' => 0b111, 'expectedDays' => 3.0],
- ['legacyDays' => 5.0, 'expectedMask' => 31, 'expectedDays' => 5.0],
- // half-days round up (2.5 → 3, 4.5 → 5)
- ['legacyDays' => 2.5, 'expectedMask' => 0b111, 'expectedDays' => 3.0],
- ['legacyDays' => 4.5, 'expectedMask' => 31, 'expectedDays' => 5.0],
- // 0.5 rounds up to 1
- ['legacyDays' => 0.5, 'expectedMask' => 0b1, 'expectedDays' => 1.0],
- ];
- }
- public function testBackfillMapsLegacyValuesToMask(): void
- {
- $pdo = $this->makeLegacyDb();
- // Seed a sprint + one week per case.
- $pdo->exec("INSERT INTO sprints (id, name, start_date, end_date, reserve_fraction, is_archived, created_at, updated_at)
- VALUES (1, 'S', '2026-01-05', '2026-03-30', 0.2, 0, '2026-01-01T00:00:00Z', '2026-01-01T00:00:00Z')");
- $insertWeek = $pdo->prepare(
- 'INSERT INTO sprint_weeks (id, sprint_id, sort_order, iso_week, start_date, max_working_days)
- VALUES (?, 1, ?, ?, ?, ?)'
- );
- $cases = self::cases();
- foreach ($cases as $i => $c) {
- $insertWeek->execute([
- $i + 1, $i + 1, 1, '2026-01-05', $c['legacyDays'],
- ]);
- }
- // Apply migration 002.
- $sql = file_get_contents(__DIR__ . '/../../migrations/002_sprint_week_active_days.sql');
- $this->assertNotFalse($sql, 'read 002');
- $pdo->exec($sql);
- // The column now exists; legacy rows were rewritten.
- $rows = $pdo->query('SELECT id, max_working_days, active_days_mask FROM sprint_weeks ORDER BY id')->fetchAll();
- $this->assertCount(count($cases), $rows);
- foreach ($cases as $i => $c) {
- $row = $rows[$i];
- $this->assertSame(
- $c['expectedMask'],
- (int) $row['active_days_mask'],
- "mask for legacy={$c['legacyDays']} (row id={$row['id']})",
- );
- $this->assertEqualsWithDelta(
- $c['expectedDays'],
- (float) $row['max_working_days'],
- 1e-9,
- "days for legacy={$c['legacyDays']}",
- );
- }
- }
- }
|