99 Followers
·
Follow

Typescript with Jasmine: easy project setup

In this article, we will go straight to the point for creating a typescript project from scratch, with Jasmine as a unit test framework, and webpack as a source bundler. The tutorial will be explained step by step with relevant commands.

Initially, my need was to have an easy typescript project setup so I can quickly implement any idea or train with a TDD (Test Driven Development) approach. But I couldn’t find a single and easy tutorial out there. Many of them were useless, confusing or time consuming. Confusing because lots of unnecessary dependencies are often required to be installed although the author doesn’t explain why… So my challenge here is to share my project setup with you in the most effective way so you’ll save your precious time and have a minimalist but efficient way to have a typescript project with a testing environment enabling unit tests implementation.

Key Take aways

I like starting with the take aways first so you can read further the details if interested.

  • your typescript, bundling and transpiling environment is as easy as installing typescript webpack webpack-cli webpack-dev-server ts-loader
  • for running your unit tests, you don’t need to install tools like ‘karma’ or ‘mocha’. Indeed, you don’t need a browser nor an http server to be launched to run unit tests. Unit tests are fully isolated tests that should be deterministic and should not rely nor require 3rd part dependencies except the testing environment. So in that manner, setting your testing environment is easy as installing jasmine jasmine-ts @types/jasminejasmine-spec-reporter ts-node
  • always init your project with command line tools, rather that by hand. (such as using npm init rather than creating the package.json file by hand; or using tsc init rather than creating the tsconfig.json by hand).
  • always use configuration file either for webpack (webpack.config.js)or for jasmine jasmine.json
  • always use local dependencies of your project, rather than globally installed dependencies on your system. To do so, use the npx tool that will look for binaries or scripts inside your node_modules directory.
  • first thing when you create a project, version it with git and create your .gitignore file. Make it an habit.

Start your project with git

Whenever you start a project from scratch, your primary automation should be to create a .gitignore file and add directory names that you should not track as source code (that is your IDE’s configuration files, your node_modules dependencies or your bundled file)

.idea/
node_modules/
dist

Then as you know, a simple git init; git add .; git commit should do the work.

Init your project with npm

Now simply use the npm init command so you will have a wizard that will guide you to define your project metadata. One file, named package.json will thus by created and used by npm (for declaring dependencies or running build & tests scripts).

Setup Typescript

Now it is time to install development dependencies for your projects. To do so, you will need to use npm to install these. The first dependency is of course typescript.

npm install --save-dev typescript
  • TypeScript is an open-source programming language which is a superset of javascript. Typescript came with a compiler called tsc which transpiles your TypeScript code to JavaScript code. TypeScript is developed and maintained by Microsoft.

Now, our package.json should look something like this :

{
"name": "typescript-from-scratch",
"version": "1.0.0",
"description": "example of typescript project with unit tests framework",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "@turhanoz",
"license": "ISC",
"devDependencies": {
"typescript": "^3.8.2"
}

}

Now it is time to configure typescript to let the transpiler (called tsc) now in which javascript format it has to convert the typescript source codes. To define the configuration file (tsconfig.json), it is a best practice to call the init script of tsc by running the following command (instead of creating it manually,) :

npx tsc --init

  • npx is a utility that came when you installed npm and allows to execute a command directly installed in the project path. In a word, both following commands are equivalent :
$ npx tsc --init
$ ./node_modules/typescript/bin/tsc --init

This command will create the tsconfig.json file with all possible options that the transpiler can understand. Remove most of them and keep only the relevant ones as follow :

{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es2015","dom"],
"allowJs": true,
"sourceMap": true,
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
}
}

Be aware that we added some library to be used by the transpiler and we also define the root directory containing all our source code as being ./src .

Now we this configuration, you can transpile any .ts file into a js file using tsc . However, it is not really convenient as you have to pass each single file path to tsc to let it know. This could really become messy if your project has many files. That is why we’ll use webpack to easily combine all our source code into a single output file.

Configure Webpack

The dependencies you’ll need to install webpack are the following :

npm install --save-dev webpack webpack-cli webpack-dev-server
npm install --save-dev ts-loader

Let’s go through each dependency to clearly understand them :

  • Webpack is a bundler. It takes all your module and dependencies and bundle them in a single static file.
  • webpack-cli : as stated in the official documentation, webpack-CLI is a tool that provides a flexible set of commands for developers to increase speed when setting up a custom webpack project.
  • webpack-dev-server : as stated in the official documentation, it is a development server that provides live reloading. This should be used for development only. Whenever you change a single bit of code in development phase, this tool automatically rebundle your project.
  • ts-loader : webpack uses loaders to preprocess files, that is for instance transforming file from one language to javascript. The concept of loader is explained here. In our case, as we are dealing with TypeScript, we want webpack to use ts-loader to preprocess all our typescript source codes.

Now we need a webpack configuration file to feed webpacks with some rules so the latter can know where look for. Unfortunately, we have to create this file by hand as there is no wizard to guide us. The webpack.config.js looks like :

const path = require('path');module.exports = {
entry: './src/index.ts',
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
include: [
path.resolve(__dirname, "src")
],
},
],
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};

Be aware of the lines in bold. For the rule, we guide weback to look for files having .ts .js .tsx extensions in the src folder using the ts-loader loader.

We also define that the output file should be named bundle.js and be located in the dist folder.

Now, to build our project, we simple need to run webpack, passing it the configuration file path : npx webpack --config=webpack.config.js

For easily run the building of our project, we can enhance our package.json script part to add the appropriate command. Thus, calling npm run build would be our preferred command to build the project. Our package.json should now look like :

{
"name": "typescript-from-scratch",
"version": "1.0.0",
"description": "example of typescript project with unit tests framework",
"main": "index.js",
"scripts": {
"build": "npx webpack --config=webpack.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "@turhanoz",
"license": "ISC",
"devDependencies": {
"typescript": "^3.8.2",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"ts-loader": "^6.2.1"

}
}

Configure Jasmine

As said in the introduction, we don’t need to install tools like ‘karma’ or ‘mocha’. Indeed, we don’t need a browser nor an http server to be launched to run unit tests. Unit tests are fully isolated tests that should be deterministic and should not rely nor require 3rd part dependencies except the testing environment. We simply use Jasmine as a testing framework.

The dependencies you’ll need to install your testing environment are the following

npm install --save-dev jasmine @types/jasmine
npm install --save-dev ts-node jasmine-ts
npm install --save-dev jasmine-spec-reporter

Let’s go through each dependency to clearly understand them :

  • jasmine : it is a testing framework for javascript code. It does not require DOM
  • @types/jasmine : it contains the type definition for Jasmine to be used with TypeScript.
  • ts-node : typescript source code does not run directly on Node. We first need to transpile the code and then pass it to Node. So ts-node is an executable that automate this part.
  • jasmine-ts : makes use of jasmine in combination of ts-node
  • jasmine-spec-reporter : outputs the results of the tests in a pretty way in the console

Now we need a jasmine configuration file to guide jasmine look for the test files (also called spec files) and to use jasmine-spec-reporter. To do so, we first create a jasmine.json configuration file :

{
"reporters": [
{
"name": "jasmine-spec-reporter#SpecReporter",
"options": {
"displayStacktrace": "all"
}
}
],
"spec_dir": "spec",
"spec_files": ["**/*[sS]pec.ts"]
}

In this file, we simply tell jasmine that

  • the test files (spec files) are located into a directory called spec
  • the test files has a naming convention, such as they end with [sS]pec.ts
  • the reporter is jasmine-spec-reporter

So for running jasmine, it is as easy as calling jasmine-ts with this jasmine.json configuration file : jasmine-ts --config=jasmine.json

For easily run the testing of our project, we can enhance our package.json script part to add the appropriate command. Thus, calling npm run test would be our preferred command to test the project. Our package.json should now look like :

{
"name": "typescript-from-scratch",
"version": "1.0.0",
"description": "example of typescript project with unit tests framework",
"main": "index.js",
"scripts": {
"build": "npx webpack --config=webpack.config.js",
"test": "jasmine-ts --config=jasmine.json"
},
"author": "@turhanoz",
"license": "ISC",
"devDependencies": {
"typescript": "^3.8.2",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3",
"ts-loader": "^6.2.1",
"jasmine": "^3.5.0",
"
@types/jasmine": "^3.5.4",
"ts-node": "^8.6.2",
"jasmine-ts": "^0.3.0",
"jasmine-spec-reporter": "^4.2.1"

}
}

Our project should look like :

$ tree -L 1
.
├── dist
├── jasmine.json
├── node_modules
├── package-lock.json
├── package.json
├── spec
├── src
├── tsconfig.json
└── webpack.config.js

Conclusion

Setting up a bare typescript project with a testing environment is not that complicated as you see. Moreover, we have added only the necessary dependencies, either for building or for testing our code. We saw the importance of configuration files and also the conveniency of adding CLI scripts directly into our package.json . Finally, our project is an invitation to train on TDD as the environment is already setup.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store