answers = Mockery::mock(AnswerRepository::class); $this->questions = Mockery::mock(QuestionRepository::class); $this->acceptances = Mockery::mock(AcceptanceRepository::class); $this->policies = Mockery::mock(PolicyRepository::class); $this->versions = Mockery::mock(PolicyVersionRepository::class); $this->detail = new IntakeAudit( $this->answers, $this->questions, $this->acceptances, $this->policies, $this->versions ); } public function testAnswersPairEachAnswerWithItsQuestionLabel(): void { $this->answers->shouldReceive('findByRegistration')->once()->with(Answer::REG_LESSON, 7)->andReturn([ new Answer(questionId: 2, registrationType: Answer::REG_LESSON, registrationId: 7, studentId: 5, answerValue: 'Beginner'), new Answer(questionId: 9, registrationType: Answer::REG_LESSON, registrationId: 7, studentId: 5, answerValue: null), ]); $this->questions->shouldReceive('findById')->with(2)->andReturn(new Question(offeringId: 1, label: 'Skill level', id: 2)); $this->questions->shouldReceive('findById')->with(9)->andReturn(null); self::assertSame( [ ['question' => 'Skill level', 'answer' => 'Beginner', 'source' => 'Given online when booking'], ['question' => '#9', 'answer' => '—', 'source' => 'Given online when booking'], ], $this->detail->answers($this->lesson(7)) ); } public function testAcceptancesResolvePolicyTitleVersionAndAuditTrail(): void { $this->acceptances->shouldReceive('findByRegistration')->once()->with(PolicyAcceptance::REG_LESSON, 7)->andReturn([ new PolicyAcceptance( policyVersionId: 4, studentId: 5, registrationType: PolicyAcceptance::REG_LESSON, registrationId: 7, ipAddress: '1.2.3.4', acceptedAt: '2026-07-01 10:00:00' ), ]); $this->versions->shouldReceive('findById')->with(4)->andReturn(new PolicyVersion(policyId: 3, versionNumber: 2, id: 4)); $this->policies->shouldReceive('findById')->with(3)->andReturn(new Policy(title: 'Cancellation', slug: 'cancellation', id: 3)); self::assertSame( [ [ 'policy' => 'Cancellation', 'version' => 'v2', 'accepted_at' => '2026-07-01 10:00:00', 'ip' => '1.2.3.4', 'source' => 'Given online when booking', ], ], $this->detail->acceptances($this->lesson(7)) ); } public function testACollectedElsewhereAnswerNamesItsSourceAndWhoRecordedIt(): void { $user = Mockery::mock(\WP_User::class); $user->ID = 7; $user->first_name = 'Jane'; $user->last_name = 'Doe'; $user->nickname = 'jane'; $user->display_name = 'jane'; Functions\when('get_userdata')->justReturn($user); $this->answers->shouldReceive('findByRegistration')->once()->with(Answer::REG_LESSON, 7)->andReturn([ new Answer( questionId: 2, registrationType: Answer::REG_LESSON, registrationId: 7, studentId: 5, answerValue: 'Nut allergy', collectedVia: IntakeProvenance::VIA_PAPER, collectedNote: 'Filed in the studio binder', recordedBy: 7 ), ]); $this->questions->shouldReceive('findById')->with(2)->andReturn(new Question(offeringId: 1, label: 'Allergies', id: 2)); self::assertSame( [[ 'question' => 'Allergies', 'answer' => 'Nut allergy', 'source' => 'On a signed paper form — Filed in the studio binder — recorded by Jane Doe', ]], $this->detail->answers($this->lesson(7)) ); } public function testSeriesOccurrenceReadsTheAnchorsAnswersAndAcceptances(): void { // Occurrence #12 of a weekly reservation anchored on lesson 7: the intake // and the agreement were recorded once, against the anchor. $occurrence = $this->lesson(12, seriesId: 7); $this->answers->shouldReceive('findByRegistration')->once()->with(Answer::REG_LESSON, 7)->andReturn([ new Answer(questionId: 2, registrationType: Answer::REG_LESSON, registrationId: 7, studentId: 5, answerValue: 'Beginner'), ]); $this->questions->shouldReceive('findById')->with(2)->andReturn(new Question(offeringId: 1, label: 'Skill level', id: 2)); $this->acceptances->shouldReceive('findByRegistration')->once()->with(PolicyAcceptance::REG_LESSON, 7)->andReturn([ new PolicyAcceptance( policyVersionId: 4, studentId: 5, registrationType: PolicyAcceptance::REG_LESSON, registrationId: 7, ipAddress: '1.2.3.4', acceptedAt: '2026-07-01 10:00:00' ), ]); $this->versions->shouldReceive('findById')->with(4)->andReturn(new PolicyVersion(policyId: 3, versionNumber: 2, id: 4)); $this->policies->shouldReceive('findById')->with(3)->andReturn(new Policy(title: 'Cancellation', slug: 'cancellation', id: 3)); self::assertSame( [['question' => 'Skill level', 'answer' => 'Beginner', 'source' => 'Given online when booking']], $this->detail->answers($occurrence) ); self::assertSame( [[ 'policy' => 'Cancellation', 'version' => 'v2', 'accepted_at' => '2026-07-01 10:00:00', 'ip' => '1.2.3.4', 'source' => 'Given online when booking', ]], $this->detail->acceptances($occurrence) ); } private function lesson(int $id, ?int $seriesId = null): Lesson { return new Lesson( slotId: 1, studentId: 5, instructorId: 9, offeringId: 1, recurrence: null === $seriesId ? Lesson::RECURRENCE_SINGLE : Lesson::RECURRENCE_WEEKLY, seriesId: $seriesId, id: $id ); } }