Angular4 + Protractor + Cucumber + TypeScript + webpack-dev-server - Angular 未找到
Angular4 + Protractor + Cucumber + TypeScript + weback-dev-server - Angular not found
- OS: macOS Sierra 10.12.4
- 节点:v7.9.0
- Npm: 5.0.3
- 黄瓜-js:2.3.0
- 量角器:4.0.14
- 打字稿:2.2.2
- webpack-开发服务器:2.4.5
我对 运行 端到端测试有疑问。当我尝试从页面获取元素时:
const el = browser.findElement(by.id('app-name'));
el.getText().then(function (text) {
console.log(text);
callback();
});
使用 'browser' 我得到这个错误:
> test-app@0.0.1 bdd:test /Users/p24/PhpstormProjects/alex-angular2
> node ./node_modules/.bin/protractor
(node:28198) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[13:03:31] I/hosted - Using the selenium server at http://selenium-standalone-chrome:4444/wd/hub
[13:03:31] I/launcher - Running 1 instances of WebDriver
Feature: : adding an advertisement
@web-test
Scenario: : adding new advertisement
✔ Given I am on the main page
✔ When I click the add advertisement button
✖ Then I should see the form to add an advertisement
Failures:
1) Scenario: : adding new advertisement - features/adding_advertisement.feature:5
Step: Then I should see the form to add an advertisement - features/adding_advertisement.feature:8
Step Definition: features/step_definitions/advertisement.ts:32
Message:
Error: function timed out after 5000 milliseconds
at Timeout._onTimeout (/Users/p24/PhpstormProjects/alex-angular2/node_modules/cucumber/lib/user_code_runner.js:91:22)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
1 scenario (1 failed)
3 steps (1 failed, 2 passed)
0m05.026s
Cucumber HTML report report/html/cucumber_report_hierarchy.html generated successfully.
Modified files:
[13:03:47] E/protractor - Could not find Angular on page http://alex.local/ : retries looking for angular exceeded
[13:03:47] E/launcher - Angular could not be found on the page http://alex.local/. If this is not an Angular application, you may need to turn off waiting for Angular. Please see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load
[13:03:47] E/launcher - Error: Angular could not be found on the page http://alex.local/. If this is not an Angular application, you may need to turn off waiting for Angular. Please see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load
at /Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/built/browser.js:506:23
at ManagedPromise.invokeCallback_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:1379:14)
at TaskQueue.execute_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2913:14)
at TaskQueue.executeNext_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2896:21)
at asyncRun (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2775:27)
at /Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:639:7
at process._tickCallback (internal/process/next_tick.js:109:7)
[13:03:47] E/launcher - Process exited with error code 199
npm ERR! code ELIFECYCLE
npm ERR! errno 199
npm ERR! test-app@0.0.1 bdd:test: `node ./node_modules/.bin/protractor`
npm ERR! Exit status 199
npm ERR!
npm ERR! Failed at the test-app@0.0.1 bdd:test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/p24/.npm/_logs/2017-06-10T11_03_47_694Z-debug.log
这是我的 webpack.config:
'use strict';
const HtmlWebpack = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({
filename: 'main.css'
});
const CleanWebpack = require('clean-webpack-plugin');
const rootDir = path.resolve(__dirname);
module.exports = {
devServer: {
contentBase: path.resolve(rootDir, 'dist'),
port: 3000,
host: '0.0.0.0',
disableHostCheck: true,
public: '172.23.0.1'
},
watchOptions: {
poll: true
},
devtool: 'source-map',
entry: {
"bundle": "./src/webpack.main.js",
"plugins": "./src/plugins.js"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
// publicPath: "/dist"
},
resolve: {
extensions: [ '.js', '.ts' ]
},
module: {
exprContextCritical: false,
rules: [
{
test: /\.html$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
},
},
{ loader: 'extract-loader' },
{ loader: 'html-loader' }
],
exclude: path.resolve(__dirname, 'src/index.html')
},
{
test: /\index.html$/,
loader: ['html-loader']
},
{
test: /\.ts$/,
loader: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(scss|css)$/,
use: extractPlugin.extract({
use: ['css-loader', 'sass-loader']
})
},
{
test: /\.(jpg|png|gif|eot|ttf|svg|woff|woff2)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: 'img/'
}
}]
},
],
},
plugins: [
new CleanWebpack(['dist']),
extractPlugin,
new HtmlWebpack({
template: 'src/index.html'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"Tether": 'tether'
})
],
};
我的protractor.config:
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
exports.config = {
seleniumAddress: 'http://selenium-standalone-chrome:4444/wd/hub',
baseUrl: 'http://alex.local',
capabilities: {
browserName:'chrome'
},
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
specs: [
'./features/*.feature'
],
cucumberOpts: {
require: ['./features/step_definitions/*.ts'],
tags: [],
strict: false,
format: ["pretty", "json:report/json/cucumber_report.json"],
dryRun: false,
compiler: ["ts:ts-node/register"]
},
onPrepare: function () {
browser.manage().window().maximize();
}
};
还有我的步骤定义文件出现错误的地方:
'use strict';
import {browser, element, by, By, $, $$, ExpectedConditions} from 'protractor';
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const expect = chai.expect;
const {defineSupportCode} = require('cucumber');
defineSupportCode(function(context: any) {
const Given = context.Given;
const When = context.When;
const Then = context.Then;
Given('I am on the main page', function (callback: any) {
browser.get('http://alex.local');
callback();
});
When('I click the add advertisement button', function (callback: any) {
callback();
});
Then('I should see the form to add an advertisement', function (callback: any) {
const el = browser.findElement(by.id('app-name'));
el.getText().then(function (text) {
console.log(text);
callback();
});
});
});
export {};
docker 一切尽在掌握。 docker-compose.yml:
version: '2'
services:
proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy-alex
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
app:
build: .
command: npm run build
environment:
- NODE_ENV=development
- VIRTUAL_HOST=alex.local
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
ports:
- "8080:3000"
selenium-chrome:
image: selenium/standalone-chrome
environment:
- VIRTUAL_HOST=selenium-standalone-chrome
ports:
- "4444:4444"
请在第一个 describe
块内的规范文件中使用 browser.ignoreSynchronization = true;
,这样 Protractor 就不会等待 Angular.
我认为有 2 个 "problems"。
首先,您使用的是 Protractor 4。要使用 Protractor 4 测试 Angular 2,您需要在配置中使用 useAllAngular2AppRoots: true
,或者,如果可能,升级到量角器 5.1.2。这应该可以解决您的第二个 Angular 超时问题。
其次,这是您的第一次超时,您仍然有 5 秒的 CucumberJS 默认超时。如果它们花费的时间超过 5 秒,那将始终停止步骤。通过将此代码添加到文件中,您可以增加它。
// cucumber.config.js file
import { defineSupportCode } from 'cucumber';
defineSupportCode(({setDefaultTimeout}) => {
setDefaultTimeout(11000);
});
希望对您有所帮助。
更新:
只是为了消除不正确的量角器语法:
useAllAngular2AppRoots: true
在量角器 5 中不需要,只在 4 中需要,我的错是我没有提到
- 使用 "correct" 语法在页面上查找元素是使用
element(by.id('app-name')
而不是 browser.findElement(by.id('app-name'))
,您的语法是 "vanilla" webdriver 语法,无需等待 Angular
只需 1 个检查问题 - 您的初始页面真的是 Angular 页面吗?
测试项目后更新:
我试图 运行 你的项目,但我遇到了各种不同的错误。我无法使用提供的命令为项目提供服务
ERROR in Cannot read property 'getSymbolByModule' of undefined
ERROR in multi ./src/styles.scss
Module not found:...
我只是想 运行 你的测试看看会发生什么和一些奇怪的事情发生了。步骤 Given('I am on the main page')
成功,但未加载任何站点。然后我在你的 Then('I should see the form to add an advertisement')
上遇到了同样的超时。
查看您的步骤实施后,我认为这是初始错误,您需要在解决 browser.get()
时调用 callback
,或者 return 承诺,请参阅下面。
// Or resolve the callback
Given('I am on the main page', function(callback: any) {
browser.get('http://alex.local').then(callback);
});
// Or return a promise
Given('I am on the main page', function() {
return browser.get('http://alex.local');
});
如果您使用上述实现之一,我想您会发现问题出在第一步,而不是您以正确方式实现 callback
的 Then('I should see the form to add an advertisement')
。
运行应用后更新
现在可以使用了。用npm run build
(手动)。然后将 http://alex.local
更改为 http://localhost:3000
.
当我运行这个测试
Given('I am on the main page', function(callback: any) {
// browser.ignoreSynchronization = true;
browser.get('http://localhost:3000').then(callback);
});
When('I click the add advertisement button', function(callback: any) {
callback();
});
Then('I should see the form to add an advertisement', function(callback: any) {
const el = element(by.css('.btn.btn-default'));
el.getText().then(function(text) {
console.log(text);
callback();
});
});
成功了,你会得到这个日志
Feature: : adding an advertisement
@web-test
Scenario: : adding new advertisement
✔ Given I am on the main page
✔ When I click the add advertisement button
ADD AD
✔ Then I should see the form to add an advertisement
1 scenario (1 passed)
3 steps (3 passed)
0m00.897s
你需要手动启动服务器,我不使用Webpack,但通常我这样做
const express = require('express');
const path = require('path');
const app = express();
const child_process = require('child_process');
const e2e = path.resolve(process.cwd(), './e2e-tests/config/');
const port = 5555;
const root = path.resolve(process.cwd(), './dist/prod/');
/**
* Start a server
*/
class Protractor {
server(port, dir) {
app.set('port', port);
app.use(express.static(dir));
return new Promise((resolve) => {
let server = app.listen(port, () => {
resolve(server);
});
});
}
}
/**
* Start server and then run protractor
*/
(() => {
process.env.LANG = 'en_US.UTF-8';
const child = child_process.exec('npm run e2e');
new Protractor()
.server(port, root)
.then((server) => {
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
// Stop the server if Protractor crashes or we're done testing
child.on('exit', () => {
server.close();
});
});
})();
我认为您也需要对您的应用执行此操作。 (我使用 ng-apimock 进行模拟)
https://gitlab.com/Saleniuk/simple-app
- 运行 命令:'npm install'
- 您可以使用命令 'npm run build' 提供应用程序,但您还必须在主机 selenium-standalone-chrome:4444 或 运行 selenium-server 上提供 selenium-server其他主机并更改量角器配置中的硒地址 'seleniumAddress'.
- 您还可以 运行 docker 和 'docker-compose up -d'。然后你必须像这样设置你的主机OS:
- 127.0.0.1 alex.local
- 127.0.0.1 selenium-standalone-chrome
我不知道它在其他系统上是如何工作的,但在 Mac 上你必须在 webpack 配置中设置你的实际主机 docker ip,如下所示:
devServer: {
contentBase: path.resolve(rootDir, 'dist'),
port: 3000,
host: '0.0.0.0',
disableHostCheck: true,
public: '172.24.0.1'
},
在 'public' 中你必须设置你的 docker 主机 ip。
然后你可以 运行 'npm run bdd:test' 得到 Angular not found 的错误。如果您对 运行 安装我的应用程序有任何问题,请写信给我。
我解决了这个问题。您所要做的就是 运行 一个在测试前包含您的应用程序的开发服务器。这适用于 webpack。我不知道如何 运行 使用 SystemJS 在量角器中开发服务器。如果你知道怎么做,请告诉我;)这是我的 protractor.conf.js:
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var webpackConfig = require('./webpack.config');
var deasync = require('deasync');
var ip = require('ip');
var server;
var port = 5000;
var baseUrl = 'http://' + ip.address() + ':' + port;
function writeScreenShot(data, filename) {
const stream = fs.createWriteStream(filename);
stream.write(new Buffer(data, 'base64'));
stream.end();
}
exports.config = {
seleniumAddress: 'http://selenium-standalone-chrome:4444/wd/hub',
baseUrl: baseUrl,
useAllAngular2AppRoots: true,
// directConnect: true,
// chromeOnly:true,
restartBrowserBetweenTests: true,
ignoreUncaughtExceptions: true,
beforeLaunch: () => {
var isServerReady = false;
var isBundleReady = false;
var compiler = webpack(webpackConfig, () => {
isBundleReady = true;
});
server = new WebpackDevServer(compiler, {});
server.listen(port, () => {
isServerReady = true;
});
deasync.loopWhile(() => !isServerReady || !isBundleReady);
},
afterLaunch: () => {
server.close();
},
capabilities: {
browserName: 'chrome',
},
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
specs: [
'./features/*.feature'
],
cucumberOpts: {
require: ['./features/step_definitions/*.ts'],
tags: [],
strict: false,
format: ["pretty", "json:report/json/cucumber_report.json"],
dryRun: false,
compiler: ["ts:ts-node/register"],
},
onPrepare: function () {
browser.ignoreSynchronization = true;
browser.manage().window().setSize(1366, 768);
}
};
- OS: macOS Sierra 10.12.4
- 节点:v7.9.0
- Npm: 5.0.3
- 黄瓜-js:2.3.0
- 量角器:4.0.14
- 打字稿:2.2.2
- webpack-开发服务器:2.4.5
我对 运行 端到端测试有疑问。当我尝试从页面获取元素时:
const el = browser.findElement(by.id('app-name'));
el.getText().then(function (text) {
console.log(text);
callback();
});
使用 'browser' 我得到这个错误:
> test-app@0.0.1 bdd:test /Users/p24/PhpstormProjects/alex-angular2
> node ./node_modules/.bin/protractor
(node:28198) DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[13:03:31] I/hosted - Using the selenium server at http://selenium-standalone-chrome:4444/wd/hub
[13:03:31] I/launcher - Running 1 instances of WebDriver
Feature: : adding an advertisement
@web-test
Scenario: : adding new advertisement
✔ Given I am on the main page
✔ When I click the add advertisement button
✖ Then I should see the form to add an advertisement
Failures:
1) Scenario: : adding new advertisement - features/adding_advertisement.feature:5
Step: Then I should see the form to add an advertisement - features/adding_advertisement.feature:8
Step Definition: features/step_definitions/advertisement.ts:32
Message:
Error: function timed out after 5000 milliseconds
at Timeout._onTimeout (/Users/p24/PhpstormProjects/alex-angular2/node_modules/cucumber/lib/user_code_runner.js:91:22)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
1 scenario (1 failed)
3 steps (1 failed, 2 passed)
0m05.026s
Cucumber HTML report report/html/cucumber_report_hierarchy.html generated successfully.
Modified files:
[13:03:47] E/protractor - Could not find Angular on page http://alex.local/ : retries looking for angular exceeded
[13:03:47] E/launcher - Angular could not be found on the page http://alex.local/. If this is not an Angular application, you may need to turn off waiting for Angular. Please see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load
[13:03:47] E/launcher - Error: Angular could not be found on the page http://alex.local/. If this is not an Angular application, you may need to turn off waiting for Angular. Please see https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular-on-page-load
at /Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/built/browser.js:506:23
at ManagedPromise.invokeCallback_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:1379:14)
at TaskQueue.execute_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2913:14)
at TaskQueue.executeNext_ (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2896:21)
at asyncRun (/Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:2775:27)
at /Users/p24/PhpstormProjects/alex-angular2/node_modules/protractor/node_modules/selenium-webdriver/lib/promise.js:639:7
at process._tickCallback (internal/process/next_tick.js:109:7)
[13:03:47] E/launcher - Process exited with error code 199
npm ERR! code ELIFECYCLE
npm ERR! errno 199
npm ERR! test-app@0.0.1 bdd:test: `node ./node_modules/.bin/protractor`
npm ERR! Exit status 199
npm ERR!
npm ERR! Failed at the test-app@0.0.1 bdd:test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/p24/.npm/_logs/2017-06-10T11_03_47_694Z-debug.log
这是我的 webpack.config:
'use strict';
const HtmlWebpack = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const extractPlugin = new ExtractTextPlugin({
filename: 'main.css'
});
const CleanWebpack = require('clean-webpack-plugin');
const rootDir = path.resolve(__dirname);
module.exports = {
devServer: {
contentBase: path.resolve(rootDir, 'dist'),
port: 3000,
host: '0.0.0.0',
disableHostCheck: true,
public: '172.23.0.1'
},
watchOptions: {
poll: true
},
devtool: 'source-map',
entry: {
"bundle": "./src/webpack.main.js",
"plugins": "./src/plugins.js"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
// publicPath: "/dist"
},
resolve: {
extensions: [ '.js', '.ts' ]
},
module: {
exprContextCritical: false,
rules: [
{
test: /\.html$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]'
},
},
{ loader: 'extract-loader' },
{ loader: 'html-loader' }
],
exclude: path.resolve(__dirname, 'src/index.html')
},
{
test: /\index.html$/,
loader: ['html-loader']
},
{
test: /\.ts$/,
loader: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(scss|css)$/,
use: extractPlugin.extract({
use: ['css-loader', 'sass-loader']
})
},
{
test: /\.(jpg|png|gif|eot|ttf|svg|woff|woff2)$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: 'img/'
}
}]
},
],
},
plugins: [
new CleanWebpack(['dist']),
extractPlugin,
new HtmlWebpack({
template: 'src/index.html'
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"Tether": 'tether'
})
],
};
我的protractor.config:
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
exports.config = {
seleniumAddress: 'http://selenium-standalone-chrome:4444/wd/hub',
baseUrl: 'http://alex.local',
capabilities: {
browserName:'chrome'
},
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
specs: [
'./features/*.feature'
],
cucumberOpts: {
require: ['./features/step_definitions/*.ts'],
tags: [],
strict: false,
format: ["pretty", "json:report/json/cucumber_report.json"],
dryRun: false,
compiler: ["ts:ts-node/register"]
},
onPrepare: function () {
browser.manage().window().maximize();
}
};
还有我的步骤定义文件出现错误的地方:
'use strict';
import {browser, element, by, By, $, $$, ExpectedConditions} from 'protractor';
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
const expect = chai.expect;
const {defineSupportCode} = require('cucumber');
defineSupportCode(function(context: any) {
const Given = context.Given;
const When = context.When;
const Then = context.Then;
Given('I am on the main page', function (callback: any) {
browser.get('http://alex.local');
callback();
});
When('I click the add advertisement button', function (callback: any) {
callback();
});
Then('I should see the form to add an advertisement', function (callback: any) {
const el = browser.findElement(by.id('app-name'));
el.getText().then(function (text) {
console.log(text);
callback();
});
});
});
export {};
docker 一切尽在掌握。 docker-compose.yml:
version: '2'
services:
proxy:
image: jwilder/nginx-proxy
container_name: nginx-proxy-alex
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
app:
build: .
command: npm run build
environment:
- NODE_ENV=development
- VIRTUAL_HOST=alex.local
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
ports:
- "8080:3000"
selenium-chrome:
image: selenium/standalone-chrome
environment:
- VIRTUAL_HOST=selenium-standalone-chrome
ports:
- "4444:4444"
请在第一个 describe
块内的规范文件中使用 browser.ignoreSynchronization = true;
,这样 Protractor 就不会等待 Angular.
我认为有 2 个 "problems"。
首先,您使用的是 Protractor 4。要使用 Protractor 4 测试 Angular 2,您需要在配置中使用 useAllAngular2AppRoots: true
,或者,如果可能,升级到量角器 5.1.2。这应该可以解决您的第二个 Angular 超时问题。
其次,这是您的第一次超时,您仍然有 5 秒的 CucumberJS 默认超时。如果它们花费的时间超过 5 秒,那将始终停止步骤。通过将此代码添加到文件中,您可以增加它。
// cucumber.config.js file
import { defineSupportCode } from 'cucumber';
defineSupportCode(({setDefaultTimeout}) => {
setDefaultTimeout(11000);
});
希望对您有所帮助。
更新:
只是为了消除不正确的量角器语法:
useAllAngular2AppRoots: true
在量角器 5 中不需要,只在 4 中需要,我的错是我没有提到- 使用 "correct" 语法在页面上查找元素是使用
element(by.id('app-name')
而不是browser.findElement(by.id('app-name'))
,您的语法是 "vanilla" webdriver 语法,无需等待 Angular
只需 1 个检查问题 - 您的初始页面真的是 Angular 页面吗?
测试项目后更新:
我试图 运行 你的项目,但我遇到了各种不同的错误。我无法使用提供的命令为项目提供服务
ERROR in Cannot read property 'getSymbolByModule' of undefined
ERROR in multi ./src/styles.scss
Module not found:...
我只是想 运行 你的测试看看会发生什么和一些奇怪的事情发生了。步骤 Given('I am on the main page')
成功,但未加载任何站点。然后我在你的 Then('I should see the form to add an advertisement')
上遇到了同样的超时。
查看您的步骤实施后,我认为这是初始错误,您需要在解决 browser.get()
时调用 callback
,或者 return 承诺,请参阅下面。
// Or resolve the callback
Given('I am on the main page', function(callback: any) {
browser.get('http://alex.local').then(callback);
});
// Or return a promise
Given('I am on the main page', function() {
return browser.get('http://alex.local');
});
如果您使用上述实现之一,我想您会发现问题出在第一步,而不是您以正确方式实现 callback
的 Then('I should see the form to add an advertisement')
。
运行应用后更新
现在可以使用了。用npm run build
(手动)。然后将 http://alex.local
更改为 http://localhost:3000
.
当我运行这个测试
Given('I am on the main page', function(callback: any) {
// browser.ignoreSynchronization = true;
browser.get('http://localhost:3000').then(callback);
});
When('I click the add advertisement button', function(callback: any) {
callback();
});
Then('I should see the form to add an advertisement', function(callback: any) {
const el = element(by.css('.btn.btn-default'));
el.getText().then(function(text) {
console.log(text);
callback();
});
});
成功了,你会得到这个日志
Feature: : adding an advertisement
@web-test
Scenario: : adding new advertisement
✔ Given I am on the main page
✔ When I click the add advertisement button
ADD AD
✔ Then I should see the form to add an advertisement
1 scenario (1 passed)
3 steps (3 passed)
0m00.897s
你需要手动启动服务器,我不使用Webpack,但通常我这样做
const express = require('express');
const path = require('path');
const app = express();
const child_process = require('child_process');
const e2e = path.resolve(process.cwd(), './e2e-tests/config/');
const port = 5555;
const root = path.resolve(process.cwd(), './dist/prod/');
/**
* Start a server
*/
class Protractor {
server(port, dir) {
app.set('port', port);
app.use(express.static(dir));
return new Promise((resolve) => {
let server = app.listen(port, () => {
resolve(server);
});
});
}
}
/**
* Start server and then run protractor
*/
(() => {
process.env.LANG = 'en_US.UTF-8';
const child = child_process.exec('npm run e2e');
new Protractor()
.server(port, root)
.then((server) => {
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
// Stop the server if Protractor crashes or we're done testing
child.on('exit', () => {
server.close();
});
});
})();
我认为您也需要对您的应用执行此操作。 (我使用 ng-apimock 进行模拟)
https://gitlab.com/Saleniuk/simple-app
- 运行 命令:'npm install'
- 您可以使用命令 'npm run build' 提供应用程序,但您还必须在主机 selenium-standalone-chrome:4444 或 运行 selenium-server 上提供 selenium-server其他主机并更改量角器配置中的硒地址 'seleniumAddress'.
- 您还可以 运行 docker 和 'docker-compose up -d'。然后你必须像这样设置你的主机OS:
- 127.0.0.1 alex.local
- 127.0.0.1 selenium-standalone-chrome
我不知道它在其他系统上是如何工作的,但在 Mac 上你必须在 webpack 配置中设置你的实际主机 docker ip,如下所示:
devServer: {
contentBase: path.resolve(rootDir, 'dist'),
port: 3000,
host: '0.0.0.0',
disableHostCheck: true,
public: '172.24.0.1'
},
在 'public' 中你必须设置你的 docker 主机 ip。
然后你可以 运行 'npm run bdd:test' 得到 Angular not found 的错误。如果您对 运行 安装我的应用程序有任何问题,请写信给我。
我解决了这个问题。您所要做的就是 运行 一个在测试前包含您的应用程序的开发服务器。这适用于 webpack。我不知道如何 运行 使用 SystemJS 在量角器中开发服务器。如果你知道怎么做,请告诉我;)这是我的 protractor.conf.js:
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var webpackConfig = require('./webpack.config');
var deasync = require('deasync');
var ip = require('ip');
var server;
var port = 5000;
var baseUrl = 'http://' + ip.address() + ':' + port;
function writeScreenShot(data, filename) {
const stream = fs.createWriteStream(filename);
stream.write(new Buffer(data, 'base64'));
stream.end();
}
exports.config = {
seleniumAddress: 'http://selenium-standalone-chrome:4444/wd/hub',
baseUrl: baseUrl,
useAllAngular2AppRoots: true,
// directConnect: true,
// chromeOnly:true,
restartBrowserBetweenTests: true,
ignoreUncaughtExceptions: true,
beforeLaunch: () => {
var isServerReady = false;
var isBundleReady = false;
var compiler = webpack(webpackConfig, () => {
isBundleReady = true;
});
server = new WebpackDevServer(compiler, {});
server.listen(port, () => {
isServerReady = true;
});
deasync.loopWhile(() => !isServerReady || !isBundleReady);
},
afterLaunch: () => {
server.close();
},
capabilities: {
browserName: 'chrome',
},
framework: 'custom',
frameworkPath: require.resolve('protractor-cucumber-framework'),
specs: [
'./features/*.feature'
],
cucumberOpts: {
require: ['./features/step_definitions/*.ts'],
tags: [],
strict: false,
format: ["pretty", "json:report/json/cucumber_report.json"],
dryRun: false,
compiler: ["ts:ts-node/register"],
},
onPrepare: function () {
browser.ignoreSynchronization = true;
browser.manage().window().setSize(1366, 768);
}
};