Protractor: ShadowDOM ์ง€์› ์š”์ฒญ

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

ShadowDOM ์ง€์›์ด ์•„์ง ๋ˆ„๋ฝ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋ฐฐ๊ฒฝ

์ €๋Š” ShadowDOM v1 ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋Š” ์ผ๋ถ€ Polymer 2 ๊ตฌ์„ฑ ์š”์†Œ๋กœ ์ž‘์—… ์ค‘์ด๋ฉฐ e2e ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋ ค๋ฉด shadowRoot ๋‚ด๋ถ€์˜ ์š”์†Œ๋ฅผ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. deepCss ๊ฐ€ ํ•ด๊ฒฐ์ฑ…์ด ๋  ์ˆ˜ ์žˆ์ง€๋งŒ ์ €์—๊ฒŒ๋Š” ํšจ๊ณผ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜์žˆ๋Š” ํ•œ by.deepCss ๋Š” by.css ์™€ ํŠน๋ณ„ํ•œ ์ฐจ์ด๊ฐ€ ์—†์ง€๋งŒ ์ฃผ์–ด์ง„ CSS ์„ ํƒ๊ธฐ์˜ ์‹œ์ž‘ ๋ถ€๋ถ„์— * /deep/ ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€๋งŒ /deep/ ๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋ฒ„์ „์œผ๋กœ ์ž‘์—…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋…ธ๋“œ ๋ฒ„์ „: v6.10.3
  • ๊ฐ๋„๊ธฐ ๋ฒ„์ „: v5.1.2
  • ๊ฐ๋„ ๋ฒ„์ „: v4.2.4
  • ๋ธŒ๋ผ์šฐ์ €: Chrome
  • ์šด์˜ ์ฒด์ œ ๋ฐ ๋ฒ„์ „: Ubuntu v16.04.2 AMD64 LTS Xenial

๋‹ค์Œ์„ ํฌํ•จํ•˜์—ฌ ๋ชจ๋“  ๊ด€๋ จ ๊ธฐ์‚ฌ๋ฅผ ํ™•์ธํ–ˆ์ง€๋งŒ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ๋‹ต๋ณ€์„ ์–ป์ง€ ๋ชปํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์–ด์จŒ๋“  ์‚ฌ์šฉ์ž ์ง€์ • ๋กœ์ผ€์ดํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ShadowDOM ์š”์†Œ์˜ ๋‚ด๋ถ€ ์š”์†Œ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

/**
 * Usage:
 *   O  element(by.css_sr('#parentElement #innerElement'))          <=> $('#parentElement #innerElement')
 *   O  element(by.css_sr('#parentElement::sr #innerElement'))      <=> $('#parentElement').shadowRoot.$('#innerElement')
 *   O  element.all(by.css_sr('#parentElement .inner-element'))     <=> $$('#parentElement .inner-element')
 *   O  element.all(by.css_sr('#parentElement::sr .inner-element')) <=> $$('#parentElement').shadowRoot.$$('.inner-element')
 *   O  parentElement.element(by.css_sr('#innerElement'))           <=> parentElement.$('#innerElement')
 *   O  parentElement.element(by.css_sr('::sr #innerElement'))      <=> parentElement.shadowRoot.$('#innerElement')
 *   O  parentElement.all(by.css_sr('.inner-element'))              <=> parentElement.$$('.inner-element')
 *   O  parentElement.all(by.css_sr('::sr .inner-element'))         <=> parentElement.shadowRoot.$$('.inner-element')
 */
by.addLocator('css_sr', (cssSelector: string, opt_parentElement, opt_rootSelector) => {
    let selectors = cssSelector.split('::sr');
    if (selectors.length === 0) {
        return [];
    }

    let shadowDomInUse = (document.head.createShadowRoot || document.head.attachShadow);
    let getShadowRoot  = (el) => ((el && shadowDomInUse) ? el.shadowRoot : el);
    let findAllMatches = (selector: string, targets: any[], firstTry: boolean) => {
        let using, i, matches = [];
        for (i = 0; i < targets.length; ++i) {
            using = (firstTry) ? targets[i] : getShadowRoot(targets[i]);
            if (using) {
                if (selector === '') {
                    matches.push(using);
                } else {
                    Array.prototype.push.apply(matches, using.querySelectorAll(selector));
                }
            }
        }
        return matches;
    };

    let matches = findAllMatches(selectors.shift().trim(), [opt_parentElement || document], true);
    while (selectors.length > 0 && matches.length > 0) {
        matches = findAllMatches(selectors.shift().trim(), matches, false);
    }
    return matches;
});

๊ฒฐ๋ก 

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

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

PRs plz!

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

์ด์— ๋Œ€ํ•œ ์ƒํƒœ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? by.shadowRoot ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

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

@first87

์ด๊ฒƒ์„ ๊ณต์œ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ณด๊ธฐ ์ข‹๊ณ  ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ตœ์‹  ๋ฒ„์ „์˜ ๊ฐ๋„๊ธฐ์—์„œ ์ด๊ฒƒ์„ ๋ณด๋ ค๋ฉด element(by. shadowRoot('#parentElement #innerElement')) ์™€ ๊ฐ™์€ ์ƒˆ ๋กœ์ผ€์ดํ„ฐ๋กœ PR์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@wwebcreation ์ข‹์•„, ์ข‹์•„. PR์„ ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ์ด๋™ํ•˜๊ธฐ ์ „์— ํ•œ ๊ฐ€์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์–ด : ๋‹น์‹ ์€ ์„ ํƒ์˜์ด ์Šคํƒ€์ผ ๊ดœ์ฐฎ #parentElement::sr #innerElement ํ‘œ์‹œํ•˜๋Š” ์š”์†Œ #innerElement ์˜ ๊ทธ๋ฆผ์ž ๋‚˜๋ฌด ๋‚ด๋ถ€ #parentElement ?

@first87

์ž˜์ƒ๊ฒผ์–ด์š”๐Ÿ‘

๋‚˜๋Š” PR์— ๋Œ€ํ•ด ๊ฒฐ์ •ํ•˜๋Š” (์œ ์ผํ•œ) ์‚ฌ๋žŒ์ด ์•„๋‹™๋‹ˆ๋‹ค. PR๋„ ๊ฒ€ํ† ํ•  ํ•ต์‹ฌ ๊ตฌ์„ฑ์›์ด ๊ฒฐ๊ตญ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

ํ›Œ๋ฅญํ•œ ์ถ”๊ฐ€์™€ ๋ช…ํ™•ํ•œ ๊ธฐ๋ก์ด ๋  ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ์–ด์„œ ๊ฐ€๋ณด์„ธ์š” ๐Ÿ˜‰

@wwebcreation ๋‚ด ์ปค๋ฐ‹์„ ํ‘ธ์‹œ

์•ˆ๋…•ํ•˜์„ธ์š” @first87๋‹˜ ,

์ด ๋ฌธ์„œ๋ฅผ ๋ณธ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์ด ์ทจํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋ชจ๋“  ๋‹จ๊ณ„๋ฅผ ๋‹ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@wswebcreation ์˜ˆ, DEVELOPER.md ๋ฅผ ํ™•์ธํ–ˆ์ง€๋งŒ ํ‘ธ์‹œ ๊ฐ€์ด๋“œ๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๊ฐ„ ๋‹จ๊ณ„๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • git clone [email protected]:angular/protractor.git
  • cd protractor/
  • git remote add upstream https://github.com/angular/protractor.git
  • git checkout -b feature/shadow-root-locator master ๋‚ด ์ž์‹ ์˜ ์ง€์  ๋งŒ๋“ค๊ธฐ
  • npm install
  • ์—ฌ๋Ÿฌ ์ปค๋ฐ‹์„ ํ–ˆ๋‹ค
  • gulp lint - ์ฝ”๋“œ ํ˜•์‹์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํ™•์ธ
  • npm start , webdriver-manager start , npm test ๋ชจ๋“  ํ…Œ์ŠคํŠธ ํ†ต๊ณผ

์ด์ œ ๋‹ค์Œ์—๋Š” ๋ฌด์—‡์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š” @first87๋‹˜ ,

  • ํ”„๋กœ์ ํŠธ๋ฅผ ๋ถ„๊ธฐํ•˜์—ฌ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฉด ๊ณ„์ •์— ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.
  • ๋กœ์ปฌ ์‹œ์Šคํ…œ์— ๋ณต์ œ ์ˆ˜ํ–‰
  • ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํ‘ธ์‹œํ•˜๊ณ  "PR ์ž‘์„ฑ" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜์‹ญ์‹œ์˜ค.

๊ทธ๊ฒƒ์€ ํŠธ๋ฆญ์„ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค

@wswebcreation ๋„ค , ์•ˆ๋‚ดํ•ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@wswebcreation ๋ฐฉ๊ธˆ PR #4392 ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

@first87 ํ‹ฐ์•ค์—‘์Šค !!

์ด์— ๋Œ€ํ•œ ์ƒํƒœ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? by.shadowRoot ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค .

@first87 ๋‚ด e2e ํ…Œ์ŠคํŠธ์—์„œ ์ƒˆ ๋กœ์ผ€์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๋ฆผ์ž ๋”์—์„œ ์š”์†Œ๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ: ํด๋ฆฌ๋จธ ์›น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ๋Š” Angular(v5) ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜. e2e ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ๋„๊ธฐ.

๊ฐ๋„ CLI: 1.6.4
๋…ธ๋“œ: 6.10.0
๊ฐ๋„: 5.2.0
@angular/cli: 1.6.4
ํƒ€์ดํ”„์Šคํฌ๋ฆฝํŠธ: 2.5.3
์•„๋ž˜๋Š” ํฌ๋กฌ์—์„œ ํ™•์žฅ๋œ ํด๋ฆฌ๋จธ ์›น ๊ตฌ์„ฑ ์š”์†Œ ์„€๋„์šฐ ๋ฃจํŠธ์ž…๋‹ˆ๋‹ค. ์ด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋‚ด์—์„œ ์ž…๋ ฅ ์œ ํ˜• = "ํ…์ŠคํŠธ"๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๋„๊ธฐ by.css_sr์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ง€์ • ํด๋ฆฌ๋จธ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด๋ถ€์˜ ์ž…๋ ฅ ์š”์†Œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

var polymerFirstName = ์š”์†Œ(by.className('polyFName'));
var inputElement = polymerFirstName.element(by.css_sr('์ž…๋ ฅ')); // ์•„๋ฌด๊ฒƒ๋„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

"๋กœ์ผ€์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ: by.css_sr("input")" ์˜ค๋ฅ˜๋กœ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

shadowroot

๋‹ค์Œ๊ณผ ๊ฐ™์€ UI ์ž๋™ํ™” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‚ด๋ถ€ ์ž…๋ ฅ ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
polymerFirstName.element(by.css_sr('์ž…๋ ฅ')).clear();
polymerFirstName.element(by.css_sr('input')).sendKeys('Ritchie');

๋‚ด๊ฐ€ ๋†“์น˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@msbasanth by.css_sr ๊ฐ€ ์š”์†Œ์˜ ์„€๋„์šฐ ๋ฃจํŠธ์—์„œ ์š”์†Œ๋ฅผ ์ฐพ๊ธฐ ์‹œ์ž‘ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ::sr ๋†“์ณค์Šต๋‹ˆ๋‹ค ~ ๊ฐ ::sr ๋Œ€ํ•œ ๋ชจ๋“  ์š”์†Œ์˜ ์„€๋„์šฐ DOM ํŠธ๋ฆฌ๋ฅผ ํŒŒํ—ค์น  ๊ฒƒ์ž…๋‹ˆ๋‹ค
๋”ฐ๋ผ์„œ ์ž…๋ ฅ ์š”์†Œ ์ฐพ๊ธฐ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐ”๊ฟ”์•ผ ํ•ฉ๋‹ˆ๋‹ค.

var inputElement = polymerFirstName.element(by.css_sr('::sr input'));

@first87 ๋•๋ถ„ ์— ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ณง ์ด shadow DOM ์ง€์›์„ ๊ฐ๋„๊ธฐ์—์„œ ์–ป์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค! ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ํŠนํžˆ ์ค‘์ฒฉ๋œ ๊ทธ๋ฆผ์ž ๋”์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์š”์†Œ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ด ๋งค์šฐ ์–ด๋ ค์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฝ˜์†”์—์„œ ๋กœ์ผ€์ดํ„ฐ๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@firstor ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์ด๊ฒƒ์ด ๊ณง ํ†ตํ•ฉ๋  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค....

๊ทธ๋ž˜๋„ ์ด๊ฒƒ์— ๋Œ€ํ•ด ๋‹น์‹ ์˜ ๋„์›€์„ ๋ฐ›๊ธฐ๋ฅผ ๋ฐ”๋ž์Šต๋‹ˆ๋‹ค. ํ•„์š”์— ๋”ฐ๋ผ ::sr์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ฌ๋ฐ”๋ฅธ ๊ฐ’์„ ์–ป์„ ์ˆ˜ ์žˆ์ง€๋งŒ title.getText() ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด "์ž˜๋ชป๋œ" ๊ฐ’์„ ์–ป๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์˜ค๋ธŒ์ œ๋กœ ๋‹ค๊ฐ€์˜ค๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์•„๋ž˜์˜ ๋‹ค์Œ ์ถœ๋ ฅ์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

[ 'Title' ]์€(๋Š”) 'Title'์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ๊ฐœ์ฒด/๋ฐฐ์—ด์—์„œ ๋ฌธ์ž์—ด์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ๊ณ  ์•„์ด๋””์–ด๊ฐ€ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!!

ํŽธ์ง‘: ๋ฌด์‹œ!! ์ด๊ฒƒ์„ ์ฐธ์กฐํ•˜๊ณ  https://stackoverflow.com/questions/29478905/protractor-element-gettext-returns-an-object-and-not-string ํŠธ๋ฆญ์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค

@firstor / @msbasanth ๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”, shadow-root DOM์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ .ts ํŒŒ์ผ์— ๋ณต์‚ฌํ–ˆ์ง€๋งŒ ๋ผ์ธ ๋ฒˆํ˜ธ์—์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. 6:
์ฝ”๋“œ: let shadowDomInUse = (document.head.createShadowRoot .......
์˜ค๋ฅ˜: 'HTMLHeadElement' ์œ ํ˜•์— 'createShadowRoot' ์†์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค .

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ: ๊ฐ๋„ v7
๋…ธ๋“œJS: 6.9.0
ํƒ€์ดํ”„์Šคํฌ๋ฆฝํŠธ: 2.3.3
๊ฐ๋„๊ธฐ: 5.3.2

shadow-root ๋‚ด๋ถ€์˜ ์ž…๋ ฅ ์ƒ์ž์— ์ผ๋ถ€ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?
๊ฐ์‚ฌ ํ•ด์š”!

image

image

@firstor
๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
var searchBar = ์š”์†Œ(by.css_sr('::sr ์ž…๋ ฅ'));
var searchButton = ์š”์†Œ(by.css_sr('::sr i'));

์•„๋ž˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค
[11:36:06] E/๋Ÿฐ์ฒ˜ - TypeError: ์ž˜๋ชป๋œ ๋กœ์ผ€์ดํ„ฐ

๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์ฃ ?
๋„์›€์„ ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

@firstor ์•ˆ๋…•ํ•˜์„ธ์š”, ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค)
๊ทธ๋Ÿฌ๋‚˜ Protractor ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜์— ๋ณ‘ํ•ฉ๋˜์ง€ ์•Š๋Š” ํ•œ ์šฐ๋ฆฌ ํŒ€์—์„œ ์™„์ „ํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(์›๊ฒฉ ๋…ธ๋“œ์—์„œ Protractor๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•ญ์ƒ ๋Œ์–ด์˜ต๋‹ˆ๋‹ค).

https://github.com/angular/protractor/pull/4786 ๋ณ‘ํ•ฉ์— ์ง„์ „์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋ชจ๋“  ์—…๋ฐ์ดํŠธ? ์ด๊ฒƒ์€ ์ตœ๊ทผ์— ๋งŽ์€ ์‚ฌ์–‘์— ๋Œ€ํ•œ ์ฐจ๋‹จ๊ธฐ์ž…๋‹ˆ๋‹ค(

์•ˆ๋…•ํ•˜์„ธ์š” @firstor๋‹˜

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ: Angular 8
๋…ธ๋“œJS : 12.13.1
ํƒ€์ดํ”„์Šคํฌ๋ฆฝํŠธ: 3.5.3
๊ฐ๋„๊ธฐ : 5.4.0

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

ShadowRoot์—์„œ ์š”์†Œ๋ฅผ ์ฐพ์œผ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜์—๋Š” 3๊ฐ€์ง€ ๊นŠ์ด ์ˆ˜์ค€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • 1๋‹จ๊ณ„ : ๋งˆ์ดํฌ๋กœ ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
  • ๋‘ ๋ฒˆ์งธ ์ˆ˜์ค€: ๋งˆ์ดํฌ๋กœ ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์„ฑ ์š”์†Œ
  • ์„ธ ๋ฒˆ์งธ ์ˆ˜์ค€ : Angular ์žฌ๋ฃŒ ๊ตฌ์„ฑ ์š”์†Œ

Protractor_ShadowRoot-issue

์ฒซ ๋ฒˆ์งธ ๋ฐ ๋‘ ๋ฒˆ์งธ shadowRoot ์ˆ˜์ค€์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งˆ์ง€๋ง‰ ์ˆ˜์ค€์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ฝ”๋“œ ์†Œ์Šค ์ถ”์ถœ:

    await expect(element(by.tagName('page-affaire')).isDisplayed());
    await browser.driver.sleep(3000);
    console.log('Page affaire chargรฉe');
    var el1 = element(by.tagName('page-affaire'));

    var el2 = el1.element(by.css_sr('::sr rac-card'));
    console.log('rac-card found');

    var el3 = el1.element(by.css_sr('::sr rac-option'));
    console.log('rac-option found');

    var el4 = el1.element(by.css_sr('::sr mat-select')); 
    console.log('rac-card select');

๊ฒฐ๊ณผ ๋กœ๊ทธ:

Jasmine` started
Page affaire chargรฉe
rac-card found
rac-option found
rac-card select
Sรฉlection du type de demande

  crรฉer Affaire
    ร— Select type demande
      - NoSuchElementError: No element found using locator: by.css_sr("::sr mat-select")

๋‹ค๋ฅธ ์†”๋ฃจ์…˜์œผ๋กœ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค( https://stackoverflow.com/questions/57979981/how-to-check-in-protractor-javescript-in-shadow-dom-if-the-button-is-enabled-o ). ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

await browser.executeScript("return document.querySelector(\"page-affaire\");").then(function () {
      console.log('page affaire found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\");").then(function () {
      console.log('rac card found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\").shadowRoot.querySelector(\"rac-option\");").then(function () {
      console.log('rac option found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\").shadowRoot.querySelector(\"rac-option\").shadowRoot.querySelector(\"mat-select\").click();").then(function () {
      console.log('Type de Demande cliquรฉ');
      browser.sleep(5000);
    });

๊ฒฐ๊ณผ :

Jasmine started
Page affaire chargรฉe
rac-card found
rac-option found
rac-card select
Sรฉlection du type de demande

  crรฉer Affaire
    ร— Select type demande
      - NoSuchElementError: No element found using locator: by.css_sr("::sr mat-select")

shadowRoot ๊นŠ์ด ์ œํ•œ ์•ก์„ธ์Šค์— ๋Œ€ํ•œ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

V1nc3kr0

์•ˆ๋…•ํ•˜์„ธ์š” @firstor๋‹˜

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ: Angular 8
๋…ธ๋“œJS : 12.13.1
ํƒ€์ดํ”„์Šคํฌ๋ฆฝํŠธ: 3.5.3
๊ฐ๋„๊ธฐ : 5.4.0

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

ShadowRoot์—์„œ ์š”์†Œ๋ฅผ ์ฐพ์œผ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜์—๋Š” 3๊ฐ€์ง€ ๊นŠ์ด ์ˆ˜์ค€์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • 1๋‹จ๊ณ„ : ๋งˆ์ดํฌ๋กœ ํ”„๋ก ํŠธ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
  • ๋‘ ๋ฒˆ์งธ ์ˆ˜์ค€: ๋งˆ์ดํฌ๋กœ ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์„ฑ ์š”์†Œ
  • ์„ธ ๋ฒˆ์งธ ์ˆ˜์ค€ : Angular ์žฌ๋ฃŒ ๊ตฌ์„ฑ ์š”์†Œ

Protractor_ShadowRoot-issue

์ฒซ ๋ฒˆ์งธ ๋ฐ ๋‘ ๋ฒˆ์งธ shadowRoot ์ˆ˜์ค€์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋งˆ์ง€๋ง‰ ์ˆ˜์ค€์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ฝ”๋“œ ์†Œ์Šค ์ถ”์ถœ:

    await expect(element(by.tagName('page-affaire')).isDisplayed());
    await browser.driver.sleep(3000);
    console.log('Page affaire chargรฉe');
    var el1 = element(by.tagName('page-affaire'));

    var el2 = el1.element(by.css_sr('::sr rac-card'));
    console.log('rac-card found');

    var el3 = el1.element(by.css_sr('::sr rac-option'));
    console.log('rac-option found');

    var el4 = el1.element(by.css_sr('::sr mat-select')); 
    console.log('rac-card select');

๊ฒฐ๊ณผ ๋กœ๊ทธ:

Jasmine` started
Page affaire chargรฉe
rac-card found
rac-option found
rac-card select
Sรฉlection du type de demande

  crรฉer Affaire
    ร— Select type demande
      - NoSuchElementError: No element found using locator: by.css_sr("::sr mat-select")

๋‹ค๋ฅธ ์†”๋ฃจ์…˜์œผ๋กœ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค( https://stackoverflow.com/questions/57979981/how-to-check-in-protractor-javescript-in-shadow-dom-if-the-button-is-enabled-o ). ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

await browser.executeScript("return document.querySelector(\"page-affaire\");").then(function () {
      console.log('page affaire found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\");").then(function () {
      console.log('rac card found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\").shadowRoot.querySelector(\"rac-option\");").then(function () {
      console.log('rac option found');
      // browser.sleep(5000);
    });
    await browser.executeScript("return document.querySelector(\"page-affaire\").shadowRoot.querySelector(\"rac-card\").shadowRoot.querySelector(\"rac-option\").shadowRoot.querySelector(\"mat-select\").click();").then(function () {
      console.log('Type de Demande cliquรฉ');
      browser.sleep(5000);
    });

๊ฒฐ๊ณผ :

Jasmine started
Page affaire chargรฉe
rac-card found
rac-option found
rac-card select
Sรฉlection du type de demande

  crรฉer Affaire
    ร— Select type demande
      - NoSuchElementError: No element found using locator: by.css_sr("::sr mat-select")

shadowRoot ๊นŠ์ด ์ œํ•œ ์•ก์„ธ์Šค์— ๋Œ€ํ•œ ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

V1nc3kr0

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ๋„ํ•˜์‹ญ์‹œ์˜ค.
var el4 = el3 .element(by.css_sr('::sr ๋งคํŠธ ์„ ํƒ'));

@firstor
๋‚ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ 10๊ฐœ ๋ ˆ๋ฒจ์˜ ์„€๋„์šฐ ๋ฃจํŠธ๊ฐ€ ์žˆ๋Š” Polymer.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
RJvlf
๊ฐœ๋ณ„ ์„€๋„์šฐ ๋ฃจํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋Œ€์‹  ์ตœ์ƒ์œ„ ๋…ธ๋“œ์—์„œ ๋งˆ์ง€๋ง‰ ์„€๋„์šฐ ๋ฃจํŠธ ์š”์†Œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„ ,
์ €๋Š” ๊ฐ๋„๊ธฐ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•˜๊ณ  ์ด ๋กœ์ผ€์ดํ„ฐ ์Šคํฌ๋ฆฝํŠธ(shadowDOM)๋ฅผ ๊ฐ๋„๊ธฐ์— ํฌํ•จ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.
๋‚˜๋Š” ํด๋ฆฌ๋จธ ์›น ๊ตฌ์„ฑ ์š”์†Œ, ๊ฐ๋„๊ธฐ ๋ฒ„์ „: 5.4.2 ๋ฐ ๋…ธ๋“œ v12.13์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ UI ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ฌด๋„ ๊ทธ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•  ์œ„์น˜๋ฅผ ๋งํ•ด ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? @firstor , @alagappan-qa

๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

@rugaba
onPrepare() ๋ฉ”์„œ๋“œ ์•„๋ž˜์˜ Configuration.js ํŒŒ์ผ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

thx @ alagappan-qa, ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค!!

์•ˆ๋…•,

์ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณ„๋„์˜ js ํŒŒ์ผ์— ํฌํ•จํ•˜๊ณ  protractor.conf ํŒŒ์ผ์— ๊ฐ€์ ธ์™€์„œ onPrepare() ๋ฉ”์„œ๋“œ์— ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”,
๋ฝ์Šˆ๋ฏธ

๋ˆ„๊ตฐ๊ฐ€ ์ง€๊ธˆ ์ด๊ฒƒ์„ ํ•„์š”๋กœ ํ•˜๋Š” ๊ฒฝ์šฐ https://github.com/angular/protractor/pull/4786#issuecomment -607204672 ๋ฐ https://github.com/angular/protractor/pull/4786#issuecomment -607224145๋ฅผ ์ฐธ์กฐ ํ•˜์‹ญ์‹œ์˜ค.

https://github.com/angular/protractor/pull/4786.patch ๋˜๋Š” https://github.com/angular/protractor/pull/4786.diff๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•,

์ด ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋ณ„๋„์˜ js ํŒŒ์ผ์— ํฌํ•จํ•˜๊ณ  protractor.conf ํŒŒ์ผ์— ๊ฐ€์ ธ์™€์„œ onPrepare() ๋ฉ”์„œ๋“œ์— ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๊ฐ์‚ฌ ํ•ด์š”,
๋ฝ์Šˆ๋ฏธ

@Lakhs02
๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ์ด ๋กœ์ผ€์ดํ„ฐ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ ์–ธํ•˜์‹ญ์‹œ์˜ค.

exports.addShadowRootLocator = function () {
    by.addLocator('css_sr', function (
.
.
.
    return matches;
    });
};

๊ทธ๋Ÿฐ ๋‹ค์Œ onPrepare() ๋ฉ”์„œ๋“œ์—์„œ

onPrepare: function () {
        // register the shadow root locator, to use it globally
        require('./path/to/file').addShadowRootLocator();
}

>

@firstor
๋‚ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ 10๊ฐœ ๋ ˆ๋ฒจ์˜ ์„€๋„์šฐ ๋ฃจํŠธ๊ฐ€ ์žˆ๋Š” Polymer.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
RJvlf
๊ฐœ๋ณ„ ์„€๋„์šฐ ๋ฃจํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋Œ€์‹  ์ตœ์ƒ์œ„ ๋…ธ๋“œ์—์„œ ๋งˆ์ง€๋ง‰ ์„€๋„์šฐ ๋ฃจํŠธ ์š”์†Œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@firstor ๋‚˜๋Š” ๋‹น์‹ ์˜ ํ”„๋กœํ•„์—์„œ ๋‹น์‹ ์ด shadow DOM์— ๋Œ€ํ•ด ๊ฒฝํ—˜ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ๋œ Shadow DOM์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์นœ์ ˆํ•˜๊ฒŒ ์˜ˆ๋ฅผ ๋“ค์–ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ง€๊ธˆ 2์ฃผ ๋™์•ˆ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ผ๋ถ€ ์š”์†Œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๋‚ด ์˜ˆ์ž…๋‹ˆ๋‹ค. ๊ฐ•์กฐ ํ‘œ์‹œ๋œ div ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. div.a-choosen-text:
image

๋‚˜๋Š” ์•„๋ž˜์˜ ๋กœ์ผ€์ดํ„ฐ(๋ฐ ๋‹ค๋ฅธ ๋งŽ์€ ๊ฒƒ๋“ค)๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค:
nameOnTheProjectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)::sr appkit-panel::sr app-assignee- dropdown::sr appkit-dropdown::sr div.a-choosen-text'));

๋†€๋ž๊ฒŒ๋„ app-project์˜ ๋กœ์ผ€์ดํ„ฐ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ฉด ๋ฌด์—‡์„ ์‹œ๋„ํ•˜๋“  ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค: static projectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)'));

๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„?
๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
๋งˆ๊ทธ๋‹ค

>

@firstor
๋‚ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ 10๊ฐœ ๋ ˆ๋ฒจ์˜ ์„€๋„์šฐ ๋ฃจํŠธ๊ฐ€ ์žˆ๋Š” Polymer.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
RJvlf
๊ฐœ๋ณ„ ์„€๋„์šฐ ๋ฃจํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋Œ€์‹  ์ตœ์ƒ์œ„ ๋…ธ๋“œ์—์„œ ๋งˆ์ง€๋ง‰ ์„€๋„์šฐ ๋ฃจํŠธ ์š”์†Œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@firstor ๋‚˜๋Š” ๋‹น์‹ ์˜ ํ”„๋กœํ•„์—์„œ ๋‹น์‹ ์ด shadow DOM์— ๋Œ€ํ•ด ๊ฒฝํ—˜ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ๋œ Shadow DOM์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์นœ์ ˆํ•˜๊ฒŒ ์˜ˆ๋ฅผ ๋“ค์–ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ง€๊ธˆ 2์ฃผ ๋™์•ˆ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ผ๋ถ€ ์š”์†Œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๋‚ด ์˜ˆ์ž…๋‹ˆ๋‹ค. ๊ฐ•์กฐ ํ‘œ์‹œ๋œ div ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. div.a-choosen-text:
image

๋‚˜๋Š” ์•„๋ž˜์˜ ๋กœ์ผ€์ดํ„ฐ(๋ฐ ๋‹ค๋ฅธ ๋งŽ์€ ๊ฒƒ๋“ค)๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค:
nameOnTheProjectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)::sr appkit-panel::sr app-assignee- dropdown::sr appkit-dropdown::sr div.a-choosen-text'));

๋†€๋ž๊ฒŒ๋„ app-project์˜ ๋กœ์ผ€์ดํ„ฐ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ฉด ๋ฌด์—‡์„ ์‹œ๋„ํ•˜๋“  ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค: static projectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)'));

๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„?
๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
๋งˆ๊ทธ๋‹ค

์•ˆ๋…•ํ•˜์„ธ์š” ๋งˆ๊ทธ๋‹ค๋‹˜
๊ท€ํ•˜์˜ ๊ฒฝ์šฐ WebElement appkit-panel ์•„๋ž˜์˜ ์„€๋„์šฐ ๋ฃจํŠธ๋Š” ์š”์†Œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ํ™•์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ nameOnTheProjectTab ์š”์†Œ์—์„œ ํ™•์žฅ๋˜์–ด ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์•„๋ž˜ ์š”์†Œ ๋กœ์ผ€์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹ญ์‹œ์˜ค.
nameOnTheProjectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)::sr app-assignee-dropdown::sr appkit- dropdown::sr div.a-chosen-text'));

OMG, ์ด์ œ ์–ป์—ˆ๊ณ  ํ•„์š”ํ•œ ๋ชจ๋“  ๋กœ์ผ€์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
๋„์›€์„ ์ฃผ์…”์„œ ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!
์นœ์• ํ•˜๋Š”,
๋งˆ๊ทธ๋‹ค

๋ณด๋‚ธ ์‚ฌ๋žŒ: alagappan-qa [email protected]
๋ณด๋ƒ„: 2020๋…„ 7์›” 4์ผ ํ† ์š”์ผ ์˜ค์ „ 4:34
๋ฐ›๋Š” ์‚ฌ๋žŒ: ๊ฐ๋„/๊ฐ๋„๊ธฐ [email protected]
์ฐธ์กฐ: Bartkowiak-Jowsa, Magdalena [email protected] ; ๋Œ“๊ธ€ [email protected]
์ œ๋ชฉ: Re: [๊ฐ๋„/๊ฐ๋„๊ธฐ] ShadowDOM ์ง€์› ์š”์ฒญ(#4367)

@firstor https://github.com/firstor
๋‚ด ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ 10๊ฐœ ๋ ˆ๋ฒจ์˜ ์„€๋„์šฐ ๋ฃจํŠธ๊ฐ€ ์žˆ๋Š” Polymer.js๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
[๋ฐœ์‹ ์ž๊ฐ€ ์‚ญ์ œํ•œ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. RJvlf] https://user-images.githubusercontent.com/57852329/72205775-de7d6300-34ac-11ea-93f7-37917052ce90.png
๊ฐœ๋ณ„ ์„€๋„์šฐ ๋ฃจํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๋Œ€์‹  ์ตœ์ƒ์œ„ ๋…ธ๋“œ์—์„œ ๋งˆ์ง€๋ง‰ ์„€๋„์šฐ ๋ฃจํŠธ ์š”์†Œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์ง€์›ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@firstor https://github.com/firstor ํ”„๋กœํ•„์—์„œ Shadow DOM์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์ฒฉ๋œ Shadow DOM์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์นœ์ ˆํ•˜๊ฒŒ ์˜ˆ๋ฅผ ๋“ค์–ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ง€๊ธˆ 2์ฃผ ๋™์•ˆ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ผ๋ถ€ ์š”์†Œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ๋‚ด ์˜ˆ์ž…๋‹ˆ๋‹ค. ๊ฐ•์กฐ ํ‘œ์‹œ๋œ div ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. div.a-choosen-text:
[๋ฐœ์‹ ์ž๊ฐ€ ์‚ญ์ œํ•œ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€] https://user-images.githubusercontent.com/50359393/86498151-c532e080-bd84-11ea-867c-337085b96087.png

๋‚˜๋Š” ์•„๋ž˜์˜ ๋กœ์ผ€์ดํ„ฐ(๋ฐ ๋‹ค๋ฅธ ๋งŽ์€ ๊ฒƒ๋“ค)๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ ์„ฑ๊ณตํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค:
nameOnTheProjectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)::sr appkit-panel::sr app-assignee- dropdown::sr appkit-dropdown::sr div.a-choosen-text'));

๋†€๋ž๊ฒŒ๋„ app-project์˜ ๋กœ์ผ€์ดํ„ฐ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๋” ๊นŠ์ด ๋“ค์–ด๊ฐ€๋ฉด ๋ฌด์—‡์„ ์‹œ๋„ํ•˜๋“  ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค: static projectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)'));

๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ์•„?
๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.
๋งˆ๊ทธ๋‹ค

์•ˆ๋…•ํ•˜์„ธ์š” ๋งˆ๊ทธ๋‹ค๋‹˜
๊ท€ํ•˜์˜ ๊ฒฝ์šฐ WebElement appkit-panel ์•„๋ž˜์˜ ์„€๋„์šฐ ๋ฃจํŠธ๋Š” ์š”์†Œ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด ํ™•์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ nameOnTheProjectTab ์š”์†Œ์—์„œ ํ™•์žฅ๋˜์–ด ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
์•„๋ž˜ ์š”์†Œ ๋กœ์ผ€์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด๋ณด์‹ญ์‹œ์˜ค.
nameOnTheProjectTab = element(by.css_sr('app-dumbledore::sr lit-route::sr app-dashboard::sr app -project:nth-child (1)::sr app-assignee-dropdown::sr appkit- dropdown::sr div.a-chosen-text'));

โ€”
๋‹น์‹ ์ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub https://github.com/angular/protractor/issues/4367#issuecomment-653710546 ์—์„œ ํ™•์ธํ•˜๊ฑฐ๋‚˜ https://github.com/notifications/unsubscribe-auth/AMAGYYOPZMDJCRSHT5XI45TRZ2ILDANCNFSM4DR44ABQ ๊ตฌ๋…์„ ์ทจ์†Œ


์บก์ œ๋ฏธ๋‹ˆ ํด์Šค์นด Sp. ์ฆˆ์šฐ,
์šธ. ลปwirki i Wigury 16a 02-092 Warszawa,
S?d Rejonowy dla M.ST. Warszawy, XII Wydzia? Gospodarczy Rejestrowy, nr KRS: 0000040605,
NIP: 526-11-84-467,
์œ„์†Œ์ฝ”?? kapita?u zak?adowego: 16.403.320,00z?.
์ด ๋ฉ”์‹œ์ง€์—๋Š” ๊ถŒํ•œ์ด ์žˆ๊ฑฐ๋‚˜ ๊ธฐ๋ฐ€์ผ ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉฐ Capgemini Group์˜ ์ž์‚ฐ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ฃผ์†Œ๊ฐ€ ์ง€์ •๋œ ์‚ฌ๋žŒ๋งŒ์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ท€ํ•˜๊ฐ€ ์˜๋„ํ•œ ์ˆ˜์‹ ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ ์ด ๋ฉ”์‹œ์ง€ ๋˜๋Š” ๊ทธ ์ผ๋ถ€๋ฅผ ์ฝ๊ฑฐ๋‚˜, ์ธ์‡„ํ•˜๊ฑฐ๋‚˜, ๋ณด๊ด€ํ•˜๊ฑฐ๋‚˜, ๋ณต์‚ฌํ•˜๊ฑฐ๋‚˜, ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜, ์‚ฌ์šฉํ•  ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ฉ”์‹œ์ง€๋ฅผ ์ž˜๋ชป ์ˆ˜์‹ ํ•œ ๊ฒฝ์šฐ ๋ฐœ์‹ ์ž์—๊ฒŒ ์ฆ‰์‹œ ์•Œ๋ฆฌ๊ณ  ์ด ๋ฉ”์‹œ์ง€์˜ ๋ชจ๋“  ์‚ฌ๋ณธ์„ ์‚ญ์ œํ•˜์‹ญ์‹œ์˜ค.

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ๊นŠ์€ ์ˆ˜์ค€์—์„œ ๊ทธ๋ฆผ์ž ๋ฃจํŠธ ๋‚ด๋ถ€์˜ ๊ทธ๋ฆผ์ž ์š”์†Œ๋ฅผ ์ฐพ๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.
๋…ธ๋“œ ๋ชจ๋“ˆ "query-selector-shadow-dom"์˜ ๋„์›€์œผ๋กœ Shadow DOM์˜ ์›น ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ทธ๋ฆผ์ž ๋ฃจํŠธ๋ฅผ ํ†ต๊ณผํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
element(by.shadowDomCss('')), ์šฐ๋ฆฌ๋Š” ๋ชจ๋“  ์ˆ˜์ค€์—์„œ Shadow Root ๋‚ด๋ถ€์˜ Web ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” Alagappan๋‹˜
์˜ˆ๋ฅผ ๋“ค์–ด ์ข€ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

2020๋…„ 8์›” 19์ผ ์ˆ˜์š”์ผ ์˜ค์ „ 7:52 alagappan-annamalai <
[email protected]>์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ๋‚ด๋ถ€์˜ ๊ทธ๋ฆผ์ž ์š”์†Œ๋ฅผ ์ฐพ๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค.
๋ชจ๋“  ๊นŠ์€ ์ˆ˜์ค€์˜ ๊ทธ๋ฆผ์ž ๋ฃจํŠธ.
๋…ธ๋“œ ๋ชจ๋“ˆ "query-selector-shadow-dom"์˜ ๋„์›€์œผ๋กœ ์šฐ๋ฆฌ๋Š”
Shadow DOM์—์„œ ์›น ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์‹๋ณ„ํ•ฉ๋‹ˆ๋‹ค. ํšก๋‹จํ•  ํ•„์š” ์—†์Œ
๋ชจ๋“  ๊ทธ๋ฆผ์ž ๋ฟŒ๋ฆฌ๋ฅผ ํ†ตํ•ด.
element(by.shadowDomCss(''))๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด๋ถ€์˜ ์›น ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋“  ์ˆ˜์ค€์—์„œ ๊ทธ๋ฆผ์ž ๋ฃจํŠธ.

โ€”
๋‹น์‹ ์ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/angular/protractor/issues/4367#issuecomment-676304234 ,
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/AK2OQDTZK2ZVJTICP3VGS3DSBPDJVANCNFSM4DR44ABQ
.

์•ˆ๋…•ํ•˜์„ธ์š” Alagappan๋‹˜, ์˜ˆ๋ฅผ ๋“ค์–ด ์ข€ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.
โ€ฆ
2020๋…„ 8์›” 19์ผ ์ˆ˜์š”์ผ ์˜ค์ „ 7:52 alagappan-annamalai < @ . * > ์ž‘์„ฑ: ์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ๋ชจ๋“  ๋”ฅ ๋ ˆ๋ฒจ์—์„œ Shadow Root ๋‚ด๋ถ€์˜ Shadow Elements๋ฅผ ์ฐพ๋Š” ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ๋…ธ๋“œ ๋ชจ๋“ˆ "query-selector-shadow-dom"์˜ ๋„์›€์œผ๋กœ Shadow DOM์˜ ์›น ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ทธ๋ฆผ์ž ๋ฃจํŠธ๋ฅผ ํ†ต๊ณผํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. element(by.shadowDomCss(''))๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ์ˆ˜์ค€์—์„œ Shadow Root ๋‚ด๋ถ€์˜ Web ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โ€” ๋‹น์‹ ์ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub < #4367 (comment) >์—์„œ ํ™•์ธํ•˜๊ฑฐ๋‚˜ https://github.com/notifications/unsubscribe-auth/AK2OQDTZK2ZVJTICP3VGS3DSBPDJVANCNFSM4DR44ABQ ๊ตฌ๋…์„ ์ทจ์†Œ

72205775-de7d6300-34ac-11ea-93f7-37917052ce90
์œ„์˜ ์Šคํฌ๋ฆฐ์ƒท์—์„œ id=container์ธ ํƒœ๊ทธ paper-input-container๋Š” 6+ ์„€๋„์šฐ ๋ฃจํŠธ ๋ ˆ์ด์–ด์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ด webElement๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด element(by.shadowDomCss('paper-input#textbox paper-input-container#container')); ์ด ์งง์€ ์š”์†Œ ์‹๋ณ„์ž๋Š” WebElement์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

@firstor / @msbasanth ๋‹˜ ์•ˆ๋…•ํ•˜์„ธ์š”, shadow-root DOM์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋ฅผ .ts ํŒŒ์ผ์— ๋ณต์‚ฌํ–ˆ์ง€๋งŒ ๋ผ์ธ ๋ฒˆํ˜ธ์—์„œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. 6:
์ฝ”๋“œ: let shadowDomInUse = (document.head.createShadowRoot .......
์˜ค๋ฅ˜: 'HTMLHeadElement' ์œ ํ˜•์— 'createShadowRoot' ์†์„ฑ์ด ์—†์Šต๋‹ˆ๋‹ค .

๋˜ํ•œ ์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์œผ๋ฉฐ ํ•ด๊ฒฐ์ฑ…์€ createShadowRoot ๋ฅผ attachShadow ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด createShadowRoot() ๋ฉ”์†Œ๋“œ๊ฐ€ attachShadow()๋ฅผ ์œ„ํ•ด ๋” ์ด์ƒ ์‚ฌ์šฉ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ฐธ์กฐ ์ฐธ์กฐ:
https://developer.mozilla.org/en-US/docs/Web/API/Element/createShadowRoot

๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ  @firstor , ์ด ๊ณตํ—Œ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ์ง€๊ธˆ๊นŒ์ง€ ํ›Œ๋ฅญํ•˜๊ฒŒ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š”๋ ค๊ณ  ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์„ ๋‚ญ๋น„ by.deepCss ๋‚˜๋Š” ์ตœ๊ทผ์— ๋‚ด ์ฝ”๋„ˆ (10 ๊ฐœ) ๊ตฌ์„ฑ ์š”์†Œ์™€ ๊ธฐ๋ณธ shadowDom ์บก์Šํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค ๊ฐ๋„๊ธฐ์™€ ๊ฐ๋„ (10)์™€ ์ผ์— encapsulation: ViewEncapsulation.ShadowDom ๋‚ด๊ฐ€ ์‚ฌ๋ž‘ํ•˜์ง€๋งŒ ํ–‰๋ณต I๋˜์ง€ ์•Š์€ e2e ํ…Œ์ŠคํŠธ ์ค‘์— ์ค‘์ฒฉ๋œ shadowDom ์š”์†Œ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ณ ๋ง™๊ฒŒ๋„ ์ด ์ฝ”๋“œ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค!

@Rob4226
https://www.npmjs.com/package/query-selector-shadow-dom ํŒจํ‚ค์ง€๋ฅผ ์‚ดํŽด๋ณด์‹ญ์‹œ์˜ค.

์œ ๋งํ•ด ๋ณด์ธ๋‹ค.

@msbasanth @Rob4226 ์ €๋Š” ๊ฐ๋„๊ธฐ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํฌ๋กฌ ๋‹ค์šด๋กœ๋“œ ํŽ˜์ด์ง€์˜ '๋‹ค์šด๋กœ๋“œ' ํ…์ŠคํŠธ์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
๋‚ด ์ฝ”๋“œ :
image
๋‚˜๋Š” ๋˜ํ•œ ์‹œ๋„ํ–ˆ๋‹ค var x = await element.element(by.css_sr('h1')).getText(); ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์•„๋ž˜ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.
image

์ด ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์ค‘์ฒฉ๋œ ์„€๋„ ๋ฃจํŠธ ์š”์†Œ์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์š”์†Œ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@firstor ์ด ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ‘

์•ˆ๋…•ํ•˜์„ธ์š” ์ €๋Š” ํ˜„์žฌ shadow dom์„ ์„ ํƒํ•˜๋Š” tr์ž…๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ๋•Œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Logg: { StaleElementReferenceError: stale element reference: stale element not found (Session info: chrome=87.0.4280.66)

์šฉ๋ฒ•:
const parent = element(by.css_sr('my-wrapper > div > div::sr my-data')); const domElement = parent.element(by.css('my-checkbox input')); console.log('Displayed', await domElement.isDisplayed());

<my-data> <my-checkbox> <input> <my-checkbox> </my-data> .....
๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์ฃ ?

์•ˆ๋…•ํ•˜์„ธ์š” ์ €๋Š” ํ˜„์žฌ shadow dom์„ ์„ ํƒํ•˜๋Š” tr์ž…๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ๋•Œ ๋‹ค์Œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Logg: { StaleElementReferenceError: stale element reference: stale element not found (Session info: chrome=87.0.4280.66)

์šฉ๋ฒ•:
const parent = element(by.css_sr('my-wrapper > div > div::sr my-data')); const domElement = parent.element(by.css('my-checkbox input')); console.log('Displayed', await domElement.isDisplayed());

<my-data> <my-checkbox> <input> <my-checkbox> </my-data> .....
๋‚ด๊ฐ€ ๋ญ˜ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์ฃ ?

@wasoek๋‹˜ , ์„€๋„์šฐ ๋ฃจํŠธ์—์„œ ์ด ์š”์†Œ์— ๋Œ€ํ•œ Chrome ๊ฐœ๋ฐœ์ž ๋„๊ตฌ > ์š”์†Œ ๊ฒ€์‚ฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋Ÿฌ๋ฉด ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•,

์ด๊ฒƒ์€ ์•„๋ž˜ 2๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

element1 = element.all(by.css_shadowroot('downloads-manager::sr div')).get(1)

element2 = element1.element(by.css_shadowroot('::sr downloads-item::sr div::sr downloads-item')).getText();
๋˜๋Š”

browser.element(by.css_shadowroot('downloads-manager::sr div[id=โ€mainContainerโ€]::sr ๋‹ค์šด๋กœ๋“œ ํ•ญ๋ชฉ::sr div::sr ๋‹ค์šด๋กœ๋“œ ํ•ญ๋ชฉ')).getText();
[์—ฌ๊ธฐ์„œ n๋ฒˆ์งธ ์ž์‹ ๋Œ€์‹ ์— ID๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์š”์†Œ์— ์ดˆ์ ์„ ๋งž์ถฅ๋‹ˆ๋‹ค.]

๊ฐ์‚ฌ ํ•ด์š”,
์•Œ๋ผ๊ฐ€ํŒ A

๋ณด๋‚ธ ์‚ฌ๋žŒ: shopmujahid [email protected]
๋ณด๋ƒ„: 2020๋…„ 12์›” 3์ผ ๋ชฉ์š”์ผ ์˜ค์ „ 9:20
๋ฐ›๋Š” ์‚ฌ๋žŒ: ๊ฐ๋„/๊ฐ๋„๊ธฐ [email protected]
์ฐธ์กฐ: Alagappan Annamalai [email protected] ; ๋Œ“๊ธ€ [email protected]
์ œ๋ชฉ: Re: [๊ฐ๋„/๊ฐ๋„๊ธฐ] ShadowDOM ์ง€์› ์š”์ฒญ(#4367)

Shadow dom(๊ฐ•์กฐ ํ‘œ์‹œ๋จ)์˜ ๋‘ ๋ฒˆ์งธ div ์š”์†Œ ์•„๋ž˜์— ์žˆ๋Š” ์š”์†Œ์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ํ•˜์ง€๋งŒ ํ•ญ์ƒ ์•„๋ž˜ ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ์ฒซ ๋ฒˆ์งธ div ์š”์†Œ๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

W/์š”์†Œ - locator by.css_shadowroot("downloads-manager::sr div")์— ๋Œ€ํ•ด ๋‘˜ ์ด์ƒ์˜ ์š”์†Œ๊ฐ€ ๋ฐœ๊ฒฌ๋จ - ์ฒซ ๋ฒˆ์งธ ๊ฒฐ๊ณผ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ๋‚ด xpath์ž…๋‹ˆ๋‹ค.
browser.element(by.css_shadowroot('downloads-manager::sr div:nth-child (1)::sr ๋‹ค์šด๋กœ๋“œ ํ•ญ๋ชฉ::sr div::sr ๋‹ค์šด๋กœ๋“œ ํ•ญ๋ชฉ')).getText();

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋‚˜๋ฅผ ์•ˆ๋‚ด ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค

[์ด๋ฏธ์ง€] https://user-images.githubusercontent.com/58770415/100961235-336c0280-34df-11eb-9618-1f24ffcd62a0.png

โ€”
๋‹น์‹ ์ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ํšŒ์‹ ํ•˜๊ฑฐ๋‚˜ GitHub https://github.com/angular/protractor/issues/4367#issuecomment-737647758 ์—์„œ ํ™•์ธํ•˜๊ฑฐ๋‚˜ https://github.com/notifications/unsubscribe-auth/AORWPO6XNK7RUWPVHCWKBCTSS4DH5ANCNFSM4DR44ABQ ๊ตฌ๋…์„ ์ทจ์†Œ

๋‚ด ๊ฒฝ์šฐ์—๋Š” nth-child()์™€ type-of()๊ฐ€ ๋ชจ๋‘ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” shadow dom ๋‚ด๋ถ€์˜ div ์š”์†Œ ์ค‘ ํ•˜๋‚˜์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ „์—์ด ๋ฌธ์ œ์— ์ง๋ฉด ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์•„๋ž˜๋Š” DOM ๊ตฌ์กฐ์™€ ๋‚ด xpath์ž…๋‹ˆ๋‹ค.
2134234

Browser.element(by.css_shadowroot('d2l-navigation::sr d2l-navigation-main- header:nth-type-of (3)'))๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค

์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ ์˜ค๋ฅ˜๊ฐ€ ์ˆ˜์‹ ๋ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ๋„์›€์ด๋ผ๋„ ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์•ˆ๋…•,

์„€๋„์šฐ ๋ฃจํŠธ ์™ธ๋ถ€์— ์žˆ์œผ๋ฏ€๋กœ ์š”์†Œ ๋กœ์ผ€์ดํ„ฐ์—์„œ ::sr์„ ์ œ๊ฑฐํ•ด ๋ณด์„ธ์š”.
์ด 2๊ฐœ์˜ ์š”์†Œ ๋กœ์ผ€์ดํ„ฐ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘๋™ํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

Browser.element(by.css_shadowroot('d2l-navigation d2l-navigation-main- header:nth-type-of (3)'))๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค
๋˜๋Š”

browser.element(by.css_shadowroot('d2l-navigation d2l-navigation-main-header div. d2l-navigation-header-right'))๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”,

์•Œ๋ผ๊ฐ€ํŒ A
๋ณด๋‚ธ ์‚ฌ๋žŒ: shopmujahid [email protected]
๋ณด๋ƒ„: 2020๋…„ 12์›” 9์ผ ์ˆ˜์š”์ผ ์˜คํ›„ 12:09
๋ฐ›๋Š” ์‚ฌ๋žŒ: ๊ฐ๋„/๊ฐ๋„๊ธฐ [email protected]
์ฐธ์กฐ: Alagappan Annamalai [email protected] ; ๋Œ“๊ธ€ [email protected]
์ œ๋ชฉ: Re: [๊ฐ๋„/๊ฐ๋„๊ธฐ] ShadowDOM ์ง€์› ์š”์ฒญ(#4367)

๋‚ด ๊ฒฝ์šฐ์—๋Š” nth-child()์™€ type-of()๊ฐ€ ๋ชจ๋‘ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” shadow dom ๋‚ด๋ถ€์˜ div ์š”์†Œ ์ค‘ ํ•˜๋‚˜์— ์•ก์„ธ์Šคํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
์ „์—์ด ๋ฌธ์ œ์— ์ง๋ฉด ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์•„๋ž˜๋Š” DOM ๊ตฌ์กฐ์™€ ๋‚ด xpath์ž…๋‹ˆ๋‹ค.
[2134234] https://user-images.githubusercontent.com/58770415/101593797-cc9e8b80-39ad-11eb-8fd0-a7cd7541773f.jpg

Browser.element(by.css_shadowroot('d2l-navigation::sr d2l-navigation-main- header:nth-type-of (3)'))๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค

์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ ์˜ค๋ฅ˜๊ฐ€ ์ˆ˜์‹ ๋ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ๋„์›€์ด๋ผ๋„ ๋Œ€๋‹จํžˆ ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub https://github.com/angular/protractor/issues/4367#issuecomment-741567009 ์—์„œ ํ™•์ธํ•˜๊ฑฐ๋‚˜ https://github.com/notifications/unsubscribe-auth/AORWPO7CSSI7P5GH37O74R3ST4LO5ANNCNFSM4DR44ABQ ๊ตฌ๋…์„ ์ทจ์†Œ

@alagappan-annamalai ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ‘ ๋‘ ๋ฒˆ์งธ ์†”๋ฃจ์…˜์€ ::sr์„ ์ œ๊ฑฐํ•˜๊ณ  tagname.classname์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„๋ž˜์˜ ์ž์‹ ์š”์†Œ์— ์•ก์„ธ์Šคํ•˜์ง€ ๋ชปํ•˜๋Š” ๋‹ค๋ฅธ ์ด์ƒํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
2134234

์œ„์˜ ๊ฐ•์กฐ ํ‘œ์‹œ๋œ ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ๋‘ xpath๋กœ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
browser.element(by.css_sr('d2l-navigation d2l-navigation-main-header div.d2l-navigation-header-right div d2l-dropdown d2l-dropdown-content div div div div ul:nth-child(2)' ))

๊ทธ๋ฆฌ๊ณ 

Browser.element(by.css_sr('d2l-navigation d2l-navigation-main-header div.d2l-navigation-header-right div d2l-dropdown d2l-dropdown-content div div div div ul li._(li ํด๋ž˜์Šค ์ด๋ฆ„์€ ๋งˆ์šฐ์Šค๋ฅผ ๊ฐ€์ ธ๊ฐˆ ๋•Œ ์ผ๋ถ€ ํ…์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.)

์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ ์˜ค๋ฅ˜๊ฐ€ ์ˆ˜์‹ ๋ฉ๋‹ˆ๋‹ค.
๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

@alagappan-annamalai ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ‘ ๋‘ ๋ฒˆ์งธ ์†”๋ฃจ์…˜์€ ::sr์„ ์ œ๊ฑฐํ•˜๊ณ  tagname.classname์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„๋ž˜์˜ ์ž์‹ ์š”์†Œ์— ์•ก์„ธ์Šคํ•˜์ง€ ๋ชปํ•˜๋Š” ๋‹ค๋ฅธ ์ด์ƒํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
2134234

์œ„์˜ ๊ฐ•์กฐ ํ‘œ์‹œ๋œ ์š”์†Œ์— ์•ก์„ธ์Šคํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜์˜ ๋‘ xpath๋กœ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค.
browser.element(by.css_sr('d2l-navigation d2l-navigation-main-header div.d2l-navigation-header-right div d2l-dropdown d2l-dropdown-content div div div div ul:nth-child(2)' ))

๊ทธ๋ฆฌ๊ณ 

Browser.element(by.css_sr('d2l-navigation d2l-navigation-main-header div.d2l-navigation-header-right div d2l-dropdown d2l-dropdown-content div div div div ul li.__')) (li ํด๋ž˜์Šค ์ด๋ฆ„ ์œ„๋กœ ๋งˆ์šฐ์Šค๋ฅผ ๊ฐ€์ ธ๊ฐ€๋ฉด ์ผ๋ถ€ ํ…์ŠคํŠธ๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.)

์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ ์˜ค๋ฅ˜๊ฐ€ ์ˆ˜์‹ ๋ฉ๋‹ˆ๋‹ค.
๋ฏธ๋ฆฌ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ css_sr ์—†์ด ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ช‡ ๊ฐ€์ง€ HTML ์›น ์š”์†Œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
browser.element.all(by.css('d2l-navigation d2l-navigation-main-header ul[class="d2l-datalist vui-list"] li')).get(1);

Bravo, ๋งค๋ ฅ์ฒ˜๋Ÿผ ์ผํ–ˆ์Šต๋‹ˆ๋‹ค @lagappan-annamalai ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! โ‡

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