3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ta1m1kamが一人で書くAdvent Calendar 2022

Day 5

window.locationオブジェクトについてJestでmockしたい!!

Last updated at Posted at 2022-12-04

概要

window.location.hrefに新しいパスを渡してリダイレクト処理等を行う場合がある。その際にJest等でテストを書きたいがMockの仕方に詰まったのでメモとして残す。

window.locationとは

JavaScriptのグローバル変数であるwindowの読み取り専用プロパティの1つです。documentの現在位置についてのLocationオブジェクトを返します。

以下のようにブラウザ上での現在の位置情報やhostname、プロトコルなどが参照できます。

> JSON.stringify(location)
'{
    "ancestorOrigins":{},
    "href":"https://developer.mozilla.org/ja/docs/Web/API/Window/location",
    "origin":"https://developer.mozilla.org",
    "protocol":"https:",
    "host":"developer.mozilla.org",
    "hostname":"developer.mozilla.org",
    "port":"",
    "pathname":"/ja/docs/Web/API/Window/location",
    "search":"",
    "hash":""
}'

Object.defineProperty()について

静的メソッドの Object.defineProperty() は、あるオブジェクトに新しいプロパティを直接定義したり、オブジェクトの既存のプロパティを変更したりして、そのオブジェクトを返します。

この Object.defineProperty() を使用することで、テストを書く際にlocationオブジェクトをモックとして新しく定義することができます。

また、オプションキーに writableというキーがあり、これをtrueにすることでテストごとにモックの値を変えることができるようになります。(※ これがfalseの場合は値が代入変更できず、最初に定義したものが使用されることになります。)

実際にテストを書いてみる

  • テスト対象
    テスト対象は、hostがexample.comであればwww.google.comにリダイレクトする関数とします。
redirectFromExample.js
const redirectFromExample = () => {
  const { hostname, search } = window.location;
  const redirectHostname = hostname === 'example.com' ? 'www.google.com' : hostname;
  window.location.href = `//${redirectHostname}${search}`;
};

export { redirectFromExample };

beforeEachwritableなwindow.locationオブジェクトを定義して、各テストでlocationオブジェクトをモックします。

redirectFromExample.test.js
const { redirectFromExample } = require('../redirectFromExample');

describe('redirectFromExample', () => {
  beforeEach(() => {
    Object.defineProperty(window, 'location', {
      value: {
        href: '',
        pathname: '/',
        search: '',
        hostname: '',
      },
      writable: true,
    });
  });

  it('redirect to google.com from example', () => {
    global.window = Object.create(window);
    Object.defineProperty(window, 'location', {
      value: {
        href: 'https://example.com/',
        pathname: '/',
        search: '',
        hostname: 'example.com',
      },
    });

    redirectFromExample();

    expect(window.location.href).toEqual('//www.google.com');
  });

  it('not redirect to google.com', () => {
    global.window = Object.create(window);
    Object.defineProperty(window, 'location', {
      value: {
        href: 'https://www.yahoo.jp/',
        pathname: '/',
        search: '?hoge=text',
        hostname: 'www.yahoo.jp',
      },
    });

    redirectFromExample();

    expect(window.location.href).toEqual('//www.yahoo.jp?hoge=text');
  });
});

テストを実行するとredirectFromExample() メソッドで書き換えられたlocationオブジェクトについてテストできていることがわかります。

 PASS  src/shared/utils/helpers/__tests__/redirectFromExample.test.js
  redirectFromExample
    ✓ redirect to google.com from example
    ✓ not redirect to google.com

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.219s, estimated 1s
Ran all test suites matching /redirectFromExample/i.
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?