client->request('GET', '/setup/' . self::MAC); $this->assertResponseIsSuccessful(); } // S-02: authenticated with named device → redirects to spa (/) public function test_setup_index_authenticated_named_device_redirects_to_spa(): void { $user = $this->createUser('setup02@example.com'); $device = new Device(); $device->setMac(self::MAC); $device->setName('Living Room'); $device->setUser($user); $this->em()->persist($device); $this->em()->flush(); $this->loginAs($user); $this->client->request('GET', '/setup/' . self::MAC); $this->assertResponseRedirects('/'); } // S-03: authenticated with no existing device (new link) → redirects to configure public function test_setup_index_authenticated_new_device_redirects_to_configure(): void { $user = $this->createUser('setup03@example.com'); $this->loginAs($user); $this->client->request('GET', '/setup/' . self::MAC); $this->assertResponseRedirects('/setup/' . self::MAC . '/configure'); } // S-04: POST /setup/{mac}/register with valid data → creates user, links device, redirects to configure public function test_setup_register_creates_user_and_redirects_to_configure(): void { $this->client->request('POST', '/setup/' . self::MAC . '/register', [ 'registration_form' => [ 'email' => 'setupnew@example.com', 'plainPassword' => [ 'first' => 'securepass123', 'second' => 'securepass123', ], ], ]); $this->assertResponseRedirects('/setup/' . self::MAC . '/configure'); } // S-05: POST /setup/{mac}/configure with valid name → saves device, redirects to spa public function test_setup_configure_saves_name_and_redirects_to_spa(): void { $user = $this->createUser('setup05@example.com'); $device = new Device(); $device->setMac(self::MAC); $device->setUser($user); $this->em()->persist($device); $this->em()->flush(); $deviceId = $device->getId(); $this->loginAs($user); $this->client->request('POST', '/setup/' . self::MAC . '/configure', [ 'name' => 'Kitchen Frame', 'orientation' => 'landscape', 'rotation_interval_minutes' => '1440', 'uniqueness_window' => '10', ]); $this->assertResponseRedirects('/'); $this->em()->clear(); $saved = $this->em()->find(Device::class, $deviceId); $this->assertSame('Kitchen Frame', $saved->getName()); } // S-06: POST /setup/{mac}/login with valid credentials → redirects to configure public function test_login_valid_credentials_redirects_to_configure(): void { $this->createUser('setuplogin@example.com', 'testpass'); $this->client->request('POST', '/setup/' . self::MAC . '/login', [ '_username' => 'setuplogin@example.com', '_password' => 'testpass', ]); $this->assertResponseRedirects('/setup/' . self::MAC . '/configure'); } // S-07: POST /setup/{mac}/login with wrong password → redirects to index public function test_login_invalid_credentials_redirects_to_index(): void { $this->createUser('setupbadlogin@example.com', 'testpass'); $this->client->request('POST', '/setup/' . self::MAC . '/login', [ '_username' => 'setupbadlogin@example.com', '_password' => 'wrongpass', ]); $this->assertResponseRedirects('/setup/' . self::MAC); } // S-08: authenticated GET /setup/{mac}/configure → 200 public function test_configure_get_renders_form(): void { $user = $this->createUser('setupconfigget@example.com'); $device = new Device(); $device->setMac(self::MAC); $device->setUser($user); $this->em()->persist($device); $this->em()->flush(); $this->loginAs($user); $this->client->request('GET', '/setup/' . self::MAC . '/configure'); $this->assertResponseIsSuccessful(); } // S-09: POST /setup/{mac}/configure with empty name → 200 (re-renders form with error) public function test_configure_post_empty_name_renders_error(): void { $user = $this->createUser('setupconfigerr@example.com'); $device = new Device(); $device->setMac(self::MAC); $device->setUser($user); $this->em()->persist($device); $this->em()->flush(); $this->loginAs($user); $this->client->request('POST', '/setup/' . self::MAC . '/configure', [ 'name' => '', 'orientation' => 'landscape', ]); $this->assertResponseIsSuccessful(); } // S-10: POST /setup/{mac}/register with invalid form data → re-renders registration page public function test_setup_register_invalid_form_renders_page(): void { // Valid email (avoids TypeError) but mismatched passwords → form is invalid $this->client->request('POST', '/setup/' . self::MAC . '/register', [ 'registration_form' => [ 'email' => 'setup-invalid@example.com', 'plainPassword' => [ 'first' => 'password123', 'second' => 'different456', ], ], ]); // Symfony 7 returns 422 for submitted-but-invalid forms $this->assertResponseStatusCodeSame(422); } }