Comment cliquer sur une "option de sélection", puis évaluer le contenu chargé avec casperjs

J'essaie de ramasser les tailles pour ce produit:

Lien vers le produit

Le problème: les tailles sont chargées après sélection de la couleur du produit.

Dans le code source de la page du produit, je peux voir que le menu déroulant a une méthode onchange: il clique sur le formulaire #postColor onchange.

Le menu déroulant sélectionné:

<select name="color" id="color" class="cposelect" onchange="document.getElementById('postColor').click();" style="width:150px;margin-right: 20px; float: left;"> <option selected="selected" onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="0">Select colour</option> <option onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="-8027">Light Camel</option> <option onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="-9999">black</option> </select> 

Le formulaire #postColor, qui est cliqué sur le changement:

 <input type="submit" name="postColor" value="" onclick="location.href=('./?model=10344-4180&amp;color='+document.forms[0].color.value+'&amp;size='+document.forms[0].size.value+'&amp;addbread=OUTLET&amp;addbread2=DRIZIA&amp;currentimage='+document.getElementById('currentimage').value+'&amp;selectedmi=a1_INDEX_14&amp;prev=10850-4314&amp;next=10413-4183'); return false;" id="postColor" class="cpobutton " style="display: none;"> 

C'est mon code jusqu'à présent et ça ne fonctionne pas:

 casper.start('http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&addbread=OUTLET&addbread2=DRIZIA&color=0&currentimage=1&selectedmi=a1_INDEX_14', function() { this.test.assertExists('select[name="color"] option:nth-child(2)'); this.click('select[name="color"] option:nth-child(2)'); this.waitForSelector('select[name="size"] option:nth-child(2)', function() { this.test.pass('selector is !'); var sizes = this.evaluate(function() { console.log("======== evaluating ========"); // var sizes = document.querySelectorAll('#size option'); return document.querySelectorAll('#size option'); }); for (var i = sizes.length - 1; i >= 0; i--) { console.log(sizes[i].innerText); } }); }); 

Je soupçonne que le problème est qu'une page totalement nouvelle est chargée lorsqu'une couleur est cliquée (les tailles ne sont pas ajoutées dynamiquement).

Comment résoudriez-vous ce problème?

C'est comme ça que je le fais

 this.evaluate(function() { $('#select_element_selector').val('value').change(); }); 

Le change() est très important

Je suppose que vous avez jQuery sur la page

J'ai le même problème ici. Ma solution est:

 casper.then(function(){ this.evaluate(function() { document.querySelector('select.select-category').selectedIndex = 2; //it is obvious }); this.capture('screenshot.png'); }); 

La solution jQuery recommandée ne fonctionne pas réellement pour moi.

 casper.evaluate(function() { $('#select_element_selector').val('value').change(); }); 

Alors, la commande capture() affiche l'option de sélection telle que sélectionnée visuellement, elle ne déclenche pas l'événement. Essayez d'utiliser ceci avec la commande waitForText() par exemple; Le programme va expirer.

 casper .start('http://factfinder.census.gov/faces/tableservices/jsf/pages/productview.xhtml?pid=DEC_00_SF1_DP1&prodType=table') .waitForText('Add/Remove Geographies', function () { casper.click('#addRemoveGeo_btn'); }) .waitForText('Select a geographic type:', function () { casper.evaluate(function () { $('#summaryLevel').val('050').change(); }); }) .waitForText('Select a state:', function () { casper.capture('test.png'); }) .run(); 

Ce qui a fonctionné pour moi, c'était le code ci-dessous (merci @ArtjomB). Comment remplir un élément sélectionné qui n'est pas intégré dans un formulaire avec CasperJS?

 casper.selectOptionByValue = function(selector, valueToMatch){ this.evaluate(function(selector, valueToMatch){ var select = document.querySelector(selector), found = false; Array.prototype.forEach.call(select.children, function(opt, i){ if (!found && opt.value.indexOf(valueToMatch) !== -1) { select.selectedIndex = i; found = true; } }); // dispatch change event in case there is some kind of validation var evt = document.createEvent("UIEvents"); // or "HTMLEvents" evt.initUIEvent("change", true, true); select.dispatchEvent(evt); }, selector, valueToMatch); }; casper.selectOptionByValue('#summaryLevel', '050'); 

Bien que je pense que CasperJS devrait fournir un support natif pour sélectionner les options à partir d'un menu déroulant lorsqu'il n'est pas séparé d'un formulaire ( http://docs.casperjs.org/en/latest/modules/index.html ). Selenium offre les commandes select et addSelection ( https://seleniumhq.github.io/selenium/docs/api/javascript/index.html ). J'ai également déposé un ticket d'émission en attente sur la page CasperJS GitHub pour l'implémenter nativement ( https://github.com/n1k0/casperjs/issues/1390 ).

C'est un code simple pour entrer les détails de la carte de crédit dans casper js

Casper.evaluate (fonction (CC, security_code) {

  document.querySelector('input#receipt_creditcard_number').value = CC; document.querySelector('select#receipt_creditcard_month').selectedIndex = 10; document.querySelector('select#receipt_creditcard_year').selectedIndex = 10; document.querySelector('input#receipt_creditcard_verification_value').value = security_code; document.querySelector('input#receipt_save_creditcard_in_profile').click(); }, '4242424242424242','123'); 

Tricky, mais en regardant l'URL, je pense que Casper peut bien gérer cela.

Permettez-moi de savoir si vous avez besoin d'aide pour le code, mais cela prendra un peu plus de temps pour vous donner un peu de pseudo-code,

  • Créez un objet vide de couleurs et d'ID de couleur {couleur: colorId}
  • Comme vous le faites déjà, trouvez le menu de sélection avec [nom = 'couleur'] et faites passer ces options. Pousse tout ce qui n'a pas une valeur de 0 à votre objet
  • Écrivez une nouvelle fonction qui ira à l'URL http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=-9999&size=0&addbread=OUTLET&addbread2=DRIZIA&currentimage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183 et color=-9999 ID de couleur où color=-9999 .

Exemple:

'http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=' + object.colorId + '&size=0&addbread=OUTLET&addbread2=DRIZIA&currentimage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183'

  • Soit ajoutez les tailles à l'objet de couleurs existantes, soit créez une nouvelle, soit console. Inscrivez-les. Le monde vous appartient!

Je ne sais pas si vous avez trouvé une solution à votre problème, mais voici comment je le résoudrais:

 casper.click('#color'); casper.then(function() { casper.waitFor(function check() { return this.evaluate(function() { return document.querySelector('select.select-category').selectedIndex === 2; }); }, function then() { /* do the rest that you would want to do!*/ }); } 

Une façon légèrement piquante de le faire sans utiliser jQuery en utilisant des méthodes casper intégrées est:

 // Assumes the select box is on the first item at index 0 chooseSelectOption = (friendlyName : string, selectLocator : string, optionIndex : number) => { casper.test.assertExists(selectLocator, "then select index " + optionIndex + " in the " + friendlyName + " select box"); casper.click(selectLocator); this.goDown(selectLocator, optionIndex); }; // recursive funtion to go down various levels private goDown = (locator: string, depth : number, currentLevel : number = 0) => { if (currentLevel >= depth) { return; } casper.sendKeys(locator, casper.page.event.key.Down, { keepFocus: true }); this.goDown(locator, depth, currentLevel + 1); }; 

Ceci est dans TypeScript, mais vous pouvez éditer pour vanilla JS si vous le souhaitez. Vous devez utiliser une fonction récursive car une boucle normale se heurte à des difficultés avec le système de mise en file d'attente de capsers.

Solution vanilla javascript (méthode déclenchant onchange):

 casper.evaluate(function() { var select_element = document.getElementById('#select_element_selector'); select_element.value = 'value'; select_element.onchange(); });