Protractor: ์‹คํŒจ: EPIPE ์“ฐ๊ธฐ EPIPE๋Š” SELENIUM_PROMISE_MANAGER์ผ ๋•Œ ์ž์ฃผ ํ‘œ์‹œ๋จ: false

์— ๋งŒ๋“  2017๋…„ 05์›” 17์ผ  ยท  47์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: angular/protractor

๋ฒ„๊ทธ ์‹ ๊ณ 

  • ๋…ธ๋“œ ๋ฒ„์ „: 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)
  • ๋ฒ„๊ทธ๋ฅผ ์žฌํ˜„ํ•˜๋Š” ๋‹จ๊ณ„
  1. ์–ธ๊ธ‰๋œ ๋Œ€๋žต์ ์ธ Node ๋ฐ Angular ๋ฒ„์ „, Chrome ๋ธŒ๋ผ์šฐ์ €, Mac OS X์„ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. (์•„์ง ๊ทธ ์กฐํ•ฉ์— ๋Œ€ํ•œ ๊ตฌ์ฒด์ ์ธ ๋ฌธ์ œ๊ฐ€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)
  2. ๊ตฌ์„ฑ์—์„œ SELENIUM_PROMISE_MANAGER: false ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค(์ œ์–ด ํ๋ฆ„ ๋น„ํ™œ์„ฑํ™”).
  3. ์œ„์˜ (2)๋กœ ์ธํ•ด ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ์˜ ๋ชจ๋“  ๊ณณ์—์„œ Promise๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.
  4. ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ ๊ฐ๊ฐ์— ๋Œ€ํ•ด URL์„ ๊ฐ€์ ธ์˜ค๊ณ  ์š”์†Œ ์กด์žฌ๋ฅผ ํด๋ฆญํ•˜๊ฑฐ๋‚˜ ํ™•์ธํ•˜๋Š” ์ œํ’ˆ๊ตฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  5. ๋งค์šฐ ๋น ๋ฅด๊ฒŒ Failed: EPIPE write EPIPE ์˜ค๋ฅ˜๊ฐ€ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋Œ€๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ๋„ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์•ฝ์†์„ ์‹๋ณ„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(์•ฝ์† ๊ฒฝํ—˜์ด ์žˆ์Œ). ์ผ๋ถ€ ์ฃผ์„์—์„œ ์ œ์•ˆํ•œ ๋‚ด์šฉ์ด๋ฏ€๋กœ ๊ทธ ๊ฐ€๋Šฅ์„ฑ์„ ํ—ˆ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜๋„ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์•ฝ์†์—์„œ ๋…ธ๋“œ๊ฐ€ ์ถฉ๋Œํ•˜๋Š” ๊ฒƒ์€ ๋†€๋ผ์šด ์ผ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ ์–ด๋”˜๊ฐ€์— ๋…ธ๋“œ ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚ด ํ…Œ์ŠคํŠธ๋‚˜ ๊ฐ๋„๊ธฐ ๋˜๋Š” ์›น ๋“œ๋ผ์ด๋ฒ„ ๋“ฑ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” URL(ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ)

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๊ณต๊ฐœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์—์„œ EPIPE ์˜ค๋ฅ˜๊ฐ€ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด (TypeScript์—์„œ) ํ…Œ์ŠคํŠธ๊ฐ€ await ๋ฅผ ์ž˜๋ชป ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ Promise ๊ฑฐ๋ถ€๊ฐ€ ๋ฌด์ž‘์œ„๋กœ ๋ฐœ์ƒํ•˜์—ฌ ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ž˜๋ชป๋œ ์‚ฌ์šฉ๋ฒ•์„ ์ˆ˜์ •ํ•˜๋ฉด ๋…ธ๋“œ 8์—์„œ ๋” ์ด์ƒ ์ด๋Ÿฌํ•œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

await ์˜ ์ž˜๋ชป๋œ ์‚ฌ์šฉ(๋ˆ„๋ฝ ๋˜๋Š” ์ค‘๋ณต) ๋˜๋Š” ์ž˜๋ชป๋œ Promise ์—ฐ๊ฒฐ(์˜ˆ: ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ์—์„œ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์—ˆ์„ ๋•Œ)์— ๋Œ€ํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์ฃผ์˜ ๊นŠ๊ฒŒ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜๋Š” ๋‹ค์Œ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

browser.wait(await EC.invisibilityOf(fade)); // incorrect

๋Œ€์‹ ์—:

await browser.wait(EC.invisibilityOf(fade)); // correct

์•„๋งˆ๋„ ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  47 ๋Œ“๊ธ€

์ €๋„ ์ด๊ฑฐ ๊ฝค ์ž์ฃผ ์ ‘ํ–ˆ์Šต๋‹ˆ๋‹ค. 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.10.1
  • OSX 10.12.5
  • ๊ฐ๋„๊ธฐ 5.1.2
  • ํฌ๋กฌ 59.0.3071.115

๊ทธ๋ฆฌ๊ณ  ๋‚ด๊ฐ€ _๊ฐ€๋Šฅ์„ฑ์ด ๊ฑฐ์˜ ์—†์Œ_์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์€ ์œ„์˜ ๊ตฌ์„ฑ์œผ๋กœ ์ œํ’ˆ๊ตฐ์„ 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์—์„œ๋Š” ์ฝ”๋“œ์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์œ ํ˜• '(command: Command, description: string) => Promise void'๋Š” ' T (command: Command, description: string) => Promise T' ์œ ํ˜•์— ํ• ๋‹นํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
'์•ฝ์† ๋ฌดํšจ' ์œ ํ˜•์€ '์•ฝ์† 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๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

4792๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ElementArrayFinder์—์„œ ํ•„ํ„ฐ๋ง์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ค‘ 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 ์— ๋Œ€ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ํ•  ๋•Œ.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰