jestjs - Mocka window.location i TypeScript jest-test


Jag har en kodbit som sätter ihop en fullständig URL för en omdirigering (något som detta):

import { redirect } from './some-utils'

export const goToURL = () => {
    const url = window.location.origin + window.location.pathname
    redirect(url)
}

Nu försöker jag skriva ett TypeScript-test som testar URL-strängen:

describe('my-test-file', () => {
    let originalWindowLocation
    const redirect = jest.fn()

    beforeEach(() => {
        jest.resetAllMocks()
        originalWindowLocation = window.location
    })

    afterEach(() => {
        window.location = originalWindowLocation
    })

    it('test that redirection URL is correct', () => {
        delete window.location // can't do this because TS complains
        window.location = { origin: 'https://www.example.com', pathname: '/mypath' } // can't do this because TS complains

        goToURL()
        expect(redirect).toHaveBeenCalledTimes(1)
        expect(redirect).toHaveBeeenCalledWith('https://www.example.com/mypath')
    })
})

Men jag får två TypeScript-fel. På delete-raden:

Operandet för en 'delete'-operator måste vara valfritt.

och på den nya tilldelningen av window.location:

Typen '{ origin: string; pathname: string; }' kan inte tilldelas typen 'Location | (string & Location)'. Typen '{ origin: string; pathname: string; }' kan inte tilldelas typen 'string & Location'. Typen '{ origin: string; pathname: string; }' kan inte tilldelas typen 'string'.

Jag försökte åtgärda det första felet genom att ta bort delete-satsen och försökte åtgärda det andra felet genom att lägga till as Location i slutet av tilldelningen. Att göra detta åtgärdar TS-felen men mitt test går inte längre igenom. Det använder domänen för min webbapp istället för den exempel som används i mitt test.

Kan någon hjälpa mig att fixa mina TS-fel samtidigt som jag säkerställer att mina tester går igenom?

Redigera :

Om jag försöker window.location='https://www.example.com/mypath', passerar mitt test fortfarande inte och jag får fortfarande ett TS-fel:

Typen 'string' kan inte tilldelas typen 'Location | (string & Location)'

Om jag försöker window.location.href='https://www.example.com/mypath', försvinner TS-felen men testet går inte igenom.

Om jag försöker window.location.assign(https://www.example.com/mypath'), försvinner TS-felen men testet godkänns inte.

Svar #1

Om du endast använder en delmängd av Location-API:et som också är tillgängligt på en instans av URL (t.ex. window.location.href="https://domain.tld/pathname"), kan du manuellt mocka (ersätta) den egenskapen på window under dina tester:

describe('description', () => {
  let originalWindowLocation = window.location;

  beforeEach(() => {
    Object.defineProperty(window, 'location', {
      configurable: true,
      enumerable: true,
      value: new URL(window.location.href),
    });
  });

  afterEach(() => {
    Object.defineProperty(window, 'location', {
      configurable: true,
      enumerable: true,
      value: originalWindowLocation,
    });
  });

  it('test that redirection URL is correct', () => {
    const expectedUrl = 'https://www.example.com/mypath';
    window.location.href = expectedUrl;
    expect(window.location.href).toBe(expectedUrl);
  });
});

Jag valde medvetet att inte ta upp de andra aspekterna av din kod eftersom det inte är det du frågade om, men om du vill mocka ett funktionsanrop (t.ex. redirect) i en closure (t.ex. goToURL) från en extern modul, behöver du mocka den funktionen. Se mockning av moduler och mockning av delar i Jest-dokumentationen.

Relaterade artiklar