fix(32): CR-04 take widget actions dispatched from connectedCallback
WidgetField assigned its element after append(), so an action the element dispatched from connectedCallback (inside append) found no target and was dropped without a result or an error state; widgets that load on connect never started. The element is now the action target before it is connected. Rebuilt the embedded admin dist.
This commit is contained in:
@@ -158,8 +158,10 @@ onMounted(async () => {
|
||||
created.setAttribute('label', props.field.actionLabel || props.field.label || props.field.name)
|
||||
created.setAttribute('busy-label', t('backend::lang.extension.busy'))
|
||||
created.addEventListener(WIDGET_EVENT, listener)
|
||||
mountPoint.value.append(created)
|
||||
// The element is the action target before it is connected: an action
|
||||
// its connectedCallback dispatches (inside append) is taken, not dropped.
|
||||
element = created
|
||||
mountPoint.value.append(created)
|
||||
status.value = 'ready'
|
||||
} catch {
|
||||
if (!unmounted) {
|
||||
|
||||
@@ -49,6 +49,7 @@ interface Options {
|
||||
assets?: () => Promise<string[]>
|
||||
source?: typeof SOURCE | null
|
||||
routes?: Record<string, Route>
|
||||
attachTo?: HTMLElement
|
||||
}
|
||||
|
||||
function mountWidget(options: Options = {}) {
|
||||
@@ -59,6 +60,7 @@ function mountWidget(options: Options = {}) {
|
||||
})
|
||||
const calls = mockApi(options.routes ?? {})
|
||||
const wrapper = mount(WidgetField, {
|
||||
attachTo: options.attachTo,
|
||||
props: {
|
||||
field: options.field ?? lookupField(),
|
||||
modelValue: undefined,
|
||||
@@ -367,6 +369,44 @@ describe('summer-action (D-05, D-07)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('an action from connectedCallback (CR-04)', () => {
|
||||
it('posts the action an element dispatches while it is being connected', async () => {
|
||||
const tag = 'acme-demo-eager'
|
||||
if (!customElements.get(tag)) {
|
||||
customElements.define(
|
||||
tag,
|
||||
class extends HTMLElement {
|
||||
connectedCallback(): void {
|
||||
this.dispatchEvent(new CustomEvent(WIDGET_EVENT, { bubbles: true, composed: true, detail: { payload: { op: 'context' } } }))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
const action = deferred()
|
||||
const host = document.createElement('div')
|
||||
document.body.append(host)
|
||||
const { wrapper, calls } = mountWidget({
|
||||
field: lookupField({ widget: tag }),
|
||||
attachTo: host,
|
||||
routes: { [`POST ${ACTION}`]: action.route },
|
||||
})
|
||||
await flushPromises()
|
||||
const target = wrapper.find(tag).element as HTMLElement
|
||||
expect(target.isConnected).toBe(true)
|
||||
expect(target.hasAttribute('busy')).toBe(true)
|
||||
const posts = requestsTo(calls, 'POST', ACTION)
|
||||
expect(posts).toHaveLength(1)
|
||||
const body = (await posts[0]!.json()) as Record<string, unknown>
|
||||
expect(body.payload).toEqual({ op: 'context' })
|
||||
const seen = results(target)
|
||||
action.release({ body: { data: { message: '', fill: {} }, meta: {} } })
|
||||
await flushPromises()
|
||||
expect(target.hasAttribute('busy')).toBe(false)
|
||||
expect(seen).toHaveLength(1)
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
|
||||
describe('payload and data (summer-result)', () => {
|
||||
const OK: Reply = { body: { data: { message: '', fill: {} }, meta: {} } }
|
||||
const DATA_REPLY: Reply = {
|
||||
|
||||
Reference in New Issue
Block a user