getMockForAbstractClass( ContainerInterface::class ) ); $permissionManager = $this->createMock( PermissionManager::class ); $routeFiles = array_merge( [ __DIR__ . '/testRoutes.json' ], $additionalRouteFiles ); return new Router( $routeFiles, [], 'http://wiki.example.com', '/rest', new \EmptyBagOStuff(), new ResponseFactory( [] ), new StaticBasicAuthorizer( $authError ), $objectFactory, new Validator( $objectFactory, $permissionManager, $request, new User ), $this->createHookContainer() ); } public function testPrefixMismatch() { $request = new RequestData( [ 'uri' => new Uri( '/bogus' ) ] ); $router = $this->createRouter( $request ); $response = $router->execute( $request ); $this->assertSame( 404, $response->getStatusCode() ); } public function testWrongMethod() { $request = new RequestData( [ 'uri' => new Uri( '/rest/mock/RouterTest/hello' ), 'method' => 'OPTIONS' ] ); $router = $this->createRouter( $request ); $response = $router->execute( $request ); $this->assertSame( 405, $response->getStatusCode() ); $this->assertSame( 'Method Not Allowed', $response->getReasonPhrase() ); $this->assertSame( 'GET', $response->getHeaderLine( 'Allow' ) ); } public function testHeadToGet() { $request = new RequestData( [ 'uri' => new Uri( '/rest/mock/RouterTest/hello' ), 'method' => 'HEAD' ] ); $router = $this->createRouter( $request ); $response = $router->execute( $request ); $this->assertSame( 200, $response->getStatusCode() ); } public function testNoMatch() { $request = new RequestData( [ 'uri' => new Uri( '/rest/bogus' ) ] ); $router = $this->createRouter( $request ); $response = $router->execute( $request ); $this->assertSame( 404, $response->getStatusCode() ); // TODO: add more information to the response body and test for its presence here } public static function throwHandlerFactory() { return new class extends Handler { public function execute() { throw new HttpException( 'Mock error', 555 ); } }; } public function testException() { $request = new RequestData( [ 'uri' => new Uri( '/rest/mock/RouterTest/throw' ) ] ); $router = $this->createRouter( $request ); $response = $router->execute( $request ); $this->assertSame( 555, $response->getStatusCode() ); $body = $response->getBody(); $body->rewind(); $data = json_decode( $body->getContents(), true ); $this->assertSame( 'Mock error', $data['message'] ); } public function testBasicAccess() { // Using the throwing handler is a way to assert that the handler is not executed $request = new RequestData( [ 'uri' => new Uri( '/rest/mock/RouterTest/throw' ) ] ); $router = $this->createRouter( $request, 'test-error', [] ); $response = $router->execute( $request ); $this->assertSame( 403, $response->getStatusCode() ); $body = $response->getBody(); $body->rewind(); $data = json_decode( $body->getContents(), true ); $this->assertSame( 'test-error', $data['error'] ); } /** * @dataProvider providePaths */ public function testAdditionalEndpoints( $path ) { $request = new RequestData( [ 'uri' => new Uri( $path ) ] ); $router = $this->createRouter( $request, null, [ __DIR__ . '/testAdditionalRoutes.json' ] ); $response = $router->execute( $request ); $this->assertSame( 200, $response->getStatusCode() ); } public static function providePaths() { return [ [ '/rest/mock/RouterTest/hello' ], [ '/rest/mock/RouterTest/hello/two' ], ]; } public function provideGetRouteUrl() { yield 'empty' => [ '' ]; yield 'simple route' => [ '/foo/bar' ]; yield 'simple route with query' => [ '/foo/bar', [ 'x' => '1', 'y' => '2' ] ]; yield 'strange chars' => [ '/foo+bar', [ 'x' => '#', 'y' => '%' ] ]; } /** * @dataProvider provideGetRouteUrl */ public function testGetRouteUrl( $route, $query = [] ) { $request = new RequestData( [ 'uri' => new Uri( '/rest/mock/route' ) ] ); $router = $this->createRouter( $request ); $url = $router->getRouteUrl( $route, $query ); $this->assertRegExp( '!^https?://[\w.]+/!', $url ); $uri = new Uri( $url ); $this->assertSame( wfArrayToCgi( $query ), $uri->getQuery() ); $this->assertStringContainsString( $route, $uri->getPath() ); } }