Initial commit
This commit is contained in:
96
tests/Feature/Admin/UserControllerTest.php
Normal file
96
tests/Feature/Admin/UserControllerTest.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Admin;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UserControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_admin_can_list_users(): void
|
||||
{
|
||||
$admin = $this->actingAsAdmin();
|
||||
$user = $this->createUser();
|
||||
|
||||
$response = $this->getJson('/api/users');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $admin->id])
|
||||
->assertJsonFragment(['id' => $user->id]);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_list_users(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->getJson('/api/users')->assertStatus(403);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_user(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$response = $this->postJson('/api/users', [
|
||||
'name' => 'Test User',
|
||||
'email' => 'test-user@example.com',
|
||||
'password' => 'secretpass',
|
||||
'is_admin' => true,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$response->assertStatus(201)
|
||||
->assertJsonFragment(['email' => 'test-user@example.com']);
|
||||
|
||||
$this->assertDatabaseHas('users', [
|
||||
'email' => 'test-user@example.com',
|
||||
'is_admin' => 1,
|
||||
'is_active' => 1,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_admin_can_update_user_and_password(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$user = $this->createUser(['password' => 'oldpass']);
|
||||
|
||||
$response = $this->putJson("/api/users/{$user->id}", [
|
||||
'name' => 'Updated Name',
|
||||
'email' => 'updated@example.com',
|
||||
'password' => 'newpass123',
|
||||
'is_admin' => false,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['email' => 'updated@example.com']);
|
||||
|
||||
$user->refresh();
|
||||
$this->assertSame('Updated Name', $user->name);
|
||||
$this->assertTrue(Hash::check('newpass123', $user->password));
|
||||
}
|
||||
|
||||
public function test_admin_can_deactivate_user(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$user = $this->createUser(['is_active' => true]);
|
||||
|
||||
$response = $this->deleteJson("/api/users/{$user->id}");
|
||||
|
||||
$response->assertStatus(200);
|
||||
$this->assertDatabaseHas('users', [
|
||||
'id' => $user->id,
|
||||
'is_active' => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_admin_cannot_deactivate_self(): void
|
||||
{
|
||||
$admin = $this->actingAsAdmin();
|
||||
|
||||
$this->deleteJson("/api/users/{$admin->id}")
|
||||
->assertStatus(422);
|
||||
}
|
||||
}
|
||||
43
tests/Feature/Auth/LoginControllerTest.php
Normal file
43
tests/Feature/Auth/LoginControllerTest.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Auth;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LoginControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_login_success_returns_user(): void
|
||||
{
|
||||
$user = $this->createUser([
|
||||
'password' => 'demodemo',
|
||||
]);
|
||||
|
||||
$response = $this->withSession([])->postJson('/api/login', [
|
||||
'email' => $user->email,
|
||||
'password' => 'demodemo',
|
||||
]);
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment([
|
||||
'id' => $user->id,
|
||||
'email' => $user->email,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_login_inactive_user_fails(): void
|
||||
{
|
||||
$user = $this->createInactiveUser([
|
||||
'password' => 'demodemo',
|
||||
]);
|
||||
|
||||
$response = $this->withSession([])->postJson('/api/login', [
|
||||
'email' => $user->email,
|
||||
'password' => 'demodemo',
|
||||
]);
|
||||
|
||||
$response->assertStatus(422);
|
||||
}
|
||||
}
|
||||
74
tests/Feature/Catalog/BandControllerTest.php
Normal file
74
tests/Feature/Catalog/BandControllerTest.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class BandControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_bands(): void
|
||||
{
|
||||
$band = $this->createBand();
|
||||
|
||||
$response = $this->getJson('/api/bands');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $band->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_band(): void
|
||||
{
|
||||
$band = $this->createBand();
|
||||
|
||||
$response = $this->getJson("/api/bands/{$band->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $band->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_band(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/bands', [
|
||||
'name' => '144 MHz',
|
||||
'order' => 1,
|
||||
'edi_band_begin' => 144000000,
|
||||
'edi_band_end' => 146000000,
|
||||
'has_power_category' => true,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$bandId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/bands/{$bandId}", [
|
||||
'name' => '144 MHz (upd)',
|
||||
'order' => 2,
|
||||
'edi_band_begin' => 144000000,
|
||||
'edi_band_end' => 146000000,
|
||||
'has_power_category' => false,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $bandId]);
|
||||
|
||||
$this->deleteJson("/api/bands/{$bandId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_band(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/bands', [
|
||||
'name' => '144 MHz',
|
||||
'order' => 1,
|
||||
'edi_band_begin' => 144000000,
|
||||
'edi_band_end' => 146000000,
|
||||
'has_power_category' => true,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
65
tests/Feature/Catalog/CategoryControllerTest.php
Normal file
65
tests/Feature/Catalog/CategoryControllerTest.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CategoryControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_categories(): void
|
||||
{
|
||||
$category = $this->createCategory();
|
||||
|
||||
$response = $this->getJson('/api/categories');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $category->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_category(): void
|
||||
{
|
||||
$category = $this->createCategory();
|
||||
|
||||
$response = $this->getJson("/api/categories/{$category->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $category->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_category(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/categories', [
|
||||
'name' => 'CAT-A',
|
||||
'order' => 1,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$categoryId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/categories/{$categoryId}", [
|
||||
'name' => 'CAT-B',
|
||||
'order' => 2,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $categoryId]);
|
||||
|
||||
$this->deleteJson("/api/categories/{$categoryId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_category(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/categories', [
|
||||
'name' => 'CAT-A',
|
||||
'order' => 1,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
100
tests/Feature/Catalog/ContestParameterControllerTest.php
Normal file
100
tests/Feature/Catalog/ContestParameterControllerTest.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ContestParameterControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_contest_parameters(): void
|
||||
{
|
||||
$item = $this->createContestParameter();
|
||||
|
||||
$response = $this->getJson('/api/contest-parameters');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_contest_parameter(): void
|
||||
{
|
||||
$item = $this->createContestParameter();
|
||||
|
||||
$response = $this->getJson("/api/contest-parameters/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_contest_parameter(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$contest = $this->createContest();
|
||||
|
||||
$createResponse = $this->postJson('/api/contest-parameters', [
|
||||
'contest_id' => $contest->id,
|
||||
'log_type' => 'STANDARD',
|
||||
'ignore_slash_part' => true,
|
||||
'ignore_third_part' => true,
|
||||
'letters_in_rst' => true,
|
||||
'discard_qso_rec_diff_call' => true,
|
||||
'discard_qso_sent_diff_call' => false,
|
||||
'discard_qso_rec_diff_rst' => true,
|
||||
'discard_qso_sent_diff_rst' => false,
|
||||
'discard_qso_rec_diff_code' => true,
|
||||
'discard_qso_sent_diff_code' => false,
|
||||
'unique_qso' => true,
|
||||
'time_tolerance' => 600,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/contest-parameters/{$itemId}", [
|
||||
'contest_id' => $contest->id,
|
||||
'log_type' => 'CHECK',
|
||||
'ignore_slash_part' => false,
|
||||
'ignore_third_part' => true,
|
||||
'letters_in_rst' => false,
|
||||
'discard_qso_rec_diff_call' => true,
|
||||
'discard_qso_sent_diff_call' => false,
|
||||
'discard_qso_rec_diff_rst' => true,
|
||||
'discard_qso_sent_diff_rst' => false,
|
||||
'discard_qso_rec_diff_code' => true,
|
||||
'discard_qso_sent_diff_code' => false,
|
||||
'unique_qso' => false,
|
||||
'time_tolerance' => 300,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/contest-parameters/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_contest_parameter(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$contest = $this->createContest();
|
||||
|
||||
$this->postJson('/api/contest-parameters', [
|
||||
'contest_id' => $contest->id,
|
||||
'log_type' => 'STANDARD',
|
||||
'ignore_slash_part' => true,
|
||||
'ignore_third_part' => true,
|
||||
'letters_in_rst' => true,
|
||||
'discard_qso_rec_diff_call' => true,
|
||||
'discard_qso_sent_diff_call' => false,
|
||||
'discard_qso_rec_diff_rst' => true,
|
||||
'discard_qso_sent_diff_rst' => false,
|
||||
'discard_qso_rec_diff_code' => true,
|
||||
'discard_qso_sent_diff_code' => false,
|
||||
'unique_qso' => true,
|
||||
'time_tolerance' => 600,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
46
tests/Feature/Catalog/CountryWwlControllerTest.php
Normal file
46
tests/Feature/Catalog/CountryWwlControllerTest.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CountryWwlControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_country_wwl_records(): void
|
||||
{
|
||||
$item = $this->createCountryWwl();
|
||||
|
||||
$response = $this->getJson('/api/countries-wwl');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment([
|
||||
'country_name' => $item->country_name,
|
||||
'wwl' => $item->wwl,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_country_wwl(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/countries-wwl', [
|
||||
'country_name' => 'Test Country',
|
||||
'wwl' => 'AA00',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_country_wwl(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/countries-wwl', [
|
||||
'country_name' => 'Test Country',
|
||||
'wwl' => 'AA00',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
94
tests/Feature/Catalog/CtyControllerTest.php
Normal file
94
tests/Feature/Catalog/CtyControllerTest.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CtyControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_cty_records(): void
|
||||
{
|
||||
$item = $this->createCty();
|
||||
|
||||
$response = $this->getJson('/api/cty');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_cty_record(): void
|
||||
{
|
||||
$item = $this->createCty();
|
||||
|
||||
$response = $this->getJson("/api/cty/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_cty_record(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/cty', [
|
||||
'country_name' => 'Test Country',
|
||||
'dxcc' => 999,
|
||||
'cq_zone' => 10,
|
||||
'itu_zone' => 20,
|
||||
'continent' => 'EU',
|
||||
'latitude' => 10.0,
|
||||
'longitude' => 20.0,
|
||||
'time_offset' => 1.0,
|
||||
'prefix' => 'TST',
|
||||
'prefix_norm' => 'TST',
|
||||
'precise' => true,
|
||||
'source' => 'test',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/cty/{$itemId}", [
|
||||
'country_name' => 'Test Country 2',
|
||||
'dxcc' => 999,
|
||||
'cq_zone' => 10,
|
||||
'itu_zone' => 20,
|
||||
'continent' => 'EU',
|
||||
'latitude' => 10.0,
|
||||
'longitude' => 20.0,
|
||||
'time_offset' => 1.0,
|
||||
'prefix' => 'TST2',
|
||||
'prefix_norm' => 'TST2',
|
||||
'precise' => false,
|
||||
'source' => 'test',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/cty/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_cty_record(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/cty', [
|
||||
'country_name' => 'Test Country',
|
||||
'dxcc' => 999,
|
||||
'cq_zone' => 10,
|
||||
'itu_zone' => 20,
|
||||
'continent' => 'EU',
|
||||
'latitude' => 10.0,
|
||||
'longitude' => 20.0,
|
||||
'time_offset' => 1.0,
|
||||
'prefix' => 'TST',
|
||||
'precise' => true,
|
||||
'source' => 'test',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
62
tests/Feature/Catalog/EdiBandControllerTest.php
Normal file
62
tests/Feature/Catalog/EdiBandControllerTest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EdiBandControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_edi_bands(): void
|
||||
{
|
||||
$item = $this->createEdiBand();
|
||||
|
||||
$response = $this->getJson('/api/edi-bands');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_edi_band(): void
|
||||
{
|
||||
$item = $this->createEdiBand();
|
||||
|
||||
$response = $this->getJson("/api/edi-bands/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_edi_band(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/edi-bands', [
|
||||
'value' => 'EDI-144',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/edi-bands/{$itemId}", [
|
||||
'value' => 'EDI-432',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/edi-bands/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_edi_band(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/edi-bands', [
|
||||
'value' => 'EDI-144',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
62
tests/Feature/Catalog/EdiCategoryControllerTest.php
Normal file
62
tests/Feature/Catalog/EdiCategoryControllerTest.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EdiCategoryControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_edi_categories(): void
|
||||
{
|
||||
$item = $this->createEdiCategory();
|
||||
|
||||
$response = $this->getJson('/api/edi-categories');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_edi_category(): void
|
||||
{
|
||||
$item = $this->createEdiCategory();
|
||||
|
||||
$response = $this->getJson("/api/edi-categories/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_edi_category(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/edi-categories', [
|
||||
'value' => 'EDI-CAT-A',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/edi-categories/{$itemId}", [
|
||||
'value' => 'EDI-CAT-B',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/edi-categories/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_edi_category(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/edi-categories', [
|
||||
'value' => 'EDI-CAT-A',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
76
tests/Feature/Catalog/EvaluationRuleSetControllerTest.php
Normal file
76
tests/Feature/Catalog/EvaluationRuleSetControllerTest.php
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EvaluationRuleSetControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_rule_sets(): void
|
||||
{
|
||||
$item = $this->createRuleSet();
|
||||
|
||||
$response = $this->getJson('/api/evaluation-rule-sets');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_rule_set(): void
|
||||
{
|
||||
$item = $this->createRuleSet();
|
||||
|
||||
$response = $this->getJson("/api/evaluation-rule-sets/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_rule_set(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/evaluation-rule-sets', [
|
||||
'name' => 'Test ruleset',
|
||||
'code' => 'TEST_RULES',
|
||||
'scoring_mode' => 'DISTANCE',
|
||||
'multiplier_type' => 'WWL',
|
||||
'dup_qso_policy' => 'ZERO_POINTS',
|
||||
'nil_qso_policy' => 'ZERO_POINTS',
|
||||
'busted_call_policy' => 'ZERO_POINTS',
|
||||
'busted_exchange_policy' => 'ZERO_POINTS',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/evaluation-rule-sets/{$itemId}", [
|
||||
'name' => 'Updated ruleset',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/evaluation-rule-sets/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_rule_set(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/evaluation-rule-sets', [
|
||||
'name' => 'Test ruleset',
|
||||
'code' => 'TEST_RULES',
|
||||
'scoring_mode' => 'DISTANCE',
|
||||
'multiplier_type' => 'WWL',
|
||||
'dup_qso_policy' => 'ZERO_POINTS',
|
||||
'nil_qso_policy' => 'ZERO_POINTS',
|
||||
'busted_call_policy' => 'ZERO_POINTS',
|
||||
'busted_exchange_policy' => 'ZERO_POINTS',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
68
tests/Feature/Catalog/PowerCategoryControllerTest.php
Normal file
68
tests/Feature/Catalog/PowerCategoryControllerTest.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Catalog;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PowerCategoryControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_power_categories(): void
|
||||
{
|
||||
$item = $this->createPowerCategory();
|
||||
|
||||
$response = $this->getJson('/api/power-categories');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_power_category(): void
|
||||
{
|
||||
$item = $this->createPowerCategory();
|
||||
|
||||
$response = $this->getJson("/api/power-categories/{$item->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $item->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_power_category(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/power-categories', [
|
||||
'name' => 'PWR-A',
|
||||
'order' => 1,
|
||||
'power_level' => 100,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$itemId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/power-categories/{$itemId}", [
|
||||
'name' => 'PWR-B',
|
||||
'order' => 2,
|
||||
'power_level' => 200,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $itemId]);
|
||||
|
||||
$this->deleteJson("/api/power-categories/{$itemId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_power_category(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/power-categories', [
|
||||
'name' => 'PWR-A',
|
||||
'order' => 1,
|
||||
'power_level' => 100,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
82
tests/Feature/Contests/ContestControllerTest.php
Normal file
82
tests/Feature/Contests/ContestControllerTest.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Contests;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ContestControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_contests(): void
|
||||
{
|
||||
$contest = $this->createContest();
|
||||
|
||||
$response = $this->getJson('/api/contests');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $contest->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_only_active(): void
|
||||
{
|
||||
$active = $this->createContest(['is_active' => true]);
|
||||
$inactive = $this->createContest(['is_active' => false]);
|
||||
|
||||
$response = $this->getJson('/api/contests?only_active=1');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $active->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertFalse(in_array($inactive->id, $ids, true));
|
||||
}
|
||||
|
||||
public function test_show_returns_contest(): void
|
||||
{
|
||||
$contest = $this->createContest();
|
||||
|
||||
$response = $this->getJson("/api/contests/{$contest->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $contest->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_contest(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$ruleSet = $this->createRuleSet();
|
||||
|
||||
$createResponse = $this->postJson('/api/contests', [
|
||||
'name' => ['cs' => 'Test soutěž', 'en' => 'Test contest'],
|
||||
'description' => ['cs' => 'Popis', 'en' => 'Description'],
|
||||
'rule_set_id' => $ruleSet->id,
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$contestId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/contests/{$contestId}", [
|
||||
'name' => ['cs' => 'Upraveno', 'en' => 'Updated'],
|
||||
'description' => ['cs' => 'Popis', 'en' => 'Description'],
|
||||
'is_active' => false,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $contestId]);
|
||||
|
||||
$this->deleteJson("/api/contests/{$contestId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_contest(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/contests', [
|
||||
'name' => ['cs' => 'Test soutěž', 'en' => 'Test contest'],
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
160
tests/Feature/Evaluation/AggregateLogResultsJobTest.php
Normal file
160
tests/Feature/Evaluation/AggregateLogResultsJobTest.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Evaluation;
|
||||
|
||||
use App\Jobs\AggregateLogResultsJob;
|
||||
use App\Models\LogResult;
|
||||
use App\Models\QsoResult;
|
||||
use App\Models\WorkingQso;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AggregateLogResultsJobTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private function createQso(int $runId, int $logId, int $bandId, Carbon $ts, int $points): int
|
||||
{
|
||||
$logQso = $this->createLogQso(['log_id' => $logId]);
|
||||
|
||||
$this->createQsoResult([
|
||||
'evaluation_run_id' => $runId,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'is_valid' => true,
|
||||
'points' => $points,
|
||||
]);
|
||||
|
||||
WorkingQso::create([
|
||||
'evaluation_run_id' => $runId,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'log_id' => $logId,
|
||||
'ts_utc' => $ts,
|
||||
'band_id' => $bandId,
|
||||
'call_norm' => 'OK1AAA',
|
||||
'rcall_norm' => 'OK1BBB',
|
||||
'loc_norm' => 'JN00AA',
|
||||
'rloc_norm' => 'JN00AA',
|
||||
]);
|
||||
|
||||
return $logQso->id;
|
||||
}
|
||||
|
||||
public function test_aggregate_applies_operating_window_for_6h(): void
|
||||
{
|
||||
$ruleSet = $this->createRuleSet([
|
||||
'use_multipliers' => false,
|
||||
'multiplier_type' => 'NONE',
|
||||
'multiplier_scope' => 'OVERALL',
|
||||
'multiplier_source' => 'VALID_ONLY',
|
||||
'operating_window_mode' => 'BEST_CONTIGUOUS',
|
||||
'operating_window_hours' => 6,
|
||||
]);
|
||||
$round = $this->createRound();
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
$run = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rule_set_id' => $ruleSet->id,
|
||||
]);
|
||||
$band = $this->createBand();
|
||||
|
||||
$t0 = Carbon::create(2025, 1, 1, 0, 0, 0, 'UTC');
|
||||
$t1 = Carbon::create(2025, 1, 1, 1, 0, 0, 'UTC');
|
||||
$t2 = Carbon::create(2025, 1, 1, 7, 0, 0, 'UTC');
|
||||
$t3 = Carbon::create(2025, 1, 1, 8, 0, 0, 'UTC');
|
||||
|
||||
$firstA = $this->createQso($run->id, $log->id, $band->id, $t0, 10);
|
||||
$firstB = $this->createQso($run->id, $log->id, $band->id, $t1, 10);
|
||||
$secondA = $this->createQso($run->id, $log->id, $band->id, $t2, 10);
|
||||
$secondB = $this->createQso($run->id, $log->id, $band->id, $t3, 10);
|
||||
|
||||
$this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'sixhr_category' => true,
|
||||
'status' => 'OK',
|
||||
]);
|
||||
|
||||
(new AggregateLogResultsJob($run->id, $log->id))->handle();
|
||||
|
||||
$result = LogResult::where('evaluation_run_id', $run->id)
|
||||
->where('log_id', $log->id)
|
||||
->first();
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertSame(40, $result->official_score);
|
||||
$this->assertSame($t0->toDateTimeString(), $result->operating_window_start_utc?->toDateTimeString());
|
||||
$this->assertSame($t1->toDateTimeString(), $result->operating_window_end_utc?->toDateTimeString());
|
||||
$this->assertSame($t2->toDateTimeString(), $result->operating_window_2_start_utc?->toDateTimeString());
|
||||
$this->assertSame($t3->toDateTimeString(), $result->operating_window_2_end_utc?->toDateTimeString());
|
||||
$this->assertSame(6, $result->operating_window_hours);
|
||||
$this->assertSame(4, $result->operating_window_qso_count);
|
||||
|
||||
$included = QsoResult::where('evaluation_run_id', $run->id)
|
||||
->whereIn('log_qso_id', [$firstA, $firstB, $secondA, $secondB])
|
||||
->pluck('is_operating_window_excluded')
|
||||
->all();
|
||||
$this->assertSame([false, false, false, false], $included);
|
||||
|
||||
$excludedCount = QsoResult::where('evaluation_run_id', $run->id)
|
||||
->where('is_operating_window_excluded', true)
|
||||
->count();
|
||||
$this->assertSame(0, $excludedCount);
|
||||
}
|
||||
|
||||
public function test_aggregate_keeps_all_qso_for_non_6h(): void
|
||||
{
|
||||
$ruleSet = $this->createRuleSet([
|
||||
'use_multipliers' => false,
|
||||
'multiplier_type' => 'NONE',
|
||||
'multiplier_scope' => 'OVERALL',
|
||||
'multiplier_source' => 'VALID_ONLY',
|
||||
'operating_window_mode' => 'BEST_CONTIGUOUS',
|
||||
'operating_window_hours' => 6,
|
||||
]);
|
||||
$round = $this->createRound();
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
$run = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rule_set_id' => $ruleSet->id,
|
||||
]);
|
||||
$band = $this->createBand();
|
||||
|
||||
$t0 = Carbon::create(2025, 1, 1, 0, 0, 0, 'UTC');
|
||||
$t1 = Carbon::create(2025, 1, 1, 1, 0, 0, 'UTC');
|
||||
$t2 = Carbon::create(2025, 1, 1, 7, 0, 0, 'UTC');
|
||||
$t3 = Carbon::create(2025, 1, 1, 8, 0, 0, 'UTC');
|
||||
|
||||
$this->createQso($run->id, $log->id, $band->id, $t0, 10);
|
||||
$this->createQso($run->id, $log->id, $band->id, $t1, 10);
|
||||
$this->createQso($run->id, $log->id, $band->id, $t2, 10);
|
||||
$this->createQso($run->id, $log->id, $band->id, $t3, 10);
|
||||
|
||||
$this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'sixhr_category' => false,
|
||||
'status' => 'OK',
|
||||
]);
|
||||
|
||||
(new AggregateLogResultsJob($run->id, $log->id))->handle();
|
||||
|
||||
$result = LogResult::where('evaluation_run_id', $run->id)
|
||||
->where('log_id', $log->id)
|
||||
->first();
|
||||
|
||||
$this->assertNotNull($result);
|
||||
$this->assertSame(40, $result->official_score);
|
||||
$this->assertNull($result->operating_window_start_utc);
|
||||
$this->assertNull($result->operating_window_end_utc);
|
||||
$this->assertNull($result->operating_window_2_start_utc);
|
||||
$this->assertNull($result->operating_window_2_end_utc);
|
||||
$this->assertNull($result->operating_window_hours);
|
||||
$this->assertNull($result->operating_window_qso_count);
|
||||
|
||||
$excludedCount = QsoResult::where('evaluation_run_id', $run->id)
|
||||
->where('is_operating_window_excluded', true)
|
||||
->count();
|
||||
$this->assertSame(0, $excludedCount);
|
||||
}
|
||||
}
|
||||
72
tests/Feature/Evaluation/EvaluationRunControllerTest.php
Normal file
72
tests/Feature/Evaluation/EvaluationRunControllerTest.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Evaluation;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EvaluationRunControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_cancel_requires_authentication(): void
|
||||
{
|
||||
$run = $this->createEvaluationRun();
|
||||
|
||||
$this->postJson("/api/evaluation-runs/{$run->id}/cancel")
|
||||
->assertStatus(401);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_cancel(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$run = $this->createEvaluationRun(['status' => 'RUNNING']);
|
||||
|
||||
$this->postJson("/api/evaluation-runs/{$run->id}/cancel")
|
||||
->assertStatus(403);
|
||||
}
|
||||
|
||||
public function test_admin_can_cancel_running_run(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun(['status' => 'RUNNING']);
|
||||
|
||||
$response = $this->postJson("/api/evaluation-runs/{$run->id}/cancel");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['status' => 'canceled']);
|
||||
|
||||
$this->assertDatabaseHas('evaluation_runs', [
|
||||
'id' => $run->id,
|
||||
'status' => 'CANCELED',
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_cancel_rejects_finished_runs(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun(['status' => 'SUCCEEDED']);
|
||||
|
||||
$this->postJson("/api/evaluation-runs/{$run->id}/cancel")
|
||||
->assertStatus(409);
|
||||
}
|
||||
|
||||
public function test_admin_can_set_result_type_and_update_round(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun(['result_type' => null]);
|
||||
$round = $run->round;
|
||||
|
||||
$response = $this->postJson("/api/evaluation-runs/{$run->id}/result-type", [
|
||||
'result_type' => 'PRELIMINARY',
|
||||
]);
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['result_type' => 'PRELIMINARY']);
|
||||
|
||||
$round->refresh();
|
||||
$this->assertSame($run->id, $round->preliminary_evaluation_run_id);
|
||||
$this->assertNull($round->official_evaluation_run_id);
|
||||
$this->assertNull($round->test_evaluation_run_id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Evaluation;
|
||||
|
||||
use App\Jobs\RecalculateOfficialRanksJob;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RecalculateOfficialRanksSixhrModeTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_iaru_sixhr_merges_single_and_multi(): void
|
||||
{
|
||||
$ruleSet = $this->createRuleSet(['sixhr_ranking_mode' => 'IARU']);
|
||||
$round = $this->createRound();
|
||||
$run = $this->createEvaluationRun(['round_id' => $round->id, 'rule_set_id' => $ruleSet->id]);
|
||||
|
||||
$band = $this->createBand();
|
||||
$single = $this->createCategory(['name' => 'SINGLE']);
|
||||
$multi = $this->createCategory(['name' => 'MULTI']);
|
||||
|
||||
$logSingle = $this->createLog(['round_id' => $round->id]);
|
||||
$logMulti = $this->createLog(['round_id' => $round->id]);
|
||||
|
||||
$resSingle = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logSingle->id,
|
||||
'band_id' => $band->id,
|
||||
'category_id' => $single->id,
|
||||
'official_score' => 200,
|
||||
'valid_qso_count' => 10,
|
||||
'status' => 'OK',
|
||||
'sixhr_category' => true,
|
||||
]);
|
||||
$resMulti = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logMulti->id,
|
||||
'band_id' => $band->id,
|
||||
'category_id' => $multi->id,
|
||||
'official_score' => 150,
|
||||
'valid_qso_count' => 8,
|
||||
'status' => 'OK',
|
||||
'sixhr_category' => true,
|
||||
]);
|
||||
|
||||
(new RecalculateOfficialRanksJob($run->id))->handle();
|
||||
|
||||
$resSingle->refresh();
|
||||
$resMulti->refresh();
|
||||
|
||||
$this->assertSame(1, $resSingle->rank_overall);
|
||||
$this->assertSame(2, $resMulti->rank_overall);
|
||||
$this->assertSame('ALL', $resSingle->sixhr_ranking_bucket);
|
||||
$this->assertSame('ALL', $resMulti->sixhr_ranking_bucket);
|
||||
}
|
||||
|
||||
public function test_crk_sixhr_keeps_single_and_multi_separate(): void
|
||||
{
|
||||
$ruleSet = $this->createRuleSet(['sixhr_ranking_mode' => 'CRK']);
|
||||
$round = $this->createRound();
|
||||
$run = $this->createEvaluationRun(['round_id' => $round->id, 'rule_set_id' => $ruleSet->id]);
|
||||
|
||||
$band = $this->createBand();
|
||||
$single = $this->createCategory(['name' => 'SINGLE']);
|
||||
$multi = $this->createCategory(['name' => 'MULTI']);
|
||||
|
||||
$logSingle = $this->createLog(['round_id' => $round->id]);
|
||||
$logMulti = $this->createLog(['round_id' => $round->id]);
|
||||
|
||||
$resSingle = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logSingle->id,
|
||||
'band_id' => $band->id,
|
||||
'category_id' => $single->id,
|
||||
'official_score' => 200,
|
||||
'valid_qso_count' => 10,
|
||||
'status' => 'OK',
|
||||
'sixhr_category' => true,
|
||||
]);
|
||||
$resMulti = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logMulti->id,
|
||||
'band_id' => $band->id,
|
||||
'category_id' => $multi->id,
|
||||
'official_score' => 150,
|
||||
'valid_qso_count' => 8,
|
||||
'status' => 'OK',
|
||||
'sixhr_category' => true,
|
||||
]);
|
||||
|
||||
(new RecalculateOfficialRanksJob($run->id))->handle();
|
||||
|
||||
$resSingle->refresh();
|
||||
$resMulti->refresh();
|
||||
|
||||
$this->assertSame(1, $resSingle->rank_overall);
|
||||
$this->assertSame(1, $resMulti->rank_overall);
|
||||
$this->assertSame('SINGLE', $resSingle->sixhr_ranking_bucket);
|
||||
$this->assertSame('MULTI', $resMulti->sixhr_ranking_bucket);
|
||||
}
|
||||
}
|
||||
7
tests/Feature/ExampleTest.php
Normal file
7
tests/Feature/ExampleTest.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
test('the application returns a successful response', function () {
|
||||
$response = $this->get('/');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
86
tests/Feature/Files/FileControllerTest.php
Normal file
86
tests/Feature/Files/FileControllerTest.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Files;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Tests\TestCase;
|
||||
|
||||
class FileControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_files(): void
|
||||
{
|
||||
$file = $this->createFile();
|
||||
|
||||
$response = $this->getJson('/api/files');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $file->id]);
|
||||
}
|
||||
|
||||
public function test_show_returns_file_metadata(): void
|
||||
{
|
||||
$file = $this->createFile();
|
||||
|
||||
$response = $this->getJson("/api/files/{$file->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment([
|
||||
'id' => $file->id,
|
||||
'filename' => $file->filename,
|
||||
]);
|
||||
}
|
||||
|
||||
public function test_store_allows_guest_before_deadline(): void
|
||||
{
|
||||
Storage::fake();
|
||||
Queue::fake();
|
||||
$round = $this->createRound(['logs_deadline' => now()->addDay()]);
|
||||
|
||||
$response = $this->postJson('/api/files', [
|
||||
'round_id' => $round->id,
|
||||
'file' => UploadedFile::fake()->create('log.edi', 5, 'text/plain'),
|
||||
]);
|
||||
|
||||
$response->assertStatus(201);
|
||||
}
|
||||
|
||||
public function test_content_returns_stored_file(): void
|
||||
{
|
||||
Storage::fake();
|
||||
|
||||
$file = $this->createFile(['path' => 'uploads/test/file.edi', 'mimetype' => 'text/plain']);
|
||||
Storage::put($file->path, 'TEST');
|
||||
|
||||
$response = $this->get("/api/files/{$file->id}/content");
|
||||
|
||||
$response->assertStatus(200);
|
||||
$this->assertSame('TEST', $response->getContent());
|
||||
}
|
||||
|
||||
public function test_delete_requires_auth(): void
|
||||
{
|
||||
$file = $this->createFile();
|
||||
|
||||
$this->deleteJson("/api/files/{$file->id}")
|
||||
->assertStatus(401);
|
||||
}
|
||||
|
||||
public function test_admin_can_delete_file(): void
|
||||
{
|
||||
Storage::fake();
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$file = $this->createFile(['path' => 'uploads/test/file.edi']);
|
||||
Storage::put($file->path, 'TEST');
|
||||
|
||||
$this->deleteJson("/api/files/{$file->id}")
|
||||
->assertStatus(204);
|
||||
|
||||
Storage::assertMissing($file->path);
|
||||
}
|
||||
}
|
||||
82
tests/Feature/Logs/LogControllerTest.php
Normal file
82
tests/Feature/Logs/LogControllerTest.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Logs;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_logs(): void
|
||||
{
|
||||
$log = $this->createLog();
|
||||
|
||||
$response = $this->getJson('/api/logs');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $log->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_round(): void
|
||||
{
|
||||
$roundA = $this->createRound();
|
||||
$roundB = $this->createRound();
|
||||
$logA = $this->createLog(['round_id' => $roundA->id]);
|
||||
$this->createLog(['round_id' => $roundB->id]);
|
||||
|
||||
$response = $this->getJson("/api/logs?round_id={$roundA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $logA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_log(): void
|
||||
{
|
||||
$log = $this->createLog();
|
||||
|
||||
$response = $this->getJson("/api/logs/{$log->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $log->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_log(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$round = $this->createRound();
|
||||
|
||||
$createResponse = $this->postJson('/api/logs', [
|
||||
'round_id' => $round->id,
|
||||
'pcall' => 'OK1ABC',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$logId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/logs/{$logId}", [
|
||||
'pcall' => 'OK1DEF',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $logId]);
|
||||
|
||||
$this->deleteJson("/api/logs/{$logId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_log(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$round = $this->createRound();
|
||||
|
||||
$this->postJson('/api/logs', [
|
||||
'round_id' => $round->id,
|
||||
'pcall' => 'OK1ABC',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
84
tests/Feature/Logs/LogQsoControllerTest.php
Normal file
84
tests/Feature/Logs/LogQsoControllerTest.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Logs;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogQsoControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_log_qsos(): void
|
||||
{
|
||||
$qso = $this->createLogQso();
|
||||
|
||||
$response = $this->getJson('/api/log-qsos');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $qso->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_log_id(): void
|
||||
{
|
||||
$logA = $this->createLog();
|
||||
$logB = $this->createLog();
|
||||
$qsoA = $this->createLogQso(['log_id' => $logA->id]);
|
||||
$this->createLogQso(['log_id' => $logB->id]);
|
||||
|
||||
$response = $this->getJson("/api/log-qsos?log_id={$logA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $qsoA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_log_qso(): void
|
||||
{
|
||||
$qso = $this->createLogQso();
|
||||
|
||||
$response = $this->getJson("/api/log-qsos/{$qso->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $qso->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_log_qso(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$log = $this->createLog();
|
||||
|
||||
$createResponse = $this->postJson('/api/log-qsos', [
|
||||
'log_id' => $log->id,
|
||||
'my_call' => 'OK1ABC',
|
||||
'dx_call' => 'OK2ABC',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$qsoId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/log-qsos/{$qsoId}", [
|
||||
'dx_call' => 'OK9XYZ',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $qsoId]);
|
||||
|
||||
$this->deleteJson("/api/log-qsos/{$qsoId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_log_qso(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$log = $this->createLog();
|
||||
|
||||
$this->postJson('/api/log-qsos', [
|
||||
'log_id' => $log->id,
|
||||
'my_call' => 'OK1ABC',
|
||||
'dx_call' => 'OK2ABC',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
119
tests/Feature/Logs/LogQsoTableTest.php
Normal file
119
tests/Feature/Logs/LogQsoTableTest.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Logs;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogQsoTableTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_qso_table_uses_latest_succeeded_non_claimed_run_by_default(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
|
||||
$qsoA = $this->createLogQso([
|
||||
'log_id' => $log->id,
|
||||
'qso_index' => 1,
|
||||
'dx_call' => 'OK1AAA',
|
||||
]);
|
||||
$qsoB = $this->createLogQso([
|
||||
'log_id' => $log->id,
|
||||
'qso_index' => 2,
|
||||
'dx_call' => 'OK1BBB',
|
||||
]);
|
||||
|
||||
$claimedRun = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rules_version' => 'CLAIMED',
|
||||
'status' => 'SUCCEEDED',
|
||||
]);
|
||||
$this->createQsoResult([
|
||||
'evaluation_run_id' => $claimedRun->id,
|
||||
'log_qso_id' => $qsoA->id,
|
||||
'error_code' => 'DUP',
|
||||
]);
|
||||
|
||||
$officialRun = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rules_version' => 'OFFICIAL',
|
||||
'status' => 'SUCCEEDED',
|
||||
]);
|
||||
$this->createQsoResult([
|
||||
'evaluation_run_id' => $officialRun->id,
|
||||
'log_qso_id' => $qsoA->id,
|
||||
'error_code' => 'OK',
|
||||
'penalty_points' => 5,
|
||||
]);
|
||||
$this->createQsoOverride([
|
||||
'evaluation_run_id' => $officialRun->id,
|
||||
'log_qso_id' => $qsoB->id,
|
||||
'forced_status' => 'AUTO',
|
||||
'reason' => 'Manual override',
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/logs/{$log->id}/qso-table");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['evaluation_run_id' => $officialRun->id]);
|
||||
|
||||
$rows = collect($response->json('data'));
|
||||
$this->assertCount(2, $rows);
|
||||
|
||||
$rowA = $rows->firstWhere('id', $qsoA->id);
|
||||
$rowB = $rows->firstWhere('id', $qsoB->id);
|
||||
|
||||
$this->assertSame('OK1AAA', $rowA['dx_call']);
|
||||
$this->assertSame('OK', $rowA['result']['error_code']);
|
||||
$this->assertSame(5, $rowA['result']['penalty_points']);
|
||||
$this->assertNull($rowA['override']);
|
||||
|
||||
$this->assertSame('OK1BBB', $rowB['dx_call']);
|
||||
$this->assertNull($rowB['result']);
|
||||
$this->assertSame('Manual override', $rowB['override']['reason']);
|
||||
}
|
||||
|
||||
public function test_qso_table_respects_explicit_evaluation_run_id(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
|
||||
$qso = $this->createLogQso([
|
||||
'log_id' => $log->id,
|
||||
'qso_index' => 1,
|
||||
]);
|
||||
|
||||
$claimedRun = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rules_version' => 'CLAIMED',
|
||||
'status' => 'SUCCEEDED',
|
||||
]);
|
||||
$this->createQsoResult([
|
||||
'evaluation_run_id' => $claimedRun->id,
|
||||
'log_qso_id' => $qso->id,
|
||||
'error_code' => 'DUP',
|
||||
]);
|
||||
|
||||
$officialRun = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rules_version' => 'OFFICIAL',
|
||||
'status' => 'SUCCEEDED',
|
||||
]);
|
||||
$this->createQsoResult([
|
||||
'evaluation_run_id' => $officialRun->id,
|
||||
'log_qso_id' => $qso->id,
|
||||
'error_code' => 'OK',
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/logs/{$log->id}/qso-table?evaluation_run_id={$claimedRun->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['evaluation_run_id' => $claimedRun->id]);
|
||||
|
||||
$rows = collect($response->json('data'));
|
||||
$row = $rows->firstWhere('id', $qso->id);
|
||||
$this->assertSame('DUP', $row['result']['error_code']);
|
||||
}
|
||||
}
|
||||
73
tests/Feature/News/NewsPostControllerTest.php
Normal file
73
tests/Feature/News/NewsPostControllerTest.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\News;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class NewsPostControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_only_published_by_default(): void
|
||||
{
|
||||
$published = $this->createNewsPost();
|
||||
$unpublished = $this->createNewsPost(['is_published' => false, 'published_at' => null]);
|
||||
|
||||
$response = $this->getJson('/api/news');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $published->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertFalse(in_array($unpublished->id, $ids, true));
|
||||
}
|
||||
|
||||
public function test_show_returns_404_for_unpublished(): void
|
||||
{
|
||||
$news = $this->createNewsPost(['is_published' => false, 'published_at' => null]);
|
||||
|
||||
$this->getJson("/api/news/{$news->slug}")
|
||||
->assertStatus(404);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_news(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
|
||||
$createResponse = $this->postJson('/api/news', [
|
||||
'title' => ['cs' => 'Novinka', 'en' => 'News'],
|
||||
'content' => ['cs' => 'Obsah', 'en' => 'Content'],
|
||||
'excerpt' => ['cs' => 'Krátce', 'en' => 'Short'],
|
||||
'is_published' => true,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$slug = $createResponse->json('slug');
|
||||
|
||||
$updateResponse = $this->putJson("/api/news/{$slug}", [
|
||||
'title' => ['cs' => 'Novinka 2', 'en' => 'News 2'],
|
||||
'content' => ['cs' => 'Obsah', 'en' => 'Content'],
|
||||
'excerpt' => ['cs' => 'Krátce', 'en' => 'Short'],
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonStructure(['slug']);
|
||||
|
||||
$updatedSlug = $updateResponse->json('slug');
|
||||
|
||||
$this->deleteJson("/api/news/{$updatedSlug}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_news(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
|
||||
$this->postJson('/api/news', [
|
||||
'title' => ['cs' => 'Novinka', 'en' => 'News'],
|
||||
'content' => ['cs' => 'Obsah', 'en' => 'Content'],
|
||||
'excerpt' => ['cs' => 'Krátce', 'en' => 'Short'],
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
90
tests/Feature/Results/LogOverrideControllerTest.php
Normal file
90
tests/Feature/Results/LogOverrideControllerTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Results;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogOverrideControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_log_overrides(): void
|
||||
{
|
||||
$override = $this->createLogOverride();
|
||||
|
||||
$response = $this->getJson('/api/log-overrides');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $override->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_evaluation_run(): void
|
||||
{
|
||||
$runA = $this->createEvaluationRun();
|
||||
$runB = $this->createEvaluationRun();
|
||||
$overrideA = $this->createLogOverride(['evaluation_run_id' => $runA->id]);
|
||||
$this->createLogOverride(['evaluation_run_id' => $runB->id]);
|
||||
|
||||
$response = $this->getJson("/api/log-overrides?evaluation_run_id={$runA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $overrideA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_log_override(): void
|
||||
{
|
||||
$override = $this->createLogOverride();
|
||||
|
||||
$response = $this->getJson("/api/log-overrides/{$override->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $override->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_override(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun();
|
||||
$log = $this->createLog(['round_id' => $run->round_id]);
|
||||
|
||||
$createResponse = $this->postJson('/api/log-overrides', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'forced_log_status' => 'CHECK',
|
||||
'reason' => 'Test důvod',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$overrideId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/log-overrides/{$overrideId}", [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'forced_log_status' => 'OK',
|
||||
'reason' => 'Aktualizace',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $overrideId]);
|
||||
|
||||
$this->deleteJson("/api/log-overrides/{$overrideId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_override(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$run = $this->createEvaluationRun();
|
||||
$log = $this->createLog(['round_id' => $run->round_id]);
|
||||
|
||||
$this->postJson('/api/log-overrides', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'forced_log_status' => 'CHECK',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
141
tests/Feature/Results/LogResultControllerTest.php
Normal file
141
tests/Feature/Results/LogResultControllerTest.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Results;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LogResultControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_filters_by_evaluation_run(): void
|
||||
{
|
||||
$runA = $this->createEvaluationRun();
|
||||
$runB = $this->createEvaluationRun();
|
||||
$logA = $this->createLog(['round_id' => $runA->round_id]);
|
||||
$logB = $this->createLog(['round_id' => $runB->round_id]);
|
||||
$resultA = $this->createLogResult([
|
||||
'evaluation_run_id' => $runA->id,
|
||||
'log_id' => $logA->id,
|
||||
]);
|
||||
$this->createLogResult([
|
||||
'evaluation_run_id' => $runB->id,
|
||||
'log_id' => $logB->id,
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/log-results?evaluation_run_id={$runA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $resultA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_index_resolves_claimed_run_for_round(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
$run = $this->createEvaluationRun([
|
||||
'round_id' => $round->id,
|
||||
'rules_version' => 'CLAIMED',
|
||||
]);
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
$result = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/log-results?round_id={$round->id}&status=CLAIMED");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $result->id]);
|
||||
}
|
||||
|
||||
public function test_index_resolves_auto_result_type_from_round(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
$run = $this->createEvaluationRun(['round_id' => $round->id]);
|
||||
$round->update(['official_evaluation_run_id' => $run->id]);
|
||||
$log = $this->createLog(['round_id' => $round->id]);
|
||||
$result = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/log-results?round_id={$round->id}&result_type=AUTO");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $result->id]);
|
||||
}
|
||||
|
||||
public function test_index_only_ok_filters_by_callsign(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
$run = $this->createEvaluationRun(['round_id' => $round->id]);
|
||||
|
||||
$logOk = $this->createLog([
|
||||
'round_id' => $round->id,
|
||||
'pcall' => 'OK1ABC',
|
||||
]);
|
||||
$logOther = $this->createLog([
|
||||
'round_id' => $round->id,
|
||||
'pcall' => 'DL1ABC',
|
||||
]);
|
||||
$resultOk = $this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logOk->id,
|
||||
]);
|
||||
$this->createLogResult([
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $logOther->id,
|
||||
]);
|
||||
|
||||
$response = $this->getJson("/api/log-results?evaluation_run_id={$run->id}&round_id={$round->id}&only_ok=1");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $resultOk->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_log_result(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun();
|
||||
$log = $this->createLog(['round_id' => $run->round_id]);
|
||||
|
||||
$createResponse = $this->postJson('/api/log-results', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
'claimed_qso_count' => 10,
|
||||
'claimed_score' => 100,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$resultId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/log-results/{$resultId}", [
|
||||
'claimed_score' => 200,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $resultId]);
|
||||
|
||||
$this->deleteJson("/api/log-results/{$resultId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_log_result(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$run = $this->createEvaluationRun();
|
||||
$log = $this->createLog(['round_id' => $run->round_id]);
|
||||
|
||||
$this->postJson('/api/log-results', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_id' => $log->id,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
90
tests/Feature/Results/QsoOverrideControllerTest.php
Normal file
90
tests/Feature/Results/QsoOverrideControllerTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Results;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class QsoOverrideControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_qso_overrides(): void
|
||||
{
|
||||
$override = $this->createQsoOverride();
|
||||
|
||||
$response = $this->getJson('/api/qso-overrides');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $override->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_evaluation_run(): void
|
||||
{
|
||||
$runA = $this->createEvaluationRun();
|
||||
$runB = $this->createEvaluationRun();
|
||||
$overrideA = $this->createQsoOverride(['evaluation_run_id' => $runA->id]);
|
||||
$this->createQsoOverride(['evaluation_run_id' => $runB->id]);
|
||||
|
||||
$response = $this->getJson("/api/qso-overrides?evaluation_run_id={$runA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $overrideA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_qso_override(): void
|
||||
{
|
||||
$override = $this->createQsoOverride();
|
||||
|
||||
$response = $this->getJson("/api/qso-overrides/{$override->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $override->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_override(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun();
|
||||
$logQso = $this->createLogQso();
|
||||
|
||||
$createResponse = $this->postJson('/api/qso-overrides', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'forced_status' => 'VALID',
|
||||
'reason' => 'Test důvod',
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$overrideId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/qso-overrides/{$overrideId}", [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'forced_status' => 'INVALID',
|
||||
'reason' => 'Aktualizace',
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $overrideId]);
|
||||
|
||||
$this->deleteJson("/api/qso-overrides/{$overrideId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_override(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$run = $this->createEvaluationRun();
|
||||
$logQso = $this->createLogQso();
|
||||
|
||||
$this->postJson('/api/qso-overrides', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'forced_status' => 'VALID',
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
85
tests/Feature/Results/QsoResultControllerTest.php
Normal file
85
tests/Feature/Results/QsoResultControllerTest.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Results;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class QsoResultControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_qso_results(): void
|
||||
{
|
||||
$result = $this->createQsoResult();
|
||||
|
||||
$response = $this->getJson('/api/qso-results');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $result->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_evaluation_run(): void
|
||||
{
|
||||
$runA = $this->createEvaluationRun();
|
||||
$runB = $this->createEvaluationRun();
|
||||
$resultA = $this->createQsoResult(['evaluation_run_id' => $runA->id]);
|
||||
$this->createQsoResult(['evaluation_run_id' => $runB->id]);
|
||||
|
||||
$response = $this->getJson("/api/qso-results?evaluation_run_id={$runA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $resultA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_qso_result(): void
|
||||
{
|
||||
$result = $this->createQsoResult();
|
||||
|
||||
$response = $this->getJson("/api/qso-results/{$result->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $result->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_qso_result(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$run = $this->createEvaluationRun();
|
||||
$logQso = $this->createLogQso();
|
||||
|
||||
$createResponse = $this->postJson('/api/qso-results', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_qso_id' => $logQso->id,
|
||||
'points' => 50,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$resultId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/qso-results/{$resultId}", [
|
||||
'points' => 75,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $resultId]);
|
||||
|
||||
$this->deleteJson("/api/qso-results/{$resultId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_qso_result(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$run = $this->createEvaluationRun();
|
||||
$logQso = $this->createLogQso();
|
||||
|
||||
$this->postJson('/api/qso-results', [
|
||||
'evaluation_run_id' => $run->id,
|
||||
'log_qso_id' => $logQso->id,
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
104
tests/Feature/Rounds/RoundControllerTest.php
Normal file
104
tests/Feature/Rounds/RoundControllerTest.php
Normal file
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Rounds;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RoundControllerTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_index_returns_rounds(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
|
||||
$response = $this->getJson('/api/rounds');
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $round->id]);
|
||||
}
|
||||
|
||||
public function test_index_can_filter_by_contest(): void
|
||||
{
|
||||
$contestA = $this->createContest();
|
||||
$contestB = $this->createContest();
|
||||
$roundA = $this->createRound(['contest_id' => $contestA->id]);
|
||||
$this->createRound(['contest_id' => $contestB->id]);
|
||||
|
||||
$response = $this->getJson("/api/rounds?contest_id={$contestA->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $roundA->id]);
|
||||
|
||||
$ids = collect($response->json('data'))->pluck('id')->all();
|
||||
$this->assertCount(1, $ids);
|
||||
}
|
||||
|
||||
public function test_show_returns_round(): void
|
||||
{
|
||||
$round = $this->createRound();
|
||||
|
||||
$response = $this->getJson("/api/rounds/{$round->id}");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $round->id]);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_update_and_delete_round(): void
|
||||
{
|
||||
$this->actingAsAdmin();
|
||||
$contest = $this->createContest();
|
||||
$ruleSet = $this->createRuleSet();
|
||||
$start = now()->addDay();
|
||||
$end = (clone $start)->addHours(2);
|
||||
$deadline = (clone $end)->addDays(2);
|
||||
|
||||
$createResponse = $this->postJson('/api/rounds', [
|
||||
'contest_id' => $contest->id,
|
||||
'rule_set_id' => $ruleSet->id,
|
||||
'name' => ['cs' => 'Kolo 1', 'en' => 'Round 1'],
|
||||
'description' => ['cs' => 'Popis', 'en' => 'Description'],
|
||||
'start_time' => $start->toDateTimeString(),
|
||||
'end_time' => $end->toDateTimeString(),
|
||||
'logs_deadline' => $deadline->toDateTimeString(),
|
||||
'is_active' => true,
|
||||
]);
|
||||
|
||||
$createResponse->assertStatus(201);
|
||||
$roundId = $createResponse->json('id');
|
||||
|
||||
$updateResponse = $this->putJson("/api/rounds/{$roundId}", [
|
||||
'contest_id' => $contest->id,
|
||||
'name' => ['cs' => 'Kolo 1B', 'en' => 'Round 1B'],
|
||||
'description' => ['cs' => 'Popis', 'en' => 'Description'],
|
||||
'start_time' => $start->toDateTimeString(),
|
||||
'end_time' => $end->toDateTimeString(),
|
||||
'logs_deadline' => $deadline->toDateTimeString(),
|
||||
'is_active' => false,
|
||||
]);
|
||||
|
||||
$updateResponse->assertStatus(200)
|
||||
->assertJsonFragment(['id' => $roundId]);
|
||||
|
||||
$this->deleteJson("/api/rounds/{$roundId}")
|
||||
->assertStatus(204);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_create_round(): void
|
||||
{
|
||||
$this->actingAsUser();
|
||||
$contest = $this->createContest();
|
||||
$start = now()->addDay();
|
||||
$end = (clone $start)->addHours(2);
|
||||
$deadline = (clone $end)->addDays(2);
|
||||
|
||||
$this->postJson('/api/rounds', [
|
||||
'contest_id' => $contest->id,
|
||||
'name' => ['cs' => 'Kolo 1', 'en' => 'Round 1'],
|
||||
'start_time' => $start->toDateTimeString(),
|
||||
'end_time' => $end->toDateTimeString(),
|
||||
'logs_deadline' => $deadline->toDateTimeString(),
|
||||
])->assertStatus(403);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user