Send students to a chosen page when registration succeeds
CI / Tests (PHP 8.2) (pull_request) Successful in 49s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m0s
CI / Coding Standards (pull_request) Successful in 2m51s
CI / PHPStan (pull_request) Successful in 2m57s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m40s
CI / Build Plugin Zip (pull_request) Skipped
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.2) (pull_request) Successful in 49s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m0s
CI / Coding Standards (pull_request) Successful in 2m51s
CI / PHPStan (pull_request) Successful in 2m57s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m40s
CI / Build Plugin Zip (pull_request) Skipped
CI / No Debug Code (pull_request) Successful in 2s
The Student Registration block's "After email confirmation" panel becomes "After registration": the page it selects is now where a newly registered student continues to, and a new autoRedirect toggle sends them there instead of showing the link. Only the two finished states qualify (RegistrationPage::isRegistrationComplete): an invited student who is now logged in, and a self-signup back from the emailed confirmation link. A validation error, an expired confirmation link, and the intermediate "check your email" step all stay on the page so their message is read. The invited-student success previously had no link at all; it gains a "Continue to your account" one. That path deliberately has no WordPress-login-screen fallback — pointing someone already signed in at the login screen helps nobody — so continueUrl() distinguishes "no page chosen" from "page chosen", and the redirect does nothing until one is picked. Closes #115 Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -484,6 +484,54 @@ class RegistrationPageTest extends TestCase
|
||||
|
||||
self::assertStringContainsString('us-success', $html);
|
||||
self::assertStringContainsString('now logged in', $html);
|
||||
// No page chosen: the sign-in-screen fallback is useless to someone who
|
||||
// is already signed in, so no link is offered at all.
|
||||
self::assertStringNotContainsString('<a href', $html);
|
||||
}
|
||||
|
||||
public function testInviteSuccessLinksToTheChosenPage(): void
|
||||
{
|
||||
$_GET = [ 'us_registered' => 'invite' ];
|
||||
Functions\when('is_user_logged_in')->justReturn(true);
|
||||
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
|
||||
Functions\expect('get_permalink')->once()->with(4)->andReturn('http://home.test/welcome/');
|
||||
|
||||
$html = $this->ctx['page']->render([ 'loginPageId' => 4 ]);
|
||||
|
||||
self::assertStringContainsString('now logged in', $html);
|
||||
self::assertStringContainsString('href="http://home.test/welcome/"', $html);
|
||||
}
|
||||
|
||||
public function testContinueUrlIsNullWithoutAResolvablePage(): void
|
||||
{
|
||||
Functions\when('get_permalink')->justReturn(false);
|
||||
|
||||
self::assertNull($this->ctx['page']->continueUrl(0));
|
||||
self::assertNull($this->ctx['page']->continueUrl(4));
|
||||
}
|
||||
|
||||
public function testIsRegistrationCompleteOnlyForFinishedStates(): void
|
||||
{
|
||||
Functions\when('sanitize_key')->alias(static fn ($v) => strtolower((string) $v));
|
||||
|
||||
// [ query args, logged in, finished ]
|
||||
$cases = [
|
||||
'invited student, now logged in' => [['us_registered' => 'invite'], true, true],
|
||||
'invited student, not logged in' => [['us_registered' => 'invite'], false, false],
|
||||
'email confirmed, ready' => [['us_confirmed' => 'ready'], false, true],
|
||||
'email confirmed, pending review' => [['us_confirmed' => '1'], false, true],
|
||||
'confirmation link expired' => [['us_confirmed' => 'expired'], false, false],
|
||||
'awaiting email confirmation' => [['us_registered' => 'confirm'], false, false],
|
||||
'group signup awaiting confirm' => [['us_registered' => 'confirm_group'], false, false],
|
||||
'plain page view' => [[], false, false],
|
||||
];
|
||||
|
||||
foreach ($cases as $label => [$get, $loggedIn, $expected]) {
|
||||
$_GET = $get;
|
||||
Functions\when('is_user_logged_in')->justReturn($loggedIn);
|
||||
|
||||
self::assertSame($expected, $this->ctx['page']->isRegistrationComplete(), $label);
|
||||
}
|
||||
}
|
||||
|
||||
public function testInviteOnlyMessageCanBeCustomised(): void
|
||||
|
||||
@@ -52,6 +52,12 @@ class BlockRegistrarTest extends TestCase
|
||||
$this->registrationPage = Mockery::mock(RegistrationPage::class);
|
||||
$this->groupClassPage = Mockery::mock(GroupClassPage::class);
|
||||
|
||||
// Most requests are not a just-finished registration; the tests that
|
||||
// exercise that path override this.
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')
|
||||
->andReturn(false)
|
||||
->byDefault();
|
||||
|
||||
$this->registrar = new TestableBlockRegistrar(
|
||||
$this->bookingPage,
|
||||
$this->loginPage,
|
||||
@@ -126,7 +132,7 @@ class BlockRegistrarTest extends TestCase
|
||||
array_keys($registered['us-scheduler/student-login']['attributes'])
|
||||
);
|
||||
self::assertSame(
|
||||
['loginPageId', 'inviteOnlyMessage'],
|
||||
['loginPageId', 'autoRedirect', 'inviteOnlyMessage'],
|
||||
array_keys($registered['us-scheduler/student-register']['attributes'])
|
||||
);
|
||||
self::assertSame(
|
||||
@@ -397,6 +403,145 @@ class BlockRegistrarTest extends TestCase
|
||||
self::assertSame([], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testAutoRedirectSendsAFinishedRegistrationToTheChosenPage(): void
|
||||
{
|
||||
$this->stubSingularRequest(
|
||||
30,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['autoRedirect' => true, 'loginPageId' => 4],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')->andReturn(true);
|
||||
$this->registrationPage->shouldReceive('continueUrl')
|
||||
->once()->with(4)->andReturn('https://example.com/welcome/');
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame(['https://example.com/welcome/'], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testAutoRedirectSendsAJustLoggedInInvitedStudentToTheChosenPage(): void
|
||||
{
|
||||
// The invited-student branch completes logged in, so the logged-in
|
||||
// student-login branch must not get first claim on the request.
|
||||
$this->stubSingularRequest(
|
||||
30,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['autoRedirect' => true, 'loginPageId' => 4],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')->andReturn(true);
|
||||
$this->registrationPage->shouldReceive('continueUrl')
|
||||
->once()->with(4)->andReturn('https://example.com/welcome/');
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame(['https://example.com/welcome/'], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testNoRedirectWhenTheRegistrationIsNotFinished(): void
|
||||
{
|
||||
// e.g. the "check your email" step, or a validation error — the
|
||||
// message has to be read, so the block never redirects past it.
|
||||
$this->stubSingularRequest(
|
||||
30,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['autoRedirect' => true, 'loginPageId' => 4],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('continueUrl')->never();
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame([], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testNoRedirectWhenTheRegisterBlockDoesNotOptIn(): void
|
||||
{
|
||||
$this->stubSingularRequest(
|
||||
30,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['loginPageId' => 4],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')->andReturn(true);
|
||||
$this->registrationPage->shouldReceive('continueUrl')->never();
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame([], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testNoRedirectWhenTheRegisterBlockHasNoPageChosen(): void
|
||||
{
|
||||
$this->stubSingularRequest(
|
||||
30,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['autoRedirect' => true],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')->andReturn(true);
|
||||
// No page chosen: there is no login-screen fallback to redirect to,
|
||||
// so the student keeps the on-page confirmation instead.
|
||||
$this->registrationPage->shouldReceive('continueUrl')->once()->with(0)->andReturnNull();
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame([], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testNoRedirectWhenTheRegisterBlockPointsAtItsOwnPage(): void
|
||||
{
|
||||
$this->stubSingularRequest(
|
||||
4,
|
||||
[
|
||||
[
|
||||
'blockName' => 'us-scheduler/student-register',
|
||||
'attrs' => ['autoRedirect' => true, 'loginPageId' => 4],
|
||||
'innerBlocks' => [],
|
||||
],
|
||||
],
|
||||
false
|
||||
);
|
||||
|
||||
$this->registrationPage->shouldReceive('isRegistrationComplete')->andReturn(true);
|
||||
$this->registrationPage->shouldReceive('continueUrl')->never();
|
||||
|
||||
$this->registrar->maybeAutoRedirect();
|
||||
|
||||
self::assertSame([], $this->registrar->redirects);
|
||||
}
|
||||
|
||||
public function testNoRedirectOutsideSingularFrontEndRequests(): void
|
||||
{
|
||||
Functions\when('is_admin')->justReturn(false);
|
||||
|
||||
Reference in New Issue
Block a user