I've updated login form in Oro application so that now behat tests cannot login to application using 'Given I login as AmandaRCole#example.org buyer'.
The problem is that in this Feature Context (\Oro\Bundle\ApplicationBundle\Tests\Behat\Context\CommerceMainContext) it searches for 'Email Address' and 'Password' form inputs, however these form inputs now have another names. How can I override this context for our needs, or how can I change approach to make tests green?
Login step implemented in OroMainContext
It's implicitly or explicitly (e.g. OroUserBundle suite) by behat.yml configuration injected in each test suite.
Selectors _username, _password and _submit are hardcoded in the loginAsUserWithPassword method.
You can either replace OroMainContext with your inheritor in all behat suites by BehatExtension, see Behat\Testwork\ServiceContainer\Extension, or you can rewrite Oro\Bundle\FormBundle\Tests\Behat\Element\OroForm and do your dirty hack there, because this class will fill the form. Don't forget to rewrite the class for OroForm element in your behat.yml
The right way, I guess, will be to create a Login from, extended from OroForm that should be used in OroMainContext. This form will have method fill that accept two arguments login and password. In this case, you will have rewrite only this tiny element to change the flow. But, I also guess, it's a long way to do so.
Related
Groups page functionality
Background:
Given When the user logs in
Then add the test group
#smoke
Scenario: Verify the groups list page
When the user opens the groups page
Then the group's page title should be visible
Cucumber does not have an after hook like background, but there is a workaround: if you want to run a after hook for a specific feature file then add a tag to the feature file, and then use that tag to write an after hook in the env file.
The given example is for capyabra with ruby
Test.feature
#test_tag
Feature: test feature file
env.rb file
After('#test_tag') do
# code for after hook
end
If you want to run an after hook for a specific scenario, use the same method. Add a tag for the scenario and pass it in after hook.
After('scenario1') do
# code
end
If you want a general after hook to run after every scenario, then we can directly write the After hook without tag
Example:
After do
# code
end
Note: The scenario parameter passed gives information for the scenario e.g scenario.failed? to check if the scenario ran successfully if you want to run logic not associated with scenario details in the After hook you can omit the parameter
Example:
After do|scenario|
if scenario.failed?
page.save_screenshot("path_#{scenario.name.parameterize}.png")
end
end
Wondering the best way to prevent a GTM tag from firing. I found https://rbardini.com/automating-gtm-data-layer-tests/ which tags about fetching the dataLayer variable and comparing it in an assertion, but this looks like a clumsy approach when you want to write to the dataLayer on every page.
For example, it suggests:
const getDataLayer = ClientFunction(() => window.dataLayer)
We use Google Tag Manager to automatically load tags on our website. Unfortunately one of them is CloudIQ (from PayPal) which pops up an iframe overlay offering a newsletter signup or ability to save your shopping basket. The Trigger in our GTM setup for that tag is simply 'All Pages'. When it pops up it generally blocks our test because Selectors cannot be clicked.
Our page flow is over several pages of an online shop, e.g.:
visit home page, click a product - navigates to a product page
click some options on the product page, then add to cart
go through checkout flow
So there might be many pages visited due to click actions.
There is an ability in GTM to define Variables and then use them in Exceptions for a tag, so I could prevent the CloudIQ tag firing either via a/ a global variable or b/ a dataLayer variable. However, I can't see how to elegantly get these set for each page visited during my test, such that they would exist when the GTM examines variables in order to block a Tag from being loaded. Fixture.beforeEach isn't right because it would only run once per fixture, and any data it set on the page's scope would be lost as soon as a page navigation occurs.
Anyone got experience of this sort of thing?
(The alternative of course is to detect the overlay, use switchToIframe to switch into the CloudIQ iframe and close it manually, but it pops up quite erratically and I'd prefer to simply disable the Tag altogether during tests as it's not core functionality of our website that we need to test.)
One way would be to set a custom user agent string to your test suite, create a custom javascript variable that returns the value for navigator.useragent, and make an exception trigger that blocks the tag.
Or any variation on that theme - set a cookie, use a url parameter, or if you test suite allow inject a global js variable, and check for the value in an exception trigger.
There is no need to avoid firing of events on the client side. Just mock the service routes for Google Tag Manager and CloudIQ and imitate correct responses for them.
I have form which contains HTML5 "required" in input type text and password. But when I run test cases using codeception, it is not considering that required property and submits the form.
This is the correct behavior! What do you Codeception to do? The 'required' trait should be processed by the browser. If you submit an incomplete form, something happens - it's not automatically an error, depending on what you're trying to do.
Situation: I needed to add form with POST method to CMS page. I created custom hook and a module displaying the form successfully. Then I need to react to user input errors eg. when user doesn't enter email address I need to detect it, display the whole page again together with the form and with "errors" in user input clearly stated.
Problem: The problem is to display the WHOLE page again with connected information (eg. about errors etc.). In the module PHP file when I add this kind of code,
return $this->display(__FILE__, 'modulename.tpl');
it (naturally) displays ONLY the form, not the whole CMS page with the form.
In case of this code,
Tools::redirectLink('cms.php?id_cms=7');
I can't get to transfer any information by GET neither POST method.
$_POST['test'] = 1;
Tools::redirectLink('cms.php?id_cms=7&test');
I tried to assign to smarty variables too
$smarty->assign('test', '1');
(I need to use it in .tpl file where the form itself is created) but no way to get it work.
{if isset($test)}...,
{if isset($smarty.post.test)}...,
{if isset($_POST['test'])}... {* neither of these conditionals end up as true *}
Even assigning a GET parameter to url has no impact, because there is link rewriting to some kind of friendly url I guess, no matter I included other argument or not. ([SHOPNAME]/cms.php?id_cms=7&test -> [SHOPNAME]/content/7-cmspage-name)
My question is: is there a way to "redirect" or "reload" current page (or possibly any page generally) in prestashop together with my own data included?
I kind of explained the whole case so I'm open to hear a better overall solution than my (maybe I'm thinking about the case in a wrong way at all). This would be other possible answer.
The simplest method would be to use javascript to validate the form - you can use jQuery to highlight the fields that are in error; providing visual feedback on how the submission failed. In effect you don't allow the user to submit the form (and thus leave the page) until you're happy that the action will succeed. I assume that you will then redirect to another page once a successful submission has been received.
There's lots of articles and how-tos available for using javascript, and indeed jQuery for form validation. If you want to keep the site lean and mean, then you can provide an override for the CMS controller and only enqueue the script for the specific page(s) you want to use form validation on.
If the validation is complex, then you might be best using AJAX and just reloading the form section of your page via a call to your module. Hooks aren't great for this kind of thing, so you might want to consider using an alternative mnethod to inject your code onto the cms page. I've written a few articles on this alternative approach which can be found on my prestashop blog
I am writing Behat tests and I need to change the value of a hidden input field
<input type="hidden" id="input_id" ..... />
I need to change the value of this input field, but I keep getting
Form field with id|name|label|value "input_id" not found
I have been using the step
$steps->And('I fill in "1" for "input_id"', $world);
Is there something special which needs to be done to modify hidden input fields?
Despite the fact that user can't fill hidden fields, there are some situations when this is desirable to be able to fill hidden field for testing (as usually rules have exceptions). You can use next step in your feature context class to fill hidden field by name:
/**
* #Given /^I fill hidden field "([^"]*)" with "([^"]*)"$/
*/
public function iFillHiddenFieldWith($field, $value)
{
$this->getSession()->getPage()->find('css',
'input[name="'.$field.'"]')->setValue($value);
}
Rev is right. If real user can can change input fields via javascript by clicking a button or link. try doing that. Fields that are not visible to user are also not visible to Mink also.
Or else what you can do is Call $session->executeScript($javascript) from your context with $javascript like
$javascript = "document.getElementById('input_id').value='abc'";
$this->getSession()->executeScript($javascript);
and check if that works
It's intended by design. Mink is user+browser emulator. It emulates everything, that real user can do in real browser. And user surely can't fill hidden fields on the page - he just don't see them.
Mink is not crawler, it's a browser emulator. The whole idea of Mink is to describe real user interactions through simple and clean API. If there's something, that user can't do through real browser - you can't do it with Mink.
(source: http://groups.google.com/group/behat/browse_thread/thread/f06d423c27754c4d)