What's the right way to write Jest tests verified with Flow? - jestjs

I imagine people commonly use Flow and Jest (and React) together, but Flow doesn't seem to know about Jest (or Jasmine) globals. When I add // #flow to my tests, I get Flow errors like this:
src/__tests__/Thing-test.js:3
3: jest.unmock('../Thing')
^^^^ identifier `jest`. Could not resolve name
src/__tests__/Thing-test.js:7
7: describe('Thing', () => {
^^^^^^^^ identifier `describe`. Could not resolve name
src/__tests__/Thing-test.js:8
8: it('does stuff', () => {
^^ identifier `it`. Could not resolve name
I could write a Flow interface for Jest/Jasmine, but that seems lengthy and like I must be missing something. Letting Flow process node_modules/jest-cli doesn't seem to help.

Although Jest is written with flow annotations they strip types for the npm version so we don't need babel to run it. Fortunately the types are already in flow-type so the solution is quite easy (just as mentioned in the comment):
npm install -g flow-typed
flow-typed install jest#22.x.x # <-- replace the version with the latest
Although I had to add this line as well to my .eslintrc.json:
{
"env": {
"jest": true
}
}

The accepted answer does not work if you use Create-React-App. Here is how you would set up jest with CRA:
1.Install flow to your project
If you use create-reat-app, here is a guide for this step.
yarn add -D flow-bin
yarn run flow init
2. Install jest flow types
npx flow-typed install jest#22 // maybe you need a different version
(You can use npx jest -v to check your jest version if you use create-react-app.)
3. Register flow-typed in config
(Update: as #Black points out in the comments, this step may not even be neccessary)
In your .flowconfig, add flow-typed to libs section.
...
[libs]
flow-typed
...
I use yarn, npm should work just the same.

If you created your project with create-react-app you have to manually add jest to your packages.json. Otherwise flow-typed won't install the needed type definitions because create-react-app doesn't add this dependency to packages.json.
yarn add --dev jest
flow-typed install

You can also run it as a one liner.
Here you go:
npm i -D flow-typed && npx flow-typed install jest#"$(npx jest -v)"

I think declare var jest: any; should do the trick (put it either on top of each test file, or somewhere in your flow lib directory).

Related

How use seeding options in MikroOrm with nestJs?

I'm using MikroOrm inside nestJs, and I added the following script inside package.json
"orm": "npx mikro-orm",
and these are the configurations
seeder: {
path: 'src/misc/db/',
defaultSeeder: 'DatabaseSeeder',
glob: '!(*.d).{js,ts}',
emit: 'ts',
fileName: (className: string) => className,
}
I need to specify a specific seeder file when writing npm run orm seeder:run --class=ClassNameSeeder as the documentation mentioned, but I'm getting the following error
Unknown argument: ClassName
I tried also to run the following script in package.json and see if it'll work or not but I got the same error
"db:seed": "npm run mikro-orm seeder:run --class=ClassName"
Note
The seeder class is inside misc/db/ as I added it in my configuration file.
I believe you are passing the --class into the npm run instead of mikro-orm commands. I dont think it makes much sense to have an NPM script as "orm": "npx mikro-orm", better to use npx directly, which won't suffer from this.
npx mikro-orm seeder:run --class=ClassNameSeeder
Alternatively, add -- when you call npm. Or use something smarter like yarn or pnpm, which also handles this automatically.
npm run orm seeder:run -- --class=ClassNameSeeder
I have a similar setup as yours, and I just run the following script:
npm run orm seeder:run
This will seed your database using the seeder file src/misc/db/DatabaseSeeder.ts by default.
Do you have multiple files, hence the need to add the class argument ?
If so, Martin's answer is probably the best to follow.

Error - ESLint: 7.32.0 ESLint couldn't find the config "standard" to extend from

We have a CircleCI Pipeline. We have a older version of eslint i.e. 5.10.0 which was around three years ago installed and now client wants to upgrade node version to 16 and upgrade related packages.
I have modified package.json file and changes eslint version from "eslint": "^5.10.0" to "eslint": "^7.10.0".
Now, while pushing changes on branch CircleCI test execution fails with the below error.:
Oops! Something went wrong! :(
ESLint: 7.32.0
ESLint couldn't find the config "standard" to extend from. Please check that the name of the config is correct.
The config "standard" was referenced from the config file in "/home/xxx/xxx/.eslintrc.yml".
I have googled for this issue but did not find the proper solution for this.
I have tried to
Removed .eslintrc.yml file by guessing that it can be created automatically.
Try to run the command yarn run eslint --init inside package.json under script tag
"scripts": {
"test": "yarn run eslint --init && yarn lint && yarn flow && yarn jest",
}
But here, CircleCI pipeline is used so eslint --init command will ask question
How would you like to use ESLint?
We don't have any provision in CircleCI during automated file and test execution to provide any answer.
I had a similar case, where this error was due to my eslint version being too new compared to the one required by standard.
Here are some steps you can try to verify whether that's the case for you as well:
Locally in your project, run npm init #eslint/config (will ask you some questions and generate a new .eslint.{js|yml|json} out of it)
When asked "Which style guide do you want to follow?" reply standard
at this point, you should see something on the line of
The style guide "standard" requires eslint#^7.12.1. You are currently using eslint#{version}
Do you want to downgrade?
choosing "No" will warn you as follow and cause the error you mentioned when trying to execute linting.
Note: it might not work since ESLint's version is mismatched with the standard config
In my case the eslint version was differing by major (8.11.0) which makes it more obvious, but it looks very similar to what you have too.
If by this point you figured that's indeed the issue, here are some alternatives that might help:
Downgrade eslint (easy one but won't work in the long run if you like your dependencies to be up-to-date)
Switch to another style guide which doesn't have this limitation with eslint version (eg. airbnb or google's are suggested by the config setup)
Switch to using standard directly instead of going through eslint
I am no expert in js world, so please feel free to point out anything I missed

How to create a simple (Hello World) node.js TypeScript project with ES6 modules?

Imagine a very simple program with a main file and some functions in a separate file, using ES6 modules and intended to be run with node.js.
my-utils.ts:
import * as fs from "fs";
export function readSimpleFile() {
return fs.fileReadSync("hello.txt", "utf-8");
}
main.ts:
import {readSimpleFile} from "./my-utils"
console.log(readSimpleFile());
What is the minimum set of files I need to add to the project and commands I have to run to get it building, running and checking types?
If you are to run a typescript project with node you need to have at least node, npm and typescript installed on your plateform.
Using an IDE to setup the project
Using intelliJ IDEA or Webstorm (they are the ones I know the best), the compilation of typescript into javascript is done automatically; you only need to do some settings.
Let us assume you have a file called project.ts containing your hello world code; IDEA or Webstorm will compile your code to project.js. Then you will only need to do node project.js to run your project.
Doing everything from scratch
First you need to know where exactly your npm packages are installed globally. This command can help you identify the path: npm config get prefix. In this folder, you should have a nodes_modules subfolder that contains the typescript module. If there is no typescript module, that is because you did not install typescript globally (npm install -g typescript).
Then you have to add the path of the bin of typescript subfolder in your environment variable.
Now you can compile the project with typescipt: tsc project.ts and you can run it node project.js.
Since you are using node function like fs you will need to install node typings npm install #types/node --save-dev before compiling with tsc.
Compilation option
To enable or disable all strict type checking options, you might need to use compilation option. You have to create the file in which you will specify the compilation option: tsc --init will create a tsconfig.json in which you can specify what behaviour you would like to have during the compilation of your app. All options are listed here.

browserify will not compile express js

I wrote a very basic express.js app. Then tried to make it one .js file. Browserify compiled the whole thing to a one file. But browserify-compiled code didn't work. As far as I know, browserify just replaces require statements with module codes. Error is:
C:\Users\HP\n\express\app.js:27025
__proto__: http.IncomingMessage.prototype
^
TypeError: Cannot read property 'prototype' of undefined
at Object.__dirname.173.accepts (C:\Users\HP\n\express\app.js:27025:34)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.170../application (C:\Users\HP\n\express\app.js:26823:11)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.168../lib/express (C:\Users\HP\n\express\app.js:26154:18)
at s (C:\Users\HP\n\express\app.js:1:316)
at C:\Users\HP\n\express\app.js:1:367
at Object.__dirname.153.express (C:\Users\HP\n\express\app.js:24010:15)
Browserify is designed specifically to package code for a browser.
Node.js supports a number of modules that a browser doesn't which have to be emulated by builtins. These modules will be replaced by a browser-specific shim. Some only supply a subset of the Node API that makes sense to have in a browser.
So you are running an app that has converted all the Node.js modules to support running what it can in a browser, back in Node where the modules are available but are no longer being used.
Try rollup or you could possibly configure babel to work like you need
I had this very same issue but like you said the compile code should work on server side. I solved it from this link:
https://www.linkedin.com/pulse/bundling-nodemodules-your-nodejs-app-one-single-file-xuan-son-nguyen/
Use browserify for bundling and terser for minifying. Starting by installing them globally:
npm install -g browserify
npm install -g terser
Next, we have to add a build script to package.json
...
"scripts": {
...
"build": "browserify --node --ignore-missing index.js | terser > bundle.js"
}
...
Each time you want to promote to production, you have to make a new bundle:
npm run build
A new file called "bundle.js" will be created.
Let there be peace, and there was peace. Happy coding.

How to run TypeScript files from command line?

I'm having a surprisingly hard time finding an answer to this. With plain Node.JS, you can run any js file with node path/to/file.js, with CoffeeScript it's coffee hello.coffee and ES6 has babel-node hello.js. How do I do the same with Typescript?
My project has a tsconfig.json which is used by Webpack/ts-loader to build a nice little bundle for the browser. I have a need for a build step run from the console before that, though, that would use some of the .ts files used in the project to generate a schema, but I can't seem to be able to run a single Typescript file without compiling the whole project.
How do I do the same with Typescript
You can leave tsc running in watch mode using tsc -w -p . and it will generate .js files for you in a live fashion, so you can run node foo.js like normal
TS Node
There is ts-node : https://github.com/TypeStrong/ts-node that will compile the code on the fly and run it through node 🌹
npx ts-node src/foo.ts
Run the below commands and install the required packages globally:
npm install -g ts-node typescript '#types/node'
Now run the following command to execute a typescript file:
ts-node typescript-file.ts
We have following steps:
First you need to install typescript
npm install -g typescript
Create one file helloworld.ts
function hello(person){
return "Hello, " + person;
}
let user = "Aamod Tiwari";
const result = hello(user);
console.log("Result", result)
Open command prompt and type the following command
tsc helloworld.ts
Again run the command
node helloworld.js
Result will display on console
To add to #Aamod answer above, If you want to use one command line to compile and run your code, you can use the following:
Windows:
tsc main.ts | node main.js
Linux / macOS:
tsc main.ts && node main.js
Edit: May 2022
ts-node now has an --esm flag use it.
Old Answer:
None of the other answers discuss how to run a TypeScript script that uses modules, and especially modern ES Modules.
First off, ts-node doesn't work in that scenario, as of March 2020. So we'll settle for tsc followed by node.
Second, TypeScript still can't output .mjs files. So we'll settle for .js files and "type": "module" in package.json.
Third, you want clean import lines, without specifying the .js extension (which would be confusing in .ts files):
import { Lib } from './Lib';
Well, that's non-trivial. Node requires specifying extensions on imports, unless you use the experimental-specifier-resolution=node flag. In this case, it would enable Node to look for Lib.js or Lib/index.js when you only specify ./Lib on the import line.
Fourth, there's still a snag: if you have a different main filename than index.js in your package, Node won't find it.
Transpiling makes things a lot messier than running vanilla Node.
Here's a sample repo with a modern TypeScript project structure, generating ES Module code.
I created #digitak/esrun, a thin wrapper around esbuild and that executes a TypeScript file almost instantly. esrun was made because I was disappointed with ts-node: too slow, and just didn't work most of the time.
Advantages of esrun over ts-node include:
very fast (uses esbuild),
can import ESM as well as CJS (just use the libraries of your choice and esrun will work out of the box),
there is an included watch mode, run your script with the --watch option and any change to your entry file or any of its dependencies will re-trigger the result
you can use esrun in inspect mode to use the DevTools console instead of your terminal console.
After installing, just run:
npx #digitak/esrun file.ts
Just helpful information - here is newest TypeScript / JavaScript runtime Deno.
It was created by the creator of node Ryan Dahl, based on what he would do differently if he could start fresh.
You can also try tsx.
tsx is a CLI command (alternative to node) for seamlessly running TypeScript, its build upon esbuild so its very fast.
https://github.com/esbuild-kit/tsx
Example:
npx tsx ./script.ts
As of May 2022 ts-node does support es modules
npx ts-node --esm file.ts
you will likely need to add "type": "module", to your package.json. And some of the imports might be wonky unless you turn on experimental-specifier-resolution=node
npmjs.com/package/ts-node#commonjs-vs-native-ecmascript-modules
For linux / mac you can add the ts-node-script shebang.
Install typescript / ts-node globally (see 1 below for non global install):
npm install ts-node typescript --save-dev --global
Add this as the first line in your .ts file:
#!/usr/bin/env ts-node-script
Then make the file executable:
$ chmod +x ./your-file.ts
You can then run the file directly from the command line:
$ ./your-file.ts
Notes:
1 For non global install you can install local to your project
npm install ts-node typescript --save-dev
and add the relative path to the shebang script eg:
#!/usr/bin/env ./node_modules/.bin/ts-node-script
2 Support for shebangs was officially added in ts-node v8.9.0.
Like Zeeshan Ahmad's answer, I also think ts-node is the way to go. I would also add a shebang and make it executable, so you can just run it directly.
Install typescript and ts-node globally:
npm install -g ts-node typescript
or
yarn global add ts-node typescript
Create a file hello with this content:
#!/usr/bin/env ts-node-script
import * as os from 'os'
function hello(name: string) {
return 'Hello, ' + name
}
const user = os.userInfo().username
console.log(`Result: ${hello(user)}`)
As you can see, line one has the shebang for ts-node
Run directly by just executing the file
$ ./hello
Result: Hello, root
Some notes:
This does not seem to work with ES modules, as Dan Dascalescu has pointed out.
See this issue discussing the best way to make a command line script with package linking, provided by Kaspar Etter. I have improved the shebang accordingly
Update 2020-04-06: Some changes after great input in the comments: Update shebang to use ts-node-script instead of ts-node, link to issues in ts-node.
Write yourself a simple bash wrapper may helps.
#!/bin/bash
npx tsc $1 && node ${1%%.ts}
For environments such as Webstorm where the node command cannot be changed to ts-node or npx:
npm install ts-node typescript (Install dependencies)
node --require ts-node/register src/foo.ts (Add --require ts-node/register to "Node parameters")
This answer may be premature, but deno supports running both TS and JS out of the box.
Based on your development environment, moving to Deno (and learning about it) might be too much, but hopefully this answer helps someone in the future.
Just in case anyone is insane like me and wants to just run typescript script as though it was a .js script, you can try this. I've written a hacky script that appears to execute the .ts script using node.
#!/usr/bin/env bash
NODEPATH="$HOME/.nvm/versions/node/v8.11.3/bin" # set path to your node/tsc
export TSC="$NODEPATH/tsc"
export NODE="$NODEPATH/node"
TSCFILE=$1 # only parameter is the name of the ts file you created.
function show_usage() {
echo "ts2node [ts file]"
exit 0
}
if [ "$TSCFILE" == "" ]
then
show_usage;
fi
JSFILE="$(echo $TSCFILE|cut -d"." -f 1).js"
$TSC $TSCFILE && $NODE $JSFILE
You can do this or write your own but essentially, it creates the .js file and then uses node to run it like so:
# tsrun myscript.ts
Simple. Just make sure your script only has one "." else you'll need to change your JSFILE in a different way than what I've shown.
Install ts-node node module globally.
Create node runtime configuration (for IDE) or use node in command line to run below file js file (The path is for windows, but you can do it for linux as well)
~\AppData\Roaming\npm\node_modules\ts-node\dist\bin.js
Give your ts file path as a command line argument.
Run Or Debug as you like.
Create your TypeScript file (ex. app.ts)
npm i -D typescript ts-node -> to install the dev dependencies local
npx nodemon app.ts
Using nodemon, automatically recompile app.ts every time you change the file
Here is the command
tsc index.ts --outDir .temp && node .temp/index.js && rm -rf .temp
<<<<<<<<< Compile >>>>>>>>> <<<<<<< Run >>>>>>> << Clean >>
There is also an option to run code directly from the CLI, not the *.ts file itself.
It's perfectly described in the ts-node manual.
As a first step, install ts-node globally via npm, yarn, or whatever you like.
...and now just use ts-node -e 'console.log("Hello, world!")' (you may also add the -p flag for printing code)
This little command is perfect for checking, does everything installed fine. And for finding some other error, relevant with tsconfig.json options.
We can run it using nodemon as well
nodemon ./filepath/filename.ts
This question was posted in 2015. In 2018, node recognizes both .js and .ts. So, running node file.ts will also run.

Resources