Cypress click doesn't trigger the action - cypress

I have a product page with the product quantity control element and the price. On the website, when I click the increase qty button +, the price changes accordingly.
But when I do it with Cypress, I can click the increase button, the product qty changes but the price stays the same. Like if the event was never triggered.
Is there is something like toHaveBeenCalledWith or any listeners I should add to the flow?
Piece of my code:
describe("checkout", describeCheckout);
function describeCheckout() {
beforeEach(() => {
populateCart();
cy.loginUi();
cy.visitPath("/checkout");
cy.wait(3000);
});
// This part works
it("should click increase button on item", increaseItemQty);
}
function increaseItemQty() {
cy.get("increase-qty").click()
}

Try the code below:
describe("checkout", describeCheckout);
function describeCheckout() {
beforeEach(() => {
populateCart();
cy.loginUi();
cy.visitPath("/checkout");
cy.wait(3000);
});
// This part works
it("should click increase button on item", increaseItemQty);
}
function increaseItemQty() {
cy.get("increase-qty").scrollIntoView().click({ force:true })
}

Related

How to write an If/ Else statement in Cypress for finding a button?

I have a page that can hold 25 items and when there are more than 25, then it goes onto the next page, how can I write an if statement to first check if the ‘Next Page Button’ is enabled/ visible and if it is visible/enabled then to click on it and if it is not visible, then to find the item on the current page it is on?
If the Next Page button is enabled/disabled then you can do:
cy.get('next-page-button').then(($btn) => {
if ($btn.is(':enabled')) {
cy.wrap($btn).click() //Click on the next page button
} else {
//Do something when the button is disabled
}
})
If the Next Page button exists/Doesn't exists:
cy.get('body').then(($body) => {
if ($body.find('next-page-button').length > 0) {
cy.get('next-page-button').click() //Button exists and click on the button
} else {
//Do something when the button doesn't exist
}
})
You will need to wait for the page to refresh each time the button is clicked.
If you have an element that indicates the page number, use that. If not you will need to add a hard wait.
const clickUntilDisabled = ($button, page = 1) => {
if (page > 100) return // make sure it does not keep clicking forever
if ($button.is(':enabled') && $button.is(':visible')) {
$button.click()
// page refeshes
cy.contains(`Page ${++page}`) // check the page indicator
// or cy.wait(500)
clickUntilDisabled($button, page) // click again
}
}
cy.contains('button', 'Next Page Button')
.then(clickUntilDisabled)
.then(() => {
// test item here
})

Laravel+Vue | Do something and prevent back button if certain condition

As we know, in mobile web-browser, if you click back button, the web-app will go to previous page, right?
But what if I want to make a certain condition which will prevent the web-app to go to previous page.
For example, if a SweetAlert2 dialog is popped-up, the back button will close the SweetAlert2 dialog.. but if there is no SweetAlert2 dialog, the back button will go to previous page..
The code I expected is like below:
export default {
mounted() {
document.addEventListener("backbutton", function(){
if(is_swal_open){
close_swal_dialog();
return false; // NOTE: i expected this should prevent from go to previous page
}
});
},
}
What you can do is warn the user:
if(is_swal_open)
{
window.onbeforeunload = function() { return "Your warning here."; };
}
or add an event listener like so:
window.addEventListener('beforeunload', function (e) {
if(is_swal_open)
{
// Cancel the event
e.preventDefault();
// Chrome requires returnValue to be set
e.returnValue = '';
}
});

Nativescript angular : handle android back button on different pages

So I use this function to handle android back button :
this._page.on(Page.loadedEvent, event => {
if (application.android) {
application.android.on(application.AndroidApplication.activityBackPressedEvent, (args:AndroidActivityBackPressedEventData) => {
args.cancel = true;
this._ngZone.run(() => {
this.router.navigate(['/parameters']);
});
});
}
})
on different pages (angular components). So on page1.ts I have navigate(['/parameters]) and on page2.ts I have console.log("test"). Problem is wherever I am in the app, pressing back button always do navigate(['/parameters]), also the console.log if i'm on the right page, but it should do console.log only.
It seems to be global, any idea how to override activityBackPressedEvent ?
activityBackPressedEvent is not specific to a page, it's global to your Activity which holds all the pages. Generally, You will not add more than one event listener to this event.
You could do something like below to handle this on page level, probably in app module / main.ts
application.android.on(application.AndroidApplication.activityBackPressedEvent,
(args: application.AndroidActivityBackPressedEventData) => {
const page = frame.topmost().currentPage;
if (page.hasListeners(application.AndroidApplication.activityBackPressedEvent)) {
args.cancel = true;
page.notify({
eventName: application.AndroidApplication.activityBackPressedEvent,
object: page
});
}
});
With above code, activityBackPressedEvent willl be triggered on every page that has a listener.
Now in your page / component in which you want to customise the behaviour you do this,
// Inject Page
constructor(private page: Page) {
this.page.on(application.AndroidApplication.activityBackPressedEvent, this.onBackButtonTap, this);
}
onBackButtonTap(data: EventData) {
this._ngZone.run(() => {
this.router.navigate(['/parameters']);
});
}
I think since you added the handle back button in the event pageLoaded that's why it does not work on other page.
The code that handle back button should be placed in the app starter. I'm using NS Vue & I place this code in my main.js. I think it could be similar in NS angular.
application.android.on(application.AndroidApplication.activityBackPressedEvent, (args:AndroidActivityBackPressedEventData) => {
args.cancel = true;
this._ngZone.run(() => {
this.router.navigate(['/parameters']);
});
});

How to avoid stacking navigation history in tab-bar states

Tab A - Tab B - Tab C
States like below;
tabs.a, tabs.b, tab.c
I want to close app like there is no navigation history when switching in each of tab states
For example: I was in Tab A then I clicked to Tab B and then I clicked to Tab C from now on if user pushes back button the app should close. In normal behaviour navigation history stacks up and if I push back button I'll go to Tab B from Tab C. How to avoid this behaviour
Below is my codes;
.state('tabs', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
.state('tabs.a', {
url: "/a",
views: {
'a-tab': {
templateUrl: "templates/a.html",
controller: 'AController'
}
}
}).state('tabs.b', {
url: "/b",
views: {
'b-tab': {
templateUrl: "templates/b.html",
controller: 'BController'
}
}
}).state('tabs.c', {
url: "/c",
views: {
'c-tab': {
templateUrl: "templates/c.html",
controller: 'CController'
}
}
});
<ion-tabs class="tabs-royal tabs-striped">
<ion-tab title="A" href="#/tab/a">
<ion-nav-view name="a-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="B" href="#/tab/b">
<ion-nav-view name="b-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="C" href="#/tab/c">
<ion-nav-view name="b-tab"></ion-nav-view>
</ion-tab>
</ion-tabs>
You can intercept the back button in each of your controllers.
From the documentation:
registerBackButtonAction(callback, priority, [actionId]) Register a
hardware back button action. Only one action will execute when the
back button is clicked, so this method decides which of the registered
back button actions has the highest priority.
For example, if an actionsheet is showing, the back button should
close the actionsheet, but it should not also go back a page view or
close a modal which may be open.
The priorities for the existing back button hooks are as follows:
Return to previous view = 100 Close side menu = 150 Dismiss modal =
200 Close action sheet = 300 Dismiss popup = 400 Dismiss loading
overlay = 500
Your back button action will override each of the above actions whose
priority is less than the priority you provide. For example, an action
assigned a priority of 101 will override the 'return to previous view'
action, but not any of the other actions.
In your controllers you can register a listener for the back button and exit if it has been pressed:
.controller('AController', function($scope, $ionicPlatform){
var deregister = $ionicPlatform.registerBackButtonAction(
function () {
ionic.Platform.exitApp();
}, 100
);
$scope.$on('$destroy', deregister)
})
.controller('BController', function($scope, $ionicPlatform){
var deregister = $ionicPlatform.registerBackButtonAction(
function () {
ionic.Platform.exitApp();
}, 100
);
$scope.$on('$destroy', deregister)
})
.controller('CController', function($scope, $ionicPlatform){
var deregister = $ionicPlatform.registerBackButtonAction(
function () {
ionic.Platform.exitApp();
}, 100
);
$scope.$on('$destroy', deregister)
});
NOTES:
Your last tab (C TAB) should have the name: c-tab:
<ion-tab title="C" href="#/tab/c">
<ion-nav-view name="c-tab"></ion-nav-view>
</ion-tab>
I have done it with a simple way
Added a function in controller scope of tabs state
.state('tabs', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html",
controller: function($scope, $ionicTabsDelegate, $ionicHistory) {
$scope.rt = function(e, index) {
$ionicTabsDelegate.select(index);
//e.preventDefault();
$ionicHistory.nextViewOptions({historyRoot:true});
}
}
})
and added ng-click on each ion-tab directive in tabs.html template like below;
<ion-tab ng-click="rt($event, 0)" title="A" href="#/tab/a">
The second parameter of rt function is the index of tab
I used $ionicHistory.nextViewOptions({historyRoot:true});
From the documentation
nextViewOptions()
Sets options for the next view. This method can be
useful to override certain view/transition defaults right before a
view transition happens. For example, the menuClose directive uses
this method internally to ensure an animated view transition does not
happen when a side menu is open, and also sets the next view as the
root of its history stack. After the transition these options are set
back to null.
Available options:
disableAnimate: Do not animate the next transition.
disableBack: The next view should forget its back view, and set it to null.
historyRoot: The next view should become the root view in its history stack.
That way I achieved what I want

Activiate jQuery function based on radio button selection w/o using .change

When my ASP MVC 3 page loads, the user may or may not have a value selected from a group of radio buttons. If, when the page loads, a value is selected (before the user clicks on a button), how would i activate a jquery function?
Currently I use a .change() method to activate some code which decides what menu to display:
$(document).ready(function () {
$('input[name=TransactionType]').change(function () {
//Clear out values
$('input:text').val('');
$('input:text').text('');
//Display input fields
var radioValue = $(this);
$('#RightDiv').children().each(function () {
if (radioValue.attr('id') == $(this).attr('id')) {
$(this).show();
} else {
$(this).hide();
}
});
});
});
Something like that should work :
$('input[name=TransactionType]').change(function () {
//Your code
}).filter(':checked').trigger('change');
I am asuming the input are checkbox's, if that's not the case, you can remove the .filter().
Trigger doc : http://api.jquery.com/trigger/

Resources