forked from potsda.mn/mobilizon
test: fix front-end tests
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
bfbc299f37
commit
105d3b5814
|
@ -76,7 +76,7 @@ lint-front:
|
|||
- npm ci
|
||||
script:
|
||||
- npm run lint || export EXITVALUE=1
|
||||
- npm run prettier -c . || export EXITVALUE=1
|
||||
- npx prettier -c . || export EXITVALUE=1
|
||||
- exit $EXITVALUE
|
||||
|
||||
build-frontend:
|
||||
|
|
|
@ -15,7 +15,7 @@ config :mobilizon, Mobilizon.Web.Endpoint,
|
|||
check_origin: false,
|
||||
watchers: [
|
||||
node: [
|
||||
"node_modules/.bin/vite",
|
||||
"node_modules/.bin/vite"
|
||||
]
|
||||
]
|
||||
|
||||
|
|
13
package-lock.json
generated
13
package-lock.json
generated
|
@ -119,7 +119,8 @@
|
|||
"vite": "^4.0.4",
|
||||
"vite-plugin-pwa": "^0.16.4",
|
||||
"vitest": "^0.34.1",
|
||||
"vue-i18n-extract": "^2.0.4"
|
||||
"vue-i18n-extract": "^2.0.4",
|
||||
"vue-router-mock": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@aashutoshrathi/word-wrap": {
|
||||
|
@ -11332,6 +11333,16 @@
|
|||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-router-mock": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-router-mock/-/vue-router-mock-1.0.0.tgz",
|
||||
"integrity": "sha512-j65lh+jhEuEM7sWAz/eenNsEV0VrRXFreNxtIGgLApZkM2h7orImvHSLJ3LhbUa2sJnTtjuy8otSrvoTsdGVYw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"vue": "^3.2.23",
|
||||
"vue-router": "^4.0.12"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-scrollto": {
|
||||
"version": "2.20.0",
|
||||
"license": "MIT",
|
||||
|
|
|
@ -136,6 +136,7 @@
|
|||
"vite": "^4.0.4",
|
||||
"vite-plugin-pwa": "^0.16.4",
|
||||
"vitest": "^0.34.1",
|
||||
"vue-i18n-extract": "^2.0.4"
|
||||
"vue-i18n-extract": "^2.0.4",
|
||||
"vue-router-mock": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,11 @@
|
|||
<transition-group
|
||||
key="list"
|
||||
name="comment-list"
|
||||
v-if="filteredOrderedComments.length && currentActor"
|
||||
v-if="
|
||||
filteredOrderedComments &&
|
||||
filteredOrderedComments.length &&
|
||||
currentActor
|
||||
"
|
||||
class="comment-list"
|
||||
tag="ul"
|
||||
>
|
||||
|
@ -110,29 +114,30 @@ import { AbsintheGraphQLError } from "@/types/errors.model";
|
|||
import { useI18n } from "vue-i18n";
|
||||
import { Notifier } from "@/plugins/notifier";
|
||||
|
||||
const props = defineProps<{
|
||||
event: IEvent;
|
||||
newComment?: IComment;
|
||||
}>();
|
||||
|
||||
const event = computed(() => props.event);
|
||||
const newCommentProps = computed(() => props.newComment);
|
||||
|
||||
const { currentActor } = useCurrentActorClient();
|
||||
|
||||
const { result: commentsResult, loading: commentsLoading } = useQuery<{
|
||||
event: Pick<IEvent, "id" | "uuid" | "comments">;
|
||||
}>(
|
||||
COMMENTS_THREADS_WITH_REPLIES,
|
||||
() => ({ eventUUID: props.event?.uuid }),
|
||||
() => ({ enabled: props.event?.uuid !== undefined })
|
||||
() => ({ eventUUID: event.value?.uuid }),
|
||||
() => ({ enabled: event.value?.uuid !== undefined })
|
||||
);
|
||||
|
||||
const comments = computed(() => commentsResult.value?.event.comments ?? []);
|
||||
|
||||
const props = defineProps<{
|
||||
event: IEvent;
|
||||
newComment?: IComment;
|
||||
}>();
|
||||
|
||||
const Editor = defineAsyncComponent(
|
||||
() => import("@/components/TextEditor.vue")
|
||||
);
|
||||
|
||||
const newCommentProps = computed(() => props.newComment);
|
||||
|
||||
const newCommentValue = ref<IComment>(new CommentModel(newCommentProps.value));
|
||||
|
||||
const emptyCommentError = ref(false);
|
||||
|
@ -170,18 +175,18 @@ const {
|
|||
) => {
|
||||
if (data == null) return;
|
||||
// comments are attached to the event, so we can pass it to replies later
|
||||
const newCommentLocal = { ...data.createComment, event: props.event };
|
||||
const newCommentLocal = { ...data.createComment, event: event.value };
|
||||
|
||||
// we load all existing threads
|
||||
const commentThreadsData = store.readQuery<{ event: IEvent }>({
|
||||
query: COMMENTS_THREADS_WITH_REPLIES,
|
||||
variables: {
|
||||
eventUUID: props.event?.uuid,
|
||||
eventUUID: event.value?.uuid,
|
||||
},
|
||||
});
|
||||
if (!commentThreadsData) return;
|
||||
const { event } = commentThreadsData;
|
||||
const oldComments = [...event.comments];
|
||||
const { event: cachedEvent } = commentThreadsData;
|
||||
const oldComments = [...cachedEvent.comments];
|
||||
|
||||
// if it's no a root comment, we first need to find
|
||||
// existing replies and add the new reply to it
|
||||
|
@ -206,12 +211,12 @@ const {
|
|||
query: COMMENTS_THREADS_WITH_REPLIES,
|
||||
data: {
|
||||
event: {
|
||||
...event,
|
||||
...cachedEvent,
|
||||
comments: oldComments,
|
||||
},
|
||||
},
|
||||
variables: {
|
||||
eventUUID: props.event?.uuid,
|
||||
eventUUID: event.value?.uuid,
|
||||
},
|
||||
});
|
||||
},
|
||||
|
@ -239,10 +244,10 @@ const createCommentForEvent = (comment: IComment) => {
|
|||
|
||||
if (emptyCommentError.value) return;
|
||||
if (!comment.actor) return;
|
||||
if (!props.event?.id) return;
|
||||
if (!event.value?.id) return;
|
||||
|
||||
createCommentForEventMutation({
|
||||
eventId: props.event?.id,
|
||||
eventId: event.value?.id,
|
||||
text: comment.text,
|
||||
inReplyToCommentId: comment.inReplyToComment?.id,
|
||||
isAnnouncement: comment.isAnnouncement,
|
||||
|
@ -266,12 +271,12 @@ const { mutate: deleteComment, onError: deleteCommentMutationError } =
|
|||
const commentsData = store.readQuery<{ event: IEvent }>({
|
||||
query: COMMENTS_THREADS_WITH_REPLIES,
|
||||
variables: {
|
||||
eventUUID: props.event?.uuid,
|
||||
eventUUID: event.value?.uuid,
|
||||
},
|
||||
});
|
||||
if (!commentsData) return;
|
||||
const { event } = commentsData;
|
||||
let updatedComments: IComment[] = [...event.comments];
|
||||
const { event: cachedEvent } = commentsData;
|
||||
let updatedComments: IComment[] = [...cachedEvent.comments];
|
||||
|
||||
if (variables?.originCommentId) {
|
||||
// we have deleted a reply to a thread
|
||||
|
@ -309,11 +314,11 @@ const { mutate: deleteComment, onError: deleteCommentMutationError } =
|
|||
store.writeQuery({
|
||||
query: COMMENTS_THREADS_WITH_REPLIES,
|
||||
variables: {
|
||||
eventUUID: props.event?.uuid,
|
||||
eventUUID: event.value?.uuid,
|
||||
},
|
||||
data: {
|
||||
event: {
|
||||
...event,
|
||||
...cachedEvent,
|
||||
comments: updatedComments,
|
||||
},
|
||||
},
|
||||
|
@ -359,14 +364,14 @@ const filteredOrderedComments = computed((): IComment[] => {
|
|||
|
||||
const isEventOrganiser = computed((): boolean => {
|
||||
const organizerId =
|
||||
props.event?.organizerActor?.id || props.event?.attributedTo?.id;
|
||||
event.value?.organizerActor?.id || event.value?.attributedTo?.id;
|
||||
return organizerId !== undefined && currentActor.value?.id === organizerId;
|
||||
});
|
||||
|
||||
const areCommentsClosed = computed((): boolean => {
|
||||
return (
|
||||
currentActor.value?.id !== undefined &&
|
||||
props.event?.options.commentModeration !== CommentModeration.CLOSED
|
||||
event.value?.options.commentModeration !== CommentModeration.CLOSED
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -250,7 +250,7 @@ const props = withDefaults(
|
|||
event: IEvent;
|
||||
currentActor: IPerson;
|
||||
rootComment?: boolean;
|
||||
readOnly: boolean;
|
||||
readOnly?: boolean;
|
||||
}>(),
|
||||
{ rootComment: true, readOnly: false }
|
||||
);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
</div>
|
||||
|
||||
<div class="p-2">
|
||||
<div class="">
|
||||
<div class="reported_by">
|
||||
<span v-if="report.reporter?.type === ActorType.APPLICATION">
|
||||
{{
|
||||
t("Reported by someone on {domain}", {
|
||||
|
|
|
@ -189,7 +189,7 @@ routes.push({
|
|||
redirect: { name: RouteName.PAGE_NOT_FOUND },
|
||||
});
|
||||
|
||||
export const router = createRouter({
|
||||
const router = createRouter({
|
||||
scrollBehavior,
|
||||
history: createWebHistory("/"),
|
||||
routes,
|
||||
|
@ -216,3 +216,5 @@ router.onError((error, to) => {
|
|||
window.location.href = to.fullPath;
|
||||
}
|
||||
});
|
||||
|
||||
export { router };
|
||||
|
|
|
@ -142,6 +142,7 @@ import RouteName from "@/router/name";
|
|||
import { LoginError, LoginErrorCode } from "@/types/enums";
|
||||
import { useCurrentUserClient } from "@/composition/apollo/user";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { enumTransformer, useRouteQuery } from "vue-use-route-query";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
const router = useRouter();
|
||||
|
@ -174,9 +175,8 @@ const credentials = reactive({
|
|||
typeof route.query.password === "string" ? route.query.password : "",
|
||||
});
|
||||
|
||||
const redirect = ref<string | undefined>("");
|
||||
|
||||
const errorCode = ref<LoginErrorCode | null>(null);
|
||||
const redirect = useRouteQuery("redirect", "");
|
||||
const errorCode = useRouteQuery("code", null, enumTransformer(LoginErrorCode));
|
||||
|
||||
const {
|
||||
onDone: onLoginMutationDone,
|
||||
|
@ -195,6 +195,7 @@ onLoginMutationDone(async (result) => {
|
|||
await setupClientUserAndActors(data.login);
|
||||
|
||||
if (redirect.value) {
|
||||
console.debug("We have a redirect", redirect.value);
|
||||
router.push(redirect.value);
|
||||
return;
|
||||
}
|
||||
|
@ -293,10 +294,6 @@ const currentProvider = computed(() => {
|
|||
});
|
||||
|
||||
onMounted(() => {
|
||||
const query = route?.query;
|
||||
errorCode.value = query?.code as LoginErrorCode;
|
||||
redirect.value = query?.redirect as string | undefined;
|
||||
|
||||
// Already-logged-in and accessing /login
|
||||
if (currentUser.value?.isLoggedIn) {
|
||||
console.debug(
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
import "./specs/mocks/matchMedia";
|
||||
import { config } from "@vue/test-utils";
|
||||
import { createHead } from "@vueuse/head";
|
||||
import { createI18n } from "vue-i18n";
|
||||
import en_US from "@/i18n/en_US.json";
|
||||
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
messages: { en_US },
|
||||
locale: "en_US",
|
||||
});
|
||||
import { i18n } from "@/utils/i18n";
|
||||
|
||||
const head = createHead();
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ describe("CommentTree", () => {
|
|||
await flushPromises();
|
||||
expect(wrapper.find("p.text-center").exists()).toBe(false);
|
||||
|
||||
expect(wrapper.findAllComponents("comment-stub").length).toBe(2);
|
||||
expect(wrapper.findAllComponents("event-comment-stub").length).toBe(2);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -130,6 +130,9 @@ describe("CommentTree", () => {
|
|||
newComment: {
|
||||
text: newCommentForEventMock.text,
|
||||
isAnnouncement: false,
|
||||
insertedAt: "2021-12-03T13:02:00Z",
|
||||
updatedAt: "2021-12-03T13:02:00Z",
|
||||
publishedAt: "2021-12-03T13:02:00Z",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
@ -137,7 +140,7 @@ describe("CommentTree", () => {
|
|||
await flushPromises();
|
||||
|
||||
expect(wrapper.find("form").isVisible()).toBe(true);
|
||||
expect(wrapper.findAllComponents("comment-stub").length).toBe(2);
|
||||
expect(wrapper.findAllComponents("event-comment-stub").length).toBe(2);
|
||||
wrapper.getComponent({ ref: "commenteditor" });
|
||||
|
||||
wrapper.find("form").trigger("submit");
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`CommentTree > renders a comment tree with comments 1`] = `
|
||||
"<div data-v-5d0380ab=\\"\\">
|
||||
<form class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<form data-v-5d0380ab=\\"\\" class=\\"mt-2\\">
|
||||
<!--v-if-->
|
||||
<article class=\\"flex flex-wrap items-start gap-2\\" data-v-5d0380ab=\\"\\">
|
||||
<figure class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<identity-picker-wrapper-stub modelvalue=\\"[object Object]\\" inline=\\"false\\" masked=\\"false\\" data-v-5d0380ab=\\"\\"></identity-picker-wrapper-stub>
|
||||
<article data-v-5d0380ab=\\"\\" class=\\"flex flex-wrap items-start gap-2\\">
|
||||
<figure data-v-5d0380ab=\\"\\" class=\\"\\">
|
||||
<identity-picker-wrapper-stub data-v-5d0380ab=\\"\\" modelvalue=\\"[object Object]\\" inline=\\"false\\" masked=\\"false\\"></identity-picker-wrapper-stub>
|
||||
</figure>
|
||||
<div class=\\"flex-1\\" data-v-5d0380ab=\\"\\">
|
||||
<div class=\\"flex flex-col gap-2\\" data-v-5d0380ab=\\"\\">
|
||||
<div class=\\"editor-wrapper\\" data-v-5d0380ab=\\"\\">
|
||||
<editor-stub currentactor=\\"[object Object]\\" mode=\\"comment\\" modelvalue=\\"\\" aria-label=\\"Comment body\\" data-v-5d0380ab=\\"\\"></editor-stub>
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"flex-1\\">
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"flex flex-col gap-2\\">
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"editor-wrapper\\">
|
||||
<editor-stub data-v-5d0380ab=\\"\\" currentactor=\\"[object Object]\\" mode=\\"comment\\" modelvalue=\\"\\" aria-label=\\"Comment body\\" placeholder=\\"Write a new comment\\"></editor-stub>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<o-button-stub variant=\\"primary\\" iconleft=\\"send\\" rounded=\\"false\\" outlined=\\"false\\" expanded=\\"false\\" inverted=\\"false\\" nativetype=\\"submit\\" tag=\\"button\\" disabled=\\"false\\" iconboth=\\"false\\" data-v-5d0380ab=\\"\\"></o-button-stub>
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"\\">
|
||||
<o-button-stub data-v-5d0380ab=\\"\\" variant=\\"primary\\" iconleft=\\"send\\" rounded=\\"false\\" outlined=\\"false\\" loading=\\"false\\" expanded=\\"false\\" inverted=\\"false\\" nativetype=\\"submit\\" tag=\\"button\\" disabled=\\"false\\" iconboth=\\"false\\"></o-button-stub>
|
||||
</div>
|
||||
</article>
|
||||
</form>
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\">
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\">
|
||||
<comment-stub comment=\\"[object Object]\\" event=\\"[object Object]\\" currentactor=\\"[object Object]\\" rootcomment=\\"true\\" class=\\"root-comment\\" data-v-5d0380ab=\\"\\"></comment-stub>
|
||||
<comment-stub comment=\\"[object Object]\\" event=\\"[object Object]\\" currentactor=\\"[object Object]\\" rootcomment=\\"true\\" class=\\"root-comment\\" data-v-5d0380ab=\\"\\"></comment-stub>
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\" tag=\\"div\\" name=\\"comment-empty-list\\" appear=\\"false\\" persisted=\\"false\\" css=\\"true\\" class=\\"mt-2\\">
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\" name=\\"comment-list\\" tag=\\"ul\\" appear=\\"false\\" persisted=\\"false\\" css=\\"true\\" class=\\"comment-list\\">
|
||||
<event-comment-stub data-v-5d0380ab=\\"\\" comment=\\"[object Object]\\" event=\\"[object Object]\\" currentactor=\\"[object Object]\\" rootcomment=\\"true\\" readonly=\\"false\\" class=\\"root-comment my-2\\"></event-comment-stub>
|
||||
<event-comment-stub data-v-5d0380ab=\\"\\" comment=\\"[object Object]\\" event=\\"[object Object]\\" currentactor=\\"[object Object]\\" rootcomment=\\"true\\" readonly=\\"false\\" class=\\"root-comment my-2\\"></event-comment-stub>
|
||||
</transition-group-stub>
|
||||
</transition-group-stub>
|
||||
</div>"
|
||||
|
@ -34,34 +34,34 @@ exports[`CommentTree > renders a comment tree with comments 1`] = `
|
|||
exports[`CommentTree > renders a loading comment tree 1`] = `
|
||||
"<div data-v-5d0380ab=\\"\\">
|
||||
<!--v-if-->
|
||||
<p class=\\"text-center\\" data-v-5d0380ab=\\"\\">Loading comments…</p>
|
||||
<p data-v-5d0380ab=\\"\\" class=\\"text-center\\">Loading comments…</p>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`CommentTree > renders an empty comment tree 1`] = `
|
||||
"<div data-v-5d0380ab=\\"\\">
|
||||
<form class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<form data-v-5d0380ab=\\"\\" class=\\"mt-2\\">
|
||||
<!--v-if-->
|
||||
<article class=\\"flex flex-wrap items-start gap-2\\" data-v-5d0380ab=\\"\\">
|
||||
<figure class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<identity-picker-wrapper-stub modelvalue=\\"[object Object]\\" inline=\\"false\\" masked=\\"false\\" data-v-5d0380ab=\\"\\"></identity-picker-wrapper-stub>
|
||||
<article data-v-5d0380ab=\\"\\" class=\\"flex flex-wrap items-start gap-2\\">
|
||||
<figure data-v-5d0380ab=\\"\\" class=\\"\\">
|
||||
<identity-picker-wrapper-stub data-v-5d0380ab=\\"\\" modelvalue=\\"[object Object]\\" inline=\\"false\\" masked=\\"false\\"></identity-picker-wrapper-stub>
|
||||
</figure>
|
||||
<div class=\\"flex-1\\" data-v-5d0380ab=\\"\\">
|
||||
<div class=\\"flex flex-col gap-2\\" data-v-5d0380ab=\\"\\">
|
||||
<div class=\\"editor-wrapper\\" data-v-5d0380ab=\\"\\">
|
||||
<editor-stub currentactor=\\"[object Object]\\" mode=\\"comment\\" modelvalue=\\"\\" aria-label=\\"Comment body\\" data-v-5d0380ab=\\"\\"></editor-stub>
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"flex-1\\">
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"flex flex-col gap-2\\">
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"editor-wrapper\\">
|
||||
<editor-stub data-v-5d0380ab=\\"\\" currentactor=\\"[object Object]\\" mode=\\"comment\\" modelvalue=\\"\\" aria-label=\\"Comment body\\" placeholder=\\"Write a new comment\\"></editor-stub>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</div>
|
||||
<div class=\\"\\" data-v-5d0380ab=\\"\\">
|
||||
<o-button-stub variant=\\"primary\\" iconleft=\\"send\\" rounded=\\"false\\" outlined=\\"false\\" expanded=\\"false\\" inverted=\\"false\\" nativetype=\\"submit\\" tag=\\"button\\" disabled=\\"false\\" iconboth=\\"false\\" data-v-5d0380ab=\\"\\"></o-button-stub>
|
||||
<div data-v-5d0380ab=\\"\\" class=\\"\\">
|
||||
<o-button-stub data-v-5d0380ab=\\"\\" variant=\\"primary\\" iconleft=\\"send\\" rounded=\\"false\\" outlined=\\"false\\" loading=\\"false\\" expanded=\\"false\\" inverted=\\"false\\" nativetype=\\"submit\\" tag=\\"button\\" disabled=\\"false\\" iconboth=\\"false\\"></o-button-stub>
|
||||
</div>
|
||||
</article>
|
||||
</form>
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\">
|
||||
<empty-content-stub icon=\\"comment\\" descriptionclasses=\\"\\" inline=\\"true\\" center=\\"false\\" data-v-5d0380ab=\\"\\"></empty-content-stub>
|
||||
<transition-group-stub data-v-5d0380ab=\\"\\" tag=\\"div\\" name=\\"comment-empty-list\\" appear=\\"false\\" persisted=\\"false\\" css=\\"true\\" class=\\"mt-2\\">
|
||||
<empty-content-stub data-v-5d0380ab=\\"\\" icon=\\"comment\\" descriptionclasses=\\"\\" inline=\\"true\\" center=\\"false\\"></empty-content-stub>
|
||||
</transition-group-stub>
|
||||
</div>"
|
||||
`;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`GroupSection > renders group section with basic informations 1`] = `
|
||||
"<section class=\\"flex flex-col mb-3 border-2 border-mbz-purple\\">
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`ParticipationWithoutAccount > handles being already a participant 1`] = `
|
||||
"<section class=\\"container mx-auto\\">
|
||||
<div class=\\"\\">
|
||||
<form>
|
||||
<p>This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.</p>
|
||||
<transition-stub>
|
||||
<transition-stub name=\\"fade\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\">
|
||||
<article class=\\"o-notification o-notification--info\\">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
|
@ -15,7 +15,7 @@ exports[`ParticipationWithoutAccount > handles being already a participant 1`] =
|
|||
</div>
|
||||
</article>
|
||||
</transition-stub>
|
||||
<transition-stub>
|
||||
<transition-stub name=\\"fade\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\">
|
||||
<article class=\\"o-notification o-notification--danger\\">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`PostListItem > renders post list item with basic informations 1`] = `
|
||||
"<a href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\" data-v-6ca7cc69=\\"\\">
|
||||
"<a data-v-6ca7cc69=\\"\\" href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\">
|
||||
<!--v-if-->
|
||||
<div class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\" data-v-6ca7cc69=\\"\\">
|
||||
<h3 class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\" data-v-6ca7cc69=\\"\\">My Blog Post</h3>
|
||||
<p class=\\"flex gap-2\\" data-v-6ca7cc69=\\"\\"><span aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\" data-v-6ca7cc69=\\"\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span dir=\\"auto\\" class=\\"\\" data-v-6ca7cc69=\\"\\">Dec 2, 2020</span></p>
|
||||
<div data-v-6ca7cc69=\\"\\" class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\">
|
||||
<h3 data-v-6ca7cc69=\\"\\" class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\">My Blog Post</h3>
|
||||
<p data-v-6ca7cc69=\\"\\" class=\\"flex gap-2\\"><span data-v-6ca7cc69=\\"\\" aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span data-v-6ca7cc69=\\"\\" dir=\\"auto\\" class=\\"\\">Dec 2, 2020</span></p>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
|
@ -13,24 +14,26 @@ exports[`PostListItem > renders post list item with basic informations 1`] = `
|
|||
`;
|
||||
|
||||
exports[`PostListItem > renders post list item with publisher name 1`] = `
|
||||
"<a href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\" data-v-6ca7cc69=\\"\\">
|
||||
"<a data-v-6ca7cc69=\\"\\" href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\">
|
||||
<!--v-if-->
|
||||
<div class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\" data-v-6ca7cc69=\\"\\">
|
||||
<h3 class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\" data-v-6ca7cc69=\\"\\">My Blog Post</h3>
|
||||
<p class=\\"flex gap-2\\" data-v-6ca7cc69=\\"\\"><span aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\" data-v-6ca7cc69=\\"\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span dir=\\"auto\\" class=\\"\\" data-v-6ca7cc69=\\"\\">Dec 2, 2020</span></p>
|
||||
<div data-v-6ca7cc69=\\"\\" class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\">
|
||||
<h3 data-v-6ca7cc69=\\"\\" class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\">My Blog Post</h3>
|
||||
<p data-v-6ca7cc69=\\"\\" class=\\"flex gap-2\\"><span data-v-6ca7cc69=\\"\\" aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span data-v-6ca7cc69=\\"\\" dir=\\"auto\\" class=\\"\\">Dec 2, 2020</span></p>
|
||||
<!--v-if-->
|
||||
<p data-v-6ca7cc69=\\"\\" class=\\"flex gap-1\\"><span data-v-6ca7cc69=\\"\\" aria-hidden=\\"true\\" class=\\"material-design-icon account-edit-icon\\" role=\\"img\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M21.7,13.35L20.7,14.35L18.65,12.3L19.65,11.3C19.86,11.09 20.21,11.09 20.42,11.3L21.7,12.58C21.91,12.79 21.91,13.14 21.7,13.35M12,18.94L18.06,12.88L20.11,14.93L14.06,21H12V18.94M12,14C7.58,14 4,15.79 4,18V20H10V18.11L14,14.11C13.34,14.03 12.67,14 12,14M12,4A4,4 0 0,0 8,8A4,4 0 0,0 12,12A4,4 0 0,0 16,8A4,4 0 0,0 12,4Z\\"><!--v-if--></path></svg></span>Published by <b data-v-6ca7cc69=\\"\\" class=\\"\\">An author</b></p>
|
||||
<!--v-if-->
|
||||
<p class=\\"flex gap-1\\" data-v-6ca7cc69=\\"\\"><span aria-hidden=\\"true\\" class=\\"material-design-icon account-edit-icon\\" role=\\"img\\" data-v-6ca7cc69=\\"\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M21.7,13.35L20.7,14.35L18.65,12.3L19.65,11.3C19.86,11.09 20.21,11.09 20.42,11.3L21.7,12.58C21.91,12.79 21.91,13.14 21.7,13.35M12,18.94L18.06,12.88L20.11,14.93L14.06,21H12V18.94M12,14C7.58,14 4,15.79 4,18V20H10V18.11L14,14.11C13.34,14.03 12.67,14 12,14M12,4A4,4 0 0,0 8,8A4,4 0 0,0 12,12A4,4 0 0,0 16,8A4,4 0 0,0 12,4Z\\"><!--v-if--></path></svg></span>Published by <b class=\\"\\" data-v-6ca7cc69=\\"\\">An author</b></p>
|
||||
</div>
|
||||
</a>"
|
||||
`;
|
||||
|
||||
exports[`PostListItem > renders post list item with tags 1`] = `
|
||||
"<a href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\" data-v-6ca7cc69=\\"\\">
|
||||
"<a data-v-6ca7cc69=\\"\\" href=\\"/p/my-blog-post-some-uuid\\" class=\\"block md:flex bg-white dark:bg-violet-2 dark:text-white dark:hover:text-white rounded-lg shadow-md\\" dir=\\"auto\\">
|
||||
<!--v-if-->
|
||||
<div class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\" data-v-6ca7cc69=\\"\\">
|
||||
<h3 class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\" data-v-6ca7cc69=\\"\\">My Blog Post</h3>
|
||||
<p class=\\"flex gap-2\\" data-v-6ca7cc69=\\"\\"><span aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\" data-v-6ca7cc69=\\"\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span dir=\\"auto\\" class=\\"\\" data-v-6ca7cc69=\\"\\">Dec 2, 2020</span></p>
|
||||
<div class=\\"flex flex-wrap gap-y-0 gap-x-2\\" data-v-6ca7cc69=\\"\\"><span aria-hidden=\\"true\\" class=\\"material-design-icon tag-icon\\" role=\\"img\\" data-v-6ca7cc69=\\"\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z\\"><!--v-if--></path></svg></span><span class=\\"rounded-md truncate text-sm text-violet-title px-2 py-1 bg-purple-3 dark:text-violet-3\\" data-v-6955ca87=\\"\\" data-v-6ca7cc69=\\"\\">A tag</span></div>
|
||||
<div data-v-6ca7cc69=\\"\\" class=\\"flex flex-col gap-1 bg-inherit p-2 rounded-lg flex-1\\">
|
||||
<h3 data-v-6ca7cc69=\\"\\" class=\\"text-xl color-violet-3 line-clamp-3 mb-2 font-bold\\" lang=\\"en\\">My Blog Post</h3>
|
||||
<p data-v-6ca7cc69=\\"\\" class=\\"flex gap-2\\"><span data-v-6ca7cc69=\\"\\" aria-hidden=\\"true\\" class=\\"material-design-icon clock-icon\\" role=\\"img\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M16.2,16.2L11,13V7H12.5V12.2L17,14.9L16.2,16.2Z\\"><!--v-if--></path></svg></span><span data-v-6ca7cc69=\\"\\" dir=\\"auto\\" class=\\"\\">Dec 2, 2020</span></p>
|
||||
<div data-v-6ca7cc69=\\"\\" class=\\"flex flex-wrap gap-y-0 gap-x-2\\"><span data-v-6ca7cc69=\\"\\" aria-hidden=\\"true\\" class=\\"material-design-icon tag-icon\\" role=\\"img\\"><svg fill=\\"currentColor\\" class=\\"material-design-icon__svg\\" width=\\"24\\" height=\\"24\\" viewBox=\\"0 0 24 24\\"><path d=\\"M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z\\"><!--v-if--></path></svg></span><span data-v-6955ca87=\\"\\" data-v-6ca7cc69=\\"\\" class=\\"rounded-md truncate text-sm text-violet-title px-2 py-1 bg-purple-3 dark:text-violet-3\\">A tag</span></div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</div>
|
||||
</a>"
|
||||
|
|
|
@ -36,11 +36,7 @@ describe("ReportCard", () => {
|
|||
reportData.reported.name
|
||||
);
|
||||
|
||||
expect(wrapper.find(".flex.gap-1 div p:nth-child(2)").text()).toBe(
|
||||
`@${reportData.reported.preferredUsername}`
|
||||
);
|
||||
|
||||
expect(wrapper.find(".reported_by div:first-child").text()).toBe(
|
||||
expect(wrapper.find(".reported_by span:first-child").text()).toBe(
|
||||
`Reported by John Snow`
|
||||
);
|
||||
});
|
||||
|
@ -50,7 +46,7 @@ describe("ReportCard", () => {
|
|||
reporter: { domain: "somewhere.else", type: ActorType.APPLICATION },
|
||||
});
|
||||
|
||||
expect(wrapper.find(".reported_by div:first-child").text()).toBe(
|
||||
expect(wrapper.find(".reported_by span:first-child").text()).toBe(
|
||||
"Reported by someone on somewhere.else"
|
||||
);
|
||||
});
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`ReportModal > renders report modal with basic informations and submits it 1`] = `
|
||||
"<div class=\\"p-2\\" data-v-e0cceef3=\\"\\">
|
||||
"<div data-v-e0cceef3=\\"\\" class=\\"p-2\\">
|
||||
<!--v-if-->
|
||||
<section data-v-e0cceef3=\\"\\">
|
||||
<div class=\\"flex gap-1 flex-row mb-3\\" data-v-e0cceef3=\\"\\"><span class=\\"o-icon o-icon--warning hidden md:block flex-1\\" data-v-e0cceef3=\\"\\"><i class=\\"mdi mdi-alert 48\\"></i></span>
|
||||
<div data-v-e0cceef3=\\"\\" class=\\"flex gap-1 flex-row mb-3 bg-mbz-yellow p-3 rounded items-center\\"><span data-v-e0cceef3=\\"\\" class=\\"o-icon o-icon--warning hidden md:block flex-1\\"><i class=\\"mdi mdi-alert 48\\"></i></span>
|
||||
<p data-v-e0cceef3=\\"\\">The report will be sent to the moderators of your instance. You can explain why you report this content below.</p>
|
||||
</div>
|
||||
<div class=\\"\\" data-v-e0cceef3=\\"\\">
|
||||
<div data-v-e0cceef3=\\"\\">
|
||||
<!--v-if-->
|
||||
<div class=\\"o-field o-field--filled\\" data-v-e0cceef3=\\"\\"><label for=\\"additional-comments\\" class=\\"o-field__label\\">Additional comments</label>
|
||||
<div class=\\"o-ctrl-input\\" data-v-e0cceef3=\\"\\"><textarea id=\\"additional-comments\\" class=\\"o-input o-input__textarea\\"></textarea>
|
||||
<div data-v-e0cceef3=\\"\\" class=\\"o-field o-field--filled\\"><label for=\\"additional-comments\\" class=\\"o-field__label\\">Additional comments</label>
|
||||
<div data-v-e0cceef3=\\"\\" class=\\"o-ctrl-input\\"><textarea id=\\"additional-comments\\" autofocus=\\"\\" class=\\"o-input o-input__textarea\\"></textarea>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
|
@ -20,9 +20,9 @@ exports[`ReportModal > renders report modal with basic informations and submits
|
|||
<!--v-if-->
|
||||
</div>
|
||||
</section>
|
||||
<footer class=\\"flex gap-2 py-3\\" data-v-e0cceef3=\\"\\"><button type=\\"button\\" class=\\"o-btn o-btn--outlined\\" data-v-e0cceef3=\\"\\"><span class=\\"o-btn__wrapper\\"><!--v-if--><span class=\\"o-btn__label\\">Cancel</span>
|
||||
<footer data-v-e0cceef3=\\"\\" class=\\"flex gap-2 py-3\\"><button data-v-e0cceef3=\\"\\" type=\\"button\\" class=\\"o-btn o-btn--outlined\\"><span class=\\"o-btn__wrapper\\"><!--v-if--><span class=\\"o-btn__label\\">Cancel</span>
|
||||
<!--v-if--></span>
|
||||
</button><button type=\\"button\\" class=\\"o-btn o-btn--primary\\" data-v-e0cceef3=\\"\\"><span class=\\"o-btn__wrapper\\"><!--v-if--><span class=\\"o-btn__label\\">Send the report</span>
|
||||
</button><button data-v-e0cceef3=\\"\\" type=\\"button\\" class=\\"o-btn o-btn--primary\\"><span class=\\"o-btn__wrapper\\"><!--v-if--><span class=\\"o-btn__label\\">Send the report</span>
|
||||
<!--v-if--></span>
|
||||
</button></footer>
|
||||
</div>"
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
const useRouterMock = vi.fn(() => ({
|
||||
push: function () {
|
||||
// do nothing
|
||||
},
|
||||
}));
|
||||
|
||||
import { config, mount } from "@vue/test-utils";
|
||||
import PasswordReset from "@/views/User/PasswordReset.vue";
|
||||
import { createMockClient, RequestHandler } from "mock-apollo-client";
|
||||
|
@ -11,15 +5,17 @@ import { RESET_PASSWORD } from "@/graphql/auth";
|
|||
import { resetPasswordResponseMock } from "../../mocks/auth";
|
||||
import RouteName from "@/router/name";
|
||||
import flushPromises from "flush-promises";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { DefaultApolloClient } from "@vue/apollo-composable";
|
||||
import Oruga from "@oruga-ui/oruga-next";
|
||||
import {
|
||||
VueRouterMock,
|
||||
createRouterMock,
|
||||
injectRouterMock,
|
||||
} from "vue-router-mock";
|
||||
|
||||
config.global.plugins.push(Oruga);
|
||||
|
||||
vi.mock("vue-router/dist/vue-router.mjs", () => ({
|
||||
useRouter: useRouterMock,
|
||||
}));
|
||||
config.plugins.VueWrapper.install(VueRouterMock);
|
||||
|
||||
let requestHandlers: Record<string, RequestHandler>;
|
||||
|
||||
|
@ -58,8 +54,21 @@ const generateWrapper = (
|
|||
};
|
||||
|
||||
describe("Reset page", () => {
|
||||
const router = createRouterMock({
|
||||
spy: {
|
||||
create: (fn) => vi.fn(fn),
|
||||
reset: (spy) => spy.mockReset(),
|
||||
},
|
||||
});
|
||||
beforeEach(() => {
|
||||
// inject it globally to ensure `useRoute()`, `$route`, etc work
|
||||
// properly and give you access to test specific functions
|
||||
injectRouterMock(router);
|
||||
});
|
||||
|
||||
it("renders correctly", () => {
|
||||
const wrapper = generateWrapper();
|
||||
expect(wrapper.router).toBe(router);
|
||||
expect(wrapper.findAll('input[type="password"').length).toBe(2);
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
@ -93,10 +102,6 @@ describe("Reset page", () => {
|
|||
});
|
||||
|
||||
it("redirects to homepage if token is valid", async () => {
|
||||
const push = vi.fn(); // needs to write this code before render()
|
||||
useRouterMock.mockImplementationOnce(() => ({
|
||||
push,
|
||||
}));
|
||||
const wrapper = generateWrapper();
|
||||
|
||||
wrapper
|
||||
|
@ -110,6 +115,6 @@ describe("Reset page", () => {
|
|||
token: "some-token",
|
||||
});
|
||||
await flushPromises();
|
||||
expect(push).toHaveBeenCalledWith({ name: RouteName.HOME });
|
||||
expect(wrapper.router.push).toHaveBeenCalledWith({ name: RouteName.HOME });
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Reset page > renders correctly 1`] = `
|
||||
"<section class=\\"container mx-auto\\">
|
||||
|
@ -25,7 +25,7 @@ exports[`Reset page > renders correctly 1`] = `
|
|||
exports[`Reset page > shows error if token is invalid 1`] = `
|
||||
"<section class=\\"container mx-auto\\">
|
||||
<h1 class=\\"\\">Password reset</h1>
|
||||
<transition-stub title=\\"Error\\">
|
||||
<transition-stub name=\\"fade\\" appear=\\"false\\" persisted=\\"true\\" css=\\"true\\" title=\\"Error\\">
|
||||
<article class=\\"o-notification o-notification--danger\\">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
const useRouterMock = vi.fn(() => ({
|
||||
push: function () {
|
||||
// do nothing
|
||||
},
|
||||
replace: function () {
|
||||
// do nothing
|
||||
},
|
||||
}));
|
||||
const useRouteMock = vi.fn(function () {
|
||||
// do nothing
|
||||
});
|
||||
|
||||
import { config, mount, VueWrapper } from "@vue/test-utils";
|
||||
import Login from "@/views/User/LoginView.vue";
|
||||
import {
|
||||
|
@ -26,23 +14,37 @@ import { CURRENT_USER_CLIENT } from "@/graphql/user";
|
|||
import { ICurrentUser } from "@/types/current-user.model";
|
||||
import flushPromises from "flush-promises";
|
||||
import RouteName from "@/router/name";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { DefaultApolloClient } from "@vue/apollo-composable";
|
||||
import Oruga from "@oruga-ui/oruga-next";
|
||||
import { cache } from "@/apollo/memory";
|
||||
|
||||
vi.mock("vue-router/dist/vue-router.mjs", () => ({
|
||||
useRouter: useRouterMock,
|
||||
useRoute: useRouteMock,
|
||||
}));
|
||||
import {
|
||||
VueRouterMock,
|
||||
createRouterMock,
|
||||
injectRouterMock,
|
||||
getRouter,
|
||||
} from "vue-router-mock";
|
||||
|
||||
config.global.plugins.push(Oruga);
|
||||
config.plugins.VueWrapper.install(VueRouterMock);
|
||||
|
||||
describe("Render login form", () => {
|
||||
let wrapper: VueWrapper;
|
||||
let mockClient: MockApolloClient | null;
|
||||
let requestHandlers: Record<string, RequestHandler>;
|
||||
|
||||
const router = createRouterMock({
|
||||
spy: {
|
||||
create: (fn) => vi.fn(fn),
|
||||
reset: (spy) => spy.mockReset(),
|
||||
},
|
||||
});
|
||||
beforeEach(() => {
|
||||
// inject it globally to ensure `useRoute()`, `$route`, etc work
|
||||
// properly and give you access to test specific functions
|
||||
injectRouterMock(router);
|
||||
});
|
||||
|
||||
const generateWrapper = (
|
||||
handlers: Record<string, unknown> = {},
|
||||
customProps: Record<string, unknown> = {},
|
||||
|
@ -90,6 +92,7 @@ describe("Render login form", () => {
|
|||
generateWrapper();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await flushPromises();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
|
@ -103,15 +106,10 @@ describe("Render login form", () => {
|
|||
});
|
||||
|
||||
it("renders and submits the login form", async () => {
|
||||
const replace = vi.fn(); // needs to write this code before render()
|
||||
const push = vi.fn();
|
||||
useRouterMock.mockImplementationOnce(() => ({
|
||||
replace,
|
||||
push,
|
||||
}));
|
||||
generateWrapper();
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await flushPromises();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
|
@ -133,16 +131,12 @@ describe("Render login form", () => {
|
|||
expect(currentUser?.email).toBe("some@email.tld");
|
||||
expect(currentUser?.id).toBe("1");
|
||||
await flushPromises();
|
||||
expect(replace).toHaveBeenCalledWith({ name: RouteName.HOME });
|
||||
expect(wrapper.router.replace).toHaveBeenCalledWith({
|
||||
name: RouteName.HOME,
|
||||
});
|
||||
});
|
||||
|
||||
it("handles a login error", async () => {
|
||||
const replace = vi.fn(); // needs to write this code before render()
|
||||
const push = vi.fn();
|
||||
useRouterMock.mockImplementationOnce(() => ({
|
||||
push,
|
||||
replace,
|
||||
}));
|
||||
generateWrapper({
|
||||
loginMutationHandler: vi.fn().mockResolvedValue({
|
||||
errors: [
|
||||
|
@ -156,6 +150,7 @@ describe("Render login form", () => {
|
|||
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await flushPromises();
|
||||
|
||||
expect(wrapper.exists()).toBe(true);
|
||||
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
|
||||
|
@ -170,28 +165,21 @@ describe("Render login form", () => {
|
|||
expect(wrapper.find(".o-notification--danger").text()).toContain(
|
||||
"Impossible to authenticate, either your email or password are invalid."
|
||||
);
|
||||
expect(push).not.toHaveBeenCalled();
|
||||
expect(wrapper.router.push).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles redirection after login", async () => {
|
||||
const replace = vi.fn(); // needs to write this code before render()
|
||||
const push = vi.fn();
|
||||
useRouterMock.mockImplementationOnce(() => ({
|
||||
replace,
|
||||
push,
|
||||
}));
|
||||
useRouteMock.mockImplementationOnce(() => ({
|
||||
query: { redirect: "/about/instance" },
|
||||
}));
|
||||
generateWrapper();
|
||||
getRouter().setQuery({ redirect: "/about/instance" });
|
||||
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.vm.$nextTick();
|
||||
await flushPromises();
|
||||
|
||||
wrapper.find('form input[type="email"]').setValue("some@email.tld");
|
||||
wrapper.find('form input[type="password"]').setValue("somepassword");
|
||||
wrapper.find("form").trigger("submit");
|
||||
await flushPromises();
|
||||
expect(push).toHaveBeenCalledWith("/about/instance");
|
||||
expect(wrapper.router.push).toHaveBeenCalledWith("/about/instance");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// Vitest Snapshot v1
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`App component > renders a Vue component 1`] = `
|
||||
"<nav class=\\"bg-white border-gray-200 px-2 sm:px-4 py-2.5 dark:bg-zinc-900\\" id=\\"navbar\\">
|
||||
<div class=\\"container mx-auto flex flex-wrap items-center mx-auto gap-4\\">
|
||||
<router-link to=\\"[object Object]\\" class=\\"flex items-center\\">
|
||||
<div class=\\"container mx-auto flex flex-wrap items-center mx-auto gap-2 sm:gap-4\\">
|
||||
<router-link to=\\"[object Object]\\" class=\\"flex items-center flex-1\\">
|
||||
<mobilizon-logo-stub invert=\\"false\\" class=\\"w-40\\"></mobilizon-logo-stub>
|
||||
</router-link>
|
||||
<!--v-if--><button type=\\"button\\" class=\\"inline-flex items-center p-2 ml-1 text-sm text-zinc-500 rounded-lg md:hidden hover:bg-zinc-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-zinc-400 dark:hover:bg-zinc-700 dark:focus:ring-gray-600\\" aria-controls=\\"mobile-menu-2\\" aria-expanded=\\"false\\"><span class=\\"sr-only\\">Open main menu</span><svg class=\\"w-6 h-6\\" aria-hidden=\\"true\\" fill=\\"currentColor\\" viewBox=\\"0 0 20 20\\" xmlns=\\"http://www.w3.org/2000/svg\\">
|
||||
|
@ -16,181 +16,9 @@ exports[`App component > renders a Vue component 1`] = `
|
|||
<li>
|
||||
<router-link to=\\"[object Object]\\" class=\\"block py-2 pr-4 pl-3 text-zinc-700 border-b border-gray-100 hover:bg-zinc-50 md:hover:bg-transparent md:border-0 md:hover:text-mbz-purple-700 md:p-0 dark:text-zinc-400 md:dark:hover:text-white dark:hover:bg-zinc-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700\\">Login</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to=\\"[object Object]\\" class=\\"block py-2 pr-4 pl-3 text-zinc-700 border-b border-gray-100 hover:bg-zinc-50 md:hover:bg-transparent md:border-0 md:hover:text-mbz-purple-700 md:p-0 dark:text-zinc-400 md:dark:hover:text-white dark:hover:bg-zinc-700 dark:hover:text-white md:dark:hover:bg-transparent dark:border-gray-700\\">Register</router-link>
|
||||
</li>
|
||||
<!--v-if-->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- <o-navbar
|
||||
id=\\"navbar\\"
|
||||
type=\\"is-secondary\\"
|
||||
wrapper-class=\\"container mx-auto\\"
|
||||
v-model:active=\\"mobileNavbarActive\\"
|
||||
>
|
||||
<template #brand>
|
||||
<o-navbar-item
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.HOME }\\"
|
||||
:aria-label=\\"$t('Home')\\"
|
||||
>
|
||||
<logo />
|
||||
</o-navbar-item>
|
||||
</template>
|
||||
<template #start>
|
||||
<o-navbar-item tag=\\"router-link\\" :to=\\"{ name: RouteName.SEARCH }\\">{{
|
||||
$t(\\"Explore\\")
|
||||
}}</o-navbar-item>
|
||||
<o-navbar-item
|
||||
v-if=\\"currentActor.id && currentUser?.isLoggedIn\\"
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.MY_EVENTS }\\"
|
||||
>{{ $t(\\"My events\\") }}</o-navbar-item
|
||||
>
|
||||
<o-navbar-item
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.MY_GROUPS }\\"
|
||||
v-if=\\"
|
||||
config &&
|
||||
config.features.groups &&
|
||||
currentActor.id &&
|
||||
currentUser?.isLoggedIn
|
||||
\\"
|
||||
>{{ $t(\\"My groups\\") }}</o-navbar-item
|
||||
>
|
||||
<o-navbar-item
|
||||
tag=\\"span\\"
|
||||
v-if=\\"
|
||||
config &&
|
||||
config.features.eventCreation &&
|
||||
currentActor.id &&
|
||||
currentUser?.isLoggedIn
|
||||
\\"
|
||||
>
|
||||
<o-button
|
||||
v-if=\\"!hideCreateEventsButton\\"
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.CREATE_EVENT }\\"
|
||||
variant=\\"primary\\"
|
||||
>{{ $t(\\"Create\\") }}</o-button
|
||||
>
|
||||
</o-navbar-item>
|
||||
</template>
|
||||
<template #end>
|
||||
<o-navbar-item tag=\\"div\\">
|
||||
<search-field @navbar-search=\\"mobileNavbarActive = false\\" />
|
||||
</o-navbar-item>
|
||||
|
||||
<o-navbar-dropdown
|
||||
v-if=\\"currentActor.id && currentUser?.isLoggedIn\\"
|
||||
right
|
||||
collapsible
|
||||
ref=\\"user-dropdown\\"
|
||||
tabindex=\\"0\\"
|
||||
tag=\\"span\\"
|
||||
@keyup.enter=\\"toggleMenu\\"
|
||||
>
|
||||
<template #label v-if=\\"currentActor\\">
|
||||
<div class=\\"identity-wrapper\\">
|
||||
<div>
|
||||
<figure class=\\"image is-32x32\\" v-if=\\"currentActor.avatar\\">
|
||||
<img
|
||||
class=\\"is-rounded\\"
|
||||
alt=\\"avatarUrl\\"
|
||||
:src=\\"currentActor.avatar.url\\"
|
||||
/>
|
||||
</figure>
|
||||
<o-icon v-else icon=\\"account-circle\\" />
|
||||
</div>
|
||||
<div class=\\"media-content is-hidden-desktop\\">
|
||||
<span>{{ displayName(currentActor) }}</span>
|
||||
<span class=\\"has-text-grey-dark\\" v-if=\\"currentActor.name\\"
|
||||
>@{{ currentActor.preferredUsername }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
No identities dropdown if no identities
|
||||
<span v-if=\\"identities.length <= 1\\"></span>
|
||||
<o-navbar-item
|
||||
tag=\\"span\\"
|
||||
v-for=\\"identity in identities\\"
|
||||
v-else
|
||||
:active=\\"identity.id === currentActor.id\\"
|
||||
:key=\\"identity.id\\"
|
||||
tabindex=\\"0\\"
|
||||
@click=\\"setIdentity({
|
||||
preferredUsername: identity.preferredUsername,
|
||||
})\\"
|
||||
@keyup.enter=\\"setIdentity({
|
||||
preferredUsername: identity.preferredUsername,
|
||||
})\\"
|
||||
>
|
||||
<span>
|
||||
<div class=\\"media-left\\">
|
||||
<figure class=\\"image is-32x32\\" v-if=\\"identity.avatar\\">
|
||||
<img
|
||||
class=\\"is-rounded\\"
|
||||
loading=\\"lazy\\"
|
||||
:src=\\"identity.avatar.url\\"
|
||||
alt
|
||||
/>
|
||||
</figure>
|
||||
<o-icon v-else size=\\"is-medium\\" icon=\\"account-circle\\" />
|
||||
</div>
|
||||
|
||||
<div class=\\"media-content\\">
|
||||
<span>{{ displayName(identity) }}</span>
|
||||
<span class=\\"has-text-grey-dark\\" v-if=\\"identity.name\\"
|
||||
>@{{ identity.preferredUsername }}</span
|
||||
>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
<hr class=\\"navbar-divider\\" role=\\"presentation\\" />
|
||||
</o-navbar-item>
|
||||
|
||||
<o-navbar-item
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.UPDATE_IDENTITY }\\"
|
||||
>{{ $t(\\"My account\\") }}</o-navbar-item
|
||||
>
|
||||
<o-navbar-item
|
||||
v-if=\\"currentUser.role === ICurrentUserRole.ADMINISTRATOR\\"
|
||||
tag=\\"router-link\\"
|
||||
:to=\\"{ name: RouteName.ADMIN_DASHBOARD }\\"
|
||||
>{{ $t(\\"Administration\\") }}</o-navbar-item
|
||||
>
|
||||
|
||||
<o-navbar-item
|
||||
tag=\\"span\\"
|
||||
tabindex=\\"0\\"
|
||||
@click=\\"logout\\"
|
||||
@keyup.enter=\\"logout\\"
|
||||
>
|
||||
<span>{{ $t(\\"Log out\\") }}</span>
|
||||
</o-navbar-item>
|
||||
</o-navbar-dropdown>
|
||||
|
||||
<o-navbar-item v-else tag=\\"div\\">
|
||||
<div class=\\"buttons\\">
|
||||
<router-link
|
||||
class=\\"button is-primary\\"
|
||||
v-if=\\"config && config.registrationsOpen\\"
|
||||
:to=\\"{ name: RouteName.REGISTER }\\"
|
||||
>
|
||||
<strong>{{ $t(\\"Sign up\\") }}</strong>
|
||||
</router-link>
|
||||
|
||||
<router-link
|
||||
class=\\"button is-light\\"
|
||||
:to=\\"{ name: RouteName.LOGIN }\\"
|
||||
>{{ $t(\\"Log in\\") }}</router-link
|
||||
>
|
||||
</div>
|
||||
</o-navbar-item>
|
||||
</template>
|
||||
</o-navbar> -->"
|
||||
</nav>"
|
||||
`;
|
||||
|
|
|
@ -134,6 +134,7 @@ export const loginMock = {
|
|||
__typename: "Config",
|
||||
auth: {
|
||||
__typename: "Auth",
|
||||
databaseLogin: true,
|
||||
oauthProviders: [],
|
||||
},
|
||||
registrationsOpen: true,
|
||||
|
|
|
@ -106,6 +106,7 @@ export const eventCommentThreadsMock = {
|
|||
},
|
||||
deletedAt: null,
|
||||
insertedAt: "2020-12-03T09:02:00Z",
|
||||
publishedAt: "2020-12-03T09:02:00Z",
|
||||
isAnnouncement: false,
|
||||
language: "en",
|
||||
},
|
||||
|
@ -137,6 +138,7 @@ export const eventCommentThreadsMock = {
|
|||
},
|
||||
deletedAt: null,
|
||||
insertedAt: "2020-12-03T11:02:00Z",
|
||||
publishedAt: "2020-12-03T11:02:00Z",
|
||||
isAnnouncement: false,
|
||||
language: "en",
|
||||
},
|
||||
|
@ -164,7 +166,6 @@ export const newCommentForEventResponse: DataMock = {
|
|||
local: true,
|
||||
visibility: "PUBLIC",
|
||||
totalReplies: 0,
|
||||
updatedAt: "2020-12-03T13:02:00Z",
|
||||
originComment: null,
|
||||
inReplyToComment: null,
|
||||
replies: [],
|
||||
|
@ -183,6 +184,8 @@ export const newCommentForEventResponse: DataMock = {
|
|||
},
|
||||
deletedAt: null,
|
||||
insertedAt: "2020-12-03T13:02:00Z",
|
||||
updatedAt: "2020-12-03T13:02:00Z",
|
||||
publishedAt: "2020-12-03T13:02:00Z",
|
||||
isAnnouncement: false,
|
||||
language: "en",
|
||||
},
|
||||
|
|
|
@ -114,7 +114,7 @@ export default defineConfig(({ command }) => {
|
|||
coverage: {
|
||||
reporter: ["text", "json", "html"],
|
||||
},
|
||||
setupFiles: path.resolve(__dirname, "./tests/unit/setup.ts"),
|
||||
setupFiles: [path.resolve(__dirname, "./tests/unit/setup.ts")],
|
||||
include: [path.resolve(__dirname, "./tests/unit/specs/**/*.spec.ts")],
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue