@actuate-media/cms-admin 0.36.1 → 0.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/layout/sidebar-brand.render.test.d.ts +2 -0
- package/dist/__tests__/layout/sidebar-brand.render.test.d.ts.map +1 -0
- package/dist/__tests__/layout/sidebar-brand.render.test.js +44 -0
- package/dist/__tests__/layout/sidebar-brand.render.test.js.map +1 -0
- package/dist/__tests__/views/appearance-settings.render.test.js +4 -4
- package/dist/__tests__/views/login-branding.render.test.d.ts +2 -0
- package/dist/__tests__/views/login-branding.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/login-branding.render.test.js +80 -0
- package/dist/__tests__/views/login-branding.render.test.js.map +1 -0
- package/dist/__tests__/views/login-mfa.render.test.js +6 -0
- package/dist/__tests__/views/login-mfa.render.test.js.map +1 -1
- package/dist/__tests__/views/updates-tab.render.test.d.ts +2 -0
- package/dist/__tests__/views/updates-tab.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/updates-tab.render.test.js +132 -0
- package/dist/__tests__/views/updates-tab.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/components/LogoPlaceholder.d.ts +17 -0
- package/dist/components/LogoPlaceholder.d.ts.map +1 -0
- package/dist/components/LogoPlaceholder.js +13 -0
- package/dist/components/LogoPlaceholder.js.map +1 -0
- package/dist/components/ui/Badge.d.ts +1 -1
- package/dist/components/ui/Button.d.ts +1 -1
- package/dist/components/ui/Card.d.ts +2 -2
- package/dist/components/ui/Input.d.ts +1 -1
- package/dist/components/ui/Select.d.ts +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +13 -10
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/views/Login.d.ts.map +1 -1
- package/dist/views/Login.js +66 -8
- package/dist/views/Login.js.map +1 -1
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +4 -112
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/settings/AdminThemeCard.js +1 -1
- package/dist/views/settings/BrandPreviewCard.js +1 -1
- package/dist/views/settings/BrandingCard.d.ts.map +1 -1
- package/dist/views/settings/BrandingCard.js +34 -19
- package/dist/views/settings/BrandingCard.js.map +1 -1
- package/dist/views/settings/TypographyMotionCard.js +1 -1
- package/dist/views/settings/UpdatesTab.d.ts +6 -0
- package/dist/views/settings/UpdatesTab.d.ts.map +1 -0
- package/dist/views/settings/UpdatesTab.js +80 -0
- package/dist/views/settings/UpdatesTab.js.map +1 -0
- package/dist/views/settings/components.d.ts +20 -0
- package/dist/views/settings/components.d.ts.map +1 -1
- package/dist/views/settings/components.js +11 -0
- package/dist/views/settings/components.js.map +1 -1
- package/dist/views/settings/useUpdates.d.ts +67 -0
- package/dist/views/settings/useUpdates.d.ts.map +1 -0
- package/dist/views/settings/useUpdates.js +127 -0
- package/dist/views/settings/useUpdates.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/layout/sidebar-brand.render.test.tsx +58 -0
- package/src/__tests__/views/appearance-settings.render.test.tsx +4 -4
- package/src/__tests__/views/login-branding.render.test.tsx +96 -0
- package/src/__tests__/views/login-mfa.render.test.tsx +7 -0
- package/src/__tests__/views/updates-tab.render.test.tsx +161 -0
- package/src/components/LogoPlaceholder.tsx +55 -0
- package/src/layout/Sidebar.tsx +14 -24
- package/src/views/Login.tsx +70 -9
- package/src/views/Settings.tsx +2 -438
- package/src/views/settings/AdminThemeCard.tsx +1 -1
- package/src/views/settings/BrandPreviewCard.tsx +1 -1
- package/src/views/settings/BrandingCard.tsx +179 -180
- package/src/views/settings/TypographyMotionCard.tsx +1 -1
- package/src/views/settings/UpdatesTab.tsx +545 -0
- package/src/views/settings/components.tsx +51 -0
- package/src/views/settings/useUpdates.ts +183 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-brand.render.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/layout/sidebar-brand.render.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
// The sidebar fetches forms unread counts on mount; stub it so these brand
|
|
6
|
+
// tests stay offline and deterministic.
|
|
7
|
+
vi.mock('../../lib/forms-service.js', () => ({
|
|
8
|
+
fetchFormsSidebarCounts: vi.fn(async () => []),
|
|
9
|
+
}));
|
|
10
|
+
// Drive the brand lockup directly: a branded install (initials derived from a
|
|
11
|
+
// site title) with no uploaded logo. happy-dom's localStorage stub is
|
|
12
|
+
// unreliable here, so we mock the theme hook rather than hydrating it.
|
|
13
|
+
vi.mock('../../components/ThemeProvider.js', () => ({
|
|
14
|
+
useTheme: () => ({
|
|
15
|
+
adminBrand: { primaryUrl: null, markUrl: null, darkUrl: null, initials: 'AC' },
|
|
16
|
+
resolvedTheme: 'light',
|
|
17
|
+
density: 'default',
|
|
18
|
+
}),
|
|
19
|
+
}));
|
|
20
|
+
const { Sidebar } = await import('../../layout/Sidebar.js');
|
|
21
|
+
/**
|
|
22
|
+
* Brand lockup fallback behaviour. When an install is branded (a site name is
|
|
23
|
+
* set, so initials exist) but no logo has been uploaded, the sidebar must show
|
|
24
|
+
* the neutral logo placeholder — NOT a filled initials badge, which reads as a
|
|
25
|
+
* user avatar (the real account avatar already lives top-right).
|
|
26
|
+
*/
|
|
27
|
+
function renderSidebar(collapsed, config) {
|
|
28
|
+
return render(_jsx(Sidebar, { collapsed: collapsed, onToggleCollapse: () => { }, currentPath: "/", onNavigate: () => { }, config: config }));
|
|
29
|
+
}
|
|
30
|
+
describe('Sidebar brand placeholder', () => {
|
|
31
|
+
it('renders the logo placeholder (not an initials avatar) when branded with no logo — expanded', () => {
|
|
32
|
+
renderSidebar(false, { admin: { branding: { name: 'Acme Co' } } });
|
|
33
|
+
// Placeholder slot is present and the brand name shows beside it.
|
|
34
|
+
expect(screen.getByText('Acme Co')).toBeTruthy();
|
|
35
|
+
// The old avatar-style initials badge must not render.
|
|
36
|
+
expect(screen.queryByText('AC')).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
it('renders the logo placeholder slot when branded with no logo — collapsed', () => {
|
|
39
|
+
renderSidebar(true);
|
|
40
|
+
expect(screen.getByRole('img', { name: 'Logo placeholder' })).toBeTruthy();
|
|
41
|
+
expect(screen.queryByText('AC')).toBeNull();
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=sidebar-brand.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-brand.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/layout/sidebar-brand.render.test.tsx"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AAEvD,2EAA2E;AAC3E,wCAAwC;AACxC,EAAE,CAAC,IAAI,CAAC,4BAA4B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC3C,uBAAuB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC;CAC/C,CAAC,CAAC,CAAA;AAEH,8EAA8E;AAC9E,sEAAsE;AACtE,uEAAuE;AACvE,EAAE,CAAC,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE,CAAC,CAAC;IAClD,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;QACf,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;QAC9E,aAAa,EAAE,OAAO;QACtB,OAAO,EAAE,SAAS;KACnB,CAAC;CACH,CAAC,CAAC,CAAA;AAEH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;AAE3D;;;;;GAKG;AACH,SAAS,aAAa,CAAC,SAAkB,EAAE,MAAgB;IACzD,OAAO,MAAM,CACX,KAAC,OAAO,IACN,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC,EAC1B,WAAW,EAAC,GAAG,EACf,UAAU,EAAE,GAAG,EAAE,GAAE,CAAC,EACpB,MAAM,EAAE,MAAM,GACd,CACH,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,aAAa,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAA;QAElE,kEAAkE;QAClE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;QAChD,uDAAuD;QACvD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,aAAa,CAAC,IAAI,CAAC,CAAA;QAEnB,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;QAC1E,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -46,9 +46,9 @@ describe('AppearanceTab', () => {
|
|
|
46
46
|
it('renders the branding/theme/typography cards with a clean (disabled) save bar', async () => {
|
|
47
47
|
render(_jsx(AppearanceTab, { role: "ADMIN" }));
|
|
48
48
|
await screen.findByText('Branding');
|
|
49
|
-
expect(screen.getByText('Admin
|
|
50
|
-
expect(screen.getByText('Typography &
|
|
51
|
-
expect(screen.getByText('Brand
|
|
49
|
+
expect(screen.getByText('Admin theme')).toBeTruthy();
|
|
50
|
+
expect(screen.getByText('Typography & motion')).toBeTruthy();
|
|
51
|
+
expect(screen.getByText('Brand preview')).toBeTruthy();
|
|
52
52
|
expect(screen.getByRole('button', { name: 'Save Changes' }).disabled).toBe(true);
|
|
53
53
|
});
|
|
54
54
|
it('enables Save when the accent changes and persists appearance to the settings global', async () => {
|
|
@@ -79,7 +79,7 @@ describe('AppearanceTab', () => {
|
|
|
79
79
|
it('uploads a logo through the Media Center and enables Save', async () => {
|
|
80
80
|
render(_jsx(AppearanceTab, { role: "ADMIN" }));
|
|
81
81
|
await screen.findByText('Branding');
|
|
82
|
-
const input = screen.getByLabelText('Primary
|
|
82
|
+
const input = screen.getByLabelText('Primary logo');
|
|
83
83
|
const file = new File(['<svg viewBox="0 0 400 100" xmlns="http://www.w3.org/2000/svg"></svg>'], 'logo.svg', { type: 'image/svg+xml' });
|
|
84
84
|
fireEvent.change(input, { target: { files: [file] } });
|
|
85
85
|
await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/media/upload', expect.objectContaining({ method: 'POST' })));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-branding.render.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/views/login-branding.render.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { describe, expect, it, vi, beforeEach } from 'vitest';
|
|
4
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
5
|
+
/**
|
|
6
|
+
* The login screen resolves its logo to match the admin sidebar:
|
|
7
|
+
* 1. the brand uploaded in Settings → Appearance (cached admin brand, then
|
|
8
|
+
* the unauthenticated `/public/brand` endpoint for fresh browsers),
|
|
9
|
+
* 2. the static `config.admin.branding.logo`,
|
|
10
|
+
* 3. the bundled Actuate wordmark,
|
|
11
|
+
* and `branding.logo === null` hides the logo entirely (whitelabel opt-out).
|
|
12
|
+
*
|
|
13
|
+
* `cmsApi` is mocked because the component fetches `/public/brand` on mount.
|
|
14
|
+
*/
|
|
15
|
+
const cmsApiMock = vi.fn();
|
|
16
|
+
vi.mock('../../lib/api.js', () => ({
|
|
17
|
+
cmsApi: (...args) => cmsApiMock(...args),
|
|
18
|
+
}));
|
|
19
|
+
import { Login } from '../../views/Login.js';
|
|
20
|
+
const onLogin = vi.fn(async () => ({ success: true }));
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
cmsApiMock.mockReset();
|
|
23
|
+
// Default: no public brand configured.
|
|
24
|
+
cmsApiMock.mockResolvedValue({ data: {}, status: 200 });
|
|
25
|
+
});
|
|
26
|
+
describe('Login — logo resolution', () => {
|
|
27
|
+
it('renders the bundled Actuate logo when nothing is branded', async () => {
|
|
28
|
+
render(_jsx(Login, { onLogin: onLogin }));
|
|
29
|
+
// Bundled SVG exposes role="img" + aria-label="Actuate Media".
|
|
30
|
+
expect(screen.getByRole('img', { name: 'Actuate Media' })).toBeTruthy();
|
|
31
|
+
// No <img> logo element.
|
|
32
|
+
expect(screen.queryByRole('img', { name: 'Actuate CMS' })).toBeNull();
|
|
33
|
+
await waitFor(() => expect(cmsApiMock).toHaveBeenCalledWith('/public/brand'));
|
|
34
|
+
});
|
|
35
|
+
it('shows the neutral logo placeholder when branded but no logo is set', async () => {
|
|
36
|
+
render(_jsx(Login, { onLogin: onLogin, branding: { name: 'Acme Co' } }));
|
|
37
|
+
// Placeholder slot, not the bundled Actuate wordmark.
|
|
38
|
+
expect(screen.getByRole('img', { name: 'Logo placeholder' })).toBeTruthy();
|
|
39
|
+
expect(screen.queryByRole('img', { name: 'Actuate Media' })).toBeNull();
|
|
40
|
+
// The brand name still renders as the headline.
|
|
41
|
+
expect(screen.getByRole('heading', { name: 'Acme Co' })).toBeTruthy();
|
|
42
|
+
});
|
|
43
|
+
it('shows the placeholder for a fresh browser when /public/brand reports a branded site (initials) but no logo', async () => {
|
|
44
|
+
// No config name, no cached admin brand — only the public brand initials
|
|
45
|
+
// signal a branded install. The logo-less fallback must be the placeholder,
|
|
46
|
+
// not the Actuate wordmark.
|
|
47
|
+
cmsApiMock.mockResolvedValue({
|
|
48
|
+
data: { public: { primary: null, initials: 'AC' } },
|
|
49
|
+
status: 200,
|
|
50
|
+
});
|
|
51
|
+
render(_jsx(Login, { onLogin: onLogin }));
|
|
52
|
+
await waitFor(() => {
|
|
53
|
+
expect(screen.getByRole('img', { name: 'Logo placeholder' })).toBeTruthy();
|
|
54
|
+
});
|
|
55
|
+
expect(screen.queryByRole('img', { name: 'Actuate Media' })).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
it('uses the static config logo when no appearance brand exists', async () => {
|
|
58
|
+
render(_jsx(Login, { onLogin: onLogin, branding: { logo: 'https://cdn.example.com/config-logo.png' } }));
|
|
59
|
+
const img = (await screen.findByAltText('Actuate CMS'));
|
|
60
|
+
expect(img.getAttribute('src')).toBe('https://cdn.example.com/config-logo.png');
|
|
61
|
+
});
|
|
62
|
+
it('prefers the uploaded appearance logo from /public/brand over the config logo', async () => {
|
|
63
|
+
cmsApiMock.mockResolvedValue({
|
|
64
|
+
data: { public: { primary: { url: 'https://cdn.example.com/appearance-logo.svg' } } },
|
|
65
|
+
status: 200,
|
|
66
|
+
});
|
|
67
|
+
render(_jsx(Login, { onLogin: onLogin, branding: { logo: 'https://cdn.example.com/config-logo.png' } }));
|
|
68
|
+
await waitFor(() => {
|
|
69
|
+
const img = screen.getByAltText('Actuate CMS');
|
|
70
|
+
expect(img.getAttribute('src')).toBe('https://cdn.example.com/appearance-logo.svg');
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
it('hides the logo entirely when branding.logo is null (whitelabel) and skips the fetch', async () => {
|
|
74
|
+
render(_jsx(Login, { onLogin: onLogin, branding: { logo: null } }));
|
|
75
|
+
expect(screen.queryByRole('img', { name: 'Actuate Media' })).toBeNull();
|
|
76
|
+
expect(screen.queryByAltText('Actuate CMS')).toBeNull();
|
|
77
|
+
expect(cmsApiMock).not.toHaveBeenCalled();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
//# sourceMappingURL=login-branding.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-branding.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/login-branding.render.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
// @vitest-environment happy-dom
|
|
3
3
|
import { describe, expect, it, vi } from 'vitest';
|
|
4
4
|
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
5
|
+
// The login screen fetches `/public/brand` on mount to mirror the sidebar
|
|
6
|
+
// logo. These MFA tests don't care about branding — stub the network so the
|
|
7
|
+
// real `cmsApi` (which reads localStorage) doesn't run in this environment.
|
|
8
|
+
vi.mock('../../lib/api.js', () => ({
|
|
9
|
+
cmsApi: vi.fn(async () => ({ data: {}, status: 200 })),
|
|
10
|
+
}));
|
|
5
11
|
import { Login } from '../../views/Login.js';
|
|
6
12
|
/**
|
|
7
13
|
* The login screen must advance to a second-factor challenge when the account
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-mfa.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/login-mfa.render.test.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"login-mfa.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/login-mfa.render.test.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updates-tab.render.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/views/updates-tab.render.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
|
5
|
+
// The Updates tab reads `/updates/check`, saves GitHub config via
|
|
6
|
+
// PUT `/updates/config`, and opens an upgrade PR via POST `/updates/apply`.
|
|
7
|
+
let checkData;
|
|
8
|
+
const cmsApi = vi.fn(async (endpoint, options) => {
|
|
9
|
+
const method = options?.method ?? 'GET';
|
|
10
|
+
if (endpoint === '/updates/check' && method === 'GET')
|
|
11
|
+
return { data: checkData, status: 200 };
|
|
12
|
+
if (endpoint === '/updates/config' && method === 'PUT')
|
|
13
|
+
return { data: { success: true }, status: 200 };
|
|
14
|
+
if (endpoint === '/updates/apply' && method === 'POST')
|
|
15
|
+
return { data: { prUrl: 'https://github.com/x/y/pull/1', prNumber: 1 }, status: 200 };
|
|
16
|
+
return { data: {}, status: 200 };
|
|
17
|
+
});
|
|
18
|
+
vi.mock('../../lib/api.js', () => ({ cmsApi: (e, o) => cmsApi(e, o) }));
|
|
19
|
+
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), loading: vi.fn() } }));
|
|
20
|
+
const { UpdatesTab } = await import('../../views/settings/UpdatesTab.js');
|
|
21
|
+
function upToDate(overrides = {}) {
|
|
22
|
+
return {
|
|
23
|
+
current: '0.46.0',
|
|
24
|
+
latest: '0.46.0',
|
|
25
|
+
updateAvailable: false,
|
|
26
|
+
canManage: true,
|
|
27
|
+
hasGithubToken: false,
|
|
28
|
+
githubRepo: '',
|
|
29
|
+
source: 'update-server',
|
|
30
|
+
...overrides,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function updateAvailable(overrides = {}) {
|
|
34
|
+
return {
|
|
35
|
+
current: '0.45.0',
|
|
36
|
+
latest: '0.46.0',
|
|
37
|
+
updateAvailable: true,
|
|
38
|
+
severity: 'minor',
|
|
39
|
+
releaseDate: '2026-01-02',
|
|
40
|
+
changelog: [
|
|
41
|
+
{
|
|
42
|
+
version: '0.46.0',
|
|
43
|
+
date: '2026-01-02',
|
|
44
|
+
summary: 'Add Brand Voice training',
|
|
45
|
+
type: 'feature',
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
hasMigrations: true,
|
|
49
|
+
breakingChanges: ['Removed the legacy provider API'],
|
|
50
|
+
pluginCompatibility: [
|
|
51
|
+
{ name: '@actuate-media/plugin-seo', compatible: true, minVersion: '0.46.0' },
|
|
52
|
+
],
|
|
53
|
+
updateCommand: 'npm update @actuate-media/cms-core',
|
|
54
|
+
canManage: true,
|
|
55
|
+
hasGithubToken: false,
|
|
56
|
+
githubRepo: '',
|
|
57
|
+
source: 'update-server',
|
|
58
|
+
...overrides,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
beforeEach(() => {
|
|
62
|
+
cmsApi.mockClear();
|
|
63
|
+
checkData = upToDate();
|
|
64
|
+
});
|
|
65
|
+
describe('UpdatesTab', () => {
|
|
66
|
+
it('shows the current version and an up-to-date banner', async () => {
|
|
67
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
68
|
+
await screen.findByText("You're up to date!");
|
|
69
|
+
expect(screen.getAllByText('0.46.0').length).toBeGreaterThan(0);
|
|
70
|
+
// Admins see the GitHub integration card.
|
|
71
|
+
expect(screen.getByText('GitHub Integration')).toBeTruthy();
|
|
72
|
+
});
|
|
73
|
+
it('surfaces severity, real changelog, migrations and breaking changes', async () => {
|
|
74
|
+
checkData = updateAvailable();
|
|
75
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
76
|
+
await screen.findByText('Update available');
|
|
77
|
+
expect(screen.getByText('Minor')).toBeTruthy();
|
|
78
|
+
expect(screen.getByText('Add Brand Voice training')).toBeTruthy();
|
|
79
|
+
expect(screen.getByText('Database migrations required')).toBeTruthy();
|
|
80
|
+
expect(screen.getByText('Breaking changes in this release')).toBeTruthy();
|
|
81
|
+
expect(screen.getByText('Removed the legacy provider API')).toBeTruthy();
|
|
82
|
+
// Plugin compatibility surfaced.
|
|
83
|
+
expect(screen.getByText('plugin-seo')).toBeTruthy();
|
|
84
|
+
expect(screen.getByRole('button', { name: 'Create Update PR' })).toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
it('flags a security release prominently', async () => {
|
|
87
|
+
checkData = updateAvailable({ severity: 'security' });
|
|
88
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
89
|
+
await screen.findByText('Security update available');
|
|
90
|
+
expect(screen.getByText('Security')).toBeTruthy();
|
|
91
|
+
});
|
|
92
|
+
it('is permission-aware: non-admins cannot manage updates', async () => {
|
|
93
|
+
checkData = updateAvailable({ canManage: false });
|
|
94
|
+
render(_jsx(UpdatesTab, { role: "EDITOR" }));
|
|
95
|
+
await screen.findByText('Update available');
|
|
96
|
+
expect(screen.queryByText('GitHub Integration')).toBeNull();
|
|
97
|
+
expect(screen.queryByRole('button', { name: 'Create Update PR' })).toBeNull();
|
|
98
|
+
expect(screen.getByText(/Ask an administrator/i)).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
it('enables Save when the repo changes and persists via PUT /updates/config', async () => {
|
|
101
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
102
|
+
await screen.findByText('GitHub Integration');
|
|
103
|
+
const save = screen.getByRole('button', { name: 'Save Changes' });
|
|
104
|
+
expect(save.disabled).toBe(true);
|
|
105
|
+
const repo = screen.getByLabelText('Repository');
|
|
106
|
+
fireEvent.change(repo, { target: { value: 'actuate-media/site' } });
|
|
107
|
+
expect(save.disabled).toBe(false);
|
|
108
|
+
fireEvent.click(save);
|
|
109
|
+
await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/updates/config', expect.objectContaining({
|
|
110
|
+
method: 'PUT',
|
|
111
|
+
body: expect.stringContaining('actuate-media/site'),
|
|
112
|
+
})));
|
|
113
|
+
});
|
|
114
|
+
it('blocks Save on an invalid repository format', async () => {
|
|
115
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
116
|
+
await screen.findByText('GitHub Integration');
|
|
117
|
+
const repo = screen.getByLabelText('Repository');
|
|
118
|
+
fireEvent.change(repo, { target: { value: 'not a repo' } });
|
|
119
|
+
expect(screen.getByText(/owner\/repo format/i)).toBeTruthy();
|
|
120
|
+
const save = screen.getByRole('button', { name: 'Save Changes' });
|
|
121
|
+
expect(save.disabled).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
it('creates an update PR via POST /updates/apply', async () => {
|
|
124
|
+
checkData = updateAvailable();
|
|
125
|
+
render(_jsx(UpdatesTab, { role: "ADMIN" }));
|
|
126
|
+
await screen.findByText('Update available');
|
|
127
|
+
fireEvent.click(screen.getByRole('button', { name: 'Create Update PR' }));
|
|
128
|
+
await waitFor(() => expect(cmsApi).toHaveBeenCalledWith('/updates/apply', expect.objectContaining({ method: 'POST', body: expect.stringContaining('0.46.0') })));
|
|
129
|
+
await screen.findByText('Pull Request Created');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
//# sourceMappingURL=updates-tab.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updates-tab.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/updates-tab.render.test.tsx"],"names":[],"mappings":"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"}
|