在 Jest 中模拟 document.querySelector

2024-03-03

我尝试模拟这个功能,但没有完全覆盖。我不确定如何嘲笑getBoundingClientRect in header and dataHeader.

handleWindowScroll() {

    const header = document.querySelector('.productNavLinksContainer');
    const dataHeader = document.querySelector('.productNavDataContainer');
    if (header && dataHeader) {
        const headerPos = header.getBoundingClientRect();
        const dataHeaderPos = dataHeader.getBoundingClientRect();
        const sticky = header.offsetTop;
        if (dataHeaderPos.top > headerPos.height) {
            this.setState({
                sticky: false
            });
        } else if (window.pageYOffset > sticky) {
            this.setState({
                sticky: true
            });
        }
    } else {
        return;
    }
}

这是单元测试解决方案:

index.jsx:

import React, { Component } from 'react';

class SomeComponent extends Component {
  constructor(props) {
    super(props);
    this.state = { sticky: false };
  }

  handleWindowScroll() {
    const header = document.querySelector('.productNavLinksContainer');
    const dataHeader = document.querySelector('.productNavDataContainer');
    if (header && dataHeader) {
      const headerPos = header.getBoundingClientRect();
      const dataHeaderPos = dataHeader.getBoundingClientRect();
      const sticky = header.offsetTop;
      if (dataHeaderPos.top > headerPos.height) {
        this.setState({ sticky: false });
      } else if (window.pageYOffset > sticky) {
        this.setState({ sticky: true });
      }
    } else {
      return;
    }
  }
  render() {
    return null;
  }
}

export default SomeComponent;

index.test.jsx:

import SomeComponent from '.';
import { shallow } from 'enzyme';
import React from 'react';

describe('60784579', () => {
  afterEach(() => {
    jest.restoreAllMocks();
  });
  it('should not sticky', () => {
    const mDataHeaderPos = { top: 100 };
    const mHeaderPos = { height: 50 };
    const mHeader = { offsetTop: 100, getBoundingClientRect: jest.fn().mockReturnValueOnce(mHeaderPos) };
    const mDataHeader = { getBoundingClientRect: jest.fn().mockReturnValueOnce(mDataHeaderPos) };
    jest.spyOn(document, 'querySelector').mockImplementation((selector) => {
      switch (selector) {
        case '.productNavLinksContainer':
          return mHeader;
        case '.productNavDataContainer':
          return mDataHeader;
      }
    });
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const instance = wrapper.instance();
    instance.handleWindowScroll();
    expect(document.querySelector).toBeCalledTimes(2);
    expect(mHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(mDataHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(instance.state).toEqual({ sticky: false });
  });

  it('should sticky if pageYOffset greater than offsetTop', () => {
    const mDataHeaderPos = { top: 40 };
    const mHeaderPos = { height: 50 };
    const mHeader = { offsetTop: 100, getBoundingClientRect: jest.fn().mockReturnValueOnce(mHeaderPos) };
    const mDataHeader = { getBoundingClientRect: jest.fn().mockReturnValueOnce(mDataHeaderPos) };
    jest.spyOn(document, 'querySelector').mockImplementation((selector) => {
      switch (selector) {
        case '.productNavLinksContainer':
          return mHeader;
        case '.productNavDataContainer':
          return mDataHeader;
      }
    });
    Object.defineProperty(window, 'pageYOffset', { value: 200 });
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const instance = wrapper.instance();
    instance.handleWindowScroll();
    expect(document.querySelector).toBeCalledTimes(2);
    expect(mHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(mDataHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(instance.state).toEqual({ sticky: true });
  });

  it('should do nothing if header or dataHeader does not exist', () => {
    jest.spyOn(document, 'querySelector').mockImplementation((selector) => {
      switch (selector) {
        case '.productNavLinksContainer':
          return undefined;
        case '.productNavDataContainer':
          return undefined;
      }
    });
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const instance = wrapper.instance();
    const actual = instance.handleWindowScroll();
    expect(actual).toBeUndefined();
    expect(document.querySelector).toBeCalledTimes(2);
    expect(instance.state).toEqual({ sticky: false });
  });
  it('should do nothing if pageYOffset less than offsetTop', () => {
    const mDataHeaderPos = { top: 40 };
    const mHeaderPos = { height: 50 };
    const mHeader = { offsetTop: 100, getBoundingClientRect: jest.fn().mockReturnValueOnce(mHeaderPos) };
    const mDataHeader = { getBoundingClientRect: jest.fn().mockReturnValueOnce(mDataHeaderPos) };
    jest.spyOn(document, 'querySelector').mockImplementation((selector) => {
      switch (selector) {
        case '.productNavLinksContainer':
          return mHeader;
        case '.productNavDataContainer':
          return mDataHeader;
      }
    });
    Object.defineProperty(window, 'pageYOffset', { value: 80 });
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const instance = wrapper.instance();
    const actual = instance.handleWindowScroll();
    expect(actual).toBeUndefined();
    expect(document.querySelector).toBeCalledTimes(2);
    expect(mHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(mDataHeader.getBoundingClientRect).toBeCalledTimes(1);
    expect(instance.state).toEqual({ sticky: false });
  });
});

100%覆盖率的单元测试结果:

 PASS  stackoverflow/60784579/index.test.jsx (7.912s)
  60784579
    ✓ should not sticky (9ms)
    ✓ should sticky if pageYOffset greater than offsetTop (2ms)
    ✓ should do nothing if header or dataHeader does not exist (2ms)
    ✓ should do nothing if pageYOffset less than offsetTop (1ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |     100 |      100 |     100 |     100 |                   
 index.jsx |     100 |      100 |     100 |     100 |                   
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       4 passed, 4 total
Snapshots:   0 total
Time:        9.223s

源代码:https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60784579 https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/60784579

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Jest 中模拟 document.querySelector 的相关文章

  • asp.net 将值从 JS/jquery 传递到 C# 背后的代码

    我已经尝试了 所有 可能的方法 将 screen width vlaue 从 aspx 页面上的 JS 脚本发送到后面代码中的 c 虽然我可以看到 screen width 被正确分配 但它永远不会分配给我的隐藏字段价值
  • 无法在 IE 中的选择选项上使用 onmouseover 事件

    更新的代码 function getElements var x document getElementsByTagName option var el document getElementById selectDept el onmou
  • 以编程方式在指令内添加指令

    我想将指令的另一个实例附加到父指令中 但我无法使用 apply 重新编译我的指令 我想我在某个地方错过了一些东西 我的 HTML 代码 div div div div
  • 如何从 Javascript/Typescript 中的数组对象计算运行总计并使用 HTML 在每个实例上显示输出?

    我正在开发一个 MEAN 堆栈项目 并且有一个如下所示的数组 savings any 300 450 350 500 我还有一个名为 saving bf 的变量 它是从数据库中检索的结转储蓄 其值如下 savings bf 15000 我想
  • 如何翻转 Twitter Bootstrap 的工具提示

    我正在使用 Twitter 的 Bootstrap 来实现工具提示 目前 工具提示显示在链接上方 我希望工具提示出现在链接下方 我该怎么做呢 我正在触发工具提示 它明确指出 底部 但它不想为我工作 tooltip tooltip place
  • 是否可以进行条件解构或有后备?

    我有一个具有许多深层嵌套属性的对象 我希望能够访问 MY KEY 上的属性 如下 但如果该属性不存在 则获取 MY OTHER KEY 我怎样才能做到这一点 const X Y MY KEY Values segments segment
  • 用于传输命名参数和正文的云端点资源属性不起作用

    我正在尝试通过gapi client rpc调用实现对谷歌云端点的调用 如文档中所述 和Google Cloud Endpoints 使用 JS 客户端进行调用 传递参数和 JSON 正文 https stackoverflow com q
  • 如何解构 React props 并仍然访问其他 props?

    我很好奇如果我想要所有的 props 但也想要解构单个属性 那么组件的参数 props 是否可以像导入一样解构 我想这更像是一个 JavaScript 问题 而不是一个 React 问题 但是举个例子 import React useEff
  • 将事件添加到 Google Maps API InfoWindow 内的元素

    我想在 Google Maps API v3 InfoWindow 内放置一个带有输入字段和提交按钮的表单 提交后 我想调用一个函数 该函数使用输入字段中输入的地址启动方向服务 这是我的代码 我目前只测试方向事件是否被触发 我已经编写了完整
  • 从 html5

    我正在寻找一种方法来根据用户代理字符串将控件属性添加到视频标签 我不希望在 iPad 和 Android 之外的任何浏览器或设备上出现控件属性 所以我认为用户代理是最好的识别方法 因为 ipad 和 android 一词出现在各自的 UA
  • Next.js:如何将 source-map-explorer 与 Next.js 一起使用

    我想分析我的 Next js 构建源地图浏览器 https www npmjs com package source map explorer 有人可以帮我编写脚本吗 对于 React CRA 我使用以下脚本 build analyze n
  • Intro.js 2页然后返回首页

    我在用intro js http introjs com 为我的网站创建一个小介绍 我希望游览从第 1 页 主页 2 另一页 然后回到第 1 页 主页 我已经成功地从第 1 2 页开始 但不确定如何让它返回到第 1 页 我对 javascr
  • 在移动网站中处理 iPhone 事件(如向左滑动)

    iPhone 浏览器是否有可以使用 Javascript 挂钩的特殊事件 例如 如果用户向左滑动 我想执行某个操作 如果有类似的活动 很高兴看到所有这些活动的参考 理想情况下 有一天所有触摸屏移动浏览器都会有一个标准 您可以访问多点触控事件
  • iPhone 点击时使 div 变暗

    当您的 div 附加了点击处理程序时 当点击该 div 时 iPhone 会使该 div 变暗 作为点击指示器 示例 在移动 Safari 上查看http jsbin com awejo3 4 http jsbin com awejo3 4
  • JavaScript 中的最短路径

    几周来我一直在寻找一种在 JavaScript 中计算最短路径的方法 我一直在玩书数据结构和算法作者 格罗纳 Groner 名字恰如其分 https github com loiane javascript datastructs algo
  • 如何显示 GroupList 的 FormArray?

    我正在尝试制作一个交互式表单 在每一行上列出一个项目以及一个删除按钮 在我的示例中称为 verwijderen 这些项目是从数据库中检索的 并且每个项目都实例化为名为的自定义对象LaborPeriod 然后这些对象被转化为FormGroup
  • Babel/RequireJS + typeof“RangeError:超出最大调用堆栈大小”

    我有一个非常基本的 JS 错误 我很羞愧无法解决它 我正在使用 ES6 和 Babel 进行开发 并且正在做一些实验 请注意 我在 Babel 中使用了这些参数 presets es2015 plugins transform es2015
  • 动态 dom 操作后,如何在浏览器历史记录中保留 dom 状态?

    是否有一个通用的解决方案来保留 dom 状态 以便当用户使用后退 前进返回页面时 整个页面处于他们离开时的确切状态 这篇文章询问并回答了为什么不同浏览器和不同 javascript 库的行为不一致 Ajax 后退按钮和 DOM 更新 htt
  • 这个 JQuery 指令做什么 $(function(){...}) [重复]

    这个问题在这里已经有答案了 我最近一直在研究JQuery 尽管我知道一些东西 但书上有这样一句话我根本无法理解 function current entry 1 有谁知道这条线是如何工作的以及它的作用是什么 它类似于 JQuery 函数中的
  • 如何在 Firefox 插件中追加到文件?

    var tabs require sdk tabs var iofile require sdk io file var widgets require sdk widget var selection require sdk select

随机推荐

  • EJB3 与数据访问对象

    我正在开发一个项目 我们需要决定如何公开我们的持久层 目前有两种选择 1 使用普通的 DAO 它们将实现一个接口并被注入 可能使用 Weld 到业务组件 即 EJB 中 在内部 他们将使用 JPA Hibernate 来实现持久性 2 不是
  • C2DM重试注册权限被拒绝

    非常感谢任何有关如何解决重试注册事件时的权限拒绝错误的想法 Permission Denial broadcasting Intent act com google android c2dm intent RETRY flg 0x4 has
  • rJava - .jcall 调用问题:未找到签名的方法

    我尝试用 rJava 调用 java 类中的方法几天了 但我还没有弄清楚我做错了什么 也许这里有人会给我一些线索 情况是这样的 我加载库并初始化一个对象 工作正常 library rJava jinit C javatemp worker
  • 是否可以使用服务帐户访问 Google Play 游戏服务 API?

    我已经通过 Google Play 开发者控制台创建了游戏 它是ready for testing 但尚未发布 在那里添加了两个服务帐户作为测试人员 email protected cdn cgi l email protection Go
  • RandomForestRegressor 中出现连续不支持错误

    我只是想做一个简单的 RandomForestRegressor 示例 但是在测试准确性时我收到此错误 Users noppanit anaconda lib python2 7 site packages sklearn metrics
  • Jquery按钮点击选择复选框

    我有包含用户数据的网格 第一列有复选框 我在网格顶部有一个按钮 如果我单击 按钮 我需要从列表中选择前 5 位用户 谁能告诉我如何使用 jquery 做到这一点 myButton click function Grid input type
  • 使用 PostgreSQL 时,一对一关联在 5.4.0+ 上产生错误

    我们有使用 OneToOne 注释和 PostgreSQL 的 Spring Boot 应用程序 所属类别 Table name PAYMENT public class PaymentDO Id GeneratedValue strate
  • 用户追加行后,文本输入不会出现

    我这里有一个小提琴 http jsfiddle net ybZvv 11 http jsfiddle net ybZvv 11 我遇到的问题是 当您打开小提琴时 如果您单击按钮 A H 中的几个按钮 然后单击 添加问题 按钮将按钮附加到新的
  • Angularjs 将请求发送到服务器

    我如何收集客户发送的信息 在这种情况下 ID 我怎样才能得到id 我确实使用客户端请求 return http post api kill id 4 headers 当我检查服务器端的 req body 时console log Req b
  • 在 C# (3.0) 中使用条件 (?:) 运算符进行方法选择?

    我正在重构一些代码 目前有不少地方有这样的功能 string error if a error f1 a long parameter list else error f2 the same long parameter list 在重构
  • 获取GeneralPath的有序顶点

    如何获取 GeneralPath 对象的顶点 看起来这应该是可能的 因为路径是由点 lineTo curveTo 等 构造的 我正在尝试创建点数据的 double x y 坐标数组 您可以从以下网站取回积分PathIterator http
  • 添加 JSON 作为资产并读取它

    我正在尝试从本地文件加载一些 JSON 数据 In 这个苹果文档 https developer apple com library ios documentation ToolsLanguages Conceptual Xcode Ove
  • Ruby、Unicorn 和环境变量

    在使用 Heroku 时 我发现他们使用环境变量进行服务器本地配置的方法非常出色 现在 在设置自己的应用程序服务器时 我发现自己想知道复制它有多困难 我正在部署一个 sinatra 应用程序 使用 Unicorn 和 Nginx 我知道ng
  • 使用 pom 将 Maven 输出发送到控制台和日志文件

    Question 在 Eclipse 中运行 Maven 时 如何将控制台输出发送到文件 我想使用 pom 设置或 Maven 插件来实现这一点 我愿意not想要修改运行配置或maven系统设置 作为参考 我使用的是 Windows 7 E
  • 如何在不同的函数中使用dispatcherTimer.Stop?

    我有一个关于在代码中使用 DispatcherTimer 的问题 请看我下面的情况 private void CheckShow object sender System Windows RoutedEventArgs e Dispatch
  • AWS API Gateway 映射模板 JSON

    我有一个 API 阶段NOT使用 Lambda 代理集成 其中 Lambda 函数传递错误 在映射模板中我有这个 input path errorMessage 其结果是 headers apiVersion 20190218 1 isTe
  • 通过背景字体很棒的动画旋转器

    我通过 CSS 背景使用 font Awesome 旋转图标来加载页面 Styles go here loading icon position relative width 20px height 20px margin 50px aut
  • 如何在 tkinter python 中获取 canvas.create_text() 文本值

    from tkinter import canvas Canvas width 500 height 100 bg black typed value canvas create text 250 50 text 5 7 font cour
  • 为什么 Hex() 函数返回字符串而不是 int 十六进制?

    我不知道为什么 Hex 函数返回像 0x41 这样的字符串而不是 0x41 我需要将 ASCII 值转换为十六进制 但我想要 0x INT 格式 而不是 0x 字符串 ascii 360 hexstring hex ascii hexstr
  • 在 Jest 中模拟 document.querySelector

    我尝试模拟这个功能 但没有完全覆盖 我不确定如何嘲笑getBoundingClientRect in header and dataHeader handleWindowScroll const header document queryS