javascript - 使用 Selenium WebDriver/Jest 进行测试时如何等待函数被调用?

标签 javascript testing selenium-webdriver extjs jestjs

我有一个使用 Ext JS 创建的应用程序,我正在使用 Selenium WebDriver(Node package - 版本 4.0.0-alpha.1)和 Jest 为其编写测试。在我的一个测试脚本中,我想等待一个函数被调用,然后再继续其余的测试逻辑,但我不确定如何实现它。为了帮助演示我想要完成的工作,我使用 Sencha Fiddle 创建了一个示例应用程序。该应用程序的所有代码以及该应用程序的运行版本都可以在这里找到:https://fiddle.sencha.com/#view/editor&fiddle/2o6m .如果查看 fiddle 的应用程序文件夹,您会看到有一个带有简单 Controller 的测试组件。 Controller 中有一个 onAdd 函数,这是我在继续之前要等待的函数,因为在我的实际应用程序中,该函数中有其余测试所依赖的代码。我可以通过运行以下代码行在开发工具中访问该功能:Ext.ComponentQuery.query('test')[0].getController().onAdd(请注意,activeElement 需要设置为预览 iFrame(文档.getElementsByName('fiddle-run-iframe')[0]) 在 fiddle 中以使其起作用)。这意味着我可以以相同的方式访问 driver.executeScript 中的函数,但是一旦我拥有该函数,我就不确定如何在继续之前等待它被调用。我试图在 Jest 中使用模拟/ spy 功能,但这不起作用,因为 jest 没有在 driver.executeScript 中定义,所以我不能调用 jest.fn 或 jest.spyOn。我创建了一个与示例应用程序一起使用的示例测试脚本来演示我正在尝试做什么,但现在它失败并出现错误,因为正如我所说,jest 没有在 driver.executeScript 中定义。以下是示例测试脚本的代码:

const {Builder, By, Key, until} = require('selenium-webdriver');
const chrome = require('selenium-webdriver/chrome');

const driver = global.driver = new Builder()
            .forBrowser('chrome')
            .setChromeOptions(new chrome.Options())
            .build();

jest.setTimeout(10000);

beforeAll(async () => {
    await driver.manage().window().maximize();
    await driver.get('https://fiddle.sencha.com/#view/editor&fiddle/2o6m');
});

afterAll(async () => {
    await driver.quit();
});


describe('check title', () => {
    it('should be SAMPLE STORE LOAD', async () => {
        expect(await driver.wait(until.elementLocated(By.css('.fiddle-title'))).getText()).toBe('SAMPLE STORE LOAD');
    });
});

describe('check store add', () => {
    it('should call add function', async () => {
        let spy;

        await driver.switchTo().frame(await driver.findElement(By.name('fiddle-run-iframe')));
        await driver.wait(until.elementIsNotVisible(await driver.wait(until.elementLocated(By.xpath('//div[starts-with(@id, "loadmask")]')))));
        await driver.executeScript(() => {
            const test = document.getElementsByName('fiddle-run-iframe')[0].contentWindow.Ext.ComponentQuery.query('test')[0];
            spy = jest.spyOn(test.getController(), 'onAdd'); //This throws an error since jest is not defined inside driver.executeScript
        });

        expect(spy).toHaveBeenCalled(); //wait for onAdd function to be called before continuing
    });

    //additional tests occur here after wait...
}); 

您可以忽略与切换到 iFrame 相关的所有逻辑,因为这只是 fiddle 所必需的,因为它在 iFrame 中运行应用程序的预览。我的实际应用程序不存在于 iFrame 中。尽管如此,我认为这个脚本有效地演示了我试图完成的事情,即等待直到调用 onAdd 函数,然后再继续我的测试。我不确定我是否需要使用 Selenium 或 Jest、两者的某种组合或完全不同的测试工具来执行此操作。我对编写测试比较陌生,这是我第一次在 Stack Overflow 上发帖,所以如果我说的不清楚,我深表歉意。如果您有任何问题,我很乐意澄清任何事情,并感谢您提供的任何建议!

最佳答案

在我看来,在单个测试中结合 2 个不同的框架(测试方法)可能不是最好的主意。以下是我将如何处理类似案件的一些想法。理论很少:

Selenium - 非常适合使用浏览器模拟最终用户行为。基本上,它可以模拟 Action (点击、文本输入等)并可以从浏览器窗口获取信息(元素、文本、样式等的存在)

Jest - 是一个单元测试框架,用于调侃 javascript 代码。

executeScript 是 Selenium 的一个方法,它在浏览器中执行任何 javascript 代码。浏览器不了解关于jest 的任何信息 - 因此预计您会遇到您描述的错误。您的项目知道 jest,因为它是专门导入到项目中的。

回到问题“如何在 Selenium 中检查是否调用了 js 函数?”

  1. 最典型的解决方案 - 是等到浏览器屏幕上的内容发生变化。典型案例:

    • 出现了一些元素

    • 一些元素消失了

    • 一些元素的样式改变了

wait for condition in js example

  1. (有点 hack)另一种可能的解决方案是在应用程序的 js 代码中添加一些标志,该标志在调用函数之前将为 false,并在调用函数后设置为 true。然后您可以在 executeScript 中访问此标志的值。

some possible implementations here

关于javascript - 使用 Selenium WebDriver/Jest 进行测试时如何等待函数被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53634467/

相关文章:

java - org.openqa.selenium.UnhandledAlertException : unexpected alert open

javascript - 在nodejs中过滤JSON数据(包含对象数组)

javascript - 如何获取表单提交按钮以保存到 localStorage

php - 我不知道如何用 PHPUnit 测试 Ratchet/Sockets

测试 CouchDB View 、过滤器、列表、显示等

python - 像 Python 的 fakeweb 这样的库

javascript - 如何在 ES6 或 Javascript 中的 settimeout 函数之后触发不受我们控制的函数?

javascript - 我可以从 ServiceWorker 中的外部 JS 文件调用方法吗?

java - 如何使用 selenium 选择不包含特定类的元素

http - 在 Python 中将 Firefox WebDriver 与 Selenium 连接时出现问题