feat: sites and authors integration into existing screens (& formated all frontend files kinda accidentally)

This commit is contained in:
Florian Sylvain committed 2026-10-15 05:25:44 +02:00
1 parent 3d81d2c717
commit 6b8990c55e
239 files changed
+9194 -1354

No files matched your search

+45 -16
View File
@@ -106,7 +106,10 @@ async function mountApp(options: MountOptions = {}): Promise<Mounted> {
return Promise.resolve([])
})
const getMe = vi.fn(options.getMe ?? (() => Promise.resolve({ ...MARTA })))
vi.mocked(useApi).mockReturnValue({ getMe, request } as unknown as ReturnType<typeof useApi>)
vi.mocked(useApi).mockReturnValue({
getMe,
request,
} as unknown as ReturnType<typeof useApi>)
await router.push(path)
const wrapper = mount(App, {
attachTo: document.body,
@@ -130,7 +133,11 @@ async function typeInto(value: string) {
function pressEnter() {
displayNameField().dispatchEvent(
new KeyboardEvent('keydown', { key: 'Enter', bubbles: true, cancelable: true }),
new KeyboardEvent('keydown', {
key: 'Enter',
bubbles: true,
cancelable: true,
}),
)
}
@@ -198,7 +205,11 @@ function activate(element: HTMLElement) {
}
function savedResponse(displayName: string) {
return Promise.resolve({ id: 1, username: 'marta', display_name: displayName })
return Promise.resolve({
id: 1,
username: 'marta',
display_name: displayName,
})
}
const NETWORK_ERROR = () => Promise.reject(new NetworkError())
@@ -287,18 +298,18 @@ describe('Default: the usual first visit with no display name', () => {
links.forEach((link) => expect(link.getAttribute('aria-current')).toBeNull())
})
it('places the three cards in order Display name, Account, Password', async () => {
it('places the four cards in order Display name, Account, Author profile, Password', async () => {
await mountApp()
const titles = Array.from(document.body.querySelectorAll('section h2')).map((el) =>
el.textContent?.trim(),
)
expect(titles).toEqual(['Display name', 'Account', 'Password'])
expect(titles).toEqual(['Display name', 'Account', 'Author profile', 'Password'])
})
})
describe('Loading: opened by URL before /auth/me has returned', () => {
it('shows the header and three skeleton cards without AppBoot, then the Default state', async () => {
it('shows the header and four skeleton cards without AppBoot, then the Default state', async () => {
const pending = deferred<Session>()
await mountApp({
session: null,
@@ -311,7 +322,7 @@ describe('Loading: opened by URL before /auth/me has returned', () => {
)
expect(document.body.textContent).toContain('Your account on this RenewCMS workspace.')
const busy = document.body.querySelector('[aria-busy="true"]')!
expect(busy.querySelectorAll('[data-testid="profile-skeleton-card"]')).toHaveLength(3)
expect(busy.querySelectorAll('[data-testid="profile-skeleton-card"]')).toHaveLength(4)
expect(document.body.querySelector('[aria-label="Loading"]')).toBeNull()
expect(displayNameField()).toBeNull()
@@ -430,7 +441,9 @@ describe('Dirty is measured on the trimmed draft against the saved name', () =>
describe('Enter saves when Save is enabled', () => {
it('sends PATCH /v1/user/me once with the trimmed display name', async () => {
const { request } = await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves'),
},
})
await typeInto('Marta Alves')
@@ -477,7 +490,9 @@ describe('Saving: the field is disabled and a second submit is ignored', () => {
describe('Saved: a 200 updates the session, the chip, the footer and raises a toast', () => {
it('replaces the session name, syncs the field, and raises the success toast', async () => {
const { request } = await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves'),
},
})
await typeInto('Marta Alves')
@@ -503,7 +518,9 @@ describe('Saved: a 200 updates the session, the chip, the footer and raises a to
it('opens no leave confirmation when navigating away afterwards', async () => {
await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves'),
},
})
await typeInto('Marta Alves')
await clickSave()
@@ -519,7 +536,9 @@ describe('Saved: a 200 updates the session, the chip, the footer and raises a to
describe("The server's value wins over what was typed", () => {
it('uses the response display_name in the field, the chip and the toast', async () => {
await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves'),
},
})
await typeInto(' Marta Alves ')
@@ -535,7 +554,9 @@ describe('Clearing the display name goes back to the username', () => {
it('sends an empty display_name and shows the username with the removed toast', async () => {
const { request } = await mountApp({
session: { ...MARTA, displayName: 'Marta Alves' },
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse(''),
},
})
await typeInto('')
@@ -565,7 +586,9 @@ describe('Save failed: a 500 or a network failure keeps the text and offers a re
async (_label, failure) => {
const attempts = [failure, () => savedResponse('Marta Alves')]
const { request } = await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => attempts.shift()!() },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => attempts.shift()!(),
},
})
await typeInto('Marta Alves')
@@ -594,7 +617,9 @@ describe('Save failed: a 500 or a network failure keeps the text and offers a re
const retry = deferred()
const attempts = [SERVER_ERROR, () => retry.promise]
await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => attempts.shift()!() },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => attempts.shift()!(),
},
})
await typeInto('Marta Alves')
await clickSave()
@@ -727,7 +752,9 @@ describe('The Home greeting follows a display name saved on /profile', () => {
it('shows the saved name on /home without a reload', async () => {
vi.spyOn(Date.prototype, 'getHours').mockReturnValue(9)
await mountApp({
handlers: { [`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves') },
handlers: {
[`PATCH ${DISPLAY_NAME_PATH}`]: () => savedResponse('Marta Alves'),
},
})
await typeInto('Marta Alves')
await clickSave()
@@ -851,7 +878,9 @@ describe('Reset: failed leaves the button pressable', () => {
async (_label, failure) => {
const responses = [failure, () => Promise.resolve({ message: 'ok' })]
await mountApp({
handlers: { [`POST ${RESET_PATH}`]: () => responses.shift()!() },
handlers: {
[`POST ${RESET_PATH}`]: () => responses.shift()!(),
},
})
await clickReset()