Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

expand test coverage #10

Merged
merged 1 commit into from
Sep 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addon/components/menu.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
isOpen=this.isOpen
onClick=this.toggle
openMenu=this.open
closeMenu=this.close
goToFirstItem=this.goToFirstItem
goToLastItem=this.goToLastItem
goToNextItem=this.goToNextItem
Expand Down
13 changes: 8 additions & 5 deletions addon/components/menu/button.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ export default class Button extends Component {
case "Enter":
case "ArrowDown":
event.preventDefault();
this.args.openMenu();

next(() => {
this.args.goToFirstItem();
});
if (this.args.isOpen && event.key === "Enter") {
this.args.closeMenu();
} else {
this.args.openMenu();
next(() => {
this.args.goToFirstItem();
});
}
break;

case "ArrowUp":
event.preventDefault();
this.args.openMenu();
Expand Down
2 changes: 1 addition & 1 deletion addon/components/menu/item-element.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{{#let (element (or @tagName "a")) as |Tag|}}
<Tag
{{did-insert @registerItemElement}}
{{on "mousemove" @onMouseMove}}
{{on "mouseover" @onMouseOver}}
{{on "click" @onClick}}
{{will-destroy @unregisterItemElement}}
id={{@guid}}
Expand Down
2 changes: 1 addition & 1 deletion addon/components/menu/item.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
'menu/item-element'
guid=this.guid
isDisabled=@isDisabled
onMouseMove=this.onMouseMove
onMouseOver=this.onMouseOver
registerItemElement=this.registerItemElement
unregisterItemElement=this.unregisterItemElement
onClick=this.onElementClick
Expand Down
2 changes: 1 addition & 1 deletion addon/components/menu/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default class Item extends Component {
}

@action
onMouseMove() {
onMouseOver() {
if (this.args.isDisabled) return;
if (this.isActive) return;

Expand Down
184 changes: 183 additions & 1 deletion tests/integration/components/menu-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import QUnit, { module, test } from "qunit";
import { setupRenderingTest } from "ember-qunit";
import { click, render, pauseTest } from "@ember/test-helpers";
import {
click,
render,
pauseTest,
focus,
find,
triggerEvent,
triggerKeyEvent,
} from "@ember/test-helpers";
import { hbs } from "ember-cli-htmlbars";

function assertClosedMenuButton(selector) {
Expand Down Expand Up @@ -95,4 +103,178 @@ module("Integration | Component | menu", function (hooks) {
});
});
});

module("Keyboard", function () {
test("Enter open and closes the menu", async function (assert) {
await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items data-test-menu-items as |items|>
<items.Item as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item A
</item.Element>
</items.Item>
<items.Item as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item B
</item.Element>
</items.Item>
<items.Item as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item C
</item.Element>
</items.Item>
</menu.Items>
</Menu>
`);

assertClosedMenuButton("[data-test-menu-button]");

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

assert
.dom("[data-test-is-selected]")
.hasText("Item A", "The first item is selected");
});

test("it should have no active item when no items are provided", async function (assert) {
await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items />
</Menu>
`);

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

assert.dom("[data-test-is-selected]").doesNotExist();
});

test("it should focus the first non disabled menu item when opening with Enter", async function (assert) {
await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items data-test-menu-items as |items|>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item A
</item.Element>
</items.Item>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item B
</item.Element>
</items.Item>
<items.Item as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item C
</item.Element>
</items.Item>
</menu.Items>
</Menu>
`);

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

assert
.dom("[data-test-is-selected]")
.hasText("Item C", "The first non-disabled item is selected");
});

test("it should have no active menu item upon Enter key press, when there are no non-disabled menu items", async function (assert) {
await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items data-test-menu-items as |items|>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item A
</item.Element>
</items.Item>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item B
</item.Element>
</items.Item>
</menu.Items>
</Menu>
`);

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

assert.dom("[data-test-is-selected]").doesNotExist();
});

test("it should be possible to close the menu with Enter when there is no active menuitem", async function (assert) {
await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items data-test-menu-items as |items|>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item A
</item.Element>
</items.Item>
<items.Item @isDisabled={{true}} as |item|>
<item.Element data-test-is-selected={{item.isActive}}>
Item B
</item.Element>
</items.Item>
</menu.Items>
</Menu>
`);

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertClosedMenuButton("[data-test-menu-button]");
});

test("it should be possible to close the menu with Enter and invoke the active menu item", async function (assert) {
let itemClicked = 0;
this.set("onClick", (item) => (itemClicked = item.target));

await render(hbs`
<Menu data-test-menu as |menu|>
<menu.Button data-test-menu-button>Trigger</menu.Button>
<menu.Items data-test-menu-items as |items|>
<items.Item as |item|>
<item.Element {{on "click" this.onClick}}>
Item A
</item.Element>
</items.Item>
<items.Item as |item|>
<item.Element data-test-item-b {{on "click" this.onClick}}>
Item B
</item.Element>
</items.Item>
</menu.Items>
</Menu>
`);

await triggerKeyEvent("[data-test-menu-button]", "keydown", "Enter");

assertOpenMenuButton("[data-test-menu-button]");

await triggerEvent("[data-test-item-b]", "mouseover");

await triggerKeyEvent("[data-test-item-b]", "keydown", "Enter");

assert.dom(itemClicked).hasText("Item B");

assertClosedMenuButton("[data-test-menu-button]");
});
});
});