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

Protractor测试两个Angular应用时跨应用导航的ScriptTimeoutError问题解决方案咨询

如何用Protractor测试两个独立的Angular应用?

我手头有两个Angular应用,一个负责登录流程,另一个处理核心业务逻辑。在用Protractor做自动化测试时,登录第一个应用的流程完全正常,但切换到第二个应用后,尝试获取元素时总是碰到超时错误——明明浏览器里能看到元素,Protractor却死活找不到。而且两个都是Angular应用,我不想通过禁用waitForAngular来绕开问题,有没有合适的解决办法?

我的测试用例顺序

specs: [
  'login.js',// 第一个登录应用
  'navigatetoRegisterReport.js',// 从第一个应用导航的页面
  'requestCreation.js',// 通过`browser.get(第二个应用Url)`加载的业务应用页面
  'navigateToDcOtherInvoice.js'// 业务应用内的页面跳转
]

登录逻辑(运行正常)

async first() {
  await browser.driver.get(browser.baseUrl).then(async () => {
    await browser.wait(ExpectedConditions.elementToBeClickable(element(by.linkText("Other User"))), 30000);
    await element(by.linkText("Other User")).click().then(() => {
      browser.wait(ExpectedConditions.elementToBeClickable(element(by.css('#username'))), 30000);
      element(by.css('#username')).sendKeys('XXXXX').then(() => {
        browser.wait(ExpectedConditions.elementToBeClickable(element(by.id("password-field"))), 30000);
        element(by.id("password-field")).sendKeys('XXXXX').then(() => {
          browser.wait(ExpectedConditions.elementToBeClickable(element(by.id('login-submit'))), 30000);
          element(by.id('login-submit')).click().then(async () => {
            const dashboardImage = await element(by.css("app-dashboard .dashboard-image"));
            browser.wait(ExpectedConditions.elementToBeClickable(dashboardImage), 30000);
            dashboardImage.isDisplayed().then((value) => {
              if (value == true) {
                console.log('dashborad image is displayed')
              } else {
                console.log('dashborad image is not identified')
              }
            }).catch(error => console.error('caught error while login', error));;
          }).catch(error => console.error('caught error 7', error));;
        }).catch(error => console.error('caught error on password', error));;
      }).catch(error => console.error('caught error on user name', error));;
    }).catch(error => console.error('caught error tab click', error));;
  }).catch(error => console.error('caught error on load', error));
}

第二个应用的操作代码(报错)

async requestCreation(date: string, report: string) {
  await browser.get('https://2ndapplication/xxx/xxxx').then(async () => {
    var selectDate = element(by.xpath("//input[@id='icon-right']"));
    var reportType = element(by.xpath("//input[@placeholder='Report Type']"));
    browser.wait(ExpectedConditions.elementToBeClickable(selectDate), 30000);
    selectDate.clear();
    selectDate.sendKeys(date)
    browser.wait(ExpectedConditions.elementToBeClickable(reportType), 30000);
    reportType.click();
    reportType.clear();
    reportType.sendKeys(report)
  }).catch(error => console.error('caught error on requestCreation', error));
}

报错信息

Error: ScriptTimeoutError: script timeout
(Session info: chrome=88.0.4324.190)
(Driver info: chromedriver=88.0.4324.96 (68dba2d8a0b149a1d3afac56fa74648032bcf46b-refs/branch-heads/4324@{#1784}),platform=Windows NT 10.0.18363 x86_64)
at Object.checkLegacyResponse (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\error.js:546:15)
at parseHttpResponse (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\http.js:509:13)
at doSend.then.response (E:\updatedCode\backup\node_modules\selenium-webdriver\lib\http.js:441:30)
at process._tickCallback (internal/process/next_tick.js:68:7)
From: Task: Protractor.waitForAngular() **- Locator: By(xpath, //input[@id='icon-right'])


解决方案

1. 切换应用时手动重置Angular上下文

Protractor默认会绑定当前页面的Angular实例,当你跳转到第二个独立的Angular应用时,它不会自动切换上下文。所以在加载第二个应用后,需要手动让Protractor重新识别新的Angular环境:

async requestCreation(date: string, report: string) {
  try {
    await browser.get('https://2ndapplication/xxx/xxxx');
    
    // 重置Angular等待状态,确保Protractor监听新应用的Angular
    await browser.waitForAngularEnabled(true);
    
    // 等待第二个应用的Angular完全初始化
    await browser.wait(async () => {
      // 执行脚本检查当前页面是否有可用的Angular实例
      return await browser.executeScript(`
        return window.angular !== undefined && 
               window.angular.element(document).injector() !== undefined;
      `);
    }, 30000, '第二个Angular应用加载超时');

    // 后续元素操作
    const selectDate = element(by.xpath("//input[@id='icon-right']"));
    await browser.wait(ExpectedConditions.elementToBeClickable(selectDate), 30000);
    await selectDate.clear();
    await selectDate.sendKeys(date);

    const reportType = element(by.xpath("//input[@placeholder='Report Type']"));
    await browser.wait(ExpectedConditions.elementToBeClickable(reportType), 30000);
    await reportType.click();
    await reportType.clear();
    await reportType.sendKeys(report);
  } catch (error) {
    console.error('caught error on requestCreation', error);
  }
}

2. 用async/await替代嵌套then

你的代码里嵌套了大量的then,这很容易导致异步时序混乱,可读性也差。全部改用async/await可以让代码逻辑更清晰,也能避免很多异步相关的bug,就像上面重构后的代码那样。

3. 检查应用兼容性与配置

  • 确认第二个应用的Angular版本和Protractor 7.0.0兼容(Protractor 7.x支持Angular 2+,一般没问题,但如果是特别旧的版本可能需要调整)。
  • 在protractor.conf.js里添加useAllAngular2AppRoots: true,确保Protractor能识别到应用的根组件:
    exports.config = {
      // 其他配置...
      useAllAngular2AppRoots: true
    }
    

4. 验证URL与跨域问题

确保browser.get()的第二个应用URL完全正确,手动在测试用的Chrome里打开这个URL,确认能正常加载Angular应用,没有跨域拦截的情况。


内容的提问来源于stack exchange,提问作者Ramesh Rajendran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 09:23:12