import { createTestingPinia } from "@pinia/testing"; import { getLocalVue, injectTestRouter } from "@tests/vitest/helpers"; import { mount } from "@vue/test-utils"; import flushPromises from "flush-promises"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { HttpResponse, useServerMock } from "@/api/client/__mocks__"; import MountTarget from "./LoginForm.vue"; const localVue = getLocalVue(true); const router = injectTestRouter(localVue); const testingPinia = createTestingPinia({ createSpy: vi.fn, stubActions: false }); const { server, http } = useServerMock(); const SELECTORS = { REGISTER_TOGGLE: "[id=register-toggle]", REGISTRATION_DISABLED: "[data-description='registration disabled message']", }; interface PostRequest { url: string; data: Record; } let postRequests: PostRequest[] = []; async function mountLoginForm() { const wrapper = mount(MountTarget as object, { propsData: { sessionCsrfToken: "sessionCsrfToken", }, localVue, router, stubs: { ExternalLogin: true, }, pinia: testingPinia, }); return wrapper; } describe("LoginForm", () => { beforeEach(() => { postRequests = []; server.use( http.get("/api/configuration", ({ response }) => { return response.untyped(HttpResponse.json({ oidc: { cilogon: false } })); }), http.untyped.post(/.*\/user\/login.*/, async ({ request }) => { const url = request.url; const data = (await request.json()) as Record; postRequests.push({ url, data }); return HttpResponse.json({}); }), ); }); it("basics", async () => { const wrapper = await mountLoginForm(); const cardHeader = wrapper.find(".card-header"); expect(cardHeader.text()).toBe("Welcome to OMAP, please log in"); const inputs = wrapper.findAll("input"); expect(inputs.length).toBe(2); const usernameField = inputs.at(0); expect(usernameField.attributes("type")).toBe("text"); await usernameField.setValue("test_user"); const pwdField = inputs.at(1); expect(pwdField.attributes("type")).toBe("password"); await pwdField.setValue("test_pwd"); const submitButton = wrapper.find("button[type='submit']"); await submitButton.trigger("submit"); await flushPromises(); expect(postRequests.length).toBe(1); expect(postRequests[0]?.data.login).toBe("test_user"); expect(postRequests[0]?.data.password).toBe("test_pwd"); }); it("props", async () => { const wrapper = await mountLoginForm(); expect(wrapper.findAll(SELECTORS.REGISTER_TOGGLE).length).toBe(0); // TODO: Never appears because of the GLink change expect(wrapper.find(SELECTORS.REGISTRATION_DISABLED).exists()).toBeTruthy(); await wrapper.setProps({ allowUserCreation: true, enableOidc: true, showWelcomeWithLogin: true, welcomeUrl: "welcome_url", }); expect(wrapper.find(SELECTORS.REGISTRATION_DISABLED).exists()).toBeFalsy(); // TODO: Changing the original `` to a `GLink` has made it so that the link never appears in the wrapper. // Currentlly, we confirm its existence by checking the fact that the disabled message is not there. // const registerToggle = wrapper.find(SELECTORS.REGISTER_TOGGLE); // expect(registerToggle.exists()).toBeTruthy(); // const register = wrapper.find(SELECTORS.REGISTER_TOGGLE); // (expect(register.text()) as any).toBe("Register here."); const welcomePage = wrapper.find("iframe"); expect(welcomePage.attributes("src")).toBe("welcome_url"); await flushPromises(); }); it("hides register link when local accounts are disabled", async () => { const wrapper = await mountLoginForm(); await wrapper.setProps({ allowUserCreation: true, disableLocalAccounts: true, }); expect(wrapper.findAll(SELECTORS.REGISTER_TOGGLE).length).toBe(0); expect(wrapper.find(SELECTORS.REGISTRATION_DISABLED).exists()).toBeTruthy(); }); it("connect external provider", async () => { const external_email = "test@test.com"; const provider_id = "test_provider"; const provider_label = "Provider"; // Mock window.location.search by overriding the property const originalSearch = window.location.search; Object.defineProperty(window.location, "search", { configurable: true, writable: true, value: `?connect_external_email=${external_email}&connect_external_provider=${provider_id}&connect_external_label=${provider_label}`, }); const wrapper = await mountLoginForm(); expect(wrapper.find(".card-header").exists()).toBe(false); const alert = wrapper.find(".alert"); expect(alert.classes()).toContain("alert-info"); expect(alert.text()).toContain(`There already exists a user with the email ${external_email}`); expect(alert.text()).toContain(`In order to associate this account with ${provider_label}`); const inputs = wrapper.findAll("input"); expect(inputs.length).toBe(2); const usernameField = inputs.at(0); expect(usernameField.attributes("type")).toBe("text"); expect((usernameField.element as HTMLInputElement).disabled).toBe(true); expect((usernameField.element as HTMLInputElement).value).not.toBe(""); expect((usernameField.element as HTMLInputElement).value).toContain(external_email); const pwdField = inputs.at(1); expect(pwdField.attributes("type")).toBe("password"); expect((pwdField.element as HTMLInputElement).value).toBe(""); await pwdField.setValue("test_pwd"); const submitButton = wrapper.find("button[type='submit']"); await submitButton.trigger("submit"); await flushPromises(); expect(postRequests.length).toBe(1); expect(postRequests[0]?.data.login).toBe(external_email); expect(postRequests[0]?.data.password).toBe("test_pwd"); expect(postRequests[0]?.url).toContain("/user/login"); // Restore original search Object.defineProperty(window.location, "search", { configurable: true, writable: true, value: originalSearch, }); }); it("renders message from query params", async () => { const originalHref = window.location.href; window.location.href = `${window.location.origin}/login/start?message=auth-error&status=info`; const wrapper = await mountLoginForm(); await flushPromises(); const alert = wrapper.find(".alert"); expect(alert.exists()).toBe(true); expect(alert.text()).toContain("auth-error"); expect(alert.classes()).toContain("alert-info"); window.location.href = originalHref; }); });