I downloaded testcafe-reporter-html-testrail and using this in my testcafe project. If I am giving a custom name to the report then it's failing to save properly, i.e report is not complete, its almost blank with few lines...However, if I am NOT giving the custom name then the report is saving in the format Report_TIMESTAMP.html (e.g.: Report_16_5_2018_14_46_46.html)
What am I doing wrong here?
const createTestCafe = require('testcafe');
let testcafe = null;
createTestCafe()
.then(tc => {
testcafe = tc;
const runner = testcafe.createRunner();
let id;
const deadlinePromise = new Promise((resolve,reject) => {
id=setTimeout(() => {
clearTimeout(id);
reject('testcase couldnt meet the actual preferred time');
},215000)
});
const runPromise=runner
.src(test1.ts)
.browsers('chrome:headless')
// what am I doing wrong in the below step? the report is not saving properly
.reporter('html-testrail', 'Reports/report1.html')
.run({skipJsErrors:true})
race =Promise.race([runPromise,deadlinePromise])
race.then((res) => console.log(res))
})
.catch(failedCount => {
console.log('Tests1 failed: ' + failedCount);
testcafe.close();
})
The html-testrail reporter ignores the output option and uses HTML_REPORT_PATH and HTML_REPORT_NAME environment variables instead. You can use process.env to modify environment variables and save your report in the desired location:
process.env.HTML_REPORT_PATH = path.resolve('Reports');
process.env.HTML_REPORT_NAME = 'report1.html';
To specify a custom output file for 'testcafe-reporter-html-testrail' reporter, you need to specify corresponding environment variables as it described in documentation.
Related
I'm using playwright to do e2e testing to check if the email is exists or not, and while I run my tests its said :
"Finished test flow with status passed"
But its show me that the test is failed because i have assertion error and not because i do something wrong
this is a piece my code:
const fillEmail = async (page: Page, value: string) =>
await page.fill("email-for-test", value);
const fillPassword = async (page: Page, value: string) =>
await page.fill("password-for-test", value);
await fillName(page, name);
await fillEmail(page, email);
const res = await page.locator('.email-error').innerText(); // return error string
expect(res).toContain("Email is already in used");
and i got error, you can see in the picture that I uploaded
any idea how to remove or fix this error
You code actually works. You can also use page.textContent()
const res = await page.locator('.email-error').innerText();
expect(res).toContain("Email is already in use");
const text = await page.textContent('.email-error');
expect(text).toContain("Email is already in use");
How about you just use this:
await expect(page.locator('.email-error')).toContainText(
'Email is already in used',
{timeout: 7000}
)
Also Check if the last word of the assertion message is used or use.
You can also use the text selector and assert it to be visible. Something like this:
await expect(page.locator('text=Email is already in use')).toBeVisible({
timeout: 7000,
})
i soulve this one by upgrade playwright library,
From v1.15 to v1.25
Let's say I have this in a test:
await t.expect(Selector('input')).ok()
And I would like to have (something like) this:
let func = 'ok';
await t.expect(Selector('input'))[func]()
This is so that I can have a map from selector to function, in order to iterate
over it and check whether some elements are in the page (ok) and some not (notOk).
My above attempt does not work and returns with an interesting error:
code: 'E1035',
data: [
'SyntaxError: test.js: await is a reserved word (325:14)'
]
I believe this is because Testcafe is doing some magic under the hood.
What would be the correct syntax to make it work?
It seems that you skipped the Selector property that you want to check (e.g. exists, visible, textContent, etc.). The following test example works properly with TestCafe v1.14.2:
import { Selector } from 'testcafe';
fixture`A set of examples that illustrate how to use TestCafe API`
.page`http://devexpress.github.io/testcafe/example/`;
const developerName = Selector('#developer-name');
const submitButton = Selector('#submit-button');
test('New Test', async t => {
await t
.typeText(developerName, 'Peter Parker')
.click(submitButton);
let assertFunc = 'ok';
await t.expect(Selector('#article-header').exists)[assertFunc]();
});
I have a function for when clicking a button increase the contents of a list.
Content is removed from an API by the following code:
const [data, setData] = useState();
const [maxRange, setMaxRange] = useState(2);
const getAPIinfo = ()=>{
GetEvents(maxRange, 0).then((response) => response.json())
.then(result_events => {
const events = result_events;
setData({events:events});
}).catch(e => setData({events:events}));
}
And my function is this:
const buttonLoadMore = ({data,type}) =>{
setMaxRange(prevRange => prevRange + 4);
data = data.slice(0,maxRange);
}
what I'm not able to do is update the maxRange value of the API query to increase the list...
this function should be heavily refactored:
const buttonLoadMore = ({data,type}) =>{
setMaxRange(prevRange => prevRange + 4);
data = data.slice(0,maxRange);
}
when you use maxRange here, you are setting new state, while the function itself ir running, the state is not instantly updated, buttonLoadMore is a function in a particular time. it cannot get new maxRange instantly, while running buttonLoadMore does that make sense? Also you cannot update data state just like a regular variable by assigning new variable using = operator, you should refactor this function to something like this:
const buttonLoadMore = ({data})=> {
const newMaxRange = maxRange + 4;
setMaxRange(newMaxRange);
const newData = {events: [...data.events.slice(0, newMaxRange)]};
setData({...newData})
}
also you will get bug here. since your getAPIinfo is setting data state to an object {events: events}. I took the liberty and tried refactoring it here.
There is also a bug in your getAPIinfo in line }).catch(e => setData({events:events})); the events variable you declared in .then function cannot be reached here. It is simply out of scope. unless you know that .catch resolves into data, you will get an error in this line.
take a look at this example here:
const promiseFunction = ()=>{
return new Promise<string>((resolve)=>resolve('i like coca cola'))
}
const getter = () => {
promiseFunction()
.then(response => {
const thenVariable = response;
console.log(thenVariable) // i like coca cola
})
.catch(error=>{
console.log(thenVariable) // Error:Cannot find name 'thenVariable'.
})
}
as you can see .catch() is in different scope than .then() will not be available outside so events cannot be reached by .catch function.
Usually you would use catch for error handling. Maybe show a line on screen, that error has accoured, and data cannot be fetched at this time. etc. There's a very good book that explains all these concepts in detail here: https://github.com/getify/You-Dont-Know-JS
I would strongly recommend for you to switch to typescript because your code is crawling with bugs that should be easily avoided just by type checking, and adding eslint configurations.
DEFINE COMMAND
Cypress.Commands.add('getLocalStorage', () => {
const state = window.localStorage.getItem('state');
return JSON.parse(state);
});
USE COMMAND
const localState = cy.getLocalStorage();
RESULT
localState variable holds this value:
chainerId: "chainer6"
firstCall: false
specWindow: Window {parent: global, opener: null, top: global, length: 0, frames: Window, …}
useInitialStack: false
userInvocationStack: " ......"
Using version 5.5.0
Just use a javascript function
const getLocalStorage = () => {
const state = window.localStorage.getItem('state');
return JSON.parse(state);
});
const localState = getLocalStorage();
Custom commands produce chainers that are for, well, chaining
cy.getLocalStorage().then(state => ...
Cypress runs a command queue asynchronously from the javascript in the test. If you want a piece of JS to run synchronously inside the queue, you create a custom command.
Or you can use .then() to hook into the command sequence.
You are using the wrong window. The global window is for the Cypress runner, cy.state('window') gets you the window in the iframe, the one the app is using.
Cypress.Commands.add('getLocalStorage', () => {
const state = cy.state('window').localStorage.getItem('state');
return JSON.parse(state);
});
The Cypress documentation advises against assigning the return value of Cypress commands (eg. const localState = cy.getLocalStorage();)
https://docs.cypress.io/guides/core-concepts/variables-and-aliases.html#Return-Values
As per my application, clicking on one of the links can open one of the URLs from two URLs.
Eg: Clicking on Link - X, it can open one of the below URLs :
http://example.com/value1 or http://example.com/value2
I have to write an .contains assertions for this which can look something like this:
expect(currentUrl).contains(value1 or value2)
As per the TestCafe documentation, contains does not have support for a regular expression and I do not want to use Match as I have to pass incomplete URL there.
Please let me know how this can be done.
Thanks.
I have solved it using match assertion as below but still it would be good if this can be somehow done with contain assertion as well.
expect(currentUrl).match(/value1|value2$/)
Check the following "current location" example test:
import { ClientFunction } from 'testcafe';
fixture `Fixture`
.page `https://google.com`;
test('Check location', async t => {
// Some actions and assertions...
await t
.navigateTo(/*...*/)
.click(/*...*/);
// Then check our location
const getLocation = ClientFunction(() => document.location.href);
const location = await getLocation();
await t
.expect(location.includes('microsoft') || location.includes('google')).ok();
});