Skip to content

Commit

Permalink
#1717 Accessibility: Notification panel should be enabled for keyboar…
Browse files Browse the repository at this point in the history
…d navigation (#1718)
  • Loading branch information
tomlyn authored Feb 27, 2024
1 parent 6115524 commit 9864601
Show file tree
Hide file tree
Showing 22 changed files with 493 additions and 328 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import CanvasContents from "../../src/common-canvas/cc-contents.jsx";
import PaletteDialog from "../../src/palette/palette-dialog.jsx";
import PaletteFlyout from "../../src/palette/palette-flyout.jsx";
import Toolbar from "../../src/toolbar/toolbar.jsx";
import NotificationPanel from "../../src/notification-panel/notification-panel.jsx";
import CanvasBottomPanel from "../../src/common-canvas/cc-bottom-panel.jsx";
import CommonCanvasRightFlyout from "../../src/common-canvas/cc-right-flyout.jsx";
import CommonCanvasStateTag from "../../src/common-canvas/cc-state-tag.jsx";
Expand Down Expand Up @@ -144,16 +143,6 @@ describe("CommonCanvas renders correctly", () => {
expect(wrapper.find(Toolbar)).to.have.length(1);
});

it("should render one <NotificationPanel/> component", () => {
const toolbarConfig = [{ action: "palette", label: "Palette", enable: true }];
const notificationConfig = { action: "notification", label: "Notifications", enable: true };
const config = {};
const wrapper = createCommonCanvas(config, canvasController, toolbarConfig, notificationConfig);
expect(wrapper.find(Toolbar)).to.have.length(1);
expect(wrapper.find(NotificationPanel)).to.have.length(1);
});


it("canvas controller isPaletteOpen() should return true when paletteInitialState is true", () => {
const toolbarConfig = [{ action: "palette", label: "Palette", enable: true }];
const notificationConfig = { action: "notification", label: "Notifications", enable: true };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ describe("Common Canvas Toolbar renders correctly with config as OBJECT", () =>

// When notification panel is open, toolbar button should have class toolbar-item-selected
// this class shows blue bottom border for the button
it("Notifications button in rightBar should have class toolbar-item-selected when notification panel is open", () => {
it("Notifications button in rightBar should have class notification-panel when notification panel is open", () => {
const toolbarConfig = {
leftBar: [
{ action: "undo", label: "Undo", enable: true },
Expand All @@ -325,7 +325,7 @@ describe("Common Canvas Toolbar renders correctly with config as OBJECT", () =>
isPaletteEnabled: true, isPaletteOpen: true,
notificationConfig, isNotificationOpen: true }, canvasController);

expect(wrapper.find(".toggleNotificationPanel-action.toolbar-item-selected")).to.have.length(1);
expect(wrapper.find(".notification-panel")).to.have.length(1);
});

// When notification panel is closed, toolbar button should NOT have class toolbar-item-selected
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ const notificationMessages = [

describe("notification panel renders correctly", () => {
let wrapper;
beforeEach(() => {
canvasController = new CanvasController();
});
afterEach(() => {
wrapper.unmount();
});
Expand All @@ -113,38 +116,23 @@ describe("notification panel renders correctly", () => {
canvasController.setNotificationPanelConfig(notificationConfigDefault);
canvasController.setNotificationMessages(notificationMessages);
canvasController.openNotificationPanel();
const subPanelData = { canvasController };
const closePanelFn = () => null;

wrapper = mountWithIntl(
<Provider store={canvasController.getStore()}>
<NotificationPanel
canvasController={canvasController}
closeSubPanel={ closePanelFn }
subPanelData={ subPanelData }
/>
</Provider>
);


const notificationPanel = wrapper.find("NotificationPanel");
expect(JSON.stringify(notificationPanel.prop("notificationConfig"))).to.equal(JSON.stringify(notificationConfigDefault));
expect(notificationPanel.prop("isNotificationOpen")).to.equal(true);
expect(JSON.stringify(notificationPanel.prop("messages"))).to.equal(JSON.stringify(notificationMessages));
expect(notificationPanel.prop("canvasController")).to.equal(canvasController);
});

it("notification panel should be hidden if isNotificationOpen is false", () => {
canvasController.setNotificationPanelConfig(notificationConfigDefault);
canvasController.setNotificationMessages(notificationMessages);
canvasController.closeNotificationPanel();

wrapper = mountWithIntl(
<Provider store={canvasController.getStore()}>
<NotificationPanel
canvasController={canvasController}
/>
</Provider>
);

const notificationPanel = wrapper.find("NotificationPanel");
expect(notificationPanel.find(".notification-panel-container.panel-hidden")).to.have.length(1);
expect(notificationPanel.prop("subPanelData")).to.equal(subPanelData);
expect(notificationPanel.prop("closeSubPanel")).to.equal(closePanelFn);
});

it("notification panel should have 4 types of messages", () => {
Expand All @@ -160,18 +148,21 @@ describe("notification panel renders correctly", () => {

canvasController.setNotificationPanelConfig(notificationConfig);
canvasController.setNotificationMessages(notificationMessages);
canvasController.closeNotificationPanel();

const subPanelData = { canvasController };
const closePanelFn = () => null;

wrapper = mountWithIntl(
<Provider store={canvasController.getStore()}>
<NotificationPanel
canvasController={canvasController}
closeSubPanel={ closePanelFn }
subPanelData={ subPanelData }
/>
</Provider>
);

const notificationPanel = wrapper.find("NotificationPanel");
expect(notificationPanel.find(".notification-panel-container.panel-hidden")).to.have.length(1);
expect(notificationPanel.find(".notification-panel")).to.have.length(1);
const messages = notificationPanel.find(".notifications-button-container");
expect(messages).to.have.length(4);

Expand Down Expand Up @@ -211,25 +202,28 @@ describe("notification panel renders correctly", () => {

canvasController.setNotificationPanelConfig(notificationConfig);
canvasController.setNotificationMessages([]);
canvasController.closeNotificationPanel();

const subPanelData = { canvasController };
const closePanelFn = () => null;

wrapper = mountWithIntl(
<Provider store={canvasController.getStore()}>
<NotificationPanel
canvasController={canvasController}
closeSubPanel={ closePanelFn }
subPanelData={ subPanelData }
/>
</Provider>
);

const subtitle = wrapper.find(".notification-panel-container .notification-panel-subtitle");
const subtitle = wrapper.find(".notification-panel .notification-panel-subtitle");
expect(subtitle).to.have.length(1);
expect(subtitle.text()).to.eql("Custom subtitle");

const emptyMessage = wrapper.find(".notification-panel-container .notification-panel-empty-message");
const emptyMessage = wrapper.find(".notification-panel .notification-panel-empty-message");
expect(emptyMessage).to.have.length(1);
expect(emptyMessage.text()).to.eql("Custom empty message");

const clearAll = wrapper.find(".notification-panel-container button.notification-panel-clear-all");
const clearAll = wrapper.find(".notification-panel button.notification-panel-clear-all");
expect(clearAll).to.have.length(1);
expect(clearAll.text()).to.eql("Clear all");
});
Expand Down Expand Up @@ -320,6 +314,7 @@ describe("toolbar notification icon state renders correctly", () => {

it("notification icon should be empty in toolbar if no messages", () => {
const notificationConfig = { action: "notification", label: "Notifications Panel", enable: true, notificationHeader: "Custom" };
canvasController.openNotificationPanel();
wrapper = createIntlCommonCanvas(
canvasConfig,
contextMenuHandler,
Expand All @@ -337,7 +332,7 @@ describe("toolbar notification icon state renders correctly", () => {
canvasController
);

expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
expect(wrapper.find(".notification-panel")).to.have.length(1);
expect(canvasController.getNotificationMessages().length).to.equal(0);
expect(wrapper.find(".notification-panel-empty-message-container")).to.have.length(1);

Expand Down Expand Up @@ -545,15 +540,16 @@ describe("notification center buttons work properly", () => {
contextMenuConfig,
canvasController
);
// open the notification center
expect(wrapper.find(".notification-panel")).to.have.length(0);

// Open the notification center
const notificationButton = wrapper.find(".toggleNotificationPanel-action button");
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
notificationButton.simulate("click");
wrapper.update();
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(0);
expect(wrapper.find(".notification-panel")).to.have.length(1);

// check that there is no clear all button
expect(wrapper.find(".notification-panel-container button.notification-panel-clear-all")).to.have.length(0);
// Check that there is no clear all button
expect(wrapper.find(".notification-panel button.notification-panel-clear-all")).to.have.length(0);
});

it("notification clear all button renders and works when enabled", () => {
Expand All @@ -574,37 +570,39 @@ describe("notification center buttons work properly", () => {
contextMenuConfig,
canvasController
);

expect(wrapper.find(".notification-panel")).to.have.length(0);

// open the notification center
const notificationButton = wrapper.find(".toggleNotificationPanel-action button");
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
notificationButton.simulate("click");
wrapper.update();
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(0);
expect(wrapper.find(".notification-panel")).to.have.length(1);

// check that there are no messages and the clear all button is disabled
let clearAllButton = wrapper.find(".notification-panel-container button.notification-panel-clear-all");
let clearAllButton = wrapper.find(".notification-panel button.notification-panel-clear-all");
expect(clearAllButton.prop("disabled")).to.equal(true);
expect(wrapper.find(".notification-panel-container .notification-panel-empty-message").length).to.equal(1);
expect(wrapper.find(".notification-panel-container .notifications").length).to.equal(0);
expect(wrapper.find(".notification-panel .notification-panel-empty-message").length).to.equal(1);
expect(wrapper.find(".notification-panel .notifications").length).to.equal(0);
expect(canvasController.getNotificationMessages().length).to.equal(0);

// add a message and check if the clear all button is enabled
canvasController.setNotificationMessages([notificationMessage0]);
wrapper.update();
clearAllButton = wrapper.find(".notification-panel-container button.notification-panel-clear-all");
clearAllButton = wrapper.find(".notification-panel button.notification-panel-clear-all");
expect(clearAllButton.prop("disabled")).to.equal(false);
expect(wrapper.find(".notification-panel-container .notification-panel-empty-message").length).to.equal(0);
expect(wrapper.find(".notification-panel-container .notifications").length).to.equal(1);
expect(wrapper.find(".notification-panel .notification-panel-empty-message").length).to.equal(0);
expect(wrapper.find(".notification-panel .notifications").length).to.equal(1);
expect(canvasController.getNotificationMessages().length).to.equal(1);

// after clicking the clear all button, messages should be removed and button disabled again
clearAllButton.simulate("click");
wrapper.update();

clearAllButton = wrapper.find(".notification-panel-container button.notification-panel-clear-all");
clearAllButton = wrapper.find(".notification-panel button.notification-panel-clear-all");
expect(clearAllButton.prop("disabled")).to.equal(true);
expect(wrapper.find(".notification-panel-container .notification-panel-empty-message").length).to.equal(1);
expect(wrapper.find(".notification-panel-container .notifications").length).to.equal(0);
expect(wrapper.find(".notification-panel .notification-panel-empty-message").length).to.equal(1);
expect(wrapper.find(".notification-panel .notifications").length).to.equal(0);
expect(canvasController.getNotificationMessages().length).to.equal(0);
});

Expand All @@ -626,19 +624,20 @@ describe("notification center buttons work properly", () => {
contextMenuConfig,
canvasController
);
expect(wrapper.find(".notification-panel")).to.have.length(0);

// open the notification center
const notificationButton = wrapper.find(".toggleNotificationPanel-action button");
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
notificationButton.simulate("click");
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(0);
expect(wrapper.find(".notification-panel")).to.have.length(1);
wrapper.update();

// click the close button
wrapper.find(".notification-panel-close-button .bx--btn--sm").simulate("click");

// check that notification panel is closed
wrapper.update();
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
expect(wrapper.find(".notification-panel")).to.have.length(0);

});

Expand Down Expand Up @@ -670,15 +669,16 @@ describe("notification center buttons work properly", () => {
contextMenuConfig,
canvasController
);
expect(wrapper.find(".notification-panel")).to.have.length(0);

// open the notification center
const notificationButton = wrapper.find(".toggleNotificationPanel-action button");
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(1);
notificationButton.simulate("click");
wrapper.update();
expect(wrapper.find(".notification-panel-container.panel-hidden")).to.have.length(0);
expect(wrapper.find(".notification-panel")).to.have.length(1);

// check that secondary button is enabled and callback works
let secondaryButton = wrapper.find(".notification-panel-container button.notification-panel-secondary-button");
let secondaryButton = wrapper.find(".notification-panel button.notification-panel-secondary-button");
expect(secondaryButton.prop("disabled")).to.equal(false);
expect(secondaryButton.text()).to.equal(notificationConfig.secondaryButtonLabel);
secondaryButton.simulate("click");
Expand All @@ -690,7 +690,7 @@ describe("notification center buttons work properly", () => {
wrapper.update();

// verify secondary button is disabled
secondaryButton = wrapper.find(".notification-panel-container button.notification-panel-secondary-button");
secondaryButton = wrapper.find(".notification-panel button.notification-panel-secondary-button");
expect(secondaryButton.prop("disabled")).to.equal(true);
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import PropTypes from "prop-types";
import Logger from "../logging/canvas-logger.js";

const TAB_KEY = 9;
const RETURN_KEY = 13;
const SPACE_KEY = 32;
const LEFT_ARROW_KEY = 37;
const UP_ARROW_KEY = 38;
Expand Down Expand Up @@ -83,7 +84,10 @@ class ColorPicker extends React.Component {
this.colorIndex -= COLORS_IN_ROW;
}

} else if (evt.keyCode === SPACE_KEY) {
} else if (evt.keyCode === SPACE_KEY ||
evt.keyCode === RETURN_KEY) {
evt.stopPropagation();
evt.preventDefault();
this.selectColor(evt);

} else if (evt.keyCode === TAB_KEY) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import CommonCanvasToolbar from "./cc-toolbar.jsx";
import CommonCanvasRightFlyout from "./cc-right-flyout.jsx";
import CanvasBottomPanel from "./cc-bottom-panel.jsx";
import CanvasTopPanel from "./cc-top-panel.jsx";
import NotificationPanel from "../notification-panel/notification-panel.jsx";
import Logger from "../logging/canvas-logger.js";

class CommonCanvasCentralItems extends React.Component {
Expand Down Expand Up @@ -74,7 +73,6 @@ class CommonCanvasCentralItems extends React.Component {
const canvasContents = (<CanvasContents canvasController={this.props.canvasController} />);
const bottomPanel = (<CanvasBottomPanel canvasController={this.props.canvasController} containingDivId={this.props.containingDivId} />);
const topPanel = (<CanvasTopPanel canvasController={this.props.canvasController} containingDivId={this.props.containingDivId} />);
const notificationPanel = (<NotificationPanel canvasController={this.props.canvasController} />);

let rightSideItems = null;
if (this.props.enableRightFlyoutUnderToolbar) {
Expand All @@ -94,7 +92,6 @@ class CommonCanvasCentralItems extends React.Component {
</div>
{rightFlyout}
</div>
{notificationPanel}
</div>
);

Expand All @@ -112,7 +109,6 @@ class CommonCanvasCentralItems extends React.Component {
{topPanel}
{canvasContents}
{bottomPanel}
{notificationPanel}
</div>
{rightFlyout}
</div>
Expand Down
Loading

0 comments on commit 9864601

Please sign in to comment.