detect.test.ts

3.2 KB · raw

1// @vitest-environment jsdom23import { beforeEach, describe, expect, it } from "vitest";45import {6  detectLoginFields,7  getPageDomain,8  isLoginForm,9  isSignupForm,10} from "./detect";1112describe("content detect", () => {13  beforeEach(() => {14    document.body.innerHTML = "";15  });1617  function visibleInput(18    attributes: Record<string, string> = {},19    tagName: "input" = "input"20  ): HTMLInputElement {21    const input = document.createElement(tagName);22    Object.entries(attributes).forEach(([key, value]) => input.setAttribute(key, value));23    Object.defineProperty(input, "getBoundingClientRect", {24      configurable: true,25      value: () => ({26        width: 100,27        height: 20,28        top: 0,29        left: 0,30        right: 100,31        bottom: 20,32        x: 0,33        y: 0,34        toJSON: () => ({}),35      }),36    });37    document.body.appendChild(input);38    return input as HTMLInputElement;39  }4041  it("isLoginForm returns true for a username/password pair", () => {42    const username = visibleInput({ type: "email", name: "email" });43    const password = visibleInput({ type: "password", autocomplete: "current-password" });4445    expect(46      isLoginForm([47        { type: "username", el: username },48        { type: "password", el: password },49      ])50    ).toBe(true);51  });5253  it("isLoginForm returns false for fields without a password", () => {54    const username = visibleInput({ type: "text", name: "username" });5556    expect(isLoginForm([{ type: "username", el: username }])).toBe(false);57  });5859  it("isSignupForm returns true for confirm-password flows", () => {60    const password = visibleInput({ type: "password", name: "password" });61    const confirm = visibleInput({ type: "password", name: "confirmPassword" });6263    expect(64      isSignupForm([65        { type: "password", el: password },66        { type: "password", el: confirm },67      ])68    ).toBe(true);69  });7071  it("isSignupForm returns false for a single current-password field", () => {72    const password = visibleInput({ type: "password", autocomplete: "current-password" });7374    expect(isSignupForm([{ type: "password", el: password }])).toBe(false);75  });7677  it("detectLoginFields matches email and username-style inputs but not tag-name fields", () => {78    const email = visibleInput({ type: "email", name: "email" });79    const username = visibleInput({ type: "text", name: "login-id" });80    const tagName = visibleInput({ type: "text", name: "tag-name" });81    const password = visibleInput({ type: "password", autocomplete: "current-password" });82    const hidden = visibleInput({ type: "hidden", name: "username" });8384    const fields = detectLoginFields(document);8586    expect(fields.some((field) => field.el === email && field.type === "username")).toBe(true);87    expect(fields.some((field) => field.el === username && field.type === "username")).toBe(true);88    expect(fields.some((field) => field.el === password && field.type === "password")).toBe(true);89    expect(fields.some((field) => field.el === tagName)).toBe(false);90    expect(fields.some((field) => field.el === hidden)).toBe(false);91  });9293  it("getPageDomain falls back to the current hostname when no registrable domain exists", () => {94    expect(getPageDomain()).toBe(window.location.hostname);95  });96});