* wip * refactor: update enum handling and improve type hints across models * refactor: deprecate labels and select methods in HasSelect trait for better separation of concerns * copilot suggestions
1001 lines
30 KiB
PHP
1001 lines
30 KiB
PHP
<?php
|
|
|
|
use App\Enums\PirepState;
|
|
use App\Enums\PirepStatus;
|
|
use App\Exceptions\AircraftNotAtAirport;
|
|
use App\Exceptions\UserNotAtAirport;
|
|
use App\Models\Acars;
|
|
use App\Models\Aircraft;
|
|
use App\Models\Airline;
|
|
use App\Models\Airport;
|
|
use App\Models\Fare;
|
|
use App\Models\Navdata;
|
|
use App\Models\PirepFare;
|
|
use App\Models\PirepFieldValue;
|
|
use App\Models\Rank;
|
|
use App\Models\Subfleet;
|
|
use App\Models\User;
|
|
use App\Services\FareService;
|
|
use App\Support\Utils;
|
|
|
|
function allPointsInRoute(array $route, array $points, array $addtl_fields = []): void
|
|
{
|
|
if ($addtl_fields === []) {
|
|
$addtl_fields = [];
|
|
}
|
|
|
|
$fields = array_merge(
|
|
[
|
|
'name',
|
|
'order',
|
|
'lat',
|
|
'lon',
|
|
],
|
|
$addtl_fields
|
|
);
|
|
|
|
expect($points)->toHaveCount(count($route));
|
|
foreach ($route as $idx => $point) {
|
|
expect($points[$idx])->toHaveKeys($fields);
|
|
foreach ($fields as $f) {
|
|
if ($f === 'lat') {
|
|
continue;
|
|
}
|
|
|
|
if ($f === 'lon') {
|
|
continue;
|
|
}
|
|
|
|
expect($points[$idx][$f])->toEqual($point[$f]);
|
|
}
|
|
}
|
|
}
|
|
|
|
function getPirepFromApi(string $pirep_id): array
|
|
{
|
|
$resp = test()->get('/api/pireps/'.$pirep_id);
|
|
$resp->assertStatus(200);
|
|
|
|
return $resp->json()['data'];
|
|
}
|
|
|
|
it('should return a prefile error', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
$aircraft = Aircraft::factory()->create();
|
|
|
|
/*
|
|
* Invalid airline id field
|
|
*/
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'_airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(400);
|
|
});
|
|
|
|
it('should not start pirep if the aircraft is not at the departure airport', function (): void {
|
|
updateSetting('pilots.only_flights_from_current', false);
|
|
updateSetting('pireps.restrict_aircraft_to_rank', false);
|
|
updateSetting('pireps.only_aircraft_at_dpt_airport', true);
|
|
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
|
|
$aircraft_airport = Airport::factory()->create();
|
|
|
|
$airline = Airline::factory()->create();
|
|
|
|
$aircraft = Aircraft::factory()->create(['airport_id' => $aircraft_airport->id]);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'Tests',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(400);
|
|
expect($response->json('title'))->toEqual('The aircraft is not at the departure airport')
|
|
->and($response->json('error.message'))->toEqual(AircraftNotAtAirport::MESSAGE);
|
|
});
|
|
|
|
it('should not start pirep without airports', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$airline = Airline::factory()->create();
|
|
$aircraft = Aircraft::factory()->create();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => null,
|
|
'arr_airport_id' => null,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'source_name' => 'ACARSTESTS',
|
|
'route' => 'POINTA POINTB',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(400);
|
|
|
|
expect($response->json('details'))->toEqual('A departure airport is required, An arrival airport is required');
|
|
});
|
|
|
|
it('should not start pirep if the pilot is not at the departure airport', function (): void {
|
|
updateSetting('pilots.only_flights_from_current', true);
|
|
updateSetting('pireps.restrict_aircraft_to_rank', false);
|
|
|
|
$user = User::factory()->create([
|
|
'curr_airport_id' => 'KJFK',
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
$aircraft = Aircraft::factory()->create();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'phpunit',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(400);
|
|
|
|
$body = $response->json();
|
|
expect($body['error']['message'])->toEqual(UserNotAtAirport::MESSAGE);
|
|
});
|
|
|
|
it('can prefile and update a pirep', function (): void {
|
|
$subfleet = Subfleet::factory()->hasAircraft(2)->create();
|
|
$rank = Rank::factory()->hasAttached($subfleet)->create();
|
|
$fare = Fare::factory()->create();
|
|
|
|
$user = User::factory()->create(
|
|
[
|
|
'rank_id' => $rank->id,
|
|
]
|
|
);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
$aircraft = $subfleet['aircraft']->random();
|
|
|
|
app(FareService::class)->setForSubfleet($subfleet, $fare);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_distance' => 400,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'UnitTest',
|
|
'fields' => [
|
|
'custom_field' => 'custom_value',
|
|
],
|
|
'fares' => [
|
|
[
|
|
'id' => $fare->id,
|
|
'count' => $fare->capacity,
|
|
],
|
|
],
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$pirep = $response->json('data');
|
|
|
|
expect($pirep['planned_distance']['nmi'])->toEqual(400)
|
|
->and($pirep['planned_distance']['mi'])->toEqual(460.31)
|
|
->and($pirep['planned_distance']['km'])->toEqual(740.8)
|
|
->and($pirep['planned_distance']['m'])->toEqual(740800)
|
|
->and(str_ends_with((string) $pirep['submitted_at'], 'Z'))->toBeTrue();
|
|
|
|
// Are date times in UTC?
|
|
|
|
// See that the fields and fares were set
|
|
$fares = PirepFare::where('pirep_id', $pirep['id'])->get();
|
|
expect($fares)->toHaveCount(1);
|
|
$saved_fare = $fares->first();
|
|
|
|
// $this->assertEquals($fare->id, $saved_fare['fare_id']);
|
|
expect($saved_fare['count'])->toEqual($fare->capacity)
|
|
->and($saved_fare['cost'])->toEqual($fare->cost)
|
|
->and($saved_fare['price'])->toEqual($fare->price);
|
|
|
|
// Check saved fields
|
|
$saved_fields = PirepFieldValue::where('pirep_id', $pirep['id'])->get();
|
|
expect($saved_fields)->toHaveCount(1);
|
|
$field = $saved_fields->first();
|
|
|
|
expect($field['name'])->toEqual('custom_field')
|
|
->and($field['value'])->toEqual('custom_value');
|
|
|
|
/**
|
|
* Try to update fields
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep['id'].'/update';
|
|
$update = [
|
|
'fares' => [
|
|
[
|
|
'id' => $fare->id,
|
|
'count' => $fare->capacity,
|
|
],
|
|
],
|
|
];
|
|
|
|
$response = $this->post($uri, $update);
|
|
$response->assertOk();
|
|
|
|
// Make sure there are no duplicates
|
|
$fares = PirepFare::where('pirep_id', $pirep['id'])->get();
|
|
expect($fares)->toHaveCount(1);
|
|
$saved_fare = $fares->first();
|
|
|
|
// $this->assertEquals($fare->id, $saved_fare['fare_id']);
|
|
expect($saved_fare['count'])->toEqual($fare->capacity);
|
|
|
|
/*
|
|
* Try cancelling the PIREP now
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep['id'].'/cancel';
|
|
$response = $this->put($uri, []);
|
|
$response->assertOk();
|
|
|
|
// Read it
|
|
$uri = '/api/pireps/'.$pirep['id'];
|
|
$response = $this->get($uri);
|
|
$response->assertOk();
|
|
|
|
$body = $response->json('data');
|
|
|
|
expect(PirepState::CANCELLED->value)->toEqual($body['state']);
|
|
});
|
|
|
|
it('should validate updates', function (): void {
|
|
$subfleet = Subfleet::factory()->hasAircraft(2)->create();
|
|
$rank = Rank::factory()->hasAttached($subfleet)->create();
|
|
|
|
$user = User::factory()->create([
|
|
'rank_id' => $rank->id,
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
$aircraft = $subfleet->aircraft->random();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_distance' => 400,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'UnitTest',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$pirep = $response->json('data');
|
|
|
|
/**
|
|
* Try to update fields
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep['id'].'/update';
|
|
$update = [
|
|
'dpt_airport_id' => '',
|
|
];
|
|
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(400);
|
|
|
|
$detail = $response->json('details');
|
|
|
|
expect($detail)->toEqual('A departure airport is required');
|
|
});
|
|
|
|
it('can receive acars updates', function (): void {
|
|
$subfleet = Subfleet::factory()->hasAircraft(2)->create();
|
|
$rank = Rank::factory()->hasAttached($subfleet)->create();
|
|
|
|
$user = User::factory()->create([
|
|
'rank_id' => $rank->id,
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
|
|
$airline = Airline::factory()->create();
|
|
|
|
$aircraft = $subfleet->aircraft->random();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep_create = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_distance' => 400,
|
|
'planned_flight_time' => 120,
|
|
'status' => PirepStatus::BOARDING->value,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'AcarsTest::testAcarsUpdates',
|
|
'fields' => [
|
|
'custom_field' => 'custom_value',
|
|
],
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep_create);
|
|
$response->assertStatus(200);
|
|
|
|
// Get the PIREP ID
|
|
$body = $response->json();
|
|
$pirep_id = $body['data']['id'];
|
|
|
|
expect($body['data'])->toHaveKeys(['airline', 'arr_airport', 'dpt_airport'])
|
|
->and($pirep_id)->not->toBeNull()
|
|
->and($user->id)->toEqual($body['data']['user_id']);
|
|
|
|
// Check the PIREP state and status
|
|
$pirep = getPirepFromApi($pirep_id);
|
|
expect(PirepState::from($pirep['state']))->toEqual(PirepState::IN_PROGRESS)
|
|
->and(PirepStatus::from($pirep['status']))->toEqual(PirepStatus::INITIATED)
|
|
->and($pirep)->toHaveKey('fields')
|
|
->and($pirep['fields']['custom_field'])->toEqual('custom_value')
|
|
->and($pirep['planned_distance']['nmi'])->toEqual($pirep_create['planned_distance'])
|
|
->and($pirep['planned_distance'])->toHaveKeys(['mi', 'nmi', 'km']);
|
|
|
|
/*
|
|
* Check the fields
|
|
*/
|
|
|
|
/**
|
|
* Update the custom field
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep_id.'/update';
|
|
$this->post($uri, [
|
|
'flight_time' => 60,
|
|
'distance' => 20,
|
|
'status' => PirepStatus::AIRBORNE->value,
|
|
'fields' => [
|
|
'custom_field' => 'custom_value_changed',
|
|
],
|
|
]);
|
|
|
|
$pirep = getPirepFromApi($pirep_id);
|
|
expect($pirep['fields']['custom_field'])->toEqual('custom_value_changed');
|
|
|
|
/**
|
|
* Add some position updates
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
|
|
|
|
// Test missing positions field
|
|
// Post an ACARS update
|
|
$update = [];
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(400);
|
|
|
|
// Post an ACARS update
|
|
$acars = Acars::factory()->make(['pirep_id' => $pirep_id])->toArray();
|
|
$acars = transformData($acars);
|
|
|
|
$update = ['positions' => [$acars]];
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(200)->assertJson(['count' => 1]);
|
|
|
|
// Read that if the ACARS record posted
|
|
$response = $this->get($uri);
|
|
$acars_data = $response->json('data')[0];
|
|
expect(round($acars_data['lat'], 2))->toEqual(round($acars['lat'], 2))
|
|
->and(round($acars_data['lon'], 2))->toEqual(round($acars['lon'], 2))
|
|
->and($acars_data['log'])->toEqual($acars['log']);
|
|
|
|
// Make sure PIREP state moved into ENROUTE
|
|
$pirep = getPirepFromApi($pirep_id);
|
|
expect(PirepState::from($pirep['state']))->toEqual(PirepState::IN_PROGRESS)
|
|
->and(PirepStatus::from($pirep['status']))->toEqual(PirepStatus::AIRBORNE);
|
|
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json()['data'];
|
|
|
|
expect($body)->not->toBeNull()
|
|
->and($body)->toHaveCount(1)
|
|
->and(round($body[0]['lat'], 2))->toEqual(round($acars['lat'], 2))
|
|
->and(round($body[0]['lon'], 2))->toEqual(round($acars['lon'], 2));
|
|
|
|
// Update fields standalone
|
|
$uri = '/api/pireps/'.$pirep_id.'/fields';
|
|
$response = $this->post($uri, [
|
|
'fields' => [
|
|
'Departure Gate' => 'G26',
|
|
],
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json('data');
|
|
expect($body['Departure Gate'])->toEqual('G26');
|
|
|
|
/*
|
|
* Get the live flights and make sure all the fields we want are there
|
|
*/
|
|
$uri = '/api/acars';
|
|
$response = $this->get($uri);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$body = collect($response->json('data'));
|
|
$body = $body->firstWhere('id', $pirep['id']);
|
|
|
|
expect($body['user']['name'])->not->toBeEmpty()
|
|
->and($body['user']['avatar'])->not->toBeEmpty();
|
|
|
|
/*
|
|
* File the PIREP
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep_id.'/file';
|
|
$response = $this->post($uri, []);
|
|
$response->assertStatus(400);
|
|
|
|
// missing field
|
|
$response = $this->post($uri, ['flight_time' => '1:30']);
|
|
$response->assertStatus(400);
|
|
|
|
// invalid flight time
|
|
$response = $this->post($uri, [
|
|
'flight_time' => 130,
|
|
'fuel_used' => 8000.19,
|
|
'distance' => 400,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json();
|
|
|
|
// Add a comment
|
|
$uri = '/api/pireps/'.$pirep_id.'/comments';
|
|
$response = $this->post($uri, ['comment' => 'A comment']);
|
|
$response->assertStatus(201);
|
|
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(200);
|
|
|
|
$comments = $response->json();
|
|
|
|
expect($comments)->toHaveCount(1);
|
|
});
|
|
|
|
test('multiple altitudes', function (): void {
|
|
$subfleet = Subfleet::factory()->hasAircraft(2)->create();
|
|
$rank = Rank::factory()->hasAttached($subfleet)->create();
|
|
|
|
$user = User::factory()->create([
|
|
'rank_id' => $rank->id,
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
|
|
$airline = Airline::factory()->create();
|
|
|
|
$aircraft = $subfleet->aircraft->random();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep_create = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_distance' => 400,
|
|
'planned_flight_time' => 120,
|
|
'status' => PirepStatus::BOARDING->value,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'AcarsTest::testAcarsUpdates',
|
|
'fields' => [
|
|
'custom_field' => 'custom_value',
|
|
],
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep_create);
|
|
$response->assertStatus(200);
|
|
|
|
// Get the PIREP ID
|
|
$body = $response->json();
|
|
$pirep_id = $body['data']['id'];
|
|
|
|
$dt = new DateTime('now');
|
|
|
|
// Post an ACARS update
|
|
$acars = Acars::factory()->make(['pirep_id' => $pirep_id])->toArray();
|
|
$acars['sim_time'] = $dt->format(DateTime::ATOM);
|
|
unset($acars['altitude_agl']);
|
|
unset($acars['altitude_msl']);
|
|
$acars['altitude'] = 1000;
|
|
|
|
$acars = transformData($acars);
|
|
|
|
// $acars = $this->transformData($acars);
|
|
$inst = new Acars($acars);
|
|
expect($inst->altitude_agl)->toEqual($acars['altitude'])
|
|
->and($inst->altitude_msl)->toEqual($acars['altitude']);
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
|
|
|
|
$response = $this->post($uri, ['positions' => [$acars]]);
|
|
$response->assertStatus(200)->assertJson(['count' => 1]);
|
|
|
|
// Read that if the ACARS record posted
|
|
$response = $this->get($uri);
|
|
$acars_data = $response->json('data')[0];
|
|
expect($acars_data['altitude_agl'])->toEqual($acars['altitude'])
|
|
->and($acars_data['altitude_msl'])->toEqual($acars['altitude']);
|
|
|
|
/**
|
|
* Now push the new fields without the old one
|
|
*/
|
|
$acars2 = Acars::factory()->make(['pirep_id' => $pirep_id])->toArray();
|
|
$acars2['sim_time'] = $dt
|
|
->add(DateInterval::createFromDateString('30 seconds'))
|
|
->format(DateTimeInterface::ATOM);
|
|
|
|
$acars2 = transformData($acars2);
|
|
// send it in
|
|
$response = $this->post($uri, ['positions' => [$acars2]]);
|
|
$response->assertStatus(200)->assertJson(['count' => 1]);
|
|
|
|
// Read that if the ACARS record posted
|
|
$response = $this->get($uri);
|
|
$acars_data = $response->json('data')[1];
|
|
expect($acars_data['altitude_agl'])->toEqualWithDelta($acars2['altitude_agl'], 0.1)
|
|
->and($acars_data['altitude_msl'])->toEqualWithDelta($acars2['altitude_msl'], 0.1);
|
|
});
|
|
|
|
test('acars data instantitaion', function (): void {
|
|
$acars = Acars::factory()->make(['pirep_id' => 'abc'])->toArray();
|
|
$acars['altitude'] = 5000;
|
|
|
|
$acars = transformData($acars);
|
|
|
|
// Set this to the model first
|
|
$inst = new Acars($acars);
|
|
expect($inst->altitude_agl)->toEqual($acars['altitude_agl'])
|
|
->and($inst->altitude_msl)->toEqual($acars['altitude_msl']);
|
|
|
|
// Now delete the agl/msl and recreate the instance
|
|
unset($acars['altitude_agl']);
|
|
unset($acars['altitude_msl']);
|
|
|
|
$inst = new Acars($acars);
|
|
expect($inst->altitude_agl)->toEqual($acars['altitude'])
|
|
->and($inst->altitude_msl)->toEqual($acars['altitude']);
|
|
});
|
|
|
|
it('can file a pirep via api', function (): void {
|
|
$subfleet = Subfleet::factory()->hasAircraft(2)->create();
|
|
$rank = Rank::factory()->hasAttached($subfleet)->create();
|
|
|
|
$user = User::factory()->create([
|
|
'rank_id' => $rank->id,
|
|
]);
|
|
apiAs($user);
|
|
|
|
$airport = Airport::factory()->create();
|
|
|
|
$airline = Airline::factory()->create();
|
|
|
|
$aircraft = $subfleet->aircraft->random();
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $aircraft->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'source_name' => 'AcarsTest::testFilePirepApi',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
// Get the PIREP ID
|
|
$body = $response->json();
|
|
$pirep_id = $body['data']['id'];
|
|
|
|
// File the PIREP now
|
|
$uri = '/api/pireps/'.$pirep_id.'/file';
|
|
|
|
$response = $this->post($uri, [
|
|
'flight_time' => 130,
|
|
'fuel_used' => 8000.19,
|
|
'distance' => 400,
|
|
]);
|
|
|
|
$response->assertStatus(200);
|
|
|
|
// Check the block_off_time and block_on_time being set
|
|
$body = $this->get('/api/pireps/'.$pirep_id)->json('data');
|
|
expect(PirepState::from($body['state']))->toEqual(PirepState::PENDING)
|
|
->and($body['block_off_time'])->not->toBeNull()
|
|
->and($body['block_on_time'])->not->toBeNull();
|
|
|
|
// Try to refile, should be blocked
|
|
$response = $this->post($uri, [
|
|
'flight_time' => 130,
|
|
'fuel_used' => 8000.19,
|
|
'distance' => 400,
|
|
]);
|
|
|
|
$response->assertStatus(400);
|
|
});
|
|
|
|
it('should check if the aircraft is allowed for flight', function (): void {
|
|
updateSetting('pireps.restrict_aircraft_to_rank', true);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
|
|
// Add subfleets and aircraft, but also add another set of subfleets
|
|
$subfleetA = Subfleet::factory()->hasAircraft(1)->create();
|
|
|
|
// User not allowed aircraft from this subfleet
|
|
$subfleetB = Subfleet::factory()->hasAircraft(1)->create();
|
|
|
|
$rank = Rank::factory()->hasAttached($subfleetA)->create();
|
|
|
|
$user = User::factory()->create(
|
|
[
|
|
'rank_id' => $rank->id,
|
|
]
|
|
);
|
|
apiAs($user);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $subfleetB->aircraft->random()->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'Unit test',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(400);
|
|
|
|
// Try refiling with a valid aircraft
|
|
$pirep['aircraft_id'] = $subfleetA->aircraft->random()->id;
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
});
|
|
|
|
it('should ignore aircraft allowed', function (): void {
|
|
updateSetting('pireps.restrict_aircraft_to_rank', false);
|
|
|
|
$airport = Airport::factory()->create();
|
|
$airline = Airline::factory()->create();
|
|
|
|
// Add subfleets and aircraft, but also add another set of subfleets
|
|
$subfleetA = Subfleet::factory()->hasAircraft(1)->create();
|
|
|
|
// User not allowed aircraft from this subfleet
|
|
$subfleetB = Subfleet::factory()->hasAircraft(1)->create();
|
|
|
|
$rank = Rank::factory()->hasAttached($subfleetA)->create();
|
|
|
|
$user = User::factory()->create(
|
|
[
|
|
'rank_id' => $rank->id,
|
|
]
|
|
);
|
|
apiAs($user);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$pirep = [
|
|
'airline_id' => $airline->id,
|
|
'aircraft_id' => $subfleetB->aircraft->random()->id,
|
|
'dpt_airport_id' => $airport->icao,
|
|
'arr_airport_id' => $airport->icao,
|
|
'flight_number' => '6000',
|
|
'level' => 38000,
|
|
'planned_flight_time' => 120,
|
|
'route' => 'POINTA POINTB',
|
|
'source_name' => 'Unit test',
|
|
];
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
});
|
|
|
|
it('can receive multiple acars position updates', function (): void {
|
|
$pirep = createPirep();
|
|
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
|
|
|
|
// Post an ACARS update
|
|
$acars_count = random_int(5, 10);
|
|
$acars = Acars::factory()->count($acars_count)->make(['id' => ''])
|
|
->map(function (Acars $point): Acars {
|
|
$point->id = Utils::generateNewId();
|
|
|
|
return $point;
|
|
})
|
|
->toArray();
|
|
|
|
$acars = transformData($acars);
|
|
|
|
$update = ['positions' => $acars];
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(200)->assertJson(['count' => $acars_count]);
|
|
|
|
// Try posting again, should be ignored/not throw any sql errors
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(200)->assertJson(['count' => $acars_count]);
|
|
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(200)->assertJsonCount($acars_count, 'data');
|
|
});
|
|
|
|
it('should return a 404 on a non existent pirep get', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$uri = '/api/pireps/DOESNTEXIST/acars';
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
it('should return a 404 on a non existent pirep store', function (): void {
|
|
$user = User::factory()->create();
|
|
apiAs($user);
|
|
|
|
$uri = '/api/pireps/DOESNTEXIST/acars/position';
|
|
$acars = Acars::factory()->make()->toArray();
|
|
$response = $this->post($uri, $acars);
|
|
$response->assertStatus(404);
|
|
});
|
|
|
|
it('should use acars iso date', function (): void {
|
|
$pirep = createPirep();
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
$dt = date('c');
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/position';
|
|
$acars = Acars::factory()->make([
|
|
'sim_time' => $dt,
|
|
])->toArray();
|
|
|
|
$acars = transformData($acars);
|
|
|
|
$update = ['positions' => [$acars]];
|
|
$response = $this->post($uri, $update);
|
|
$response->assertStatus(200);
|
|
});
|
|
|
|
it('refuses invalid route post', function (): void {
|
|
$pirep = createPirep();
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$response = $this->post($uri, $pirep);
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
// Missing lat/lon
|
|
$post_route = ['order' => 1, 'name' => 'NAVPOINT'];
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->post($uri, $post_route);
|
|
$response->assertStatus(400);
|
|
|
|
$post_route = [
|
|
[
|
|
'id' => 'NAVPOINT',
|
|
'order' => 1,
|
|
'name' => 'NAVPOINT',
|
|
'lat' => 'notanumber',
|
|
'lon' => 34.11,
|
|
],
|
|
];
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->post($uri, $post_route);
|
|
$response->assertStatus(400);
|
|
});
|
|
|
|
it('can receive acars log', function (): void {
|
|
$pirep = createPirep();
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$response = $this->post($uri, $pirep);
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
$acars = Acars::factory()->make();
|
|
$post_log = [
|
|
'logs' => [
|
|
['log' => $acars->log],
|
|
],
|
|
];
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/logs';
|
|
$response = $this->post($uri, $post_log);
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json();
|
|
|
|
expect($body['count'])->toEqual(1);
|
|
|
|
$acars = Acars::factory()->make();
|
|
$post_log = [
|
|
'events' => [
|
|
['event' => $acars->log],
|
|
],
|
|
];
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/acars/events';
|
|
$response = $this->post($uri, $post_log);
|
|
$response->assertStatus(200);
|
|
|
|
$body = $response->json();
|
|
|
|
expect($body['count'])->toEqual(1);
|
|
});
|
|
|
|
it('can receive acars route', function (): void {
|
|
$pirep = createPirep();
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$response = $this->post($uri, $pirep);
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
$order = 1;
|
|
$post_route = [];
|
|
$route_count = random_int(2, 10);
|
|
|
|
$route = Navdata::factory()->count($route_count)->create();
|
|
foreach ($route as $position) {
|
|
$post_route[] = [
|
|
'order' => $order,
|
|
'id' => $position->id,
|
|
'name' => $position->id,
|
|
'lat' => $position->lat,
|
|
'lon' => $position->lon,
|
|
];
|
|
|
|
$order++;
|
|
}
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->post($uri, ['route' => $post_route]);
|
|
$response->assertStatus(200)->assertJson(['count' => $route_count]);
|
|
|
|
// Try double post to ignore SQL update
|
|
$response = $this->post($uri, ['route' => $post_route]);
|
|
$response->assertStatus(200)->assertJson(['count' => $route_count]);
|
|
|
|
/**
|
|
* Get
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(200)->assertJsonCount($route_count, 'data');
|
|
|
|
$body = $response->json()['data'];
|
|
allPointsInRoute($post_route, $body);
|
|
|
|
/**
|
|
* Delete and then recheck
|
|
*/
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->delete($uri);
|
|
$response->assertStatus(200);
|
|
|
|
$uri = '/api/pireps/'.$pirep_id.'/route';
|
|
$response = $this->get($uri);
|
|
$response->assertStatus(200)->assertJsonCount(0, 'data');
|
|
});
|
|
|
|
it('handles duplicate pirep', function (): void {
|
|
$pirep = createPirep();
|
|
apiAs($pirep->user);
|
|
$pirep = $pirep->toArray();
|
|
$pirep = transformData($pirep);
|
|
|
|
$uri = '/api/pireps/prefile';
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$pirep_id = $response->json()['data']['id'];
|
|
|
|
// try readding
|
|
$response = $this->post($uri, $pirep);
|
|
$response->assertStatus(200);
|
|
|
|
$dupe_pirep_id = $response->json()['data']['id'];
|
|
|
|
expect($dupe_pirep_id)->toEqual($pirep_id);
|
|
});
|