I am trying to open a confirmation dialog via p-menu command. I am able to display menu items by clicking on p-menu. But when I click on menuitem, the command is not executed and the confirmation dialog is not displayed.
This is my component template:
<div>
<div role="list">
<div
*ngFor="let user of users"
role="listitem"
[attr.aria-label]="user.firstName + ' ' + user.lastName"
>
<span>{{ user.firstName }} {{ user.lastName }}</span>
<button
class="as-button p-button-transparent"
aria-label="Menu"
type="button"
pButton
icon="pi pi-ellipsis-v"
(click)="activeMenu = user; menu.toggle($event)"
></button>
<p-menu #menu [model]="menuItems" [popup]="true"></p-menu>
</div>
</div>
<p-confirmDialog></p-confirmDialog>
relevant component code:
activeMenu: ConnectionUser | null = null
public menuItems = [
{
label: 'Remove',
command: () => {
this.showConfirmationDialog()
}
}
]
showConfirmationDialog() {
this.confirmationService.confirm({
message: 'Are you sure you want to remove the connection?',
header: 'Remove connection',
rejectButtonStyleClass: 'p-button-secondary',
acceptButtonStyleClass: 'p-button-danger',
acceptLabel: 'Remove',
rejectLabel: 'Cancel',
defaultFocus: 'reject',
accept: () => {
if (this.activeMenu) {
this.removeConnection(this.activeMenu._id)
}
}
})
}
This are my jest imports:
imports: [ConnectionsModule, NoopAnimationsModule, SharedModule, RouterTestingModule],
And the failing jest test:
it('should remove connection', async () => {
const userEv = userEvent.setup({ delay: null })
await userEv.click(
within(await screen.findByRole('listitem', { name: 'Joe Doe' })).getByRole('button', {
name: 'Menu'
})
)
fixture.detectChanges()
await userEv.click(await screen.findByRole('menuitem', { name: 'Remove' }))
fixture.detectChanges()
// ERROR: The button has not been found
await userEv.click(await screen.findByRole('button', { name: 'Remove' }))
expect(screen.queryByRole('listitem')).not.toBeInTheDocument()
})
I have tried detectChanges and waitFor but non of it would show the confirmation.
Here is the p-menu rendered by jest:
<p-menu
class="p-element ng-tns-c215187649-2 ng-star-inserted"
ng-reflect-model="[object Object]"
ng-reflect-popup="true"
>
<div
class="ng-trigger ng-trigger-overlayAnimation ng-tns-c215187649-2 p-menu p-component p-menu-overlay ng-star-inserted"
data-pc-name="menu"
id="pn_id_5"
ng-reflect-ng-class="[object Object]"
style="z-index: 1001; visibility: visible; display: none; transform-origin: top; top: 0px; left: 0px;"
>
<ul
class="p-menu-list p-reset ng-tns-c215187649-2"
data-pc-section="menu"
id="pn_id_5_list"
role="menu"
tabindex="0"
>
<li
aria-disabled="false"
aria-label="Remove"
class="p-element p-menuitem ng-tns-c215187649-2 ng-star-inserted"
data-p-disabled="false"
data-p-focused="false"
data-pc-section="menuitem"
id="pn_id_5_0"
ng-reflect-content=""
ng-reflect-id="pn_id_5_0"
ng-reflect-item="[object Object]"
ng-reflect-ng-class="[object Object]"
ptooltip=""
role="menuitem"
style=""
>
<div
class="p-menuitem-content"
data-pc-section="content"
>
<a
aria-hidden="true"
class="p-ripple p-element p-menuitem-link ng-star-inserted"
data-pc-section="action"
ng-reflect-ng-class="[object Object]"
pripple=""
tabindex="-1"
target="undefined"
>
<span
class="p-menuitem-text ng-star-inserted"
>
Remove
</span>
</a>
</div>
</li>
</ul>
</div>
</p-menu>
Can it be that it is not being triggered as in the rendered html the p-menu-overlay has display: none; style? On the other hand the menuitem button is found by jest and the click has not failed.
I have placed a debug in the command function (this.showConfirmationDialog()) and it is never called.
I could not figure out why it was not called so I went with a workaround to call the command directly.
component.menuItems[0].command()
I have also added missing ConfirmationService provider, to display the confirmation dialog.
This is what I have endup with:
component.menuItems[0].command()
fixture.detectChanges()
// Confirm dialog
await userEvent.click(await screen.findByRole('button', { name: 'Remove' }))
fixture.detectChanges()