How do I assert .containsText with case insensitive in Nightwatch.js? - nightwatch.js

How do I assert .containsText with case insensitive in Nightwatch.js?
For example I search for 'odin sphere' on google.
There are a lot of possibilities for the search result, like 'Odin Sphere' 'odin sphere' 'ODIN SPHERE' etc etc I would like to assert with just 'odin sphere'.
Here's the code I wrote.
module.exports = {
beforeEach: browser => {
browser.url('https://www.google.com/')
},
after: browser => {
browser.end()
},
'Search test': browser => {
browser
.setValue('input[name="q"]',['odin sphere',browser.Keys.ENTER])
.waitForElementVisible('#res')
.pause(5000)
.verify.containsText('#res','Odin Sphere')
}
}```
Thanks in advance!

https://nightwatchjs.org/api/#assert-containsText
Usage:
this.demoTest = function (browser) {
browser.assert.containsText("#main", "The Night Watch");
};

Related

How to map different JSON objects from the fixture into specific spec test file in the cypress

I have the below Input.json as fixture and It contains two different test cases.
Input.json (Fixture folder)
[
{
"searchKeyword":"cypress"
},
{
"username":"QATesting",
"password":"testprofile"
}
]
The above data will validate two different functionality of Google. One is going to validate search engine and another one is going to validate the user login activity (This is just for sample use case which may imitate my actual requirement).
I just created the cypress runner and I just want to run the spec file by using the below runner.js file
const cypress = require('cypress')
const fixtures = require('./cypress/fixtures/Test.json')
const promises = fixtures.map(fixture => {
return cypress.run({
env: {
fixture
},
spec: './cypress/integration/test.spec.js',
});
});
I just added two different It(test cases) respectively in the below "test.spec.js" file. And one test is gonna do the search function and another one is gonna check the existing user login activity:
describe("How to map two different data set with respective test function",() =>{
const baseUrl = "https://www.google.com/";
const testData = Cypress.env('fixture')
beforeEach("",()=>{
cy.visit(baseUrl);
});
it("Test Case1: Search the keyword", function () {
cy.xpath("//input[#name='q']").type(testData.searchKeyword);
cy.xpath("//input[#value='Google Search']").click();
cy.get("//ul/li[2]").should("be.visible");
});
it("Test Case2: login to the gmail account", function(){
cy.xpath("//a[contains(text(),'Sign in')]").click();
cy.xpath("//div[contains(text(),'Use another account')]").click();
cy.xpath("#identifierId").type(testData.username);
cy.xpath("//*[contains(text(),'Next')]").click();
cy.xpath("#password").type(testData.password);
cy.xpath("#submitbtn").click();
})
});
But the second test is getting failed and the testData.username return undefined.
Is there anyway to map the specific JSON array object with specific function in the test.spec.js file?
Not sure how to map the first dataset index with first It (Test case 1) and second dataset index with second test case respectively.
One quick way is to skip if the testData does not have the required properties,
describe("How to map two different data set with respective test function",() =>{
const baseUrl = "https://www.google.com/";
const testData = Cypress.env('fixture')
beforeEach("",()=>{
cy.visit(baseUrl);
});
it("Test Case1: Search the keyword", function () {
if (!testData.searchKeyword) this.skip
cy.xpath("//input[#name='q']").type(testData.searchKeyword);
cy.xpath("//input[#value='Google Search']").click();
cy.get("//ul/li[2]").should("be.visible");
});
it("Test Case2: login to the gmail account", function() {
if (!testData.username) this.skip
cy.xpath("//a[contains(text(),'Sign in')]").click();
cy.xpath("//div[contains(text(),'Use another account')]").click();
cy.xpath("#identifierId").type(testData.username);
cy.xpath("//*[contains(text(),'Next')]").click();
cy.xpath("#password").type(testData.password);
cy.xpath("#submitbtn").click();
})
});
Tagging
You can also get into tags, adding a tag property to the testData
[
{
"tag": "search",
"searchKeyword":"cypress"
},
{
"tag": "user",
"username":"QATesting",
"password":"testprofile"
}
]
Perhaps use a library like cypress-tags, then in the runner script
const cypress = require('cypress')
const fixtures = require('./cypress/fixtures/Test.json')
const promises = fixtures.map(fixture => {
if (fixture.tag) {
process.env.CYPRESS_INCLUDE_TAGS = fixture.tag
}
return cypress.run({
env: {
fixture
},
spec: './cypress/integration/test.spec.js',
});
});
Since your fixtures data is in a array and the username and password fields are at index 1, so in order to access those you have to use:
testData[1].username
testData[1].password
In case if you don't want to use the index value, change the fixture structure to:
{
"searchKeyword": "cypress",
"username": "QATesting",
"password": "testprofile"
}
And in your test directly use:
testData.username
testData.password

Yup validation with one field but two possible options (OR)

I am trying to create an input that takes a string that will be used as the href value for a tag. The href can be a url OR an email (for mailto:).
It works if I just check for email, or if I just check for URL. However, I want to check for one or the other. I am looking through yup documentation but I can't find a way to do an OR.
I noticed that there is a when to test for another field but I'm not checking if another field is true or not, or use test but I also can't seem to get it to work.
const vSchema = yup.object().shape({
text: yup.string().required(),
href: yup
.string()
.email('Link must be a URL or email')
.url('Link must be a URL or email')
.required('Link is a required field'),
});
test this
yup.addMethod(yup.string, "or", function(schemas, msg) {
return this.test({
name: "or",
message: "Please enter valid url or email." || msg,
test: value => {
if (Array.isArray(schemas) && schemas.length > 1) {
const resee = schemas.map(schema => schema.isValidSync(value));
return resee.some(res => res);
} else {
throw new TypeError("Schemas is not correct array schema");
}
},
exclusive: false
});
});

How to run a graphql against faunadb from html client

I am totally new to graphql and faunadb, so plz bear with me if its a silly question.
I see I can run graphql query from the dashboard > GRAPHQL. e.g. Pasting the following code
query FindAllTodos {
allTodos {
data {
_id
title
completed
list {
title
}
}
}
}
and hitting the Run button. But how I can run this query from my html/js code which I want to run in browser?
In js I can create the clientsdk but not sure how to pass the above query?
import faunadb, { query as q } from 'faunadb';
let adminClient = new faunadb.Client({
secret: 'my-key'
});
On googling I found example which were using some FQL like structures like
adminClient.query(
q.Get(q.Ref(q.Collection('Todo'), '276653641074475527'))
)
.then((ret) => console.log(ret));
but how I can just pass the graphql query and get the same result, its returning me in right side pane of the graphql play ground.
You can use a client like curl or any GraphQL client.
With curl you can issue something like:
curl -X POST -H 'Authorization: Bearer <your key>' https://graphql.fauna.com/graphql -d '{ "query": "{ FindAllTodos{ data {_id title completed list { title }} }}"}'
I can get you 90% there but the code I present to you is written in TypeScript in an Angular app that uses HttpClient and RxJs Observables. With a little effort you can rewrite in JS using vanilla HTTP fetch.
By the way here is a video by Brecht De Rooms that helped me a lot:
https://www.youtube.com/watch?v=KlUPiQaTp0I
const SERVER_KEY = 'Your server key goes here';
const executeQuery = (query: string) => {
const headers = new HttpHeaders().set('Authorization', 'Bearer ' + SERVER_KEY);
return this.http.post<any>('https://graphql.fauna.com/graphql',
JSON.stringify({ query }), { headers });
}
const findAllTodos = () => {
const query = `query FindAllTodos {
allTodos {
data {
_id
title
completed
list {
title
}
}
}
}`;
return executeQuery(query);
}
findAllTodos().subscribe(console.log);
For me the hurdle was learning that the Fauna server expects JSON in this form:
{ "query": "query FindAllTodos {allTodos { ... and so forth and so on ..." }
That same structure applies when you run a mutation:
{ "query": "mutation AddTodo { ...etc... " }
By the way, if your query doesn't work the first time, which it probably won't, I recommend opening your browser's developer's tools Network tab and inspect the request that was sent to the Fauna server. Look at the Response. There will be error information in there. The response status will be 200(OK) even when there are errors. You need to look inside the response to check for errors.

Strapi GraphQL search by multiple attributes

I've got a very simple Nuxt app with Strapi GraphQL backend that I'm trying to use and learn more about GraphQL in the process.
One of my last features is to implement a search feature where a user enters a search query, and Strapi/GraphQL performs that search based on attributes such as image name and tag names that are associated with that image. I've been reading the Strapi documentation and there's a segment about performing a search.
So in my schema.graphql, I've added this line:
type Query {
...other generated queries
searchImages(searchQuery: String): [Image
}
Then in the /api/image/config/schema.graphql.js file, I've added this:
module.exports = {
query: `
searchImages(searchQuery: String): [Image]
`,
resolver: {
Query: {
searchImages: {
resolverOf: 'Image.find',
async resolver(_, { searchQuery }) {
if (searchQuery) {
const params = {
name_contains: searchQuery,
// tags_contains: searchQuery,
// location_contains: searchQuery,
}
const searchResults = await strapi.services.image.search(params);
console.log('searchResults: ', searchResults);
return searchResults;
}
}
}
},
},
};
At this point I'm just trying to return results in the GraphQL playground, however when I run something simple in the Playground like:
query($searchQuery: String!) {
searchImages(searchQuery:$searchQuery) {
id
name
}
}
I get the error: "TypeError: Cannot read property 'split' of undefined".
Any ideas what might be going on here?
UPDATE:
For now, I'm using deep filtering instead of the search like so:
query($searchQuery: String) {
images(
where: {
tags: { title_contains: $searchQuery }
name_contains: $searchQuery
}
) {
id
name
slug
src {
url
formats
}
}
}
This is not ideal because it's not an OR/WHERE operator, meaning it's not searching by tag title or image name. It seems to only hit the first where. Ideally I would like to use Strapi's search service.
I actually ran into this problem not to recently and took a different solution.
the where condition can be combined with using either _and or _or. as seen below.
_or
articles(where: {
_or: [
{ content_contains: $dataContains },
{ description_contains: $dataContains }
]})
_and
(where: {
_and: [
{slug_contains: $categoriesContains}
]})
Additionally, these operators can be combined given that where in this instance is an object.
For your solution I would presume you want an or condition in your where filter predicate like below
images(where: {
_or: [
{ title_contains: $searchQuery },
{ name_contains: $searchQuery }
]})
Lastly, you can perform a query that filters by a predicate by creating an event schema and adding the #search directive as seen here

Chai assertion, unable to identify property using should / expect

Hello: Need your help on a chai assertion.
I have a JSON response as shown below. I want to assert that it contains "Lastname is mandatory" only.
I tried using this statement but the error i get is AssertionError: expected [ Array(2) ] to have a deep property '#text'. Please help how to write this correctly.
using expect
chai.expect(data.response.error).to.have.deep.property('#text', 'Lastname is mandatory.');
using should
data.response.error.should.have.deep.property('#text', 'Lastname is mandatory.');
Response JSON
{
response: {
error: [
{
'#id': '1000',
'#text': 'Firstname is mandatory.'
},
{
'#id': '10001',
'#text': 'Lastname is mandatory.'
}
],
result:
{
status: '0'
}
}
}
Prior to Chai version 4
The use of deep with property requires that you pass a complete path to the property you want to test. In other words, deep.property won't do a search through all the properties for you. As the documentation puts it:
If the deep flag is set, you can use dot- and bracket-notation for deep references into objects and arrays.
Something like:
data.response.should.have.deep.property("error[0].#text");
Or you can start the path to the property with an array index if the object on which you use should is an array:
data.response.error.should.have.deep.property("[0].#text");
Here is a complete example derived from the code you show:
const chai = require("chai");
chai.should();
const data = {
response: {
error: [
{
'#id': '1000',
'#text': 'Firstname is mandatory.'
},
{
'#id': '10001',
'#text': 'Lastname is mandatory.'
}
],
result:
{
status: '0'
}
}
};
it("works", () => {
data.response.should.have.deep.property("error[0].#text");
// Or this, which looks weird but is allowed...
data.response.error.should.have.deep.property("[0].#text");
});
Chai version 4 and later
The OP was using a release of Chai earlier than version 4. If you are using Chai version 4 and over, the flag to use to is not .deep anymore but .nested. So in earlier versions where you would use data.response.should.have.deep.property("error[0].#text"); in version 4 or later you'd use data.response.should.have.nested.property("error[0].#text");
Thanks to answer from #shvaikalesh at github. It has the relevant answer to my question which i provide here for future reference + the code extract is also below for quick reference.
chai.expect(data.response.error.some(e => e['#text'] == 'Lastname is mandatory.')).to.be.true

Resources