测试用的HTML页面:

    <div cxLockFocus id="a"><button id="a1"></button><a href="" id="a2"></a></div><div [cxLockFocus]="{ lock: true, group: 'g1' }" id="b" tabindex="-1"><button id="b1"></button><a href="" id="b2"></a><textarea id="b3"></textarea><a id="b4"></a><p id="b5"></p></div><div [cxLockFocus]="{ lock: false }" id="c" tabindex="5"><button id="c1"></button><a href="" id="c2"></a></div><div[cxLockFocus]="{ lock: true, focusOnEscape: false, autofocus: false }"id="d"><button id="d1"></button><a href="" id="d2" data-cx-focus="d2"></a></div><div [cxLockFocus]="{ lock: true, autofocus: 'button' }" id="e"><a href="" id="e1"></a><button id="e2"></button><button id="e3"></button></div>


这些方法可以全部mock:

在beforeEach实现里,选取每一组的部分子元素,注入到service.findFocusable的返回结果集里。

第一组测试:id为a的a标签,tabindex应该被设置为0:

lockFocus directive的默认配置:

注意shouldLock的标志位是通过config.lock决定的:

b标签通过显式传入的lock:true,也将tabindex设置为0,这一点同a标签一样:

c标签:如果显式地传入lock:false:

则host元素的tabindex不发生变化,仍然是初始值5:

在configuration测试里,监控event对象的stopPropagation方法,并且让service的hasFocusableChildren方法返回false.

  describe('configuration', () => {beforeEach(() => {spyOn(event, 'stopPropagation');spyOn(service, 'hasFocusableChildren').and.returnValue(false);fixture.detectChanges();});

显式触发a标签的回车事件:

注意上图代码,在使用代码触发a标签的keydown.enter事件时,也要将mock过后的event对象传到event handler里去。

根据lockFocus directive的实现,在handleEnter方法里会调用event.stopPropagation:

如果lock=false,则enter事件触发后,不应该自动被unlock, 单元测试代码:

    it('should not unlock when lock=false', () => {const host = fixture.debugElement.query(By.css('#c'));event.target = host.nativeElement;host.triggerEventHandler('keydown.enter', event);expect(event.stopPropagation).not.toHaveBeenCalled();});

原因在于,如果lock=false,shouldLock也为false,因此无法进入下图的IF分支。

子元素的锁定测试:

b1,b2, b3应该全部被锁住,tabindex为-1:

为什么要tick(500)?

只要lock=true,就会自动将autofocus设置为true:

在view渲染完毕之后,会调用handleFocus:

handleFocus里会调用setTimeout执行lockFocus方法:

b4,b5属于non-focusable标签,不应该被lock:

b4没有href属性,b5是p标签,都不应被锁住。

如果lock=false,也不应被lock,tabindex不应该为-1:

如果child具有persisted focus,那么不应再lock:

d1和d2的定义:

enter事件触发时,执行unlockFocus方法:

unlockFocus会将子元素的tabindex设置成0:

persist group的测试:

b1,b2,b3会自动被添加上data-cx-focus-group的属性,值为config里传入的g1:

b4, b5不是focusable element,所以不应该被设置data-cx-focus-group属性。

id为a的a标签会在escape时触发service的handleEscape方法:

如果lock=false,那么escape时没必要unlock:

更多Jerry的原创文章,尽在:“汪子熙”:

SAP Spartacus的Lock Focus Directive单元测试实现相关推荐

  1. SAP Spartacus lock focus Directive的工作原理示意图

    源代码: import {AfterViewInit,Directive,ElementRef,EventEmitter,HostBinding,HostListener,OnInit,Output, ...

  2. SAP Spartacus lock focus directive如何判断有没有focusable children

    hasFocusableChildren:返回boolean focusable:返回HTMLElement数组 service的原本类型是LockFocusService 没有任何实现: 再往上看T ...

  3. SAP Spartacus里和focus相关的directive之间的继承关系

    selector:cxFocus FocusDirective -> LockFocusDirective -> TrapFocusDirective -> TabFocusDire ...

  4. SAP Spartacus的persist focus,触发map set的条件

    判断isPersisted的条件: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NOMtVYAx-1610104864467)(https://upload-imag ...

  5. SAP Spartacus pop over 元素的单元测试

    如下图所示的 (i) icon,其对应的 HTML 原生代码如下:button 标签里包含 ng-reflect-cx-popover 属性. <button ng-reflect-cx-pop ...

  6. SAP Spartacus的persist focus

    design time: Directive的attr属性的改变,会触发最后html dom元素的FOCUS_ATTR属性data-cx-focus变化. 最后的结果: 这个key的getter,什么 ...

  7. SAP Spartacus delivery mode continue button单元测试失败原因分析

    原因在于continue button被设置成了disabled,因此无法点击: 因此需要研究这个button默认的enable状态: 通过测试发现,其默认是disable的.因此在单元测试之前,需要 ...

  8. SAP Spartacus里的HTTPErrorInterceptor的单元测试设计原理

    测试UnKnownErrorHandler是否能正确 处理UnknownError这个状态: 这个handler是import进来的: 调用经过TestBed.inject注入后的http: 执行su ...

  9. SAP Spartacus需要补充url validation单元测试的地方

    home page: 点了digital compacts: http://localhost:4200/electronics-spa/en/USD/Open-Catalogue/Cameras/D ...

最新文章

  1. Unet神经网络为什么会在医学图像分割表现好?
  2. 系统更新链接服务器超时,Win10系统更新后Dr.com连接认证服务器一直超时如何解决?...
  3. c++队列指针 结构体指针
  4. Kubernetes Dashboard - 每天5分钟玩转 Docker 容器技术(173)
  5. php获取函数里参数吗,php函数中获取参数信息方法(记录)
  6. linux程序实例获取,Linux命令备忘实例(4)——获取内容
  7. postman面试_Postman 收费太贵了,我决定用 Postwoman。。。
  8. 计算机网络:05---网络类型:局域网、城域网、广域网、个域网、无线网络
  9. 通过Socket实现文件上传/上传文件
  10. 深度学习在文本领域的应用
  11. 从零开始学习音视频编程技术(七) FFMPEG Qt视频播放器之SDL的使用
  12. 传聊天宝团队解散 罗永浩已退出股东行列
  13. vscode 5500 but failed to open in Browser Preview. Got Browser Preview extension installed?
  14. hdu 1217 Arbitrage (最小生成树)
  15. css background 旋转_纯CSS画小电视
  16. VMwareTools安装工具linux.iso
  17. 手机ncm转mp3工具_一款手机、电脑都能用的文字转语音工具,够高能! - 橘子世界...
  18. 去律师面试python_我的五次律所面试到底都经历了什么,这些真相……
  19. Schema for type Unit is not supported
  20. 道格拉斯普克算法(简化线段点)

热门文章

  1. nginx端合并JS
  2. Poj 1611 The Suspects
  3. RHEL6 cryptsetup 磁盘分区加密实验
  4. OpenExpressApp对建模支持的初步计划
  5. rowspan和colspan用法详解
  6. Quartus 使用tcl分配管脚
  7. vue 设置代理报错;occurred while trying to proxy request xxx
  8. beego orm 删除不掉数据!!!
  9. 读《深入jvm原理》之class文件
  10. 仿jquery 编写自己的js库