Reputation: 6497
I'm using Behat with Mink and the Drupal extension to test my Drupal 8 website. I've got the tests running over Selenium server on Docker so I can watch them taking place.
My tests are pretty simple, just filling out forms and making sure the results match expectations, like this:
And I fill in "Sesame Street" for "Street address"
And I fill in "FamilyName" for "Last name"
However, I can't get it to work with the credit card field. Here is what I tried so far.
And I fill in "4242424242424242" for "The card number"
And I fill in "4242424242424242" for "edit-payment-information-add-payment-method-payment-details-card-number"
And I fill in "4242424242424242" for "card-number-element"
All of these give the same error:
Form field with id|name|label|value|placeholder "The card number" not found. (Behat\Mink\Exception\ElementNotFoundException)
Note: This test site is configured to use the Stripe test gateway, and I am attempting to use a test credit card number. No real card numbers will ever touch this system.
I think this is because the credit card payment is handled using the Stripe library and this uses some special kind of HTML structure that I'm not famiiar with. Here is the HTML below:
<div data-drupal-selector="edit-payment-information-add-payment-method" class="form-group js-form-wrapper form-wrapper" id="edit-payment-information-add-payment-method"><div class="stripe-form form-group js-form-wrapper form-wrapper" data-drupal-selector="edit-payment-information-add-payment-method-payment-details" id="edit-payment-information-add-payment-method-payment-details"><div id="payment-errors"></div><input id="stripe_token" data-drupal-selector="edit-payment-information-add-payment-method-payment-details-stripe-token" type="hidden" name="payment_information[add_payment_method][payment_details][stripe_token]" value="" /><div id="edit-payment-information-add-payment-method-payment-details-card-number" class="form-item js-form-item form-type-item js-form-type-item form-item-payment-information-add-payment-method-payment-details-card-number js-form-item-payment-information-add-payment-method-payment-details-card-number form-group"><label class="js-form-required form-required control-label" for="edit-payment-information-add-payment-method-payment-details-card-number">The card number</label><div id="card-number-element" class="form-text"></div></div>
How can I target the credit card input and fill in a test card number with Behat?
EDIT: Even if I wait, I get the same error:
And I wait 5 seconds
Upvotes: 1
Views: 735
Reputation: 2184
Hi you need to switch to stripe iframe:
/**
* @When /^I fill stripe credit card informations$/
*/
public function fillCreditCardInformations(int $card = 0)
{
...
$this->switchToIFrame('iframe[name^="__privateStripeFrame"]');
$this->fillField('cardnumber', self::CARDS[$card]);
...
}
/**
* @Given /^I switch to iframe "([^"]*)"$/
*/
public function switchToIFrame(string $locator)
{
$found = false;
$selector = '/' === $locator[0] ? 'xpath' : 'css';
$iframes = $this->getSession()->getPage()->findAll($selector, $locator);
foreach ($iframes as $iframe) {
try {
if ($name = $iframe->getAttribute('name')) {
$this->getSession()->getDriver()->switchToIFrame($name);
$found = true;
break;
}
} catch (Exception $e) {
//ignoring
}
}
if (!$found) {
throw new InvalidArgumentException(sprintf('Could not evaluate CSS Selector: "%s"', $locator));
}
}
Upvotes: 1
Reputation: 34
There are 2 things here:
The stripe field is in an Iframe, search for the iFrame conatining the stripe field, switch to the Iframe then use the regular I fill in as you have used before.
Upvotes: 1
Reputation: 146
The only input field I can see in the code you've provided is for a hidden field. So I suppose that the field you're trying to access is generated dynamically client side inside the #card-number-element
div.
In which case, you need to ensure the browser has finished loading the page before you can check if this is working.
You could use Mink's session wait()
method in your context file if you are using custom definitions. Alternatively, you could try using a different browser when testing with selenium.
Upvotes: 1