How to launch supertest files in node? - node.js

I have a node/typescript server. I wish to test the api routes with supertest. I've written my first test, but cannot start it because
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/myname/Desktop/Code/Reapr/server/src/tests/search.test.ts
The test.ts file is:
import request from "supertest";
import { server } from "../index";
describe("GET /user/:id", () => {
it("return user information", (done) => {
request(server)
.get("/user/123")
.set("Accept", "application/json")
.expect("Content-Type", /json/)
.expect(200, done);
});
});
The package.json is:
{
"name": "my-server",
"version": "1.0.0",
"main": "index.js",
"license": "",
"scripts": {
"build": "rimraf ./build && tsc",
"dev": "nodemon",
"lint": "eslint . --ext .js,.ts",
"start": "npm run build && node build/index.js",
"test": "node src/tests/search.test.ts"
},
"type": "module",
"dependencies": {
"bcrypt": "^5.0.1",
"body-parser": "^1.19.0",
"cloudinary": "^1.25.1",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-rate-limit": "^5.2.6",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.12.3",
"multer": "^1.4.2",
"nodemailer": "^6.5.0",
"nodemailer-express-handlebars": "^4.0.0",
"socket.io": "^4.0.1",
"stripe": "^8.142.0"
},
"devDependencies": {
"#types/express": "^4.17.11",
"#types/jest": "^26.0.22",
"#types/mongoose": "^5.10.4",
"#types/node": "^14.14.37",
"#types/socket.io": "^2.1.13",
"#types/stripe": "^8.0.417",
"#typescript-eslint/eslint-plugin": "^4.20.0",
"#typescript-eslint/parser": "^4.20.0",
"babel-plugin-module-resolver": "^4.1.0",
"dotenv": "^8.2.0",
"eslint": "^7.23.0",
"nodemon": "^2.0.7",
"rimraf": "^3.0.2",
"supertest": "^6.1.3",
"ts-node": "^9.1.1",
"typescript": "^4.2.3"
}
}
Also, this error is only here when I explicitly write the script "test": node src/tests/search.test.ts". If I write "test": "jest", I got this error:
jest: command not found
So, how to properly launch my supertests files, if possible all at once, instead of changing the script line for every file?

You can execute a ts file directly with ts-node.
"test": "ts-node src/tests/search.test.ts"
Or build it to js file and run it with node.
To execute jest command, you have to install it, and you are using Typescript (?) then you also need ts-jest:
npm install ts-jest jest -D
Create a configuration file for jest: jest.config.js
module.exports = {
roots: ['<rootDir>/src'],
testMatch: [
'**/__tests__/**/*.+(ts|tsx|js)',
'**/?(*.)+(spec|test).+(ts|tsx|js)',
],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
};
Now, try to execute jest: npx jest

in package.json:
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"setupFilesAfterEnv": [
"./src/test/setup.ts"
]
},
jest does not understand what typescript is, "ts-jest" will add typescript support.
"setupFilesAfterEnv" is optional. if you have a setup file, it will run this to set up extra configuration like adding "beforeAll, beforeEach" etc.
here is the dependencies you need to install for testing environment:
"devDependencies": {
"#types/jest": "^26.0.15",
"#types/supertest": "^2.0.10",
"jest": "^26.6.1",
"supertest": "^6.0.0",
"ts-jest": "^26.4.3"
}
also add this script to package.json:
"test": "jest --watchAll --no-cache"
--no-cache flag is related to typescript setup. jest sometimes does not catch the changes in typescript files.
lastly you imported server but make sure you set up server.ts properly. here I explained: supertest not found error testing express endpoint
this should set your testing environment

Related

Node - attempt to zip directory does not do anyting

I'm trying to archive an entire folder using Node, archiver and fs, but nothing seems to happen.
This is my implementation:
import { createWriteStream } from 'fs';
import archiver from 'archiver';
await zipDirectory('./work', './work/folderName.zip');
const zipDirectory = async (source: string, out: string): Promise<void> => {
const archive = archiver('zip', { zlib: { level: 9 }});
return new Promise((resolve, reject) => {
const stream = createWriteStream(out);
archive
.directory(source, false)
.on('error', err => reject(err))
.pipe(stream);
stream.on('close', () => resolve());
archive.finalize();
});
}
Running on Node 14.15.4
Package.json
{
"name": "rpj",
"version": "1.0.0",
"description": "",
"main": "./dist/src/main.js",
"author": "David Faizulaev",
"license": "ISC",
"scripts": {
"start": "node ./dist/main.js",
"build": "yarn build:js",
"build:prod": "yarn run build:js",
"build:types": "tsc --emitDeclarationOnly",
"build:js": "babel . --out-dir ./dist --extensions \".ts\" --ignore node_modules --ignore dist --source-maps",
"build-ts": "tsc",
"test": "jest --coverage --verbose",
"lint-test": "npm run lint && npm run test",
"lint": "eslint -c .eslintrc.js --ext .ts ./src",
"lint:fix": "eslint --fix -c .eslintrc.js --ext .ts ./src",
"tslint": "tslint -c tslint.json --project tsconfig.json",
"sonar": "node ./config/sonar-project.js",
"prettier": "prettier --write ./projects/**/*.*",
"sonar-dev": "node ./config/sonar-dev-project.js"
},
"dependencies": {
"archiver": "^5.3.0",
"aws-sdk": "2.861.0",
"cheerio": "^1.0.0-rc.5",
"config": "3.3.6",
"esm": "^3.2.25",
"express": "^4.17.1",
"imagemin": "7.0.1",
"imagemin-mozjpeg": "^9.0.0",
"imagemin-pngquant": "^9.0.2",
"jszip": "3.6.0",
"lodash": "4.17.21",
"node-request-context": "^1.0.5",
"uuid": "^8.3.2",
"winston": "^3.3.3"
},
"devDependencies": {
"#babel/cli": "7.13.10",
"#babel/core": "7.13.10",
"#babel/plugin-proposal-class-properties": "7.13.0",
"#babel/plugin-proposal-object-rest-spread": "7.13.8",
"#babel/plugin-transform-runtime": "7.13.10",
"#babel/preset-env": "7.13.10",
"#babel/preset-typescript": "7.13.0",
"#babel/runtime": "7.13.10",
"#types/archiver": "^5.1.1",
"#types/config": "0.0.38",
"#types/express": "^4.17.11",
"#types/imagemin": "7.0.1",
"#types/imagemin-mozjpeg": "^8.0.1",
"#types/jest": "^26.0.20",
"#types/node": "14.14.33",
"#types/uuid": "^8.3.0",
"#typescript-eslint/eslint-plugin": "4.17.0",
"#typescript-eslint/eslint-plugin-tslint": "4.17.0",
"#typescript-eslint/parser": "4.17.0",
"aws-sdk-mock": "5.1.0",
"eslint": "7.21.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.18.0",
"eslint-plugin-jsdoc": "32.2.0",
"jest": "27",
"lint-staged": "^10.5.3",
"sonarqube-scanner": "^2.8.0",
"ts-jest": "27",
"ts-node": "10",
"tslint": "^6.1.3",
"typescript": "4.4.4"
}
}
Please advise on how I can resolve this?
Issue was caused because I did not create the directory to where I wanted to store the zip file.
Once I added the directory creation at startup everything worked.

TypeScript - error TS5023: Unknown compiler option '-r'

I'm working on Windows environment and trying to run a forked node.js + typescript project.
This is my package.json :
{
"name": "my-task",
"version": "1.0.0",
"private": true,
"main": "dist/main.js",
"scripts": {
"start": "tsc-watch --onSuccess 'node -r source-map-support/register .'",
"test": "jest",
"lint": "eslint --cache '{src,test}/**/*.ts'"
},
"dependencies": {
"#types/express": "^4.17.7",
"#types/node": "^12.12.53",
"express": "^4.17.1",
"get-port": "^5.1.1",
"got": "^11.5.1",
"source-map-support": "^0.5.19"
},
"devDependencies": {
"#types/jest": "^26.0.8",
"#typescript-eslint/eslint-plugin": "^3.8.0",
"#typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-jest": "^23.20.0",
"jest": "^26.2.2",
"prettier": "^2.0.5",
"ts-jest": "^26.1.4",
"tsc-watch": "^4.2.9",
"typescript": "^4.0.2"
}
}
For some reason, i'm getting the following error:
error TS5023: Unknown compiler option '-r'.
I tried to remove the -r, but then i'm getting these errors:
error TS6054: File '.'' has an unsupported extension. The only supported extensions are '.ts', '.tsx', '.d.ts'.
error TS6231: Could not resolve the path 'source-map-support/register' with the extensions: '.ts', '.tsx', '.d.ts'.
and server won't start.
I ran npm uninstall + npm install - nothing seems to solve these issues.
Can anyone assist?
EDITED:
ts.config:
{
"extends": "../tsconfig.json",
"include": ["**/*.ts"]
}

SyntaxError Importing Mocha for Typescript Unit Testing

Below I have a sample test for a Typescript project. I'm using mocha chai to do the testing. The test case is blank for now.
import {KafkaConsumer} from '../infrastructure/delivery/kafka/kafka-consumer';
import {expect} from 'chai';
import {describe, it} from 'mocha';
describe('KafkaConsumer Initialization', () => {
it('should initialize KafkaConsumer', () => {
})
})
When I run the test I get the following error:
import {describe} from 'mocha';
^
SyntaxError: Unexpected token {
Any idea why this might be? If I change line 3 to import 'mocha'; I a similar SyntaxError. Without that line, describe() and it() are not defined
Below is my package.json file.
{
"name": "wss",
"version": "0.0.0",
"private": true,
"main": "dist/index.js",
"scripts": {
"tsc": "tsc",
"start": "node --inspect=5858 -r ts-node/register ./src/index.ts",
"start:watch": "nodemon",
"build": "tsc",
"prod": "tsc && npm run postbuild && node ./dist/index.js",
"postbuild": "npm run copy-files",
"copy-files": "copyfiles -u 1 ./src/**/*.js dist",
"test": "env TS_NODE_COMPILER_OPTIONS='{\"module\": \"commonjs\" }' mocha -r ts-node/register 'tests/**/*.ts'",
"test:watch": "nodemon --exec npm test"
},
"nyc": {
"require": [
"ts-node/register"
],
"include": [
"src/**/*.ts"
],
"extension": [
".ts"
],
"reporter": [
"lcov",
"text"
],
"sourceMap": true,
"instrument": true
},
"dependencies": {
"#types/dotenv": "^6.1.1",
"#types/newrelic": "^5.11.0",
"#types/redis": "^2.8.21",
"aws-iot-device-sdk": "^2.2.4",
"axios": "^0.19.0",
"bluebird": "^3.5.5",
"chai-http": "^4.3.0",
"cookie-parser": "~1.4.3",
"copyfiles": "^2.2.0",
"dotenv": "^7.0.0",
"express": "~4.16.0",
"kafka-node": "^4.1.3",
"lodash": "^4.17.15",
"morgan": "~1.9.0",
"newrelic": "^5.11.0",
"redis": "^3.0.2",
"reflect-metadata": "^0.1.13",
"uuid": "^8.0.0"
},
"devDependencies": {
"#types/bluebird": "^3.5.27",
"#types/express": "^4.16.1",
"#types/jsonwebtoken": "^8.3.2",
"#types/lodash": "^4.14.150",
"#types/mocha": "^8.0.0",
"#types/node": "^11.13.14",
"#types/winston": "^2.4.4",
"chai": "^4.2.0",
"eslint": "^4.19.1",
"mocha": "^8.0.1",
"nodemon": "^1.18.11",
"nyc": "^14.1.1",
"ts-node": "^8.10.2",
"ts-node-dev": "^1.0.0-pre.41",
"tslint": "^5.16.0",
"typescript": "^3.9.2",
"typescript-eslint-parser": "^22.0.0"
}
}
RESOLVED! test script in package.json should be changed to:
"test": "mocha --require ts-node/register --watch-extensions ts './src/test/test.ts'",

Jest fails with SyntaxError: Unexpected token {

I'm integrating jest into my nuxt application using vue-test-utils (following Edd Yerburgh's new book).
The test fails right out of the box with "SyntaxError: Unexpected token {". Similar code builds fine with nuxt and the tests ran with Ava. I'm assuming that I have a problem with my jest configuration.
I've included my package.json, code excerpt and console out.
Thanks for any help,
Dan
npm 6.4.0
package.json
{
"name": "cxl-ui-base",
"version": "1.0.0",
"description": "Base UI for SA and CXL",
"author": "Dan Mahoney <dan.mahoney#contextlabs.com>",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"test:coverage": "TEST=unit nyc --report-dir=generated-files/coverage ava --tap | tap-summary",
"test:unit": "NODE_ENV=testing jest --verbose --no-cache",
"test:watch": "NODE_ENV=pro ava --watch",
"lint": "eslint -f node_modules/eslint-detailed-reporter/lib/detailed.js --ext .js,.vue -o generated-files/lint.html .",
"doc": "jsdoc -c doc.conf.js"
},
"dependencies": {
"#nuxtjs/auth": "^4.5.1",
"#nuxtjs/axios": "^5.3.1",
"#nuxtjs/dotenv": "^1.1.1",
"ava-describe": "^2.0.0",
"axios": "^0.18.0",
"body-parser": "^1.18.3",
"dotenv": "^5.0.1",
"eslint-import-resolver-alias": "^1.1.1",
"express": "^4.16.3",
"jsdoc-vue": "^1.0.0",
"jsonwebtoken": "^8.2.1",
"leaflet": "^1.3.1",
"lodash": "^4.17.10",
"moment": "^2.22.1",
"npm": "^6.4.0",
"nuxt": "1.4.1",
"nuxt-leaflet": "0.0.10",
"nuxt-material-design-icons": "^1.0.4",
"oauth-1.0a": "^2.2.4",
"vue": "^2.5.16",
"vue-d3": "^0.1.0",
"vue-i18n": "^7.6.0",
"vue-uuid": "^1.0.0",
"vue2-leaflet": "^1.0.2",
"vuelidate": "^0.7.2",
"vuetify": "^1.0.17",
"vuex": "^3.0.1",
"webpack-node-externals": "^1.7.2"
},
"devDependencies": {
"#babel/core": "^7.0.0-rc.2",
"#vue/test-utils": "^1.0.0-beta.19",
"ajv": "^6.5.0",
"babel-eslint": "^7.2.3",
"babel-jest": "^23.4.2",
"babel-plugin-add-module-exports": "^0.3.3",
"babel-plugin-transform-imports": "^1.4.1",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.24.1",
"babel-preset-vue-app": "^2.0.0",
"chromedriver": "^2.38.3",
"eslint": "^4.3.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-config-standard": "^10.2.1",
"eslint-detailed-reporter": "^0.7.3",
"eslint-import-resolver-webpack": "^0.9.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-html": "^4.0.3",
"eslint-plugin-import": "^2.12.0",
"eslint-plugin-jsdoc": "^3.7.1",
"eslint-plugin-leon-require-jsdoc": "0.0.1",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-promise": "^3.7.0",
"eslint-plugin-standard": "^3.1.0",
"eslint-plugin-vue": "^4.5.0",
"eslint-plugin-vue-a11y": "0.0.26",
"jest": "^23.5.0",
"jest-vue-preprocessor": "^1.4.0",
"jsdoc": "^3.5.5",
"jsdom": "^11.11.0",
"jsdom-global": "^3.0.2",
"loglevel": "^1.6.1",
"nightwatch": "^0.9.21",
"npm-merge-driver": "^2.3.5",
"raf": "^3.4.0",
"require-extension-hooks": "^0.3.2",
"require-extension-hooks-babel": "^0.1.1",
"require-extension-hooks-vue": "^1.0.0",
"selenium": "^2.20.0",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.1",
"tap-summary": "^4.0.0",
"vue-jest": "^2.6.0",
"vue-loader": "^13.7.2",
"vue-meta": "^1.5.0",
"vue-template-compiler": "^2.5.16"
},
"jest": {
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue-jest"
}
},
"eslintConfig": {
"env": {
"browser": true,
"node": true,
"jest": true
}
}
}
Code
import { shallowMount, createLocalVue } from '#vue/test-utils';
import Vuetify from 'vuetify';
import test from 'jest';
import ClientMap from '#/components/Map'; // eslint-disable-line
import { commonAssertions } from '#/plugins/test.utils';
// for mocking
import modal from '#/components/Modal'; // eslint-disable-line
const localVue = createLocalVue();
localVue.use(Vuetify);
test('Sanity Test', () => {});
test('Initial State', (t) => {
const $modal = sinon.mock(modal);
const wrapper = shallowMount(Map, {
mocks: {
$modal,
},
localVue,
});
commonAssertions(Map, t, wrapper);
});
test.todo('Select Layer');
test.todo('Test Modal??');
test.todo('Test Tooltip??');
test.todo('UnSelect Layer');
Relevant Output
FAIL src/test/specs/map.spec.js
● Test suite failed to run
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".
Here's what you can do:
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/Users/dan.mahoney/Projects/cxl-ui-base/src/test/specs/map.spec.js:10
import { shallowMount, createLocalVue } from '#vue/test-utils';
^
SyntaxError: Unexpected token {
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:403:17)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 1.045s
The problem is that nuxt puts the babel config into nuxt.config.js. I found an npm package that solves that. It allows you to have a .babelrc file and have it injected into nuxt.config.js. When Jest compiles the files for testing, it uses .babelrc. Kudos to the author.
You should set the NODE_ENV to test then run the jest
you can do it by adding this line to your package.json file
"scripts": {
....
"test": "NODE_ENV=test jest"
},

nodemon not refreshing when using typescript

I'm working on an app with NodeJs, express, typescript and nodemon.
But the page is not refreshed when I changed some code in the ts files.
How can I do to compile the ts file in js and refresh the browser with nodemon (or other tool)?
package.json
{
"name": "myapp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.17.2",
"debug": "^2.6.8",
"dotenv": "^2.0.0",
"express": "^4.15.3",
"iconv-lite": "^0.4.17",
"inversify": "^4.11.1",
"jsonwebtoken": "^7.4.1",
"mongoose": "^5.0.10",
"morgan": "^1.8.2",
"passport": "^0.3.2",
"passport-jwt": "^2.2.1",
"rxjs": "^5.4.2",
"typescript": "^2.7.2",
"winston": "^2.3.1"
},
"devDependencies": {
"#types/chai": "^4.0.0",
"#types/debug": "0.0.29",
"#types/dotenv": "^2.0.20",
"#types/express": "^4.0.35",
"#types/mocha": "^2.2.41",
"#types/mongoose": "^4.7.15",
"#types/morgan": "^1.7.32",
"#types/node": "^6.0.77",
"#types/passport": "^0.3.3",
"#types/passport-jwt": "^2.0.20",
"chai": "^4.0.2",
"chai-http": "^3.0.0",
"gulp": "^3.9.1",
"gulp-clean": "^0.3.2",
"gulp-typescript": "^3.1.7",
"gulp-yaml": "^1.0.1",
"mocha": "^3.4.2",
"mocha-typescript": "^1.1.4"
},
"scripts": {
"start": "gulp build && nodemon dist/index.js",
"build": "gulp build",
"test": "gulp build && mocha -t 30000 dist/**/*.test.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/devslaw/TypeScript-Node.js-REST-example.git"
},
"keywords": [],
"author": "Arthur Arakelyan <arthur#devslaw.com>",
"license": "ISC",
"homepage": "https://github.com/devslaw/TypeScript-Node.js-REST-example#readme"
}
So know, anytime i make a change, I need to stop the server and run npm start again
The problem lies in the fact that your start script is watching dist/index.js. This folder only changes when the code gets recompiled into plain JavaScript. So you will need to watch the TypeScript files instead. The great thing is that you can change nodemon's default behavior. You will need to add ts-node to your package.json as well.
Try setting the script to something like the following:
nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts
You will then want to set up a nodemon.json file with the following also:
{
"watch": ["src"],
"ext": "ts",
"exec": "ts-node ./src/index.ts"
}

Resources