Cypress.io can't find the specs when wrapping with nodejs - node.js

I am trying to add a REST API on top of Cypress.io to mimic the Appium framework. I can run the test from the console, but when I try to run the spec with an http request cypress can't find the test. I've tried to add a bunch of different path settings in cypress.json located in the root folder of the project but no luck so far.
Here is a small example server of what I'm trying to achieve.
import express from 'express';
import cypress from 'cypress';
const app = express();
const PORT = 5000;
app.get('/cypress/v1/run/:specName', (req, res) => {
cypress.run({
spec: req.params.specName})
.then(results => {
res.status(200).send({
status: results.totalFailed,
result: results
})
})
.catch((err) => {
console.error(err)
});
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`)
});
Whatever I send in I get following error:
Request: curl -v http://localhost:5000/cypress/v1/run/test.js
Response: {"result":{"failures":1,"message":"Could not find Cypress test run results"}}
Log:
Can't run because no spec files were found.
We searched for any files matching this glob pattern:
test.js
So my question is, what am I missing?

Cypress seems to be extremely sensitive to configuration and is somewhat not logic. I changed the config file to following and specs are found:
{
"projectId": "xyz123",
"integrationFolder": "cypress/integration",
"testFiles": "**/*.*"
}
I still have to specify the test as cypress/integration/test.js, otherwise Cypress will not find it.

Related

Jest and supertest: Test keep exceeding timeout

Hello I am a bit confused by this error I have encountered.
I am working on an Universal React App using Webpack 5 and Express.
I want to implement Jest support by using the React-testing-Library for the frontend (which work) and supertest for the backend (this is where I am blocked).
I am following this basic tutorial recommended by the jest doc himself in order to use jest on an node express environment.
But everytime I get this error:
thrown: "Exceeded timeout of 5000 ms for a test.
Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."
Here are my code:
server.js
import app from './app.js';
import { mongooseConnection, disconnectMongoDB } from "./routers/services/url/urlDB.js"; // we call mongooseConnect var to connect only once into the mongoDB database
const PORT = process.env.PORT || 8080;
// the server listen on the port set by node on localhost.
app.listen(PORT, () => {
console.log(
`Server listening on \x1b[42m\x1b[1mhttp://localhost:${PORT}\x1b[0m in \x1b[41m${process.env.NODE_ENV}\x1b[0m`,
);
});
// when when we shut down the app we execute a callback function before closing the server
process.on('exit', function() {
disconnectMongoDB();
});
app.js
import express from 'express';
import path from 'path';
import cors from 'cors';
import {envIsProduction, envIsDevelopment} from './envmode/envUtil.js';
import { enableHMR } from './reload/hotReload.js';
let app = express();
// if we have set the environnent on production then:
if (envIsProduction()) {
console.log(" _______________________________________ ");
console.log("| |");
console.log("| ( PRODUCTION ) |");
console.log("|_______________________________________|");
console.log(" ");
app.use(express.static(path.join(__dirname,'../client'))); // we serve static file like the bundle-app.js to the browser from the current directory where the server is executed and we move to the top root to access the file
}
else if (envIsDevelopment()) {
console.log(" _______________________________________ ");
console.log("| |");
console.log("| ( DEVELOPMENT ) |");
console.log("|_______________________________________|");
console.log(" ");
enableHMR(app); // we enable the Hot MPodule Reload on the frontend and the backend
}
app.use(cors());
app.use(express.urlencoded({extended:false}));
app.use(express.json());
//Hot reload!
//ALL server routes are in this module!
app.use((req, res, next) => {
require("./routers/routers")(req, res, next);
});
export default app;
routers.js
import renderPage from "./renderpage/renderPage.js";
import { serverRoutes, reactRouterRoutes, getReactRouterRoutesString } from "./routes.js";
import express from "express";
import routerLoginDB from "./request/routerLoginDB.js";
import routerSignupDB from "./request/routerSignupDB.js";
const router = express.Router();
// Put all your server routes in here
// When the user connect to the root of the server we send the page
router.get(serverRoutes.root, renderPage);
// When the user send a get request by the /click route a console.log and a respone is send.
router.get(serverRoutes.click, (req, res)=>{
res.status(200).send("Click");
});
// when this user want to login into his account, we ask for the routerLoginDB to handle it
router.post(serverRoutes.login,routerLoginDB);
// when this user want to signup into his account, we ask for the routerSignupDB to handle it
router.post(serverRoutes.signup, routerSignupDB);
// For all the routes that only react-router need to use, if we refresh on a nested route of the react-router from the client side then we redirect it to the root route "/"
router.get(reactRouterRoutes,(req,res) => {
res.redirect("/");
});
router.get("*", (req,res) =>{
res.status(404).send('page not found');
}); //For all other type of request excluding the one specified here, we send back a 404 page;
module.exports = router;
app.test.js
import request from '../utils/test-node-utils.js'
describe("Test the /click path", () => {
test("It should response the GET method", () => {
return request
.get("/click")
.expect(200);
});
});
and finally test-node-utils.js
import supertest from "supertest";
import app from "../serverside/app.js";
const request = supertest(app);
export default request;
Don't believe what the error say because I think it is more deep than that.
I have tried to increased the jest timeout value but it keep being stuck and reach the timeout limit.
I have done exactly like the tutorial say without using my project structure and it worked but when I try to implement the tutorial in my backend structure, it don't work with supertest.
I think it is related to my files or backend structure that make it don't work with the test.
Thanks in advance for your help
I've recently debugged a similar issue where my Jest tests would run successfully (or not) in my dev. environment but when I would try and package the app as a Docker image all my tests would time out.
It turned out that by commenting out the line which setup CORS, which for me I only turned on in production builds (should have been a clue), the tests started to run again when building the image.
...
const NODE_ENV = process.env.NODE_ENV;
const app = express();
NODE_ENV.toUpperCase() === 'PRODUCTION' && app.use(cors);
...
I mentioned this as I can see from your snippet above that you are also using the cors middleware and that, in your case, it's set all the time.
Perhaps not your issue, and you may want CORS in your tests for some reason, but try commenting it out and see if your tests run.

Proxy error: Could not proxy request /users from localhost:3000 to http://localhost:5000/

I am trying to create a simple react app with node/express for the backend. When I start my app I get this error:
Proxy error: Could not proxy request /users from localhost:3000 to http://localhost:5000/.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
My front-end package.json looks like this
The front-end is pretty simple. fetchUserData() under useEffect() is what calls the backend.
import React, { useEffect, useState } from "react";
function App() {
let [userData, setUserData] = useState([{}]);
useEffect(() => {
const fetchUserData = async () => {
const response = await fetch(`/users`);
const data = await response.json();
setUserData(data);
};
fetchUserData();
}, []);
return (
<div>
<h1>Hello React World!</h1>
</div>
);
}
export default App;
The backend is pretty barebone as I just started this project. I have no problem getting the correct response if I just request http://localhost:5000/users directly from the browser or postman:
const express = require("express");
const app = express();
const port = process.env.PORT || 5000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/users", (req, res) => {
console.log(req);
res.json({ users: ["Bob", "Sally"] });
});
app.listen(port, () => {
console.log(`Listening on port ${port}`);
});
The error message appears when I try to load the front end on http://localhost:3000 which should then fetch the backend resource. I look at the network tab of chrome and for some reason it is going to port 3000 instead of 5000:
I've tried the below but no luck:
Closing my app. Deleting package-lock.json and node_modules, reinstalling them.
Add '/' to the end of the string for the "proxy" setting in package.json
Replacing localhost with 127.0.0.1 in package.json
Tried adding "--ignore client" to dev script in server package.json
Tried adding "secure": false in client package.json
Edit 1: This issue is driving me crazy. If I remove the proxy from package.json, add cors to the server side, and use the absolute path of the endpoint instead of the relative path in my client-side fetch request, it works. But I would much rather use the relative path.
import React, { useEffect, useState } from "react";
function App() {
let [userData, setUserData] = useState([{}]);
useEffect(() => {
const fetchUserData = async () => {
const response = await fetch(`http://localhost:5000/users`);
const data = await response.json();
setUserData(data);
};
fetchUserData();
}, []);
return (
<div>
<h1>Hello React World!</h1>
</div>
);
}
export default App;
Just don't use 'localhost'. Put everything as 127.0.0.1
Font: hours trying every solution possible.
From trying to replicate your issue I think in your proxy you have "proxy": "http://localhost:5000/", but then you also pass a fetch request for "/users" which would lead to a "http://localhost:5000//users.
I would imagine that when you were trying to figure this out that the issue was that you didn't restart your React App after changing the package.json to include the Proxy, and then by the time you restarted the React App, you had already added the extra "/".
Also in your browser console.log when, no matter where your proxy is it will come up with http://localhost:3000 as the address rather than your actual endpoint - it can be a bit of a red herring
Hope it helps
I finally got it to work!
After a lot of experimenting, I realized that this was indeed an environment problem. That explains a lot since the many other suggestions I tried worked for other people but not for me.
What had happened was that my client-side was using wsl for the terminal yet my backend was using PowerShell. When I switched both to wsl it worked. Or when I switched both to Powershell it also worked.

Api returning 404 on production

I have a next.js app and I'm trying to create an api. When I run it as development, the api's get called, but when I run it using next start I get a 404 error when calling the api's.
Here's the relevant server.js code:
app.prepare().then(() => {
require('./server/startup/routes')(server);
server.get('*', (req, res) => {
return handle(req, res);
});
const PORT = process.env.PORT || 5000;
server.listen(PORT, err => {
if (err) throw err;
console.log(`> Read on http://localhost:${PORT}`);
});
});
Here's the routes file
module.exports = app => {
app.use('/api/something-cool', cool);
};
Cool File:
const express = require('express');
const router = express.Router();
router.post('/', async (req, res) => {
...Code
res.send({ status: 'ok' });
});
module.exports = router;
The api route of /something-cool works when I run nodemon, but when I run next run, it returns a 404 error. What am I doing wrong and how can I fix it?
You are using a custom server (express) on top of Next.js to customize routes. This means that first, you have to build the Next.js App and then you have to run your server.js file in order to serve the App.
Option 1:
Builds the production application first
next build
Then run you server.js file:
NODE_ENV=production node server.js
more info here https://github.com/zeit/next.js/tree/master/examples/custom-server-express
Option 2:
There is also the option to create the API route within the Next.js App without using a custom server.
See https://github.com/zeit/next.js/tree/master/examples/api-routes for more info on how to do it.

How to startup the server when testing an Express app via Mocha

I would like to write unit tests using Mocha for my Nodejs/Express app that I have written in visual studio. I have scoured everywhere I could looking for a simple tutorial but not found what I am looking for. I have seen many tutorials in creating a test using assert to test that 5=5, etc. but that's not what I want to do.
I am trying to add a JavaScript Mocha Unit Test file through VS and then all I really want it to do is open the home page of my app, check for some content in the body and pass the test. If I want to run the tests from the Test Explorer window the nodejs app can't be running and if it isn't running there would be nothing to receive the request for the homepage.
So I'm not sure if the test itself is somehow supposed to launch the app or what? I feel like I'm in a catch 22 and missing the very basics, just don't see it described anywhere.
What you're looking for is most commonly called an API test - a part of integration testing, not a unit test. If a test touches network, a database or I/O it's, most commonly, an integration test instead.
Now to your question. In order to test your app.js code without starting up the server manually beforehand you can do the following:
module.export your app server.
In your tests, use chai-http to test routes.
require your app in the tests and use that instead of URL's when testing routes.
The key here is the 1st bullet point. You must export your app so you can require it and use it in your tests. This allows you to skip the part where you start a separate server process to run the tests on.
Server code
// app.js
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
app.use(bodyParser.json())
// Routes
app.post('/register', (req, res) => {
const requiredFields = ['name', 'email']
if (requiredFields.every(field => Object.keys(req.body).includes(field))) {
// Run business logic and insert user in DB ...
res.sendStatus(204)
} else {
res.sendStatus(400)
}
})
app.listen(3000)
// export your app so you can include it in your tests.
module.exports = app
Test code
// test/registration.spec.js
const chai = require('chai')
const chaiHttp = require('chai-http')
// `require` your exported `app`.
const app = require('../app.js')
chai.should()
chai.use(chaiHttp)
describe('User registration', () => {
it('responds with HTTP 204 if form fields are valid', () => {
return chai.request(app)
.post('/register')
.send({
name: 'John Doe',
email: 'john#doe.com'
})
.then(res => {
res.should.have.status(204)
})
.catch(err => {
throw err
})
})
it('responds with HTTP 400 if some fields are missing', () => {
return chai.request(app)
.post('/register')
.send({
name: 'John Doe'
})
.catch(err => {
err.should.have.status(400)
})
})
})
Then just run your test from the root directory with:
$ mocha test/registration.spec.js

Mocha + Nodejs + Heroku .env file

I have a REST app written in NodeJS running on Heroku. I have my .env file setup for local development and works fine whenever I run foreman to serve my app locally. The app also runs fine when I deploy it to my heroku server.
I am trying to write unit tests for my app with Mocha/Supertest/should/assert. When I run my app through Mocha, it doesn't load up the .env file to get my environment variables – in my case, the URL for the PSQL database. As a result, all my tests that involve DB I/O timeout.
I've been scouring the Internet for a solution but I can't seem to find anything helpful.
Here is some sample code:
app.js:
var application_root = __dirname,
express = require("express"),
port = process.env.PORT || 4482;
pg = require('pg').native,
client = new pg.Client(process.env.DATABASE_URL);
// Connect To DB
client.connect();
(...)
app.get('/api', function (req, res) {
res.send('PS API is running');
});
app.get('/', function (req, res) {
res.send('PS API is running');
});
(...)
// Read Users
app.get('/users', function (req,res) {
user.readUsers(res,client);
});
(...)
// Launch server
console.log('Listening on port: '+ port);
app.listen(port);
module.exports = app;
userTest.js
var request = require('supertest');
var assert = require('assert');
var app = require('app.js');
var should = require('should');
describe('Get /', function(){
it('should respond OK',function(done){
request(app)
.get('/')
.end(function(err, res){
res.status.should.equal(200);
done(err);
});
});
});
describe('Get /api', function(){
it('should respond OK',function(done){
request(app)
.get('/api')
.end(function(err, res){
res.status.should.equal(200);
done(err);
});
});
});
// Getting All Users
describe('Get /users', function(){
it('should respond OK',function(done){
request(app)
.get('/users')
.end(function(err, res){
res.status.should.equal(200);
done(err);
});
});
});
.env
== LOCAL DB ==
DATABASE_URL=MY_DB_URL
HEROKU_POSTGRESQL_GOLD_URL=MY_DB_URL
PATH=bin:node_modules/.bin:/usr/local/bin:/usr/bin:/bin
And the output I get from running mocha test
Listening on port: 4482
․․Getting all users
․
2 passing (2 seconds)
1 failing
1) Get /users should respond OK:
Error: timeout of 2000ms exceeded
at Object.<anonymous> (/usr/local/lib/node_modules/mocha/lib/runnable.js:165:14)
at Timer.list.ontimeout (timers.js:101:19)
When I replace the process.env.DATABASE_URL with my hardcoded PSQL local URL, the tests all pass. So it's clear that the .env file is not being read by mocha.
I have also tried passing env vars to Mocha with little success. Does anyone know of a proper way to have Mocha read in my environment vars from the .env file?
The foreman gem (written by a Heroku engineer, to make it easy to use .env files and Procfiles in development as you would on Heroku production) has a command just for this purpose: run.
foreman run npm test <-- or however you trigger your tests.
Alternatively, on my current project here's what we do:
we have a test.env file containing the environmental variables and values appropriate for testing, in Unix export format. So, yes, export DATABASE_URL=MY_DB_URL. The format is a bit different, but that's an annoyance we're OK with
We have a Makefile containing the following directives:
-include test.env
test:
npm test
When we want to run the tests for our project we just make test. Make will load up the test.env file, assign all the environmental variables, then run npm test for us.
I'm not entirely sure, but I don't think you can make mocha read your .env file. That appears to be specific to foreman. If your environment variable definitions are plain KEY=VALUE, then I believe something as simple as env $(cat .env) mocha would do. Otherwise, you may have to do some preprocessing first using sed/perl/etc.
After searching the internet for days, following is something, that's working for me:
> PATH=$(npm bin):$PATH env $(cat .env) mocha
It is to be noted that PATH=$(npm bin):$PATH is used as my environment was not able to find mocha.

Resources