2021-11-24 21:48:07 +08:00
|
|
|
/*
|
|
|
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import React from "react";
|
2022-08-02 21:10:43 +08:00
|
|
|
// eslint-disable-next-line deprecate/import
|
2021-11-24 21:48:07 +08:00
|
|
|
import { mount, ReactWrapper } from "enzyme";
|
2021-12-09 17:10:23 +08:00
|
|
|
import { Room } from "matrix-js-sdk/src/models/room";
|
2023-01-14 01:02:33 +08:00
|
|
|
import { M_POLL_KIND_DISCLOSED, M_POLL_KIND_UNDISCLOSED, M_POLL_START } from "matrix-js-sdk/src/@types/polls";
|
|
|
|
import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
|
2022-03-22 18:32:35 +08:00
|
|
|
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
2023-01-14 01:02:33 +08:00
|
|
|
import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events";
|
2021-12-09 17:10:23 +08:00
|
|
|
|
2022-03-22 18:32:35 +08:00
|
|
|
import { findById, getMockClientWithEventEmitter } from "../../../test-utils";
|
2021-11-24 21:48:07 +08:00
|
|
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
2022-03-22 18:32:35 +08:00
|
|
|
import PollCreateDialog from "../../../../src/components/views/elements/PollCreateDialog";
|
|
|
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
2021-11-24 21:48:07 +08:00
|
|
|
|
|
|
|
// Fake date to give a predictable snapshot
|
|
|
|
const realDateNow = Date.now;
|
|
|
|
const realDateToISOString = Date.prototype.toISOString;
|
|
|
|
Date.now = jest.fn(() => 2345678901234);
|
|
|
|
// eslint-disable-next-line no-extend-native
|
|
|
|
Date.prototype.toISOString = jest.fn(() => "2021-11-23T14:35:14.240Z");
|
2022-02-19 00:35:08 +08:00
|
|
|
|
2021-11-24 21:48:07 +08:00
|
|
|
afterAll(() => {
|
|
|
|
Date.now = realDateNow;
|
|
|
|
// eslint-disable-next-line no-extend-native
|
|
|
|
Date.prototype.toISOString = realDateToISOString;
|
|
|
|
});
|
|
|
|
|
|
|
|
describe("PollCreateDialog", () => {
|
2022-03-22 18:32:35 +08:00
|
|
|
const mockClient = getMockClientWithEventEmitter({
|
|
|
|
sendEvent: jest.fn().mockResolvedValue({ event_id: "1" }),
|
|
|
|
});
|
|
|
|
|
|
|
|
beforeEach(() => {
|
|
|
|
mockClient.sendEvent.mockClear();
|
|
|
|
});
|
|
|
|
|
2021-11-25 00:24:19 +08:00
|
|
|
it("renders a blank poll", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />, {
|
2022-03-22 18:32:35 +08:00
|
|
|
wrappingComponent: MatrixClientContext.Provider,
|
|
|
|
wrappingComponentProps: { value: mockClient },
|
2021-11-25 00:24:19 +08:00
|
|
|
});
|
2022-02-03 19:54:03 +08:00
|
|
|
expect(dialog.html()).toMatchSnapshot();
|
2021-11-25 00:24:19 +08:00
|
|
|
});
|
|
|
|
|
2022-02-19 00:35:08 +08:00
|
|
|
it("autofocuses the poll topic on mount", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("autofocuses the new poll option field after clicking add option button", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(true);
|
|
|
|
|
|
|
|
dialog.find("div.mx_PollCreateDialog_addOption").simulate("click");
|
|
|
|
|
|
|
|
expect(findById(dialog, "poll-topic-input").at(0).props().autoFocus).toEqual(false);
|
|
|
|
expect(findById(dialog, "pollcreate_option_1").at(0).props().autoFocus).toEqual(false);
|
|
|
|
expect(findById(dialog, "pollcreate_option_2").at(0).props().autoFocus).toEqual(true);
|
|
|
|
});
|
|
|
|
|
2021-11-25 00:24:19 +08:00
|
|
|
it("renders a question and some options", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(submitIsDisabled(dialog)).toBe(true);
|
|
|
|
|
|
|
|
// When I set some values in the boxes
|
|
|
|
changeValue(dialog, "Question or topic", "How many turnips is the optimal number?");
|
|
|
|
changeValue(dialog, "Option 1", "As many as my neighbour");
|
|
|
|
changeValue(dialog, "Option 2", "The question is meaningless");
|
|
|
|
dialog.find("div.mx_PollCreateDialog_addOption").simulate("click");
|
|
|
|
changeValue(dialog, "Option 3", "Mu");
|
2022-02-03 19:54:03 +08:00
|
|
|
expect(dialog.html()).toMatchSnapshot();
|
2021-11-25 00:24:19 +08:00
|
|
|
});
|
|
|
|
|
2022-02-17 17:13:05 +08:00
|
|
|
it("renders info from a previous event", () => {
|
|
|
|
const previousEvent: MatrixEvent = new MatrixEvent(
|
|
|
|
PollStartEvent.from("Poll Q", ["Answer 1", "Answer 2"], M_POLL_KIND_DISCLOSED).serialize(),
|
|
|
|
);
|
|
|
|
|
|
|
|
const dialog = mount(
|
|
|
|
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} editingMxEvent={previousEvent} />,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(submitIsDisabled(dialog)).toBe(false);
|
|
|
|
expect(dialog.html()).toMatchSnapshot();
|
|
|
|
});
|
|
|
|
|
2021-11-24 21:48:07 +08:00
|
|
|
it("doesn't allow submitting until there are options", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(submitIsDisabled(dialog)).toBe(true);
|
|
|
|
});
|
|
|
|
|
|
|
|
it("does allow submitting when there are options and a question", () => {
|
|
|
|
// Given a dialog with no info in (which I am unable to submit)
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(submitIsDisabled(dialog)).toBe(true);
|
|
|
|
|
|
|
|
// When I set some values in the boxes
|
|
|
|
changeValue(dialog, "Question or topic", "Q");
|
|
|
|
changeValue(dialog, "Option 1", "A1");
|
|
|
|
changeValue(dialog, "Option 2", "A2");
|
|
|
|
|
|
|
|
// Then I am able to submit
|
|
|
|
expect(submitIsDisabled(dialog)).toBe(false);
|
|
|
|
});
|
|
|
|
|
2022-02-21 18:21:35 +08:00
|
|
|
it("shows the open poll description at first", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_DISCLOSED.name);
|
|
|
|
expect(dialog.find("p").text()).toEqual("Voters see results as soon as they have voted");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("shows the closed poll description if we choose it", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name);
|
|
|
|
expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_UNDISCLOSED.name);
|
|
|
|
expect(dialog.find("p").text()).toEqual("Results are only revealed when you end the poll");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("shows the open poll description if we choose it", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name);
|
|
|
|
changeKind(dialog, M_POLL_KIND_DISCLOSED.name);
|
|
|
|
expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_DISCLOSED.name);
|
|
|
|
expect(dialog.find("p").text()).toEqual("Voters see results as soon as they have voted");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("shows the closed poll description when editing a closed poll", () => {
|
|
|
|
const previousEvent: MatrixEvent = new MatrixEvent(
|
|
|
|
PollStartEvent.from("Poll Q", ["Answer 1", "Answer 2"], M_POLL_KIND_UNDISCLOSED).serialize(),
|
|
|
|
);
|
|
|
|
previousEvent.event.event_id = "$prevEventId";
|
|
|
|
|
|
|
|
const dialog = mount(
|
|
|
|
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} editingMxEvent={previousEvent} />,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(dialog.find("select").prop("value")).toEqual(M_POLL_KIND_UNDISCLOSED.name);
|
|
|
|
expect(dialog.find("p").text()).toEqual("Results are only revealed when you end the poll");
|
|
|
|
});
|
|
|
|
|
2021-11-25 00:24:19 +08:00
|
|
|
it("displays a spinner after submitting", () => {
|
2021-11-24 21:48:07 +08:00
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
2021-11-25 00:24:19 +08:00
|
|
|
changeValue(dialog, "Question or topic", "Q");
|
|
|
|
changeValue(dialog, "Option 1", "A1");
|
|
|
|
changeValue(dialog, "Option 2", "A2");
|
|
|
|
expect(dialog.find("Spinner").length).toBe(0);
|
2021-11-24 21:48:07 +08:00
|
|
|
|
2021-11-25 00:24:19 +08:00
|
|
|
dialog.find("button").simulate("click");
|
|
|
|
expect(dialog.find("Spinner").length).toBe(1);
|
2021-11-24 21:48:07 +08:00
|
|
|
});
|
2022-02-17 17:13:05 +08:00
|
|
|
|
|
|
|
it("sends a poll create event when submitted", () => {
|
|
|
|
const dialog = mount(<PollCreateDialog room={createRoom()} onFinished={jest.fn()} />);
|
|
|
|
changeValue(dialog, "Question or topic", "Q");
|
|
|
|
changeValue(dialog, "Option 1", "A1");
|
|
|
|
changeValue(dialog, "Option 2", "A2");
|
|
|
|
|
|
|
|
dialog.find("button").simulate("click");
|
2022-03-22 18:32:35 +08:00
|
|
|
const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0];
|
|
|
|
expect(M_POLL_START.matches(eventType)).toBeTruthy();
|
2022-02-17 17:13:05 +08:00
|
|
|
expect(sentEventContent).toEqual({
|
|
|
|
[M_TEXT.name]: "Q\n1. A1\n2. A2",
|
|
|
|
[M_POLL_START.name]: {
|
|
|
|
answers: [
|
|
|
|
{
|
|
|
|
id: expect.any(String),
|
|
|
|
[M_TEXT.name]: "A1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
id: expect.any(String),
|
|
|
|
[M_TEXT.name]: "A2",
|
|
|
|
},
|
2022-12-12 19:24:14 +08:00
|
|
|
],
|
2022-02-17 17:13:05 +08:00
|
|
|
kind: M_POLL_KIND_DISCLOSED.name,
|
|
|
|
max_selections: 1,
|
2021-11-24 21:48:07 +08:00
|
|
|
question: {
|
2022-12-12 19:24:14 +08:00
|
|
|
body: "Q",
|
2022-02-17 17:13:05 +08:00
|
|
|
format: undefined,
|
|
|
|
formatted_body: undefined,
|
|
|
|
msgtype: "m.text",
|
|
|
|
[M_TEXT.name]: "Q",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
it("sends a poll edit event when editing", () => {
|
|
|
|
const previousEvent: MatrixEvent = new MatrixEvent(
|
|
|
|
PollStartEvent.from("Poll Q", ["Answer 1", "Answer 2"], M_POLL_KIND_DISCLOSED).serialize(),
|
|
|
|
);
|
|
|
|
previousEvent.event.event_id = "$prevEventId";
|
|
|
|
|
|
|
|
const dialog = mount(
|
|
|
|
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} editingMxEvent={previousEvent} />,
|
|
|
|
);
|
|
|
|
|
|
|
|
changeValue(dialog, "Question or topic", "Poll Q updated");
|
|
|
|
changeValue(dialog, "Option 2", "Answer 2 updated");
|
2022-02-21 18:21:35 +08:00
|
|
|
changeKind(dialog, M_POLL_KIND_UNDISCLOSED.name);
|
2022-02-17 17:13:05 +08:00
|
|
|
dialog.find("button").simulate("click");
|
|
|
|
|
2022-03-22 18:32:35 +08:00
|
|
|
const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0];
|
|
|
|
expect(M_POLL_START.matches(eventType)).toBeTruthy();
|
2022-02-17 17:13:05 +08:00
|
|
|
expect(sentEventContent).toEqual({
|
|
|
|
"m.new_content": {
|
|
|
|
[M_TEXT.name]: "Poll Q updated\n1. Answer 1\n2. Answer 2 updated",
|
|
|
|
[M_POLL_START.name]: {
|
|
|
|
answers: [
|
|
|
|
{
|
|
|
|
id: expect.any(String),
|
|
|
|
[M_TEXT.name]: "Answer 1",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
id: expect.any(String),
|
|
|
|
[M_TEXT.name]: "Answer 2 updated",
|
|
|
|
},
|
2022-12-12 19:24:14 +08:00
|
|
|
],
|
2022-02-21 18:21:35 +08:00
|
|
|
kind: M_POLL_KIND_UNDISCLOSED.name,
|
2022-02-17 17:13:05 +08:00
|
|
|
max_selections: 1,
|
|
|
|
question: {
|
|
|
|
body: "Poll Q updated",
|
|
|
|
format: undefined,
|
|
|
|
formatted_body: undefined,
|
|
|
|
msgtype: "m.text",
|
|
|
|
[M_TEXT.name]: "Poll Q updated",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"m.relates_to": {
|
|
|
|
event_id: previousEvent.getId(),
|
|
|
|
rel_type: "m.replace",
|
2022-12-12 19:24:14 +08:00
|
|
|
},
|
2022-02-17 17:13:05 +08:00
|
|
|
});
|
|
|
|
});
|
2022-12-22 05:29:11 +08:00
|
|
|
|
|
|
|
it("retains poll disclosure type when editing", () => {
|
|
|
|
const previousEvent: MatrixEvent = new MatrixEvent(
|
|
|
|
PollStartEvent.from("Poll Q", ["Answer 1", "Answer 2"], M_POLL_KIND_DISCLOSED).serialize(),
|
|
|
|
);
|
|
|
|
previousEvent.event.event_id = "$prevEventId";
|
|
|
|
|
|
|
|
const dialog = mount(
|
|
|
|
<PollCreateDialog room={createRoom()} onFinished={jest.fn()} editingMxEvent={previousEvent} />,
|
|
|
|
);
|
|
|
|
|
|
|
|
changeValue(dialog, "Question or topic", "Poll Q updated");
|
|
|
|
dialog.find("button").simulate("click");
|
|
|
|
|
|
|
|
const [, , eventType, sentEventContent] = mockClient.sendEvent.mock.calls[0];
|
|
|
|
expect(M_POLL_START.matches(eventType)).toBeTruthy();
|
|
|
|
// didnt change
|
|
|
|
expect(sentEventContent["m.new_content"][M_POLL_START.name].kind).toEqual(M_POLL_KIND_DISCLOSED.name);
|
|
|
|
});
|
2021-11-24 21:48:07 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
function createRoom(): Room {
|
|
|
|
return new Room("roomid", MatrixClientPeg.get(), "@name:example.com", {});
|
|
|
|
}
|
|
|
|
|
|
|
|
function changeValue(wrapper: ReactWrapper, labelText: string, value: string) {
|
|
|
|
wrapper.find(`input[label="${labelText}"]`).simulate("change", { target: { value: value } });
|
|
|
|
}
|
|
|
|
|
2022-02-21 18:21:35 +08:00
|
|
|
function changeKind(wrapper: ReactWrapper, value: string) {
|
|
|
|
wrapper.find("select").simulate("change", { target: { value: value } });
|
|
|
|
}
|
|
|
|
|
2021-11-24 21:48:07 +08:00
|
|
|
function submitIsDisabled(wrapper: ReactWrapper) {
|
|
|
|
return wrapper.find('button[type="submit"]').prop("aria-disabled") === true;
|
|
|
|
}
|