update frontend lib : remove histoire (obselete) + update vitest - #1815

This commit is contained in:
Laurent GAY
2025-10-24 13:00:15 +02:00
committed by setop
parent ffa3e0ebd7
commit d971fd77af
192 changed files with 4767 additions and 5300 deletions

View File

@@ -2,13 +2,12 @@ import { beforeEach, describe, it, expect } from "vitest";
import { enUS } from "date-fns/locale";
import { routes } from "@/router";
import { createRouter, createWebHistory, Router } from "vue-router";
import { getMockClient, requestHandlers } from "../../mocks/client";
import SendPasswordReset from "@/views/User/SendPasswordReset.vue";
import { config, mount } from "@vue/test-utils";
import { Oruga } from "@oruga-ui/oruga-next";
import flushPromises from "flush-promises";
import { SEND_RESET_PASSWORD } from "@/graphql/auth";
import { getMockClient } from "../../mocks/client";
import { htmlRemoveId } from "../../common";
import AuthProviders from "@/components/User/AuthProviders.vue";
config.global.plugins.push(Oruga);
@@ -23,13 +22,15 @@ beforeEach(async () => {
// await router.isReady();
});
const providers = [{ id: "keycloak", label: "Entreprise" }, { id: "google" }];
const generateWrapper = () => {
const global_data = getMockClient([SEND_RESET_PASSWORD]);
const global_data = getMockClient([]);
global_data.provide.dateFnsLocale = enUS;
global_data.plugins = [router];
return mount(SendPasswordReset, {
return mount(AuthProviders, {
props: {
email: "some@email.tld",
oauthProviders: providers,
},
global: {
...global_data,
@@ -40,20 +41,11 @@ const generateWrapper = () => {
});
};
describe("SendPasswordReset", () => {
describe("AuthProviders", () => {
it("Show simple", async () => {
const wrapper = generateWrapper();
await wrapper.vm.$nextTick();
await flushPromises();
expect(htmlRemoveId(wrapper.html())).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(0);
wrapper.find("form").trigger("submit");
await flushPromises();
expect(htmlRemoveId(wrapper.html())).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledWith({
email: "some@email.tld",
});
});
});

View File

@@ -1,122 +0,0 @@
import { config, mount } from "@vue/test-utils";
import PasswordReset from "@/views/User/PasswordReset.vue";
import { createMockClient, RequestHandler } from "mock-apollo-client";
import { RESET_PASSWORD } from "@/graphql/auth";
import { resetPasswordResponseMock } from "../../mocks/auth";
import RouteName from "@/router/name";
import flushPromises from "flush-promises";
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);
config.plugins.VueWrapper.install(VueRouterMock);
let requestHandlers: Record<string, RequestHandler>;
const generateWrapper = (
customRequestHandlers: Record<string, RequestHandler> = {},
customMocks = {}
) => {
const mockClient = createMockClient();
requestHandlers = {
resetPasswordMutationHandler: vi
.fn()
.mockResolvedValue(resetPasswordResponseMock),
...customRequestHandlers,
};
mockClient.setRequestHandler(
RESET_PASSWORD,
requestHandlers.resetPasswordMutationHandler
);
return mount(PasswordReset, {
props: {
token: "some-token",
},
global: {
stubs: ["router-link", "router-view"],
mocks: {
...customMocks,
},
provide: {
[DefaultApolloClient]: mockClient,
},
},
});
};
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);
const labels = wrapper.findAll("label");
expect(labels.length).toBe(2);
expect(labels.at(0).text()).toBe("Password");
expect(labels.at(1).text()).toBe("Password (confirmation)");
});
it("shows error if token is invalid", async () => {
const wrapper = generateWrapper({
resetPasswordMutationHandler: vi.fn().mockResolvedValue({
errors: [{ message: "The token you provided is invalid." }],
}),
});
wrapper
.findAll('input[type="password"')
.forEach((inputField) => inputField.setValue("my password"));
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.resetPasswordMutationHandler).toBeCalledTimes(1);
expect(requestHandlers.resetPasswordMutationHandler).toBeCalledWith({
password: "my password",
token: "some-token",
});
await flushPromises();
expect(wrapper.find(".o-notification--danger").text()).toContain(
"The token you provided is invalid"
);
});
it("redirects to homepage if token is valid", async () => {
const wrapper = generateWrapper();
wrapper
.findAll('input[type="password"')
.forEach((inputField) => inputField.setValue("my password"));
await wrapper.find("form").trigger("submit");
expect(requestHandlers.resetPasswordMutationHandler).toBeCalledTimes(1);
expect(requestHandlers.resetPasswordMutationHandler).toBeCalledWith({
password: "my password",
token: "some-token",
});
await flushPromises();
expect(wrapper.router.push).toHaveBeenCalledWith({ name: RouteName.LOGIN });
});
});

View File

@@ -1,185 +0,0 @@
import { config, mount } from "@vue/test-utils";
import RegisterView from "@/views/User/RegisterView.vue";
import { createMockClient, RequestHandler } from "mock-apollo-client";
import flushPromises from "flush-promises";
import { configMock } from "../../mocks/config";
import { CONFIG } from "@/graphql/config";
import { CREATE_USER } from "@/graphql/user";
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";
import { nullMock } from "../../common";
config.global.plugins.push(Oruga);
config.plugins.VueWrapper.install(VueRouterMock);
let requestHandlers: Record<string, RequestHandler>;
const generateWrapper = (
customRegModeration: boolean = false,
customRequestHandlers: Record<string, RequestHandler> = {}
) => {
const mockClient = createMockClient();
const config_value = {
...configMock,
};
if (customRegModeration) {
config_value.data.config.registrationsModeration = true;
}
requestHandlers = {
configQueryHandler: vi.fn().mockResolvedValue(config_value),
createUserHandler: vi.fn().mockResolvedValue(nullMock),
...customRequestHandlers,
};
mockClient.setRequestHandler(CONFIG, requestHandlers.configQueryHandler);
mockClient.setRequestHandler(CREATE_USER, requestHandlers.createUserHandler);
return mount(RegisterView, {
global: {
stubs: ["router-link", "router-view"],
provide: {
[DefaultApolloClient]: mockClient,
},
},
});
};
describe("Register 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("register without moderation", async () => {
const wrapper = generateWrapper();
expect(wrapper.router).toBe(router);
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(wrapper.find("form").exists()).toBe(true);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.createUserHandler).toHaveBeenCalledWith({
email: "some@email.tld",
locale: "en_US",
moderation: "",
password: "somepassword",
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(false);
});
it("shows error without moderation email", async () => {
const wrapper = generateWrapper(false, {
createUserHandler: vi.fn().mockResolvedValue({
errors: [{ field: "email", message: ["Bad email."] }],
}),
});
expect(wrapper.find("form").exists()).toBe(true);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.createUserHandler).toBeCalledTimes(1);
expect(requestHandlers.createUserHandler).toHaveBeenCalledWith({
email: "some@email.tld",
locale: "en_US",
moderation: "",
password: "somepassword",
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(true);
expect(wrapper.find(".o-field__message-danger").text()).toContain(
"Bad email."
);
});
it("shows error without moderation password", async () => {
const wrapper = generateWrapper(false, {
createUserHandler: vi.fn().mockResolvedValue({
errors: [{ field: "password", message: ["Bad password."] }],
}),
});
expect(wrapper.find("form").exists()).toBe(true);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.createUserHandler).toBeCalledTimes(1);
expect(requestHandlers.createUserHandler).toHaveBeenCalledWith({
email: "some@email.tld",
locale: "en_US",
moderation: "",
password: "somepassword",
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(true);
expect(wrapper.find(".o-field__message-danger").text()).toContain(
"Bad password."
);
});
it("register with moderation", async () => {
const wrapper = generateWrapper(true);
expect(wrapper.router).toBe(router);
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(wrapper.find("form").exists()).toBe(true);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form .o-input__textarea").setValue("text for moderation");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.createUserHandler).toHaveBeenCalledWith({
email: "some@email.tld",
locale: "en_US",
moderation: "text for moderation",
password: "somepassword",
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(false);
});
it("shows error with moderation", async () => {
const wrapper = generateWrapper(true, {
createUserHandler: vi.fn().mockResolvedValue({
errors: [{ field: null, message: ["Bad moderation."] }],
}),
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(true);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form .o-input__textarea").setValue("text for moderation");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.createUserHandler).toBeCalledTimes(1);
expect(requestHandlers.createUserHandler).toHaveBeenCalledWith({
email: "some@email.tld",
locale: "en_US",
moderation: "text for moderation",
password: "somepassword",
});
await flushPromises();
expect(wrapper.find("form").exists()).toBe(true);
expect(wrapper.find(".o-field__message-danger").text()).toContain(
"Bad moderation."
);
});
});

View File

@@ -1,118 +0,0 @@
import { config, mount } from "@vue/test-utils";
import ValidateUser from "@/views/User/ValidateUser.vue";
import { createMockClient, RequestHandler } from "mock-apollo-client";
import flushPromises from "flush-promises";
import { VALIDATE_USER, UPDATE_CURRENT_USER_CLIENT } from "@/graphql/user";
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";
import { nullMock } from "../../common";
import * as auth_mod from "@/utils/auth.ts";
config.global.plugins.push(Oruga);
config.plugins.VueWrapper.install(VueRouterMock);
vi.spyOn(auth_mod, "saveTokenData");
vi.spyOn(auth_mod, "saveUserData");
let requestHandlers: Record<string, RequestHandler>;
const validateUserMock = {
data: {
validateUser: {
accessToken: "aaaaaaa",
refreshToken: "zzzzzzz",
user: {
id: "123",
email: "truc@machin.com",
role: "USER",
},
},
},
};
const generateWrapper = (moderate: boolean = false) => {
const mockClient = createMockClient();
const validate_user = {
...validateUserMock,
};
if (moderate) {
validate_user.data.validateUser.user.role = "PENDING";
}
requestHandlers = {
validateUserHandler: vi.fn().mockResolvedValue(validateUserMock),
updateUserHandler: vi.fn().mockResolvedValue(nullMock),
};
mockClient.setRequestHandler(
VALIDATE_USER,
requestHandlers.validateUserHandler
);
mockClient.setRequestHandler(
UPDATE_CURRENT_USER_CLIENT,
requestHandlers.updateUserHandler
);
const wrapper = mount(ValidateUser, {
props: {
token: "123456789",
},
global: {
stubs: ["router-link", "router-view"],
provide: {
[DefaultApolloClient]: mockClient,
},
},
});
wrapper.router.push.mockReset();
return wrapper;
};
describe("Validate user 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("simple", async () => {
const wrapper = generateWrapper();
expect(wrapper.router).toBe(router);
await flushPromises();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.validateUserHandler).toBeCalledTimes(1);
expect(requestHandlers.validateUserHandler).toHaveBeenCalledWith({
token: "123456789",
});
// expect(wrapper.router.replace).toHaveBeenCalledWith({
// name: RouteName.CREATE_IDENTITY,
// });
// expect(requestHandlers.updateUserHandler).toBeCalledTimes(1);
});
it("moderate", async () => {
const wrapper = generateWrapper(true);
expect(wrapper.router).toBe(router);
await flushPromises();
await wrapper.vm.$nextTick();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.validateUserHandler).toBeCalledTimes(1);
expect(requestHandlers.validateUserHandler).toHaveBeenCalledWith({
token: "123456789",
});
expect(requestHandlers.updateUserHandler).toBeCalledTimes(0);
});
});

View File

@@ -0,0 +1,11 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`AuthProviders > Show simple 1`] = `
"<div><b>Sign in with</b>
<div class="flex gap-1 flex-wrap"><a class="o-btn o-btn--primary o-btn--outlined-primary" role="button" data-oruga="button" href="/auth/keycloak"><span class="o-btn__wrapper"><span class="o-icon o-btn__icon o-btn__icon-left" data-oruga="icon"><i class="mdi mdi-lock mdi-24px"></i></span><span class="o-btn__label"><span>Entreprise</span></span>
<!----></span>
</a><a class="o-btn o-btn--primary o-btn--outlined-primary" role="button" data-oruga="button" href="/auth/google"><span class="o-btn__wrapper"><span class="o-icon o-btn__icon o-btn__icon-left" data-oruga="icon"><i class="mdi mdi-google mdi-24px"></i></span><span class="o-btn__label"><span>Google</span></span>
<!----></span>
</a></div>
</div>"
`;

View File

@@ -1,166 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Register page > register with moderation 1`] = `
"<div class="container mx-auto py-6">
<section class="">
<h1>Register an account on Mobilizon!</h1>
<p><b>Mobilizon</b> is an instance of the <a href="https://mobilizon.org" target="_blank" class="out">Mobilizon</a> software.</p>
</section>
<section class="flex flex-wrap gap-6">
<div class="">
<div class="my-4">
<h2 class="text-xl">Why create an account?</h2>
<div class="prose dark:prose-invert">
<ul>
<li>To create and manage your events</li>
<li>To create and manage multiples identities from a same account</li>
<li>To register for an event by choosing one of your identities</li>
<li>To create or join an group and start organizing with other people</li>
<li>To follow groups and be informed of their latest events</li>
</ul>
</div>
</div>
<router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out block my-4"></router-link-stub>
<hr role="presentation">
<div class="my-4">
<h2 class="text-xl">About Mobilizon</h2>
<div class="prose dark:prose-invert">Mobilizon.fr est l'instance Mobilizon de Framasoft.</div>
<p>Please read the <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub> published by <b>Mobilizon</b>'s administrators.</p>
</div>
</div>
<div>
<!--v-if-->
<div data-oruga="field" class="o-field">
<!---->
<!---->
</div>
<form>
<div data-oruga="field" class="o-field"><label for="email" class="o-field__label">Email</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded"><input aria-required="true" required="" id="email" data-oruga-input="email" type="email" class="o-input" autocomplete="off">
<!---->
<!---->
<!---->
</div>
</div>
</div>
<!---->
</div>
<div data-oruga="field" class="o-field"><label for="password" class="o-field__label">Password</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded o-input__wrapper--has-icon-right"><input aria-required="true" required="" minlength="6" id="password" data-oruga-input="password" type="password" class="o-input o-input--iconspace-right" autocomplete="off">
<!----><span class="o-icon o-icon--clickable o-input__icon-right" data-oruga="icon"><i class="mdi mdi-eye mdi-24px"></i></span>
<!---->
</div>
</div>
</div>
<!---->
</div>
<div data-oruga="field" class="o-field"><label for="moderation" class="o-field__label">Registration is subject to moderation, indicate your motivation.</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded"><textarea aria-required="true" required="" id="moderation" data-oruga-input="textarea" class="o-input o-input__textarea"></textarea>
<!---->
<!---->
<!---->
</div>
</div>
</div>
<!---->
</div>
<div class="flex items-start mb-6 mt-2">
<div class="flex items-center h-5"><input type="checkbox" id="accept_rules_terms" class="w-4 h-4 bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-blue-600 dark:ring-offset-gray-800" required=""></div><label for="accept_rules_terms" class="ml-2 text-gray-900 dark:text-gray-300"><span>I agree to the <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub> and <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub></span></label>
</div>
<p><button type="submit" class="o-btn o-btn--large o-btn--primary" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Create an account</span>
<!----></span>
</button></p>
<p class="my-6">
<router-link-stub class="o-btn o-btn--text" role="button" data-oruga="button" to="[object Object]"></router-link-stub>
<router-link-stub class="o-btn o-btn--text" role="button" data-oruga="button" to="[object Object]"></router-link-stub>
</p>
<hr role="presentation">
<!--v-if-->
</form>
</div>
</section>
</div>"
`;
exports[`Register page > register without moderation 1`] = `
"<div class="container mx-auto py-6">
<section class="">
<h1>Register an account on Mobilizon!</h1>
<p><b>Mobilizon</b> is an instance of the <a href="https://mobilizon.org" target="_blank" class="out">Mobilizon</a> software.</p>
</section>
<section class="flex flex-wrap gap-6">
<div class="">
<div class="my-4">
<h2 class="text-xl">Why create an account?</h2>
<div class="prose dark:prose-invert">
<ul>
<li>To create and manage your events</li>
<li>To create and manage multiples identities from a same account</li>
<li>To register for an event by choosing one of your identities</li>
<li>To create or join an group and start organizing with other people</li>
<li>To follow groups and be informed of their latest events</li>
</ul>
</div>
</div>
<router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out block my-4"></router-link-stub>
<hr role="presentation">
<div class="my-4">
<h2 class="text-xl">About Mobilizon</h2>
<div class="prose dark:prose-invert">Mobilizon.fr est l'instance Mobilizon de Framasoft.</div>
<p>Please read the <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub> published by <b>Mobilizon</b>'s administrators.</p>
</div>
</div>
<div>
<!--v-if-->
<div data-oruga="field" class="o-field">
<!---->
<!---->
</div>
<form>
<div data-oruga="field" class="o-field"><label for="email" class="o-field__label">Email</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded"><input aria-required="true" required="" id="email" data-oruga-input="email" type="email" class="o-input" autocomplete="off">
<!---->
<!---->
<!---->
</div>
</div>
</div>
<!---->
</div>
<div data-oruga="field" class="o-field"><label for="password" class="o-field__label">Password</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded o-input__wrapper--has-icon-right"><input aria-required="true" required="" minlength="6" id="password" data-oruga-input="password" type="password" class="o-input o-input--iconspace-right" autocomplete="off">
<!----><span class="o-icon o-icon--clickable o-input__icon-right" data-oruga="icon"><i class="mdi mdi-eye mdi-24px"></i></span>
<!---->
</div>
</div>
</div>
<!---->
</div>
<!--v-if-->
<div class="flex items-start mb-6 mt-2">
<div class="flex items-center h-5"><input type="checkbox" id="accept_rules_terms" class="w-4 h-4 bg-gray-50 rounded border border-gray-300 focus:ring-3 focus:ring-blue-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-blue-600 dark:ring-offset-gray-800" required=""></div><label for="accept_rules_terms" class="ml-2 text-gray-900 dark:text-gray-300"><span>I agree to the <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub> and <router-link-stub to="[object Object]" replace="false" custom="false" ariacurrentvalue="page" viewtransition="false" class="out"></router-link-stub></span></label>
</div>
<p><button type="submit" class="o-btn o-btn--large o-btn--primary" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Create an account</span>
<!----></span>
</button></p>
<p class="my-6">
<router-link-stub class="o-btn o-btn--text" role="button" data-oruga="button" to="[object Object]"></router-link-stub>
<router-link-stub class="o-btn o-btn--text" role="button" data-oruga="button" to="[object Object]"></router-link-stub>
</p>
<hr role="presentation">
<!--v-if-->
</form>
</div>
</section>
</div>"
`;

View File

@@ -1,16 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`Validate user page > moderate 1`] = `
"<section class="container mx-auto">
<div>
<h1 class="title">Your account has been validated</h1>
<h2 class="title">A moderator will take care of your request.</h2>
</div>
</section>"
`;
exports[`Validate user page > simple 1`] = `
"<section class="container mx-auto">
<h1 class="title">Your account is being validated</h1>
</section>"
`;

View File

@@ -1,9 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`EmailValidate > Show simple 1`] = `
"<section class="container mx-auto">
<div>
<h1 class="title">Your email has been changed</h1>
</div>
</section>"
`;

View File

@@ -1,3 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ProviderValidation > Show simple 1`] = `"<p>Redirecting in progress…</p>"`;

View File

@@ -1,54 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`ResendConfirmation > Show simple 1`] = `
"<section class="container mx-auto pt-4 max-w-2xl">
<h1>Resend confirmation email</h1>
<!--v-if-->
<form>
<div data-oruga="field" class="o-field"><label for="emailAddress" class="o-field__label">Email address</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded"><input aria-required="true" required="" id="emailAddress" data-oruga-input="email" type="email" class="o-input" autocomplete="off">
<!---->
<!---->
<!---->
</div>
</div>
</div>
<!---->
</div>
<p class="flex flex-wrap gap-1 mt-2"><button type="submit" class="o-btn o-btn--primary" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Send the confirmation email again</span>
<!----></span>
</button><a href="/login" class="o-btn o-btn--primary o-btn--outlined-primary" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Cancel</span>
<!----></span>
</a></p>
</form>
</section>"
`;
exports[`ResendConfirmation > Show simple 2`] = `
"<section class="container mx-auto pt-4 max-w-2xl">
<h1>Resend confirmation email</h1>
<!--v-if-->
<div>
<transition-stub name="fade" appear="false" persisted="false" css="true">
<article title="Success" class="o-notification o-notification--success o-notification--top" data-oruga="notification">
<!---->
<div class="o-notification__wrapper">
<!---->
<div class="o-notification__content">If an account with this email exists, we just sent another confirmation email to some@email.tld</div>
</div>
</article>
</transition-stub>
<transition-stub name="fade" appear="false" persisted="false" css="true">
<article class="mt-2 o-notification o-notification--info o-notification--top" data-oruga="notification">
<!---->
<div class="o-notification__wrapper">
<!---->
<div class="o-notification__content">Please check your spam folder if you didn't receive the email.</div>
</div>
</article>
</transition-stub>
</div>
</section>"
`;

View File

@@ -1,54 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`SendPasswordReset > Show simple 1`] = `
"<section class="container mx-auto">
<h1>Forgot your password?</h1>
<p>Enter your email address below, and we'll email you instructions on how to change your password.</p>
<form>
<div data-oruga="field" class="o-field o-field--filled"><label class="o-field__label" for="">Email address</label>
<div class="o-field__body">
<div class="o-field o-field--addons">
<div data-oruga="input" class="o-input__wrapper o-input__wrapper--expanded"><input aria-required="true" required="" id="" data-oruga-input="email" type="email" class="o-input" autocomplete="off">
<!---->
<!---->
<!---->
</div>
</div>
</div>
<!---->
</div>
<p class="my-4 flex gap-2"><button type="submit" class="o-btn o-btn--primary" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Submit</span>
<!----></span>
</button><a href="/login" class="o-btn o-btn--text" role="button" data-oruga="button"><span class="o-btn__wrapper"><!----><span class="o-btn__label">Cancel</span>
<!----></span>
</a></p>
</form>
</section>"
`;
exports[`SendPasswordReset > Show simple 2`] = `
"<section class="container mx-auto">
<h1>Forgot your password?</h1>
<p>Enter your email address below, and we'll email you instructions on how to change your password.</p>
<div>
<transition-stub name="fade" appear="false" persisted="false" css="true">
<article class="my-2 o-notification o-notification--success o-notification--top" title="Success" data-oruga="notification">
<!---->
<div class="o-notification__wrapper">
<!---->
<div class="o-notification__content">We just sent an email to some@email.tld</div>
</div>
</article>
</transition-stub>
<transition-stub name="fade" appear="false" persisted="false" css="true">
<article class="my-2 o-notification o-notification--info o-notification--top" data-oruga="notification">
<!---->
<div class="o-notification__wrapper">
<!---->
<div class="o-notification__content">Please check your spam folder if you didn't receive the email.</div>
</div>
</article>
</transition-stub>
</div>
</section>"
`;

View File

@@ -1,37 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`SettingsOnboard > Show simple - step 1 1`] = `
"<div data-v-68ff875c="" class="container mx-auto">
<h1 data-v-68ff875c="" class="title">Let's define a few settings</h1>
<o-steps-stub data-v-68ff875c="" modelvalue="0" vertical="false" iconprev="chevron-left" iconnext="chevron-right" hasnavigation="false" destroyonhide="false" animated="true" animation="slide-next,slide-prev,slide-down,slide-up" animateinitially="false" labelposition="bottom" rounded="true"></o-steps-stub>
<section data-v-68ff875c="" class="has-text-centered section buttons">
<o-button-stub data-v-68ff875c="" tag="router-link" rounded="false" expanded="false" disabled="true" outlined="true" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
<o-button-stub data-v-68ff875c="" tag="router-link" variant="success" rounded="false" expanded="false" disabled="false" outlined="true" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
<!--v-if-->
</section>
</div>"
`;
exports[`SettingsOnboard > Show simple - step 2 1`] = `
"<div data-v-68ff875c="" class="container mx-auto">
<h1 data-v-68ff875c="" class="title">Let's define a few settings</h1>
<o-steps-stub data-v-68ff875c="" modelvalue="1" vertical="false" iconprev="chevron-left" iconnext="chevron-right" hasnavigation="false" destroyonhide="false" animated="true" animation="slide-next,slide-prev,slide-down,slide-up" animateinitially="false" labelposition="bottom" rounded="true"></o-steps-stub>
<section data-v-68ff875c="" class="has-text-centered section buttons">
<o-button-stub data-v-68ff875c="" tag="router-link" rounded="false" expanded="false" disabled="false" outlined="true" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
<o-button-stub data-v-68ff875c="" tag="router-link" variant="success" rounded="false" expanded="false" disabled="false" outlined="true" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
<!--v-if-->
</section>
</div>"
`;
exports[`SettingsOnboard > Show simple - step 3 1`] = `
"<div data-v-68ff875c="" class="container mx-auto">
<h1 data-v-68ff875c="" class="title">Let's define a few settings</h1>
<o-steps-stub data-v-68ff875c="" modelvalue="2" vertical="false" iconprev="chevron-left" iconnext="chevron-right" hasnavigation="false" destroyonhide="false" animated="true" animation="slide-next,slide-prev,slide-down,slide-up" animateinitially="false" labelposition="bottom" rounded="true"></o-steps-stub>
<section data-v-68ff875c="" class="has-text-centered section buttons">
<o-button-stub data-v-68ff875c="" tag="router-link" rounded="false" expanded="false" disabled="false" outlined="true" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
<!--v-if-->
<o-button-stub data-v-68ff875c="" tag="router-link" variant="success" size="big" rounded="false" expanded="false" disabled="false" outlined="false" loading="false" inverted="false" nativetype="button" role="button" iconboth="false" to="[object Object]"></o-button-stub>
</section>
</div>"
`;

View File

@@ -1,59 +0,0 @@
import { beforeEach, describe, it, expect } from "vitest";
import { enUS } from "date-fns/locale";
import { routes } from "@/router";
import { createRouter, createWebHistory, Router } from "vue-router";
import { getMockClient, requestHandlers } from "../../mocks/client";
import EmailValidate from "@/views/User/EmailValidate.vue";
import { config, mount } from "@vue/test-utils";
import { Oruga } from "@oruga-ui/oruga-next";
import flushPromises from "flush-promises";
import { VALIDATE_EMAIL } from "@/graphql/user";
config.global.plugins.push(Oruga);
let router: Router;
beforeEach(async () => {
router = createRouter({
history: createWebHistory(),
routes: routes,
});
// await router.isReady();
});
const email_mock = {
data: {
id: "987654",
},
};
const generateWrapper = (mock_email = {}) => {
const global_data = getMockClient([[VALIDATE_EMAIL, mock_email]]);
global_data.provide.dateFnsLocale = enUS;
global_data.plugins = [router];
return mount(EmailValidate, {
props: {
token: "azerty123456789",
},
global: {
...global_data,
stubs: {
RouterLink: false,
},
},
});
};
describe("EmailValidate", () => {
it("Show simple", async () => {
const wrapper = generateWrapper(email_mock);
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({
token: "azerty123456789",
});
});
});

View File

@@ -1,201 +0,0 @@
import { config, mount, VueWrapper } from "@vue/test-utils";
import Login from "@/views/User/LoginView.vue";
import {
createMockClient,
MockApolloClient,
RequestHandler,
} from "mock-apollo-client";
import buildCurrentUserResolver from "@/apollo/user";
import { loginMock as loginConfigMock } from "../../mocks/config";
import { CONFIG } from "@/graphql/config";
import {
loginMock,
loginResponseMock,
nullIdentityMock,
} from "../../mocks/auth";
import { LOGIN } from "@/graphql/auth";
import {
CURRENT_USER_CLIENT,
LOGGED_USER_LOCATION,
UPDATE_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, 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";
import {
VueRouterMock,
createRouterMock,
injectRouterMock,
getRouter,
} from "vue-router-mock";
import { IDENTITIES } from "@/graphql/actor";
import { nullMock } from "../../common";
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> = {},
customMocks: Record<string, unknown> = {}
) => {
mockClient = createMockClient({
cache,
resolvers: buildCurrentUserResolver(cache),
});
requestHandlers = {
configQueryHandler: vi.fn().mockResolvedValue(loginConfigMock),
loginMutationHandler: vi.fn().mockResolvedValue(loginResponseMock),
identity: vi.fn().mockResolvedValue(nullIdentityMock),
mockhdl: vi.fn().mockResolvedValue(nullMock),
...handlers,
};
mockClient.setRequestHandler(CONFIG, requestHandlers.configQueryHandler);
mockClient.setRequestHandler(LOGIN, requestHandlers.loginMutationHandler);
mockClient.setRequestHandler(IDENTITIES, requestHandlers.identity);
mockClient.setRequestHandler(LOGGED_USER_LOCATION, requestHandlers.mockhdl);
mockClient.setRequestHandler(
UPDATE_CURRENT_USER_CLIENT,
requestHandlers.mockhdl
);
wrapper = mount(Login, {
props: {
...customProps,
},
mocks: {
...customMocks,
},
stubs: ["router-link", "router-view"],
global: {
provide: {
[DefaultApolloClient]: mockClient,
},
},
});
wrapper.router.push.mockReset();
};
afterEach(() => {
wrapper?.unmount();
cache.reset();
mockClient = null;
});
it("requires email and password to be filled", async () => {
generateWrapper();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.exists()).toBe(true);
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
wrapper.find('form input[type="email"]').setValue("");
wrapper.find('form input[type="password"]').setValue("");
wrapper.find('form button[type="submit"]').trigger("click");
const form = wrapper.find("form");
expect(form.exists()).toBe(true);
const formElement = form.element as HTMLFormElement;
expect(formElement.checkValidity()).toBe(false);
});
it("renders and submits the login form", async () => {
generateWrapper();
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.exists()).toBe(true);
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.loginMutationHandler).toHaveBeenCalledWith({
...loginMock,
});
await flushPromises();
const currentUser = mockClient?.cache.readQuery<{
currentUser: ICurrentUser;
}>({
query: CURRENT_USER_CLIENT,
})?.currentUser;
await flushPromises();
expect(currentUser?.email).toBe("some@email.tld");
expect(currentUser?.id).toBe("1");
await flushPromises();
expect(wrapper.router.replace).toHaveBeenCalledWith({
name: RouteName.HOME,
});
});
it("handles a login error", async () => {
generateWrapper({
loginMutationHandler: vi.fn().mockResolvedValue({
errors: [
{
message:
'"Impossible to authenticate, either your email or password are invalid."',
},
],
}),
});
await wrapper.vm.$nextTick();
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.exists()).toBe(true);
expect(requestHandlers.configQueryHandler).toHaveBeenCalled();
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find('form input[type="password"]').setValue("somepassword");
wrapper.find("form").trigger("submit");
await wrapper.vm.$nextTick();
expect(requestHandlers.loginMutationHandler).toHaveBeenCalledWith({
...loginMock,
});
await flushPromises();
expect(wrapper.find(".o-notification--danger").text()).toContain(
"Impossible to authenticate, either your email or password are invalid."
);
expect(wrapper.router.push).not.toHaveBeenCalled();
});
it("handles redirection after login", async () => {
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(wrapper.router.push).toHaveBeenCalledWith("/about/instance");
});
});

View File

@@ -1,72 +0,0 @@
import { beforeEach, describe, it, expect, vi } from "vitest";
import { enUS } from "date-fns/locale";
import { routes } from "@/router";
import { createRouter, createWebHistory, Router } from "vue-router";
import { getMockClient, requestHandlers } from "../../mocks/client";
import ProviderValidation from "@/views/User/ProviderValidation.vue";
import { config, mount } from "@vue/test-utils";
import { Oruga } from "@oruga-ui/oruga-next";
import flushPromises from "flush-promises";
import { UPDATE_CURRENT_USER_CLIENT, LOGGED_USER } from "@/graphql/user";
vi.mock("@/utils/html", () => {
return {
getValueFromMeta: (name: string) => name,
escapeHtml: (html: string) => html,
};
});
config.global.plugins.push(Oruga);
let router: Router;
beforeEach(async () => {
router = createRouter({
history: createWebHistory(),
routes: routes,
});
// await router.isReady();
});
const logged_mock = {
data: {
loggedUser: {
__typename: "User",
defaultActor: {
__typename: "Person",
id: "1",
unreadConversationsCount: 0,
},
id: "1",
},
},
};
const generateWrapper = (mock_logged = {}) => {
const global_data = getMockClient([
[LOGGED_USER, mock_logged],
UPDATE_CURRENT_USER_CLIENT,
]);
global_data.provide.dateFnsLocale = enUS;
global_data.plugins = [router];
return mount(ProviderValidation, {
global: {
...global_data,
stubs: {
RouterLink: false,
},
},
});
};
describe("ProviderValidation", () => {
it("Show simple", async () => {
const wrapper = generateWrapper(logged_mock);
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_1).toHaveBeenCalledTimes(0);
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({});
});
});

View File

@@ -1,57 +0,0 @@
import { beforeEach, describe, it, expect } from "vitest";
import { enUS } from "date-fns/locale";
import { routes } from "@/router";
import { createRouter, createWebHistory, Router } from "vue-router";
import { getMockClient, requestHandlers } from "../../mocks/client";
import ResendConfirmation from "@/views/User/ResendConfirmation.vue";
import { config, mount } from "@vue/test-utils";
import { Oruga } from "@oruga-ui/oruga-next";
import flushPromises from "flush-promises";
import { RESEND_CONFIRMATION_EMAIL } from "@/graphql/auth";
config.global.plugins.push(Oruga);
let router: Router;
beforeEach(async () => {
router = createRouter({
history: createWebHistory(),
routes: routes,
});
// await router.isReady();
});
const generateWrapper = () => {
const global_data = getMockClient([RESEND_CONFIRMATION_EMAIL]);
global_data.provide.dateFnsLocale = enUS;
global_data.plugins = [router];
return mount(ResendConfirmation, {
global: {
...global_data,
stubs: {
RouterLink: false,
},
},
});
};
describe("ResendConfirmation", () => {
it("Show simple", async () => {
const wrapper = generateWrapper();
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(0);
wrapper.find('form input[type="email"]').setValue("some@email.tld");
wrapper.find("form").trigger("submit");
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({
email: "some@email.tld",
});
});
});

View File

@@ -1,73 +0,0 @@
import { beforeEach, describe, it, expect } from "vitest";
import { enUS } from "date-fns/locale";
import { routes } from "@/router";
import { createRouter, createWebHistory, Router } from "vue-router";
import { getMockClient, requestHandlers } from "../../mocks/client";
import SettingsOnboard from "@/views/User/SettingsOnboard.vue";
import { config, shallowMount } from "@vue/test-utils";
import { Oruga } from "@oruga-ui/oruga-next";
import flushPromises from "flush-promises";
import { USER_SETTINGS } from "@/graphql/user";
config.global.plugins.push(Oruga);
let router: Router;
beforeEach(async () => {
router = createRouter({
history: createWebHistory(),
routes: routes,
});
// await router.isReady();
});
const settings_mock = {
data: {},
};
const generateWrapper = (mock_settings = {}, step) => {
const global_data = getMockClient([[USER_SETTINGS, mock_settings]]);
global_data.provide.dateFnsLocale = enUS;
global_data.plugins = [router];
return shallowMount(SettingsOnboard, {
props: {
step: step,
},
global: {
...global_data,
stubs: {
RouterLink: false,
},
},
});
};
describe("SettingsOnboard", () => {
it("Show simple - step 1", async () => {
const wrapper = generateWrapper(settings_mock, 1);
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({});
});
it("Show simple - step 2", async () => {
const wrapper = generateWrapper(settings_mock, 2);
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({});
});
it("Show simple - step 3", async () => {
const wrapper = generateWrapper(settings_mock, 3);
await wrapper.vm.$nextTick();
await flushPromises();
expect(wrapper.html()).toMatchSnapshot();
expect(requestHandlers.handle_0).toHaveBeenCalledTimes(1);
expect(requestHandlers.handle_0).toHaveBeenCalledWith({});
});
});