In Part 5 (Step 6: Gulp) we built up our fully working ecosystem with TypeScript. It enables us to use TypeScript, compile it automatically on every change, clean up, handle dependencies both for internal and external node modules. Now it is time to put the cherry on the top of the cake: let’s add Jasmine tests written in TypeScript!
Step 7: Jasmine tests written in TypeScript
Okay, so let’s test if words in ViewModel class really contains ‘Hello’ and ‘Word’ as expected.
We are going to use Jasmine as a testing framework so let’s download it (and the definition file of course):
npm install --save jasmine-core typings install --save --global dt~jasmine
Before we start writing our test, let’s put ViewModel into another file. Decoupling is always good, but in this case you would also get an error if you imported main.ts into your test: we don’t want knockout to do applyBindings to a view that is not there in the test environment.
main.ts
import * as ko from 'knockout'; import {ViewModel} from './viewmodel.ts'; ko.applyBindings(new ViewModel());
And create “viewmodel.ts” in the typescript folder:
import * as ko from 'knockout'; export class ViewModel { words = ko.observableArray(['Hello', 'World']); }
Create a folder named “test” in the “typescript” folder and create your first test file in there named “test.ts”.
import {ViewModel} from '../viewmodel.ts'; describe('Our awesome test', () => { it('tests something completely non-sense', () => { let expected = ['Hello', 'World']; expect(new ViewModel().words()).toEqual(expected); }); });
So here is our first test, now we just have to make it somehow visible if it works. Since we have dependencies, and we might have many other jasmine test files later, we also have to compile and browserify tests into a testbundle. So let’s make some modification in our “gulpfile.js”!
… //require parts are the same as showed previously const watch = require('gulp-watch'); const jasmineBrowser = require('gulp-jasmine-browser'); function createBrowserifier(entry) { return browserify({ basedir: '.', debug: true, entries: [entry], cache: {}, packageCache: {} }) .plugin(tsify) .plugin(watchify) .plugin(errorify); } function bundle(browserifier, bundleName, destination) { return browserifier .bundle() .pipe(source(bundleName)) .pipe(gulp.dest(destination)); } gulp.task('clean', () => { return del('./javascript/**/*') }); gulp.task('installTypings', () => { return gulp.src('typings.json').pipe(gulpTypings()); }); gulp.task('tsc-browserify-src', () => { return bundle( createBrowserifier('./typescript/main.ts'), 'bundle.js', 'javascript'); }); gulp.task('tsc-browserify-test', () => { return bundle( createBrowserifier('./typescript/test/test.ts'), 'testbundle.js', 'javascript/test'); }); gulp.task('run-jasmine', () => { gulp.src(['', 'javascript/test/testbundle.js']) .pipe(watch('javascript/test/testbundle.js')) .pipe(jasmineBrowser.specRunner()) .pipe(jasmineBrowser.server({ port: 8888 })); }); gulp.task('default', (done) => { runSequence(['clean', 'installTypings'], 'tsc-browserify-src', 'tsc-browserify-test', () => { console.log('Watching...') gulp.watch(['typescript/**/*.ts'], ['tsc-browserify-src', 'tsc-browserify-test']); }); });
Since we’ll use gulp-watch and gulp-jasmine-browser, let’s install those:
npm install --save gulp-watch gulp-jasmine-browser
Now it will generate a “testbundle.js” too in the “javascript/test” folder. If you read the gulpfile carefully you might have noticed that there is a task named “run-jasmine” in there. It is not included in the default gulp task, but we can run it separately:
gulp run-jasmine
Open a browser and check http://localhost:8888, and you will see the jasmine page with your green test!
Note that it only works if you generated the “testbundle.js” file first! The way I am using it now, is that I first run “gulp” in one Console and then in another Console I run “gulp run-jasmine”. If you modify your tests and refresh your browser, it will be up to date.
There! We are having a sufficient enough ecosystem for you to get started with a real TypeScript project!
Coming up next:
But what about the Backend? Can we have One Build on both sides?
In my upcoming posts we will figure out how to integrate all this into Maven, and we will have a look how all this works with a Node.js server.