Protractor+Mocha 在浏览器加载 SUT 之前因 TypeError 套件失败

Protractor+Mocha fails suite with TypeError before browser loads SUT

上下文

我正在探索 angular2 + angular-cli + 打字稿。我的 objective 是为了确保如果我在打字稿中做 angular 应用程序或节点应用程序,我将使用与使用 mocha 的遗留节点应用程序相同的测试技术。为此,我正在尝试重新配置 angular-cli 生成的 protractor.conf.js 以使用 mocha 而不是 jasmine。

问题

您如何正确集成 angular-cli + mocha + 量角器,以便测试将使用量角器执行,实际上提供 mocha 规范有用的 browser/element/by 组件?

我已经将 protractor.conf.js 更改为使用 mocha 和 chai 并且测试已完成,但是与量角器组件的所有交互都失败了,即 element(by.css('app-root h1')).getText()

已转换protractor.conf.js

exports.config = {
  allScriptsTimeout: 11000, // The timeout for a script run on the browser. 
  specs: [
    './e2e/**/*.e2e-spec.ts' // pattern for the test specs
  ],
  baseUrl: 'http://localhost:4200/', // base url of the SUT
  capabilities: {
    'browserName': 'chrome' // browser to use
  },
  directConnect: true, // selenium will not need a server, direct connet to chrome
  framework: 'mocha', // Use mocha instead of jasmine
  mochaOpts: { // Mocha specific options 
    reporter: "spec",
    slow: 3000,
    ui: 'bdd',
    timeout: 30000
  },
  beforeLaunch: function() { // Do all the typescript 
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });
  },
  onPrepare: function() {}
};

怀疑

感觉问题出在浏览器加载应用程序之前套件正在执行(并失败)。这可能是 protractor/browser 交互,根据我的理解,它应该与正在使用的规范无关。也许这种理解是不正确的?

示例来源

我在 GitHub 上有一个 运行ning 示例,我用它来测试和比较转换

目前调查

运行 命令行上的量角器(通过节点)node node_modules\protractor\bin\protractor protractor.conf.js --stackTrace --troubleshoot 向我们展示了该套件已配置并且 运行 一个 truthy 测试,一个跳过的测试,以及实际应用测试

套件结果

我们看到 truthy 测试正在通过,skipped 测试被跳过,应用程序测试都失败并出现相同类型的错误

1 passing 
1 pending
5 failing

 1) A descriptive test name that is irrelevant to the error:
     TypeError: obj.indexOf is not a function
      at include (node_modules\chai\lib\chai\core\assertions.js:228:45)
      at doAsserterAsyncAndAddThen (node_modules\chai-as-promised\lib\chai-as-promised.js:293:29)
      at .<anonymous> (node_modules\chai-as-promised\lib\chai-as-promised.js:271:25)
      at chainableBehavior.method (node_modules\chai\lib\chai\utils\overwriteChainableMethod.js:51:34)
      at assert (node_modules\chai\lib\chai\utils\addChainableMethod.js:84:49)
      at Context.it (e2e\search\search.e2e-spec.ts:14:40)
      at runTest (node_modules\selenium-webdriver\testing\index.js:166:22)
      at node_modules\selenium-webdriver\testing\index.js:187:16
      at new ManagedPromise (node_modules\selenium-webdriver\lib\promise.js:1067:7)
      at controlFlowExecute (node_modules\selenium-webdriver\testing\index.js:186:14)
  From: Task: A descriptive test name that is irrelevant to the error
      at Context.ret (node_modules\selenium-webdriver\testing\index.js:185:10)

TypeError 似乎是因为应用程序本身似乎从来没有时间在套件完成之前实际加载到浏览器中

--解决输出问题

[09:26:33] D/launcher - Running with --troubleshoot
[09:26:33] D/launcher - Protractor version: 5.1.1
[09:26:33] D/launcher - Your base url for tests is http://localhost:4200/
[09:26:33] I/direct - Using ChromeDriver directly...
[09:26:36] D/runner - WebDriver session successfully started with capabilities Capabilities {
  'acceptSslCerts' => true,
  'applicationCacheEnabled' => false,
  'browserConnectionEnabled' => false,
  'browserName' => 'chrome',
  'chrome' => { chromedriverVersion: '2.28.455520 (cc17746adff54984afff480136733114c6b3704b)',
  userDataDir: 'C:\Users\abartish\AppData\Local\Temp\scoped_dir4596_5000' },
  'cssSelectorsEnabled' => true,
  'databaseEnabled' => false,
  'handlesAlerts' => true,
  'hasTouchScreen' => false,
  'javascriptEnabled' => true,
  'locationContextEnabled' => true,
  'mobileEmulationEnabled' => false,
  'nativeEvents' => true,
  'networkConnectionEnabled' => false,
  'pageLoadStrategy' => 'normal',
  'platform' => 'Windows NT',
  'rotatable' => false,
  'takesHeapSnapshot' => true,
  'takesScreenshot' => true,
  'unexpectedAlertBehaviour' => '',
  'version' => '56.0.2924.87',
  'webStorageEnabled' => true }
[09:26:36] D/runner - Running with spec files ./e2e/**/*.e2e-spec.ts

附加信息

有趣的是,如果您使用 elementExplorer 运行 量角器 node node_modules\protractor\bin\protractor protractor.conf.js --stackTrace --troubleshoot --elementExplorer 它不会 运行 测试,但我们确实看到 SUT 在启动的浏览器中解析。这个我解释不了。

首先,我对摩卡不是很熟悉。但是,我可以让你的测试通过。这是您需要做的:

设置依赖项

有时候使用最新最好的依赖项是很棒的。最新的 chai-as-promised 对我不起作用。我曾经尝试将 Protractor 依赖项更新为最新版本的 chai 和 chai-as-promised 以及 运行 问题。我不得不降级您的依赖项并最终使用:

"chai": "~3.5.0",
"chai-as-promised": "~5.3.0",

这些是与量角器相同的版本 package.json。

使用 onPrepare 插件

在 Protractor 运行测试之前设置 chai-as-promised:

onPrepare: function() {
  let chai = require('chai');
  let chaiAsPromised = require("chai-as-promised");
  chai.use(chaiAsPromised);
  global.chai = chai;
}

编辑测试:

添加或修改以下内容。

app.e2e-spec.ts

import {RootPage} from './root/root.po';
let expect = global["chai"].expect;

  // change the following lines to have "eventually"
  expect(page.getParagraphText()).to.eventually.contain('Car search POC');

  // if you don't want to use "eventually"
  page.getParagraphText().then(paragraph => {
    expect(paragraph).to.contain('Car search POC');
  });

root.e2e-spec.ts:

let expect = global["chai"].expect;

describe('Home page', () => {

  // change the following lines to have "eventually"
  expect(page.getParagraphText()).to.eventually.include('Car search POC');
  expect(browser.getCurrentUrl()).to.eventually.include(homePage.uri());

home.e2e-spec.ts:

import {RootPage} from './root.po';
import {HomePage} from '../home/home.po';
import {WaitCondition} from '../wait.conditions';
let expect = global["chai"].expect;

  // change the following lines to have "eventually"
  expect(page.getParagraphText()).to.eventually.equal('Car search POC');

  // This line will not work. getInnerHtml has been deprecated by both
  // Protractor and selenium-webdriver.
  //
  // If you want to use something similar, do something like:
  // let i = browser.executeScript("return arguments[0].innerHTML;", element(locator));
  // This is noted in the CHANGELOG under the Protractor 5.0.0 release
  expect(page.getListingContent()).to.exist;

search.e2e-spec.ts

import {SearchPage} from './search.po';
let expect = global["chai"].expect;

  // change the following lines to have "eventually"
  expect(page.getParagraphText()).to.eventually.contain('Car search POC');

控制台输出

这是我 运行 你的测试结果。请注意 "will have content" 失败,因为 getInnerHtml() 无效。

angular-cli-seed App
  ✓ will do normal tests
  ✓ will display its title

Home page
  ✓ will display its title
  - will have content

root page
  ✓ will display its title
  ✓ will redirect the URL to the home page

search page
  ✓ will display its title


6 passing (5s)
1 pending

这是一个有趣的 Whosebug 问题。很容易回答,因为您包含了 b运行ch 无效的内容。测试愉快!