assertEquals('https', $this->getPrivateProperty($request, 'scheme')); $this->assertEquals('lemmy.world', $this->getPrivateProperty($request, 'instance')); $this->assertNull($this->getPrivateProperty($request, 'token')); } public function test_constructor_with_https_url(): void { $request = new LemmyRequest('https://lemmy.world'); $this->assertEquals('https', $this->getPrivateProperty($request, 'scheme')); $this->assertEquals('lemmy.world', $this->getPrivateProperty($request, 'instance')); } public function test_constructor_with_http_url(): void { $request = new LemmyRequest('http://lemmy.world'); $this->assertEquals('http', $this->getPrivateProperty($request, 'scheme')); $this->assertEquals('lemmy.world', $this->getPrivateProperty($request, 'instance')); } public function test_constructor_with_trailing_slash(): void { $request = new LemmyRequest('lemmy.world/'); $this->assertEquals('lemmy.world', $this->getPrivateProperty($request, 'instance')); } public function test_constructor_with_full_url_and_trailing_slash(): void { $request = new LemmyRequest('https://lemmy.world/'); $this->assertEquals('https', $this->getPrivateProperty($request, 'scheme')); $this->assertEquals('lemmy.world', $this->getPrivateProperty($request, 'instance')); } public function test_constructor_with_token(): void { $request = new LemmyRequest('lemmy.world', 'test-token'); $this->assertEquals('test-token', $this->getPrivateProperty($request, 'token')); } public function test_constructor_preserves_case_in_scheme_detection(): void { $request = new LemmyRequest('HTTPS://lemmy.world'); $this->assertEquals('https', $this->getPrivateProperty($request, 'scheme')); } public function test_with_scheme_sets_https(): void { $request = new LemmyRequest('lemmy.world'); $result = $request->withScheme('https'); $this->assertSame($request, $result); $this->assertEquals('https', $this->getPrivateProperty($request, 'scheme')); } public function test_with_scheme_sets_http(): void { $request = new LemmyRequest('lemmy.world'); $result = $request->withScheme('http'); $this->assertSame($request, $result); $this->assertEquals('http', $this->getPrivateProperty($request, 'scheme')); } public function test_with_scheme_normalizes_case(): void { $request = new LemmyRequest('lemmy.world'); $request->withScheme('HTTPS'); $this->assertEquals('https', $this->getPrivateProperty($request, 'scheme')); } public function test_with_scheme_ignores_invalid_schemes(): void { $request = new LemmyRequest('lemmy.world'); $originalScheme = $this->getPrivateProperty($request, 'scheme'); $request->withScheme('ftp'); $this->assertEquals($originalScheme, $this->getPrivateProperty($request, 'scheme')); } public function test_with_token_sets_token(): void { $request = new LemmyRequest('lemmy.world'); $result = $request->withToken('new-token'); $this->assertSame($request, $result); $this->assertEquals('new-token', $this->getPrivateProperty($request, 'token')); } public function test_get_without_token(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $response = $request->get('site'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'https://lemmy.world/api/v3/site' && !$httpRequest->hasHeader('Authorization'); }); } public function test_get_with_token(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world', 'test-token'); $response = $request->get('site'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'https://lemmy.world/api/v3/site' && $httpRequest->header('Authorization')[0] === 'Bearer test-token'; }); } public function test_get_with_parameters(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $params = ['limit' => 10, 'page' => 1]; $response = $request->get('posts', $params); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) use ($params) { $url = $httpRequest->url(); return str_contains($url, 'https://lemmy.world/api/v3/posts') && str_contains($url, 'limit=10') && str_contains($url, 'page=1'); }); } public function test_get_with_http_scheme(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $request->withScheme('http'); $response = $request->get('site'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'http://lemmy.world/api/v3/site'; }); } public function test_post_without_token(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $response = $request->post('login'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'https://lemmy.world/api/v3/login' && $httpRequest->method() === 'POST' && !$httpRequest->hasHeader('Authorization'); }); } public function test_post_with_token(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world', 'test-token'); $response = $request->post('login'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'https://lemmy.world/api/v3/login' && $httpRequest->method() === 'POST' && $httpRequest->header('Authorization')[0] === 'Bearer test-token'; }); } public function test_post_with_data(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $data = ['username' => 'test', 'password' => 'pass']; $response = $request->post('login', $data); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) use ($data) { return $httpRequest->url() === 'https://lemmy.world/api/v3/login' && $httpRequest->method() === 'POST' && $httpRequest->data() === $data; }); } public function test_post_with_http_scheme(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $request->withScheme('http'); $response = $request->post('login'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'http://lemmy.world/api/v3/login'; }); } public function test_requests_use_30_second_timeout(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $request->get('site'); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'https://lemmy.world/api/v3/site'; }); } public function test_chaining_methods(): void { Http::fake(['*' => Http::response(['success' => true])]); $request = new LemmyRequest('lemmy.world'); $response = $request->withScheme('http')->withToken('chained-token')->get('site'); $this->assertInstanceOf(Response::class, $response); Http::assertSent(function ($httpRequest) { return $httpRequest->url() === 'http://lemmy.world/api/v3/site' && $httpRequest->header('Authorization')[0] === 'Bearer chained-token'; }); } private function getPrivateProperty(object $object, string $property): mixed { $reflection = new \ReflectionClass($object); $reflectionProperty = $reflection->getProperty($property); $reflectionProperty->setAccessible(true); return $reflectionProperty->getValue($object); } }