Hi I am trying to run mocha and chai test to test my node js router, which saves a user in mysql database and then returns the same array back.
The problem I am facing at the moment is that I would not like to save the information in the database when I run it from local and when I use a continious integration software like travis/Ci the test fails since there is no database connection. I would like to know how can I test the database saving with the current without actually saving to the database.
Basically meaning having a fake virtual database to save or returning save.
I read that sinon.js can help but I am quite not sure on how to use it.
Here is my code
var expect = require('chai').expect;
var faker = require('faker');
const request = require('supertest');
const should = require('should');
const sinon = require('sinon');
const helper = require('../../models/user');
describe('POST /saveUser',()=>{
it('should save a new user',(done)=>{
var fake =
request(app)
.post('/saveUser')
.send({
Owner : faker.random.number(),
firstname : faker.name.firstName(),
lastname : faker.name.lastName(),
email:faker.internet.email(),
password : faker.random.number(),
token : faker.random.uuid()
})
.expect(200)
.expect((res)=>{
expect(res.body.firstname).to.be.a("string");
expect(res.body.lastname).to.be.a("string");
expect(res.body.Owner).to.be.a("number");
})
.end(done);
});
});
This is the router
router.post('/saveUser',(req,res,next)=>{
saveUser(req.body).then((result)=>{
return res.send(req.body);
}).catch((e)=>{
return res.send('All info not saved');
});
});
And here is the model
saveUser = (userinfo) => new Promise((resolve,reject)=>{
db.query('INSERT INTO user SET ?',userinfo,function(error,results,fields){
if(error){
reject();
}else{
resolve(userinfo);
}
})
});
What you are describing is a stub. With sinon you can stub methods and call fake methods instead like this:
sinon.stub(/* module that implements saveUser */, 'saveUser').callsFake(() => Promise.resolve());
Related
Im very new to Redis but it seems like somthing my program need to work faster.
I have build my whole database with mongoose/mongodbAtlas.
But is there a way to update one item in the object I got from the database and set in cache. I want to update a location in the setted redis key many times and only need to save the last updated location to the actual database.
So far I have some code to get 1 object from the database and store it in redis but I want to implement the updating part in this function as it is used for the PUT request to update a persons location every second
const updateLocation = async (req, res) => {
const { id} = req.params;
if (!redisClient.isOpen) {
await redisClient.connect()
console.log('connected')
}
const value = await redisClient.get(`person-${id}`)
if (value) {
res.json(value)
// Here I would like to update the documents location everytime
//this endpoint is called from frontend
} else {
const res = await Person.findById(id);
await redisClient.set(`person-${id}`, res);
console.log("from source data")
res.status(200).json(res);
}
};
In the Appwrite console, I'm adding a test environment variable to pass into function...
In my function code (NodeJs) index.js, I'm logging out the value of above variable...
I save the code and use the Appwrite CLI (createTag) to push/publish the code.
Then in Appwrite console, I activate the new function then I execute it and I see this in log...
Clearly I'm missing something but I'm searching the Appwrite docs and I don't see it.
What am I doing incorrectly?
Thank you for helping :-)
Ok looks like as of this post, this is a bug in the Appwrite web UI code. You can do this 2 ways right now. You can set the environment vars in code or you can use the Appwrite CLI. I ended up putting the CLI commend in my NodeJs package.json scripts for quick easy access.
Here are both ways that worked for me...
appwrite functions create --functionId=regions_get_all --name=regions_get_all --execute=[] --runtime=node-16.0 --vars={ 'LT_API_ENDPOINT': 'https://appwrite.league-tracker.com/v1', 'LT_PROJECT_ID': '61eb...7e4ff', 'LT_FUNCTIONS_SECRET': '3b4b478e5a5576c1...ef84ba44e5fc2261cb8a8b3bfee' }
const sdk = require('node-appwrite');
const endpoint = 'https://appwrite.league-tracker.com/v1';
const projectId = '61eb3...7e4ff';
const funcionsSecret = '3b4b478e5a557ab8a...c121ff21977a';
const functionId = process.argv[2];
const name = process.argv[2];
const execute = [];
const runtime = 'node-16.0';
const env_vars = {
"LT_API_ENDPOINT": endpoint,
"LT_PROJECT_ID": projectId,
"LT_FUNCTIONS_SECRET": funcionsSecret
};
// Init SDK
const client = new sdk.Client();
const functions = new sdk.Functions(client);
client
.setEndpoint(endpoint) // Your API Endpoint
.setProject(projectId) // Your project ID
.setKey('33facd6c0d792e...359362efbc35d06bfaa'); // Your secret API key
functions.get(functionId)
.then(
func => {
// Does this function already exist?
if ((typeof (func) == 'object' && func['$id'] == functionId)) {
throw `Function '${functionId}' already exists. Cannot 'create'.\n\n`;
}
// Create the function
functions.create(functionId, name, execute, runtime, env_vars)
.then(
response => console.log(response),
error => console.error(`>>> ERROR! ${error}`)
);
}).catch(
error => console.error(`>>> ERROR! ${error}`)
);
As of Appwrite 0.13.0, an Appwrite Function must expose a function that accepts a request and response. To return data, you would use the response object and either call response.json() or response.send(). The request object has an env object with all function variables. Here is an example NodeJS Function:
module.exports = async (req, res) => {
const payload =
req.payload ||
'No payload provided. Add custom data when executing function.';
const secretKey =
req.env.SECRET_KEY ||
'SECRET_KEY environment variable not found. You can set it in Function settings.';
const randomNumber = Math.random();
const trigger = req.env.APPWRITE_FUNCTION_TRIGGER;
res.json({
message: 'Hello from Appwrite!',
payload,
secretKey,
randomNumber,
trigger,
});
};
In the example above, you can see req.env.SECRET_KEY being referenced. For more information, refer to the Appwrite Functions docs.
I'm simply looking for something like this
app.on('init', async context => {
...
})
Basically I just need to make to calls to the github API, but I'm not sure there is a way to do it without using the API client inside the Context object.
I ended up using probot-scheduler
const createScheduler = require('probot-scheduler')
module.exports = app => {
createScheduler(app, {
delay: false
})
robot.on('schedule.repository', context => {
// this is called on startup and can access context
})
}
I tried probot-scheduler but it didn't exist - perhaps removed in an update?
In any case, I managed to do it after lots of digging by using the actual app object - it's .auth() method returns a promise containing the GitHubAPI interface:
https://probot.github.io/api/latest/classes/application.html#auth
module.exports = app => {
router.get('/hello-world', async (req, res) => {
const github = await app.auth();
const result = await github.repos.listForOrg({'org':'org name});
console.log(result);
})
}
.auth() takes the ID of the installation if you wish to access private data. If called empty, the client will can only retrieve public data.
You can get the installation ID by calling .auth() without paramaters, and then listInstallations():
const github = await app.auth();
const result = github.apps.listInstallations();
console.log(result);
You get an array including IDs that you can in .auth().
Need to automate tests with the values retrieve from the database. Also, the same test is needed to be run with a set of data.
I use the Jest Testing framework and have to use it.test() to test the data. The issue is the test file first checks the array that I am passing to it.test() and initially, it is empty. Please check the attached code.
import "jest";
describe('Document Training test suit', function(this:any){
let docTrainingPage: DocumentTraining;
let driver: any;
let valuesArray:Array<any>=[];
var i=0;
beforeAll(async()=>{
const driver = await new ConfigBrowser();
this.driver = driver;
docTrainingPage = new DocumentTraining(this.driver);
await docTrainingPage.connectToDB();
valuesArray = await docTrainingPage.retrieveValues();//Retrieve value from database
});
describe('Should not save the document', async() => {
it.each(valuesArray )('Should NOT savedocuments with INVALID values',async() => {
const A= JSON.stringify(valuesArray[i].AAA);
const B= JSON.stringify(valuesArray[i].BBB);
const C= JSON.stringify(valuesArray[i].CCC);
const D= JSON.stringify(valuesArray[i].DDD);
const E= JSON.stringify(valuesArray[i].EEE);
await docTrainingPage.enterValues(A, B, C, D, E);
const testResult = await docTrainingPage.verifyValidDocTrainingSuccessful();
expect(testResult).toBeTruthy();
i++;
});
})
afterAll(()=>{
docTrainingPage.endConnection();
setTimeout(() => process.exit(), 1000)
});
})
I tried debugging this code. It goes to beforeAll first at the beginning. But then its go to it and check whether any valid tests are there. At this point, the array is not loaded.
Error
● Test suite failed to run
Your test suite must contain at least one test.
Is there a recommended way to handle data from data file in protractor scripts?
If I want to keep all the test data (like login details, user input values) in separate data file then what type of file should I use and how should I import them to my protractor scripts?
If suppose you need to work with json then:
Suppose your json for username and password of a login page looks like:
Example of JSON:
[
{
"username": "kishan",
"password": "patel"
}
]
Then you can simply import this to your code and access it as below.
describe ('Login Page Data Driven' , function() {
browser.ignoreSynchronization = true;
beforeEach(function(){
browser.get('your url');
browser.driver.manage().window().maximize();
});
it('To verify Login, using Data Driven Technique from Json file', function()
{
var testData = require('D:/json path'); //this is the path where your json is stored
var user= element(by.id("username"));
var password = element(by.id("password"));
user.sendKeys(testData[0].username);
password.sendKeys(testData[0].password);
});
This Is just an Example. I hope you can Relate and apply.
Try at your end & Let me know for more concerns.
I typically create a separate data file, and require it as needed in my specs. I have a working example on my github protractor-examples repo. Here's the jist:
// userData.js
var UserData = {
testUser : {'username': 'test', 'password': 'test'},
};
module.exports = UserData;
then in my spec...
// nonAngularLoginSpec.js
it('should goto friend pages on successful login', function() {
loginPage.loginAs(userData.testUser);
expect(friendPage.at()).toBeTruthy();
});