Reputation: 784
I have this selection of multiple cells in a table while the control key must be pressed in order to select all the clicked cells:
cy.get("[data-cy=cell-1],[data-cy=cell-5],[data-cy=cell-32]")
.click({ multiple: true, ctrlKey: true})
It works well, I see the multiple selection since selected cells have a different background color. I coded the page so when the window:keyup event on the control key happens, a dialog opens to edit the cells content. This works very well on dev, but with cypress, the .click({ multiple: true, ctrlKey: true})
doesn't trigger my dialog, and if I had a manual .type({ctrl})
after, it triggers the dialog but the multiple selection is lost
cy.get("[data-cy=cell-1],[data-cy=cell-5],[data-cy=cell-32]")
.click({ multiple: true, ctrlKey: true})
cy.get("#my-table-container").type("{ctrl}")
It acts like for my first click({multiple: true, ctrlKey: true})
the control key is down but never released. Do you know how could I use the click multiple and control but triggering the keyup at the end?
UPDATE: @HostListener setup I am on Angular 12, here is exactly how I setup the key event with the @HostListener (I also listen the escape key to clear the cell selection):
@HostListener("window:keyup", ["$event"])
handleKeyDown(event: KeyboardEvent) {
switch(event.key){
case "Escape": this.clearSelection(); break;
case "Control":this.openEditDialog(); break;
}
}
Upvotes: 1
Views: 2137
Reputation: 784
It appears Cypress don't react as intended with the HostListener setup with event.key
instead of event.keyCode
(which is deprecated). I adapted in my component the @HostListener to use event.keyCode === 17
and it worked.
Upvotes: 1
Reputation: 31904
Since you're using the window:keyup
event, you could try to trigger that event, presume it's firing on the ctrl key (code 17).
cy.get("[data-cy=cell-1],[data-cy=cell-5],[data-cy=cell-32]")
.click({ multiple: true, ctrlKey: true})
cy.get("#my-table-container").trigger('keyup', { keyCode: 17 })
Also a keydown/keyup combo might work better (try with or without the ctrlKey
modifier on .click()
)
cy.get('#my-table-container').trigger('keydown', { keyCode: 17 })
cy.get('[data-cy=cell-1]').click({ctrlKey: true})
cy.get('[data-cy=cell-5]').click({ctrlKey: true})
cy.get('[data-cy=cell-32]').click({ctrlKey: true})
cy.get('#my-table-container').trigger('keyup', { keyCode: 17 })
Lastly, the target of the .trigger()
may need to be something other than #my-table-container
, depending on the way addEventListener()
is invoked. Would need to see more of the HTML and source to be sure.
Angular @HostListener
If you have an event listener set by the @HostListener decorator as follows
@HostListener("window:keyup", ["$event"])
onKeyup(event: KeyboardEvent): void {
event.preventDefault();
console.log('keyup', event)
}
when you look a the console.log, the event has the path property path: (4) [body, html, document, Window]
which means you can trigger it on <body>
.
To check, the following test passes
it('triggers keyup set by @HostListener on window', () => {
let ev;
cy.visit('http://localhost:4200').then(win => {
cy.stub(win.console, 'log', (eventName, event) => {
ev = event
}).as('consoleLog')
})
cy.get('body').trigger('keyup', {keyCode:17})
cy.get('@consoleLog')
.should(() => {
expect(ev.type).to.equal('keyup')
expect(ev.keyCode).to.equal(17)
})
})
So to trigger the dialog
cy.get("[data-cy=cell-1],[data-cy=cell-5],[data-cy=cell-32]")
.click({ multiple: true, ctrlKey: true})
cy.get('body')
.focus()
.trigger('keyup', { keyCode: 17 })
Upvotes: 1