Handle redirects and implicit at assertions - geb

The website I want to test has a landing page which asks you to chose a language. You can skip this question by adding an extra parameter in the url. I want to test this behaviour with Geb and Spock as testing framework.
So I have the landing page with language selection:
class LanguageSelectionPage extends Page {
static url = "http://localhost:8080/registration/"
static at = { $("form#languageForm") }
}
The second page where it redirects to:
class InsertCardReaderPage extends Page {
static at = { welcomeTitle1 }
static content = {
welcomeTitle1(wait: true, cache: false) { $("#eidWelcomeTitle1") }
welcomeTitle2(wait: true, cache: false) { $("#eidWelcomeTitle2") }
}
}
(I've removed some methods from the pasted code)
So this is my test:
given:
to LanguageSelectionPage, "09";
expect:
at InsertCardReaderPage;
The "09" is an extra parameter in the url, when this one is available you will be immediatly redirected by the server (http redirect, so the page does change) to the InsertCardReaderPage. Now, my problem is that the to statement performs an implicit assertion on the at closure. This one fails because you have been redirected away from the page already.
Is there a way to conditionally disable this implicit assertion in this case? Or any other proposal how to setup the pages? I'm pretty new to Geband can't find any documentation that seems to help me in this case.

Use via instead of to
given:
via LanguageSelectionPage, "09";
expect:
at InsertCardReaderPage;
Geb Manual

Related

Cypress - run test in iframe

I'm trying to find elements in iframe but it doesn't work.
Is there anyone who have some system to run tests with Cypress in iframe? Some way to get in iframe and work in there.
It's a known issue mentioned here. You can create your own custom cypress command which mocks the iframe feature. Add following function to your cypress/support/commands.js
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe, selector) => {
Cypress.log({
name: 'iframe',
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
resolve($iframe.contents().find(selector));
});
});
Then you can use it like this:
cy.get('#iframe-id')
.iframe('body #elementToFind')
.should('exist')
Also, because of CORS/same-origin policy reasons, you might have to set chromeWebSecurity to false in cypress.json (Setting chromeWebSecurity to false allows you to access cross-origin iframes that are embedded in your application and also navigate to any superdomain without cross-origin errors).
This is a workaround though, it worked for me locally but not during CI runs.
This works for me locally and via CI. Credit: Gleb Bahmutov iframes blog post
export const getIframeBody = (locator) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(locator)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
spec file:
let iframeStripe = 'iframe[name="stripe_checkout_app"]'
getIframeBody(iframeStripe).find('button[type="submit"] .Button-content > span').should('have.text', `Buy me`)
that is correct. Cypress doesn't support Iframes. It is simple not possible at the moment. You can follow (and upvote) this ticket: https://github.com/cypress-io/cypress/issues/136

How to a hide a page

I have a pop up that is called through a java script, the same pop up without a JavaScript is an ctp page in cakephp. How can I hide that page from users and search engines going to access it like: /users/register
Is there anything that can be done in .htaccess or cakephp to prevent access to it through /users/register
Remove register.ctp file from users folder and create one in ajax folder users/ajax/register.ctp, then use RequestHandler component to inspect request type:
public function register()
{
if($this->request->is('ajax')){
// add registration code here
} else {
//Throw new error
}
}

How to stop Internal link redirection looping in prestashop

In my prestashop site with in a jquery script i have written an if condition.If the "if" condition is true,I want to redirect my site to login page .Condition is false means it should redirect to the contact us page.But this internal link redirection is keep on redirecting based upon condition. Instead of the prestashop site url if i have provided an external url means redirection happening only once properly.How to overcome this multiple redirection looping problem with this internal site links?
Note: Just for example i have expalined with login page and contact page.It may be any of the prestashop page.
<script type="text/javascript">
var code=firstshop;
if( code == "firstshop" )
{
window.location="http://localhost/jewellery/shop1/";
}
else
{
window.location="http://localhost/jewellery/shop2/";
}
//
</script>
You should provide more information on your "condition" or post some code. You probably need to check that the visitor is not already on the page that is desired
if (condition && !isLoginPage) {
} else if (!condition && !isContactUsPage) {
}

AngularJS - permission directive

I am trying to write directive that will evaluate user permissions.
In case user is not permitted to see given content
the content will not be displayed (done, working fine)
requests from controllers inside permission directive will not get
fired.
Example:
Controller:
function MyController ($scope){
// performing imediately server request, witch is allowed only for admin
// therefore i will get error when non admin user access this page
}
Permission directive:
return {
priority: 1000,
restrict: 'E',
link: (scope, element, attrs) => {
var permission = attrs.permission;
if (/*evaluating permission*/) {
// user has permission, no work for me
return;
}
element.remove();
}
};
All together:
<permission permission="isAdmin">
<div ng-controller="MyController">
</div>
</permission>
This version is removing elements from DOM, but request in MyController still gets executed. Off course, I can make check for permissions in MyController, but I don't want to.
Thank for help.
Your issue is that the controller will always be called before the link function executes. See this fiddle.
function MyCtrl($scope) {
console.log('in controller');
}
myApp.directive('permission', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
console.log('in link');
Log shows:
in controller
in link
I tried another approach and put removal of element into compile function. According to log, it is executed BEFORE controller, so it is right place. Anyway the request was still fired. So I tried just as a blind shot remove element children (I know, it does not make sense, removal of element should be sufficient and should remove children also).
But it worked!
compile: function(element) {
var children = element.children();
children.remove(); element.remove();
}
It is working, but I am not sure how much OK it is (e.g. future version Ang.)
If I were you I would make a call to the server and check if they are authorised for access.
Doing this with a directive does not really make sense.
Directives are generally for manipulating dom and this is authorisation confirmation should generally be handled in the controller and then have the result of that trigger an event.
Then have your directive be listening for that event and manipulate the dom if they got access from the server.
Otherwise anyone could easily just inject whatever they wanted and see your admin panel.
If your not sure what I mean let me know I can expand the answer if you need me to.

Multiple whitelists/blacklists for content script injection?

I'm building a Safari extension with two different content scripts. One script needs to be injected into all http pages (but not https pages). The other one only gets injected into google.com pages regardless of scheme.
In order to achieve this, I have set Extension Website Access to:
This should mean that at a high level, content scripts in my extension should be able to access all pages.
To get more fine-grained control, I then programatically inject the content scripts into URLs which match my patterns.
App = {
content: {
// Inject into unsecure pages.
whitelist: ['http://*/*'],
// But not into secure pages.
blackList: ['https://*/*'],
loc: safari.extension.baseURI + 'data/content.js'
},
results: {
// Inject this script into all google.com pages
whiteList: ['http://*.google.com/*', 'https://*.google.com/*'],
// Surely I don't need a blacklist if I specify a whitelist?
blacklist: undefined,
loc: safari.extension.baseURI + 'data/results.js',
}
};
// Inject the first content script.
safari.extension.addContentScriptFromURL(App.content.loc,
App.content.whitelist, App.content.blacklist, false);
// Inject the second content script.
safari.extension.addContentStyleSheetFromURL(App.results.cssLoc,
App.results.whitelist, App.results.blacklist, false);
The problem is that both scripts are being injected into all pages. It's as if my white and blacklists do nothing. What am I doing wrong?
I was using capitals in my whilelist/blacklist definitions at the top:
App = {
content: {
blackList: ['https://*/*'],
},
results: {
whiteList: ['http://*.google.com/*', 'https://*.google.com/*']
}
};
But then using non-capitalized versions of the variables when I pass the lists into the script injection function.
safari.extension.addContentScriptFromURL(App.content.loc, App.content.whitelist, App.content.blacklist, false);
This obviously means that undefined was being passed into the injection function rather than an actual whitelist/blacklist.