1

I am trying to write a test that validates and confirms add-ons in a cart flow. One page I'm having difficulty with loads the page, and has a checkbox I need to hit that's within a shadow root. I can identify some of the highest level components on the page and am stuck trying to get to one in particular.

I have a byebug where I'm trying in the flow of the test and at the page in question.

Running "sales_channels_reg.regsaver_section.regsaver_testtest.text(:all)". returns:

"Show Progress Welcome Who Are You Registering? Information Review Suggested Add-Ons Shopping Cart Checkout Confirmation Zach Partyka Demo Site Suggested Add-Ons Loading... Loading... #displayBodyHeader { display: none !important } $j(document).ready(function () { listenForEventsFromSalesChannelsElement(); function listenForEventsFromSalesChannelsElement() { document.getElementById('sales-channels-element').addEventListener('outputEvent', function(event) { switch (event.detail.type) { case 'registration': registerAnotherOrContinueToCheckout(event.detail); break; case 'analytics': handleAnalyticsEvents(event.detail); break; } }); } function registerAnotherOrContinueToCheckout(eventDetail) { if (eventDetail.action === 'registerAnother') $j('.js-register-another-button').click(); else if (eventDetail.action === 'continue') $j('.js-continue-button').click(); } function handleAnalyticsEvents(eventDetail) { const railsEnv = 'production'; if (railsEnv === 'development') return; // SeMParticle only works for staging and production. switch (eventDetail.action) { case 'pageView': setCookie(\"surveySport\", eventDetail.pageAttributes.survey_sport , 1); setCookie(\"surveyType\", encodeURIComponent(eventDetail.pageAttributes.survey_type), 1); setCookie(\"surveyRegistrantType\", eventDetail.pageAttributes.survey_registrant_type, 1); setCookie(\"surveyParticipantType\", eventDetail.pageAttributes.survey_participant_type, 1); setCookie(\"surveyParticipantDOB\", eventDetail.pageAttributes.survey_participant_dob , 1); setCookie(\"surveyParticipantGender\", eventDetail.pageAttributes.survey_participant_gender, 1); setCookie(\"bossOrganizationId\", encodeURIComponent(eventDetail.pageAttributes.boss_organization_id), 1); setCookie(\"bossOrganizationName\", encodeURIComponent(eventDetail.pageAttributes.boss_organization_name), 1); setCookie(\"bossOrganizationAddrState\", encodeURIComponent(eventDetail.pageAttributes.boss_organization_addrState), 1); setCookie(\"bossOrganizationSports\", encodeURIComponent(eventDetail.pageAttributes.boss_organization_sports), 1); window.SeMParticle.pageView(eventDetail.pageAttributes); break; case 'logImpression': window.SeMParticle.logImpression(eventDetail.pageAttributes, eventDetail.productAttributes, 'SalesChannelsImpression'); break; case 'addToCart': window.SeMParticle.addToCart(eventDetail.pageAttributes, eventDetail.productAttributes); break; } } function setCookie(name,value,exp_days) { var d = new Date(); d.setTime(d.getTime() + (exp_days*24*60*60*1000)); var expires = \"expires=\" + d.toGMTString(); document.cookie = name + \"=\" + value + \";\" + expires + \";path=/;domain=.sportngin.com\"; } });"

But running "sales_channels_reg.regsaver_section.regsaver_testtest.find(:css, "#sales-channels-element__container").text(:all)" returns only the "Loading... Loading..." text above the shadow-root div

The part I need help with is I don't know why I can't I dig to the div element that has the shadow-root? I've tried using find_element for :id, :css, lots of "sleep()" to let the page load, etc., but still stuck there

The Code for trying to target the test in particular:

-first file-
describe "Showing 4 max add-ons in reg flow", type: :feature, service: "sales_channels1" do
  context "yadda yadda" do
    subject(:sales_channels_reg) { SalesChannelsRegGenerals.new }
    subject(:se_signup_page) { SELogin.new }
    # subject(:gen_reg) { RegistrationHelper.new }
    let(:form_number) { "848624247" }

    it "in test flow does thing" do
      couple of other steps first
      byebug (where I'm at in the code now)
    end
  end
end
    

-different file-
require "./spec/page_models/sales_channels_ncsa_section.rb"
require "./spec/page_models/sales_channels_medsaver_section.rb"
require "./spec/page_models/sales_channels_regsaver_section.rb"
require "./spec/page_models/sales_channels_four_addons_section.rb"

class SalesChannelsRegGenerals < SitePrism::Page
  set_url "https://zachpartyka#{SeleniumTest.ngin_site}/register/form/{/form_number}"

  section :regsaver_section, RegSaverSection, "div#siteContainer2"
end

-different file-
class RegSaverSection < SitePrism::Section
  element :regsaver_testtest, "#pageContentContainer"
end

The HTML for this section is (see attached pic for clearer picture):

<div id="pageContentContainer" class="clearfix" xpath="1">
      ::before[![enter image description here][1]][1]
      <div id="panelOne">
        <div class="subNavContainer">
          <div id="sequenceMenu">
            <div id="sub-nav-toggle" class="sub-nav-toggle">
              <span class="sub-nav-toggle-text">Show Progress</span>
            </div>
                  <div class="subNav noHeader">
    <ul id="formsBin" class="steps">


        <li class="enabled complete"><a href="https://zachpartyka.sportngin.com/register/form/848624247">Welcome</a></li>

            <li class="enabled complete"><a href="/register/who/005253336">Who Are You Registering?</a></li>



        <li id="form_2959222" class="enabled complete"><a href="/register/form/621807424">Information</a></li>


        
        <li class="enabled complete"><a href="/survey/summary">Review</a></li>
    <li class="enabled selected"><span>Suggested Add-Ons</span></li>
    <li class="enabled incomplete"><span>Shopping Cart</span></li>
    <li class="enabled incomplete"><span>Checkout</span></li>

          <li class="enabled incomplete"><span>Confirmation</span></li>


      
    </ul>
  </div>

            </div>
        </div>
      </div>
      <div id="panelTwo">
        <div id="displayBodyContent">
          <div id="flashNotice">
</div>

          <div id="yieldContent">
              <h2 id="displayBodyHeader" class=""><span>Zach Partyka Demo Site Suggested Add-Ons</span></h2>

            <div id="sales-channels-element__container" style="">
  <sales-channels-element id="sales-channels-element" context="{&quot;multipleRegistrations&quot;:{&quot;enabled&quot;:true,&quot;buttonLabel&quot;:&quot;Register Another person&quot;},&quot;mode&quot;:&quot;user&quot;,&quot;userId&quot;:&quot;49dd822a5d654085a5e4b435b83265cc&quot;,&quot;bossOrganization&quot;:{&quot;id&quot;:230482,&quot;name&quot;:&quot;Sales Channels Test Org&quot;},&quot;guestKey&quot;:&quot;9553ee6b1c99c47deda474f5fb09a074c8820b6188b1ac7031f4452546386b27&quot;,&quot;enabledSalesChannels&quot;:[&quot;MedSaver&quot;,&quot;Skills&quot;,&quot;PitchTrackerBaseball&quot;,&quot;PitchTrackerSoftball&quot;,&quot;RegSaver&quot;,&quot;Ncsa&quot;],&quot;participant&quot;:{&quot;firstName&quot;:&quot;baseballpitchtracker&quot;,&quot;lastName&quot;:&quot;child&quot;,&quot;gender&quot;:&quot;male&quot;,&quot;dob&quot;:&quot;01/01/2006&quot;,&quot;address&quot;:{&quot;address1&quot;:&quot;45645 buttsville&quot;,&quot;address2&quot;:null,&quot;state&quot;:&quot;mn&quot;,&quot;city&quot;:&quot;burning&quot;,&quot;zip&quot;:&quot;55418&quot;,&quot;country&quot;:&quot;US&quot;},&quot;email&quot;:&quot;selenium+actionable_redirect@sportngin.com&quot;,&quot;phoneNumber&quot;:&quot;6515555555&quot;,&quot;graduationYear&quot;:null},&quot;registrant&quot;:{&quot;firstName&quot;:&quot;Actionable&quot;,&quot;lastName&quot;:&quot;Redirect&quot;,&quot;dob&quot;:&quot;01/01/1990&quot;,&quot;address&quot;:{&quot;address1&quot;:&quot;2345 Foo Bar Circle&quot;,&quot;address2&quot;:null,&quot;state&quot;:&quot;MN&quot;,&quot;city&quot;:&quot;Testingville&quot;,&quot;zip&quot;:&quot;55428&quot;,&quot;country&quot;:&quot;US&quot;},&quot;email&quot;:&quot;selenium+actionable_redirect@sportngin.com&quot;,&quot;phoneNumber&quot;:&quot;6515555555&quot;},&quot;requestDetails&quot;:{&quot;eventType&quot;:&quot;Multiple&quot;,&quot;eventCost&quot;:10.0,&quot;programStartDate&quot;:&quot;12/22/2021&quot;,&quot;programEndDate&quot;:&quot;12/22/2022&quot;,&quot;paymentDate&quot;:&quot;12/21/2021&quot;,&quot;sport&quot;:&quot;Baseball&quot;,&quot;submittedBy&quot;:&quot;parent&quot;},&quot;analyticsPageAttributes&quot;:{&quot;depth1&quot;:&quot;Sitebuilder&quot;,&quot;depth2&quot;:&quot;Registration&quot;,&quot;depth3&quot;:&quot;SalesChannels&quot;,&quot;survey_sport&quot;:&quot;Baseball&quot;,&quot;survey_type&quot;:&quot;Event&quot;,&quot;survey_registrant_type&quot;:&quot;parent&quot;,&quot;survey_participant_type&quot;:&quot;athlete&quot;,&quot;survey_participant_dob&quot;:&quot;01/01/2006&quot;,&quot;survey_participant_gender&quot;:&quot;male&quot;},&quot;analyticsEventAttributes&quot;:{&quot;event_action_sports&quot;:&quot;Baseball&quot;,&quot;event_action_genders&quot;:&quot;male&quot;,&quot;event_action_dobs&quot;:&quot;01/01/2006&quot;,&quot;event_type&quot;:1,&quot;action&quot;:&quot;Click&quot;,&quot;bossOrganizationId&quot;:230482,&quot;bossOrganizationName&quot;:&quot;Sales Channels Test Org&quot;,&quot;bossOrganizationAddrState&quot;:&quot;MN&quot;,&quot;bossOrganizationSports&quot;:&quot;baseball&quot;}}" ng-version="10.2.5" style=""></sales-channels-element>

  <div style="display: none;">
    <br>
<div class="pageElement">
  <div class="surveyButtonWrap" style="margin-left:0;text-align: center;">

      <div style="display: inline-block;text-align: right;">
          <form class="button_to" method="post" action="/survey/register_another_person/591168"><input waiting_class="submitProcess pageElement" style="text-transform:capitalize;" class="button-large js-register-another-button" id="processing_link" type="submit" value="Register Another person"><input type="hidden" name="authenticity_token" value="lBrd9OZaA7siTgHe8WYjV3LSqYKUGthsNloEKiMMVeypQUcTUVq/AxLjEjQv0i+Y79R4YPQOMcrlGGwxos/gJw=="></form><div id="waiting_textprocessing_link" style="display:none;" class="pl-overlay"><div class="pl-progress__container"><p class="pl-progress__label">Loading...</p><div class="pl-progress"><div role="progressbar" class="pl-progress__bar--indeterminate"></div></div></div></div>
      </div>

    <div style="display: inline-block; text-align: left;">
          <form class="button_to" method="post" action="/cart/add?from_step=85"><input class="button-large button-siteColor button-default js-continue-button" id="processing_link" type="submit" value="Continue"><input type="hidden" name="authenticity_token" value="lBrd9OZaA7siTgHe8WYjV3LSqYKUGthsNloEKiMMVeypQUcTUVq/AxLjEjQv0i+Y79R4YPQOMcrlGGwxos/gJw=="></form><div id="waiting_textprocessing_link" style="display:none;" class="pl-overlay"><div class="pl-progress__container"><p class="pl-progress__label">Loading...</p><div class="pl-progress"><div role="progressbar" class="pl-progress__bar--indeterminate"></div></div></div></div>
    </div>
  </div>
</div>
<div class="clearAll"></div>

  </div>
</div>

<style>#displayBodyHeader { display: none !important }</style>

<script type="text/javascript" src="https://se-sales-channels.ui.sportsengine.com/sales-channels-element.js"></script>

<script>
  $j(document).ready(function () {
    listenForEventsFromSalesChannelsElement();

    function listenForEventsFromSalesChannelsElement() {
      document.getElementById('sales-channels-element').addEventListener('outputEvent', function(event) {
        switch (event.detail.type) {
          case 'registration':
            registerAnotherOrContinueToCheckout(event.detail);
            break;
          case 'analytics':
            handleAnalyticsEvents(event.detail);
            break;
        }
      });
    }

    function registerAnotherOrContinueToCheckout(eventDetail) {
      if (eventDetail.action === 'registerAnother') $j('.js-register-another-button').click();
      else if (eventDetail.action === 'continue') $j('.js-continue-button').click();
    }

    function handleAnalyticsEvents(eventDetail) {
      const railsEnv = 'production';
      if (railsEnv === 'development') return; // SeMParticle only works for staging and production.
      switch (eventDetail.action) {
        case 'pageView':
          setCookie("surveySport", eventDetail.pageAttributes.survey_sport , 1);
          setCookie("surveyType", encodeURIComponent(eventDetail.pageAttributes.survey_type), 1);
          setCookie("surveyRegistrantType", eventDetail.pageAttributes.survey_registrant_type, 1);
          setCookie("surveyParticipantType", eventDetail.pageAttributes.survey_participant_type, 1);
          setCookie("surveyParticipantDOB", eventDetail.pageAttributes.survey_participant_dob , 1);
          setCookie("surveyParticipantGender", eventDetail.pageAttributes.survey_participant_gender, 1);
          setCookie("bossOrganizationId", encodeURIComponent(eventDetail.pageAttributes.boss_organization_id), 1);
          setCookie("bossOrganizationName", encodeURIComponent(eventDetail.pageAttributes.boss_organization_name), 1);
          setCookie("bossOrganizationAddrState", encodeURIComponent(eventDetail.pageAttributes.boss_organization_addrState), 1);
          setCookie("bossOrganizationSports", encodeURIComponent(eventDetail.pageAttributes.boss_organization_sports), 1);
          window.SeMParticle.pageView(eventDetail.pageAttributes);
          break;
        case 'logImpression':
          window.SeMParticle.logImpression(eventDetail.pageAttributes, eventDetail.productAttributes, 'SalesChannelsImpression');
          break;
        case 'addToCart':
          window.SeMParticle.addToCart(eventDetail.pageAttributes, eventDetail.productAttributes);
          break;
      }
    }

    function setCookie(name,value,exp_days) {
      var d = new Date();
      d.setTime(d.getTime() + (exp_days*24*60*60*1000));
      var expires = "expires=" + d.toGMTString();
      document.cookie = name + "=" + value + ";" + expires + ";path=/;domain=.sportngin.com";
    }
    
   });
</script>

          </div>
          <div class="clearAll"></div>
        </div>
      </div>
    </div>

Screenshot of HTML

rgorowsky
  • 105
  • 1
  • 12
  • You can not _get_ **into** a shadowRoot with a CSS selector. You need JavaScript to retrieve the Custom Element, then dig deeper into it (just like you would do with any Tag) from its ``.shadowRoot`` property. See: https://stackoverflow.com/questions/69867758/how-can-i-get-all-the-html-in-a-document-or-node-containing-shadowroot-elements – Danny '365CSI' Engelman Dec 24 '21 at 13:29
  • I guess then to start, how do I retrieve the custom element? I was hoping to dig into the element with something like `execute_script("return arguments[0].shadowRoot", sales_channels_reg.regsaver_section.regsaver_testtest)`. but that only returns 'nil'. Though if I input `sales_channels_reg.regsaver_section.regsaver_testtest it returns `#` so I can see there is some element I can return. Having difficulty 'stepping' down to find the shadowRoot in the first place – rgorowsky Dec 26 '21 at 08:48

2 Answers2

1

You need to use evaluate_script rather than execute_script or the returned value won't get unwrapped into an element that can be used.

evaluate_script("arguments[0].shadowRoot", ...)
Thomas Walpole
  • 48,548
  • 5
  • 64
  • 78
0

As it turns out, I didn't do a thorough enough investigation. The element was not visible, and I didn't try using visible? along with find_element. The solution to selecting the shadow root - and then digging within it was as follows:

sales_channels_reg.execute_script("return arguments[0].shadowRoot", sales_channels_reg.regsaver_section.regsaver_testtest.find("#sales-channels-element", visible: false)).find('#addToCart--false')

rgorowsky
  • 105
  • 1
  • 12