6.9.1
5.1.2
4.0.0
Chrome Version 57.0.2987.133 (64-bit)
OS X Version 10.10.5 (14F2315)
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/docs/referenceConf.js
/* Third-party */
let HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
let JUnitXmlReporter = require('jasmine-reporters').JUnitXmlReporter;
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;
/* Custom */
let setup = require('./e2e/setup/setup');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./e2e/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
SELENIUM_PROMISE_MANAGER: false,
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
useAllAngular2AppRoots: true,
beforeLaunch: function() {
require('ts-node').register({
project: 'e2e'
});
},
onPrepare: function() {
jasmine.getEnv().addReporter(new SpecReporter());
jasmine.getEnv().addReporter(new JUnitXmlReporter({
consolidateAll: true,
savePath: browser.params.output || 'protractor/log',
filePrefix: 'protractor_output'
}));
jasmine.getEnv().addReporter(new HtmlScreenshotReporter({
cleanDestination: true,
dest: 'protractor/log',
filename: 'index.html'
}));
setup();
}
};
import { browser } from 'protractor';
import { A2Page } from './app.po';
import { NavPartial } from './nav/nav.po';
import { SettingsPage } from './settings/settings.po';
import { Utils } from './utils';
let utils = new Utils();
describe('a2 root', function() {
let page: A2Page = new A2Page();
let navPartial: NavPartial = new NavPartial();
let settingsPage: SettingsPage = new SettingsPage();
it('should be able to navigate to', () => {
return page.navigateTo();
});
it('should take user to Settings', () => {
return settingsPage.getTitle().then(title => {
return expect(title).toEqual('Title');
}).then(() => {
return settingsPage.getSubtitle();
}).then(subtitle => {
return expect(subtitle).toEqual('Subtitle');
});
});
it('should have a Home menu', () => {
return page.navigateTo().then(() => {
return navPartial.isHomePresent();
}).then(present => {
return expect(present).toBeTruthy();
});
});
it('should have an Info menu', () => {
return page.navigateTo().then(() => {
return navPartial.isInfoPresent();
}).then(present => {
return expect(present).toBeTruthy();
});
});
});
$ npm run e2e -- --params.baseUrl 'https://myurl'
> [email protected] pree2e /Users/me/a2
> webdriver-manager update
[13:56:14] I/update - chromedriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: unzipping chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29
[13:56:14] I/update - chromedriver: chromedriver_2.29 up to date
[13:56:14] I/update - selenium standalone: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar
[13:56:14] I/update - selenium standalone: selenium-server-standalone-3.4.0.jar up to date
[13:56:14] I/update - geckodriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: unzipping geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1
[13:56:14] I/update - geckodriver: geckodriver-v0.16.1 up to date
> [email protected] e2e /Users/me/a2
> $(npm bin)/protractor "--params.baseUrl" "https://myurl"
[13:56:16] I/launcher - Running 1 instances of WebDriver
[13:56:16] I/direct - Using ChromeDriver directly...
Spec started
a2 root
โ should be able to navigate to
โ should take user to Settings
โ should have a Home menu
โ should have an Info menu
- Failed: EPIPE write EPIPE
**************************************************
* Failures *
**************************************************
1) a2 root should have an Info menu
- Failed: EPIPE write EPIPE
Executed 4 of 4 specs (1 FAILED) in 22 secs.
[13:56:41] I/launcher - 0 instance(s) of WebDriver still running
[13:56:41] I/launcher - chrome #01 failed 1 test(s)
[13:56:41] I/launcher - overall: 1 failed spec(s)
[13:56:41] E/launcher - Process exited with error code 1
npm ERR! Darwin 14.5.0
npm ERR! argv "/Users/me/.nvm/versions/node/v6.9.1/bin/node" "/Users/me/.nvm/versions/node/v6.9.1/bin/npm" "run" "e2e" "--" "--params.baseUrl" "https://myurl"
npm ERR! node v6.9.1
npm ERR! npm v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! [email protected] e2e: `$(npm bin)/protractor "--params.baseUrl" "https://myurl"`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] e2e script '$(npm bin)/protractor "--params.baseUrl" "https://myurl"'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the a2 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR! $(npm bin)/protractor "--params.baseUrl" "https://myurl"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR! npm bugs a2
npm ERR! Or if that isn't available, you can get their info via:
npm ERR! npm owner ls a2
npm ERR! There is likely additional logging output above.
npm ERR! Please include the following file with any support request:
npm ERR! /Users/me/a2/npm-debug.log
๋ํ npm-debug.log์์ ๋ฐ์ท:
18 verbose stack Exit status 1
18 verbose stack at EventEmitter.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/lifecycle.js:255:16)
18 verbose stack at emitTwo (events.js:106:13)
18 verbose stack at EventEmitter.emit (events.js:191:7)
18 verbose stack at ChildProcess.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/spawn.js:40:14)
18 verbose stack at emitTwo (events.js:106:13)
18 verbose stack at ChildProcess.emit (events.js:191:7)
18 verbose stack at maybeClose (internal/child_process.js:877:16)
18 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
SELENIUM_PROMISE_MANAGER: false
๋ฅผ ์ค์ ํฉ๋๋ค(์ ์ด ํ๋ฆ ๋นํ์ฑํ).Failed: EPIPE write EPIPE
์ค๋ฅ๊ฐ ์๊ธฐ์น ์๊ฒ ๋ฐ์ํ๊ธฐ ์์ํ ๊ฒ์
๋๋ค.๋๋ ๋๊ธฐ๋ฅผ ์ฌ์ฉํ์ง ์์ต๋๋ค. ํ ์คํธ ์ฝ๋์์๋ ์ฒ๋ฆฌ๋์ง ์์ ์ฝ์์ ์๋ณํ ์ ์์ต๋๋ค(์ฝ์ ๊ฒฝํ์ด ์์). ์ผ๋ถ ์ฃผ์์์ ์ ์ํ ๋ด์ฉ์ด๋ฏ๋ก ๊ทธ ๊ฐ๋ฅ์ฑ์ ํ์ฉํด์ผ ํฉ๋๋ค. ๊ทธ๋๋ ์ฒ๋ฆฌ๋์ง ์์ ์ฝ์์์ ๋ ธ๋๊ฐ ์ถฉ๋ํ๋ ๊ฒ์ ๋๋ผ์ด ์ผ์ ๋๋ค. ๊ทธ๋์ ์ฌ๊ธฐ ์ด๋๊ฐ์ ๋ ธ๋ ๋ฒ๊ทธ๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. ๋ด ํ ์คํธ๋ ๊ฐ๋๊ธฐ ๋๋ ์น ๋๋ผ์ด๋ฒ ๋ฑ์ ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค.
์ฃ์กํฉ๋๋ค. ๊ณต๊ฐ๋์ง ์์ต๋๋ค.
์ ๋ ์ด๊ฑฐ ๊ฝค ์์ฃผ ์ ํ์ต๋๋ค. Chrome์ด ๋ฐฑ๊ทธ๋ผ์ด๋์ ์์ ๋ ๋ ์์ฃผ, ์๋ง๋ ๋ ์ ์ ์ผ๋ก ๋ฐ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ฅ ์ฐ์ฐ์ผ์ง๋ ๋ชฐ๋ผ
์, ์ ๋ ์ด ๋ชป์๊ธด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค!
๋ต๋ณ์ด ๋ฆ์ด ์ฃ์กํฉ๋๋ค. ๋๋ ์ด๊ฒ์ ์ฌํํ์ง ๋ชปํ์ต๋๋ค. ์ด๋ฅผ ์ฌํํ๋ Angular 2 ์ฑ์ ์์ ์์ ์ ์ฅ์(https://github.com/NickTomlin/protractor-mcve๋ฅผ ์คํํฐ๋ก ์ฌ์ฉํ ์ ์์)๋ฅผ ์ ๊ณตํ ์ ์์ต๋๊น?
์ ์ด ํ๋ฆ์ ์ ๊ฑฐํ๋ ๊ฒ์ ์ฌ๋ฐ๋ฅธ ๋ฐฉํฅ์ผ๋ก ๊ฐ๋ ๋จ๊ณ์ด์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ค๋ช ํด์ผ ํ ๋ช ๊ฐ์ง ๋ฌธ์ (์: ์ด์ ๊ฐ์)๊ฐ ๋๋ฌ๋ ์ ์์ต๋๋ค. ๊ฐ์ฌ ํด์!
@NickTomlin @wcainboundary ๋ฐฉ๊ธ nodejs๋ฅผ ์ต์ ์์ ๋ฒ์ ์ผ๋ก ์ ๊ทธ๋ ์ด๋ํ๋๋ฐ ์ด์ ์ ๋๋ก ์๋ํฉ๋๋ค.
์๋ํ์ง ์์:
$node -v
v6.10.1
์ ์๋ํฉ๋๋ค:
$node -v
v7.10.0
๋ ธ๋ v8.0.0์์ ์ค๋ฅ๊ฐ ํ์๋ฉ๋๋ค.
๋๋ ๋ํ ์ด ์ค๋ฅ๊ฐ _without_ ๊ฐ๋๊ธฐ(์ง์ [email protected]์ด๊ณ ๋๋ ๊ทธ ์ ์ 3.3์ ๋ฏฟ์ต๋๋ค)๋ฅผ ๋ณด๊ณ ์์ต๋๋ค. OS X์์๋ ๋ฐ์ํ์ง ์์ง๋ง ๋น๋ ์์ด์ ํธ(Linux)์์๋ ๋งค์ฐ ์์ฃผ ๋ฐ์ํฉ๋๋ค.
๋๋ ์ด ๋ฌธ์ ๊ฐ Selenium์ ๋ํด ์ ๊ธฐ๋ ๊ฒ์ ๋ณธ ์ ์ด ์์ง๋ง ์๋ง๋ ๊ทธ๋์ผ ํ ๊ฒ์ ๋๋ค.
OSX์์ ์ด ์ค๋ฅ๋ฅผ ๋ณธ ์ ์ด ์์ต๋๋ค.
๋์๊ฒ ๋ฌธ์ ๋ ํ์ด๋ฐ๊ณผ ๊ด๋ จ๋ ๊ฒ์ด์๋ค. ๋ด ํ ์คํธ๋ ์ฌ์ฉํ ์ ์๋ ์์์ ์ํธ ์์ฉํ๋ ค๊ณ ํ์ต๋๋ค. ๊ฐ๋ ์์ ์ด ์๋ฃ๋์์ง๋ง ํ์ด์ง์ ์ผ๋ถ ๋ ๋๋ง์ด ์๋ฃ๋์ง ์์ ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ฐ๊ฒฐ์ด ๋๋ ธ๊ธฐ ๋๋ฌธ์ ํธ์คํ ๊ทธ๋ฆฌ๋์์ ์ฌํํ๊ธฐ๊ฐ ๋ ์ฌ์ ์ต๋๋ค.
๋๋ waitForAngularEnabled๊ฐ true์ false๋ก ์ค์ ๋์ด ์๋ ๊ฒ์ ๋ณด์์ต๋๋ค.
์ ๊ทธ๋ ์ด๋ํ๊ธฐ ์ ์ ๋์ผํ ํ ์คํธ ์ค ์ผ๋ถ์์ ์๊ฐ ์ด๊ณผ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. Webdriver 3.x๊ฐ ๊ฐ์ ๊ฒ์ ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ๋งํ๋ ๊ฒ์ธ์ง ๊ถ๊ธํฉ๋๋ค...
์ด์ ๋ํด +1, ๋ด ์ฌ์์ OS X 10.12.5์์ ๋ก์ปฌ๋ก ์คํํ ๋ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ทธ๋งํ ๊ฐ์น๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋ค์์์ EPIPE ์ค๋ฅ๋ฅผ ๋ณผ ๊ฐ๋ฅ์ฑ์ด ์ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ด๊ฐ _๊ฐ๋ฅ์ฑ์ด ๊ฑฐ์ ์์_์ด๋ผ๊ณ ๋งํ๋ ๊ฒ์ ์์ ๊ตฌ์ฑ์ผ๋ก ์ ํ๊ตฐ์ 7๋ฒ ์คํํ์ ๋ Chrome ๋ธ๋ผ์ฐ์ ์ ์ฆ์ ์ด์ ์ ๋ง์ถ๊ณ Chrome ๋ ์์ด์ฝ์์ ๋ง์ฐ์ค๋ฅผ ์์ง์ด์ง ์์ผ๋ฉด ์คํ ์ค 4๋ฒ์ด ์ฑ๊ณตํ๋ค๋ ์๋ฏธ์ ๋๋ค(์๋ง๋ ๊ด๋ จ ์์).
์ฐ๋ฆฌ ํ๋ก์ ํธ์์ EPIPE
์ค๋ฅ๊ฐ ๋ํ๋ฌ์ต๋๋ค. ์๋ํ๋ฉด (TypeScript์์) ํ
์คํธ๊ฐ await
๋ฅผ ์๋ชป ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
๋๋ค. ๋ฐ๋ผ์ ์ฒ๋ฆฌ๋์ง ์์ Promise ๊ฑฐ๋ถ๊ฐ ๋ฌด์์๋ก ๋ฐ์ํ์ฌ ์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์๋ชป๋ ์ฌ์ฉ๋ฒ์ ์์ ํ๋ฉด ๋
ธ๋ 8์์ ๋ ์ด์ ์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.
await
์ ์๋ชป๋ ์ฌ์ฉ(๋๋ฝ ๋๋ ์ค๋ณต) ๋๋ ์๋ชป๋ Promise ์ฐ๊ฒฐ(์: ๋์ฐ๋ฏธ ๋ฉ์๋์์ Promise๋ฅผ ๋ฐํํ๋ ๊ฒ์ ์์์ ๋)์ ๋ํด ํ
์คํธ๋ฅผ ์ฃผ์ ๊น๊ฒ ํ์ธํ์ญ์์ค. ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ธ ์ค๋ฅ๋ ๋ค์์ ์ฌ์ฉํ์ต๋๋ค.
browser.wait(await EC.invisibilityOf(fade)); // incorrect
๋์ ์:
await browser.wait(EC.invisibilityOf(fade)); // correct
์๋ง๋ ์ด ๋ฌธ์ ๊ฐ ์๋ ๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋ ๊ฒ์ ๋๋ค.
์ด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์์ต๋๊น? ์ฌ์ ํ ๋ ธ๋ ๋ฒ์ 7.7.3 ๋ฐ ๊ฐ๋๊ธฐ ๋ฒ์ 5.1.1์์ ๋ณผ ์ ์์ต๋๋ค.
@ sri1987 ์์ ๋ด ์๊ฒฌ์ ์ฐธ์กฐํ์ญ์์ค. ๊ฐ๋๊ธฐ๊ฐ ์๋ ์ฝ๋์ ๋ฌธ์ ์ผ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
@sri1987 ์ผ๊ด๋๊ฒ ์ฌํํ ์ ์๋ ๊ฒฝ์ฐ ์ด๋๊ฐ์ ๋๋ฝ/์ถ๊ฐ await
๊ฐ ์๋ ๊ฒ๊ณผ ๊ด๋ จ์ด ์์ต๋๋ค.
์ต๊ทผ SELENIUM_PROMISE_ MANAGER:false ์์ ์ด๋ฌํ ์ค๋ฅ๊ฐ ์์ฃผ ๋ฐ์ํ์ต๋๋ค.
์ฌ๋ฌ ํ
์คํธ๋ฅผ ์คํํ ๋
์ฌ๊ธฐ์ #4507์ ๋ฌธ์ ๋ ๋์ ์น ๋๋ผ์ด๋ฒ ๋ช
๋ น์ธ ๊ฒ ๊ฐ์ต๋๋ค. @wvanderdeijl ์ #4508์์ ElementArrayFinder::map()
์ ํน์ ๊ฒฝ์ฐ์ ๋ํ ์๋ฃจ์
์ ์ ์ํ์ต๋๋ค. ์ด ๋ฌธ์ ๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ํด๊ฒฐ๋ ๋๊น์ง ๋์ ์น ๋๋ผ์ด๋ฒ ๋ช
๋ น์ด ์คํ๋๋ ๊ฒ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋๊ธฐ์ด์ ์์ฑํ๋ browser.driver.schedule()
์ ๋ํ ๋ค์ ๋ํผ๊ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ ์ ์์ต๋๋ค.
EPIPE ์ค๋ฅ๋ฅผ ๊ฒช๊ณ ์๋ ์ฌ๋์ด ์ ๊ธฐ์ ์ผ๋ก ์ด๊ฒ์ ํ ์คํธํ ์ ์์ต๋๊น? ํ ์คํธ ์คํ์ด ์ด๋ ์ ๋ ๋๋ ค์ง ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด ๋ค์ ์ฝ๋๋ ๊ฐ๋๊ธฐ์ onPrepare()
ํํฌ์์ ํธ์ถํ ์ ์์ต๋๋ค.
let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
currentCommand = currentCommand.then(() =>
webdriverSchedule.call(browser.driver, command, description)
);
return currentCommand as any;
}
๋๋ ์ผ๋ถ ์ถ๊ฐ ๋ก๊น :
let currentCommand = Promise.resolve();
let concurrencyCounter = 0;
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
console.log(`${++concurrencyCounter} concurrent webdriver command(s). Latest command: ${description}`);
currentCommand = currentCommand.then(() =>
webdriverSchedule.call(browser.driver, command, description)
.then(result => {
concurrencyCounter--;
return result;
})
.catch(error => {
concurrencyCounter--;
//console.lgErrLabel('Webdriver error')(command, description, error);
console.error('Webdriver error:', command, description, error);
throw error;
})
);
return currentCommand as any;
}
@renehamburger
๋๋ ๋น์ ์ด ๊ฑฐ๊ธฐ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ๋๋ถ๋ถ์ ์ค๋ฅ๊ฐ Promise.all ํธ์ถ์ ๋ฐํํ๋ ํจ์์์ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋์์ฑ๊ณผ ๊ด๋ จ์ด ์์ ๊ฒ์ด๋ผ๊ณ ํ์ ํฉ๋๋ค.
@renehamburger ๊ฐ์ฌํฉ๋๋ค. ๋ด protractor.conf.js์ onPrepare ์น์ ์ ์ด๊ฒ์ ์ถ๊ฐํ ํ:
let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command, description) => {
currentCommand = currentCommand.then(() =>
webdriverSchedule.call(browser.driver, command, description)
);
return currentCommand;
};
์ค๋ฅ '์คํจ: EPIPE ์ฐ๊ธฐ EPIPE'๊ฐ ์ฌ๋ผ์ก์ต๋๋ค.
@Xaz16 : ํด๊ฒฐ ๋ฐฉ๋ฒ์ผ๋ก ์ฐ๋ฆฌ๋ฅผ ์ํด ์ผํ์ต๋๋ค. ๊ฐ์ฌํฉ๋๋ค!
๊ทธ๋ฌ๋ "EPIPE write EPIPE" ์ค๋ฅ๋ Selenium์ ๋ฒ๊ทธ์ธ ๊ฒ ๊ฐ์ต๋๋ค( https://github.com/SeleniumHQ/selenium/issues/5345 ). ์ด๋ 4.0.0์์ ํด๊ฒฐ๋ ๊ฒ์ ๋๋ค.
๋ฐ๋ผ์ ๊ฐ๋๊ธฐ๊ฐ 4.0.0 ๋ฒ์ ์ ์ฌ์ฉํ ๋๊น์ง ๊ธฐ๋ค๋ ค์ผ ํ๋ฉฐ ์ด ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๊ฑฐํ ์ ์์ต๋๋ค.
Protractor
๋ก๋๋งต์ ๋ํ ๋งํฌ๊ฐ ์์ต๋๊น? ์๋๋ฉด ์์ ์กด์ฌํ์ง ์๋๋ค.
@renehamburger , ๋์์ฃผ์๊ฒ ์ต๋๊น? SELENIUM_PROMISE_MANAGER: false
๊ฒฝ์ฐ์ ๋๋นํ์ฌ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ค์ ์์ฑํ๋ ค๊ณ ํฉ๋๋ค. ํ์ฌ ๊ทํ์ ์๋ฃจ์
์ ๋ณต์ฌ/๋ถ์ฌ๋ฃ๊ธฐ๋ง ํ๋ฉด async/await
๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ ์ ์๋ค๊ณ ์๊ฐํ๋ ์ด์ํ ๋ฌธ์ ๊ฐ ๋ง์ด ์์ต๋๋ค.
@CrispusDH ์ฝ๋ ์ค๋ํซ์ ๋ค์์ผ๋ก ๋ณ๊ฒฝํด์ผ ํ์ต๋๋ค.
let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.schedule;
browser.schedule = (command, description) => {
currentCommand = currentCommand.then(() =>
webdriverSchedule.call(browser, command, description)
);
return currentCommand;
};
๋ฐ๋ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก .driver
๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
Async/await๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ controlFlow๋ณด๋ค ๋ ํฐ ํผ๋์ธ ๊ฒ ๊ฐ์ต๋๋ค.
์์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋ํ ํ์๋ Mac OS Sierra์์ ์ค๋ฅ๊ฐ ๊ณ์ ๊ด์ฐฐ๋ฉ๋๋ค.
์๋ ํ ์์๋ ๋ค๋ฅธ ์๋ฃจ์ ์ด ์์ต๋๊น?
๊ฐ์ฌ ํด์
์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ์ผ๋ถ ์ฃผ์ฅ์์ async/await๋ฅผ ์๋ชป ์ฌ์ฉํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด๊ฒ์ ๊ฐ์ง๊ณ :
const modal = await page.getModalInfo()
expect(modal.isDisplayed()).toBeTruthy()
๋์ ์:
const modal = page.getModalInfo()
expect(await modal.isDisplayed()).toBeTruthy()
์๋
ํ์ธ์ @danigar ํจ์ isDisplayed()
๋ ์ฝ์์ ๋ฐํํ๋ฏ๋ก ์ด๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด await๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ํ์์ ์
๋๋ค. ๋ฐ๋ผ์ ๋ ๋ฒ์งธ ์์ ์ ๋ ๋ฒ์งธ ์ฝ๋ ์ค์ ๊ด์ฐฎ์ ๋ณด์
๋๋ค.
์ฒซ ๋ฒ์งธ ์ค์ await
๋ getModalInfo()
๋ฐํ ๊ฐ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. ํ์ฌ๋ก์๋ ๋ถ๋ช
ํํ๊ณ 1ํ๊ณผ 2ํ์ ์ฐ๊ฒฐ์ด ๋ณด์ด์ง ์์ต๋๋ค.
@marcincharezinski jasmine
๋ await
Promise
in except()
๋ฅผ ์ค์ค๋ก ํด๊ฒฐํฉ๋๋ค.
๋ค. @marcincharezinski ์ง์ฐ์ ๋ํด ์ฃ์กํฉ๋๋ค. ์ฒซ ๋ฒ์งธ ์ค์ getModalInfo()
๋ฉ์๋๋ ElementFinder(Promise๋ก ๋ํ๋์ง ์์)๋ฅผ ๋ฐํํ์ผ๋ฉฐ ์ฒซ ๋ฒ์งธ ์์ ์์ ๋ณผ ์ ์๋ฏ์ด awaiting
์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์ด์ ๊ฐ์ ๋ช ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์๊ณ ๊ทธ๊ฒ์ ์์ ํ๋ฉด EPIPE ์ค๋ฅ๊ฐ ์ฌ๋ผ์ก์ต๋๋ค ๐.
@CrispusDH - ์ดํดํ ์ ์๋ ์ด์ ๋ก ์คํจํ ํ
์คํธ์ ๋ํ ๋ฌธ์ ๊ฐ ๊ณ์ ๋ฐ์ํ ๋๊น์ง ๊ฐ์ ์๊ฐ์ ํ๊ณค ํ์ต๋๋ค. ๋์๊ฐ์ except()
๋ช
์ธ์ ์์ await
๋ฅผ ์ถ๊ฐํ๊ณ ์ ๋ฆฌํ์ต๋๋ค.
@Mokkapps ์ ์ด๋ TypeScript์์๋ ์ฝ๋์์ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ ํ '
'์ฝ์ ๋ฌดํจ' ์ ํ์ '์ฝ์ T' ์ ํ์ ํ ๋นํ ์ ์์ต๋๋ค.
'์ฝ์ ๋ฌดํจ' ์ ํ์ '์ทจ์' ์์ฑ์ด ์์ต๋๋ค.
@kahan002
์ด ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ง์นจ๋ด ํด๊ฒฐํ์ต๋๋ค.
function patchSchedule() {
if (os.platform() === 'darwin') {
let currentCommand = Promise.resolve();
let concurrencyCounter = 0;
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
currentCommand = currentCommand.then(() =>
webdriverSchedule
.call(browser.driver, command, description)
.then(result => {
concurrencyCounter--;
return result;
})
.catch(error => {
concurrencyCounter--;
// tslint:disable-next-line:no-console
console.error('Webdriver error:', command, description, error);
throw error;
})
);
return currentCommand as any;
};
}
}
protractor.conf.ts์์ ํธ์ถ๋๋
onPrepare: () => {
patchSchedule();
},
๊ณต์ ํด ์ฃผ์
์ ๊ฐ์ฌ ํฉ๋๋ค @Mokkapps . ๋๊ตฐ๊ฐ๊ฐ typeScript ๋ฐ ๋์ ๊ฐ์ ํ๊ฒฝ์ ๋ง๊ฒ ์กฐ์ ํ๋ ค๋ ๊ฒฝ์ฐ์ ๋๋นํ์ฌ ๋ช ๊ฐ์ง ์ฐธ๊ณ ์ฌํญ์
๋๋ค. os.platform()
๊ฐ ์๋ ค์ง์ง ์์์ process.platform
๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๋๋ import { Command } from "selenium-webdriver";
ํด์ผ ํ์ต๋๋ค. concurrencyCounter๋ ์ฝ์ง ์์๊ธฐ ๋๋ฌธ์ ์ฃผ์ ์ฒ๋ฆฌํด์ผ ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์์์ any์ ๋ํ typeScript ๊ฒฝ๊ณ ๊ฐ ์์ผ๋ฏ๋ก .then((result : any) => {
๋ฐ .catch((error: any) => {
์์ ๋ช
์์ ์ผ๋ก ๋ง๋ค์ด์ผ ํ์ต๋๋ค. ๋๋ ์ฝ๋์ ๋ํด ๋ถํํ์ง ์๊ณ ๋น์ ์ด ๊ทธ๊ฒ์ ๊ณต์ ํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค(๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๊ฒ ๊ฐ์ง๋ง ๊ฐํ์ ์ด์ด์ ๋งํ๊ธฐ๊ฐ ์กฐ๊ธ ์ด๋ ต์ต๋๋ค). ์ด ๋๊ธ์ด ๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋๊ธฐ๋ฅผ ๋ฐ๋๋๋ค. ์ ์ ๋ค๋ฅธ ์ฌ๋๋ค์๊ฒ ๋ค์ ์ฐพ์์ฃผ์
์ ์ ๋ง ๊ฐ์ฌํฉ๋๋ค.
ํ์ง๋ง UnhandledPromiseRejectionWarning: Unhandled Promise Rejection (rejection id: 4): Error: EPIPE write EPIPE
(node:8514) [DEP0018] DeprecationWarning: ์ฒ๋ฆฌ๋์ง ์์ ์ฝ์ ๊ฑฐ๋ถ๋ ๋ ์ด์ ์ฌ์ฉ๋์ง ์์ต๋๋ค. ์์ผ๋ก ์ฒ๋ฆฌ๋์ง ์์ ์ฝ์ ๊ฑฐ๋ถ๋ 0์ด ์๋ ์ข
๋ฃ ์ฝ๋๋ก Node.js ํ๋ก์ธ์ค๋ฅผ ์ข
๋ฃํฉ๋๋ค.
๊ฒฐ๊ตญ. ๋์๊ฐ์ await
๋ฅผ ์๋ชป ์ฌ์ฉํ๊ณ ์๋ ๊ณณ์ ํ์ธํ๊ฒ ์ต๋๋ค.
OSX ์ฌ์ฉ์๋ฅผ ์ํ ์ง์ ์ฌํญ์ด ์์ต๋๊น?
์ด๊ฒ์ ๋ค๋ฅธ ์ ์ฌํ ์ค๋ฅ์ ๋์ผํ ์ํฉ์ ์ํด ์ ๋ฐ๋ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ์์ ์ฌํญ์ Selenium Node ์ฝ๋์ ๋ธ๋ผ์ฐ์ ๊ฐ์ ํต์ ์์ HTTP ์ฐ๊ฒฐ ์ ์ง๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์๋ ์ Selenium ๋ฉ์ธ ๋ผ์ธ์ ์ด์ ๋ํ ์์ ์ฌํญ์ด ์์ง๋ง ํด๋น ์ฝ๋์ ์ด๋ค ๋ฒ์ ์๋ ๊ฒ์๋์ง ์์์ต๋๋ค.
์ฌ๊ธฐ์์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๋ค๋ฅธ ๋ ผํ์๊ฐ ๋ค๋ฅธ ํธ์ ์ด ๋ด์ฉ์์ ์ฐจ์ฉํ๊ณ ํธ์งํ์ต๋๋ค. NPM package.script๋ฅผ ์ค์ ํ์ฌ ์คํํฉ๋๋ค.
"scripts": {
"install": "webdriver-manager update && node keep-alive-patch.js",
ํจ์ฒ ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
const fs = require('fs');
const chromeFile = 'node_modules/selenium-webdriver/chrome.js';
fs.readFile(chromeFile, 'utf8', function (err, data) {
if (err)
throw err;
const result = data.replace(/new http.HttpClient\(url\)/g,
"new http.HttpClient(url, new (require('http').Agent)({ keepAlive: true }))");
console.log(`Patching ${chromeFile}`);
fs.writeFileSync(chromeFile, result, 'utf8');
});
์ด ํจ์น๋ฅผ ํตํด Protractor๋ SELENIUM_PROMISE_MANAGER: false
๋ฅผ ์ฌ์ฉํ์ฌ Windows์ OSX ๋ชจ๋์์ 99% ์ด์ ๊ฐ๋ ฅํฉ๋๋ค. EPIPE ์ค๋ฅ๊ฐ ๋น์ฌ์ ๋์ผํ ๊ธฐ๋ณธ ์ํฉ์์ ๋ฐ์ํ๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ๋ง์ผ๋ฆฌ์ง๊ฐ ๋ค๋ฅผ ์ ์์ต๋๋ค.
์ฒด์ธ(๋๋ ์ด๋ ์ด ์ด์)์ผ๋ก ๋๊ธฐํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ทจ์ฝํ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค. ์๋ฅผ ๋ค์ด let testFormatID: string =await element.all(by.className('ng-star-inserted')).all(by.tagName('td')).get(1)์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. getText(); ์ค๋ฅ๊ฐ ๋ด ๊ฒ์ด๊ณ ๋ด๊ฐ ์์ฑํ ๊ฒ์ด ์๋ํ์ง ์์์ผ ํ ์๋ ์์ต๋๋ค.
#4792 ๊ฐ Mac OS X์์ ๋ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ ๊ฐ์ต๋๋ค. IgorDorokhov๋, ํ ๊ฐ์ฌํฉ๋๋ค.
@kahan002 ์ฒ๋ง์์ !
๊ฐ๋๊ธฐ์ ํฌํจ๋ 4.0.0-alpha.1์ ๋ํ ETA๊ฐ ์์ต๋๊น?
Failed: EPIPE write EPIPE
์ค๋ฅ 5/5๊ฐ ๊ณ์ ๋ฐ์ํฉ๋๋ค.$$('classified-section').filter((section) => section.isDisplayed())
[email protected]
๋ก ์
๊ทธ๋ ์ด๋ํ์ญ์์ค. ๊ฑฐ๊ธฐ์ ํด๊ฒฐ์ด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
@demisx ๋๋ ๊ทธ๊ฒ์ ์ฌ๊ธฐ์์ ํจ์นํ๊ณ ๊ทธ๊ฒ์ ๋๋ฅผ ์ํด ์๋ํฉ๋๋ค
@rafalf ๊ฐ์ฌํฉ๋๋ค. "selenium-3.7.0์์ index.js ๋ฅผ ๊ฐ์ ธ์ค๊ณ ECONNREFUSED๋ฅผ ์ถ๊ฐํ๋ ๊ฒ"์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์๋ค๋ฉด ์๋ํด ๋ณด์์ง๋ง ์ฌ์ ํ ๊ฐ๋ ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ ๊ฐ ๋๊ธ์ ์๋ชป ์ดํดํ๋ค๋ฉด ์๋ ค์ฃผ์ธ์.
EPIPE ์ค๋ฅ๋ MacOS Mojave์ ์ต์ ๊ฐ๋๊ธฐ 5.4.1, chromedriver_2.43 ๋ฐ async/await์์ ์ฌ์ ํ ์์ฃผ ๋ฐ์ํฉ๋๋ค. ๋ ์ด์ CI์์ E2E ์ฌ์์ ์คํํ ์ ์์ต๋๋ค. ๋ชจ๋ ํต๊ณผํ ๋๊น์ง ์๋์ผ๋ก ์ฌ๋ฌ ๋ฒ ์คํํฉ๋๋ค. ๋งค์ฐ ๋ถ์์ ํฉ๋๋ค.
@demisx
์ด๊ฒ์ ์ฃผ๋ก each
, filter
๋ฐ iwth ๋ฐฐ์ด์์ ์ฌ์ฉ๋๋ ๊ธฐํ ๊ธฐ๋ฅ์ ๋ํด ๋ฐ์ํฉ๋๋ค.
๋ด๊ฐ ๊ทธ๊ฒ์ ์ฌ ์์ ํ ๋ฐฉ๋ฒ
// EPIPE write EPIPE
// await $$("short-list-component.ng-valid mat-label").each(async function (element) {
// labels.push(await element.getText())
// });
// this.logInfo("getMatLabels: " + labels);
// return labels
let l = await $$("q-short-list-component.ng-valid mat-label");
for (let element of l){
text = await element.getText();
labels.push(text)
}
@rafalf ์, ๊ทธ๊ฒ์ด ์ฐ๋ฆฌ๊ฐ ์ ๊ฑฐํ ์ฒซ ๋ฒ์งธ ๊ฒ์ด์์ต๋๋ค. EPIPE ์ค๋ฅ์ ๋น๋๋ฅผ ์ค์์ง๋ง ์์ ํ ์ฌ๋ผ์ง์ง๋ ์์์ต๋๋ค. ์ฌ๋ฌ ๊ธฐ๋ฅ์ ๊ฐ์ง ๊ฐ๋๊ธฐ๋ฅผ ์คํํ ๋ ์
ํ๋ฉ๋๋ค. ๊ทธ๋์ ์ง๊ธ๊น์ง @kylecordes ํจ์น๊ฐ ์ผ์ ํ๊ณ ์๋ ๊ฒ ๊ฐ์ต๋๋ค. @kylecordes ๊ฐ์ฌํฉ๋๋ค! ์ด ์์ ์ผ๋ก ๊ณง master
์ด ๋ ๊ฒ์
๋๋ค.
์ฃผ์ ์์ ๋ฒ์ด๋ let l = await $$("q-short-list-component.ng-valid mat-label")
await
๊ฐ ํ์ํ์ง ์์ต๋๋ค. $$
๋ ์ฝ์์ด ์๋ ElementArrayFinder
$๋ฅผ ๋ฐํํฉ๋๋ค. ๐
@demisx ์๋์ ๋น์ ์ด ํ๋ ธ์ต๋๋ค. ์๋ง๋ ๊ทธ๊ฒ์ด ์ฌ์ ํ EPIPE ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ์ด์ ์ผ ๊ฒ์
๋๋ค :dancer:
์ - ๋๊ธฐ ์์ด ElementArrayFinder๋ฅผ ๋ฐํํ์ง๋ง ๋ฐ๋ณตํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด ๋ถ๋ถ์ ์๋ํ์ง ์์ ๊ฒ์
๋๋ค
for (let element of l){
text = await element.getText();
labels.push(text)
}
await
ํ๋ฉด ์์ ๋ชฉ๋ก์ ์ป์ต๋๋ค.
@rafalf ์ฃ์กํฉ๋๋ค. await
์๋์ ๋ฐ๋ณต ๋ถ๋ถ์ ๋์ณค์ต๋๋ค. ๋น์ ์ ์ ๋์ ์ผ๋ก ์ณ์ต๋๋ค.
๋ด๊ฐ ํ๋ฆด ์๋ ์์ง๋ง ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก ElementArrayFinder๋ฅผ ์ฌ์ฉํ ๋๋ง๋ค ์ด๋ฌํ ์ค๋ฅ๊ฐ ๊ฐํ์ ์ผ๋ก ๋ฐ์ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
await $$('some-selector').click()
@yyankowski ๋ค, ์ ๊ฒฝํ์ด๊ธฐ๋ ํฉ๋๋ค. ๋ค๋ฅธ ์ด๋ค ๊ฒ๋ณด๋ค $$
์์ ์ด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ณด์์ต๋๋ค. ํนํ $$
ElementArrayFinder
์ ๋ํ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ค๊ณ ํ ๋.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ฐ๋ฆฌ ํ๋ก์ ํธ์์
EPIPE
์ค๋ฅ๊ฐ ๋ํ๋ฌ์ต๋๋ค. ์๋ํ๋ฉด (TypeScript์์) ํ ์คํธ๊ฐawait
๋ฅผ ์๋ชป ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋ฐ๋ผ์ ์ฒ๋ฆฌ๋์ง ์์ Promise ๊ฑฐ๋ถ๊ฐ ๋ฌด์์๋ก ๋ฐ์ํ์ฌ ์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์๋ชป๋ ์ฌ์ฉ๋ฒ์ ์์ ํ๋ฉด ๋ ธ๋ 8์์ ๋ ์ด์ ์ด๋ฌํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ง ์์ต๋๋ค.await
์ ์๋ชป๋ ์ฌ์ฉ(๋๋ฝ ๋๋ ์ค๋ณต) ๋๋ ์๋ชป๋ Promise ์ฐ๊ฒฐ(์: ๋์ฐ๋ฏธ ๋ฉ์๋์์ Promise๋ฅผ ๋ฐํํ๋ ๊ฒ์ ์์์ ๋)์ ๋ํด ํ ์คํธ๋ฅผ ์ฃผ์ ๊น๊ฒ ํ์ธํ์ญ์์ค. ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ์ผ๋ฐ์ ์ธ ์ค๋ฅ๋ ๋ค์์ ์ฌ์ฉํ์ต๋๋ค.๋์ ์:
์๋ง๋ ์ด ๋ฌธ์ ๊ฐ ์๋ ๋๊ตฐ๊ฐ์๊ฒ ๋์์ด ๋ ๊ฒ์ ๋๋ค.