phpvms/tests/ImporterTest.php

714 lines
24 KiB
PHP
Raw Normal View History

<?php
namespace Tests;
use App\Contracts\ImportExport;
use App\Models\Aircraft;
use App\Models\Airline;
use App\Models\Airport;
7.0.0-beta3 Release (#541) * 391 Notification refactorings (#441) * Refactor notifications to allow easier plugins * Notification refactoring * Formatting * Move news to NewsService; cleanup of events * More refactoring; added send email out for news item and the template * Formatting * Formatting * Fix missing newsRepo (#445) * Refactor and add importer to Installer module #443 (#444) * Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting * Replace importer with AJAX powered; better error handling #443 (#447) * Replace importer with AJAX powered; better error handling #443 * Formatting * Fix command line importer * Remove bootstrap cache (#448) * Cleanup the bootstrap/cache directory when packaging * Fix removal of bootstrap cache * Formatting * Stricter checks on ACARS API data (#451) * Stricter checks on ACARS API data * More checks * Fix for flight_number check forcing to exist * Allow nullable on flight_id * Avoid proc_open use #455 (#456) * Use PhpExecutableFinder() closes #457 #458 (#460) * Use DateTimeZone instead of int for creating datetime closes #461 * Fix CSV imports giving Storage class not found #454 (#462) * Fix CSV imports giving Storage class not found #454 * Update yarn files for security alert * Add PHP 7.4 support (#464) * Add PHP 7.4 to build matrix * DB fix * YAML parser fix in test data * Show versions * Package updates * Track used ICAOs * 7.4 METAR parsing fix * METAR parser fix * Formatting * Add meters to response units * Call instance for unit conversion * Return value * Catch exception for unknown quantity * Comment fix * Formatting * METAR parsing fixes on PHP 7.4 * Package updates * More random airport ID * More random airport ID * Properly disable toolbar * Semver written out to version file * Use dev as default identifier * Fix BindingResolutionError when debug toolbar isn't present (#465) * Fix BindingResolutionError when debug toolbar isn't present * Formatting * Split the importer module out from the installer module (#468) * Split the importer module out from the installer module * Cleanup of unused imports * Move updater into separate module #453 * Remove unused imports/formatting * Disable the install and importer modules at the end of the setup * Unused imports; update IJ style * test explicit stage for php+mysql * add more to matrix * Add different MariaDB versions * undo * Cleanup Model doc * Pilots cannot use the dashboard or flights without admin rights (#481) * Use auth middleware instead of specific groups for logged in state * Auth check for admin access * Check user admin access for updates * Formatting * Allow nullable field and calculate distance if nulled for flight import #478 (#482) * Check for no roles being attached #480 (#483) * Return the flight fares if there are no subfleet fares #488 (#489) * Return the flight fares if there are no subfleet fares #488 * Formatting * Formatting * Account for units when entering fuel amounts #493 * Search for ICAO not working properly (#496) * /flights and /flights/search direct to the same endpoint * Properly set the distance/planned_distance on save (#497) * 491 Installation Error (#495) * Disable CSRF token * Add error handling around looking up the theme and set a default * Note about logs in issue template * Formatting * Fix GeoService errors when viewing PIREP #498 (#499) * Add new command to export a specific PIREP for debugging (#501) * Set a default model value for airports on PIREP (#500) * Set a default model value for airports on PIREP * Fix airport icao reference * Default airport models * Catch broader exception writing out config files #491 * style * Add reference to docs on doc site (#502) * Properly create/update rows importing #486 (#503) * Add base Dockerfile for Dockerhub builds (#504) * New subfleet not being attached to an airline on import #479 (#505) * Fix subfleet not being attached to an airline on creation in import #479 * Call airline name with optional() around subfleet * Minor cleanup * Search flights by subfleet #484 (#506) * API level search of flights #484 * Add Subfleet to flights page for search * Make the fuel used optional (#512) * Add make to Docker container * Add getRootDomain() to Utils (#514) * Show admin dropdown for admin-access ability (#515) * Show admin dropdown for admin-access ability closes #509 * Formatting * Check user permissions on the routes #508 (#516) * Check user permissions on the routes #508 * Formatting * Return default value on exception for setting() * Correct text for no subfleets #507 (#518) * Add a public_url() helper #513 (#519) * Reduce number of queries for update check (#520) * Try to clear caches before updating (#522) * Try to clear caches before updating * Add clear-compiled to maintenance cache list * Formatting * Set PIREPs page to public (#526) Set PIREPs page to public * Fix live and route map errors #527 (#528) * Add menu bar for mobile (#529) * Format all blade templates to 2 spaces #530 (#531) * Fix PIREP edit endpoint closes #533 (#534) * Fix import during flight cron #532 (#535) * PIREPS resource except for show (#536) * Use optional() around the airport fields (#537) * Use optional() around the airport fields * Add null-coalesce around full_name * Add link to download ACARS config from profile (#539) * Add link to download ACARS config from profile * Formatting * Update xml config file template (#540)
2020-02-09 02:29:34 +08:00
use App\Models\Enums\AircraftStatus;
use App\Models\Enums\Days;
use App\Models\Enums\ExpenseType;
use App\Models\Enums\FlightType;
use App\Models\Expense;
use App\Models\Fare;
use App\Models\Flight;
use App\Models\FlightFieldValue;
use App\Models\Subfleet;
use App\Services\ExportService;
2018-08-27 00:40:04 +08:00
use App\Services\FareService;
use App\Services\ImportExport\AircraftExporter;
use App\Services\ImportExport\AirportExporter;
use App\Services\ImportExport\FlightExporter;
use App\Services\ImportService;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\ValidationException;
class ImporterTest extends TestCase
{
2018-08-27 00:40:04 +08:00
private $importBaseClass;
private $importSvc;
private $fareSvc;
2019-05-12 23:50:38 +08:00
public function setUp(): void
{
parent::setUp();
$this->importBaseClass = new ImportExport();
$this->importSvc = app(ImportService::class);
$this->fareSvc = app(FareService::class);
Storage::fake('local');
}
/**
* Add some of the basic data needed to properly import the flights.csv file
2018-08-27 00:40:04 +08:00
*
* @return mixed
*/
protected function insertFlightsScaffoldData()
{
$fare_svc = app(FareService::class);
$al = [
'icao' => 'VMS',
'name' => 'phpVMS Airlines',
];
$airline = factory(Airline::class)->create($al);
$subfleet = factory(Subfleet::class)->create(['type' => 'A32X']);
2018-08-27 00:40:04 +08:00
// Add the economy class
$fare_economy = factory(Fare::class)->create(['code' => 'Y', 'capacity' => 150]);
$fare_svc->setForSubfleet($subfleet, $fare_economy);
$fare_business = factory(Fare::class)->create(['code' => 'B', 'capacity' => 20]);
2018-03-23 06:48:57 +08:00
$fare_svc->setForSubfleet($subfleet, $fare_business);
2018-03-22 06:07:30 +08:00
2018-08-27 00:40:04 +08:00
// Add first class
$fare_first = factory(Fare::class)->create(['code' => 'F', 'capacity' => 10]);
$fare_svc->setForSubfleet($subfleet, $fare_first);
2018-03-22 06:07:30 +08:00
return [$airline, $subfleet];
}
/**
* Test the parsing of different field/column which can be used
* for specifying different field values
*/
2018-03-22 06:07:30 +08:00
public function testConvertStringtoObjects(): void
{
$tests = [
[
2018-08-27 00:40:04 +08:00
'input' => '',
'expected' => [],
],
[
2018-08-27 00:40:04 +08:00
'input' => 'gate',
'expected' => ['gate'],
],
[
2018-08-27 00:40:04 +08:00
'input' => 'gate;cost index',
'expected' => [
'gate',
'cost index',
2018-08-27 00:40:04 +08:00
],
],
[
2018-08-27 00:40:04 +08:00
'input' => 'gate=B32;cost index=100',
'expected' => [
2018-08-27 00:40:04 +08:00
'gate' => 'B32',
'cost index' => '100',
],
],
[
2018-08-27 00:40:04 +08:00
'input' => 'Y?price=200&cost=100; F?price=1200',
'expected' => [
'Y' => [
'price' => 200,
2018-08-27 00:40:04 +08:00
'cost' => 100,
],
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
],
],
[
2018-08-27 00:40:04 +08:00
'input' => 'Y?price&cost; F?price=1200',
'expected' => [
'Y' => [
'price',
'cost',
],
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
],
],
[
'input' => 'Y; F?price=1200',
'expected' => [
2018-08-27 00:40:04 +08:00
0 => 'Y',
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
],
],
2018-03-22 06:07:30 +08:00
[
'input' => 'Y?;F?price=1200',
'expected' => [
'Y' => [],
2018-03-22 06:07:30 +08:00
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
],
2018-03-22 06:07:30 +08:00
],
[
2018-08-27 00:40:04 +08:00
'input' => 'Departure Gate=4;Arrival Gate=C61',
'expected' => [
'Departure Gate' => '4',
2018-08-27 00:40:04 +08:00
'Arrival Gate' => 'C61',
],
],
];
2018-08-27 00:40:04 +08:00
foreach ($tests as $test) {
$parsed = $this->importBaseClass->parseMultiColumnValues($test['input']);
2018-03-22 06:07:30 +08:00
$this->assertEquals($test['expected'], $parsed);
}
}
2018-03-22 06:07:30 +08:00
/**
* Tests for converting the different object/array key values
* into the format that we use in CSV files
*/
public function testConvertObjectToString(): void
{
$tests = [
[
2018-08-27 00:40:04 +08:00
'input' => '',
'expected' => '',
],
2018-03-22 06:07:30 +08:00
[
2018-08-27 00:40:04 +08:00
'input' => ['gate'],
'expected' => 'gate',
2018-03-22 06:07:30 +08:00
],
[
'input' => [
'gate',
'cost index',
],
'expected' => 'gate;cost index',
],
[
'input' => [
'gate' => 'B32',
2018-08-27 00:40:04 +08:00
'cost index' => '100',
2018-03-22 06:07:30 +08:00
],
'expected' => 'gate=B32;cost index=100',
],
[
'input' => [
'Y' => [
'price' => 200,
'cost' => 100,
],
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
2018-03-22 06:07:30 +08:00
],
'expected' => 'Y?price=200&cost=100;F?price=1200',
],
[
'input' => [
'Y' => [
'price',
'cost',
],
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
2018-03-22 06:07:30 +08:00
],
'expected' => 'Y?price&cost;F?price=1200',
],
[
2018-08-27 00:40:04 +08:00
'input' => [
2018-03-22 06:07:30 +08:00
'Y' => [
'price',
'cost',
],
2018-08-27 00:40:04 +08:00
'F' => [],
2018-03-22 06:07:30 +08:00
],
'expected' => 'Y?price&cost;F',
],
[
'input' => [
0 => 'Y',
'F' => [
2018-08-27 00:40:04 +08:00
'price' => 1200,
],
2018-03-22 06:07:30 +08:00
],
'expected' => 'Y;F?price=1200',
],
[
'input' => [
'Departure Gate' => '4',
'Arrival Gate' => 'C61',
],
'expected' => 'Departure Gate=4;Arrival Gate=C61',
],
];
foreach ($tests as $test) {
$parsed = $this->importBaseClass->objectToMultiString($test['input']);
$this->assertEquals($test['expected'], $parsed);
}
}
/**
* Test exporting all the flights to a file
2018-08-27 02:51:47 +08:00
*
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
public function testAircraftExporter(): void
{
$aircraft = factory(Aircraft::class)->create();
$exporter = new AircraftExporter();
$exported = $exporter->export($aircraft);
$this->assertEquals($aircraft->iata, $exported['iata']);
$this->assertEquals($aircraft->icao, $exported['icao']);
$this->assertEquals($aircraft->name, $exported['name']);
$this->assertEquals($aircraft->zfw, $exported['zfw']);
$this->assertEquals($aircraft->subfleet->type, $exported['subfleet']);
$importer = app(ImportService::class);
$exporter = app(ExportService::class);
$file = $exporter->exportAircraft(collect([$aircraft]));
$status = $importer->importAircraft($file);
$this->assertCount(1, $status['success']);
$this->assertCount(0, $status['errors']);
}
/**
* Test exporting all the flights to a file
*/
public function testAirportExporter(): void
{
$airport_name = 'Adolfo Suárez MadridBarajas Airport';
$airport = factory(Airport::class)->create([
'name' => $airport_name,
]);
$exporter = new AirportExporter();
$exported = $exporter->export($airport);
$this->assertEquals($airport->iata, $exported['iata']);
$this->assertEquals($airport->icao, $exported['icao']);
$this->assertEquals($airport->name, $exported['name']);
$importer = app(ImportService::class);
$exporter = app(ExportService::class);
2018-03-31 10:25:54 +08:00
$file = $exporter->exportAirports(collect([$airport]));
$status = $importer->importAirports($file);
$this->assertCount(1, $status['success']);
$this->assertCount(0, $status['errors']);
}
2018-03-22 06:07:30 +08:00
/**
* Test exporting all the flights to a file
*/
public function testFlightExporter(): void
{
$fareSvc = app(FareService::class);
[$airline, $subfleet] = $this->insertFlightsScaffoldData();
$subfleet2 = factory(Subfleet::class)->create(['type' => 'B74X']);
2018-03-22 06:07:30 +08:00
$fareY = Fare::where('code', 'Y')->first();
$fareF = Fare::where('code', 'F')->first();
2018-03-22 06:07:30 +08:00
$flight = factory(Flight::class)->create([
2018-08-27 00:40:04 +08:00
'airline_id' => $airline->id,
'flight_type' => 'J',
'days' => Days::getDaysMask([
Days::TUESDAY,
Days::SUNDAY,
]),
2018-03-22 06:07:30 +08:00
]);
$flight->subfleets()->syncWithoutDetaching([$subfleet->id, $subfleet2->id]);
//
$fareSvc->setForFlight($flight, $fareY, ['capacity' => '100']);
$fareSvc->setForFlight($flight, $fareF);
// Add some custom fields
FlightFieldValue::create([
2018-03-22 06:07:30 +08:00
'flight_id' => $flight->id,
2018-08-27 00:40:04 +08:00
'name' => 'Departure Gate',
'value' => '4',
2018-03-22 06:07:30 +08:00
]);
FlightFieldValue::create([
2018-03-22 06:07:30 +08:00
'flight_id' => $flight->id,
'name' => 'Arrival Gate',
2018-08-27 00:40:04 +08:00
'value' => 'C41',
2018-03-22 06:07:30 +08:00
]);
// Test the conversion
$exporter = new FlightExporter();
2018-03-22 06:07:30 +08:00
$exported = $exporter->export($flight);
$this->assertEquals('27', $exported['days']);
2018-03-22 06:07:30 +08:00
$this->assertEquals('VMS', $exported['airline']);
2018-03-31 09:57:30 +08:00
$this->assertEquals($flight->flight_time, $exported['flight_time']);
$this->assertEquals('J', $exported['flight_type']);
2018-03-22 06:07:30 +08:00
$this->assertEquals('A32X;B74X', $exported['subfleets']);
$this->assertEquals('Y?capacity=100;F', $exported['fares']);
$this->assertEquals('Departure Gate=4;Arrival Gate=C41', $exported['fields']);
$importer = app(ImportService::class);
$exporter = app(ExportService::class);
$file = $exporter->exportFlights(collect([$flight]));
$status = $importer->importFlights($file);
$this->assertCount(1, $status['success']);
$this->assertCount(0, $status['errors']);
2018-03-22 06:07:30 +08:00
}
2018-03-23 06:17:37 +08:00
/**
* Try importing the aicraft in the airports. Should fail
*/
public function testInvalidFileImport(): void
{
$this->expectException(ValidationException::class);
2018-03-23 06:17:37 +08:00
$file_path = base_path('tests/data/aircraft.csv');
$this->importSvc->importAirports($file_path);
}
/**
* Try importing the aicraft in the airports. Should fail because of
* empty/invalid rows
*/
public function testEmptyCols(): void
{
$file_path = base_path('tests/data/expenses_empty_rows.csv');
$status = $this->importSvc->importExpenses($file_path);
$this->assertCount(8, $status['success']);
$this->assertCount(0, $status['errors']);
}
2018-03-23 06:17:37 +08:00
/**
* Test the importing of expenses
2018-08-27 00:40:04 +08:00
*
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
2018-03-23 06:17:37 +08:00
*/
public function testExpenseImporter(): void
{
$airline = factory(Airline::class)->create(['icao' => 'VMS']);
$subfleet = factory(Subfleet::class)->create(['type' => '744-3X-RB211']);
$aircraft = factory(Aircraft::class)->create([
2018-08-27 00:40:04 +08:00
'subfleet_id' => $subfleet->id,
2018-03-23 06:17:37 +08:00
'registration' => '001Z',
]);
$file_path = base_path('tests/data/expenses.csv');
$status = $this->importSvc->importExpenses($file_path);
$this->assertCount(8, $status['success']);
$this->assertCount(0, $status['errors']);
2018-03-23 06:17:37 +08:00
$expenses = Expense::all();
2018-03-23 06:17:37 +08:00
$on_airline = $expenses->where('name', 'Per-Flight (multiplier, on airline)')->first();
$this->assertEquals(200, $on_airline->amount);
$this->assertEquals($airline->id, $on_airline->airline_id);
$pf = $expenses->where('name', 'Per-Flight (no muliplier)')->first();
$this->assertEquals(100, $pf->amount);
$this->assertEquals(ExpenseType::FLIGHT, $pf->type);
2018-03-23 06:17:37 +08:00
$catering = $expenses->where('name', 'Catering Staff')->first();
$this->assertEquals(1000, $catering->amount);
$this->assertEquals(ExpenseType::DAILY, $catering->type);
$this->assertEquals(Subfleet::class, $catering->ref_model);
2018-04-02 03:32:01 +08:00
$this->assertEquals($subfleet->id, $catering->ref_model_id);
2018-03-23 06:17:37 +08:00
$mnt = $expenses->where('name', 'Maintenance')->first();
$this->assertEquals(Aircraft::class, $mnt->ref_model);
2018-04-02 03:32:01 +08:00
$this->assertEquals($aircraft->id, $mnt->ref_model_id);
2018-03-23 06:17:37 +08:00
}
2018-03-23 06:48:57 +08:00
/**
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
2018-03-23 06:48:57 +08:00
*/
public function testFareImporter(): void
{
$file_path = base_path('tests/data/fares.csv');
$status = $this->importSvc->importFares($file_path);
$this->assertCount(3, $status['success']);
$this->assertCount(0, $status['errors']);
2018-03-23 06:48:57 +08:00
$fares = Fare::all();
2018-03-23 06:48:57 +08:00
$y_class = $fares->where('code', 'Y')->first();
$this->assertEquals('Economy', $y_class->name);
$this->assertEquals(100, $y_class->price);
$this->assertEquals(0, $y_class->cost);
$this->assertEquals(200, $y_class->capacity);
$this->assertEquals(true, $y_class->active);
$this->assertEquals('This is the economy class', $y_class->notes);
$b_class = $fares->where('code', 'B')->first();
$this->assertEquals('Business', $b_class->name);
$this->assertEquals(500, $b_class->price);
$this->assertEquals(250, $b_class->cost);
$this->assertEquals(10, $b_class->capacity);
$this->assertEquals('This is business class', $b_class->notes);
$this->assertEquals(false, $b_class->active);
$f_class = $fares->where('code', 'F')->first();
$this->assertEquals('First-Class', $f_class->name);
$this->assertEquals(800, $f_class->price);
$this->assertEquals(350, $f_class->cost);
$this->assertEquals(5, $f_class->capacity);
$this->assertEquals('', $f_class->notes);
$this->assertEquals(true, $f_class->active);
}
/**
* Test the flight importer
2018-08-27 00:40:04 +08:00
*
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
public function testFlightImporter(): void
{
2018-03-22 06:07:30 +08:00
[$airline, $subfleet] = $this->insertFlightsScaffoldData();
$file_path = base_path('tests/data/flights.csv');
$status = $this->importSvc->importFlights($file_path);
7.0.0-beta3 Release (#541) * 391 Notification refactorings (#441) * Refactor notifications to allow easier plugins * Notification refactoring * Formatting * Move news to NewsService; cleanup of events * More refactoring; added send email out for news item and the template * Formatting * Formatting * Fix missing newsRepo (#445) * Refactor and add importer to Installer module #443 (#444) * Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting * Replace importer with AJAX powered; better error handling #443 (#447) * Replace importer with AJAX powered; better error handling #443 * Formatting * Fix command line importer * Remove bootstrap cache (#448) * Cleanup the bootstrap/cache directory when packaging * Fix removal of bootstrap cache * Formatting * Stricter checks on ACARS API data (#451) * Stricter checks on ACARS API data * More checks * Fix for flight_number check forcing to exist * Allow nullable on flight_id * Avoid proc_open use #455 (#456) * Use PhpExecutableFinder() closes #457 #458 (#460) * Use DateTimeZone instead of int for creating datetime closes #461 * Fix CSV imports giving Storage class not found #454 (#462) * Fix CSV imports giving Storage class not found #454 * Update yarn files for security alert * Add PHP 7.4 support (#464) * Add PHP 7.4 to build matrix * DB fix * YAML parser fix in test data * Show versions * Package updates * Track used ICAOs * 7.4 METAR parsing fix * METAR parser fix * Formatting * Add meters to response units * Call instance for unit conversion * Return value * Catch exception for unknown quantity * Comment fix * Formatting * METAR parsing fixes on PHP 7.4 * Package updates * More random airport ID * More random airport ID * Properly disable toolbar * Semver written out to version file * Use dev as default identifier * Fix BindingResolutionError when debug toolbar isn't present (#465) * Fix BindingResolutionError when debug toolbar isn't present * Formatting * Split the importer module out from the installer module (#468) * Split the importer module out from the installer module * Cleanup of unused imports * Move updater into separate module #453 * Remove unused imports/formatting * Disable the install and importer modules at the end of the setup * Unused imports; update IJ style * test explicit stage for php+mysql * add more to matrix * Add different MariaDB versions * undo * Cleanup Model doc * Pilots cannot use the dashboard or flights without admin rights (#481) * Use auth middleware instead of specific groups for logged in state * Auth check for admin access * Check user admin access for updates * Formatting * Allow nullable field and calculate distance if nulled for flight import #478 (#482) * Check for no roles being attached #480 (#483) * Return the flight fares if there are no subfleet fares #488 (#489) * Return the flight fares if there are no subfleet fares #488 * Formatting * Formatting * Account for units when entering fuel amounts #493 * Search for ICAO not working properly (#496) * /flights and /flights/search direct to the same endpoint * Properly set the distance/planned_distance on save (#497) * 491 Installation Error (#495) * Disable CSRF token * Add error handling around looking up the theme and set a default * Note about logs in issue template * Formatting * Fix GeoService errors when viewing PIREP #498 (#499) * Add new command to export a specific PIREP for debugging (#501) * Set a default model value for airports on PIREP (#500) * Set a default model value for airports on PIREP * Fix airport icao reference * Default airport models * Catch broader exception writing out config files #491 * style * Add reference to docs on doc site (#502) * Properly create/update rows importing #486 (#503) * Add base Dockerfile for Dockerhub builds (#504) * New subfleet not being attached to an airline on import #479 (#505) * Fix subfleet not being attached to an airline on creation in import #479 * Call airline name with optional() around subfleet * Minor cleanup * Search flights by subfleet #484 (#506) * API level search of flights #484 * Add Subfleet to flights page for search * Make the fuel used optional (#512) * Add make to Docker container * Add getRootDomain() to Utils (#514) * Show admin dropdown for admin-access ability (#515) * Show admin dropdown for admin-access ability closes #509 * Formatting * Check user permissions on the routes #508 (#516) * Check user permissions on the routes #508 * Formatting * Return default value on exception for setting() * Correct text for no subfleets #507 (#518) * Add a public_url() helper #513 (#519) * Reduce number of queries for update check (#520) * Try to clear caches before updating (#522) * Try to clear caches before updating * Add clear-compiled to maintenance cache list * Formatting * Set PIREPs page to public (#526) Set PIREPs page to public * Fix live and route map errors #527 (#528) * Add menu bar for mobile (#529) * Format all blade templates to 2 spaces #530 (#531) * Fix PIREP edit endpoint closes #533 (#534) * Fix import during flight cron #532 (#535) * PIREPS resource except for show (#536) * Use optional() around the airport fields (#537) * Use optional() around the airport fields * Add null-coalesce around full_name * Add link to download ACARS config from profile (#539) * Add link to download ACARS config from profile * Formatting * Update xml config file template (#540)
2020-02-09 02:29:34 +08:00
$this->assertCount(2, $status['success']);
$this->assertCount(1, $status['errors']);
// See if it imported
2020-10-28 06:46:15 +08:00
/** @var Flight $flight */
$flight = Flight::where([
'airline_id' => $airline->id,
2018-08-27 00:40:04 +08:00
'flight_number' => '1972',
])->first();
$this->assertNotNull($flight);
// Check the flight itself
$this->assertEquals('KAUS', $flight->dpt_airport_id);
$this->assertEquals('KJFK', $flight->arr_airport_id);
$this->assertEquals('0810 CST', $flight->dpt_time);
$this->assertEquals('1235 EST', $flight->arr_time);
$this->assertEquals('350', $flight->level);
$this->assertEquals(1477, $flight->distance);
$this->assertEquals('207', $flight->flight_time);
2018-03-30 00:34:36 +08:00
$this->assertEquals(FlightType::SCHED_PAX, $flight->flight_type);
$this->assertEquals('ILEXY2 ZENZI LFK ELD J29 MEM Q29 JHW J70 STENT J70 MAGIO J70 LVZ LENDY6', $flight->route);
$this->assertEquals('Just a flight', $flight->notes);
$this->assertEquals(true, $flight->active);
2018-08-27 00:40:04 +08:00
// Test that the days were set properly
$this->assertTrue($flight->on_day(Days::MONDAY));
$this->assertTrue($flight->on_day(Days::FRIDAY));
$this->assertFalse($flight->on_day(Days::TUESDAY));
// Check the custom fields entered
$fields = FlightFieldValue::where([
'flight_id' => $flight->id,
])->get();
$this->assertCount(2, $fields);
$dep_gate = $fields->where('name', 'Departure Gate')->first();
$this->assertEquals('4', $dep_gate['value']);
$dep_gate = $fields->where('name', 'Arrival Gate')->first();
$this->assertEquals('C41', $dep_gate['value']);
// Check the fare class
2020-10-28 06:46:15 +08:00
$fares = $this->fareSvc->getFareWithOverrides(null, $flight->fares);
2018-03-22 06:07:30 +08:00
$this->assertCount(3, $fares);
$first = $fares->where('code', 'Y')->first();
$this->assertEquals(300, $first->price);
$this->assertEquals(100, $first->cost);
$this->assertEquals(130, $first->capacity);
$first = $fares->where('code', 'F')->first();
$this->assertEquals(600, $first->price);
$this->assertEquals(400, $first->cost);
$this->assertEquals(10, $first->capacity);
// Check the subfleets
$subfleets = $flight->subfleets;
$this->assertCount(1, $subfleets);
}
/**
* Test the flight importer
2018-08-27 00:40:04 +08:00
*
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
public function testFlightImporterEmptyCustomFields(): void
{
[$airline, $subfleet] = $this->insertFlightsScaffoldData();
$file_path = base_path('tests/data/flights_empty_fields.csv');
$status = $this->importSvc->importFlights($file_path);
$this->assertCount(1, $status['success']);
$this->assertCount(0, $status['errors']);
// See if it imported
$flight = Flight::where([
'airline_id' => $airline->id,
2018-08-27 00:40:04 +08:00
'flight_number' => '1972',
])->first();
$this->assertNotNull($flight);
// Check the custom fields entered
$fields = FlightFieldValue::where([
'flight_id' => $flight->id,
])->get();
$this->assertCount(0, $fields);
}
/**
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
2018-03-22 06:07:30 +08:00
public function testAircraftImporter(): void
{
factory(Airline::class)->create();
// $subfleet = factory(\App\Models\Subfleet::class)->create(['type' => 'A32X']);
$file_path = base_path('tests/data/aircraft.csv');
$status = $this->importSvc->importAircraft($file_path);
$this->assertCount(1, $status['success']);
$this->assertCount(1, $status['errors']);
// See if it imported
$aircraft = Aircraft::where([
'registration' => 'N309US',
])->first();
$this->assertNotNull($aircraft);
2018-03-31 10:56:55 +08:00
$this->assertNotNull($aircraft->hex_code);
7.0.0-beta3 Release (#541) * 391 Notification refactorings (#441) * Refactor notifications to allow easier plugins * Notification refactoring * Formatting * Move news to NewsService; cleanup of events * More refactoring; added send email out for news item and the template * Formatting * Formatting * Fix missing newsRepo (#445) * Refactor and add importer to Installer module #443 (#444) * Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting * Replace importer with AJAX powered; better error handling #443 (#447) * Replace importer with AJAX powered; better error handling #443 * Formatting * Fix command line importer * Remove bootstrap cache (#448) * Cleanup the bootstrap/cache directory when packaging * Fix removal of bootstrap cache * Formatting * Stricter checks on ACARS API data (#451) * Stricter checks on ACARS API data * More checks * Fix for flight_number check forcing to exist * Allow nullable on flight_id * Avoid proc_open use #455 (#456) * Use PhpExecutableFinder() closes #457 #458 (#460) * Use DateTimeZone instead of int for creating datetime closes #461 * Fix CSV imports giving Storage class not found #454 (#462) * Fix CSV imports giving Storage class not found #454 * Update yarn files for security alert * Add PHP 7.4 support (#464) * Add PHP 7.4 to build matrix * DB fix * YAML parser fix in test data * Show versions * Package updates * Track used ICAOs * 7.4 METAR parsing fix * METAR parser fix * Formatting * Add meters to response units * Call instance for unit conversion * Return value * Catch exception for unknown quantity * Comment fix * Formatting * METAR parsing fixes on PHP 7.4 * Package updates * More random airport ID * More random airport ID * Properly disable toolbar * Semver written out to version file * Use dev as default identifier * Fix BindingResolutionError when debug toolbar isn't present (#465) * Fix BindingResolutionError when debug toolbar isn't present * Formatting * Split the importer module out from the installer module (#468) * Split the importer module out from the installer module * Cleanup of unused imports * Move updater into separate module #453 * Remove unused imports/formatting * Disable the install and importer modules at the end of the setup * Unused imports; update IJ style * test explicit stage for php+mysql * add more to matrix * Add different MariaDB versions * undo * Cleanup Model doc * Pilots cannot use the dashboard or flights without admin rights (#481) * Use auth middleware instead of specific groups for logged in state * Auth check for admin access * Check user admin access for updates * Formatting * Allow nullable field and calculate distance if nulled for flight import #478 (#482) * Check for no roles being attached #480 (#483) * Return the flight fares if there are no subfleet fares #488 (#489) * Return the flight fares if there are no subfleet fares #488 * Formatting * Formatting * Account for units when entering fuel amounts #493 * Search for ICAO not working properly (#496) * /flights and /flights/search direct to the same endpoint * Properly set the distance/planned_distance on save (#497) * 491 Installation Error (#495) * Disable CSRF token * Add error handling around looking up the theme and set a default * Note about logs in issue template * Formatting * Fix GeoService errors when viewing PIREP #498 (#499) * Add new command to export a specific PIREP for debugging (#501) * Set a default model value for airports on PIREP (#500) * Set a default model value for airports on PIREP * Fix airport icao reference * Default airport models * Catch broader exception writing out config files #491 * style * Add reference to docs on doc site (#502) * Properly create/update rows importing #486 (#503) * Add base Dockerfile for Dockerhub builds (#504) * New subfleet not being attached to an airline on import #479 (#505) * Fix subfleet not being attached to an airline on creation in import #479 * Call airline name with optional() around subfleet * Minor cleanup * Search flights by subfleet #484 (#506) * API level search of flights #484 * Add Subfleet to flights page for search * Make the fuel used optional (#512) * Add make to Docker container * Add getRootDomain() to Utils (#514) * Show admin dropdown for admin-access ability (#515) * Show admin dropdown for admin-access ability closes #509 * Formatting * Check user permissions on the routes #508 (#516) * Check user permissions on the routes #508 * Formatting * Return default value on exception for setting() * Correct text for no subfleets #507 (#518) * Add a public_url() helper #513 (#519) * Reduce number of queries for update check (#520) * Try to clear caches before updating (#522) * Try to clear caches before updating * Add clear-compiled to maintenance cache list * Formatting * Set PIREPs page to public (#526) Set PIREPs page to public * Fix live and route map errors #527 (#528) * Add menu bar for mobile (#529) * Format all blade templates to 2 spaces #530 (#531) * Fix PIREP edit endpoint closes #533 (#534) * Fix import during flight cron #532 (#535) * PIREPS resource except for show (#536) * Use optional() around the airport fields (#537) * Use optional() around the airport fields * Add null-coalesce around full_name * Add link to download ACARS config from profile (#539) * Add link to download ACARS config from profile * Formatting * Update xml config file template (#540)
2020-02-09 02:29:34 +08:00
$this->assertNotNull($aircraft->subfleet);
$this->assertNotNull($aircraft->subfleet->airline);
$this->assertEquals('A32X', $aircraft->subfleet->type);
$this->assertEquals('A320-211', $aircraft->name);
$this->assertEquals('N309US', $aircraft->registration);
$this->assertEquals(null, $aircraft->zfw);
7.0.0-beta3 Release (#541) * 391 Notification refactorings (#441) * Refactor notifications to allow easier plugins * Notification refactoring * Formatting * Move news to NewsService; cleanup of events * More refactoring; added send email out for news item and the template * Formatting * Formatting * Fix missing newsRepo (#445) * Refactor and add importer to Installer module #443 (#444) * Refactor and add importer to Installer module #443 * Refactor for finances to use in import * Import groups into roles * Formatting * Formatting * Add interface in installer for import * Notes about importing * Check for installer folder * Formatting * Fix pirep->user mapping * Unused import * Formatting * Replace importer with AJAX powered; better error handling #443 (#447) * Replace importer with AJAX powered; better error handling #443 * Formatting * Fix command line importer * Remove bootstrap cache (#448) * Cleanup the bootstrap/cache directory when packaging * Fix removal of bootstrap cache * Formatting * Stricter checks on ACARS API data (#451) * Stricter checks on ACARS API data * More checks * Fix for flight_number check forcing to exist * Allow nullable on flight_id * Avoid proc_open use #455 (#456) * Use PhpExecutableFinder() closes #457 #458 (#460) * Use DateTimeZone instead of int for creating datetime closes #461 * Fix CSV imports giving Storage class not found #454 (#462) * Fix CSV imports giving Storage class not found #454 * Update yarn files for security alert * Add PHP 7.4 support (#464) * Add PHP 7.4 to build matrix * DB fix * YAML parser fix in test data * Show versions * Package updates * Track used ICAOs * 7.4 METAR parsing fix * METAR parser fix * Formatting * Add meters to response units * Call instance for unit conversion * Return value * Catch exception for unknown quantity * Comment fix * Formatting * METAR parsing fixes on PHP 7.4 * Package updates * More random airport ID * More random airport ID * Properly disable toolbar * Semver written out to version file * Use dev as default identifier * Fix BindingResolutionError when debug toolbar isn't present (#465) * Fix BindingResolutionError when debug toolbar isn't present * Formatting * Split the importer module out from the installer module (#468) * Split the importer module out from the installer module * Cleanup of unused imports * Move updater into separate module #453 * Remove unused imports/formatting * Disable the install and importer modules at the end of the setup * Unused imports; update IJ style * test explicit stage for php+mysql * add more to matrix * Add different MariaDB versions * undo * Cleanup Model doc * Pilots cannot use the dashboard or flights without admin rights (#481) * Use auth middleware instead of specific groups for logged in state * Auth check for admin access * Check user admin access for updates * Formatting * Allow nullable field and calculate distance if nulled for flight import #478 (#482) * Check for no roles being attached #480 (#483) * Return the flight fares if there are no subfleet fares #488 (#489) * Return the flight fares if there are no subfleet fares #488 * Formatting * Formatting * Account for units when entering fuel amounts #493 * Search for ICAO not working properly (#496) * /flights and /flights/search direct to the same endpoint * Properly set the distance/planned_distance on save (#497) * 491 Installation Error (#495) * Disable CSRF token * Add error handling around looking up the theme and set a default * Note about logs in issue template * Formatting * Fix GeoService errors when viewing PIREP #498 (#499) * Add new command to export a specific PIREP for debugging (#501) * Set a default model value for airports on PIREP (#500) * Set a default model value for airports on PIREP * Fix airport icao reference * Default airport models * Catch broader exception writing out config files #491 * style * Add reference to docs on doc site (#502) * Properly create/update rows importing #486 (#503) * Add base Dockerfile for Dockerhub builds (#504) * New subfleet not being attached to an airline on import #479 (#505) * Fix subfleet not being attached to an airline on creation in import #479 * Call airline name with optional() around subfleet * Minor cleanup * Search flights by subfleet #484 (#506) * API level search of flights #484 * Add Subfleet to flights page for search * Make the fuel used optional (#512) * Add make to Docker container * Add getRootDomain() to Utils (#514) * Show admin dropdown for admin-access ability (#515) * Show admin dropdown for admin-access ability closes #509 * Formatting * Check user permissions on the routes #508 (#516) * Check user permissions on the routes #508 * Formatting * Return default value on exception for setting() * Correct text for no subfleets #507 (#518) * Add a public_url() helper #513 (#519) * Reduce number of queries for update check (#520) * Try to clear caches before updating (#522) * Try to clear caches before updating * Add clear-compiled to maintenance cache list * Formatting * Set PIREPs page to public (#526) Set PIREPs page to public * Fix live and route map errors #527 (#528) * Add menu bar for mobile (#529) * Format all blade templates to 2 spaces #530 (#531) * Fix PIREP edit endpoint closes #533 (#534) * Fix import during flight cron #532 (#535) * PIREPS resource except for show (#536) * Use optional() around the airport fields (#537) * Use optional() around the airport fields * Add null-coalesce around full_name * Add link to download ACARS config from profile (#539) * Add link to download ACARS config from profile * Formatting * Update xml config file template (#540)
2020-02-09 02:29:34 +08:00
$this->assertEquals(AircraftStatus::ACTIVE, $aircraft->status);
// Now try importing the updated file, the status for the aircraft should change
// to being stored
$file_path = base_path('tests/data/aircraft-update.csv');
$status = $this->importSvc->importAircraft($file_path);
$this->assertCount(1, $status['success']);
$aircraft = Aircraft::where([
'registration' => 'N309US',
])->first();
$this->assertEquals(AircraftStatus::STORED, $aircraft->status);
}
/**
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
2018-03-22 06:07:30 +08:00
public function testAirportImporter(): void
{
$file_path = base_path('tests/data/airports.csv');
$status = $this->importSvc->importAirports($file_path);
$this->assertCount(2, $status['success']);
$this->assertCount(1, $status['errors']);
// See if it imported
$airport = Airport::where([
'id' => 'KAUS',
])->first();
$this->assertNotNull($airport);
$this->assertEquals('KAUS', $airport->id);
$this->assertEquals('AUS', $airport->iata);
$this->assertEquals('KAUS', $airport->icao);
2018-03-31 10:51:13 +08:00
$this->assertEquals('Austin-Bergstrom', $airport->name);
$this->assertEquals('Austin, Texas, USA', $airport->location);
$this->assertEquals('United States', $airport->country);
$this->assertEquals('America/Chicago', $airport->timezone);
$this->assertEquals(true, $airport->hub);
$this->assertEquals('30.1945', $airport->lat);
$this->assertEquals('-97.6699', $airport->lon);
$this->assertEquals(0.0, $airport->ground_handling_cost);
$this->assertEquals(setting('airports.default_jet_a_fuel_cost'), $airport->fuel_jeta_cost);
// See if it imported
$airport = Airport::where([
'id' => 'KSFO',
])->first();
$this->assertNotNull($airport);
$this->assertEquals(true, $airport->hub);
$this->assertEquals(0.9, $airport->fuel_jeta_cost);
$this->assertEquals(setting('airports.default_ground_handling_cost'), $airport->ground_handling_cost);
}
/**
* Test importing the subfleets
2018-08-27 00:40:04 +08:00
*
2019-07-18 01:40:56 +08:00
* @throws \Illuminate\Validation\ValidationException
*/
public function testSubfleetImporter(): void
{
$fare_economy = factory(Fare::class)->create(['code' => 'Y', 'capacity' => 150]);
$fare_business = factory(Fare::class)->create(['code' => 'B', 'capacity' => 20]);
$airline = factory(Airline::class)->create(['icao' => 'VMS']);
$file_path = base_path('tests/data/subfleets.csv');
$status = $this->importSvc->importSubfleets($file_path);
$this->assertCount(1, $status['success']);
$this->assertCount(1, $status['errors']);
// See if it imported
$subfleet = Subfleet::where([
'type' => 'A32X',
])->first();
$this->assertNotNull($subfleet);
$this->assertEquals($airline->id, $subfleet->id);
$this->assertEquals('A32X', $subfleet->type);
$this->assertEquals('Airbus A320', $subfleet->name);
2018-03-23 06:48:57 +08:00
2018-03-23 06:59:10 +08:00
// get the fares and check the pivot tables and the main tables
$fares = $subfleet->fares()->get();
2018-03-23 06:48:57 +08:00
$eco = $fares->where('code', 'Y')->first();
2018-03-23 06:59:10 +08:00
$this->assertEquals(null, $eco->pivot->price);
$this->assertEquals(null, $eco->pivot->capacity);
$this->assertEquals(null, $eco->pivot->cost);
2018-03-23 06:48:57 +08:00
$this->assertEquals($fare_economy->price, $eco->price);
2018-03-23 06:59:10 +08:00
$this->assertEquals($fare_economy->capacity, $eco->capacity);
2018-03-23 06:48:57 +08:00
$this->assertEquals($fare_economy->cost, $eco->cost);
$busi = $fares->where('code', 'B')->first();
2018-03-23 06:59:10 +08:00
$this->assertEquals($fare_business->price, $busi->price);
$this->assertEquals($fare_business->capacity, $busi->capacity);
2018-03-23 06:48:57 +08:00
$this->assertEquals($fare_business->cost, $busi->cost);
2018-03-23 06:59:10 +08:00
$this->assertEquals('500%', $busi->pivot->price);
$this->assertEquals(100, $busi->pivot->capacity);
$this->assertEquals(null, $busi->pivot->cost);
}
public function testAirportSpecialCharsImporter(): void
{
$file_path = base_path('tests/data/airports_special_chars.csv');
$status = $this->importSvc->importAirports($file_path);
// See if it imported
$airport = Airport::where([
'id' => 'LEMD',
])->first();
$this->assertNotNull($airport);
$this->assertEquals('Adolfo Suárez MadridBarajas Airport', $airport->name);
}
}