mobilizon/js/tests/unit/specs/components/Participation/ParticipationWithoutAccount...

272 lines
8.4 KiB
TypeScript

import { config, createLocalVue, mount, Wrapper } from "@vue/test-utils";
import ParticipationWithoutAccount from "@/components/Participation/ParticipationWithoutAccount.vue";
import Buefy from "buefy";
import VueRouter from "vue-router";
import { routes } from "@/router";
import {
CommentModeration,
EventJoinOptions,
ParticipantRole,
} from "@/types/enums";
import {
createMockClient,
MockApolloClient,
RequestHandler,
} from "mock-apollo-client";
import { CONFIG } from "@/graphql/config";
import VueApollo from "@vue/apollo-option";
import { FETCH_EVENT_BASIC, JOIN_EVENT } from "@/graphql/event";
import { IEvent } from "@/types/event.model";
import { i18n } from "@/utils/i18n";
import { configMock } from "../../mocks/config";
import {
fetchEventBasicMock,
joinEventMock,
joinEventResponseMock,
} from "../../mocks/event";
import { InMemoryCache } from "@apollo/client/cache";
import { defaultResolvers } from "../../common";
import flushPromises from "flush-promises";
const localVue = createLocalVue();
localVue.use(Buefy);
localVue.use(VueRouter);
const router = new VueRouter({ routes, mode: "history" });
config.mocks.$t = (key: string): string => key;
const eventData = {
id: "1",
uuid: "f37910ea-fd5a-4756-9679-00971f3f4106",
options: {
commentModeration: CommentModeration.ALLOW_ALL,
},
joinOptions: EventJoinOptions.FREE,
beginsOn: new Date("2089-12-04T09:21:25Z"),
endsOn: new Date("2089-12-04T11:21:25Z"),
participantStats: {
notApproved: 0,
notConfirmed: 0,
rejected: 0,
participant: 0,
creator: 1,
moderator: 0,
administrator: 0,
going: 1,
},
};
describe("ParticipationWithoutAccount", () => {
let wrapper: Wrapper<Vue>;
let mockClient: MockApolloClient;
let apolloProvider;
let requestHandlers: Record<string, RequestHandler>;
const generateWrapper = (
handlers: Record<string, unknown> = {},
customProps: Record<string, unknown> = {},
baseData: Record<string, unknown> = {}
) => {
const cache = new InMemoryCache({ addTypename: false });
mockClient = createMockClient({
cache,
resolvers: defaultResolvers,
});
requestHandlers = {
configQueryHandler: jest.fn().mockResolvedValue(configMock),
fetchEventQueryHandler: jest.fn().mockResolvedValue(fetchEventBasicMock),
joinEventMutationHandler: jest
.fn()
.mockResolvedValue(joinEventResponseMock),
...handlers,
};
mockClient.setRequestHandler(CONFIG, requestHandlers.configQueryHandler);
mockClient.setRequestHandler(
FETCH_EVENT_BASIC,
requestHandlers.fetchEventQueryHandler
);
mockClient.setRequestHandler(
JOIN_EVENT,
requestHandlers.joinEventMutationHandler
);
apolloProvider = new VueApollo({
defaultClient: mockClient,
});
wrapper = mount(ParticipationWithoutAccount, {
localVue,
router,
i18n,
apolloProvider,
propsData: {
uuid: eventData.uuid,
...customProps,
},
data() {
return {
...baseData,
};
},
});
};
it("renders the participation without account view with minimal data", async () => {
generateWrapper();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
expect(wrapper.exists()).toBe(true);
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
expect(wrapper.vm.$apollo.queries.config).toBeTruthy();
expect(requestHandlers.fetchEventQueryHandler).toHaveBeenCalledWith({
uuid: eventData.uuid,
});
expect(wrapper.vm.$apollo.queries.event).toBeTruthy();
expect(wrapper.find(".hero-body .container").isVisible()).toBeTruthy();
expect(wrapper.find("article.message.is-info").text()).toBe(
"Your email will only be used to confirm that you're a real person and send you eventual updates for this event. It will NOT be transmitted to other instances or to the event organizer."
);
wrapper.find('input[type="email"]').setValue("some@email.tld");
wrapper.find("textarea").setValue("a message long enough");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.joinEventMutationHandler).toHaveBeenCalledWith({
...joinEventMock,
});
const cachedData = mockClient.cache.readQuery<{ event: IEvent }>({
query: FETCH_EVENT_BASIC,
variables: {
uuid: eventData.uuid,
},
});
if (cachedData) {
const { event } = cachedData;
expect(event.participantStats.going).toBe(
eventData.participantStats.going + 1
);
expect(event.participantStats.participant).toBe(
eventData.participantStats.participant + 1
);
}
await flushPromises();
expect(wrapper.find("form").exists()).toBeFalsy();
expect(wrapper.find("h1.title").text()).toBe(
"Request for participation confirmation sent"
);
// TextEncoder is not in js-dom
expect(
wrapper.find("article.message.is-warning .media-content").text()
).toBe("Unable to save your participation in this browser.");
expect(wrapper.find("span.details").text()).toBe(
"Your participation will be validated once you click the confirmation link into the email."
);
expect(wrapper.html()).toMatchSnapshot();
});
it("renders the warning if the event participation is restricted", async () => {
generateWrapper({
fetchEventQueryHandler: jest.fn().mockResolvedValue({
data: {
event: {
...fetchEventBasicMock.data.event,
joinOptions: EventJoinOptions.RESTRICTED,
},
},
}),
joinEventMutationHandler: jest.fn().mockResolvedValue({
data: {
joinEvent: {
...joinEventResponseMock.data.joinEvent,
role: ParticipantRole.NOT_CONFIRMED,
},
},
}),
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$data.event.joinOptions).toBe(
EventJoinOptions.RESTRICTED
);
expect(wrapper.find(".hero-body .container").text()).toContain(
"The event organizer manually approves participations. Since you've chosen to participate without an account, please explain why you want to participate to this event."
);
expect(wrapper.find(".hero-body .container").text()).not.toContain(
"If you want, you may send a message to the event organizer here."
);
wrapper.find('input[type="email"]').setValue("some@email.tld");
wrapper.find("textarea").setValue("a message long enough");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.joinEventMutationHandler).toHaveBeenCalledWith({
...joinEventMock,
});
const cachedData = mockClient.cache.readQuery<{ event: IEvent }>({
query: FETCH_EVENT_BASIC,
variables: {
uuid: eventData.uuid,
},
});
if (cachedData) {
const { event } = cachedData;
expect(event.participantStats.notConfirmed).toBe(
eventData.participantStats.notConfirmed + 1
);
}
await flushPromises();
expect(wrapper.find("form").exists()).toBeFalsy();
expect(wrapper.find("h1.title").text()).toBe(
"Request for participation confirmation sent"
);
expect(wrapper.find("span.details").text()).toBe(
"Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation."
);
expect(wrapper.html()).toMatchSnapshot();
});
it("handles being already a participant", async () => {
generateWrapper({
joinEventMutationHandler: jest
.fn()
.mockRejectedValue(
new Error("You are already a participant of this event")
),
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
wrapper.find('input[type="email"]').setValue("some@email.tld");
wrapper.find("textarea").setValue("a message long enough");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.joinEventMutationHandler).toHaveBeenCalledWith({
...joinEventMock,
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
expect(wrapper.find("form").exists()).toBeTruthy();
expect(
wrapper.find("article.message.is-danger .media-content").text()
).toContain("You are already a participant of this event");
expect(wrapper.html()).toMatchSnapshot();
});
});