feed = Feed::factory()->create(); $this->channel = PlatformChannel::factory()->create(); $this->route = Route::create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'is_active' => true, 'priority' => 50 ]); } public function test_can_get_keywords_for_route(): void { $keyword = Keyword::factory()->create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'keyword' => 'test keyword', 'is_active' => true ]); $response = $this->getJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords"); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'data' => [ '*' => [ 'id', 'keyword', 'is_active', 'feed_id', 'platform_channel_id' ] ] ]) ->assertJsonPath('data.0.keyword', 'test keyword'); } public function test_can_create_keyword_for_route(): void { $keywordData = [ 'keyword' => 'new keyword', 'is_active' => true ]; $response = $this->postJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords", $keywordData); $response->assertStatus(201) ->assertJsonStructure([ 'success', 'data' => [ 'id', 'keyword', 'is_active', 'feed_id', 'platform_channel_id' ] ]) ->assertJsonPath('data.keyword', 'new keyword') ->assertJsonPath('data.is_active', true); $this->assertDatabaseHas('keywords', [ 'keyword' => 'new keyword', 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'is_active' => true ]); } public function test_cannot_create_duplicate_keyword_for_route(): void { Keyword::factory()->create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'keyword' => 'duplicate keyword' ]); $response = $this->postJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords", [ 'keyword' => 'duplicate keyword' ]); $response->assertStatus(409) ->assertJsonPath('success', false) ->assertJsonPath('message', 'Keyword already exists for this route.'); } public function test_can_update_keyword(): void { $keyword = Keyword::factory()->create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'is_active' => true ]); $response = $this->putJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords/{$keyword->id}", [ 'is_active' => false ]); $response->assertStatus(200) ->assertJsonPath('data.is_active', false); $this->assertDatabaseHas('keywords', [ 'id' => $keyword->id, 'is_active' => false ]); } public function test_can_delete_keyword(): void { $keyword = Keyword::factory()->create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id ]); $response = $this->deleteJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords/{$keyword->id}"); $response->assertStatus(200); $this->assertDatabaseMissing('keywords', [ 'id' => $keyword->id ]); } public function test_can_toggle_keyword(): void { $keyword = Keyword::factory()->create([ 'feed_id' => $this->feed->id, 'platform_channel_id' => $this->channel->id, 'is_active' => true ]); $response = $this->postJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords/{$keyword->id}/toggle"); $response->assertStatus(200) ->assertJsonPath('data.is_active', false); $this->assertDatabaseHas('keywords', [ 'id' => $keyword->id, 'is_active' => false ]); } public function test_cannot_access_keyword_from_different_route(): void { $otherFeed = Feed::factory()->create(); $otherChannel = PlatformChannel::factory()->create(); $keyword = Keyword::factory()->create([ 'feed_id' => $otherFeed->id, 'platform_channel_id' => $otherChannel->id ]); $response = $this->deleteJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords/{$keyword->id}"); $response->assertStatus(404) ->assertJsonPath('message', 'Keyword not found for this route.'); } public function test_validates_required_fields(): void { $response = $this->postJson("/api/v1/routing/{$this->feed->id}/{$this->channel->id}/keywords", []); $response->assertStatus(422) ->assertJsonValidationErrors(['keyword']); } }