When I press the "run all specs" button or use the run command that runs all files in Cypress it runs all test files alphabetically, so I don't want that.
I want to sort all of them with my own rules.
Let's say I have 3 steps in a chat app test.
Can connect the chat app
Can connect the chat
Can the user send a message
I want to test every step without being tied to each other.
What I mean, Testing one of their own function.
What I do is as follows
chat_app_connect.spec.js
describe('Server Connecting Test', () => {
it('Visit Server page', () => {
cy.visit('https://chat.page..');
});
it('Check welcome messages', () => {
cy.contains('Live Support');
cy.contains('Hello, Stranger');
});
it('Check URL and status of circle', () => {
// URL
cy.url()
.should('include', '/hello');
// Status Circle
cy.get('circle')
.should('have.class', 'positive');
});
});
chat_connect.spec.js
import './chat_app_connect.spec.js';
describe('Chat Connecting Test', () => {
it('Type customer name', () => {
cy.get('input')
.clear()
.type('E2E Test');
});
it('Click to the submit button', () => {
cy.get('.submit-button')
.click();
});
it('Check URL and status of circle', () => {
// URL
cy.url()
.should('equal', 'https://client.dev.octopus.chat/');
// Status Circle
cy.get('circle', { timeout: 5000 })
.should('have.class', 'positive');
});
});
chatting.spec.js
import './chat_connect.spec.js';
describe('Chatting Tests', () => {
it('Type a test message then press Enter and check the message if it sent', () => {
// Type
cy.get('#chat-message')
.clear()
.type('Hey I\'m a test message{enter}');
// Check the message
cy.get('.message-list')
.should('contain', 'Hey I\'m a test message');
});
});
as you see every test is tied to each other, and that is mean when I tried to test just catting functionality its call every test and the whole tests will be tested.
I don't know if it is the right way or not.
what should I do in this case or can it be an acceptable way
I have a particular case where I launch multiple instances of an app, rather than using fixtures or test data, I simply integrate user feedback as Cypress tests from login on forwards.
In any case, I used the specPattern config in cypress.json to set the spec file run order:
{
"baseUrl": "http://localhost:5000",
"specPattern": [
"login/*.js",
"leads/new-lead.spec.js",
"leads/leads-list.spec.js",
"leads/lead-detail.spec.js",
"leads/lead-modify.spec.js",
//...
]
}
No file numbering needed :D
The easiest solution is most likely to add a prefix to all your test files, such as:
01-chat_app_connect.spec.js
02-chat_connect.spec.js
etc.
Cypress is going to take those files in alphabetical order, which you can "trick" into your wanted behavior by using a number as a prefix.
Jean Lescure's answer was a lifesaver. We needed to run tests based on priority without having a bunch of duplicated tests or symlinks. The following worked for us in our default cypress config file:
"integrationFolder":"cypress/integration",
"testFiles": [
"high_priority_specs/**/*.js",
"medium_priority_specs/**/*.js",
"low_priority_specs/**/*.js"
]
To change the level of priority we used 3 configs files that were loaded using the cypress --configFile argument. To run the higher priority tests (smoke tests only) we used the following:
"integrationFolder":"cypress/integration",
"testFiles": [
"high_priority_specs/**/*.js"
]
Cypress does not intentionally let you do this, and for good reasons:
It's generally indicative of poor test design. Tests should not depend on the state of one another. Any test should be able to be run successfully in isolation from the rest of the test suite.
You'll never be able to take advantage of cypress' built in ability to run tests in parallel since you can't guarantee one spec will be ran after another
Here is a relevant discussion about this that gets into more detail: https://github.com/cypress-io/cypress/issues/390
However, if you decide to do this anyway, you can do it by prefixing the name of the specs with a number:
01-some-spec.js
02-alphabetically-first-spec.js
03-some-other-spec.js
In addition to #Brendan answer, if you have a nested folder structure, this approach will work as well.
01-folder-name
|
- 01-some-spec.js
Related
When tests pass in Cypress it doesn't show the steps but if fails it shows all the steps and what step caused test to fail.
I want to see passing tests body/steps too.
Below image shows a passing test and a failing test. Failing test is much more informative. I want passing test to be like that too. How can I achieve this?
it('should select shipment method and type "test" into additional
notes', function () {
cy.intercept('GET',
'**/GetDetailWithAvailableCampaign*').as('basketDetails')
cy.on('uncaught:exception', (err, runnable) => { // If CheckoutJS throws an error, it will be caught here
cy.get('[data-cy="information::forward"]').click()
cy.url().should('include', '/basket/checkout/payment')
cy.get('[data-cy="shipping::shipment_type"]').first().click()
cy.get('[data-cy="shipping::shipment_type"]').should('be.checked')
cy.get('[data-cy="misc::additional_message_checkbox"]').check({force: true}).should('be.checked')
cy.get('[data-cy="misc::additional_message_textarea"]').should('be.visible').clear().type('Test')
// there is no shipping::forward
// cy.get('[data-cy="shipping::forward"]').click()
cy.get('[data-cy="information::forward"]').click()
})
})
it('should focus iframe and put a credit card', function () {
cy.wait(4000)
cy.url().should('include', '/basket/checkout/shipping')
const iframeSelector = 'iframe[data-cy="payment::iframe"]'
getIframeBody(iframeSelector).find('.btn-card-visa').click()
cy.wait(2000)
getIframeBody(iframeSelector).find('input#CardNumber').clear().type(Cypress.env('credit_card').number)
getIframeBody(iframeSelector).find('input#Expiry').clear().type(Cypress.env('credit_card').expiry)
getIframeBody(iframeSelector).find('input#HolderName').clear().type(Cypress.env('credit_card').holder_name)
getIframeBody(iframeSelector).find('input#VerificationCode').clear().type(Cypress.env('credit_card').cvv)
getIframeBody(iframeSelector).find('.btn-next').click()
}
By default, clicking on a test's name in the runner will expand and show all steps executed. In your case, it is doing this. But the issue you are running into is most likely that the uncaught:exception event you are waiting for in the first test is not occurring, and therefore no steps are executed. If you remove the cy.on('uncaught:exception'), you'll see the steps are executed.
I am running a test suite (test1, test2, test3) in Cypress. I noticed when I run this suite for the first time, they all pass. On the next test run, they fail. It seems that it is failing because the data from test3 has not been removed from the cypress browser when test1 begins to run. Could this be a load issue or would adding a logout command at the end of each test case be the solution? Not sure what would be the solution for this.
It seems that it is failing because the data from test3 has not been removed from the cypress browser. First step is to find out where that data being stored ex: cookie, session storage or local storage? Once you found it, you can choose appropriate method to delete data. Incase you are interested in clearing all u can do something as below
beforeEach(() => {
cy.window().then(win => win.sessionStorage.clear());
cy.clearCookies();
cy.clearLocalStorage();
});
Make sure above syntax is correct from cypress.io.
In your support/index.js or support/index.ts file, you could have a call to before(() => {} that loads your browser up once, and then have all of your tests run in one browser session. When you run the tests again, the first thing it will do is reload the page in the browser so that you have a clean session to start from.
Have you tried adding a step to clear the cookies?
Cypress.Commands.add('logout', () => {
cy.clearCookies().then(() => {
cy.getCookies().should('be.empty').visit('/')
})
});
I see 2 solutions:
I. Add an assertion for the logout command - usualy adding an assertion solves this problem.
Cypress.Commands.add("shopFE_logout", (domain) => {
cy.log('shopFE_logout - start')
cy.get('[data-qa="logoutButton"]')
.click({ force: true })
.should('not.exist')
cy.log('shopFE_logout - end')
})
II. The more secure, but not popular way - separate the test cases to be 1 per file and organize them in folders
I found this on cypress docs "Remember, Cypress already automatically clears localStorage, cookies, sessions, etc before each test. Make sure you are not trying to clean up state that is already cleaned up by Cypress automatically."
https://docs.cypress.io/guides/references/best-practices.html#Is-resetting-the-state-necessary.
I don't think adding logout before each test will be a good idea.
In my test, I do login before each test and I have not done logout and still working fine
describe('This is my test suite', () => {
let credential = "";
beforeEach(function () {
cy.visit(Cypress.env('devUrl'));
cy.fixture('data/common/loginData.json').then(loginData => {
credential = loginData;
});
})
it('This is my first testcase', () => {
cy.myLoginCommand(credential.valid.username, credential.valid.password)
objLocation.navToLocationPage()
objLocation.verifySuccessMsg('Successfully Saved')
})
it('This is my second testcase', () => {
cy.myLoginCommand(credential.valid.username, credential.valid.password)
objLocation.navToLocationPage()
objLocation.verifySuccessMsg('Successfully Updated')
})
})
Here is the scenario:
I'm logging to my application by visiting app.domain/login (example) which will redirect me to something like another.app.domain/
This is working fine. But when I logout: cy.contains('logout').click(), I am getting
CypressError: Timed out after waiting '60000ms' for your remote page to load.
Any suggestions to get around this issue? Ps: I just started to learn Cypress and I want to logout mainly because I want to restore the state back.. I don't want my environment to be updated/modified with the automation scripts. Thanks in advance.
First of all, in cypress there is no AfterAll hook, so we have to use more handmade solution. Second think: if you want to use cypress instead of curl to clean up after test is ok (but I recommend us curl ;)).
First you need to add line to scripts section in package.json:
{
"scripts": {
"after-cypress": "cypress run --spec cypress/hooks/after-all.js",
}
}
File cypress/hooks/after-all.js should looks like this:
describe('clean up after test', () => {
before(() => {
cy.login() // Should we save auth token here?
});
it('', () => {
cy
.request()
.request()
.request() // each of request should delete created during test data
});
});
After reading the Cypress documentation on web security and when to disable it, I've decided I indeed need to do it. Is there a way to disable this just for one particular test/test suite? I'm using version 3.4.1 and this config is being set in cypress.json - therefore it's global for all tests.
Is there a way to disable web security just for one test? Thanks!
Original answer:
Does this work for you?
describe("test the config json", function () {
it("use web security false here", function () {
Cypress.config('chromeWebSecurity',false);
cy.visit("https://www.google.com");
console.log(Cypress.config('chromeWebSecurity'));
});
it("use web security true here", function () {
Cypress.config('chromeWebSecurity',true);
cy.visit("https://www.google.com");
console.log(Cypress.config('chromeWebSecurity'));
});
});
The config is changed as you can see from the console log.
See document here https://docs.cypress.io/guides/references/configuration.html#Cypress-config
Updates:
After I saw DurkoMatKo's comment I managed to find an URL to test this 'chromeWebSecurity' option. It did not work as expected.
I think changing this config might not work during running the same browser as this is more like a browser feature which will determine when start.
In this case what I can think of is only to run Cypress with different configurations.
The cypress doc here shows clear steps to do this.
hope this helps.
In my case it worked as follows.
the first thing was to set chromeWebSecurity to false
//cypress.json
{
"chromeWebSecurity": false
}
Then what I do is with a before assign it to true with Cypress.config
//cypress/integration/testing.spec.js
context('DEMO-01', () => {
beforeEach(function () {
Cypress.config('chromeWebSecurity', true);
});
describe('CP001 - start dasboard', () => {
it('P01: open dashboard', () => {
cy.visit(URL);
});
});
});
I am writing a node.js skill using ask-sdk and using alexa-skill-local to test the endpoint. I need to persist data to DynamoDb in one of the handler. But I keep getting "missing region error". Please find my code below:
'use strict';
// use 'ask-sdk' if standard SDK module is installed
const Alexa = require('ask-sdk');
const { launchRequestHandler, HelpIntentHandler, CancelAndStopIntentHandler, SessionEndedRequestHandler } = require('./commonHandlers');
const ErrorHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
return handlerInput.responseBuilder
.speak('Sorry, I can\'t understand the command. Please say again.')
.reprompt('Sorry, I can\'t understand the command. Please say again.')
.getResponse();
},
};
////////////////////////////////
// Code for the handlers here //
////////////////////////////////
exports.handler = Alexa.SkillBuilders
.standard()
.addRequestHandlers(
launchRequestHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
ErrorHandler
)
.withTableName('devtable')
.withDynamoDbClient()
.lambda();
And in one of the handler I am trying to get persisted attributes like below:
handlerInput.attributesManager.getPersistentAttributes().then((data) => {
console.log('--- the attributes are ----', data)
})
But I keep getting the following error:
(node:12528) UnhandledPromiseRejectionWarning: AskSdk.DynamoDbPersistenceAdapter Error: Could not read item (amzn1.ask.account.AHJECJ7DTOPSTT25R36BZKKET4TKTCGZ7HJWEJEBWTX6YYTLG5SJVLZH5QH257NFKHXLIG7KREDKWO4D4N36IT6GUHT3PNJ4QPOUE4FHT2OYNXHO6Z77FUGHH3EVAH3I2KG6OAFLV2HSO3VMDQTKNX4OVWBWUGJ7NP3F6JHRLWKF2F6BTWND7GSF7OVQM25YBH5H723VO123ABC) from table (EucerinSkinCareDev): Missing region in config
at Object.createAskSdkError (E:\projects\nodejs-alexa-sdk-v2-eucerin-skincare-dev\node_modules\ask-sdk-dynamodb-persistence-adapter\dist\utils\AskSdkUtils.js:22:17)
at DynamoDbPersistenceAdapter.<anonymous> (E:\projects\nodejs-alexa-sdk-v2-eucerin-skincare-dev\node_modules\ask-sdk-dynamodb-persistence-adapter\dist\attributes\persistence\DynamoDbPersistenceAdapter.js:121:45)
Can we read and write attributes from DynamoDb using alexa-skill-local ? Do we need some different setup to achieve this ?
Thanks
I know that this is a really old topic, but I had the same problem few days ago, and I'm gonna explain how I did it work.
You have to download DynamoDB Locally and follow the instructions from here
Once that you have configure your local DynamoDB and check that it is working. You have to pass it through your code, to DynamoDbPersistenceAdapter constructor.
Your code should look similar to:
var awsSdk = require('aws-sdk');
var myDynamoDB = new awsSdk.DynamoDB({
endpoint: 'http://localhost:8000', // If you change the default url, change it here
accessKeyId: <your-access-key-id>,
secretAccessKey: <your-secret-access-key>,
region: <your-region>,
apiVersion: 'latest'
});
const {DynamoDbPersistenceAdapter} = require('ask-sdk-dynamodb-persistence-adapter');
return new DynamoDbPersistenceAdapter({
tableName: tableName || 'my-table-name',
createTable: true,
dynamoDBClient: myDynamoDB
});
Where <your-acces-key-id>, <your-secrete-access-key> and <your-region> are defined at aws config and credentials files.
The next step is launch your server with alexa-skill-local command as always.
Hope this will be helpfull! =)
Presumably you have an AWS config profile that your skill is using when running locally.
You need to edit the .config file and set the default region (ie us-east-1) there. The region should match the region where your table exists.
Alternatively, if you want to be able to run completely isolated, you may need to write come conditional logic and swap the dynamo client with one targeting an instance of DynamoDB Local running on your machine.