Ask the account holder the studio's questions when they are a student too
CI / Tests (PHP 8.2) (pull_request) Successful in 43s
CI / Tests (PHP 8.1) (pull_request) Successful in 52s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m50s
CI / Coding Standards (pull_request) Successful in 3m19s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m47s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 43s
CI / Tests (PHP 8.1) (pull_request) Successful in 52s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m50s
CI / Coding Standards (pull_request) Successful in 3m19s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m47s
CI / Build Plugin Zip (pull_request) Skipped
Under "both" the questions were collected per student only, so someone registering themselves alongside their children was never asked their own instrument, level or anything else — despite being able to book lessons. The account-scope questions describe a student, and under "both" the account holder is one. Their answers are recorded against their own user id, not shared with a child's, and recorded after the children so a rollback that deletes the account cannot leave answers pointing at a user that no longer exists. A pure guardian is unchanged: they are not a student, so anything posted for them is still ignored. Validation became two passes rather than one so the message can say whose answers are missing — with one pass, "both" had to blame "each student" for the account holder's own blank field. In the form, the two questions turn out to be independent: whether student blocks are in play, and whether the account holder answers for themselves. "Both" is the case that needs its own answer to each, so sync() now tracks them separately, and step two comes back into play under "both". Verified in a headless browser: 21 checks across all three choices, now including that "both" enables the account holder's own question panel and offers Next rather than the early submit. Closes #146 Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -825,6 +825,95 @@ class RegistrationPageTest extends TestCase
|
||||
self::assertSame('invite', $this->submit(new Invite(email: '[email protected]', token: 'hash'), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Under "both" the account holder is a student too, so the studio's
|
||||
* questions are asked of them as well as of each student they add. Before
|
||||
* this they were asked per student only, and the account holder's own
|
||||
* answers were never collected or stored.
|
||||
*/
|
||||
public function testBothRecordsAnswersForTheAccountHolderAndEachStudent(): void
|
||||
{
|
||||
$_POST = [
|
||||
'password' => 'thistle-marrow-42',
|
||||
'display_name' => 'Grace',
|
||||
'us_registering_for' => RegistrationPage::FOR_BOTH,
|
||||
'us_answers' => ['7' => 'Cello'],
|
||||
'children' => [['name' => 'Ada', 'birth_year' => '2015', 'answers' => [7 => 'Piano']]],
|
||||
];
|
||||
|
||||
$question = new Question(null, 'Instrument', isRequired: true, scope: Question::SCOPE_ACCOUNT, id: 7);
|
||||
$this->ctx['questions']->shouldReceive('findByScope')->andReturn([$question]);
|
||||
$this->ctx['guardians']->shouldReceive('createChild')->once()->andReturn(101);
|
||||
$this->stubInviteSuccess();
|
||||
|
||||
$recorded = [];
|
||||
$this->ctx['answers']->shouldReceive('insert')->andReturnUsing(
|
||||
static function (Answer $answer) use (&$recorded): int {
|
||||
$recorded[] = [$answer->studentId, $answer->answerValue];
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
|
||||
self::assertSame('invite', $this->submit(new Invite(email: '[email protected]', token: 'hash'), false));
|
||||
|
||||
// The student's answer against the student, the account holder's against
|
||||
// themselves — not one answer shared between them.
|
||||
self::assertEqualsCanonicalizing([[101, 'Piano'], [42, 'Cello']], $recorded);
|
||||
}
|
||||
|
||||
public function testBothRejectsAnUnansweredQuestionForTheAccountHolder(): void
|
||||
{
|
||||
$_POST = [
|
||||
'password' => 'thistle-marrow-42',
|
||||
'display_name' => 'Grace',
|
||||
'us_registering_for' => RegistrationPage::FOR_BOTH,
|
||||
'us_answers' => ['7' => ' '],
|
||||
'children' => [['name' => 'Ada', 'birth_year' => '2015', 'answers' => [7 => 'Piano']]],
|
||||
];
|
||||
|
||||
$question = new Question(null, 'Instrument', isRequired: true, scope: Question::SCOPE_ACCOUNT, id: 7);
|
||||
$this->ctx['questions']->shouldReceive('findByScope')->andReturn([$question]);
|
||||
Functions\when('email_exists')->justReturn(false);
|
||||
Functions\expect('wp_insert_user')->never();
|
||||
|
||||
$result = $this->submit(new Invite(email: '[email protected]', token: 'hash'), false);
|
||||
|
||||
// The message names nobody else — the student's answer was fine.
|
||||
self::assertStringContainsString('Please answer all required registration questions.', $result);
|
||||
self::assertStringNotContainsString('for each student', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* A pure guardian is not a student, so the questions are theirs to answer
|
||||
* per student and never about them. Anything posted for them is ignored.
|
||||
*/
|
||||
public function testRegisteringOnlyForStudentsStoresNoAnswersForTheAccountHolder(): void
|
||||
{
|
||||
$_POST = [
|
||||
'password' => 'thistle-marrow-42',
|
||||
'display_name' => 'Grace',
|
||||
'us_registering_for' => RegistrationPage::FOR_STUDENTS,
|
||||
'us_answers' => ['7' => 'Should be ignored'],
|
||||
'children' => [['name' => 'Ada', 'birth_year' => '2015', 'answers' => [7 => 'Piano']]],
|
||||
];
|
||||
|
||||
$question = new Question(null, 'Instrument', isRequired: true, scope: Question::SCOPE_ACCOUNT, id: 7);
|
||||
$this->ctx['questions']->shouldReceive('findByScope')->andReturn([$question]);
|
||||
$this->ctx['guardians']->shouldReceive('createChild')->once()->andReturn(101);
|
||||
$this->stubInviteSuccess();
|
||||
|
||||
$students = [];
|
||||
$this->ctx['answers']->shouldReceive('insert')->andReturnUsing(
|
||||
static function (Answer $answer) use (&$students): int {
|
||||
$students[] = $answer->studentId;
|
||||
return 1;
|
||||
}
|
||||
);
|
||||
|
||||
self::assertSame('invite', $this->submit(new Invite(email: '[email protected]', token: 'hash'), false));
|
||||
self::assertSame([101], $students);
|
||||
}
|
||||
|
||||
public function testGuardianSignupWithNoChildrenIsRejected(): void
|
||||
{
|
||||
$_POST = [
|
||||
|
||||
Reference in New Issue
Block a user