One of our tests fails on CI, while running the test locally results in the test passing. I've been trying to figure out why for hours/days now, and I still can't seem to fix it.
The test
The steps of the test are as follows:
Register as a new user
Confirm the sent email in order to login by clicking a link
Once logged in, click a link in the dashboard and check if you're on the page.
// $signup & $address are dusk pages
$browser->visit($signup)
->acceptCookies()
->signup([
'firstName' => 'John',
'email' => 'john.doe#example.org',
'password' => 'john.doe',
])
->on($thanks)
->visitMail($confirmationMail)
->withinMail(fn (DuskBrowser $browser) => $browser->click('#confirmLink'))
->switchToLatestWindow()
->on($dashboard)
->click('#editAddressButton')
->on($address)
Every step succeeds until the last line. When the browser asserts it's on the "address" page, the assertion fails. The assertion is based on seeing certain text displayed.
This makes sense, because when dumping the page (on CI) after clicking #editAddressButton, the page is empty like so: <html><body></body></html>.
All dependencies are up-to-date and the same version, as well for chrome-driver.
Conclusion
I'm just baffled why it fails at that specific point on CI, but not locally. Our other tests do succeed, so it's not like our .env files are setup incorrectly.
Thank you for your time reading this, I sincerely hope that someone can help us figure this out.
Related
2fold question:
how do I get Percy to execute snapshots -in order-?
can you help me troubleshoot my simple login script?
Trying to set up a basic beginnings of Percy CLI. Using a .js file as they detail here - https://docs.percy.io/docs/cli-snapshot (I have spent a lot of time with this document)
My website is mostly behind a login, so being able to login in Percy and continue snapshotting is of key importance. I have created the following execute script. It sends Percy to the login screen, puts in credentials and logs in, then takes a snapshot of /home (not accessible without login)
module.exports = [ {
name: 'Login Page - Execute Login',
url: 'http://localhost:3000/login',
waitForSelector: '.login-form > button',
waitForTimeout: 3000,
execute() {
document.querySelector('#email').value = 'test#test.com';
document.querySelector('#confirmPassword').value = 'password';
document.querySelector('.login-form > button').click();
}
},
{
name: 'Home',
url: 'http://localhost:3000/home',
waitForTimeout: 2000
}
]
When I input this script line by line into Chrome console, everything works as expected.
When I run it in Percy CLI in the terminal, it executes without error:
9:50:~$ npx percy snapshot snapshots.js
[percy] Percy has started!
[percy] Snapshot taken: Home
[percy] Snapshot taken: Login Page - Execute Login
[percy] Finalized build #21: <URL removed for privacy>
But the screenshots I see show that the email and password have not been set as the values of the inputs. I do not understand how this would work in Chrome console but not in Percy Chromium headless browser.
Additionally, you'll notice that percy takes the 'Home' snapshot first, when it is listed second in the JS object.
Is there any trick to getting snapshots taken in a certain order? A different format besides exporting as a JS module?
Or, can I somehow create a login cookie for my website before running Percy so I don't have to worry about order?
Is there some SDK I should be using to make these slightly more complex interactions beyond just going to a URL and snapshotting possible?
Thanks very very much.
I'm new to cypress and have ran into an issue. I have my base URL set to the domain I want to test, the issue is when I want to test the ability to login on my base url site I need to verify the user on another site, once I click apply on site number 2 the page on my base url reloads and I would then be able to test the rest of the site.
When I try to visit site 2 from my test I get an error
cy.visit() failed because you are attempting to visit a URL that is of
a different origin.
The new URL is considered a different origin because the following
parts of the URL are different:
superdomain
You may only cy.visit() same-origin URLs within a single test.
I read this https://docs.cypress.io/guides/guides/web-security.html#Set-chromeWebSecurity-to-false I've tried setting "chromeWebSecurity": false in cypress.json but I still get the same issue (I'm running in chrome)
Is there something I am missing?
As a temporary but solid work around, I was able to find this script in one of the Cypress Git issue threads (I don't remember where I found it so I can't link back to it)
Add the below to your cypress commands file
Cypress.Commands.add('forceVisit', url => {
cy.window().then(win => {
return win.open(url, '_self');
});
});
and in your tests you can call
cy.forceVisit("www.google.com")
From version 9.6.0 of cypress, you can use cy.origin.
If you want to use it, you must first set the "experimentalSessionAndOrigin" record to true.
{
"experimentalSessionAndOrigin": true
}
And here's how to use it.
cy.origin('www.example.com', () => {
cy.visit('/')
})
cy.origin change the baseurl, so you can link to another external link via cy.visit('/').
You can stub the redirect from login site to base site, and assert the URL that was called.
Based on Cypress tips and tricks here is a custom command to do the stubbing.
The login page may be using one of several methods to redirect, so besides the replace(<new-url>) stub given in the tip I've added href = <new-url> and assign(<new-url>).
Stubbing command
Cypress.Commands.add('stubRedirect', () => {
cy.once('window:before:load', (win) => {
win.__location = { // set up the stub
replace: cy.stub().as('replace'),
assign: cy.stub().as('assign'),
href: null,
}
cy.stub(win.__location, 'href').set(cy.stub().as('href'))
})
cy.intercept('GET', '*.html', (req) => { // catch the page as it loads
req.continue(res => {
res.body = res.body
.replaceAll('window.location.replace', 'window.__location.replace')
.replaceAll('window.location.assign', 'window.__location.assign')
.replaceAll('window.location.href', 'window.__location.href')
})
}).as('index')
})
Test
it('checks that login page redirects to baseUrl', () => {
cy.stubRedirect()
cy.visit(<url-for-verifying-user>)
cy.wait('#index') // waiting for the window load
cy.('button').contains('Apply').click() // trigger the redirect
const alias = '#replace' // or '#assign' or '#href'
// depending on the method used to redirect
// if you don't know which, try each one
cy.get(alias)
.should('have.been.calledOnceWith', <base-url-expected-in-redirect>)
})
You can't!
But, maybe it will be possible soon. See Cypress ticket #944.
Meanwhile you can refer to my lighthearted comment in the same thread where I describe how I cope with the issue while Cypress devs are working on multi-domain support:
For everyone following this, I feel your pain! #944 (comment) really gives hope, so while we're patiently waiting, here's a workaround that I'm using to write multi-domain e2e cypress tests today. Yes, it is horrible, but I hope you will forgive me my sins. Here are the four easy steps:
Given that you can only have one cy.visit() per it, write multiple its.
Yes, your tests now depend on each other. Add cypress-fail-fast to make sure you don't even attempt to run other tests if something failed (your whole describe is a single test now, and it makes sense in this sick alternate reality).
It is very likely that you will need to pass data between your its. Remember, we're already on this crazy “wrong” path, so nothing can stop us naughty people. Just use cy.writeFile() to save your state (whatever you might need), and use cy.readFile() to restore it at the beginning of your next it.
Sue me.
All I care about at this point is that my system has tests. If cypress adds proper support for multiple domains, fantastic! I'll refactor my tests then. Until that happens, I'd have to live with horrible non-retriable tests. Better than not having proper e2e tests, right? Right?
You could set the window.location.href manually which triggers a page load, this works for me:
const url = 'http://localhost:8000';
cy.visit(url);
// second "visit"
cy.window().then(win => win.location.href = url);
You will also need to add "chromeWebSecurity": false to your cypress.json configuration.
Note: setting the window to navigate won't tell cypress to wait for the page load, you need to wait for the page to load yourself, or use timeout on get.
I've started using Cypress to test our front End Internal Application (being built using Angular5), which uses Auth0 as login authentication.
I'm a QA with NO experience of any sort of coding, so I was quite pleased when I managed to get a few tests working (and passing).
However I have hit a stumbling block. Even though I can use Cypress to test that the Auth0 login works; when the login is successful it is not opening the application in the test as it would if I were manually testing.
Below is my test that runs the Auth0 authentication test.
describe('My Login Test', function (){
it('Visit Risk App Landing Page', function (){
const typedText = 'user-email-address'
cy.visit('http://localhost:3000/workflow')
cy.get('button').click()
cy.get('input.auth0-lock-input').first()
.type(typedText)
.should('have.value', typedText)
cy.get('button').click()
cy.url().should('eq','http://localhost:3000/workflow')
})
})
I'm also trying to create a function where I can call Auth0 and store the response so I don't have to run a login scenario before every tests that runs for the rest of the application, but as I said I have no coding experience and I've found that creating a function is far different to creating a test as that shown above.
If anyone could offer any suggestions/tips/clues, they would all be appreciated.
can't help you with your first question. But as for extracting your login code for reusablitity you could create a cypress command https://docs.cypress.io/api/cypress-api/custom-commands.html#Syntax
Cypress.Commands.add('login', (email, password) => {
cy.visit('http://localhost:3000/workflow')
cy.get('button').click()
cy.get('input.auth0-lock-input').first()
.type(email)
cy.get('button').click()
cy.url().should('eq','http://localhost:3000/workflow')
})
Then from within your tests you could call it like:
cy.login('some-email', 'somepassword')
I'm almost done with a Laravel project I'm working on and am wanting to try it out on an actual server.
However after I loaded the entire project (slower than using composer but I was hoping to keep this as simple as possible the first time I tried this) I can't even log in as I'm getting a "syntax error, unexpected '['" error message with the debug window pointing to this code:
Route::get('login', [
'as' => 'login',
'uses' => 'SessionsController#create'
]);
I tried changing it to
Route::get('login', array(
'as' => 'login',
'uses' => 'SessionsController#create'
));
but after I changed it and uploaded the file again it still looked like the original code. To make things more confusing the code should work either way, unless I am missing something.
If anyone can point out 1.)the reason for the error message - the project runs fine on my local server and 2.)why the file does not seem to be updating when I send in a new version it would be greatly appreciated! Thanks!
Your actual server is running PHP 5.3
Your local server is running PHP >=5.4
The short array syntax [] was added in PHP 5.4. See change log here.
We've been getting a 503 error since yesterday when making this call:
result = session.execute(
api_method: drive.files.insert,
body_object: file,
media: media,
parameters: {'uploadType' => 'multipart', 'alt' => 'json'}
)
We have 3 set of keys - one each for our development, staging, and production environments.
The above call works without issue in our development environment, but fails 100% of the time in both staging and production environments
Based on the gists shared privately, it looks like the issue is the user agent header. I was able to reproduce by setting the UA similar to that one. I haven't been able to narrow it down to a particular issue with the UA, just that it doesn't work. Other multi-line strings work, and other chars seem fine if I replace the newlines.
Anyway, easiest thing to do is set :application_name with a different value that what you're using now.