452 lines
13 KiB
PHP
452 lines
13 KiB
PHP
<?php
|
|
|
|
// use Swagger\Serializer;
|
|
use App\Enums\UserState;
|
|
use App\Http\Resources\AirlineResource;
|
|
use App\Http\Resources\AirportResource;
|
|
use App\Http\Resources\NewsResource;
|
|
use App\Models\Aircraft;
|
|
use App\Models\Airline;
|
|
use App\Models\Airport;
|
|
use App\Models\Fare;
|
|
use App\Models\News;
|
|
use App\Models\Subfleet;
|
|
use App\Models\User;
|
|
use App\Services\FareService;
|
|
use App\Support\Utils;
|
|
|
|
test('api authentication', function (): void {
|
|
$user = User::factory()->create();
|
|
|
|
$uri = '/api/user';
|
|
|
|
// Missing auth header
|
|
$res = $this->get($uri);
|
|
$res->assertStatus(401);
|
|
|
|
// Test invalid API key
|
|
$this->withHeaders(['Authorization' => 'invalidKey'])->get($uri)
|
|
->assertStatus(401);
|
|
|
|
$this->withHeaders(['Authorization' => ''])->get($uri)
|
|
->assertStatus(401);
|
|
|
|
// Test upper/lower case of Authorization header, etc
|
|
$response = $this->withHeader('Authorization', $user->api_key)->get($uri);
|
|
$body = $response->json();
|
|
$response->assertStatus(200)->assertJson(['data' => ['id' => $user->id]]);
|
|
|
|
$this->withHeaders(['x-api-key' => $user->api_key])->get($uri)
|
|
->assertJson(['data' => ['id' => $user->id]]);
|
|
|
|
$this->withHeaders(['x-API-key' => $user->api_key])->get($uri)
|
|
->assertJson(['data' => ['id' => $user->id]]);
|
|
|
|
$this->withHeaders(['X-API-KEY' => $user->api_key])->get($uri)
|
|
->assertJson(['data' => ['id' => $user->id]]);
|
|
});
|
|
|
|
it('should deny a non active user', function (): void {
|
|
$uri = '/api/user';
|
|
|
|
$user = User::factory()->create([
|
|
'state' => UserState::PENDING,
|
|
]);
|
|
$this->withHeader('Authorization', $user->api_key)->get($uri)->assertStatus(401);
|
|
|
|
$user = User::factory()->create([
|
|
'state' => UserState::REJECTED,
|
|
]);
|
|
$this->withHeader('Authorization', $user->api_key)->get($uri)->assertStatus(401);
|
|
|
|
$user = User::factory()->create([
|
|
'state' => UserState::DELETED,
|
|
]);
|
|
$this->withHeader('Authorization', $user->api_key)->get($uri)->assertStatus(401);
|
|
|
|
$user = User::factory()->create([
|
|
'state' => UserState::SUSPENDED,
|
|
]);
|
|
$this->withHeader('Authorization', $user->api_key)->get($uri)->assertStatus(401);
|
|
});
|
|
|
|
it('can retrieve news', function (): void {
|
|
$news = News::factory()->create();
|
|
$response = $this->get('/api/news');
|
|
|
|
$expected = NewsResource::collection([$news])->resolve();
|
|
|
|
$response->assertSuccessful();
|
|
|
|
expect($response)->assertJsonCount(1, 'data')
|
|
->and($response->json('data'))->toEqual($expected);
|
|
});
|
|
|
|
it('can retrieve airlines', function (): void {
|
|
// Clear out base data
|
|
Airline::truncate();
|
|
|
|
$size = random_int(5, 10);
|
|
$user = User::factory()->create([
|
|
'airline_id' => 0,
|
|
]);
|
|
|
|
apiAs($user);
|
|
|
|
$airlines = Airline::factory()->count($size)->create();
|
|
|
|
$res = $this->get('/api/airlines');
|
|
|
|
$res->assertSuccessful()
|
|
->assertJsonCount($size, 'data');
|
|
|
|
$expected = AirlineResource::collection($airlines)->resolve();
|
|
expect($res->json('data'))->toEqualCanonicalizing($expected);
|
|
|
|
$airline = $airlines->random();
|
|
$response = $this->get('/api/airlines/'.$airline->id);
|
|
|
|
$response->assertSuccessful();
|
|
|
|
$expected = AirlineResource::make($airline)->resolve();
|
|
expect($response->json('data'))->toEqual($expected);
|
|
|
|
});
|
|
|
|
test('get airlines chinese chars', function (): void {
|
|
// Clear out base data
|
|
Airline::truncate();
|
|
|
|
$user = User::factory()->create([
|
|
'airline_id' => 0,
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airlines = Airline::factory()->count(4)->sequence(
|
|
[
|
|
'icao' => 'DKH',
|
|
'name' => '吉祥航空',
|
|
],
|
|
[
|
|
'icao' => 'CSZ',
|
|
'name' => '深圳航空',
|
|
],
|
|
[
|
|
'icao' => 'CCA',
|
|
'name' => '中国国际航空',
|
|
],
|
|
[
|
|
'icao' => 'CXA',
|
|
'name' => '厦门航空',
|
|
]
|
|
)->create();
|
|
|
|
$res = $this->get('/api/airlines');
|
|
$res->assertSuccessful()
|
|
->assertJsonCount(4, 'data');
|
|
|
|
$expected = AirlineResource::collection($airlines)->resolve();
|
|
expect($res->json('data'))->toEqualCanonicalizing($expected);
|
|
});
|
|
|
|
it('should paginate results', function (): void {
|
|
$size = random_int(5, 10);
|
|
$user = User::factory()->create([
|
|
'airline_id' => 0,
|
|
]);
|
|
apiAs($user);
|
|
|
|
Subfleet::factory()->count($size)->create();
|
|
|
|
/*
|
|
* Page 0 and page 1 should return the same thing
|
|
*/
|
|
// Test pagination
|
|
$res = $this->get('/api/fleet?limit=1&page=0');
|
|
$res->assertSuccessful()
|
|
->assertJsonCount(1, 'data');
|
|
|
|
$body = $res->json('data');
|
|
$id_first = $body[0]['id'];
|
|
|
|
$res = $this->get('/api/fleet?limit=1&page=1');
|
|
$res->assertSuccessful()
|
|
->assertJsonCount(1, 'data');
|
|
|
|
$body = $res->json('data');
|
|
|
|
$id_second = $body[0]['id'];
|
|
|
|
expect($id_second)->toEqual($id_first);
|
|
|
|
/*
|
|
* Page 2 should be different from page 1
|
|
*/
|
|
$res = $this->get('/api/fleet?limit=1&page=2');
|
|
$res->assertSuccessful()
|
|
->assertJsonCount(1, 'data');
|
|
|
|
$body = $res->json('data');
|
|
|
|
$id_third = $body[0]['id'];
|
|
|
|
$this->assertNotEquals($id_first, $id_third);
|
|
});
|
|
|
|
it('preserves ?limit= in /api/fleet pagination metadata', function (): void {
|
|
$user = User::factory()->create(['airline_id' => 0]);
|
|
apiAs($user);
|
|
|
|
Subfleet::factory()->count(5)->create();
|
|
|
|
$res = $this->get('/api/fleet?limit=2');
|
|
$res->assertSuccessful();
|
|
|
|
// The codebase wraps paginators with CustomPaginatedResourceResponse,
|
|
// which moves the next-page URL onto meta.next_page. Both the page
|
|
// size AND the next-page URL must carry ?limit= forward so clients
|
|
// can follow pagination without losing page size.
|
|
expect($res->json('meta.per_page'))->toEqual(2);
|
|
|
|
$next = $res->json('meta.next_page');
|
|
expect($next)->not->toBeNull()
|
|
->and($next)->toContain('limit=2');
|
|
});
|
|
|
|
it('preserves ?limit= in /api/news pagination metadata', function (): void {
|
|
$user = User::factory()->create(['airline_id' => 0]);
|
|
apiAs($user);
|
|
|
|
News::factory()->count(5)->create();
|
|
|
|
$res = $this->get('/api/news?limit=2');
|
|
$res->assertSuccessful();
|
|
|
|
expect($res->json('meta.per_page'))->toEqual(2);
|
|
|
|
$next = $res->json('meta.next_page');
|
|
expect($next)->not->toBeNull()
|
|
->and($next)->toContain('limit=2');
|
|
});
|
|
|
|
it('returns a real paginator on /api/user/fleet', function (): void {
|
|
$user = User::factory()->create(['airline_id' => 0]);
|
|
apiAs($user);
|
|
|
|
// Without rank restriction the endpoint exposes all subfleets,
|
|
// which is the simplest setup that exercises pagination here.
|
|
updateSetting('pireps.restrict_aircraft_to_rank', false);
|
|
|
|
Subfleet::factory()->count(5)->create();
|
|
|
|
$res = $this->get('/api/user/fleet?limit=2');
|
|
$res->assertSuccessful()
|
|
->assertJsonStructure([
|
|
'data',
|
|
'meta' => ['current_page', 'per_page', 'total', 'next_page'],
|
|
]);
|
|
|
|
// The migration prior to this test caused getAllowableSubfleets() to
|
|
// unwrap the paginator via transform(); now it preserves it via
|
|
// through(), so meta.next_page must be a real URL with ?limit= intact.
|
|
expect($res->json('meta.per_page'))->toEqual(2);
|
|
|
|
$next = $res->json('meta.next_page');
|
|
expect($next)->not->toBeNull()
|
|
->and($next)->toContain('limit=2');
|
|
});
|
|
|
|
it('can retrieve an airport', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airport->refresh();
|
|
|
|
$response = $this->get('/api/airports/'.$airport->icao);
|
|
|
|
$response->assertSuccessful();
|
|
|
|
$expected = AirportResource::make($airport)->resolve();
|
|
|
|
expect($response->json('data'))->toMatchArray(Arr::except($expected, ['deleted_at']));
|
|
|
|
$this->get('/api/airports/UNK')->assertStatus(404);
|
|
});
|
|
|
|
test('airport request5 char', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
/** @var Airport $airport */
|
|
$airport = Airport::factory()->create(['icao' => '5Char']);
|
|
|
|
$response = $this->get('/api/airports/'.$airport->icao);
|
|
|
|
$response->assertStatus(200);
|
|
$response->assertJson(['data' => ['icao' => $airport->icao]]);
|
|
|
|
$this->get('/api/airports/UNK')->assertStatus(404);
|
|
});
|
|
|
|
test('get all airports', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
Airport::factory()->count(70)->create();
|
|
|
|
$response = $this->get('/api/airports/')
|
|
->assertStatus(200);
|
|
|
|
$body = $response->json();
|
|
expect($body)->toHaveKeys(['data', 'links', 'meta']);
|
|
});
|
|
|
|
test('get all airports hubs', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
Airport::factory()->count(10)->create();
|
|
Airport::factory()->create(['hub' => 1]);
|
|
|
|
$this->get('/api/airports/hubs')
|
|
->assertStatus(200)
|
|
->assertJsonCount(1, 'data');
|
|
});
|
|
|
|
test('get subfleets', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$subfleetA = Subfleet::factory()->create([
|
|
'airline_id' => $user->airline_id,
|
|
]);
|
|
|
|
$subfleetB = Subfleet::factory()->create([
|
|
'airline_id' => $user->airline_id,
|
|
]);
|
|
|
|
$subfleetA_size = random_int(2, 10);
|
|
$subfleetB_size = random_int(2, 10);
|
|
Aircraft::factory()->count($subfleetA_size)->create([
|
|
'subfleet_id' => $subfleetA->id,
|
|
]);
|
|
|
|
Aircraft::factory()->count($subfleetB_size)->create([
|
|
'subfleet_id' => $subfleetB->id,
|
|
]);
|
|
|
|
$response = $this->get('/api/fleet');
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json()['data'];
|
|
|
|
foreach ($body as $subfleet) {
|
|
$size = $subfleet['id'] === $subfleetA->id ? $subfleetA_size : $subfleetB_size;
|
|
|
|
expect($subfleet['aircraft'])->toHaveCount($size);
|
|
foreach ($subfleet['aircraft'] as $aircraft) {
|
|
expect($aircraft['ident'])->not->toBeEmpty();
|
|
}
|
|
}
|
|
});
|
|
|
|
test('get aircraft', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$fare_svc = app(FareService::class);
|
|
|
|
/** @var Subfleet $subfleet */
|
|
$subfleet = Subfleet::factory()->create([
|
|
'airline_id' => $user->airline_id,
|
|
]);
|
|
|
|
/** @var Fare $fare */
|
|
$fare = Fare::factory()->create();
|
|
|
|
$fare_svc->setForSubfleet($subfleet, $fare);
|
|
|
|
/** @var Aircraft $aircraft */
|
|
$aircraft = Aircraft::factory()->create([
|
|
'subfleet_id' => $subfleet->id,
|
|
'mtow' => 93000.0,
|
|
'zfw' => 71500.0,
|
|
]);
|
|
|
|
/**
|
|
* Just try retrieving by ID
|
|
*/
|
|
$resp = $this->get('/api/fleet/aircraft/'.$aircraft->id);
|
|
$body = $resp->json()['data'];
|
|
|
|
expect($aircraft->id)->toEqual($body['id']);
|
|
expect($aircraft->name)->toEqual($body['name']);
|
|
expect($body['ident'])->not->toBeEmpty();
|
|
|
|
// $this->assertEquals($body['mtow'], $aircraft->mtow->local(0));
|
|
// $this->assertEquals($body['zfw'], $aircraft->zfw->local(0));
|
|
$resp = $this->get('/api/fleet/aircraft/'.$aircraft->id.'?registration='.$aircraft->registration);
|
|
$body = $resp->json()['data'];
|
|
|
|
expect($aircraft->id)->toEqual($body['id']);
|
|
expect($aircraft->name)->toEqual($body['name']);
|
|
|
|
// $this->assertEquals($body['mtow'], $aircraft->mtow->local(0));
|
|
// $this->assertEquals($body['zfw'], $aircraft->zfw->local(0));
|
|
expect($body['ident'])->not->toBeEmpty();
|
|
expect($aircraft->ident)->toEqual($body['ident']);
|
|
|
|
$resp = $this->get('/api/fleet/aircraft/'.$aircraft->id.'?icao='.$aircraft->icao);
|
|
$body = $resp->json()['data'];
|
|
|
|
expect($aircraft->id)->toEqual($body['id']);
|
|
expect($aircraft->name)->toEqual($body['name']);
|
|
|
|
// $this->assertEquals($body['mtow'], $aircraft->mtow->local(0));
|
|
// $this->assertEquals($body['zfw'], $aircraft->zfw->local(0));
|
|
});
|
|
|
|
test('get user', function (): void {
|
|
$user = User::factory()->create([
|
|
'avatar' => '/assets/avatar.jpg',
|
|
]);
|
|
|
|
apiAs($user);
|
|
|
|
$res = $this->get('/api/user')->assertStatus(200);
|
|
$user = $res->json('data');
|
|
expect($user)->not->toBeNull();
|
|
$this->assertNotSame(-1, strpos((string) $user['avatar'], 'http'));
|
|
|
|
// Should go to gravatar
|
|
$user = User::factory()->create();
|
|
|
|
$res = $this->get('/api/user')->assertStatus(200);
|
|
$user = $res->json('data');
|
|
expect($user)->not->toBeNull();
|
|
$this->assertNotSame(-1, strpos((string) $user['avatar'], 'gravatar'));
|
|
});
|
|
|
|
test('web cron', function (): void {
|
|
updateSetting('cron.random_id', '');
|
|
|
|
$this->get('/api/cron/sdf')->assertStatus(400);
|
|
|
|
$id = Utils::generateNewId(24);
|
|
updateSetting('cron.random_id', $id);
|
|
|
|
$this->get('/api/cron/sdf')->assertStatus(400);
|
|
|
|
$res = $this->get('/api/cron/'.$id);
|
|
$res->assertStatus(200);
|
|
});
|
|
|
|
test('status', function (): void {
|
|
$res = $this->get('/api/status');
|
|
$status = $res->json();
|
|
|
|
expect($status['version'])->not->toBeEmpty();
|
|
expect($status['php'])->not->toBeEmpty();
|
|
});
|