Show instructor real name or nickname in group-class views, not the login
CI / Tests (PHP 8.2) (pull_request) Successful in 46s
CI / Tests (PHP 8.1) (pull_request) Successful in 46s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m47s
CI / Coding Standards (pull_request) Successful in 2m51s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m41s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.2) (pull_request) Successful in 46s
CI / Tests (PHP 8.1) (pull_request) Successful in 46s
CI / No Debug Code (pull_request) Successful in 2s
CI / PHPStan (pull_request) Successful in 2m47s
CI / Coding Standards (pull_request) Successful in 2m51s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m41s
CI / Build Plugin Zip (pull_request) Skipped
Add Auth\UserName::format(), which prefers a user's first + last name, then their nickname, avoiding display_name (which can be the login/username). Route the instructor name through it in both the front-end offerings response (instructor_name) and the back-end group-class summary and details views. Tests: composer test (513), composer lint, composer cs all pass. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Unsupervised\Schedular\Tests\Unit\Auth;
|
||||
|
||||
use Mockery;
|
||||
use Unsupervised\Schedular\Auth\UserName;
|
||||
use Unsupervised\Schedular\Tests\Unit\TestCase;
|
||||
|
||||
class UserNameTest extends TestCase
|
||||
{
|
||||
private function user(string $first, string $last, string $nickname): \WP_User
|
||||
{
|
||||
$user = Mockery::mock(\WP_User::class);
|
||||
$user->first_name = $first;
|
||||
$user->last_name = $last;
|
||||
$user->nickname = $nickname;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function testPrefersFirstAndLastName(): void
|
||||
{
|
||||
self::assertSame('Ada Lovelace', UserName::format($this->user('Ada', 'Lovelace', 'ada_login')));
|
||||
}
|
||||
|
||||
public function testUsesFirstNameAloneWhenLastNameMissing(): void
|
||||
{
|
||||
self::assertSame('Ada', UserName::format($this->user('Ada', '', 'ada_login')));
|
||||
}
|
||||
|
||||
public function testFallsBackToNicknameWhenNoRealName(): void
|
||||
{
|
||||
self::assertSame('Countess', UserName::format($this->user('', '', 'Countess')));
|
||||
}
|
||||
|
||||
public function testFallsBackToIdWhenNothingSet(): void
|
||||
{
|
||||
self::assertSame('42', UserName::format($this->user('', '', ''), 42));
|
||||
}
|
||||
|
||||
public function testReturnsFallbackIdWhenUserMissing(): void
|
||||
{
|
||||
self::assertSame('42', UserName::format(null, 42));
|
||||
self::assertSame('', UserName::format(null));
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,24 @@ class GroupClassControllerTest extends TestCase
|
||||
$_GET = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* A WP_User whose real name (and display name) is the given full name, so
|
||||
* both instructor resolution (first + last) and roster display (display name)
|
||||
* render it.
|
||||
*/
|
||||
private function userNamed(string $full): \WP_User
|
||||
{
|
||||
[$first, $last] = array_pad(explode(' ', $full, 2), 2, '');
|
||||
|
||||
$user = Mockery::mock(\WP_User::class);
|
||||
$user->first_name = $first;
|
||||
$user->last_name = $last;
|
||||
$user->nickname = $full;
|
||||
$user->display_name = $full;
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function offering(int $id, string $title, ?int $capacity): Offering
|
||||
{
|
||||
return new Offering(
|
||||
@@ -109,7 +127,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testClassDetailListsRosterWithPaymentStatus(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Ada Lovelace']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Ada Lovelace'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = $this->offering(8, 'Choir', 10);
|
||||
@@ -131,7 +149,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testClassDetailShowsClassSettingsAndInviteControlsForInviteOnly(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Ada Lovelace']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Ada Lovelace'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = new Offering(
|
||||
@@ -167,7 +185,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testClassDetailEnrolmentCountExcludesCancelledButRosterKeepsThem(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Grace Hopper']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Grace Hopper'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = $this->offering(8, 'Band', null);
|
||||
@@ -187,7 +205,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testClassDetailFreeEnrolmentShowsDashForPayment(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Alan Turing']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Alan Turing'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = $this->offering(8, 'Theory', 5);
|
||||
@@ -218,7 +236,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testClassDetailWithNoEnrolmentsShowsEmptyMessage(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Ada Lovelace']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Ada Lovelace'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = $this->offering(8, 'Jazz', 5);
|
||||
@@ -243,7 +261,7 @@ class GroupClassControllerTest extends TestCase
|
||||
|
||||
public function testStudioAdminPageSummarisesClassesNotStudents(): void
|
||||
{
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Ada Lovelace']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Ada Lovelace'));
|
||||
|
||||
$offering = new Offering(
|
||||
instructorId: 3,
|
||||
@@ -272,7 +290,7 @@ class GroupClassControllerTest extends TestCase
|
||||
public function testStudioAdminCanOpenClassDetailWithInviteControls(): void
|
||||
{
|
||||
// A studio admin (view_all_lessons) opens a class taught by instructor 7.
|
||||
Functions\when('get_userdata')->justReturn((object) ['display_name' => 'Ada Lovelace']);
|
||||
Functions\when('get_userdata')->justReturn($this->userNamed('Ada Lovelace'));
|
||||
$_GET = ['class_id' => '8'];
|
||||
|
||||
$offering = new Offering(
|
||||
|
||||
@@ -92,7 +92,10 @@ class OfferingEndpointTest extends TestCase
|
||||
public function testIndexIncludesInstructorNameForEachOffering(): void
|
||||
{
|
||||
$instructor = Mockery::mock(\WP_User::class);
|
||||
$instructor->display_name = 'Ada Lovelace';
|
||||
$instructor->first_name = 'Ada';
|
||||
$instructor->last_name = 'Lovelace';
|
||||
$instructor->nickname = 'ada_login';
|
||||
$instructor->display_name = 'ada_login';
|
||||
Functions\when('get_userdata')->justReturn($instructor);
|
||||
|
||||
$this->repository->shouldReceive('findAll')->andReturn([$this->group(1, Offering::ACCESS_PUBLIC)]);
|
||||
@@ -100,6 +103,7 @@ class OfferingEndpointTest extends TestCase
|
||||
|
||||
$data = $this->endpoint->index(new \WP_REST_Request())->get_data();
|
||||
|
||||
// Real name is shown, not the login-style display name.
|
||||
self::assertSame('Ada Lovelace', $data[0]['instructor_name']);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user