Cucumber.js Before hook not working on tagged Scenario - cucumberjs

I am writing UI tests using cypress and cucumber (with the cypress-cucumber-preprocessor).
I'm trying to write a Before hook, that will automatically delete local storage. I want to run this hook only for some of the tests (ones that have a login stage as part of the Given stage. Deleting the storage makes sure the app is not logged in when the test starts).
I'v added a tag to both the Before hook and to the Scenario, but the step in the hook is not being executed. I know this because when I run the test the login steps fail, because the storage isn't cleared and the app stays logged in from the last run.
If I delete the tag from the Before and from the Scenario, then the Before hook is executed, the local storage wiped and the login stages run without a problem.
What am i doing wrong?
Here is the hook:
Before({tags: "#clear_storage"},()=>{
indexedDB.deleteDatabase('firebaseLocalStorageDb')
})
and the Scenarios:
#clear_storage
Feature: tasks view
Scenario Outline: validate task selection buttons
Given User is logged in
And User is in tasks screen
When User clicks on <task view controler> button
Then Task <selection menu validator> is visible
Examples:
| task view controler | selection menu validator |
| tasks_status | "All Tasks" |
| tasks_filter | "My Tasks" |
| tasks_sort | "Rank" |
and the step definition for the Given stage:
onst username = 'integration-test#sedric.me'
const password = 'integration-test#sedric.me'
Given('User is logged in', ()=>{
cy.visit('https://sedric-dev-a8294.web.app/app/')
cy.get('#login_username_input').type(username)
cy.get('#login_password_input').type(password)
cy.get('#login_submit_button').click()
})

Related

Why cypress loads login page again instead of home page?

I wrote a cypress script to log in to the application ( enter the user id, password and click the log-in button), and expecting to load the home page. Cypress enters the user id, password and clicks the button but, loads the login page again instead of the home page.
Below is my script to login:
`
cy.visit('https://digitalxq1.com/sis/basic?accountNumber=123456');
cy.enterText(txtUserID, userid);
cy.enterText(txtPwd, 121212);
cy.clickElement(btnPwd);
Has anyone faced a similar issue? And, Does anyone knows the solution? Please assist.
The nature of the application forced me to log in first without account no- " cy.visit('https://digitalxq1.com/sis/basic'" and reload the app with account number after that - "cy.visit('https://digitalxq1.com/sis/basic?accountNumber=123456')" ).
I made mistake of doing the refresh immediately after clicking on login button as below:
cy.visit('https://digitalxq1.com/sis/basic');
cy.enterText(txtUserID, userid);
cy.enterText(txtPwd, 121212);
cy.clickElement(btnPwd);
cy.visit('https://digitalxq1.com/sis/basic?accountNumber=123456'
Somehow cypress unable to respond to the refresh and loaded the login page again. As a solution, I did validate whether the app is loaded or not after clicking login button. Then proceeded with refresh as below:
cy.visit('https://digitalxq1.com/sis/basic');
cy.enterText(txtUserID, userid);
cy.enterText(txtPwd, 121212);
cy.clickElement(btnPwd);
cy.get(#testElement). should('have.length',2);
cy.visit('https://digitalxq1.com/sis/basic?accountNumber=123456'
This approach resolved my issue.
Try this cy.reload(); this will work.
If you want to reload the page with cache then try this cy.reload(true)

NativeScript Angular routing error after changing context of application

I apologize at the start for the lengthy explanation that follows. I believe it is necessary to fully explain what is going on.
I setup my NS app to used tabbed navigation with a login screen by following the writeup here.
The overall structure of the app is identical to the structure of the app in the git repo here.
Instead of the players and teams in the git repo I have 3 tabs: Dashboard, Advisor, and Tasks. The tasks component uses a tasks service to get the tasks for the user via an API call and then displays a list of tasks. The user can tap on the task to view the task details. I use a class called Global that is imported by all of the components to store context info such as the username and the API token that was acquired after authenticating.
I replaced the welcome component with a profile component, the idea being that a profile button is displayed in the ActionBar, and from anywhere in the tab view the user can tap the profile button to view the profile page. I achieved this by including the following code in each of the tab components:
toProfile() {
this.re.navigateByUrl("/profile");
}
I am sure that is not the most efficient way to do it but it was what I came up with and it works. The profile page shows a bit of info and allows the user to log out. If the user is designated as an admin it provides a form to allow the admin user to impersonate any other user and see the app exactly as that user would.
The following code displays the impersonate form:
<GridLayout *ngIf="isAdmin" columns="auto, auto" rows="auto, auto">
<TextField hint="username" [(ngModel)]="impersonateUser" row="1" col="0"></TextField>
<button text="Impersonate" (tap)="impersonate()" row="1" col="1"></button>
</GridLayout>
The profile component imports the user service, task service, and the Global class. When an admin user enters a username (for example we will use "user2") and taps "impersonate" the following function in the profile component is called:
impersonate() {
Global.username = this.impersonateUser;
Global.isAdmin = "0";
this.taskService.reset();
this.userService.getUserInfo(Global.username)
.subscribe(
(resp) => {
this.userService.saveSession(Global.username, Global.token, Global.expires);
this.re.navigateByUrl("/tabs/default", {clearHistory: true});
},
(exception) => {
alert("Something went wrong.");
}
);
}
The task service reset function just clears any data the task service had in memory. I am navigating to /tabs/default at the end to trigger the onInit functions of the components so that new tasks will get pulled for the user being impersonated. The tasks page loads and displays the correct tasks that correspond to user2 via the following code:
<ng-template ngFor let-task [ngForOf]="tasks">
<GridLayout class="data-container" columns="*, auto" rows="auto, auto" [nsRouterLink]="['../task', task.ID]">
<Label [text]="task.TITLE" class="task-title" row="0" col="0"></Label>
<FlexboxLayout class="task-date" row="1" col="0">
<Label [text]="task.START_DATE | slice:0:10 | date:'MMM d, yyyy'"></Label>
<Label text=" - "></Label>
<Label [text]="task.END_DATE | slice:0:10 | date:'MMM d, yyyy'"></Label>
</FlexboxLayout>
<Label text="" class="fas task-status" [ngClass]="{'completed' : task.COMPLETED}" rowSpan="2" col="1"></Label>
</GridLayout>
</ng-template>
Everythign works up to this point. When the admin user taps on one of the tasks to view the task details I get the following error:
Error: Uncaught (in promise): TypeError: undefined is not an object (evaluating 'this.currentOutlet.peekState')
When I inspect the elements with Chrome dev tools I can see that the GridLayout element has the proper ID that matches the task it should link to
<GridLayout ng-reflect-params="../task,5e46c219add54" iosOverflowSafeArea="true" classNAme="data-container">
Any help or insight would be greatly appreciated. I am relatively new to both Angular and NativeScript.
EDIT:
Here is a link to a NS playground where you can see the issue in action. I have removed just about everything that is not needed to replicate the issues.
To replicate:
Sign in with the username "u1".
Go to the tasks tab and tap one of the tasks. You will be taken to the task details.
Tap the Profile button on the Activity bar.
On the profile page enter u2 in the username field under Admin and tap the impersonate button. You will be returned to the dashboard as user2.
Go to the tasks tab and tap one of the tasks.
Tapping on the task should take you to the task details but instead, it produces the error described above.
NOTE: Tapping on any of the tasks on the dashboard at any time will not work. That is another issue I am trying to figure out. If you can help me figure out what I am doing wrong there as well it would be much appreciated.

Jhipster cannot use anonymous user before login

When I visit to jhipster websit pre-login, it always displays error message (User could not be found).
In jhipster project, where to setup anonymous user for pre-login?
I also have this issue, the backend logs and the browser console fills up with errors of type
AccountResourceException: User could not be found
Whenever user browses the application before logging in. Probably because of this code in app.tsx:
export const App = (props: IAppProps) => {
useEffect(() => {
props.getSession();
props.getProfile();
}, []);
This means it tries to run the effect on load and each time AppProps change, no matter what route the user is trying to visit, even the ones that should be open without login.
I would look into moving this effect into some part of the code that only runs for login-only routes.

Cypress seems to have stalled

I'm new to cypress and love the way it is architected. However, I seem to have run into a problem early on for a very simple thing that I'm trying to do.
My workflow is:
1) Visit the site
2) Enter username and password
3) On the next screen, type a number and press submit,
4) On the next screen, select a value from a dropdown and press enter.
5) I get to the landing page of my website.
Cypress works totally fine till step 4). It seems to stall at step 5. The test runner suddenly stalls and without warning or error, shows
"Whoops, there is no test to run."
From here, when I click the "View All Tests" button, it takes me to the runner tool. There I see the indication that something is still running in the background. I tried waiting for more than 10 minutes but nothing happens until I click on the "Stop" action.
How do I debug this? Can I see what is happening via any log etc?
There could even be something wrong with my website as well, but without any log information, I'm unable to proceed further. Any help is appreciated.
To provide more context, I don't think this is a timeout based issue as if that were the case, cypress did report to me about this and stopped. I then increased the timeout.
My spec file
describe('My first test', function() {
it('Visits home page', function() {
cy.visit('https://mywebsite.com:5800', {timeout: 400000}, {pageLoadTimeout: 400000}, {defaultCommandTimeout: 400000})
cy.get('#USERNAME').type('myusername')
cy.get('#PASSWORD').type('mypassword')
cy.get('#loginbutton').click()
cy.get('#SOMELEMENT_WHERE_I_TYPE_A_UNIQUE_NUMBER').type('8056')
cy.get('#loginbutton').click()
cy.get('#loginbutton').click()
})
})
Thanks.
If you run DEBUG=cypress:* cypress open from the terminal when initially opening Cypress, there will be more debug log information printed there while you run your tests.
Also, it's always a good idea to search the issues for the project to see if anyone else has had this happen.
For some reason, the Cypress automation gets into a state where it thinks that you have no spec file. All Cypress does to determine this is to see if there is a location.hash defined on the main window -> where it usually says https://localhost:2020/__/#tests/integration/my_spec.js.
Likely this is due to security mechanisms in the app that prevent your application from being run within an iframe (which is how Cypress runs all applications under test). Maybe in your application code it is something like:
if (top !== self) {
top.location.href = self.location.href;
}
You can simply disable these checks while testing or in Cypress you can add to your test file (or a support file to have it work on every test file):
Cypress.on('window:before:load', (win) => {
Object.defineProperty(win, 'self', {
get: () => {
return window.top
}
})
})
I had the same issue. Usually this is related to the page moving out of the parent and can be solved by invoking the attribute and changing it to the current page.
cy.get('.approved-content .no-auto-submit').invoke('attr', 'target', '_self');

Cucumber: How to run the After hook only once after all examples in scenarion_outline

I have a scenario_outline which tests login screen of a website.
Scenario_outline:
Try to login
Verify login
Examples:
| User | Pass |
| user1 | pass1 |
| user2 | pass2 |
I want to be able to start the web page at the beginning and close if after all examples are done.
Running the Before hook is easy
Before do
$start ||= false
if ! start
#start web page
$start = true
end
end
But how do i run my After hook only once after all scenarios are done?
After do
#close web page
end
The above example simply closes the web page after the first example and causes the rest to fail. I cannot apply here what i did with the Before hook unfortunately
The reason the rest of the tests are failing is because your After method is not setting your global back to false:
After do
#close web page
$start = false
end
I don't believe there is an AfterScenario hook. But in your situation, if you want the browser open for the entire Scenario Outline, I would consider using a regular Scenario and cucumber table. The will share the browser session across each test case.
FYI: There is also an at_exit hook. It's purpose is running some code after all tests.
at_exit do
#close web page
end
https://github.com/cucumber/cucumber/wiki/Hooks#global-hooks

Resources