feat: entry list at /content/:key
This commit is contained in:
1 parent
b4cbcb0395
commit
91d916fb74
44 files changed
+4984
-32
No files matched your search
@@ -0,0 +1,250 @@
|
||||
import { vi } from 'vitest'
|
||||
import { flushPromises } from '@vue/test-utils'
|
||||
import { addCollection } from '@iconify/vue'
|
||||
import lucide from 'virtual:lucide-subset'
|
||||
import { mountAt, type SchemaMount } from './schemaTestKit'
|
||||
|
||||
export {
|
||||
button,
|
||||
calls,
|
||||
customTypes,
|
||||
failWith,
|
||||
failWithBody,
|
||||
manyTypes,
|
||||
networkFailure,
|
||||
pending,
|
||||
text,
|
||||
unmountAll,
|
||||
} from './schemaTestKit'
|
||||
|
||||
addCollection(lucide)
|
||||
|
||||
export const SKELETON_DELAY_MS = 150
|
||||
export const DEFAULT_SORT = 'updated_at:desc'
|
||||
|
||||
const MARTA = 3
|
||||
const INES = 4
|
||||
const JONAS = 5
|
||||
|
||||
type Row = [
|
||||
number,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
boolean,
|
||||
number | null,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
number,
|
||||
]
|
||||
|
||||
const ROWS: Row[] = [
|
||||
[
|
||||
42,
|
||||
'Lime plaster workshop',
|
||||
'2026-11-21',
|
||||
'2026-11-22',
|
||||
false,
|
||||
18,
|
||||
'Workshop',
|
||||
'Two days of hands-on work with lime putty and old stone.',
|
||||
'2026-10-12',
|
||||
'2026-10-15',
|
||||
MARTA,
|
||||
],
|
||||
[
|
||||
41,
|
||||
'Heat pumps: what the numbers say',
|
||||
'2026-11-03',
|
||||
'',
|
||||
true,
|
||||
500,
|
||||
'Talk',
|
||||
'A look at running costs after two winters.',
|
||||
'2026-10-08',
|
||||
'2026-10-14',
|
||||
JONAS,
|
||||
],
|
||||
[
|
||||
40,
|
||||
'Open day at the Rue Verte site',
|
||||
'2026-11-12',
|
||||
'2026-11-12',
|
||||
false,
|
||||
120,
|
||||
'Meetup',
|
||||
'',
|
||||
'2026-10-02',
|
||||
'2026-10-12',
|
||||
INES,
|
||||
],
|
||||
[
|
||||
39,
|
||||
'Winter windows clinic',
|
||||
'2026-12-05',
|
||||
'',
|
||||
false,
|
||||
null,
|
||||
'Workshop',
|
||||
'Bring a window, leave with a plan.',
|
||||
'2026-09-30',
|
||||
'2026-10-09',
|
||||
MARTA,
|
||||
],
|
||||
[
|
||||
38,
|
||||
'Timber joinery for beginners',
|
||||
'2027-01-14',
|
||||
'2027-01-15',
|
||||
false,
|
||||
12,
|
||||
'Workshop',
|
||||
'Mortise, tenon and a lot of patience.',
|
||||
'2026-09-28',
|
||||
'2026-10-07',
|
||||
INES,
|
||||
],
|
||||
[
|
||||
37,
|
||||
'Q&A with the site managers',
|
||||
'2026-10-28',
|
||||
'',
|
||||
true,
|
||||
null,
|
||||
'Meetup',
|
||||
'',
|
||||
'2026-09-21',
|
||||
'2026-10-02',
|
||||
JONAS,
|
||||
],
|
||||
[
|
||||
36,
|
||||
'Reclaimed floorboards talk',
|
||||
'2026-10-17',
|
||||
'',
|
||||
false,
|
||||
60,
|
||||
'Talk',
|
||||
'Where to find them and how to lay them.',
|
||||
'2026-09-14',
|
||||
'2026-09-29',
|
||||
MARTA,
|
||||
],
|
||||
]
|
||||
|
||||
export function entry(row: Row) {
|
||||
const [
|
||||
id,
|
||||
title,
|
||||
startsOn,
|
||||
endsOn,
|
||||
online,
|
||||
capacity,
|
||||
category,
|
||||
description,
|
||||
created,
|
||||
updated,
|
||||
by,
|
||||
] = row
|
||||
return {
|
||||
id,
|
||||
content_type_id: 1,
|
||||
data: {
|
||||
title,
|
||||
starts_on: startsOn,
|
||||
ends_on: endsOn,
|
||||
online,
|
||||
capacity,
|
||||
category,
|
||||
description,
|
||||
},
|
||||
created_by: by,
|
||||
updated_by: by,
|
||||
created_at: `${created}T09:14:00Z`,
|
||||
updated_at: `${updated}T11:02:00Z`,
|
||||
}
|
||||
}
|
||||
|
||||
export const eventEntries = ROWS.map(entry)
|
||||
|
||||
export const userNames = [
|
||||
{ id: MARTA, display_name: 'Marta Alves' },
|
||||
{ id: INES, display_name: 'Inès Duarte' },
|
||||
{ id: JONAS, display_name: 'Jonas Pereira' },
|
||||
]
|
||||
|
||||
export function listPage(items: unknown[], total: number, query: URLSearchParams) {
|
||||
return {
|
||||
items,
|
||||
total,
|
||||
page: Number(query.get('page')),
|
||||
size: Number(query.get('size')),
|
||||
sort: query.get('sort'),
|
||||
}
|
||||
}
|
||||
|
||||
export function populated(key: string, query: URLSearchParams) {
|
||||
return key === 'events' ? listPage(eventEntries, 7, query) : listPage([], 0, query)
|
||||
}
|
||||
|
||||
export function lookupNames(ids: number[]) {
|
||||
return userNames.filter((user) => ids.includes(user.id))
|
||||
}
|
||||
|
||||
export function mountList(path: string, options: SchemaMount = {}) {
|
||||
return mountAt(path, { list: populated, lookup: lookupNames, ...options })
|
||||
}
|
||||
|
||||
export async function settle() {
|
||||
await flushPromises()
|
||||
}
|
||||
|
||||
export function listRequests(calls: string[]) {
|
||||
return calls.filter((url) => /\/entry\?/.test(url) && !/size=5$/.test(url))
|
||||
}
|
||||
|
||||
export function lookupRequests(calls: string[]) {
|
||||
return calls.filter((url) => url.startsWith('/v1/user/lookup'))
|
||||
}
|
||||
|
||||
export function installSelectPolyfills() {
|
||||
Element.prototype.scrollIntoView = vi.fn()
|
||||
Element.prototype.hasPointerCapture = vi.fn(() => false)
|
||||
Element.prototype.releasePointerCapture = vi.fn()
|
||||
}
|
||||
|
||||
export function openSelect(trigger: Element | null) {
|
||||
trigger?.dispatchEvent(
|
||||
Object.assign(new MouseEvent('pointerdown', { bubbles: true, button: 0 }), {
|
||||
pointerType: 'mouse',
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
export async function chooseSort(label: string) {
|
||||
openSelect(document.body.querySelector('[aria-label="Sort by"]'))
|
||||
await flushPromises()
|
||||
const option = [...document.body.querySelectorAll<HTMLElement>('[role="option"]')].find(
|
||||
(candidate) => candidate.textContent?.trim() === label,
|
||||
)!
|
||||
option.dispatchEvent(new MouseEvent('pointerup', { bubbles: true }))
|
||||
option.click()
|
||||
await flushPromises()
|
||||
}
|
||||
|
||||
export async function chooseSize(label: string) {
|
||||
document.body.querySelector<HTMLElement>('[aria-label="Rows per page"]')!.click()
|
||||
await flushPromises()
|
||||
const option = [...document.body.querySelectorAll<HTMLElement>('[role="option"]')].find(
|
||||
(candidate) => candidate.textContent?.trim() === label,
|
||||
)!
|
||||
option.click()
|
||||
await flushPromises()
|
||||
}
|
||||
|
||||
export async function press(label: string) {
|
||||
document.body.querySelector<HTMLElement>(`[aria-label="${label}"]`)!.click()
|
||||
await flushPromises()
|
||||
}
|
||||
Reference in new issue
Block a user