mirror of
https://github.com/Studio-Saelix/sencho.git
synced 2026-08-18 06:23:18 +00:00
docs: align Community and Admiral assurance positioning (#1632)
Reframe docs, OpenAPI registries copy, and License trial/expiry helpers so Community is the full AGPLv3 product and Admiral leads with current assurance (Hardened Build, Recovery Vault, support, governance). Mesh, Secrets, and Host Console stay limited-availability without Admiral sales framing.
This commit is contained in:
@@ -206,7 +206,7 @@ export function LicenseSection() {
|
||||
label={getTierDisplayName(license?.tier, license?.status)}
|
||||
helper={
|
||||
license?.status === 'expired'
|
||||
? 'Your Admiral license has expired. Renew to restore Admiral plan benefits.'
|
||||
? 'Your Admiral license has expired. Renew to restore Admiral assurance (priority support, Recovery Vault, Hardened Build, and governance).'
|
||||
: license?.status === 'disabled'
|
||||
? 'Your license has been disabled. Contact support for assistance.'
|
||||
: license?.status === 'trial' && license.trialDaysRemaining !== null
|
||||
@@ -299,7 +299,7 @@ export function LicenseSection() {
|
||||
{license?.status === 'expired' ? (
|
||||
<SettingsField
|
||||
label="Status"
|
||||
helper="Renew to restore Admiral plan benefits."
|
||||
helper="Renew to restore Admiral assurance (priority support, Recovery Vault, Hardened Build, and governance)."
|
||||
tone="error"
|
||||
>
|
||||
<div className="flex items-center gap-2 text-destructive">
|
||||
@@ -312,7 +312,7 @@ export function LicenseSection() {
|
||||
{license?.status === 'trial' && license.trialDaysRemaining !== null ? (
|
||||
<SettingsField
|
||||
label="Trial countdown"
|
||||
helper="Activate before the trial ends to keep Admiral plan benefits."
|
||||
helper="Activate before the trial ends to keep Admiral assurance (priority support, Recovery Vault, Hardened Build, and governance)."
|
||||
tone="warn"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { LicenseInfo } from '@/context/LicenseContext';
|
||||
|
||||
const useLicenseMock = vi.fn();
|
||||
|
||||
vi.mock('@/context/LicenseContext', () => ({
|
||||
useLicense: () => useLicenseMock(),
|
||||
}));
|
||||
|
||||
vi.mock('../MastheadStatsContext', () => ({
|
||||
useMastheadStats: () => {},
|
||||
}));
|
||||
|
||||
vi.mock('@/components/TierBadge', () => ({
|
||||
TierBadge: () => <span data-testid="tier-badge">tier</span>,
|
||||
}));
|
||||
|
||||
vi.mock('@/lib/api', () => ({
|
||||
apiFetch: vi.fn(async () => ({
|
||||
ok: true,
|
||||
json: async () => ({ channel: 'community' }),
|
||||
})),
|
||||
}));
|
||||
|
||||
import { LicenseSection } from '../LicenseSection';
|
||||
|
||||
const ASSURANCE =
|
||||
'Admiral assurance (priority support, Recovery Vault, Hardened Build, and governance)';
|
||||
|
||||
function baseLicense(overrides: Partial<LicenseInfo> = {}): LicenseInfo {
|
||||
return {
|
||||
tier: 'community',
|
||||
status: 'community',
|
||||
customerName: null,
|
||||
productName: null,
|
||||
maskedKey: null,
|
||||
validUntil: null,
|
||||
trialDaysRemaining: null,
|
||||
instanceId: 'abcdef0123456789',
|
||||
portalUrl: null,
|
||||
isLifetime: false,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
function mockLicense(license: LicenseInfo, isPaid = license.tier === 'paid') {
|
||||
useLicenseMock.mockReturnValue({
|
||||
license,
|
||||
isPaid,
|
||||
loading: false,
|
||||
licenseStatus: 'ready',
|
||||
licenseReady: true,
|
||||
refresh: vi.fn(),
|
||||
activate: vi.fn(),
|
||||
deactivate: vi.fn(),
|
||||
});
|
||||
}
|
||||
|
||||
describe('LicenseSection assurance copy', () => {
|
||||
beforeEach(() => {
|
||||
useLicenseMock.mockReset();
|
||||
});
|
||||
|
||||
it('describes Community as the full AGPLv3 self-hosted control plane', () => {
|
||||
mockLicense(baseLicense());
|
||||
render(<LicenseSection />);
|
||||
expect(screen.getByText('Community plan. Full AGPLv3 self-hosted control plane.')).toBeTruthy();
|
||||
expect(screen.queryByText(/plan benefits/i)).toBeNull();
|
||||
});
|
||||
|
||||
it('describes trial countdown as evaluating current Admiral assurance', () => {
|
||||
mockLicense(
|
||||
baseLicense({
|
||||
tier: 'paid',
|
||||
status: 'trial',
|
||||
trialDaysRemaining: 5,
|
||||
}),
|
||||
true,
|
||||
);
|
||||
render(<LicenseSection />);
|
||||
expect(
|
||||
screen.getByText(
|
||||
`Activate before the trial ends to keep ${ASSURANCE}.`,
|
||||
),
|
||||
).toBeTruthy();
|
||||
expect(screen.queryByText(/plan benefits/i)).toBeNull();
|
||||
expect(screen.queryByText(/Release Safety|Fleet Beacon|Production Assurance/i)).toBeNull();
|
||||
});
|
||||
|
||||
it('describes expired licenses with current assurance, not generic plan benefits', () => {
|
||||
mockLicense(
|
||||
baseLicense({
|
||||
tier: 'community',
|
||||
status: 'expired',
|
||||
}),
|
||||
false,
|
||||
);
|
||||
render(<LicenseSection />);
|
||||
expect(
|
||||
screen.getByText(
|
||||
`Your Admiral license has expired. Renew to restore ${ASSURANCE}.`,
|
||||
),
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
screen.getByText(
|
||||
`Renew to restore ${ASSURANCE}.`,
|
||||
),
|
||||
).toBeTruthy();
|
||||
expect(screen.queryByText(/plan benefits/i)).toBeNull();
|
||||
expect(screen.queryByText(/Release Safety|Fleet Beacon|Production Assurance/i)).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user