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">Welcome</li>
<li class="enabled complete">Who Are You Registering?</li>
<li id="form_2959222" class="enabled complete">Information</li>
<li class="enabled complete">Review</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="{"multipleRegistrations":{"enabled":true,"buttonLabel":"Register Another person"},"mode":"user","userId":"49dd822a5d654085a5e4b435b83265cc","bossOrganization":{"id":230482,"name":"Sales Channels Test Org"},"guestKey":"9553ee6b1c99c47deda474f5fb09a074c8820b6188b1ac7031f4452546386b27","enabledSalesChannels":["MedSaver","Skills","PitchTrackerBaseball","PitchTrackerSoftball","RegSaver","Ncsa"],"participant":{"firstName":"baseballpitchtracker","lastName":"child","gender":"male","dob":"01/01/2006","address":{"address1":"45645 buttsville","address2":null,"state":"mn","city":"burning","zip":"55418","country":"US"},"email":"selenium+actionable_redirect#sportngin.com","phoneNumber":"6515555555","graduationYear":null},"registrant":{"firstName":"Actionable","lastName":"Redirect","dob":"01/01/1990","address":{"address1":"2345 Foo Bar Circle","address2":null,"state":"MN","city":"Testingville","zip":"55428","country":"US"},"email":"selenium+actionable_redirect#sportngin.com","phoneNumber":"6515555555"},"requestDetails":{"eventType":"Multiple","eventCost":10.0,"programStartDate":"12/22/2021","programEndDate":"12/22/2022","paymentDate":"12/21/2021","sport":"Baseball","submittedBy":"parent"},"analyticsPageAttributes":{"depth1":"Sitebuilder","depth2":"Registration","depth3":"SalesChannels","survey_sport":"Baseball","survey_type":"Event","survey_registrant_type":"parent","survey_participant_type":"athlete","survey_participant_dob":"01/01/2006","survey_participant_gender":"male"},"analyticsEventAttributes":{"event_action_sports":"Baseball","event_action_genders":"male","event_action_dobs":"01/01/2006","event_type":1,"action":"Click","bossOrganizationId":230482,"bossOrganizationName":"Sales Channels Test Org","bossOrganizationAddrState":"MN","bossOrganizationSports":"baseball"}}" 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>
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", ...)
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')
I've a problem with Jquery Mobile. Buttons that I add from JS are not displayed properly, and lacks CSS. On the other hand, hitting a button calls that function, but if another button is clicked, because of on off tap, problem occurs. "addExerciseButton" lacks CSS, and the problem occurs within addExerciseButton
<div data-role="page" id="addprogram">
<div data-role="header" data-position="fixed">
<h1>Add Program</h1>
Back
Save
</div><!-- /header -->
<div data-role="content" class='addprogramcontent'>
<div data-role="fieldcontain" class='addprogramlist'>
</div>
</div>
</div><!-- /page -->
JS:
$(document).off("tap").on('tap', '.addExerciseButton', function(event){
//alert(1);
var container = $(this).attr('id');
alert(container);
});
JS page:
eArray.sort();
var container = $("#addprogram").find(".addprogramlist");
container.empty();
// alert(eArray);
for(var i = 1; i <=7; i++)
{
var day = getDay(i);
container.append("<label for='day-" + i + "' class='select'>" + day + "</label>");
var select = $("<select name='day-" + i + "' id='day-" + i + "'></select>");
for (var j = 0; j < eArray.length; j++)
{
select.append("<option value='" + eArray[j] + "'>" + eArray[j] + "</option>");
}
container.append(select);
var addExerciseButton = "<input type='button' value='Add Exercise' class='addExerciseButton' data-role='button' data-theme='b' id='day-" + i + "'/>"
container.append(addExerciseButton);
}
$("select").selectmenu();
$("#day-1").change(function() {
// alert(value);
$("#day-1 option:selected").each(function () {
// alert(1);
var value = $(this).val();
$(this).parent().selectmenu('disable');
alert(value);
});
});
});
you have to refresh buttons after you append em to the dom:
working example: http://jsfiddle.net/PG2bV/55/
CODE
$(":button").button();
Using
container.trigger('create');
solved my problem with no CSS on buttons.
I tried to create pop ups using for-loop, but does not work. Why?
http://jsfiddle.net/edgardaraujo/Rud3G/2/
I thank you all for the help.
content html
<div data-role="page" id="page1">
<div data-role="content">
<div id="output"></div>
</div>
<!-- /content -->
</div>
content jquery
var array = new Array();
array[0] = "link-image-1";
array[1] = "link-image-2";
array[2] = "link-image-3";
var len = Object.keys(array).length;
for (i = 0; i < len; i++) {
var popup = array[i];
$('#output').css({'font-weight': 'bold'}).append('<img class="popphoto" src="' + popup + '" alt="photo, test" style="width:30%">');
var arrayPhotos = $('<div data-role="popup" id="' + popup + '" data-overlay-theme="a" data-theme="d" data-corners="false"></div>');
arrayPhotos.append('Close <img class="popphoto" src="' + popup + '" style="max-height:512px;" alt="photo, test">');
}
Upadate
When you create [data-role=popup] dynamically, you need to enhance its markup by using .trigger('create').
Demo
You have a mistake in href of the link to popup. You have used variable popup which holds image links instead of using the count variable i.
href="#popup' + i + '"
Here
$('#output').css({ 'font-weight': 'bold'}).append('<img class="popphoto" src="' + popup + '" alt="photo, test" style="width:30%">');
And
var arrayPhotos = $('<div data-role="popup" id="popup' + i +'" data-overlay-theme="a" data-theme="d" data-corners="false"></div>');
I try to add several small canvas elements to accordion content area. How can I dynamically extend the width of the content?
http://jsfiddle.net/WBHUk/
<div data-role="page" id="page">
<div data-role="header">
<h1>Header</h1>
</div><!-- /header -->
<div data-role="content" id="content01">
</div><!-- /content -->
<div data-role="footer">
<h4>Footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
$('#content01').append('<div data-role="collapsible-set" data-theme="c" data-content-theme="d" id="acc01"></div>').trigger("create");
$('#acc01').append('<div data-role="collapsible" data-collapsed="false" id="acc01a"><h3>First</h3><div id="acc01a1"></div></div>').trigger("create");
$('#acc01').append('<div data-role="collapsible" id="acc01b"><h3>Second</h3><p>TODO</p></div>').trigger("create");
$('#acc01').append('<div data-role="collapsible"><h3>Third</h3><p>TODO</p></div>').trigger("create");
for(var ch=0; ch<20; ch++){
$('#acc01a1').append('<div id="c_panel'+ ch + '" class="chpanel"></div>');
$('#c_panel' + ch).width(80);
$('#c_panel' + ch).height(30);
$('#c_panel' + ch).append('<canvas id="cccanvas' +ch+ '" class="cccanvas" width="80" height = "30"></canvas>').trigger("create");
$('#c_panel' + ch).css( "position", "relative" );
$('#c_panel' + ch).css( "float", "left" );
$('#c_panel' + ch).css( "background-color", "yellow" );
$('#c_panel' + ch).css( "margin", "2px" );
$('#c_panel' + ch).css( "border-radius", "5px" );
var ctx = $('#cccanvas' + ch)[0].getContext("2d");
}
Many thanks
Matt Jo
here is the html file which calls the above method. When call "callAjax" is clicked, i can get the listview displayed. These listview when clicked will not show navigation bar title.
<body>
<div data-role="page" >
<div data-role="header" data-theme="b" >
<h1>NDUS Directory</h1>
</div><!-- /header -->
<div data-role="content" >
<div id ="divsearch" class ="LogoImage" >
<img src="Images/logo.gif" align="middle" />
</div>
<p></p>
<label for="fname">First Name: </label>
<input type="text" name="fname" id="fname" value="" />
<label for="lname">Last Name: </label>
<input type="text" name="lname" id="lname" value="" />
<p></p>
<input id="callAjax" type="button" value="Search" data-theme="b" />
<!-- TO SHOW PEOCESSING LAG INFORMATION -->
<span id="sp" class = "spanRed"></span>
<div id="resultLog">
</div>
<div id="ajaxBusy" class ="busyAJAX">
<p>
<img src="Images/progress.gif">
</p>
</div>
<span id="placeholder"></span>
<ul id = "idul" data-role="listview" data-theme="b" data-inset="true">
</ul>
</div><!-- /content -->
</div><!-- /page -->
</body>
</html>
here is a sample ajax call which dynamically generates the listview. The code does its job..but the window which shows the details about the listview(when clicked) does not get any title for the navigation bar. In code..it needs to display the txt.firstname and txt.lastname.
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "DirectoryData.asmx/TestSearch",
data: argument,
dataType: "json",
beforeSend: function () {
$("#resultLog").html("Loading" + '<img src="Images/progress.gif" />');
},
success: function (msg) {
var items = [];
$("#unfinshed").remove();
var public_tweets = JSON.parse(msg.d);
if (public_tweets.length > 0) {
// remove older values
$("#placeholder").after('<ol id="unfinshed" data-role="listview" data-theme="b" data-inset="true" data-dividertheme="c"></ol>');
$('<li data-role="list-divider">Records found: ' + public_tweets.length + '</li>').appendTo("#unfinshed");
// $('#unfinshed').empty();
for (var x = 0; x < public_tweets.length; x++) {
var txt = public_tweets[x];
var imageName;
if (txt.type == "Faculty") {
imageName = "Images/BusinessPerson.png";
} else {
imageName = "Images/StudentPerson.png";
}
//<img src="images/gf.png" alt="France" class="ui-li-icon">
$('<li><img src="' + imageName + '" class="ui-li-icon">
<a href="#" >' + txt.firstname + ' ' + txt.lastname + '
</a><p></p><p>' + txt.title + '</p>' +
'<ul data-theme="c" data-inset="true">' +
'<li><span class="dirHeaderFont">' + 'Institution:</span><p></p>
<span class="footerTextFont">' + txt.institution + '</span></li>' +
'<li><span class="dirHeaderFont">' + 'Department:</span><p></p>
<span class="footerTextFont">' + txt.department + '</span></li>' +
'<li><span class="dirHeaderFont">' + 'Title:</span><p></p>
<span class="footerTextFont">' + txt.title + '</span></li>' +
'<li data-icon="grid"><span class="dirHeaderFont">' +
'Phone:</span><p></p><span class="footerTextFont">
<a href="tel:' + txt.phonenumber + '">' + txt.phonenumber +
'</a></span></li>' +
'<li data-icon="search"><span class="dirHeaderFont">' +
'Email:</span><p></p><span class="footerTextFont">
<a href="mailto:' + txt.email + '">' + txt.email +
'</a></span></li>' +
'<li><span class="dirHeaderFont">' + 'Active:</span><p>
</p><span class="footerTextFont">' + txt.active +
'</span></li>' + '</ul>' +
'</li>').appendTo("#unfinshed");
}
$("#unfinshed").page();
} else {
// display no records found
$("#placeholder").after('<ul id="unfinshed" data-role="listview" data-theme="c" data-inset="true"></ul>');
$('<li>' + 'No records found' + '</li>').appendTo("#unfinshed");
$("#unfinshed").page();
} // end of public_tweets check
$("#resultLog").html(' '); // remove the loading image
}
}); // end of ajax
$("#resultLog").ajaxError(function (event, request, settings, exception) {
$("#resultLog").html("Error connecting to database. Try again later.");
//$("#resultLog").html("Error connecting to database. Try again later.: " + settings.url + "<br />HTPP Code: " + request.status);
});
You could try to add a custom title like this:
$("div:jqmData(role='header')").prepend('<h1>Custom Title</h1>');
Might need to tinker with it a tad but it works
UPDATE:
Live Example:
http://jsfiddle.net/phillpafford/trdYP/51/
JS:
$("div:jqmData(role='header') > h1").replaceWith('<h1 class="ui-title" tabindex="0" role="heading" aria-level="1">New Title</h1>');
HTML:
<div data-role="page" id="home">
<div data-role="header">
<h1 >Home</h1>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">Home Page</li>
<li>Page 2</li>
</ul>
</div>
</div>
<!-- Page 2 -->
<div data-role="page" id="page2">
<div data-role="header">
<h1 >Page 2</h1>
</div>
<div data-role="content">
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="f">
<li data-role="list-divider">Home Page</li>
<li>Home Page</li>
</ul>
</div>
</div>