J'écris un scénario avec Ruby et Capybara. Ce script doit télécharger un fichier et une fois le fichier téléchargé, le script doit cliquer sur le bouton "Enregistrer". J'ai réussi à faire démarrer le téléchargement du fichier, mais après plusieurs secondes, le script s'arrête. En fin de compte, le fichier n'est pas téléchargé et je dois tout recommencer à zéro.
Il y a un bouton "Enregistrer" sur la page qui reste désactivé jusqu'à ce que le fichier soit téléchargé. J'ai donc essayé d'utiliser son état comme indicateur. Mais Capybara ne le reconnaît pas.
Mon code:
upload_btn = browser.all(:element, 'span', text: 'Upload') browser.attach_file($app_path) do upload_btn[0].click end browser.has_button?('Save', wait: 200) browser.click_on('Save')
A quoi ressemble l'interface utilisateur de la page (désolé pour la capture d'écran):
Je suppose que cela ne fonctionne pas car ce n'est pas un button
mais un button
material-button
et Capybara ne reconnaît pas cet élément. Utiliser des classes / identifiants n'est pas la meilleure idée car toutes les classes sont dynamiques et je ne peux pas compter dessus
Pourriez-vous nous dire ce qui pourrait être fait ici? Ou comment faire attendre capybara jusqu'à ce que ce bouton soit désactivé?
Merci!
3 Réponses :
En supposant que la classe is_disabled
et l'attribut disabled
sont supprimés lorsque le bouton devient actif, vous pouvez utiliser l'un des éléments suivants (en supposant que 200 secondes suffisent pour que le téléchargement se termine)
find(:element, 'material-design', 'debug-id': 'save-button', disabled: false, wait: 200).click find(:element, 'material-design', disabled: false, text: 'Save', wait: 200).click
Si le debug-id
est disponible et stable, vous pouvez ignorer l'option de text
, qui sera plus efficace
find("material-button[debug-id='save-button']:not([disabled])", wait:200).click
Une dernière option serait d'utiliser le type de sélecteur Capybara: élément
find('material-button:not([disabled])', text: 'Save', wait: 200).click find('material-button:not(.is_disabled)', text: 'Save', wait:200).click find('material-button', class: '^is_disabled', text: 'Save', wait: 200).click # The ^ in front of the class name indicates to negate
Non pas que je sois un expert mais l'attente est-elle réellement nécessaire? Il semble que (selon ma lecture) capybara attendra automatiquement de trouver jusqu'à ce que le match se produise.
@engineersmnky Par défaut, Capybara attendra jusqu'à Capybara.default_max_wait_time
qu'une condition soit remplie. La valeur par défaut est de 2 secondes, et en fonction du matériel utilisé pour les tests, elle est généralement définie quelque part dans la plage de 1 à 5 secondes. Sur la base de la publication originale, je suppose que le téléchargement ne se termine pas dans cette plage, donc j'ai inclus l'option d' wait
. C'est un temps d'attente maximum, donc quand la condition est remplie, elle continuerait (c'est-à-dire qu'elle n'attendrait pas les 200 pleins) donc le pire des cas est qu'elle retarde les cas d'échec si / quand le téléchargement échoue réellement.
Parfait. Considérez-moi édifié. J'apprécie la clarification et maintenant je sais si j'aurais besoin d'utiliser capybara à l'avenir.
Le revirement pour moi était un peu différent de ce que vous avez écrit. Mais la plus proche était la dernière variante que vous avez proposée. Je vais poster la solution maintenant ci-dessous. Merci pour vos conseils, les gars!
Donc, le redressement n'était peut-être pas des plus professionnels, mais au moins cela a fonctionné et je peux automatiser certaines choses maintenant.
Fondamentalement, j'ai utilisé has_button?
pour que mon script attende que le fichier APK soit téléchargé. 200 secondes suffisent pour le téléchargement de fichiers (statistiquement). À la fin, le script fait une pause mais j'ai décidé d'ajouter sleep 3
à la fin juste pour être du bon côté.
Voici la fonction qui télécharge l'APK pour moi. Peut-être que quelqu'un en aura besoin
def create_release puts('Create release and upload APK') browser.find(:element, 'div', role: 'menuitem', text: 'Production').click create_release_btn = browser.all(:button, text: 'Create new release') create_release_btn[0].click #OPT out browser.click_button('Manage preferences', wait: 200) sleep 2 browser.choose('Opt out of app signing by Google Play') browser.click_button('Update', wait: 100) sleep 3 op_out_btn = browser.all(:button, text: 'Opt out', wait: 500) op_out_btn[0].click sleep 4 #File upload part and saving upload_btn = browser.all(:element, 'span', text: 'Upload') browser.attach_file($app_path) do upload_btn[0].click end save_btn = browser.all(:element, 'material-button', text: 'Save', disabled: false, wait: 200) browser.has_button?(save_btn, disabled: false, wait: 200) button_test = browser.all(:button, text: 'Save', wait: 100) button_test[0].click sleep 3 end
Maintenant que OP a publié sa méthode complète, pour quiconque aborde cette question plus tard, veuillez ne pas écrire de code Capybara comme dans la réponse actuellement acceptée.
N'utilisez pas all
lorsque vous vous souciez uniquement du first
élément
N'utilisez pas le type de sélecteur d'élément: lorsque vous n'en avez pas vraiment besoin
N'utilisez pas les méthodes de prédicat juste pour attendre
Préférez une attente / une affirmation plutôt que de simplement dormir
Cela se résume à quelque chose de plus comme
def create_release puts('Create release and upload APK') browser.find('div[role="menuitem"]', text: 'Production').click browser.first(:button, 'Create new release').click #OPT out browser.click_button('Manage preferences', wait: 200) # 200 seems like a really long max wait time here browser.choose('Opt out of app signing by Google Play') browser.click_button('Update', wait: 100) # again - seems really long browser.first(:button, 'Opt out', wait: 500).click # and again #File upload part and saving browser.attach_file($app_path) do browser.first('span', text: 'Upload').click end expect(browser).to have_selector(:element, 'material-button', text: 'Save', disabled: false, wait: 200) browser.first(:button, 'Save', wait: 300).click expect(browser).to ... # whatever change clicking the button triggers end
Sympa, merci Thomas, je vais essayer de le mettre en œuvre