I am looking to interact with mongodb from cypress test.I couldn't find any useful documentation.Please help me how to acheive this?
Look at their documentation about tasks :https://docs.cypress.io/api/commands/task.html#Command
I needed to do something with mongodb and i managed to connect doing something like this (inside "plugins" directory):
const MongoClient = require('mongodb').MongoClient;
module.exports = (on, config) => {
on('task', {
updateTask (id) {
return new Promise((resolve) => {
MongoClient.connect('mongodb://localhost:27017', (err, client) => {
if (err) {
console.log(`MONGO CONNECTION ERROR: ${err}`)
throw err;
} else {
const db = client.db('myDB');
db.collection('someCollection').count({}, function(error, numOfDocs){
resolve({success: numOfDocs})
client.close();
})
}
});
}); // end of return Promise
}
}) // end of task
}
and you call it inside "spec" like this:
cy.task('updateTask', someParam).then((textOrNull) => {
console.log(textOrNull)
})
There is now a mongodb plugin for cypress: https://www.npmjs.com/package/cypress-mongodb
After you configure it, you'll be able to call cy commands to perform actions in your local or remote db:
cy.createCollection(...);
cy.dropCollection(...);
cy.insertMany(...);
cy.aggregate(...);
Execute a shell command from your cypress test:
https://docs.cypress.io/api/commands/exec.html#Syntax
Example:
cy.exec(mongo mydatabase --eval 'db.collection.find({})')
Related
I am completely new to writing node scripts in Postman.
My requirement:
I have an api to get user details. I want to iterate for n number of users. I created a Runner collection and it executes. But i want to write each request response to a file.
Can anyone help me how to do this?
I watched some youtube video https://www.youtube.com/watch?v=cCRmry10874 for this. But my case is i have runner collection with data file.
When i exported the collection, i dont get the different values from data file.
const newman = require('newman');
newman.run({
collection: require('./collection.json'),
reporters: 'cli'
}, (err) => {
if(err) { throw err; }
console.log('collection run complete');
});
const fs = require('fs');
fs.writeFile('response.txt', 'Some text', (error) => {
if(error) {
console.error(error);
}
})
Thanks
Can you try it?
newman.run(
{
collection: require("./collection.json"),
reporters: "cli",
iterationData: "./data.json",
},
(err, summary) => {
if (err) {
throw err;
}
const results = summary.run.executions;
results.forEach((result) => {
fs.appendFileSync("response.txt", result.response.text());
});
}
);
If you are not limited to using a textfile, I would suggest using htmlextra.
It provides an HTML webpage with your runs and response body.
I would like to drop database after all tests in all files ran. Is there a hook for it in Mocha?
after() hook can be applied only within 1 file only.
There is a root level hook in mocha. For your case, you can create a new file and specify drop database command in after function. That's it!
// init-test.js
after(function() {
// drop database
});
You don't need to move any test in other test file for this solution.
Reference:
https://mochajs.org/#root-level-hooks
Create a parent file that includes/requires all other tests, then use after within that file:
describe('User', () => {
require('../user/user.spec.js')
})
describe('Post', () => {
require('../post/post.spec.js')
})
describe('Tag', () => {
require('../tag/tag.spec.js')
})
describe('Routes', () => {
require('./routes.spec.js')
})
after(() => {
// drop database
})
I'm using process.on('exit'). It works when running only one file as well as when running tests from package.json.
database.mocha-base.js:
db.connect()
process.on('exit', async () => {
console.log('All tests finished. Droping database')
db.dropDatabase(dbName)
db.disconnect()
})
module.exports = {
applyHooks() {
before(async () => {
// truncate tables
})
}
}
I'm including database.mocha-base.js in all tests that need database access:
const dbMochaBase = require('./path/to/database.mocha-base.js')
describe('Tests', () => {
dbMochaBase.applyHooks()
...
})
I'm running a task to seed my database in a before hook. Cypress is complaining that
Cypress Warning: Cypress detected that you returned a promise in a test, but also invoked one or more cy commands inside of that promise.
Here is the task
import { seed } from '../../../src/server/db/seed'
const pluginHandler = on => {
on('task', {
'seed:db': () => {
return seed()
}
})
}
export default pluginHandler
This is the seed function
import { exec } from 'child_process'
import util from 'util'
const execP = util.promisify(exec)
export const seed = () => {
// Drop notes.
return execP('mongo starter_test --eval "db.notes.drop()"')
.then(async () => {
// Insert notes fixtures.
await execP(
'mongoimport --db starter_test --collection notes --file ./src/server/db/notes.json'
)
})
.then(() => {
return 0
})
}
And finally the test, which doesn't do anything yet
describe('My First Test', () => {
before(async () => {
await cy.task('seed:db')
})
it('Does not do much!', () => {
cy.visit(Cypress.env('HOST'))
})
})
I'm not, as far as I can see, using commands inside the promise as the warning suggests.
As far as I know, async should not be used inside Cypress before, or any other command (unless you install a 3rd-party lib).
Please try with before(() => cy.task('seed:db'))
I'm writing a Vue app that uses vue-apollo to interact with graphql. I'm wondering if it's possible to stub the graphql requests. I thought this should work:
it('should access a story', function() {
cy.server();
cy.route('http://localhost:3002/graphql', {
data: {
Story: { id: 2, title: 'story title', content: 'story content' }
}
});
cy.visit('/stories/2');
});
Unfortunately, I get an error from graphql complaining that id is an Int instead of an ObjectId. Am I missing something?
The problem was that stubbing fetch requests isn't yet implemented in Cypress (which is what Vue Apollo is using). I ended up following these instructions:
Install github/fetch
Add this to cypress/support/index.js:
.
Cypress.on('window:before:load', win => {
win.fetch = null;
win.Blob = null;
});
Now it works!
I got it working with this package here:
npm i #iam4x/cypress-graphql-mock
Add this line to 'support/commands.js'
import "#iam4x/cypress-graphql-mock";
go to your graphiql playground and download your schema
add task command to 'plugins/index.js' (REMEMBER TO CHANGE PATH TO SCHEMA FILE YOU DOWNLOADED EARLIER)
module.exports = (on, config) => {
on("task", {
getSchema() {
return fs.readFileSync(
path.resolve(__dirname, "../../../schema.graphql"),
"utf8"
);
}
});
};
write your tests with loaded schema
beforeEach(() => {
cy.server();
cy.task("getSchema").then(schema => {
cy.mockGraphql({
schema
});
});
});`
describe("Login Form", () => {
it("should redirect after login", () => {
cy.mockGraphqlOps({
operations: {
Login: {
login: {
jwt: "some-token",
user: {
id: "5d5a8e1e635a8b6694dd7cb0"
}
}
}
}
});
cy.visit("/login");
cy.getTestEl("email-input").type("Max Mustermann");
cy.getTestEl("password-input").type("passwort");
cy.getTestEl("submit").click();
cy.getTestEl("toolbar-title").should("exist");
});
})
Visit the original repo for further explanation as i find it less confusing. The package you have installed is just a working fork of this one:
https://github.com/tgriesser/cypress-graphql-mock
I am writing tests for back-end which uses MongoDB and Elasticsearch. The problem is that without wrapping test with setTimeout test fails, and it looks like elasticsearch can't index mock data into db before test. Here is the code:
let elasticSearch = require('elasticsearch');
let elasticClient = new elasticSearch.Client({
host: 'localhost:9200'
});
let app = require('./dist/app'); //path to my application
let supertest = require('supertest');
before((done) => {
elasticClient.index(elasticMockData, function() {
done();
});
});
beforeEach(() => {
request = supertest(app);
});
it('should get data from elastic', () => {
setTimeout(() => { // if I comment this timeout, test will fail
request.get('/api/elastic')
.end((err, res) => {
expect(res.body.hits.hits.length).not.to.equal(0);
})
}, 1000); // if I comment this timeout, test will fail
});
I think you will agree that timeout is not an elegant and nice solution, which slows every test to 1 second or more. Maybe, am I missing something?
Found a solution, maybe it will be useful for someone.
According to Elasticsearch docs:
By default, the document will be available for get() actions immediately, but will only be available for searching after an index refresh (which can happen automatically or manually).
So, in this case, done() should be called within another callback function:
before((done) => {
elasticClient.index(elasticMockData, function() {
elasticClient.indices.refresh(function (err: any, res: any) {
if (err) {
return;
}
done();
});
});
});