feat: sites and authors integration into existing screens (& formated all frontend files kinda accidentally)
This commit is contained in:
1 parent
3d81d2c717
commit
6b8990c55e
239 files changed
+9194
-1354
No files matched your search
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user