Search code examples
unit-testingtestingvuejs3nuxt3.jsvitest

Function testing with vitest + vue 3 + nuxt 3 + typescript


In my nuxt3 + vue3 project, I have the below function, that checks if the content of a given html element overflows vertically and it returns a boolean for overflowing and the difference in height for the html element against the window object.

useVerticalOverflow.ts file

const useVerticalOverflow = (el: HTMLElement) => {
  const height = el.scrollHeight - window.innerHeight;

  const hasOverflowY = el.scrollHeight > window.innerHeight;

  return { hasOverflowY, height };
};

export default useVerticalOverflow;

I am trying to write a test for this, however, my div height is always showing up as 0 even if I set the height.

useVerticalOverflow.spec.ts file

import { describe, expect, test, beforeEach, afterEach } from "vitest";
import useVerticalOverflow from "./useVerticalOverflow";

describe("useVerticalOverflow", () => {
  let el: HTMLElement;

  beforeEach(() => {
    el = document.createElement("div");
    el.style.height = "200px";
    el.style.overflowY = "auto";
    el.innerHTML = `Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`;
    document.body.appendChild(el);

    console.log("--------");
    console.log("divEl getBoundingClientRect: ", el.getBoundingClientRect());
    console.log("window.innerHeight", window.innerHeight);  // 768
  });

  afterEach(() => {
    document.body.removeChild(el);
  });

  test("should return hasOverflowY as true and height greater than 0 when the element has vertical overflow", () => {
    const result = useVerticalOverflow(el);

    expect(result.hasOverflowY).toBe(true);
    expect(result.height).toBeGreaterThan(0);
  });

  test("should return hasOverflowY as false and height lesser than or equal to 0 when the element does not have vertical overflow", () => {
    el.style.height = "1000px";
    const result = useVerticalOverflow(el);

    expect(result.hasOverflowY).toBe(false);
    expect(result.height).toBeLessThanOrEqual(0);
  });
});

The console.log gives out the below output:

divEl getBoundingClientRect:  {
  x: 0,
  y: 0,
  bottom: 0,
  height: 0,
  left: 0,
  right: 0,
  top: 0,
  width: 0
}
window.innerHeight 768

QUESTION: How can I set the height of the div element and read its height property to make sure that my function works correctly.


Solution

  • My updated solution for the test file. Everything works correctly now. To manipulate the scrollHeight all that was needed to be added was this piece of code:

    Object.defineProperty(el, "scrollHeight", { configurable: true, value: 1000 });
    

    useVerticalOverflow.spec.ts file

    import { describe, expect, test, beforeEach, afterEach } from "vitest";
    import useVerticalOverflow from "./composables/useVerticalOverflow";
    
    describe("useVerticalOverflow composable", () => {
      let el: HTMLElement;
    
      beforeEach(() => {
        el = document.createElement("div");
    
        Object.defineProperty(window, "innerHeight", {
          configurable: true,
          value: 700,
        });
    
        document.body.appendChild(el);
      });
    
      afterEach(() => {
        document.body.removeChild(el);
      });
    
      test("should return hasOverflowY as true and height greater than 0 when the element has vertical overflow", () => {
        Object.defineProperty(el, "scrollHeight", {
          configurable: true,
          value: 1000,
        });
    
        const result = useVerticalOverflow(el);
        expect(result.hasOverflowY).toBe(true);
        expect(result.height).toBeGreaterThan(0);
      });
    
      test("should return hasOverflowY as false and height 0 when the element does not have vertical overflow", () => {
        Object.defineProperty(el, "scrollHeight", {
          configurable: true,
          value: 500,
        });
    
        const result = useVerticalOverflow(el);
        expect(result.hasOverflowY).toBe(false);
        expect(result.height).toBeLessThanOrEqual(0);
      });
    });