forked from potsda.mn/mobilizon
Merge branch 'add-tests-for-participation-without-account' into 'master'
Add tests for participation without account Closes #533 See merge request framasoft/mobilizon!744
This commit is contained in:
commit
fe81771658
|
@ -81,33 +81,72 @@
|
||||||
{{ $t("Request for participation confirmation sent") }}
|
{{ $t("Request for participation confirmation sent") }}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="content">
|
<p class="content">
|
||||||
{{ $t("Check your inbox (and your junk mail folder).") }}
|
<span>{{
|
||||||
|
$t("Check your inbox (and your junk mail folder).")
|
||||||
|
}}</span>
|
||||||
|
<span
|
||||||
|
class="details"
|
||||||
|
v-if="event.joinOptions === EventJoinOptions.RESTRICTED"
|
||||||
|
>
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation."
|
||||||
|
)
|
||||||
|
}} </span
|
||||||
|
><span class="details" v-else>{{
|
||||||
|
$t(
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email."
|
||||||
|
)
|
||||||
|
}}</span>
|
||||||
|
</p>
|
||||||
|
<b-message type="is-warning" v-if="error">{{ error }}</b-message>
|
||||||
|
<p class="content">
|
||||||
|
<i18n path="You may now close this window, or {return_to_event}.">
|
||||||
|
<router-link
|
||||||
|
slot="return_to_event"
|
||||||
|
:to="{ name: RouteName.EVENT, params: { uuid: event.uuid } }"
|
||||||
|
>{{ $t("return to the event's page") }}</router-link
|
||||||
|
>
|
||||||
|
</i18n>
|
||||||
</p>
|
</p>
|
||||||
<p class="content">{{ $t("You may now close this window.") }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<b-message type="is-danger" v-else-if="!$apollo.loading"
|
||||||
|
>{{
|
||||||
|
$t(
|
||||||
|
"Unable to load event for participation. The error details are provided below:"
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
<details>
|
||||||
|
<pre>{{ error }}</pre>
|
||||||
|
</details>
|
||||||
|
</b-message>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop, Vue } from "vue-property-decorator";
|
import { Component, Prop, Vue } from "vue-property-decorator";
|
||||||
import { EventModel, IEvent } from "@/types/event.model";
|
import { EventModel, IEvent } from "@/types/event.model";
|
||||||
import { FETCH_EVENT, JOIN_EVENT } from "@/graphql/event";
|
import { FETCH_EVENT_BASIC, JOIN_EVENT } from "@/graphql/event";
|
||||||
import { IConfig } from "@/types/config.model";
|
import { IConfig } from "@/types/config.model";
|
||||||
import { CONFIG } from "@/graphql/config";
|
import { CONFIG } from "@/graphql/config";
|
||||||
import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
|
import { addLocalUnconfirmedAnonymousParticipation } from "@/services/AnonymousParticipationStorage";
|
||||||
import { EventJoinOptions, ParticipantRole } from "@/types/enums";
|
import { EventJoinOptions, ParticipantRole } from "@/types/enums";
|
||||||
|
import RouteName from "@/router/name";
|
||||||
import { IParticipant } from "../../types/participant.model";
|
import { IParticipant } from "../../types/participant.model";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
apollo: {
|
apollo: {
|
||||||
event: {
|
event: {
|
||||||
query: FETCH_EVENT,
|
query: FETCH_EVENT_BASIC,
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
uuid: this.uuid,
|
uuid: this.uuid,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
error(e) {
|
||||||
|
this.error = e;
|
||||||
|
},
|
||||||
skip() {
|
skip() {
|
||||||
return !this.uuid;
|
return !this.uuid;
|
||||||
},
|
},
|
||||||
|
@ -141,6 +180,8 @@ export default class ParticipationWithoutAccount extends Vue {
|
||||||
|
|
||||||
EventJoinOptions = EventJoinOptions;
|
EventJoinOptions = EventJoinOptions;
|
||||||
|
|
||||||
|
RouteName = RouteName;
|
||||||
|
|
||||||
async joinEvent(): Promise<void> {
|
async joinEvent(): Promise<void> {
|
||||||
this.error = false;
|
this.error = false;
|
||||||
this.sendingForm = true;
|
this.sendingForm = true;
|
||||||
|
@ -163,7 +204,7 @@ export default class ParticipationWithoutAccount extends Vue {
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachedData = store.readQuery<{ event: IEvent }>({
|
const cachedData = store.readQuery<{ event: IEvent }>({
|
||||||
query: FETCH_EVENT,
|
query: FETCH_EVENT_BASIC,
|
||||||
variables: { uuid: this.event.uuid },
|
variables: { uuid: this.event.uuid },
|
||||||
});
|
});
|
||||||
if (cachedData == null) {
|
if (cachedData == null) {
|
||||||
|
@ -186,16 +227,15 @@ export default class ParticipationWithoutAccount extends Vue {
|
||||||
event.participantStats.going += 1;
|
event.participantStats.going += 1;
|
||||||
event.participantStats.participant += 1;
|
event.participantStats.participant += 1;
|
||||||
}
|
}
|
||||||
console.log("just before writequery");
|
|
||||||
|
|
||||||
store.writeQuery({
|
store.writeQuery({
|
||||||
query: FETCH_EVENT,
|
query: FETCH_EVENT_BASIC,
|
||||||
variables: { uuid: this.event.uuid },
|
variables: { uuid: this.event.uuid },
|
||||||
data: { event },
|
data: { event },
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
console.log("finished with store", data);
|
this.formSent = true;
|
||||||
if (
|
if (
|
||||||
data &&
|
data &&
|
||||||
data.joinEvent.metadata.cancellationToken &&
|
data.joinEvent.metadata.cancellationToken &&
|
||||||
|
@ -205,13 +245,28 @@ export default class ParticipationWithoutAccount extends Vue {
|
||||||
this.event,
|
this.event,
|
||||||
data.joinEvent.metadata.cancellationToken
|
data.joinEvent.metadata.cancellationToken
|
||||||
);
|
);
|
||||||
console.log("done with crypto stuff");
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error = e.message;
|
if (
|
||||||
|
["TextEncoder is not defined", "crypto.subtle is undefined"].includes(
|
||||||
|
e.message
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
this.error = this.$t(
|
||||||
|
"Unable to save your participation in this browser."
|
||||||
|
) as string;
|
||||||
|
} else if (e.graphQLErrors && e.graphQLErrors.length > 0) {
|
||||||
|
this.error = e.graphQLErrors[0].message;
|
||||||
|
} else if (e.networkError) {
|
||||||
|
this.error = e.networkError.message;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.sendingForm = false;
|
this.sendingForm = false;
|
||||||
this.formSent = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
section.container.section {
|
||||||
|
background: $white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -176,6 +176,22 @@ export const FETCH_EVENT = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const FETCH_EVENT_BASIC = gql`
|
||||||
|
query($uuid: UUID!) {
|
||||||
|
event(uuid: $uuid) {
|
||||||
|
id
|
||||||
|
uuid
|
||||||
|
joinOptions
|
||||||
|
participantStats {
|
||||||
|
going
|
||||||
|
notApproved
|
||||||
|
notConfirmed
|
||||||
|
participant
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const FETCH_EVENTS = gql`
|
export const FETCH_EVENTS = gql`
|
||||||
query {
|
query {
|
||||||
events {
|
events {
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
"Anonymous participant": "Anonymous participant",
|
"Anonymous participant": "Anonymous participant",
|
||||||
"Anonymous participants will be asked to confirm their participation through e-mail.": "Anonymous participants will be asked to confirm their participation through e-mail.",
|
"Anonymous participants will be asked to confirm their participation through e-mail.": "Anonymous participants will be asked to confirm their participation through e-mail.",
|
||||||
"Anonymous participations": "Anonymous participations",
|
"Anonymous participations": "Anonymous participations",
|
||||||
"Approve": "Approve",
|
|
||||||
"Are you really sure you want to delete your whole account? You'll lose everything. Identities, settings, events created, messages and participations will be gone forever.": "Are you really sure you want to delete your whole account? You'll lose everything. Identities, settings, events created, messages and participations will be gone forever.",
|
"Are you really sure you want to delete your whole account? You'll lose everything. Identities, settings, events created, messages and participations will be gone forever.": "Are you really sure you want to delete your whole account? You'll lose everything. Identities, settings, events created, messages and participations will be gone forever.",
|
||||||
"Are you sure you want to <b>delete</b> this comment? This action cannot be undone.": "Are you sure you want to <b>delete</b> this comment? This action cannot be undone.",
|
"Are you sure you want to <b>delete</b> this comment? This action cannot be undone.": "Are you sure you want to <b>delete</b> this comment? This action cannot be undone.",
|
||||||
"Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the discussion with the event creator or edit its event instead.": "Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the discussion with the event creator or edit its event instead.",
|
"Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the discussion with the event creator or edit its event instead.": "Are you sure you want to <b>delete</b> this event? This action cannot be undone. You may want to engage the discussion with the event creator or edit its event instead.",
|
||||||
|
@ -70,7 +69,6 @@
|
||||||
"Create my profile": "Create my profile",
|
"Create my profile": "Create my profile",
|
||||||
"Create token": "Create token",
|
"Create token": "Create token",
|
||||||
"Create": "Create",
|
"Create": "Create",
|
||||||
"Creator": "Creator",
|
|
||||||
"Current identity has been changed to {identityName} in order to manage this event.": "Current identity has been changed to {identityName} in order to manage this event.",
|
"Current identity has been changed to {identityName} in order to manage this event.": "Current identity has been changed to {identityName} in order to manage this event.",
|
||||||
"Current page": "Current page",
|
"Current page": "Current page",
|
||||||
"Custom URL": "Custom URL",
|
"Custom URL": "Custom URL",
|
||||||
|
@ -126,7 +124,6 @@
|
||||||
"Event": "Event",
|
"Event": "Event",
|
||||||
"Events": "Events",
|
"Events": "Events",
|
||||||
"Ex: mobilizon.fr": "Ex: mobilizon.fr",
|
"Ex: mobilizon.fr": "Ex: mobilizon.fr",
|
||||||
"Exclude": "Exclude",
|
|
||||||
"Explore": "Explore",
|
"Explore": "Explore",
|
||||||
"Failed to save admin settings": "Failed to save admin settings",
|
"Failed to save admin settings": "Failed to save admin settings",
|
||||||
"Featured events": "Featured events",
|
"Featured events": "Featured events",
|
||||||
|
@ -145,7 +142,6 @@
|
||||||
"General": "General",
|
"General": "General",
|
||||||
"Getting location": "Getting location",
|
"Getting location": "Getting location",
|
||||||
"Go": "Go",
|
"Go": "Go",
|
||||||
"Going as {name}": "Going as {name}",
|
|
||||||
"Group name": "Group name",
|
"Group name": "Group name",
|
||||||
"Group {displayName} created": "Group {displayName} created",
|
"Group {displayName} created": "Group {displayName} created",
|
||||||
"Groups": "Groups",
|
"Groups": "Groups",
|
||||||
|
@ -280,7 +276,6 @@
|
||||||
"Registration is allowed, anyone can register.": "Registration is allowed, anyone can register.",
|
"Registration is allowed, anyone can register.": "Registration is allowed, anyone can register.",
|
||||||
"Registration is closed.": "Registration is closed.",
|
"Registration is closed.": "Registration is closed.",
|
||||||
"Registration is currently closed.": "Registration is currently closed.",
|
"Registration is currently closed.": "Registration is currently closed.",
|
||||||
"Reject": "Reject",
|
|
||||||
"Rejected": "Rejected",
|
"Rejected": "Rejected",
|
||||||
"Reopen": "Reopen",
|
"Reopen": "Reopen",
|
||||||
"Reply": "Reply",
|
"Reply": "Reply",
|
||||||
|
@ -749,7 +744,7 @@
|
||||||
"Go to the event page": "Go to the event page",
|
"Go to the event page": "Go to the event page",
|
||||||
"Request for participation confirmation sent": "Request for participation confirmation sent",
|
"Request for participation confirmation sent": "Request for participation confirmation sent",
|
||||||
"Check your inbox (and your junk mail folder).": "Check your inbox (and your junk mail folder).",
|
"Check your inbox (and your junk mail folder).": "Check your inbox (and your junk mail folder).",
|
||||||
"You may now close this window.": "You may now close this window.",
|
"You may now close this window, or {return_to_event}.": "You may now close this window, or {return_to_event}.",
|
||||||
"Create an account": "Create an account",
|
"Create an account": "Create an account",
|
||||||
"You are not an administrator for this group.": "You are not an administrator for this group.",
|
"You are not an administrator for this group.": "You are not an administrator for this group.",
|
||||||
"Why create an account?": "Why create an account?",
|
"Why create an account?": "Why create an account?",
|
||||||
|
@ -810,5 +805,10 @@
|
||||||
"Your participation status is saved only on this device and will be deleted one month after the event's passed.": "Your participation status is saved only on this device and will be deleted one month after the event's passed.",
|
"Your participation status is saved only on this device and will be deleted one month after the event's passed.": "Your participation status is saved only on this device and will be deleted one month after the event's passed.",
|
||||||
"You may clear all participation information for this device with the buttons below.": "You may clear all participation information for this device with the buttons below.",
|
"You may clear all participation information for this device with the buttons below.": "You may clear all participation information for this device with the buttons below.",
|
||||||
"Clear participation data for this event": "Clear participation data for this event",
|
"Clear participation data for this event": "Clear participation data for this event",
|
||||||
"Clear participation data for all events": "Clear participation data for all events"
|
"Clear participation data for all events": "Clear participation data for all events",
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation.": "Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation.",
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email.": "Your participation will be validated once you click the confirmation link into the email.",
|
||||||
|
"Unable to load event for participation. The error details are provided below:": "Unable to load event for participation. The error details are provided below:",
|
||||||
|
"Unable to save your participation in this browser.": "Unable to save your participation in this browser.",
|
||||||
|
"return to the event's page": "return to the event's page"
|
||||||
}
|
}
|
||||||
|
|
|
@ -794,7 +794,6 @@
|
||||||
"You have one event today.": "Vous n'avez pas d'évenement aujourd'hui | Vous avez un évènement aujourd'hui. | Vous avez {count} évènements aujourd'hui",
|
"You have one event today.": "Vous n'avez pas d'évenement aujourd'hui | Vous avez un évènement aujourd'hui. | Vous avez {count} évènements aujourd'hui",
|
||||||
"You have one event tomorrow.": "Vous n'avez pas d'évènement demain | Vous avez un évènement demain. | Vous avez {count} évènements demain",
|
"You have one event tomorrow.": "Vous n'avez pas d'évènement demain | Vous avez un évènement demain. | Vous avez {count} évènements demain",
|
||||||
"You may also ask to {resend_confirmation_email}.": "Vous pouvez aussi demander à {resend_confirmation_email}.",
|
"You may also ask to {resend_confirmation_email}.": "Vous pouvez aussi demander à {resend_confirmation_email}.",
|
||||||
"You may now close this window.": "Vous pouvez maintenant fermer cette fenêtre.",
|
|
||||||
"You need to create the group before you create an event.": "Vous devez créer le groupe avant de créer l'événement.",
|
"You need to create the group before you create an event.": "Vous devez créer le groupe avant de créer l'événement.",
|
||||||
"You need to login.": "Vous devez vous connecter.",
|
"You need to login.": "Vous devez vous connecter.",
|
||||||
"You will be able to add an avatar and set other options in your account settings.": "Vous pourrez ajouter un avatar et définir d'autres options dans les paramètres de votre compte.",
|
"You will be able to add an avatar and set other options in your account settings.": "Vous pourrez ajouter un avatar et définir d'autres options dans les paramètres de votre compte.",
|
||||||
|
@ -898,5 +897,11 @@
|
||||||
"Your participation status is saved only on this device and will be deleted one month after the event's passed.": "Le statut de votre participation est enregistré uniquement sur cet appareil et sera supprimé un mois après la fin de l'événement.",
|
"Your participation status is saved only on this device and will be deleted one month after the event's passed.": "Le statut de votre participation est enregistré uniquement sur cet appareil et sera supprimé un mois après la fin de l'événement.",
|
||||||
"You may clear all participation information for this device with the buttons below.": "Vous pouvez effacer toutes les informations de participation pour cet appareil avec les boutons ci-dessous.",
|
"You may clear all participation information for this device with the buttons below.": "Vous pouvez effacer toutes les informations de participation pour cet appareil avec les boutons ci-dessous.",
|
||||||
"Clear participation data for this event": "Effacer mes données de participation pour cet événement",
|
"Clear participation data for this event": "Effacer mes données de participation pour cet événement",
|
||||||
"Clear participation data for all events": "Effacer mes données de participation pour tous les événements"
|
"Clear participation data for all events": "Effacer mes données de participation pour tous les événements",
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation.": "Votre participation sera validée une fois que vous aurez cliqué sur le lien de confirmation contenu dans le courriel, et après que l'organisateur·ice valide votre participation.",
|
||||||
|
"Your participation will be validated once you click the confirmation link into the email.": "Votre participation sera validée une fois que vous aurez cliqué sur le lien de confirmation contenu dans le courriel.",
|
||||||
|
"Unable to load event for participation. The error details are provided below:": "Impossible de charger l'événement pour la participation. Les détails de l'erreur sont disponibles ci-dessous :",
|
||||||
|
"Unable to save your participation in this browser.": "Échec de la sauvegarde de votre participation dans ce navigateur.",
|
||||||
|
"return to the event's page": "retourner sur la page de l'événement",
|
||||||
|
"You may now close this window, or {return_to_event}.": "Vous pouvez maintenant fermer cette fenêtre, ou bien {return_to_event}."
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,9 @@ describe("CommentTree", () => {
|
||||||
await wrapper.vm.$nextTick(); // because of the <transition>
|
await wrapper.vm.$nextTick(); // because of the <transition>
|
||||||
|
|
||||||
expect(wrapper.exists()).toBe(true);
|
expect(wrapper.exists()).toBe(true);
|
||||||
expect(requestHandlers.eventCommentThreadsQueryHandler).toHaveBeenCalled();
|
expect(
|
||||||
|
requestHandlers.eventCommentThreadsQueryHandler
|
||||||
|
).toHaveBeenCalledWith({ eventUUID: eventData.uuid });
|
||||||
expect(wrapper.vm.$apollo.queries.comments).toBeTruthy();
|
expect(wrapper.vm.$apollo.queries.comments).toBeTruthy();
|
||||||
expect(wrapper.find(".loading").exists()).toBe(false);
|
expect(wrapper.find(".loading").exists()).toBe(false);
|
||||||
expect(wrapper.findAll(".comment-list .root-comment").length).toBe(2);
|
expect(wrapper.findAll(".comment-list .root-comment").length).toBe(2);
|
||||||
|
|
|
@ -0,0 +1,278 @@
|
||||||
|
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 buildCurrentUserResolver from "@/apollo/user";
|
||||||
|
import { InMemoryCache } from "apollo-cache-inmemory";
|
||||||
|
import { CONFIG } from "@/graphql/config";
|
||||||
|
import VueApollo from "vue-apollo";
|
||||||
|
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";
|
||||||
|
|
||||||
|
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: buildCurrentUserResolver(cache),
|
||||||
|
});
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// lots of things to await
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// lots of things to await
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,126 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`ParticipationWithoutAccount handles being already a participant 1`] = `
|
||||||
|
<section class="container section hero is-fullheight">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container">
|
||||||
|
<form>
|
||||||
|
<p>
|
||||||
|
This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.
|
||||||
|
</p>
|
||||||
|
<transition-stub name="fade">
|
||||||
|
<article class="message is-info">
|
||||||
|
<!---->
|
||||||
|
<section class="message-body">
|
||||||
|
<div class="media">
|
||||||
|
<!---->
|
||||||
|
<div class="media-content">
|
||||||
|
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.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</transition-stub>
|
||||||
|
<transition-stub name="fade">
|
||||||
|
<article class="message is-danger">
|
||||||
|
<!---->
|
||||||
|
<section class="message-body">
|
||||||
|
<div class="media">
|
||||||
|
<!---->
|
||||||
|
<div class="media-content">You are already a participant of this event</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</transition-stub>
|
||||||
|
<div class="field"><label class="label">Email address</label>
|
||||||
|
<div class="control is-clearfix"><input type="email" autocomplete="on" placeholder="Your email" required="required" class="input">
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
If you want, you may send a message to the event organizer here.
|
||||||
|
</p>
|
||||||
|
<div class="field"><label class="label">Message</label>
|
||||||
|
<div class="control is-clearfix"><textarea minlength="10" class="textarea"></textarea>
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<!---->
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<!----><label class="b-checkbox checkbox"><input type="checkbox" true-value="true" value="false"><span class="check"></span><span class="control-label"><b>Remember my participation in this browser</b> <p>
|
||||||
|
Will allow to display and manage your participation status on the event page when using this device. Uncheck if you're using a public device.
|
||||||
|
</p></span></label>
|
||||||
|
<!---->
|
||||||
|
</div> <button type="submit" class="button is-primary">
|
||||||
|
<!----><span>Send email</span>
|
||||||
|
<!---->
|
||||||
|
</button>
|
||||||
|
<div class="has-text-centered"><a type="button" class="button is-text">
|
||||||
|
<!----><span>Back to previous page</span>
|
||||||
|
<!---->
|
||||||
|
</a></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`ParticipationWithoutAccount renders the participation without account view with minimal data 1`] = `
|
||||||
|
<section class="container section hero is-fullheight">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<h1 class="title">
|
||||||
|
Request for participation confirmation sent
|
||||||
|
</h1>
|
||||||
|
<p class="content"><span>Check your inbox (and your junk mail folder).</span> <span class="details">Your participation will be validated once you click the confirmation link into the email.</span></p>
|
||||||
|
<transition-stub name="fade">
|
||||||
|
<article class="message is-warning">
|
||||||
|
<!---->
|
||||||
|
<section class="message-body">
|
||||||
|
<div class="media">
|
||||||
|
<!---->
|
||||||
|
<div class="media-content">Unable to save your participation in this browser.</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</transition-stub>
|
||||||
|
<p class="content"><span>You may now close this window, or <a href="/events/f37910ea-fd5a-4756-9679-00971f3f4106" class="">return to the event's page</a>.</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`ParticipationWithoutAccount renders the warning if the event participation is restricted 1`] = `
|
||||||
|
<section class="container section hero is-fullheight">
|
||||||
|
<div class="hero-body">
|
||||||
|
<div class="container">
|
||||||
|
<div>
|
||||||
|
<h1 class="title">
|
||||||
|
Request for participation confirmation sent
|
||||||
|
</h1>
|
||||||
|
<p class="content"><span>Check your inbox (and your junk mail folder).</span> <span class="details">
|
||||||
|
Your participation will be validated once you click the confirmation link into the email, and after the organizer manually validates your participation. </span></p>
|
||||||
|
<transition-stub name="fade">
|
||||||
|
<article class="message is-warning">
|
||||||
|
<!---->
|
||||||
|
<section class="message-body">
|
||||||
|
<div class="media">
|
||||||
|
<!---->
|
||||||
|
<div class="media-content">Unable to save your participation in this browser.</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
</transition-stub>
|
||||||
|
<p class="content"><span>You may now close this window, or <a href="/events/f37910ea-fd5a-4756-9679-00971f3f4106" class="">return to the event's page</a>.</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
`;
|
|
@ -1,3 +1,59 @@
|
||||||
|
import { EventJoinOptions, ParticipantRole } from "@/types/enums";
|
||||||
|
|
||||||
|
type DataMock = {
|
||||||
|
data: Record<string, unknown>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchEventBasicMock = {
|
||||||
|
data: {
|
||||||
|
event: {
|
||||||
|
__typename: "Event",
|
||||||
|
id: "1",
|
||||||
|
uuid: "f37910ea-fd5a-4756-9679-00971f3f4106",
|
||||||
|
joinOptions: EventJoinOptions.FREE,
|
||||||
|
participantStats: {
|
||||||
|
notApproved: 0,
|
||||||
|
notConfirmed: 0,
|
||||||
|
rejected: 0,
|
||||||
|
participant: 0,
|
||||||
|
creator: 1,
|
||||||
|
moderator: 0,
|
||||||
|
administrator: 0,
|
||||||
|
going: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const joinEventResponseMock = {
|
||||||
|
data: {
|
||||||
|
joinEvent: {
|
||||||
|
id: "5",
|
||||||
|
role: ParticipantRole.NOT_APPROVED,
|
||||||
|
insertedAt: "2020-12-07T09:33:41Z",
|
||||||
|
metadata: {
|
||||||
|
cancellationToken: "some token",
|
||||||
|
message: "a message long enough",
|
||||||
|
},
|
||||||
|
event: {
|
||||||
|
id: "1",
|
||||||
|
uuid: "f37910ea-fd5a-4756-9679-00971f3f4106",
|
||||||
|
},
|
||||||
|
actor: {
|
||||||
|
id: "1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const joinEventMock = {
|
||||||
|
eventId: "1",
|
||||||
|
actorId: "1",
|
||||||
|
email: "some@email.tld",
|
||||||
|
message: "a message long enough",
|
||||||
|
locale: "en_US",
|
||||||
|
};
|
||||||
|
|
||||||
export const eventCommentThreadsMock = {
|
export const eventCommentThreadsMock = {
|
||||||
data: {
|
data: {
|
||||||
event: {
|
event: {
|
||||||
|
@ -64,7 +120,7 @@ export const newCommentForEventMock = {
|
||||||
inReplyToCommentId: null,
|
inReplyToCommentId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newCommentForEventResponse = {
|
export const newCommentForEventResponse: DataMock = {
|
||||||
data: {
|
data: {
|
||||||
createComment: {
|
createComment: {
|
||||||
id: "79",
|
id: "79",
|
||||||
|
|
|
@ -100,6 +100,8 @@ defmodule Mobilizon.Service.Workers.Notification do
|
||||||
user
|
user
|
||||||
|> Notification.pending_participation_notification(event, total)
|
|> Notification.pending_participation_notification(event, total)
|
||||||
|> Mailer.deliver_later()
|
|> Mailer.deliver_later()
|
||||||
|
|
||||||
|
:ok
|
||||||
else
|
else
|
||||||
err ->
|
err ->
|
||||||
require Logger
|
require Logger
|
||||||
|
|
Loading…
Reference in a new issue