You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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]   }

错误原因分析

  1. JSON结构不匹配:JSON根节点是数组,但stfc.utils中直接访问eventMap.children,数组没有children属性,导致eventMap.children为undefined,调用find方法时触发错误。
  2. Section名称不匹配:测试中指定的sectionName是'Fmt:0 - 3DHUD',但JSON中对应的section名称是'42:Stars - 3DHUD',即使解析逻辑正确,也会找不到目标section。
  3. 验证逻辑不符合需求:当前验证的是拖拽元素的名称等于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:25:02