WebdriverIO+Mocha解析JSON拖拽失败,报find未定义错误
解决WebdriverIO结合Mocha解析JSON时的"Cannot read properties of undefined (reading 'find')"错误
问题概述
在WebdriverIO结合Mocha框架解析JSON文件时触发错误:Cannot read properties of undefined (reading 'find')。核心需求是:解析JSON中包含"before": {"title": "- STFC42"}的字段,将对应页面元素拖拽到"State 0"目标元素,并验证目标元素显示JSON中"after": {"detail": "STFC42"}的内容。单独调用dragEvents功能正常,但结合JSON解析逻辑后报错。
相关代码及日志
测试文件代码
import { parseEventMapFile } from '../utils/stfc.utils' it('should drag all items from Events to State', async () => { const eventMapFilePath = '../noddi/test/utils/Event_map.json'; const sectionName = 'Fmt:0 - 3DHUD'; try { const EventTriggers = await parseEventMapFile(eventMapFilePath, sectionName); for (const item of EventTriggers) { const draggedItems = await TriggerPage.dragEvents(item.before.title); for (const draggedItem of draggedItems) { assert.strictEqual(draggedItem.itemName, item.before.title); } } } catch (error) { console.error('Error in parsing test:', error); throw error; } });
页面对象代码
/** * Returns the element to be dragged based on the item name * @param {string} itemName - The name of the item to be dragged * @returns {Promise<WebdriverIO.Element>} */ public async getDraggedElement(itemName: string): Promise<WebdriverIO.Element> { return this.$(`//span[contains(@class, "event-key") and contains(text(), "${itemName}")]`) } /** * Returns the target element (State 0) * @returns {Promise<WebdriverIO.Element>} */ public async getTargetElement(): Promise<WebdriverIO.Element> { return this.$('#State\\ 0') } /** * Drags the specified item from Events over to the State 0 element * @param {string} [itemName] - The name of the item to be dragged (optional) * @returns {Promise<{ itemName: string; html: string }[]>} */ public async dragEvents(itemName?: string): Promise<{ itemName: string; html: string }[]> { try { if (itemName) { const elem = await this.getDraggedElement(itemName); const target = await this.getTargetElement(); await browser.executeScript(dragAndDrop, [elem, target]); } const elements = await $$('.detail'); await Promise.all(elements.map(element => element.waitForDisplayed())); const draggedItems = []; if (elements) { for (const element of elements) { const html = await element.getHTML(); const itemName = await element.getText(); draggedItems.push({ itemName, html }); } } else { console.error('No elements found.'); } return draggedItems; } catch (error) { console.error('Error during dragEvents:', error); throw error; } }
stfc.utils文件代码
import { promises as fsPromises } from 'fs'; export async function parseEventMapFile(filePath: string, sectionName?: string) { try { const content = await fsPromises.readFile(filePath, 'utf8'); const eventMap = JSON.parse(content); const section = eventMap.children.find(child => child.title === sectionName); if (!section) { throw new Error(`Section "${sectionName}" not found in Event_map.json`); } return section.children; } catch (error) { console.error('Error reading the file:', error); throw error; } }
JSON片段
[ { "title": "STFC - Ships", "children": [ { "title": "42:Stars - 3DHUD", "children": [ { "before": { "title": "- STFC42", "description": "Station 42" }, "after": { "title": "Neutral Zone", "detail": "STFC42" } }, { "before": { "title": "- Cube9", "description": "The Borg" }, "after": { "title": "Delta9", "detail": "Cube.9" } } ] } ] } ]
解析日志
[0-0] Parsed Event Map: [ [0-0] { [0-0] title: 'STFC - Ships', [0-0] children: [ [Object], [Object] ] [0-0] }
错误原因分析
- JSON结构不匹配:JSON根节点是数组,但
stfc.utils中直接访问eventMap.children,数组没有children属性,导致eventMap.children为undefined,调用find方法时触发错误。 - Section名称不匹配:测试中指定的
sectionName是'Fmt:0 - 3DHUD',但JSON中对应的section名称是'42:Stars - 3DHUD',即使解析逻辑正确,也会找不到目标section。 - 验证逻辑不符合需求:当前验证的是拖拽元素的名称等于
item.before.title,但需求是验证目标元素显示item.after.detail的内容。
解决方案
1. 修正JSON解析逻辑
修改stfc.utils中的代码,适配JSON根节点为数组的结构:
import { promises as fsPromises } from 'fs'; export async function parseEventMapFile(filePath: string, sectionName?: string) { try { const content = await fsPromises.readFile(filePath, 'utf8'); const eventMap = JSON.parse(content); // 遍历根数组,找到包含目标section的父节点 const parentNode = eventMap.find(node => node.children?.some(child => child.title === sectionName) ); if (!parentNode) { throw new Error(`未找到包含section "${sectionName}"的父节点`); } // 从父节点的children中定位目标section const targetSection = parentNode.children.find(child => child.title === sectionName); if (!targetSection) { throw new Error(`Section "${sectionName}"未在JSON文件中找到`); } return targetSection.children; } catch (error) { console.error('读取文件时出错:', error); throw error; } }
2. 修正Section名称
将测试文件中的sectionName改为JSON中实际存在的名称:
const sectionName = '42:Stars - 3DHUD';
3. 调整验证逻辑以匹配需求
修改测试中的验证代码,验证目标元素显示item.after.detail的内容:
for (const item of EventTriggers) { const draggedItems = await TriggerPage.dragEvents(item.before.title); // 查找并验证目标元素是否显示预期的after.detail内容 const matchedItem = draggedItems.find(dragged => dragged.itemName === item.after.detail); assert.ok(matchedItem, `未找到显示内容为"${item.after.detail}"的目标元素`); }
内容的提问来源于stack exchange,提问作者STFC
相关产品推荐
相关产品推荐

