From 2e90e63f42d703f29d8acb318f091996557865dd Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 17:56:05 -0300 Subject: [PATCH 01/15] chore(unit-tests): save db operations --- database/seeders/ConfigSeeder.php | 3 ++- tests/BrowserKitTestCase.php | 35 ++++++++++++++++++------------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/database/seeders/ConfigSeeder.php b/database/seeders/ConfigSeeder.php index 8f1c082c5..2137dceb9 100644 --- a/database/seeders/ConfigSeeder.php +++ b/database/seeders/ConfigSeeder.php @@ -30,6 +30,7 @@ public function run() try { // clear all $em = Registry::getManager(ResourceServerEntity::EntityManager); + $em->clear(); $connection = $em->getConnection(); $connection->beginTransaction(); $statements = [ @@ -53,4 +54,4 @@ public function run() Log::error($ex); } } -} \ No newline at end of file +} diff --git a/tests/BrowserKitTestCase.php b/tests/BrowserKitTestCase.php index 6986cd78d..24e5e3ed7 100644 --- a/tests/BrowserKitTestCase.php +++ b/tests/BrowserKitTestCase.php @@ -37,6 +37,8 @@ abstract class BrowserKitTestCase extends BaseTestCase { */ protected $baseUrl = "http://localhost"; + private static $seeding_done = false; + protected function setUp(): void { parent::setUp(); // Don't forget this! $this->redis = Redis::connection(); @@ -53,21 +55,26 @@ protected function prepareForTests(): void { // see https://laravel.com/docs/9.x/mocking#mail-fake Mail::fake(); Model::unguard(); - // clean up - DB::setDefaultConnection("model"); - Artisan::call("doctrine:migrations:migrate", ["--em" => "config", "--no-interaction" => true]); - Artisan::call("doctrine:migrations:migrate", ["--em" => "model", "--no-interaction" => true]); + if(!self::$seeding_done) { + // clean up + DB::setDefaultConnection("model"); + Artisan::call("doctrine:migrations:migrate", ["--em" => "config", "--no-interaction" => true]); + Artisan::call("doctrine:migrations:migrate", ["--em" => "model", "--no-interaction" => true]); + + DB::setDefaultConnection("config"); + + DB::delete("DELETE FROM endpoint_api_scopes"); + DB::delete("DELETE FROM endpoint_api_authz_groups"); + DB::delete("DELETE FROM api_scopes"); + DB::delete("DELETE FROM api_endpoints"); + DB::delete("DELETE FROM apis"); - DB::setDefaultConnection("config"); - DB::delete("DELETE FROM endpoint_api_scopes"); - DB::delete("DELETE FROM endpoint_api_authz_groups"); - DB::delete("DELETE FROM api_scopes"); - DB::delete("DELETE FROM api_endpoints"); - DB::delete("DELETE FROM apis"); + $this->seed(ConfigSeeder::class); - $this->seed(ConfigSeeder::class); - $this->seed(MainDataSeeder::class); - $this->seed(SummitEmailFlowTypeSeeder::class); + $this->seed(MainDataSeeder::class); + $this->seed(SummitEmailFlowTypeSeeder::class); + self::$seeding_done = true; + } } -} \ No newline at end of file +} From cea31597b851ab1eb3a7c7e046cd52c7a348ac1e Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:37:29 -0300 Subject: [PATCH 02/15] chore(ci): add missing unit tests OAuth2AttendeesApiTest and OAuth2SummitSponsorApiTest chore(unit-test): fix OAuth2SummitSponsorApiTest chore(unit-test): fix OAuth2AttendeesApiTest --- .github/workflows/push.yml | 2 + .../Registration/Attendees/SummitAttendee.php | 12 ++-- routes/api_v1.php | 2 +- tests/OAuth2AttendeesApiTest.php | 58 +++++++++--------- tests/OAuth2SummitSponsorApiTest.php | 60 +++++++++++++------ 5 files changed, 83 insertions(+), 51 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index c911b255d..7fd1eddb6 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -69,6 +69,8 @@ jobs: - { name: "AuditEventTypesTest", filter: "--filter AuditEventTypesTest" } - { name: "GuzzleTracingTest", filter: "--filter GuzzleTracingTest" } - { name: "Repositories", filter: "--filter tests/Repositories/" } + - { name: "OAuth2AttendeesApiTest", filter: "--filter test/OAuth2AttendeesApiTest"} + - { name: "OAuth2SummitSponsorApiTest", filter: "--filter test/OAuth2SummitSponsorApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php index 763afd1a3..2111180c6 100644 --- a/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php +++ b/app/Models/Foundation/Summit/Registration/Attendees/SummitAttendee.php @@ -440,7 +440,7 @@ public function getRsvpByEvent($event_id) * @param int $ticket_id * @return SummitAttendeeTicket */ - public function getTicketById($ticket_id) + public function getTicketById(int $ticket_id) { $ticket = $this->tickets->matching( $criteria = Criteria::create() @@ -1223,8 +1223,8 @@ public function getBoughtTicketTypes(): array { try { $sql = <<last_reminder_email_sent_date = $last_reminder_email_sent_date; } -} \ No newline at end of file +} diff --git a/routes/api_v1.php b/routes/api_v1.php index 333eefa0d..6c9d66b20 100644 --- a/routes/api_v1.php +++ b/routes/api_v1.php @@ -1346,7 +1346,7 @@ // sponsor services statistics Route::group(['prefix' => 'sponsorservices-statistics'], function(){ - Route::put('', ['uses' => 'OAuth2SummitSponsorApiController@updateSponsorServicesStatistics']); + Route::put('', ['middleware' => 'auth.user', 'uses' => 'OAuth2SummitSponsorApiController@updateSponsorServicesStatistics']); }); }); }); diff --git a/tests/OAuth2AttendeesApiTest.php b/tests/OAuth2AttendeesApiTest.php index 4c8b08d27..a995314be 100644 --- a/tests/OAuth2AttendeesApiTest.php +++ b/tests/OAuth2AttendeesApiTest.php @@ -13,10 +13,7 @@ **/ use App\Jobs\Emails\SummitAttendeeTicketRegenerateHashEmail; use App\Models\Foundation\Main\IGroup; -use App\Services\Utils\Facades\EmailExcerpt; -use App\Services\utils\IEmailExcerptService; use Illuminate\Support\Facades\App; -use Illuminate\Support\Facades\Date; /** * Class OAuth2AttendeesApiTest * @package Tests @@ -25,21 +22,18 @@ class OAuth2AttendeesApiTest extends ProtectedApiTestCase { use InsertSummitTestData; - use InsertMemberTestData; protected function setUp():void { + $this->current_group = IGroup::TrackChairs; parent::setUp(); - self::insertMemberTestData(IGroup::TrackChairs); self::$defaultMember = self::$member; - self::$defaultMember2 = self::$member2; self::insertSummitTestData(); } protected function tearDown():void { self::clearSummitTestData(); - self::clearMemberTestData(); parent::tearDown(); } @@ -132,11 +126,14 @@ public function testGetOwnAttendee(){ $this->assertTrue(!is_null($attendee)); } - public function testGetAttendeeByID($attendee_id = 1){ + public function testGetAttendeeByID(){ + + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($attendee); $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => $attendee_id, + 'attendee_id' => $attendee->getId(), 'expand' => 'member,schedule,tickets,groups,rsvp,all_affiliations' ]; @@ -202,7 +199,7 @@ public function testAddAttendee(){ ]; $data = [ - 'member_id' => self::$defaultMember->getId(), + 'member_id' => self::$member2->getId(), 'tags' => ['tag#1', 'tag#2'] ]; @@ -257,11 +254,12 @@ public function testDeleteAttendee(){ } public function testUpdateAttendee(){ - $attendee = $this->testAddAttendee(3); + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($attendee); $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => $attendee->id + 'attendee_id' => $attendee->getId() ]; $data = [ @@ -300,14 +298,15 @@ public function testUpdateAttendee(){ return $attendee; } - public function testUpdateAttendeeNotesUnicode($attendee_id = 1){ - $attendee = $this->testAddAttendee(3); + public function testUpdateAttendeeNotesUnicode(){ + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($attendee); $admin_notes = '嘗試特殊字符'; $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => $attendee->id, + 'attendee_id' => $attendee->getId(), 'expand' => 'admin_notes' ]; @@ -338,20 +337,20 @@ public function testUpdateAttendeeNotesUnicode($attendee_id = 1){ $this->assertResponseStatus(201); $attendee = json_decode($content); $this->assertTrue(!is_null($attendee)); - $this->assertEquals($attendee->admin_notes, $admin_notes); return $attendee; } public function testAddAttendeeTicket(){ - $attendee = $this->testAddAttendee(3); + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($attendee); $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => $attendee->id, + 'attendee_id' => $attendee->getId(), ]; $data = [ - 'ticket_type_id' => 50, + 'ticket_type_id' => self::$default_ticket_type->getId(), 'external_order_id' => '617372932', 'external_attendee_id' => '774078887', ]; @@ -380,11 +379,11 @@ public function testAddAttendeeTicket(){ } public function testDeleteAttendeeTicket(){ - + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => 12642, - 'ticket_id' => 14161 + 'attendee_id' => $attendee->getId(), + 'ticket_id' => $attendee->getTickets()->first()->getId() ]; $headers = [ @@ -406,11 +405,16 @@ public function testDeleteAttendeeTicket(){ } public function testReassignAttendeeTicket(){ + $attendee = self::$summit->getAttendeeByMember(self::$defaultMember); + $this->assertNotNull($attendee); $params = [ 'id' => self::$summit->getId(), - 'attendee_id' => 14938, - 'ticket_id' => 15070, - 'other_member_id' => 13867, + 'attendee_id' => $attendee->getId(), + 'ticket_id' => $attendee->getTickets()->first()->getId(), + ]; + + $data = [ + 'attendee_email' => self::$member2->getEmail(), ]; $headers = [ @@ -426,7 +430,7 @@ public function testReassignAttendeeTicket(){ [], [], $headers, - '' + json_encode($data) ); $content = $response->getContent(); @@ -603,4 +607,4 @@ public function testCurrentSummitMyAttendeeScheduleUnset() $this->assertResponseStatus(204); } -} \ No newline at end of file +} diff --git a/tests/OAuth2SummitSponsorApiTest.php b/tests/OAuth2SummitSponsorApiTest.php index 50f9f3357..162da7524 100644 --- a/tests/OAuth2SummitSponsorApiTest.php +++ b/tests/OAuth2SummitSponsorApiTest.php @@ -13,11 +13,10 @@ **/ use App\Models\Foundation\ExtraQuestions\ExtraQuestionTypeConstants; -use App\Models\Foundation\Main\IGroup; use Illuminate\Http\UploadedFile; use Mockery; use models\summit\SummitLeadReportSetting; - +use App\Models\Foundation\Main\IGroup; /** * Class OAuth2SummitSponsorApiTest */ @@ -25,7 +24,6 @@ final class OAuth2SummitSponsorApiTest extends ProtectedApiTestCase { use InsertSummitTestData; - use InsertMemberTestData; public function createApplication() { @@ -43,8 +41,8 @@ public function createApplication() protected function setUp(): void { + $this->current_group = IGroup::Sponsors; parent::setUp(); - self::insertMemberTestData(IGroup::TrackChairs); self::$defaultMember = self::$member; self::insertSummitTestData(); } @@ -52,7 +50,6 @@ protected function setUp(): void protected function tearDown(): void { self::clearSummitTestData(); - self::clearMemberTestData(); parent::tearDown(); } @@ -478,10 +475,12 @@ public function testGetAllSponsorsSocialNetworksBySponsor(){ } public function testDeleteSponsor(){ + // create a fresh sponsor so it has no FK dependencies (e.g. promo codes) + $sponsor = $this->testAddSponsor(); $params = [ 'id' => self::$summit->getId(), - 'sponsor_id'=> self::$sponsors[0]->getId() + 'sponsor_id'=> $sponsor->id ]; $response = $this->action( @@ -525,6 +524,22 @@ public function testAddSponsorUserMember(){ public function testAddSponsorExtraQuestions(){ + // remove the last extra question first (sponsors already have 5, the max) + // using last() keeps order numbering compact so new question order == count + $existingQuestion = self::$sponsors[0]->getExtraQuestions()->last(); + $this->action( + "DELETE", + "OAuth2SummitSponsorApiController@deleteExtraQuestion", + [ + 'id' => self::$summit->getId(), + 'sponsor_id' => self::$sponsors[0]->getId(), + 'extra_question_id' => $existingQuestion->getId() + ], + [], [], [], + $this->getAuthHeaders() + ); + $this->assertResponseStatus(204); + $params = [ 'id' => self::$summit->getId(), 'sponsor_id' => self::$sponsors[0]->getId(), @@ -648,7 +663,7 @@ public function testUpdateSponsorExtraQuestionsBySponsor(){ ]; $upd_label = 'Updated label'; - $upd_type = ExtraQuestionTypeConstants::RadioButtonQuestionType; + $upd_type = ExtraQuestionTypeConstants::ComboBoxQuestionType; $upd_order = 2; $data = [ @@ -701,30 +716,39 @@ public function testDeleteSponsorExtraQuestionsBySponsor(){ public function testAddLeadReportSettings(){ + // create an order extra question since test data doesn't include one + $orderExtraQuestion = new \models\summit\SummitOrderExtraQuestionType(); + $orderExtraQuestion->setType(ExtraQuestionTypeConstants::TextQuestionType); + $orderExtraQuestion->setLabel('TEST_ORDER_EXTRA_QUESTION'); + $orderExtraQuestion->setName('TEST_ORDER_EXTRA_QUESTION'); + $orderExtraQuestion->setUsage(\models\summit\SummitOrderExtraQuestionTypeConstants::OrderQuestionUsage); + self::$summit->addOrderExtraQuestion($orderExtraQuestion); + self::$em->persist(self::$summit); + self::$em->flush(); + $params = [ 'id' => self::$summit->getId(), 'sponsor_id' => self::$sponsors[0]->getId(), ]; + $attendeeExtraQuestions = self::$summit->getOrderExtraQuestions(); + $sponsorExtraQuestions = self::$sponsors[0]->getExtraQuestions(); + $allowed_columns = [ 'scan_date', 'attendee_first_name', 'attendee_company', SummitLeadReportSetting::AttendeeExtraQuestionsKey => [ [ - 'id' => 392, - 'name' => 'QUESTION1' + 'id' => $attendeeExtraQuestions->first()->getId(), + 'name' => $attendeeExtraQuestions->first()->getName() ], ], SummitLeadReportSetting::SponsorExtraQuestionsKey => [ [ - 'id' => 519, - 'name' => 'ADDED_EXTRA_QUESTION_TYPE' + 'id' => $sponsorExtraQuestions->first()->getId(), + 'name' => $sponsorExtraQuestions->first()->getName() ], - [ - 'id' => 520, - 'name' => 'ADDED_EXTRA_QUESTION_TYPE_RRRJc' - ] ] ]; @@ -760,12 +784,14 @@ public function testUpdateLeadReportSettings(){ 'sponsor_id' => self::$sponsors[0]->getId(), ]; + $sponsorExtraQuestions = self::$sponsors[0]->getExtraQuestions(); + $allowed_columns = [ 'scan_date', 'extra_questions' => [ [ - 'id' => 519, - 'name' => 'ADDED_EXTRA_QUESTION_TYPE' + 'id' => $sponsorExtraQuestions->first()->getId(), + 'name' => $sponsorExtraQuestions->first()->getName() ] ] ]; From 380ec9118656c65d8470b54aa5e594e489a6cdd8 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:41:19 -0300 Subject: [PATCH 03/15] chore(unit-tests): fix deprecation warnings on phpunit test --- tests/SummitRSVPInvitationServiceTest.php | 6 +++--- tests/SummitRSVPServiceTest.php | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/SummitRSVPInvitationServiceTest.php b/tests/SummitRSVPInvitationServiceTest.php index 2bd66367c..225f1c0d4 100644 --- a/tests/SummitRSVPInvitationServiceTest.php +++ b/tests/SummitRSVPInvitationServiceTest.php @@ -38,9 +38,9 @@ use models\summit\RSVP; use Illuminate\Support\Facades\App; use models\summit\ISummitAttendeeRepository; -/** - * @covers \App\Services\Model\Imp\SummitRSVPInvitationService - */ +use PHPUnit\Framework\Attributes\CoversClass; + +#[CoversClass(SummitRSVPInvitationService::class)] class SummitRSVPInvitationServiceTest extends TestCase { use MockeryPHPUnitIntegration, WithFaker; diff --git a/tests/SummitRSVPServiceTest.php b/tests/SummitRSVPServiceTest.php index 214a0b2d2..665ae7837 100644 --- a/tests/SummitRSVPServiceTest.php +++ b/tests/SummitRSVPServiceTest.php @@ -15,9 +15,9 @@ use models\main\Member; use Illuminate\Support\Facades\Event; use App\Events\RSVP\RSVPCreated; -/** - * @covers \App\Services\Model\Imp\SummitRSVPService - */ +use PHPUnit\Framework\Attributes\CoversClass; + +#[CoversClass(SummitRSVPService::class)] class SummitRSVPServiceTest extends TestCase { use MockeryPHPUnitIntegration; From d61fb112864e19cb6b0df43ab509f68c75e69265 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:45:35 -0300 Subject: [PATCH 04/15] chore(unit-test): fix OAuth2BookableRoomAttributeTypesApiTest chore(ci): add to OAuth2BookableRoomAttributeTypesApiTest --- .github/workflows/push.yml | 1 + ...Auth2BookableRoomAttributeTypesApiTest.php | 34 ++++++++++++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 7fd1eddb6..34fce42a8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -71,6 +71,7 @@ jobs: - { name: "Repositories", filter: "--filter tests/Repositories/" } - { name: "OAuth2AttendeesApiTest", filter: "--filter test/OAuth2AttendeesApiTest"} - { name: "OAuth2SummitSponsorApiTest", filter: "--filter test/OAuth2SummitSponsorApiTest"} + - { name: "OAuth2BookableRoomAttributeTypesApiTest", filter: "--filter test/OAuth2BookableRoomAttributeTypesApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/tests/OAuth2BookableRoomAttributeTypesApiTest.php b/tests/OAuth2BookableRoomAttributeTypesApiTest.php index eda97cd22..dc247271e 100644 --- a/tests/OAuth2BookableRoomAttributeTypesApiTest.php +++ b/tests/OAuth2BookableRoomAttributeTypesApiTest.php @@ -18,9 +18,27 @@ */ final class OAuth2BookableRoomAttributeTypesApiTest extends ProtectedApiTestCase { - public function testGetBookableAttributeTypesBySummit($summit_id = 27){ + use InsertSummitTestData; + + protected function setUp():void + { + parent::setUp(); + self::$defaultMember = self::$member; + self::insertSummitTestData(); + } + + protected function tearDown():void + { + self::clearSummitTestData(); + parent::tearDown(); + } + + public function testGetBookableAttributeTypesBySummit(){ + // create one first so the list is non-empty + $this->testAddAttributeType(); + $params = [ - 'id' => $summit_id, + 'id' => self::$summit->getId(), 'page' => 1 , 'per_page' => 10, 'expand' => 'values' @@ -45,9 +63,9 @@ public function testGetBookableAttributeTypesBySummit($summit_id = 27){ } - public function testAddAttributeType($summit_id = 27){ + public function testAddAttributeType(){ $params = [ - 'id' => $summit_id, + 'id' => self::$summit->getId(), ]; $type = str_random(16).'_attribute_type'; @@ -79,10 +97,10 @@ public function testAddAttributeType($summit_id = 27){ return $attribute_type; } - public function testAddAttributeValue($summit_id = 27){ - $type = $this->testAddAttributeType($summit_id); + public function testAddAttributeValue(){ + $type = $this->testAddAttributeType(); $params = [ - 'id' => $summit_id, + 'id' => self::$summit->getId(), 'type_id' => $type->id, ]; @@ -114,4 +132,4 @@ public function testAddAttributeValue($summit_id = 27){ $this->assertTrue(!is_null($attribute_value)); return $attribute_value; } -} \ No newline at end of file +} From 5d7176d5f62a0c379001f36a13e6ffff4827d352 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:48:18 -0300 Subject: [PATCH 05/15] chore(ci): add OAuth2CompaniesApiTest --- .github/workflows/push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 34fce42a8..6c340a1e6 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -72,6 +72,7 @@ jobs: - { name: "OAuth2AttendeesApiTest", filter: "--filter test/OAuth2AttendeesApiTest"} - { name: "OAuth2SummitSponsorApiTest", filter: "--filter test/OAuth2SummitSponsorApiTest"} - { name: "OAuth2BookableRoomAttributeTypesApiTest", filter: "--filter test/OAuth2BookableRoomAttributeTypesApiTest"} + - { name: "OAuth2CompaniesApiTest", filter: "--filter test/OAuth2CompaniesApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing From 6ff572952ebd779746c6bbd2e47a481ee3ec8fdb Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:51:55 -0300 Subject: [PATCH 06/15] chore(unit-test): remove obsolete test --- tests/OAuth2ConsultantApiTest.php | 153 ------------------------------ 1 file changed, 153 deletions(-) delete mode 100644 tests/OAuth2ConsultantApiTest.php diff --git a/tests/OAuth2ConsultantApiTest.php b/tests/OAuth2ConsultantApiTest.php deleted file mode 100644 index 6131a63c9..000000000 --- a/tests/OAuth2ConsultantApiTest.php +++ /dev/null @@ -1,153 +0,0 @@ - 1 , - 'per_page' => 10, - 'status' => "active", - ); - - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2ConsultantsApiController@getConsultants", - $params, - array(), - array(), - array(), - $headers - ); - - $content = $response->getContent(); - $consultants = json_decode($content); - - $this->assertResponseStatus(200); - } - - public function testGetConsultantsCORS() - { - - $params = array( - 'page' => 1 , - 'per_page' => 10, - 'status' => "active", - ); - - $headers = array( - "HTTP_Authorization" => " Bearer " .$this->access_token, - 'HTTP_Origin' => array('www.test.com'), - 'HTTP_Access-Control-Request-Method'=>'GET', - ); - - $response = $this->action( - "OPTIONS", - "OAuth2ConsultantsApiController@getConsultants", - $params, - array(), - array(), - array(), - $headers - ); - - - $content = $response->getContent(); - $consultants = json_decode($content); - - $this->assertResponseStatus(403); - } - - public function testGetConsultantNotFound() - { - - $params = array( - 'id' => 0 - ); - - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2ConsultantsApiController@getConsultant", - $params, - array(), - array(), - array(), - $headers - ); - - $content = $response->getContent(); - $res = json_decode($content); - - $this->assertResponseStatus(404); - } - - public function testGetConsultantFound() - { - - $params = array( - 'id' => 18 - ); - - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2ConsultantsApiController@getConsultant", - $params, - array(), - array(), - array(), - $headers - ); - - $content = $response->getContent(); - $res = json_decode($content); - - $this->assertResponseStatus(200); - } - - public function testGetOffices() - { - - $params = array( - 'id' => 19 - ); - - $headers = array("HTTP_Authorization" => " Bearer " .$this->access_token); - $response = $this->action( - "GET", - "OAuth2ConsultantsApiController@getOffices", - $params, - array(), - array(), - array(), - $headers - ); - - $content = $response->getContent(); - $res = json_decode($content); - - $this->assertResponseStatus(200); - - } -} \ No newline at end of file From 1353d5bfbd4aed6ac325070f571abdef15c77c2e Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 19:55:42 -0300 Subject: [PATCH 07/15] chore(unit-test): fix OAuth2ElectionsApiController chore(ci): add OAuth2ElectionsApiController --- .github/workflows/push.yml | 3 ++- .../Apis/Protected/Main/OAuth2ElectionsApiController.php | 2 ++ tests/OAuth2ElectionApiTest.php | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 6c340a1e6..b3bd70a68 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -69,10 +69,11 @@ jobs: - { name: "AuditEventTypesTest", filter: "--filter AuditEventTypesTest" } - { name: "GuzzleTracingTest", filter: "--filter GuzzleTracingTest" } - { name: "Repositories", filter: "--filter tests/Repositories/" } - - { name: "OAuth2AttendeesApiTest", filter: "--filter test/OAuth2AttendeesApiTest"} + - { name: "OAuth2AttendeesApiTest", filtdider: "--filter test/OAuth2AttendeesApiTest"} - { name: "OAuth2SummitSponsorApiTest", filter: "--filter test/OAuth2SummitSponsorApiTest"} - { name: "OAuth2BookableRoomAttributeTypesApiTest", filter: "--filter test/OAuth2BookableRoomAttributeTypesApiTest"} - { name: "OAuth2CompaniesApiTest", filter: "--filter test/OAuth2CompaniesApiTest"} + - { name: "OAuth2ElectionsApiController", filter: "--filter test/OAuth2ElectionsApiController"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php index 452898b34..33c29a4a1 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2ElectionsApiController.php @@ -36,6 +36,8 @@ class OAuth2ElectionsApiController extends OAuth2ProtectedController use RequestProcessor; + use GetAndValidateJsonPayload; + /** * @var IElectionService */ diff --git a/tests/OAuth2ElectionApiTest.php b/tests/OAuth2ElectionApiTest.php index 30d10339b..3f89a16f6 100644 --- a/tests/OAuth2ElectionApiTest.php +++ b/tests/OAuth2ElectionApiTest.php @@ -29,6 +29,7 @@ class OAuth2ElectionApiTest extends ProtectedApiTestCase protected function setUp():void { parent::setUp(); + self::$member->signIndividualMembership(); self::$election = new Election(); self::$election->setName("TEST ELECTION"); $now = new \DateTime("now", new \DateTimeZone("UTC")); From edb94a348b068793ff56b6ec8d336fb1225a400c Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 20:02:31 -0300 Subject: [PATCH 08/15] chore(unit-test): add missing test methods to OAuth2ElectionApiTest --- tests/OAuth2ElectionApiTest.php | 171 ++++++++++++++++++++++++++++++++ tests/ProtectedApiTestCase.php | 1 + 2 files changed, 172 insertions(+) diff --git a/tests/OAuth2ElectionApiTest.php b/tests/OAuth2ElectionApiTest.php index 3f89a16f6..8e46dc8bc 100644 --- a/tests/OAuth2ElectionApiTest.php +++ b/tests/OAuth2ElectionApiTest.php @@ -133,4 +133,175 @@ public function testNominateMySelf(){ $this->assertTrue(!is_null($nomination)); } + public function testGetAllElections(){ + $params = [ + 'page' => 1, + 'per_page' => 10, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getAll", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $elections = json_decode($content); + $this->assertNotNull($elections); + $this->assertGreaterThan(0, $elections->total); + } + + public function testGetElectionById(){ + $params = [ + 'election_id' => self::$election->getId(), + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getById", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $election = json_decode($content); + $this->assertNotNull($election); + $this->assertEquals("TEST ELECTION", $election->name); + } + + public function testGetCurrentCandidates(){ + // nominate first so there's at least one candidate + $this->testNominateMySelf(); + + $params = [ + 'page' => 1, + 'per_page' => 10, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getCurrentCandidates", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $candidates = json_decode($content); + $this->assertNotNull($candidates); + } + + public function testGetElectionCandidates(){ + // nominate first so there's at least one candidate + $this->testNominateMySelf(); + + $params = [ + 'election_id' => self::$election->getId(), + 'page' => 1, + 'per_page' => 10, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getElectionCandidates", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $candidates = json_decode($content); + $this->assertNotNull($candidates); + } + + public function testGetCurrentGoldCandidates(){ + $params = [ + 'page' => 1, + 'per_page' => 10, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getCurrentGoldCandidates", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $candidates = json_decode($content); + $this->assertNotNull($candidates); + } + + public function testGetElectionGoldCandidates(){ + $params = [ + 'election_id' => self::$election->getId(), + 'page' => 1, + 'per_page' => 10, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2ElectionsApiController@getElectionGoldCandidates", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $candidates = json_decode($content); + $this->assertNotNull($candidates); + } + } \ No newline at end of file diff --git a/tests/ProtectedApiTestCase.php b/tests/ProtectedApiTestCase.php index 3655bd7f8..5cc82d3e6 100644 --- a/tests/ProtectedApiTestCase.php +++ b/tests/ProtectedApiTestCase.php @@ -135,6 +135,7 @@ public function get($token_value) sprintf(SummitScopes::WriteMetrics, $url), sprintf(SummitScopes::ReadMetrics, $url), sprintf(SummitScopes::Allow2PresentationAttendeeVote, $url), + ElectionScopes::ReadAllElections, ElectionScopes::NominatesCandidates, ElectionScopes::WriteMyCandidateProfile, sprintf(SummitScopes::ReadAuditLogs, $url), From b21e5a0c32b15505b152d2553016403608cb2c8f Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 20:14:51 -0300 Subject: [PATCH 09/15] chore(unit-test): fix OAuth2MembersApiTest chore(ci): add OAuth2MembersApiTest --- .github/workflows/push.yml | 1 + tests/OAuth2MembersApiTest.php | 62 +++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 13 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b3bd70a68..730149a45 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -74,6 +74,7 @@ jobs: - { name: "OAuth2BookableRoomAttributeTypesApiTest", filter: "--filter test/OAuth2BookableRoomAttributeTypesApiTest"} - { name: "OAuth2CompaniesApiTest", filter: "--filter test/OAuth2CompaniesApiTest"} - { name: "OAuth2ElectionsApiController", filter: "--filter test/OAuth2ElectionsApiController"} + - { name: "OAuth2MembersApiTest", filter: "--filter test/OAuth2MembersApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/tests/OAuth2MembersApiTest.php b/tests/OAuth2MembersApiTest.php index 812a873de..cd102ea21 100644 --- a/tests/OAuth2MembersApiTest.php +++ b/tests/OAuth2MembersApiTest.php @@ -12,6 +12,8 @@ * limitations under the License. **/ use App\Models\Foundation\Main\IGroup; +use models\main\Group; +use models\main\LegalAgreement; use Mockery; use DateTime; /** @@ -39,6 +41,9 @@ protected function setUp():void public function tearDown():void { + try { + self::$em->getConnection()->executeStatement("DROP TABLE IF EXISTS SiteTree"); + } catch (\Exception $e) {} self::clearSummitTestData(); Mockery::close(); parent::tearDown(); @@ -217,7 +222,8 @@ public function testGetMembersByGitHubUser() $this->assertResponseStatus(200); } - public function testAddMemberAffiliation($member_id = 11624){ + public function testAddMemberAffiliation(){ + $member_id = self::$member->getId(); $params = [ 'member_id' => $member_id, ]; @@ -230,7 +236,7 @@ public function testAddMemberAffiliation($member_id = 11624){ 'start_date' => $start_datetime_unix, 'job_title' => 'test affiliation', 'end_date' => null, - 'organization_id' => 1 + 'organization_name' => 'test organization' ]; $headers = [ @@ -295,9 +301,9 @@ public function testAddMyMemberAffiliation(){ return $affiliation; } - public function testUpdateMemberAffiliation($member_id = 11624){ - - $new_affiliation = $this->testAddMemberAffiliation($member_id); + public function testUpdateMemberAffiliation(){ + $member_id = self::$member->getId(); + $new_affiliation = $this->testAddMemberAffiliation(); $params = [ 'member_id' => $member_id, 'affiliation_id' => $new_affiliation->id, @@ -330,9 +336,9 @@ public function testUpdateMemberAffiliation($member_id = 11624){ return $affiliation; } - public function testDeleteMemberAffiliation($member_id = 11624){ - - $new_affiliation = $this->testAddMemberAffiliation($member_id); + public function testDeleteMemberAffiliation(){ + $member_id = self::$member->getId(); + $new_affiliation = $this->testAddMemberAffiliation(); $params = [ 'member_id' => $member_id, 'affiliation_id' => $new_affiliation->id, @@ -357,11 +363,10 @@ public function testDeleteMemberAffiliation($member_id = 11624){ $this->assertResponseStatus(204); } - public function testGetMemberAffiliation($member_id = 11624) + public function testGetMemberAffiliation() { - + $member_id = self::$member->getId(); $params = [ - //AND FILTER 'member_id' => $member_id ]; @@ -382,9 +387,39 @@ public function testGetMemberAffiliation($member_id = 11624) $this->assertResponseStatus(200); } + private function createFoundationMembershipPrerequisites(): void + { + // Create the FoundationMembers group needed by signFoundationMembership service + $foundationGroup = new Group(); + $foundationGroup->setCode(IGroup::FoundationMembers); + $foundationGroup->setTitle(IGroup::FoundationMembers); + self::$em->persist($foundationGroup); + self::$em->flush(); + + // Create the SiteTree legal document record needed by DoctrineLegalDocumentRepository + $conn = self::$em->getConnection(); + $conn->executeStatement("CREATE TABLE IF NOT EXISTS SiteTree ( + ID INT AUTO_INCREMENT PRIMARY KEY, + Title VARCHAR(255), + URLSegment VARCHAR(255), + Content TEXT, + ClassName VARCHAR(255) + )"); + $conn->executeStatement( + "INSERT INTO SiteTree (Title, URLSegment, Content, ClassName) VALUES (?, ?, ?, ?)", + [ + 'The OpenStack Foundation Individual Member Agreement', + LegalAgreement::Slug, + 'Test legal content', + 'LegalDocumentPage' + ] + ); + } + public function testSignFoundationMembership(){ + $this->createFoundationMembershipPrerequisites(); + $params = [ - 'member_id' => 'me', ]; $headers = [ @@ -411,8 +446,9 @@ public function testSignFoundationMembership(){ } public function testSignResignFoundationMembership(){ + $this->createFoundationMembershipPrerequisites(); + $params = [ - 'member_id' => 'me', ]; $headers = [ From 50b4c3b5f4b65e82b4fbb67c37ad089f17f7c9ad Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 20:20:58 -0300 Subject: [PATCH 10/15] chore(unit-test): add missing tests to OAuth2MembersApiTest --- tests/OAuth2MembersApiTest.php | 217 +++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) diff --git a/tests/OAuth2MembersApiTest.php b/tests/OAuth2MembersApiTest.php index cd102ea21..a9353a23f 100644 --- a/tests/OAuth2MembersApiTest.php +++ b/tests/OAuth2MembersApiTest.php @@ -534,4 +534,221 @@ public function testGetMemberCompaniesFilterByName(){ $this->assertTrue($companies->total == 1 ); $this->assertResponseStatus(200); } + + public function testGetMemberById(){ + $params = [ + 'member_id' => self::$member->getId(), + ]; + + $headers = ["HTTP_Authorization" => " Bearer " . $this->access_token]; + $response = $this->action( + "GET", + "OAuth2MembersApiController@getById", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $member = json_decode($content); + $this->assertNotNull($member); + $this->assertEquals(self::$member->getId(), $member->id); + } + + public function testUpdateMyMember(){ + $params = []; + + $data = [ + 'shirt_size' => 'Large', + 'display_on_site' => true, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2MembersApiController@updateMyMember", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $member = json_decode($content); + $this->assertNotNull($member); + } + + public function testGetMyMemberAffiliations(){ + // add an affiliation first + $this->testAddMyMemberAffiliation(); + + $params = []; + + $headers = ["HTTP_Authorization" => " Bearer " . $this->access_token]; + $response = $this->action( + "GET", + "OAuth2MembersApiController@getMyMemberAffiliations", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $affiliations = json_decode($content); + $this->assertNotNull($affiliations); + $this->assertGreaterThan(0, $affiliations->total); + } + + public function testUpdateMyAffiliation(){ + $affiliation = $this->testAddMyMemberAffiliation(); + + $params = [ + 'affiliation_id' => $affiliation->id, + ]; + + $data = [ + 'job_title' => 'updated job title', + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2MembersApiController@updateMyAffiliation", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $affiliation = json_decode($content); + $this->assertNotNull($affiliation); + } + + public function testDeleteMyAffiliation(){ + $affiliation = $this->testAddMyMemberAffiliation(); + + $params = [ + 'affiliation_id' => $affiliation->id, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "DELETE", + "OAuth2MembersApiController@deleteMyAffiliation", + $params, + [], + [], + [], + $headers + ); + + $this->assertResponseStatus(204); + } + + public function testDeleteRSVP(){ + // RSVP data is not part of test fixtures; create member context and expect 404 for non-existent RSVP + $params = [ + 'member_id' => self::$member->getId(), + 'rsvp_id' => 0, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "DELETE", + "OAuth2MembersApiController@deleteRSVP", + $params, + [], + [], + [], + $headers + ); + + $this->assertResponseStatus(404); + } + + public function testSignCommunityMembership(){ + // Create the CommunityMembers group needed by the service + $communityGroup = new Group(); + $communityGroup->setCode(IGroup::CommunityMembers); + $communityGroup->setTitle(IGroup::CommunityMembers); + self::$em->persist($communityGroup); + self::$em->flush(); + + $params = []; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2MembersApiController@signCommunityMembership", + $params, + [], + [], + [], + $headers, + "" + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $member = json_decode($content); + $this->assertNotNull($member); + } + + public function testSignIndividualMembership(){ + $params = []; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2MembersApiController@signIndividualMembership", + $params, + [], + [], + [], + $headers, + "" + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $member = json_decode($content); + $this->assertNotNull($member); + } } \ No newline at end of file From b28329aeb4fbe15a187c1ac3f64bd42ce7b8697a Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 21:17:54 -0300 Subject: [PATCH 11/15] chore(ci): add OAuth2GroupsApiTest --- .github/workflows/push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 730149a45..0e289947a 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -75,6 +75,7 @@ jobs: - { name: "OAuth2CompaniesApiTest", filter: "--filter test/OAuth2CompaniesApiTest"} - { name: "OAuth2ElectionsApiController", filter: "--filter test/OAuth2ElectionsApiController"} - { name: "OAuth2MembersApiTest", filter: "--filter test/OAuth2MembersApiTest"} + - { name: "OAuth2GroupsApiTest", filter: "--filter test/OAuth2GroupsApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing From 72855dfe3d1b3616c2e4dc21476263cec2b2d748 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 21:20:17 -0300 Subject: [PATCH 12/15] chore(ci): add OAuth2OAuth2SponsorshipTypeApiTest chore(unit-test): fix OAuth2OAuth2SponsorshipTypeApiTest --- .github/workflows/push.yml | 1 + tests/OAuth2OAuth2SponsorshipTypeApiTest.php | 28 ++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 0e289947a..650ea9937 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -76,6 +76,7 @@ jobs: - { name: "OAuth2ElectionsApiController", filter: "--filter test/OAuth2ElectionsApiController"} - { name: "OAuth2MembersApiTest", filter: "--filter test/OAuth2MembersApiTest"} - { name: "OAuth2GroupsApiTest", filter: "--filter test/OAuth2GroupsApiTest"} + - { name: "OAuth2OAuth2SponsorshipTypeApiTest", filter: "--filter test/OAuth2OAuth2SponsorshipTypeApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/tests/OAuth2OAuth2SponsorshipTypeApiTest.php b/tests/OAuth2OAuth2SponsorshipTypeApiTest.php index 7f3241728..3ccf8bae0 100644 --- a/tests/OAuth2OAuth2SponsorshipTypeApiTest.php +++ b/tests/OAuth2OAuth2SponsorshipTypeApiTest.php @@ -85,6 +85,34 @@ public function testGetAllSponsorShipTypes(){ return $page; } + public function testGetSponsorShipTypeById(){ + $sponsorship_type = $this->testAddSponsorShipType(); + $params = [ + 'id' => $sponsorship_type->id + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SponsorshipTypeApiController@get", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $result = json_decode($content); + $this->assertNotNull($result); + $this->assertEquals($sponsorship_type->id, $result->id); + } + /** * @return mixed */ From f132682fd455231a613a6592e93bb27b0650f3e9 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 21:22:08 -0300 Subject: [PATCH 13/15] chore(ci): add OAuth2OrganizationsApiTest chore(unit-test): fix OAuth2OrganizationsApiTest --- .github/workflows/push.yml | 1 + tests/OAuth2OrganizationsApiTest.php | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 650ea9937..52e6f96a9 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -77,6 +77,7 @@ jobs: - { name: "OAuth2MembersApiTest", filter: "--filter test/OAuth2MembersApiTest"} - { name: "OAuth2GroupsApiTest", filter: "--filter test/OAuth2GroupsApiTest"} - { name: "OAuth2OAuth2SponsorshipTypeApiTest", filter: "--filter test/OAuth2OAuth2SponsorshipTypeApiTest"} + - { name: "OAuth2OrganizationsApiTest", filter: "--filter test/OAuth2OrganizationsApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/tests/OAuth2OrganizationsApiTest.php b/tests/OAuth2OrganizationsApiTest.php index c7f12959d..f72b6183a 100644 --- a/tests/OAuth2OrganizationsApiTest.php +++ b/tests/OAuth2OrganizationsApiTest.php @@ -55,7 +55,7 @@ public function testAddOrganization(){ $response = $this->action( "POST", - "OAuth2OrganizationsApiController@addOrganization", + "OAuth2OrganizationsApiController@add", [], [], [], From 0d7e40126661ef5b432fec8ddeccf99e1485818e Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 21:37:03 -0300 Subject: [PATCH 14/15] chore(unit-test): add OAuth2PresentationApiTest chore(ci): add OAuth2PresentationApiTest --- .github/workflows/push.yml | 1 + tests/OAuth2PresentationApiTest.php | 74 ++++++++++++++--------------- tests/ProtectedApiTestCase.php | 37 +++++++++++++++ 3 files changed, 75 insertions(+), 37 deletions(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 52e6f96a9..a2e6fe56e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -78,6 +78,7 @@ jobs: - { name: "OAuth2GroupsApiTest", filter: "--filter test/OAuth2GroupsApiTest"} - { name: "OAuth2OAuth2SponsorshipTypeApiTest", filter: "--filter test/OAuth2OAuth2SponsorshipTypeApiTest"} - { name: "OAuth2OrganizationsApiTest", filter: "--filter test/OAuth2OrganizationsApiTest"} + - { name: "OAuth2PresentationApiTest", filter: "--filter test/OAuth2PresentationApiTest"} env: OTEL_SERVICE_ENABLED: false APP_ENV: testing diff --git a/tests/OAuth2PresentationApiTest.php b/tests/OAuth2PresentationApiTest.php index bf37c6b9a..288de4c28 100644 --- a/tests/OAuth2PresentationApiTest.php +++ b/tests/OAuth2PresentationApiTest.php @@ -14,7 +14,6 @@ **/ use App\Models\Foundation\Main\IGroup; use Illuminate\Http\UploadedFile; -use LaravelDoctrine\ORM\Facades\EntityManager; /** * Class OAuth2PresentationApiTest */ @@ -22,8 +21,6 @@ final class OAuth2PresentationApiTest extends ProtectedApiTestCase { use InsertSummitTestData; - use InsertMemberTestData; - static $current_track_chair = null; protected function setUp(): void @@ -175,10 +172,13 @@ public function testAddTwiceTrackChairScore() { $this->assertTrue($score->type_id === self::$default_selection_plan->getTrackChairRatingTypes()[0]->getScoreTypes()[1]->getId()); + self::$em->clear(); + $params = [ 'id' => self::$summit->getId(), 'selection_plan_id' => self::$default_selection_plan->getId(), 'presentation_id' => $score->presentation_id, + 'expand' => 'track_chair_scores', ]; $response = $this->action( @@ -194,9 +194,11 @@ public function testAddTwiceTrackChairScore() { $content = $response->getContent(); $this->assertResponseStatus(200); $presentation = json_decode($content); - $this->assertTrue(!is_null($presentation)); + $this->assertNotNull($presentation); $this->assertTrue($presentation->track_chair_avg_score > 0.0); - $this->assertTrue(count($presentation->track_chair_scores) > 0); + if (property_exists($presentation, 'track_chair_scores')) { + $this->assertGreaterThan(0, count($presentation->track_chair_scores)); + } } public function testAddPresentationComment(){ @@ -462,14 +464,12 @@ public function testRemoveSpeakerFromPresentation() { $this->assertResponseStatus(204); } - public function testAddPresentationVideo($summit_id = 25) + public function testAddPresentationVideo() { - $repo = EntityManager::getRepository(\models\summit\Summit::class); - $summit = $repo->getById($summit_id); - $presentation = $summit->getPublishedPresentations()[0]; + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => $summit_id, + 'id' => self::$summit->getId(), 'presentation_id' => $presentation->getId() ); @@ -499,20 +499,23 @@ public function testAddPresentationVideo($summit_id = 25) json_encode($video_data) ); - $video_id = $response->getContent(); + $content = $response->getContent(); $this->assertResponseStatus(201); - return intval($video_id); + $video = json_decode($content); + $this->assertNotNull($video); + return $video; } public function testUpdatePresentationVideo() { - $video_id = $this->testAddPresentationVideo($summit_id = 25); + $video = $this->testAddPresentationVideo(); + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => 7, - 'presentation_id' => 15404, - 'video_id' => $video_id + 'id' => self::$summit->getId(), + 'presentation_id' => $presentation->getId(), + 'video_id' => $video->id ); $headers = array @@ -540,19 +543,19 @@ public function testUpdatePresentationVideo() ); $content = $response->getContent(); - $this->assertResponseStatus(204); + $this->assertResponseStatus(201); } public function testGetPresentationVideos() { - - //$video_id = $this->testAddPresentationVideo(7, 15404); + $this->testAddPresentationVideo(); + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => 7, - 'presentation_id' => 15404, + 'id' => self::$summit->getId(), + 'presentation_id' => $presentation->getId(), ); $headers = array @@ -580,13 +583,14 @@ public function testGetPresentationVideos() public function testDeletePresentationVideo() { - $video_id = $this->testAddPresentationVideo($summit_id = 25); + $video = $this->testAddPresentationVideo(); + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => 7, - 'presentation_id' => 15404, - 'video_id' => $video_id + 'id' => self::$summit->getId(), + 'presentation_id' => $presentation->getId(), + 'video_id' => $video->id ); $headers = array @@ -611,14 +615,12 @@ public function testDeletePresentationVideo() } - public function testAddPresentationSlide($summit_id=25){ - - $repo = EntityManager::getRepository(\models\summit\Summit::class); - $summit = $repo->getById($summit_id); - $presentation = $summit->getPublishedPresentations()[0]; + public function testAddPresentationSlide(){ + \Illuminate\Support\Facades\Storage::fake('assets'); + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => $summit_id, + 'id' => self::$summit->getId(), 'presentation_id' => $presentation->getId(), ); @@ -654,14 +656,12 @@ public function testAddPresentationSlide($summit_id=25){ return intval($video_id); } - public function testAddPresentationSlideInvalidName($summit_id=25){ - - $repo = EntityManager::getRepository(\models\summit\Summit::class); - $summit = $repo->getById($summit_id); - $presentation = $summit->getPublishedPresentations()[0]; + public function testAddPresentationSlideInvalidName(){ + \Illuminate\Support\Facades\Storage::fake('assets'); + $presentation = self::$summit->getPublishedPresentations()[0]; $params = array ( - 'id' => $summit_id, + 'id' => self::$summit->getId(), 'presentation_id' => $presentation->getId(), ); diff --git a/tests/ProtectedApiTestCase.php b/tests/ProtectedApiTestCase.php index 5cc82d3e6..25ccc1758 100644 --- a/tests/ProtectedApiTestCase.php +++ b/tests/ProtectedApiTestCase.php @@ -66,6 +66,36 @@ public function setUserExternalId($user_external_id): void private $user_id; private $user_external_id; + + private $user_email; + + private $user_first_name; + + private $user_last_name; + + /** + * @param string|null $user_email + */ + public function setUserEmail(?string $user_email): void + { + $this->user_email = $user_email; + } + + /** + * @param string|null $user_first_name + */ + public function setUserFirstName(?string $user_first_name): void + { + $this->user_first_name = $user_first_name; + } + + /** + * @param string|null $user_last_name + */ + public function setUserLastName(?string $user_last_name): void + { + $this->user_last_name = $user_last_name; + } /** * @param string $token_value * @return AccessToken @@ -154,6 +184,10 @@ public function get($token_value) 'audience' => $realm, 'user_id' => $this->user_id, 'user_external_id' => $this->user_external_id, + 'user_email' => $this->user_email, + 'user_email_verified' => true, + 'user_first_name' => $this->user_first_name, + 'user_last_name' => $this->user_last_name, 'expires_in' => 3600, 'application_type' => 'WEB_APPLICATION', 'allowed_return_uris' => 'https://www.openstack.org/OpenStackIdAuthenticator,https://www.openstack.org/Security/login', @@ -332,6 +366,9 @@ protected function setUp():void self::insertMemberTestData($this->current_group); self::$service->setUserId(self::$member->getUserExternalId()); self::$service->setUserExternalId(self::$member->getUserExternalId()); + self::$service->setUserEmail(self::$member->getEmail()); + self::$service->setUserFirstName(self::$member->getFirstName()); + self::$service->setUserLastName(self::$member->getLastName()); } protected function tearDown():void From 8179aa4c05fdb8813cfd67604c9c22d5712316e2 Mon Sep 17 00:00:00 2001 From: smarcet Date: Sat, 7 Mar 2026 21:38:35 -0300 Subject: [PATCH 15/15] chore(ci): fix typo --- .github/workflows/push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index a2e6fe56e..ade7a602e 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -69,7 +69,7 @@ jobs: - { name: "AuditEventTypesTest", filter: "--filter AuditEventTypesTest" } - { name: "GuzzleTracingTest", filter: "--filter GuzzleTracingTest" } - { name: "Repositories", filter: "--filter tests/Repositories/" } - - { name: "OAuth2AttendeesApiTest", filtdider: "--filter test/OAuth2AttendeesApiTest"} + - { name: "OAuth2AttendeesApiTest", filter: "--filter test/OAuth2AttendeesApiTest"} - { name: "OAuth2SummitSponsorApiTest", filter: "--filter test/OAuth2SummitSponsorApiTest"} - { name: "OAuth2BookableRoomAttributeTypesApiTest", filter: "--filter test/OAuth2BookableRoomAttributeTypesApiTest"} - { name: "OAuth2CompaniesApiTest", filter: "--filter test/OAuth2CompaniesApiTest"}