'https://bnfexpress.test', 'services.bnfexpress.client_id' => 'ev_admin', 'services.bnfexpress.client_secret' => 'test-secret', ]); Permission::findOrCreate('manage_ai_agent', 'web'); $this->admin = User::factory()->create()->givePermissionTo(['manage_ai_agent']); $this->actingAs($this->admin); }); test('a user without manage_ai_agent cannot access it', function () { $this->actingAs(User::factory()->create()); expect(ManageSuggestionMisses::canAccess())->toBeFalse(); }); test('it renders and lists misses from the client', function () { Http::fake(['bnfexpress.test/*' => Http::response([ ['id' => 1, 'text_norm' => 'ev charging cost', 'lang' => 'en', 'syllables' => 3, 'was_used' => false, 'created_at' => now()->toIso8601String()], ])]); Livewire::test(ManageSuggestionMisses::class) ->assertOk() ->loadTable() ->assertSee('ev charging cost'); Http::assertSent(fn (Request $request) => str_contains($request->url(), '/admin/suggestion-misses') && $request->method() === 'GET'); }); test('dismiss calls dismissSuggestionMiss and shows a success notification', function () { Http::fake(['bnfexpress.test/*' => fn (Request $request) => match ($request->method()) { 'DELETE' => Http::response([]), default => Http::response([ ['id' => 1, 'text_norm' => 'to dismiss', 'lang' => 'en', 'syllables' => 2, 'was_used' => false, 'created_at' => now()->toIso8601String()], ]), }]); Livewire::test(ManageSuggestionMisses::class) ->loadTable() ->callTableAction('dismiss', 1) ->assertNotified('Miss dismissed'); Http::assertSent(fn (Request $request) => $request->method() === 'DELETE' && str_contains($request->url(), '/admin/suggestion-misses/1')); }); test('a failed dismiss surfaces the gateway detail message', function () { Http::fake(['bnfexpress.test/*' => fn (Request $request) => match ($request->method()) { 'DELETE' => Http::response(['detail' => 'Suggestion miss not found.'], 404), default => Http::response([ ['id' => 1, 'text_norm' => 'to dismiss', 'lang' => 'en', 'syllables' => 2, 'was_used' => false, 'created_at' => now()->toIso8601String()], ]), }]); Livewire::test(ManageSuggestionMisses::class) ->loadTable() ->callTableAction('dismiss', 1) ->assertNotified('Failed to dismiss miss'); }); test('promote bulk action calls promoteSuggestionMisses with the selected ids and shows the result', function () { Http::fake(['bnfexpress.test/*' => fn (Request $request) => match (true) { str_contains($request->url(), '/admin/suggestion-misses/promote') => Http::response(['created' => 2, 'skipped' => 0, 'trie_rebuilt' => true]), default => Http::response([ ['id' => 1, 'text_norm' => 'a', 'lang' => 'en', 'syllables' => 1, 'was_used' => false, 'created_at' => now()->toIso8601String()], ['id' => 2, 'text_norm' => 'b', 'lang' => 'en', 'syllables' => 1, 'was_used' => false, 'created_at' => now()->toIso8601String()], ]), }]); Livewire::test(ManageSuggestionMisses::class) ->loadTable() ->callTableBulkAction('promote', [1, 2], data: ['lang' => 'my', 'intent' => null]) ->assertNotified('2 promoted, 0 skipped'); Http::assertSent(fn (Request $request) => str_contains($request->url(), '/admin/suggestion-misses/promote') && $request['miss_ids'] === [1, 2] && $request['lang'] === 'my'); });