stitch-ui
Version:
281 lines (269 loc) • 9.01 kB
JavaScript
/* global it, describe, beforeAll, expect */
import React from "react"; // eslint-disable-line no-unused-vars
import { Provider } from "react-redux";
import { JSDOM } from "jsdom";
import { MemoryRouter } from "react-router-dom";
import { mount, ReactWrapper } from "enzyme";
import sinon from "sinon";
import {
testSetup,
noConsoleErrorsAllowed,
stubConfirmation
} from "../../testutil";
import * as homeActions from "../../home/actions";
import * as actions from "../actions";
import * as serviceActions from "../../services/actions";
// importing both the class and the connected component,
// so that we can stub its confirm() method.
import Push from "../components/PushNotifications";
import MessageEditor from "../components/MessageEditor";
global.navigator = {
userAgent: "node.js"
};
const doc = new JSDOM("<!doctype html><html><body></body></html>");
global.document = doc;
global.window = doc.defaultView;
describe("auth", () => {
noConsoleErrorsAllowed();
let store;
let testApp;
let display;
let displaySent;
let actionSub;
beforeAll(async () => {
const testHarness = await testSetup();
store = testHarness.store;
actionSub = testHarness.actionSub;
testApp = await store.dispatch(
homeActions.createApp(testHarness.groupId, "my-test-app")
);
await store.dispatch(
serviceActions.saveConfig(testApp.groupId, testApp._id, "gcm", {
apiKey: "myApiKey",
senderId: "123456"
})
);
// Mount two 'tabs': one for the sent messages and one for the drafts
await new Promise(resolve => {
actionSub.subscribe(actions.loadMessagesActions.rcv.getType(), resolve);
display = mount(
<Provider store={store}>
<MemoryRouter
initialEntries={[
`/groups/${testHarness.groupId}/apps/${testApp._id}/push/drafts`
]}
initialIndex={0}
>
<Push
app={testApp}
match={{
url: `/groups/${testHarness.groupId}/apps/${testApp._id}/push`
}}
/>
</MemoryRouter>
</Provider>
);
});
await new Promise(resolve => {
actionSub.subscribe(actions.loadMessagesActions.rcv.getType(), resolve);
displaySent = mount(
<Provider store={store}>
<MemoryRouter
initialEntries={[
`/groups/${testHarness.groupId}/apps/${testApp._id}/push/sent`
]}
initialIndex={0}
>
<Push
app={testApp}
match={{
url: `/groups/${testHarness.groupId}/apps/${testApp._id}/push`
}}
/>
</MemoryRouter>
</Provider>
);
});
});
it("can save a message as a draft", async () => {
display
.find("button")
.findWhere(x => x.text() === "Send New Notification")
.props()
.onClick();
const newMsgModalPortal = display.find("MessageEditor").at(0).node.modal
.portal;
expect(newMsgModalPortal).toBeDefined();
const newMsgModal = new ReactWrapper(newMsgModalPortal, newMsgModalPortal);
newMsgModal
.find("input[name='message']")
.props()
.onChange({ target: { value: "test msg text" } });
newMsgModal
.find("input[name='label']")
.props()
.onChange({ target: { value: "test msg label" } });
newMsgModal
.find("input[name='topic']")
.props()
.onChange({ target: { value: "test msg topic" } });
await newMsgModal
.find("button")
.findWhere(x => x.text() === "Save Draft")
.props()
.onClick();
expect(display.find("MessageList").props().messages).toHaveLength(1);
const msg = display.find("MessageList").props().messages[0];
expect(msg.type).toEqual("draft");
expect(msg.topic).toEqual("test msg topic");
expect(msg.message).toEqual("test msg text");
expect(msg.label).toEqual("test msg label");
});
it("can populate the send form by duplicating a message", async () => {
display.find("Message").find("DropdownMenu").props().toggle.props.onClick();
display
.find("Message")
.find("DropdownMenu")
.find("a")
.findWhere(x => x.text() === "Duplicate")
.props()
.onClick();
expect(
display.find("MessageEditor").at(0).props().editingMessageId
).toBeFalsy();
const msgModalPortal = display.find("MessageEditor").at(0).node.modal
.portal;
expect(msgModalPortal).toBeDefined();
const msgModal = new ReactWrapper(msgModalPortal, msgModalPortal);
const msg = display.find("MessageList").props().messages[0];
expect(msgModal.find("input[name='message']").props().value).toEqual(
msg.message
);
expect(msgModal.find("input[name='label']").props().value).toEqual(
msg.label
);
expect(msgModal.find("input[name='topic']").props().value).toEqual(
msg.topic
);
display.find("MessageEditor").props().onClose();
});
it("can save edits to a draft", async () => {
display.find("Message").find("DropdownMenu").props().toggle.props.onClick();
display
.find("Message")
.find("DropdownMenu")
.find("a")
.findWhere(x => x.text() === "Edit")
.props()
.onClick();
const msg = display.find("MessageList").props().messages[0];
expect(
display.find("MessageEditor").at(0).props().editingMessageId
).toEqual(msg._id);
const msgModalPortal = display.find("MessageEditor").at(0).node.modal
.portal;
expect(msgModalPortal).toBeDefined();
const msgModal = new ReactWrapper(msgModalPortal, msgModalPortal);
msgModal
.find("input[name='message']")
.props()
.onChange({ target: { value: "updated message" } });
await msgModal
.find("button")
.findWhere(x => x.text() === "Save Draft")
.props()
.onClick();
expect(display.find("Message").find("td").at(1).text()).toEqual(
"updated message"
);
});
it("saving an invalid message displays an error", async () => {
expect.assertions(4);
display.find("Message").find("DropdownMenu").props().toggle.props.onClick();
display
.find("Message")
.find("DropdownMenu")
.find("a")
.findWhere(x => x.text() === "Edit")
.props()
.onClick();
const msg = display.find("MessageList").props().messages[0];
expect(
display.find("MessageEditor").at(0).props().editingMessageId
).toEqual(msg._id);
const msgModalPortal = display.find("MessageEditor").at(0).node.modal
.portal;
expect(msgModalPortal).toBeDefined();
const msgModal = new ReactWrapper(msgModalPortal, msgModalPortal);
msgModal
.find("input[name='message']")
.props()
.onChange({ target: { value: "" } });
try {
await msgModal
.find("button")
.findWhere(x => x.text() === "Save Draft")
.props()
.onClick();
} catch (err) {
expect(display.find("MessageEditor").props().open).toBe(true);
expect(msgModal.find(".banner-error").text()).toBe(
"message must not be blank"
);
}
});
it("can send the message", async () => {
const msgItem = display.find("Message");
msgItem.find("DropdownMenu").props().toggle.props.onClick();
msgItem
.find("DropdownMenu")
.find("a")
.findWhere(x => x.text() === "Edit")
.props()
.onClick();
const msg = display.find("MessageList").props().messages[0];
expect(
display.find("MessageEditor").at(0).props().editingMessageId
).toEqual(msg._id);
const msgModalPortal = display.find("MessageEditor").at(0).node.modal
.portal;
expect(msgModalPortal).toBeDefined();
const msgModal = new ReactWrapper(msgModalPortal, msgModalPortal);
msgModal
.find("input[name='message']")
.props()
.onChange({ target: { value: "updated message" } });
const pipelineStub = sinon.stub(MessageEditor, "makeTopicPipeline");
pipelineStub.returns([
{
action: "literal",
args: { items: [] }
}
]);
await msgModal
.find("button")
.findWhere(x => x.text() === "Send Message")
.props()
.onClick();
// Message should be gone from drafts folder.
// Check the 'sent' folder, and the message should appear there
await displaySent.find("PushNotifications").find("MessageList").node.load();
expect(displaySent.find("MessageList").find("Message")).toHaveLength(1);
});
it("can delete a message from the list", async () => {
stubConfirmation(true);
displaySent
.find("Message")
.find("DropdownMenu")
.props()
.toggle.props.onClick();
await displaySent
.find("Message")
.find("DropdownMenu")
.find("a")
.findWhere(x => x.text() === "Delete")
.props()
.onClick();
expect(displaySent.find("MessageList").find("Message")).toHaveLength(0);
});
});