addHours(6)); $response = $this->get('/js/script.js'); $response->assertStatus(200) ->assertHeader('Content-Type', 'application/javascript') ->assertSee('Cached script'); }); it('fetches plausible script if not cached', function () { Http::fake([ config('plausible-proxy.domain').'/js/script.js' => Http::response('console.log("Plausible script");', 200), ]); $response = $this->get('/js/script.js'); $response->assertStatus(200) ->assertHeader('Content-Type', 'application/javascript') ->assertSee('Plausible script'); expect(Cache::get('plausible_script_js'))->toBe('console.log("Plausible script");'); }); it('handles failed script fetch', function () { Http::fake([ config('plausible-proxy.domain').'/js/script.js' => Http::response('', 500), ]); $response = $this->get('/js/script.js'); $response->assertStatus(500) ->assertSee('Error fetching Plausible script'); }); it('rejects invalid event data', function () { $response = $this->postJson('/api/event', [ 'n' => 'pageview', 'u' => 'invalid-url', 'd' => 'example.com', ]); $response->assertStatus(422) ->assertJsonValidationErrors(['u' => 'The u field must be a valid URL.']); }); it('forwards only user agent and client ip to plausible', function () { config()->set('plausible-proxy.domain', 'https://plausible.io'); Http::fake([ 'https://plausible.io/api/event' => Http::response('ok', 202), ]); $response = $this->withServerVariables(['REMOTE_ADDR' => '203.0.113.7']) ->postJson('/api/event', [ 'n' => 'pageview', 'u' => 'https://example.com/page', 'd' => 'example.com', ], [ 'User-Agent' => 'TestAgent', 'Cookie' => 'laravel_session=secret', 'Authorization' => 'Bearer secret', ]); $response->assertStatus(202); expect($response->getContent())->toBe('ok'); Http::assertSentCount(1); Http::assertSent(function ($request) { return $request->url() === 'https://plausible.io/api/event' && $request->header('User-Agent') === ['TestAgent'] && $request->header('X-Forwarded-For') === ['203.0.113.7'] && ! $request->hasHeader('Cookie') && ! $request->hasHeader('Authorization') && $request['n'] === 'pageview' && $request['u'] === 'https://example.com/page' && $request['d'] === 'example.com'; }); }); it('forwards additional plausible fields', function () { config()->set('plausible-proxy.domain', 'https://plausible.io'); Http::fake([ 'https://plausible.io/api/event' => Http::response('ok', 202), ]); $this->postJson('/api/event', [ 'n' => 'Purchase', 'u' => 'https://example.com/checkout', 'd' => 'example.com', 'i' => false, 'p' => '{"plan":"pro"}', '$' => ['amount' => '9.99', 'currency' => 'EUR'], ])->assertStatus(202); Http::assertSent(function ($request) { return $request['i'] === false && $request['p'] === '{"plan":"pro"}' && $request['$'] === ['amount' => '9.99', 'currency' => 'EUR']; }); }); it('rejects invalid props', function () { $this->postJson('/api/event', [ 'n' => 'pageview', 'u' => 'https://example.com/page', 'd' => 'example.com', 'p' => 'not-json', ])->assertStatus(422)->assertJsonValidationErrors(['p']); });