From 5f146212032146d372ac72b58db988e6c4563a90 Mon Sep 17 00:00:00 2001 From: Brinda Sasikumar Date: Wed, 22 May 2024 16:46:22 -0400 Subject: [PATCH] [Debt] Improve seeding for RoD (#10290) * Add pools for RoD testing * add EX-03 * add EX classification * add EX03 * extract out skill,questions creation * fix poolskill * add more pool data * add personas * fix linting * Revert "fix linting" This reverts commit b33243a0aeb7bd2cd6fd6925449bc604ac1f5713. * fix linting * fix linting * add missing assessment results nuances * fix pool tests * Fix ScreeningQuestionsTest * fix tests * fix linting * remove duplicate code * fix the citizenship status for the personas * fix pools & spacing between them * fix test * fix linting * clean up PoolTestSeeder * code clean up * fix line formatting * fix duplicate code * fix pool naming * fix pool naming * improve pool seeder performance * add priority no * fix linting * add stream * Revert "improve pool seeder performance" This reverts commit d97a986a257c87d92a808738c186d4488b7d0f78. * restore the lost changes * remove unnecessary code * fix linting * restore the last changes * fix linting * fix after latest main merge in * applyToAllPools should be private * try the flaky test with sep user instance * fix the test * try split the tests into 2 * lint fix --------- Co-authored-by: vd1992 <40485260+vd1992@users.noreply.github.com> --- api/app/Enums/GenericJobTitleKey.php | 1 + api/app/Models/PoolSkill.php | 2 + api/database/factories/PoolFactory.php | 193 ++++++++++----- api/database/factories/UserFactory.php | 49 ++-- .../seeders/AssessmentResultTestSeeder.php | 139 +++++++++++ api/database/seeders/ClassificationSeeder.php | 13 + api/database/seeders/DatabaseSeeder.php | 1 + .../seeders/GenericJobTitleSeeder.php | 13 +- .../seeders/PoolCandidateTestSeeder.php | 177 ++++++++++++++ api/database/seeders/PoolRandomSeeder.php | 2 +- api/database/seeders/PoolTestSeeder.php | 229 +++++++++++++++--- api/storage/app/lighthouse-schema.graphql | 1 + api/tests/Feature/AssessmentResultTest.php | 2 +- api/tests/Feature/AssessmentStepTest.php | 4 +- .../Feature/GeneralQuestionResponsesTest.php | 2 +- api/tests/Feature/GeneralQuestionTest.php | 2 +- api/tests/Feature/PoolApplicationTest.php | 39 ++- api/tests/Feature/PoolTest.php | 6 + api/tests/Feature/ScreeningQuestionsTest.php | 4 +- api/tests/Feature/SnapshotTest.php | 1 + 20 files changed, 750 insertions(+), 130 deletions(-) create mode 100644 api/database/seeders/PoolCandidateTestSeeder.php diff --git a/api/app/Enums/GenericJobTitleKey.php b/api/app/Enums/GenericJobTitleKey.php index 0c0461edc04..a2d2a1ea9bf 100644 --- a/api/app/Enums/GenericJobTitleKey.php +++ b/api/app/Enums/GenericJobTitleKey.php @@ -10,4 +10,5 @@ enum GenericJobTitleKey case TECHNICAL_ADVISOR_IT03; case SENIOR_ADVISOR_IT04; case MANAGER_IT04; + case EXECUTIVE_EX03; } diff --git a/api/app/Models/PoolSkill.php b/api/app/Models/PoolSkill.php index 3f352531315..0fd83db28e2 100644 --- a/api/app/Models/PoolSkill.php +++ b/api/app/Models/PoolSkill.php @@ -27,6 +27,8 @@ class PoolSkill extends Model protected $keyType = 'string'; + protected $fillable = ['skill_id', 'type', 'required_skill_level']; + protected static function boot() { parent::boot(); diff --git a/api/database/factories/PoolFactory.php b/api/database/factories/PoolFactory.php index 485c52bc3a5..9462615e60f 100644 --- a/api/database/factories/PoolFactory.php +++ b/api/database/factories/PoolFactory.php @@ -15,7 +15,6 @@ use App\Models\Classification; use App\Models\GeneralQuestion; use App\Models\Pool; -use App\Models\PoolSkill; use App\Models\ScreeningQuestion; use App\Models\Skill; use App\Models\Team; @@ -72,57 +71,90 @@ public function definition() ]; } - public function configure() + public function withPoolSkills($essentialCount, $nonEssentialCount) { - return $this->afterCreating(function (Pool $pool) { + return $this->afterCreating(function (Pool $pool) use ($essentialCount, $nonEssentialCount) { $skills = Skill::inRandomOrder()->limit(10)->get(); + //slice first set of skills as essential skills + $essentialSkills = $skills->slice(0, $essentialCount); + //slice next set of skills as non essential skills + $nonEssentialSkills = $skills->slice($essentialCount, $nonEssentialCount); + $this->createPoolSkills($pool, $essentialSkills, PoolSkillType::ESSENTIAL->name); + $this->createPoolSkills($pool, $nonEssentialSkills, PoolSkillType::NONESSENTIAL->name); + }); + } - foreach ($skills->slice(0, 5) as $skill) { - $poolSkill = new PoolSkill(); - $poolSkill->skill_id = $skill->id; - $poolSkill->type = PoolSkillType::ESSENTIAL->name; - $poolSkill->required_skill_level = $this->faker->randomElement(array_column(SkillLevel::cases(), 'name')); - $pool->poolSkills()->save($poolSkill); - } - foreach ($skills->slice(5, 5) as $skill) { - $poolSkill = new PoolSkill(); - $poolSkill->skill_id = $skill->id; - $poolSkill->type = PoolSkillType::NONESSENTIAL->name; - $poolSkill->required_skill_level = $this->faker->randomElement(array_column(SkillLevel::cases(), 'name')); - $pool->poolSkills()->save($poolSkill); - } + private function createPoolSkills($pool, $skills, $type) + { + // for each skills create it as pool skill + foreach ($skills as $skill) { + $pool->poolSkills()->create([ + 'skill_id' => $skill->id, + 'type' => $type, + 'required_skill_level' => $this->faker->randomElement(array_column(SkillLevel::cases(), 'name')), + ]); + } + } - GeneralQuestion::factory() - ->count(3) - ->sequence( - ['sort_order' => 1], - ['sort_order' => 2], - ['sort_order' => 3], - ) - ->create(['pool_id' => $pool->id]); - - $screeningAssessmentStep = AssessmentStep::factory()->create( - [ - 'pool_id' => $pool->id, - 'type' => AssessmentStepType::SCREENING_QUESTIONS_AT_APPLICATION->name, - ] - ); - ScreeningQuestion::factory() - ->count(3) - ->sequence( - ['sort_order' => 1], - ['sort_order' => 2], - ['sort_order' => 3], - ) - ->create( - [ - 'pool_id' => $pool->id, - 'assessment_step_id' => $screeningAssessmentStep->id, - ] - ); + public function withQuestions($generalQuestionsCount, $screeningQuestionsCount) + { + return $this->afterCreating(function (Pool $pool) use ($generalQuestionsCount, $screeningQuestionsCount) { + $this->createQuestions(GeneralQuestion::class, $generalQuestionsCount, $pool->id); + $this->createQuestions(ScreeningQuestion::class, $screeningQuestionsCount, $pool->id, $this->createAssessmentStepWithPoolSkills($pool, AssessmentStepType::SCREENING_QUESTIONS_AT_APPLICATION->name)->id); }); } + private function createAssessmentStep($pool, $type) + { + return AssessmentStep::factory() + ->create([ + 'pool_id' => $pool->id, + 'type' => $type, + ]); + } + + private function createAssessmentStepWithPoolSkills($pool, $type) + { + $step = $this->createAssessmentStep($pool, $type); + $poolSkillArray = $pool->poolSkills->pluck('id')->toArray(); + $step->poolSkills()->sync($poolSkillArray); + + return $step; + } + + public function withAssessmentStepAndWithoutPoolSkills() + { + return $this->afterCreating(function (Pool $pool) { + $step = $this->createAssessmentStep($pool, AssessmentStepType::SCREENING_QUESTIONS_AT_APPLICATION->name); + + return $step; + }); + } + + private function createQuestions($factory, $count, $poolId, $assessmentStepId = null) + { + $sequence = []; + for ($i = 1; $i <= $count; $i++) { + $sequence[] = ['sort_order' => $i]; + } + if ($assessmentStepId !== null) { + $factory::factory() + ->count($count) + ->sequence(...$sequence) + ->create([ + 'pool_id' => $poolId, + 'assessment_step_id' => $assessmentStepId, + ]); + } else { + $factory::factory() + ->count($count) + ->sequence(...$sequence) + ->create([ + 'pool_id' => $poolId, + ]); + } + } + /** * Indicate that the pool is draft. */ @@ -130,7 +162,26 @@ public function draft(): Factory { return $this->state(function (array $attributes) { // the base state is draft already - return []; + $hasSpecialNote = $this->faker->boolean(); + $isRemote = $this->faker->boolean(); + + return [ + 'operational_requirements' => $this->faker->randomElements(array_column(OperationalRequirement::cases(), 'name'), 2), + 'key_tasks' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], + 'your_impact' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], + 'what_to_expect' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], + 'what_to_expect_admission' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], + 'about_us' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], + 'security_clearance' => $this->faker->randomElement(array_column(SecurityStatus::cases(), 'name')), + 'advertisement_language' => $this->faker->randomElement(array_column(PoolLanguage::cases(), 'name')), + 'advertisement_location' => ! $isRemote ? ['en' => $this->faker->country(), 'fr' => $this->faker->country()] : null, + 'special_note' => ! $hasSpecialNote ? ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'] : null, + 'is_remote' => $this->faker->boolean, + 'stream' => $this->faker->randomElement(PoolStream::cases())->name, + 'process_number' => $this->faker->word(), + 'publishing_group' => $this->faker->randomElement(array_column(PublishingGroup::cases(), 'name')), + 'opportunity_length' => $this->faker->randomElement(array_column(PoolOpportunityLength::cases(), 'name')), + ]; }); } @@ -146,7 +197,6 @@ public function published(): Factory return [ // published in the past, closes in the future 'published_at' => $this->faker->dateTimeBetween('-30 days', '-1 days'), - 'operational_requirements' => $this->faker->randomElements(array_column(OperationalRequirement::cases(), 'name'), 2), 'key_tasks' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], 'your_impact' => ['en' => $this->faker->paragraph().' EN', 'fr' => $this->faker->paragraph().' FR'], @@ -217,16 +267,47 @@ public function candidatesAvailableInSearch() * * @return \Illuminate\Database\Eloquent\Factories\Factory */ - public function withAssessments() + public function withAssessments($noOfAssessmentSteps = 2) { - return $this->afterCreating(function (Pool $pool) { - $step1 = AssessmentStep::factory() - ->create(['pool_id' => $pool->id]); - $step2 = AssessmentStep::factory() - ->create(['pool_id' => $pool->id]); - $poolSkillArray = $pool->poolSkills->pluck('id')->toArray(); - $step1->poolSkills()->sync(array_slice($poolSkillArray, 0, 5, true)); - $step2->poolSkills()->sync(array_slice($poolSkillArray, 5, 5, true)); + return $this->afterCreating(function (Pool $pool, $noOfAssessmentSteps) { + $steps = []; + $this->createAssessmentStepWithPoolSkills($pool, AssessmentStepType::SCREENING_QUESTIONS_AT_APPLICATION->name); + + for ($i = 0; $i < $noOfAssessmentSteps - 1; $i++) { + $steps[$i] = $this->createAssessmentStepWithPoolSkills($pool, $this->faker->randomElement(array_column(AssessmentStepType::cases(), 'name'))->name); + } }); } + + // Add a single assessment step to the pool for the given assessment step type + public function WithAssessmentStep(AssessmentStepType $type) + { + return $this->afterCreating(function (Pool $pool) use ($type) { + + $step = $this->createAssessmentStep($pool, $type->name); + $poolSkillArray = $pool->poolSkills()->pluck('id')->toArray(); + $step->poolSkills()->sync($poolSkillArray); + + return $step; + }); + } + + /** + * Create a new pool or get an existing pool based on the given attributes. + * + * @param array $attributes The attributes of the pool. + * @return Pool The created or existing pool. + */ + public function createOrGetExisting($attributes = []) + { + $pool = Pool::where('name->en', $attributes['name']['en']) + ->where('name->fr', $attributes['name']['fr']) + ->first(); + + if ($pool) { + return $pool; + } + + return $this->create($attributes); + } } diff --git a/api/database/factories/UserFactory.php b/api/database/factories/UserFactory.php index f1e9bab6531..b9654cf87b9 100644 --- a/api/database/factories/UserFactory.php +++ b/api/database/factories/UserFactory.php @@ -129,19 +129,35 @@ public function definition() ]; } - public function withSkillsAndExperiences($count = 10) + private function createExperienceAndSyncSkills($user, $skills) { + $experienceFactories = [ + AwardExperience::factory(['user_id' => $user->id]), + CommunityExperience::factory(['user_id' => $user->id]), + EducationExperience::factory(['user_id' => $user->id]), + PersonalExperience::factory(['user_id' => $user->id]), + WorkExperience::factory(['user_id' => $user->id]), + ]; + + $experience = $this->faker->randomElement($experienceFactories)->create(); + $skillsForExperience = $this->faker->randomElements($skills, $this->faker->numberBetween(1, $skills->count())); + $syncDataExperience = array_map(function ($skill) { + return ['id' => $skill->id, 'details' => $this->faker->text()]; + }, $skillsForExperience); + + $experience->syncSkills($syncDataExperience); + } + + public function withSkillsAndExperiences($count = 10, $skills = []) + { + if (empty($skills)) { + $allSkills = Skill::select('id')->inRandomOrder()->take($count)->get(); + } else { + $allSkills = $skills; + } $allSkills = Skill::select('id')->inRandomOrder()->take($count)->get(); return $this->afterCreating(function (User $user) use ($count, $allSkills) { - $experienceFactories = [ - AwardExperience::factory(['user_id' => $user->id]), - CommunityExperience::factory(['user_id' => $user->id]), - EducationExperience::factory(['user_id' => $user->id]), - PersonalExperience::factory(['user_id' => $user->id]), - WorkExperience::factory(['user_id' => $user->id]), - ]; - $skillSequence = $allSkills->shuffle()->map(fn ($skill) => ['skill_id' => $skill['id']])->toArray(); $userSkills = UserSkill::factory($count)->for($user) @@ -149,20 +165,7 @@ public function withSkillsAndExperiences($count = 10) ->create(); $skills = $userSkills->map(fn ($us) => $us->skill); - // create two experiences and attach a random number of skills to each through experience_skill pivot - $experienceOne = $this->faker->randomElement($experienceFactories)->create(); - $skillsForExperienceOne = $this->faker->randomElements($skills, $this->faker->numberBetween(1, $skills->count())); - $syncDataExperienceOne = array_map(function ($skill) { - return ['id' => $skill->id, 'details' => $this->faker->text()]; - }, $skillsForExperienceOne); - $experienceOne->syncSkills($syncDataExperienceOne); - - $experienceTwo = $this->faker->randomElement($experienceFactories)->create(); - $skillsForExperienceTwo = $this->faker->randomElements($skills, $this->faker->numberBetween(1, $skills->count())); - $syncDataExperienceTwo = array_map(function ($skill) { - return ['id' => $skill->id, 'details' => $this->faker->text()]; - }, $skillsForExperienceTwo); - $experienceTwo->syncSkills($syncDataExperienceTwo); + $this->createExperienceAndSyncSkills($user, $skills); }); } diff --git a/api/database/seeders/AssessmentResultTestSeeder.php b/api/database/seeders/AssessmentResultTestSeeder.php index 4258b9be2f4..ab3310d653e 100644 --- a/api/database/seeders/AssessmentResultTestSeeder.php +++ b/api/database/seeders/AssessmentResultTestSeeder.php @@ -2,11 +2,16 @@ namespace Database\Seeders; +use App\Enums\AssessmentDecision; +use App\Enums\AssessmentDecisionLevel; +use App\Enums\AssessmentResultJustification; use App\Enums\AssessmentResultType; +use App\Enums\PoolSkillType; use App\Models\AssessmentResult; use App\Models\AssessmentStep; use App\Models\Pool; use App\Models\PoolCandidate; +use App\Models\User; use Faker\Generator; use Illuminate\Container\Container; use Illuminate\Database\Seeder; @@ -67,5 +72,139 @@ public function run() 'pool_candidate_id' => $poolCandidate->id, 'pool_skill_id' => $dcmPoolSkills[1], ]); + + $publishedPool = Pool::select('id')->where('name->en', 'Published – Complex')->sole(); + $user1 = User::select('id')->where('first_name', 'Perfect')->sole(); + $poolCandidate1 = PoolCandidate::select('id')->where('user_id', $user1->id)->where('pool_id', $publishedPool->id)->sole(); + $assessmentStep = AssessmentStep::factory()->create([ + 'pool_id' => $publishedPool->id, + ]); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate1, + $publishedPool->poolSkills()->pluck('id')->toArray(), + $assessmentStep, + AssessmentDecisionLevel::ABOVE_REQUIRED->name, + [AssessmentResultJustification::EDUCATION_ACCEPTED_INFORMATION->name], + AssessmentDecision::SUCCESSFUL->name, + AssessmentResultType::EDUCATION); + + $user2 = User::select('id')->where('first_name', 'Barely qualified')->sole(); + $poolCandidate2 = PoolCandidate::select('id')->where('user_id', $user2->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate2, + $publishedPool->poolSkills()->where('type', PoolSkillType::ESSENTIAL->name)->pluck('id')->toArray(), + $assessmentStep, + AssessmentDecisionLevel::AT_REQUIRED->name, + [AssessmentResultJustification::EDUCATION_ACCEPTED_WORK_EXPERIENCE_EQUIVALENCY->name], + AssessmentDecision::SUCCESSFUL->name, + AssessmentResultType::SKILL); + + $user3 = User::select('id')->where('first_name', 'Try-hard')->sole(); + $poolCandidate3 = PoolCandidate::select('id')->where('user_id', $user3->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate3, + $publishedPool->poolSkills()->pluck('id')->toArray(), + $assessmentStep, + AssessmentDecisionLevel::ABOVE_REQUIRED->name, + [AssessmentResultJustification::EDUCATION_ACCEPTED_WORK_EXPERIENCE_EQUIVALENCY->name], + AssessmentDecision::SUCCESSFUL->name, + AssessmentResultType::SKILL); + + $user4 = User::select('id')->where('first_name', 'Absent')->sole(); + $poolCandidate4 = PoolCandidate::select('id')->where('user_id', $user4->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate4, + $publishedPool->poolSkills()->where('type', PoolSkillType::ESSENTIAL->name)->pluck('id')->toArray(), + $assessmentStep, AssessmentDecisionLevel::AT_REQUIRED->name, + [AssessmentResultJustification::EDUCATION_ACCEPTED_WORK_EXPERIENCE_EQUIVALENCY->name], + AssessmentDecision::HOLD->name, + AssessmentResultType::SKILL); + + $user5 = User::select('id')->where('first_name', 'Screened-out')->sole(); + $poolCandidate5 = PoolCandidate::select('id')->where('user_id', $user5->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate5, + $publishedPool->poolSkills()->where('type', PoolSkillType::ESSENTIAL->name)->pluck('id')->toArray(), + $assessmentStep, + AssessmentDecisionLevel::AT_REQUIRED->name, + [AssessmentResultJustification::EDUCATION_FAILED_NOT_RELEVANT->name, + AssessmentResultJustification::EDUCATION_FAILED_REQUIREMENT_NOT_MET->name], + AssessmentDecision::UNSUCCESSFUL->name, + AssessmentResultType::EDUCATION); + + $user6 = User::select('id')->where('first_name', 'Failed')->sole(); + $poolCandidate6 = PoolCandidate::select('id')->where('user_id', $user6->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate6, + $publishedPool->poolSkills()->pluck('id')->toArray(), $assessmentStep, + null, + [AssessmentResultJustification::EDUCATION_FAILED_REQUIREMENT_NOT_MET->name], + AssessmentDecision::UNSUCCESSFUL->name, + AssessmentResultType::EDUCATION); + + $user7 = User::select('id')->where('first_name', 'Barely')->sole(); + $poolCandidate7 = PoolCandidate::select('id')->where('user_id', $user7->id)->where('pool_id', $publishedPool->id)->sole(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate7, + null, + $assessmentStep, + null, + [AssessmentResultJustification::EDUCATION_ACCEPTED_WORK_EXPERIENCE_EQUIVALENCY->name], + AssessmentDecision::HOLD->name, + assessmentResultType::EDUCATION); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate7, + $publishedPool->poolSkills()->pluck('id')->toArray(), + $assessmentStep, + null, + [AssessmentResultJustification::SKILL_FAILED_INSUFFICIENTLY_DEMONSTRATED], + AssessmentDecision::HOLD->name, + assessmentResultType::SKILL); + + $user8 = User::select('id')->where('first_name', 'Unsuccessful')->sole(); + $poolCandidate8 = PoolCandidate::select('id')->where('user_id', $user8->id)->where('pool_id', $publishedPool->id)->sole(); + // select first essential skill from pool skills + $firstEssentialSkill = $publishedPool->poolSkills()->where('type', PoolSkillType::ESSENTIAL->name)->first(); + $this->assessSkillsWithLevelAndJustification( + $poolCandidate8, + [$firstEssentialSkill->id], + $assessmentStep, + null, + [AssessmentResultJustification::SKILL_FAILED_INSUFFICIENTLY_DEMONSTRATED->name, + AssessmentResultJustification::FAILED_NOT_ENOUGH_INFORMATION->name, + AssessmentResultJustification::FAILED_OTHER->name], + AssessmentDecision::UNSUCCESSFUL->name, + AssessmentResultType::SKILL); + } + + private function assessSkillsWithLevelAndJustification($poolCandidate, + $poolSkills, + $assessmentStep, + $level, + $justifications, + $assessmentDecision, + $assessmentResultType) + { + if ($assessmentResultType == null) { + $assessmentResultType = AssessmentResultType::SKILL; + } elseif ($assessmentResultType == AssessmentResultType::EDUCATION) { + AssessmentResult::factory()->withResultType($assessmentResultType)->create([ + 'assessment_step_id' => $assessmentStep->id, + 'pool_candidate_id' => $poolCandidate->id, + 'justifications' => json_encode($justifications), + 'assessment_decision' => $assessmentDecision, + ]); + } else { + foreach ($poolSkills as $poolSkill) { + AssessmentResult::factory()->withResultType($assessmentResultType)->create([ + 'assessment_step_id' => $assessmentStep->id, + 'pool_candidate_id' => $poolCandidate->id, + 'pool_skill_id' => $poolSkill, + 'assessment_decision_level' => $level, + 'justifications' => json_encode($justifications), + 'assessment_decision' => $assessmentDecision, + ]); + } + } } } diff --git a/api/database/seeders/ClassificationSeeder.php b/api/database/seeders/ClassificationSeeder.php index 63b4a322db9..1905afc1236 100644 --- a/api/database/seeders/ClassificationSeeder.php +++ b/api/database/seeders/ClassificationSeeder.php @@ -33,6 +33,11 @@ public function run() 'name' => ['en' => 'Economics and Social Science Services', 'fr' => 'économique et services de sciences sociales'], ]; + $exGroup = [ + 'group' => 'EX', + 'name' => ['en' => 'Executive', 'fr' => 'Cadre'], + ]; + $classifications = [ // IT classifications 01-05. array_merge( @@ -238,6 +243,14 @@ public function run() 'max_salary' => 151729, ] ), + array_merge( + $exGroup, + [ + 'level' => 3, + 'min_salary' => 169165, + 'max_salary' => 198939, + ] + ), ]; foreach ($classifications as $classification) { $identifier = [ diff --git a/api/database/seeders/DatabaseSeeder.php b/api/database/seeders/DatabaseSeeder.php index 91047c3bd84..5aafc0c2bda 100644 --- a/api/database/seeders/DatabaseSeeder.php +++ b/api/database/seeders/DatabaseSeeder.php @@ -27,6 +27,7 @@ public function run(): void // convenient test data UserTestSeeder::class, PoolTestSeeder::class, + PoolCandidateTestSeeder::class, AssessmentResultTestSeeder::class, // random data to fill it out diff --git a/api/database/seeders/GenericJobTitleSeeder.php b/api/database/seeders/GenericJobTitleSeeder.php index 2753a54f406..92036c2f0ef 100644 --- a/api/database/seeders/GenericJobTitleSeeder.php +++ b/api/database/seeders/GenericJobTitleSeeder.php @@ -87,6 +87,18 @@ public function run() ], ], + [ + 'key' => GenericJobTitleKey::EXECUTIVE_EX03->name, + 'name' => [ + 'en' => 'Digital Leaders', + 'fr' => 'Chefs de file du numérique', + ], + 'classification' => [ + 'group' => 'EX', + 'level' => 3, + ], + + ], ]; foreach ($genericJobTitles as $genericJobTitle) { @@ -97,7 +109,6 @@ public function run() 'group' => $genericJobTitle['classification']['group'], 'level' => $genericJobTitle['classification']['level'], ])->sole()->id; - $finalValue = array_merge($genericJobTitle, ['classification_id' => $classificationId]); unset($finalValue['classification']); GenericJobTitle::updateOrCreate($identifier, $finalValue); diff --git a/api/database/seeders/PoolCandidateTestSeeder.php b/api/database/seeders/PoolCandidateTestSeeder.php new file mode 100644 index 00000000000..babe6632c29 --- /dev/null +++ b/api/database/seeders/PoolCandidateTestSeeder.php @@ -0,0 +1,177 @@ +create([ + 'pool_candidate_status' => PoolCandidateStatus::QUALIFIED_AVAILABLE->name, + 'submitted_at' => config('constants.far_past_date'), + 'expiry_date' => config('constants.far_future_date'), + 'pool_id' => Pool::select('id')->where('name->en', 'CMO Digital Careers')->sole()->id, + ]); + // set status to EXPIRED manually despite not being submitted + // this was split into two steps as otherwise PoolCandidateFactory automatically assigns a submitted_at + $candidateOne->pool_candidate_status = PoolCandidateStatus::EXPIRED->name; + $candidateOne->save(); + $this->publishedPools = Pool::select('id', 'name')->whereNotNull('published_at')->get(); + + // 1- Perfect Priority + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::QUALIFIED_AVAILABLE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Perfect', + 'last_name' => 'Priority', + 'email' => 'perfect@test.com', + 'sub' => 'perfect@test.com', + 'has_priority_entitlement' => true, + 'priority_number' => '123456789', + 'citizenship' => CitizenshipStatus::CITIZEN->name, + ]); + + //2- Barely qualified Veteran + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::QUALIFIED_AVAILABLE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Barely qualified', + 'last_name' => 'Veteran', + 'email' => 'veteran@test.com', + 'sub' => 'veteran@test.com', + 'citizenship' => CitizenshipStatus::CITIZEN->name, + ]); + + // 3- Try-hard Not a veteran + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::PLACED_TENTATIVE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Try-hard', + 'last_name' => 'Not a veteran', + 'email' => 'try-hard@test.com', + 'sub' => 'try-hard@test.com', + 'citizenship' => CitizenshipStatus::PERMANENT_RESIDENT->name, + ]); + + //4- Absent Canadian + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::REMOVED); + }) + ->create([ + 'first_name' => 'Absent', + 'last_name' => 'Canadian', + 'email' => 'absent@test.com', + 'sub' => 'absent@test.com', + 'citizenship' => CitizenshipStatus::CITIZEN->name, + ]); + + //5- Screened-out Non-Canadian + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::QUALIFIED_AVAILABLE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Screened-out', + 'last_name' => 'Non-Canadian', + 'email' => 'Screened-out@test.com', + 'sub' => 'Screened-out@test.com', + 'citizenship' => CitizenshipStatus::OTHER->name, + ]); + + // 6- Failed Notes master + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::QUALIFIED_AVAILABLE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Failed', + 'last_name' => 'NotesMaster', + 'email' => 'Failed@test.com', + 'sub' => 'Failed@test.com', + 'citizenship' => CitizenshipStatus::CITIZEN->name, + ]); + + // 7- Barely qualified Holder + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::QUALIFIED_AVAILABLE, now()->addYears(2)); + }) + ->create([ + 'first_name' => 'Barely', + 'last_name' => 'qualified Holder', + 'email' => 'barely@test.com', + 'sub' => 'barely@test.com', + 'citizenship' => CitizenshipStatus::PERMANENT_RESIDENT->name, + ]); + + //8- Unsuccessful Priority + User::factory() + ->asApplicant() + ->withSkillsAndExperiences() + ->afterCreating(function (User $user) { + $this->applyToAllPools($user, PoolCandidateStatus::SCREENED_OUT_ASSESSMENT); + }) + ->create([ + 'first_name' => 'Unsuccessful', + 'last_name' => 'Priority', + 'email' => 'Unsuccessful@test.com', + 'sub' => 'Unsuccessful@test.com', + 'citizenship' => CitizenshipStatus::CITIZEN->name, + ]); + + } + + private function applyToAllPools($user, $status, $expiryDate = null, $placedDepartmentId = null) + { + foreach ($this->publishedPools as $pool) { + // create a pool candidate in the pool + PoolCandidate::factory()->for($user)->for($pool) + ->create([ + 'pool_id' => $pool->id, + 'user_id' => $user->id, + 'submitted_at' => config('constants.far_past_date'), + 'submitted_steps' => array_column(ApplicationStep::cases(), 'name'), + 'pool_candidate_status' => $status->name, + 'expiry_date' => $expiryDate, + 'placed_department_id' => $placedDepartmentId, + ]); + } + } +} diff --git a/api/database/seeders/PoolRandomSeeder.php b/api/database/seeders/PoolRandomSeeder.php index 586b20498cd..06e54ca2cc8 100644 --- a/api/database/seeders/PoolRandomSeeder.php +++ b/api/database/seeders/PoolRandomSeeder.php @@ -15,7 +15,7 @@ class PoolRandomSeeder extends Seeder public function run() { Pool::factory()->draft()->create(); - Pool::factory()->count(3)->published()->withAssessments()->create(); + Pool::factory()->count(3)->published()->withAssessments(3)->create(); Pool::factory()->closed()->create(); Pool::factory()->archived()->create(); } diff --git a/api/database/seeders/PoolTestSeeder.php b/api/database/seeders/PoolTestSeeder.php index 4742abf00f3..fdf1f4d1470 100644 --- a/api/database/seeders/PoolTestSeeder.php +++ b/api/database/seeders/PoolTestSeeder.php @@ -2,6 +2,7 @@ namespace Database\Seeders; +use App\Enums\AssessmentStepType; use App\Enums\PoolLanguage; use App\Enums\PoolStream; use App\Enums\PublishingGroup; @@ -20,51 +21,209 @@ class PoolTestSeeder extends Seeder */ public function run() { - $pools = [ - [ + + // Caching commonly used queries + $adminUserId = User::select('id')->where('email', 'admin@test.com')->sole()->id; + $dcmTeamId = Team::select('id')->where('name', 'digital-community-management')->sole()->id; + + // CMO Digital + $createdPool = Pool::factory() + ->withPoolSkills(4, 4) + ->withQuestions(2, 2) + ->published() + ->createOrGetExisting([ 'name' => [ 'en' => 'CMO Digital Careers', 'fr' => 'CMO Carrières Numériques', ], - 'user_id' => User::select('id')->where('email', 'admin@test.com')->sole()->id, - 'team_id' => Team::select('id')->where('name', 'digital-community-management')->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, 'published_at' => config('constants.past_date'), 'closing_date' => config('constants.far_future_date'), 'publishing_group' => PublishingGroup::IT_JOBS->name, - ], - [ + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + ]); + $classificationIT01Id = Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 1)->sole()->id; + $createdPool->classification_id = $classificationIT01Id; + $createdPool->stream = PoolStream::BUSINESS_ADVISORY_SERVICES->name; + $createdPool->advertisement_language = PoolLanguage::VARIOUS->name; + $createdPool->save(); + + // IAP + Pool::factory() + ->withPoolSkills(0, 0) + ->withQuestions(0, 0) + ->draft() + ->createOrGetExisting( + [ + 'name' => [ + 'en' => 'IT Apprenticeship Program for Indigenous Peoples', + 'fr' => 'Programme d’apprentissage en TI pour les personnes autochtones', + ], + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => config('constants.past_date'), + 'closing_date' => config('constants.far_future_date'), + 'publishing_group' => PublishingGroup::IAP->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + ], + ); + + // IT -01 + Pool::factory() + ->withPoolSkills(0, 0) + ->withQuestions(0, 0) + ->draft() + ->createOrGetExisting([ 'name' => [ - 'en' => 'IT Apprenticeship Program for Indigenous Peoples', - 'fr' => 'Programme d’apprentissage en TI pour les personnes autochtones', + 'en' => 'Draft Job', + 'fr' => 'Ébauche de travail', ], - 'user_id' => User::select('id')->where('email', 'admin@test.com')->sole()->id, - 'team_id' => Team::select('id')->where('name', 'digital-community-management')->sole()->id, + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 1)->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => null, + 'closing_date' => config('constants.far_future_date'), + 'publishing_group' => PublishingGroup::IT_JOBS->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + + ]); + + // IT -02 + Pool::factory() + ->withPoolSkills(2, 2) + ->withQuestions(0, 1) + ->draft() + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->createOrGetExisting( // IT-02 - Simple + [ + 'name' => [ + 'en' => 'Ready to publish - Simple', + 'fr' => 'Prêt à publier - Simple', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 2)->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => null, + 'closing_date' => config('constants.far_future_date'), + 'publishing_group' => PublishingGroup::IT_JOBS->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + + ], + ); + + // IT - 03 + Pool::factory() + ->withPoolSkills(6, 6) + ->withQuestions(3, 3) + ->published() + ->withAssessmentStep(AssessmentStepType::INTERVIEW_INDIVIDUAL) + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->withAssessmentStep(AssessmentStepType::REFERENCE_CHECK) + ->createOrGetExisting([ + 'name' => [ + 'en' => 'Published – Complex', + 'fr' => 'Publié – Complexe', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 3)->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, 'published_at' => config('constants.past_date'), 'closing_date' => config('constants.far_future_date'), - 'publishing_group' => PublishingGroup::IAP->name, - ], - ]; - - foreach ($pools as $poolData) { - $identifier = [ - 'name->en' => $poolData['name']['en'], - ]; - $poolModel = Pool::where($identifier)->first(); - if (! $poolModel) { - $createdPool = Pool::factory() - ->published() - ->create($poolData); - // constrain CMO Digital Careers pool to predictable values - if ($identifier['name->en'] == 'CMO Digital Careers') { - $classificationIT01Id = Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 1)->sole()->id; - $createdPool->classification_id = $classificationIT01Id; - $createdPool->stream = PoolStream::BUSINESS_ADVISORY_SERVICES->name; - $createdPool->advertisement_language = PoolLanguage::VARIOUS->name; - $createdPool->save(); - } - } else { - $poolModel->update($poolData); - } - } + 'publishing_group' => PublishingGroup::IT_JOBS_ONGOING->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + + ]); + + //IT -04 + Pool::factory() + ->withPoolSkills(2, 2) + ->withQuestions(3, 3) + ->published() + ->withAssessmentStep(AssessmentStepType::INTERVIEW_INDIVIDUAL) + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->withAssessmentStep(AssessmentStepType::REFERENCE_CHECK) + ->createOrGetExisting([ + 'name' => [ + 'en' => 'Published - Simple', + 'fr' => 'Publié - Simple', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 4)->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => config('constants.past_date'), + 'closing_date' => now()->addMonths(6), + 'publishing_group' => PublishingGroup::IT_JOBS->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + + ]); + + // IT - 05 Closed - Simple + Pool::factory() + ->withPoolSkills(2, 2) + ->withQuestions(2, 1) + ->published() + ->withAssessmentStep(AssessmentStepType::INTERVIEW_INDIVIDUAL) + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->withAssessmentStep(AssessmentStepType::REFERENCE_CHECK) + ->createOrGetExisting( + [ + 'name' => [ + 'en' => 'Closed - Simple', + 'fr' => 'Fermé - Simple', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'IT')->where('level', 5)->sole()->id, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => config('constants.past_date'), + 'closing_date' => config('constants.past_date'), + 'publishing_group' => PublishingGroup::IT_JOBS->name, + 'stream' => PoolStream::BUSINESS_ADVISORY_SERVICES->name, + ], + ); + + // Ex-03 Complex + Pool::factory() + ->withPoolSkills(6, 6) + ->withQuestions(3, 3) + ->published() + ->withAssessmentStep(AssessmentStepType::INTERVIEW_INDIVIDUAL) + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->withAssessmentStep(AssessmentStepType::REFERENCE_CHECK) + ->createOrGetExisting( + [ + 'name' => [ + 'en' => 'Complex', + 'fr' => 'complexe', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'EX')->where('level', 3)->sole()->id, + 'stream' => PoolStream::EXECUTIVE_GROUP->name, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => config('constants.past_date'), + 'closing_date' => config('constants.past_date'), + 'publishing_group' => PublishingGroup::EXECUTIVE_JOBS->name, + ], + ); + + // PM-01 – Simple + Pool::factory() + ->withPoolSkills(2, 2) + ->withQuestions(0, 1) + ->published() + ->withAssessmentStep(AssessmentStepType::TECHNICAL_EXAM_AT_SITE) + ->createOrGetExisting([ + 'name' => [ + 'en' => 'Simple', + 'fr' => 'Simple', + ], + 'classification_id' => Classification::select('id')->where('group', 'ilike', 'PM')->where('level', 1)->sole()->id, + 'stream' => PoolStream::ACCESS_INFORMATION_PRIVACY->name, + 'user_id' => $adminUserId, + 'team_id' => $dcmTeamId, + 'published_at' => config('constants.past_date'), + 'closing_date' => now()->addMonths(6), + 'publishing_group' => PublishingGroup::OTHER->name, + ]); } } diff --git a/api/storage/app/lighthouse-schema.graphql b/api/storage/app/lighthouse-schema.graphql index 427f1d6af6e..01f431cf518 100755 --- a/api/storage/app/lighthouse-schema.graphql +++ b/api/storage/app/lighthouse-schema.graphql @@ -2244,6 +2244,7 @@ enum GenericJobTitleKey { TECHNICAL_ADVISOR_IT03 SENIOR_ADVISOR_IT04 MANAGER_IT04 + EXECUTIVE_EX03 } enum PoolCandidateSearchStatus { diff --git a/api/tests/Feature/AssessmentResultTest.php b/api/tests/Feature/AssessmentResultTest.php index 12ce1e4505f..ddb9376c1ef 100644 --- a/api/tests/Feature/AssessmentResultTest.php +++ b/api/tests/Feature/AssessmentResultTest.php @@ -257,7 +257,7 @@ public function testAssessmentResultPoolValidation(): void ]); // unrelated models - $randomPool = Pool::factory()->create(); + $randomPool = Pool::factory()->withPoolSkills(2, 2)->withQuestions(2, 2)->create(); $randomAssessmentStep = AssessmentStep::factory()->create([ 'pool_id' => $randomPool->id, ]); diff --git a/api/tests/Feature/AssessmentStepTest.php b/api/tests/Feature/AssessmentStepTest.php index d87dc3aae21..a438c2552ee 100644 --- a/api/tests/Feature/AssessmentStepTest.php +++ b/api/tests/Feature/AssessmentStepTest.php @@ -290,7 +290,7 @@ public function testAssessmentStepTypeValidation(): void public function testScreeningQuestionsAndSkills(): void { Skill::factory()->count(3)->create(); - $testPool = Pool::factory()->draft()->create([ + $testPool = Pool::factory()->draft()->WithPoolSkills(2, 2)->WithQuestions(2, 2)->create([ 'team_id' => $this->team->id, ]); $screeningQuestion = $testPool->screeningQuestions[0]; // first factory created question @@ -369,7 +369,7 @@ public function testScreeningQuestionsAndSkills(): void public function testScreeningQuestionsCreatingAssessmentStep(): void { Skill::factory()->count(3)->create(); - $testPool = Pool::factory()->draft()->create([ + $testPool = Pool::factory()->draft()->withPoolSkills(2, 2)->withQuestions(2, 2)->create([ 'team_id' => $this->team->id, ]); AssessmentStep::truncate(); diff --git a/api/tests/Feature/GeneralQuestionResponsesTest.php b/api/tests/Feature/GeneralQuestionResponsesTest.php index d9f8048f247..2d53f4be65e 100644 --- a/api/tests/Feature/GeneralQuestionResponsesTest.php +++ b/api/tests/Feature/GeneralQuestionResponsesTest.php @@ -53,7 +53,7 @@ protected function setUp(): void $this->team = Team::factory()->create([ 'name' => $this->teamName, ]); - $this->pool = Pool::factory()->draft()->create([ + $this->pool = Pool::factory()->draft()->WithPoolSkills(2, 2)->WithQuestions(2, 2)->create([ 'team_id' => $this->team->id, ]); $this->teamUser = User::factory() diff --git a/api/tests/Feature/GeneralQuestionTest.php b/api/tests/Feature/GeneralQuestionTest.php index 68e35457334..9df3ac6c5a3 100644 --- a/api/tests/Feature/GeneralQuestionTest.php +++ b/api/tests/Feature/GeneralQuestionTest.php @@ -51,7 +51,7 @@ protected function setUp(): void $this->team = Team::factory()->create([ 'name' => $this->teamName, ]); - $this->pool = Pool::factory()->draft()->create([ + $this->pool = Pool::factory()->draft()->WithPoolSkills(2, 2)->WithQuestions(3, 1)->create([ 'team_id' => $this->team->id, ]); // this seeds 3 questions onto the pool $this->teamUser = User::factory() diff --git a/api/tests/Feature/PoolApplicationTest.php b/api/tests/Feature/PoolApplicationTest.php index 20a02cc4edd..30e017e7eac 100644 --- a/api/tests/Feature/PoolApplicationTest.php +++ b/api/tests/Feature/PoolApplicationTest.php @@ -17,6 +17,7 @@ use App\Models\ScreeningQuestionResponse; use App\Models\Team; use App\Models\User; +use App\Models\WorkExperience; use Carbon\Carbon; use Database\Helpers\ApiEnums; use Database\Seeders\ClassificationSeeder; @@ -407,14 +408,15 @@ public function testApplicationSubmitSignature(): void public function testApplicationSubmitSkills(): void { // create a pool, attach one essential skill to it - $newPool = Pool::factory()->create([ + $newPool = Pool::factory()->WithPoolSkills(1, 0)->create([ 'closing_date' => Carbon::now()->addDays(1), 'advertisement_language' => PoolLanguage::ENGLISH->name, // avoid language requirements ]); // create an experience with no skills, then attach it to the user - AwardExperience::factory()->create([ + WorkExperience::factory()->create([ 'user_id' => $this->applicantUser->id, + ]); $newPoolCandidate = PoolCandidate::factory()->create([ @@ -422,8 +424,11 @@ public function testApplicationSubmitSkills(): void 'pool_id' => $newPool->id, 'pool_candidate_status' => PoolCandidateStatus::DRAFT->name, ]); - $educationExperience = EducationExperience::factory()->create(['user_id' => $newPoolCandidate->user_id]); - $newPoolCandidate->educationRequirementEducationExperiences()->sync([$educationExperience->id]); + + // Refresh the data from the database to ensure it is correctly loaded + $this->applicantUser->refresh(); + $newPool->refresh(); + $newPoolCandidate->refresh(); // assert user cannot submit application with missing essential skills $this->actingAs($this->applicantUser, 'api') @@ -439,11 +444,31 @@ public function testApplicationSubmitSkills(): void ]], ]); - // create another experience, then attach it to the user, and then connect the essential skill to it - $secondExperience = AwardExperience::factory()->create([ + } + + public function testApplicationSubmitWithEssentialSkill(): void + { + + // create a pool, attach one essential skill to it + $newPool = Pool::factory()->WithPoolSkills(1, 0)->create([ + 'closing_date' => Carbon::now()->addDays(1), + 'advertisement_language' => PoolLanguage::ENGLISH->name, // avoid language requirements + ]); + + $newPoolCandidate = PoolCandidate::factory()->create([ + 'user_id' => $this->applicantUser->id, + 'pool_id' => $newPool->id, + 'pool_candidate_status' => PoolCandidateStatus::DRAFT->name, + ]); + + $educationExperience = EducationExperience::factory()->create(['user_id' => $newPoolCandidate->user_id]); + $newPoolCandidate->educationRequirementEducationExperiences()->sync([$educationExperience->id]); + + // create award experience, then attach it to the user, and then connect the essential skill to it + $awardExperience = AwardExperience::factory()->create([ 'user_id' => $this->applicantUser->id, ]); - $secondExperience->syncSkills($newPool->essentialSkills); + $awardExperience->syncSkills($newPool->essentialSkills); // assert user can now submit application as the essential skill is present $this->actingAs($this->applicantUser, 'api') diff --git a/api/tests/Feature/PoolTest.php b/api/tests/Feature/PoolTest.php index c8871622e2c..6dd0e259f5b 100644 --- a/api/tests/Feature/PoolTest.php +++ b/api/tests/Feature/PoolTest.php @@ -681,6 +681,8 @@ public function testPoolIsCompleteAccessor(): void Skill::factory()->create(); $completePool = Pool::factory() + ->withPoolSkills(2, 2) + ->withAssessments(2) ->published() ->create([ 'closing_date' => config('constants.far_future_date'), @@ -733,6 +735,7 @@ public function testPoolIsCompleteAccessorSkillLevel(): void $completePool = Pool::factory() ->published() + ->withPoolSkills(2, 2) ->create([ 'closing_date' => config('constants.far_future_date'), ]); @@ -770,7 +773,9 @@ public function testAssessmentStepValidation(): void 'category' => SkillCategory::TECHNICAL->name, ]); $completePool = Pool::factory() + ->withPoolSkills(2, 2) ->published() + ->withAssessmentStepAndWithoutPoolSkills() ->create([ 'closing_date' => config('constants.far_future_date'), 'published_at' => null, @@ -826,6 +831,7 @@ public function testPoolSkillValidation(): void ]); $completePool = Pool::factory() ->published() + ->withPoolSkills(2, 2) ->create([ 'closing_date' => config('constants.far_future_date'), 'published_at' => null, diff --git a/api/tests/Feature/ScreeningQuestionsTest.php b/api/tests/Feature/ScreeningQuestionsTest.php index 0c6e644e289..f56ac527e10 100644 --- a/api/tests/Feature/ScreeningQuestionsTest.php +++ b/api/tests/Feature/ScreeningQuestionsTest.php @@ -102,11 +102,11 @@ protected function setUp(): void 'name' => $this->teamName, ]); Skill::factory()->count(3)->create(); - $this->pool = Pool::factory()->draft()->create([ + $this->pool = Pool::factory()->draft()->withPoolSkills(2, 2)->create([ 'team_id' => $this->team->id, ]); $this->poolSkillId = (PoolSkill::all()->pluck('id')->toArray())[0]; - $this->publishedPool = Pool::factory()->published()->create([ + $this->publishedPool = Pool::factory()->published()->WithPoolSkills(2, 2)->WithQuestions(2, 2)->create([ 'team_id' => $this->team->id, ]); $this->adminUser = User::factory() diff --git a/api/tests/Feature/SnapshotTest.php b/api/tests/Feature/SnapshotTest.php index 35d54c17101..12112a70950 100644 --- a/api/tests/Feature/SnapshotTest.php +++ b/api/tests/Feature/SnapshotTest.php @@ -130,6 +130,7 @@ public function testSnapshotSkillFiltering() $poolCandidate = PoolCandidate::factory()->create([ 'user_id' => $user->id, 'pool_candidate_status' => PoolCandidateStatus::DRAFT->name, + 'pool_id' => Pool::factory()->withPoolSkills(5, 5), ]); // collect skills attached to the Pool