如何合理链式调用命令以断言指定DOM文本结构?
需求与问题
我需要断言如下DOM结构:
<app-toggler data-cy="toggler"> <button id="1" data-cy="1"> <rows data-cy="rows"> <span>Title</span> </rows> <textarea> <text-rows data-cy="textarea"> <div title="Value1" data-cy="app-textarea-val1"> <span>Value1</span> </div> <div title="Value2" data-cy="app-textarea-val2"><!----> <span>Value2</span> </div> <div title="Value3" data-cy="app-textarea-val3"> <span>Value3</span> </div> </text-rows> </textarea> </button> <button id="2" data-cy="2"> <rows data-cy="rows"> <span>Titletwo</span> </rows> <textarea> <text-rows data-cy="textarea"> <div title="Value1two" data-cy="app-textarea-val1"> <span>Value1two</span> </div> <div title="Value2two" data-cy="app-textarea-val2"><!----> <span>Value2two</span> </div> <div title="Value3two" data-cy="app-textarea-val3"> <span>Value3two</span> </div> </text-rows> </textarea> </button> </app-toggler>
我希望实现类似"Title, Value1, Value2, Value3".isOneOf.Buttons.Text()的链式调用功能,用来判断逗号分隔的指定文本组合是否完全属于某个<button>元素下的所有文本。示例如下:
"Title, Value1, Value2, Value3".isOneOf.Buttons.Text()=>true"Titletwo, Value1, Value2, Value3".isOneOf.Buttons.Text()=>false"Title, Value1two, Value2three, Value3four".isOneOf.Buttons.Text()=>false
目前不清楚如何正确实现这种实用的链式调用逻辑。
实现方案
1. 原生JS环境实现(扩展String原型)
通过给String原型添加属性和方法,实现链式调用的语法。核心逻辑是先解析目标文本,再对比每个button下的文本集合:
// 辅助函数:获取所有button对应的文本数组集合 function getButtonTextGroups() { return Array.from(document.querySelectorAll('app-toggler button')).map(button => { // 提取button下所有span的文本,过滤空内容 return Array.from(button.querySelectorAll('span')) .map(el => el.textContent.trim()) .filter(text => text.length > 0); }); } // 给String原型添加isOneOf链式调用属性 Object.defineProperty(String.prototype, 'isOneOf', { get() { // 解析当前字符串为目标文本数组 const targetTexts = this.split(',') .map(text => text.trim()) .filter(text => text.length > 0); return { Buttons: { // 核心判断方法 Text() { const buttonTextGroups = getButtonTextGroups(); // 检查是否存在某个button的文本数组与目标完全匹配 return buttonTextGroups.some(group => { if (group.length !== targetTexts.length) return false; return group.every((text, index) => text === targetTexts[index]); }); } } }; } });
2. 测试验证
直接调用示例中的链式语法即可得到预期结果:
console.log("Title, Value1, Value2, Value3".isOneOf.Buttons.Text()); // true console.log("Titletwo, Value1, Value2, Value3".isOneOf.Buttons.Text()); // false console.log("Title, Value1two, Value2three, Value3four".isOneOf.Buttons.Text()); // false
3. 测试框架环境优化(以Cypress为例)
如果是在测试框架中使用,不建议修改原生原型,推荐自定义测试命令:
// 注册Cypress自定义命令 Cypress.Commands.add('hasMatchingButtonText', (targetTextStr) => { const targetTexts = targetTextStr.split(',').map(t => t.trim()).filter(Boolean); let matched = false; cy.get('app-toggler button').each($button => { cy.wrap($button).find('span').then($spans => { const texts = Array.from($spans).map(el => el.textContent.trim()).filter(Boolean); if (JSON.stringify(texts) === JSON.stringify(targetTexts)) { matched = true; } }); }).then(() => { expect(matched).to.be.true; }); }); // 使用方式 cy.hasMatchingButtonText("Title, Value1, Value2, Value3"); // 断言通过 cy.hasMatchingButtonText("Titletwo, Value1, Value2, Value3"); // 断言失败
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

