Как протестировать функцию, которая использует window.screen.width в шутку

#javascript #jestjs #window #width #screen

Вопрос:

Я пытаюсь проверить эту функцию в шутку, но я не могу переопределить, изменить размер экрана или создать виртуальный dom.

Я запускаю это тестирование на узле. ps: Я пытался использовать jsdom, но мне это не удалось.

functions.js

 export const getScreenWidth = () => {
  const screenWidth = window.screen.width;
  if (screenWidth <= 425) return "mobile";
  if (screenWidth <= 768) return "tablet";
  if (screenWidth <= 1024) return "laptopSm";
  if (screenWidth <= 1440) return "laptopLg";
  if (screenWidth <= 2560) return "HD";
  return screenWidth;
};

 

Ответ №1:

Над экраном можно поиздеваться, переопределив глобальную переменную экрана.

Пример:

 const mockScreen = (size) => {
  const { screen } = window.screen;
  delete window.screen;
  window.screen = {
    ...screen,
    width: size
  };
};

test("getScreenWidth", () => {
  mockScreen(300);
  expect(getScreenWidth()).toBe("mobile");
  mockScreen(1025);
  expect(getScreenWidth()).toBe("laptopLg");
});
 

Комментарии:

1. Я получил эту ошибку The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string. Consider using the "jsdom" test environment.

Ответ №2:

Я попытался сделать это насмешкой, и это сработало, но я действительно не знаю, правильный ли это способ сделать это.

 const mockScreen = (size) => {
      global.window = {};
      global.window.screen = {};
      global.window.screen.width = size;
    };
 

таким образом, заключительным испытанием будет

 describe("getScreenWidth()", () => {
  it.only("returns a string representing the width of the screen", () => {
    const mockScreen = (size) => {
      global.window = {};
      global.window.screen = {};
      global.window.screen.width = size;
    };
    mockScreen(425);
    expect(jsf.getScreenWidth()).toBe("mobile");
    mockScreen(2560);
    expect(jsf.getScreenWidth()).toBe("HD");
  });
});
 

Ответ №3:

Если вы работаете с библиотекой тестирования react, смоделируйте такой размер

 global.innerWidth = 1024;
global.dispatchEvent(new Event('resize'));
 

затем ожидайте, что ваша функция вернет правильный размер

Я протестировал пользовательский крючок, такой как

 function useWindowSize() {
  const [width, setWidth] = useState(window.innerWidth);
  const [height, setHeight] = useState(window.innerHeight);

  useEffect(() => {
    const handleResize = () => {
      setWidth(window.innerWidth);
      setHeight(window.innerHeight);
    };
    window.addEventListener('resize', handleResize);
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  });

  return { width, height };
}
 

таким образом

 function TestUseWindowSize() {
  const { height, width } = useWindowSize();
  return (
    <div>
      <h1 data-testid="height">{height}</h1>
      <h1 data-testid="width">{width}</h1>
    </div>
  );
}

describe('useWindowSize Custom Hook', () => {
  it('should return height and width', () => {
    const { getByTestId } = render(<TestUseWindowSize />);
    // screen defaults by render function
    expect(getByTestId('height')).toHaveTextContent(/768/);
    expect(getByTestId('width')).toHaveTextContent(/1024/);

    global.innerWidth = 1000;
    global.dispatchEvent(new Event('resize'));
    expect(getByTestId('width')).toHaveTextContent(/1000/);
  });
});