Files
thatguygriffandClaude Opus 5 3a954bac57
CI / Tests (PHP 8.1) (pull_request) Successful in 50s
CI / Tests (PHP 8.2) (pull_request) Successful in 1m12s
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 2m50s
CI / PHPStan (pull_request) Successful in 3m4s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m42s
CI / Build Plugin Zip (pull_request) Skipped
View a policy version's content, and make policy text readable
The Policies admin page listed versions but never showed what any of them
said, so revising a policy meant retyping it blind into an empty draft box.
Each version row now has a View action that renders that version's text on
the page, editable in place. A draft is saved back to itself; editing a
published or archived version branches a new draft and leaves the original
alone, because acceptances are recorded against policy_version_id and text a
student agreed to must stay exactly as they saw it.

That viewer also exposed why a studio reported the acceptance box as
unreadable — one squashed line, overlapping words, a horizontal scrollbar.
Bodies are typed into a bare textarea, so most carry no markup, and the raw
text was emitted with its blank lines intact but nothing to turn them into
paragraphs. PolicyVersion::bodyHtml() now renders every body the way
WordPress renders post content (kses, then wpautop) and feeds all three
consumers: the booking/enrolment JSON, the signup form, and the new viewer.
Bodies written with markup are unaffected.

The other half was that .us-policy-body had no CSS whatsoever and inherited
whatever the theme did with an unstyled block in a form. It is now a bounded
reading box that scrolls vertically and breaks long tokens, so a pasted URL
cannot force the page sideways and a long policy cannot push the accept
checkbox out of view. RegistrationPage was also never enqueueing the plugin
stylesheet, which is why the signup gate looked worst of all.

Closes #126
Closes #127

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-07-28 17:05:00 -03:00

110 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace Unsupervised\Schedular\Tests\Unit\Policy;
use Unsupervised\Schedular\Policy\Policy;
use Unsupervised\Schedular\Policy\PolicyAcceptance;
use Unsupervised\Schedular\Policy\PolicyVersion;
use Unsupervised\Schedular\Tests\Unit\TestCase;
class PolicyValueObjectsTest extends TestCase
{
public function testPolicyFromRowAndToArray(): void
{
$policy = Policy::fromRow((object) [
'id' => '4',
'title' => 'Cancellation',
'slug' => 'cancellation',
'current_version_id' => '9',
'acceptance_scope' => Policy::SCOPE_BOTH,
]);
self::assertSame(4, $policy->id);
self::assertSame('cancellation', $policy->slug);
self::assertSame(9, $policy->currentVersionId);
self::assertSame(Policy::SCOPE_BOTH, $policy->acceptanceScope);
self::assertArrayHasKey('acceptance_scope', $policy->toArray());
}
public function testAnEmptyBodyRendersAsNothingRatherThanAnEmptyParagraph(): void
{
\Brain\Monkey\Functions\when('wp_kses_post')->returnArg();
$this->stubAutop();
$version = new PolicyVersion(policyId: 4, versionNumber: 1, body: null);
self::assertSame('', $version->bodyHtml());
}
public function testPolicyHandlesNullCurrentVersion(): void
{
$policy = Policy::fromRow((object) [
'id' => '4',
'title' => 'Cancellation',
'slug' => 'cancellation',
'current_version_id' => null,
'acceptance_scope' => Policy::SCOPE_BOOKING,
]);
self::assertNull($policy->currentVersionId);
}
public function testPolicyAppliesToScopeAndBoth(): void
{
$signup = new Policy('Terms', 'terms', acceptanceScope: Policy::SCOPE_SIGNUP);
self::assertTrue($signup->appliesTo(Policy::SCOPE_SIGNUP));
self::assertFalse($signup->appliesTo(Policy::SCOPE_BOOKING));
$both = new Policy('Both', 'both', acceptanceScope: Policy::SCOPE_BOTH);
self::assertTrue($both->appliesTo(Policy::SCOPE_SIGNUP));
self::assertTrue($both->appliesTo(Policy::SCOPE_BOOKING));
}
public function testPolicyVersionFromRowAndStatusHelper(): void
{
$version = PolicyVersion::fromRow((object) [
'id' => '9',
'policy_id' => '4',
'version_number' => '2',
'body' => '<p>Policy</p>',
'status' => PolicyVersion::STATUS_PUBLISHED,
'published_at' => '2026-06-01 10:00:00',
]);
self::assertSame(9, $version->id);
self::assertSame(2, $version->versionNumber);
self::assertTrue($version->isPublished());
self::assertSame('2026-06-01 10:00:00', $version->publishedAt);
}
public function testPolicyVersionDefaultsToDraft(): void
{
$version = new PolicyVersion(4, 1);
self::assertSame(PolicyVersion::STATUS_DRAFT, $version->status);
self::assertFalse($version->isPublished());
self::assertNull($version->publishedAt);
self::assertContains(PolicyVersion::STATUS_ARCHIVED, PolicyVersion::VALID_STATUSES);
}
public function testPolicyAcceptanceFromRowAndToArray(): void
{
$acceptance = PolicyAcceptance::fromRow((object) [
'id' => '1',
'policy_version_id' => '9',
'student_id' => '5',
'registration_type' => PolicyAcceptance::REG_LESSON,
'registration_id' => '12',
'accepted_at' => '2026-06-02 09:00:00',
'ip_address' => '203.0.113.7',
]);
self::assertSame(9, $acceptance->policyVersionId);
self::assertSame(PolicyAcceptance::REG_LESSON, $acceptance->registrationType);
self::assertSame('203.0.113.7', $acceptance->ipAddress);
self::assertArrayHasKey('policy_version_id', $acceptance->toArray());
self::assertContains(PolicyAcceptance::REG_ENROLLMENT, PolicyAcceptance::VALID_REGISTRATION_TYPES);
}
}