How do I write TypeScript tests that don't include the classes under test in the transpiled test code? - node.js

I have a TypeScript project that compiles down to a single JS file in /dist.
I have Jasmine tests, also written in TypeScript, that reference the various classes they test with references like:
/// <reference path="../../../src/script/classUnderTest.ts" />
When I compile the tests the TypeScript compiler pulls in all the referenced classes and I get a single JS file containing the test code and the code under test.
This actually works fine for just running the tests, but now I'd like code coverage too. From what I can tell, to get Istanbul to work I need to have the code under test separate from the test code. Also it would be nice to be testing exactly the JS file that will be live.
So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
(Or am I barking up the wrong tree entirely?)
Note, I am building this on a Mac, so from what I've read Chutzpah is not currently an option. I'm also currently using only npm scripts to do builds. I'd prefer to not bring in grunt or gulp unless it's absolutely necessary.

So, how can I get the type safety and autocomplete benefits of "/// reference" whilst using my compiled JS file when the tests are actually run?
Don't using TypeScript's --outFile option (few other reasons). Instead use modules e.g. --module commonsjs and a module loader e.g. webpack.
More
Browser quickstart : https://basarat.gitbooks.io/typescript/content/docs/quick/browser.html
Modules:
https://basarat.gitbooks.io/typescript/content/docs/project/modules.html

Related

Typescript and Node.js

I am learning the typescript also I am learning how to implement typescript in Node.js. Now, I have watched several videos and in those videos I found 2 methods to tie typescript with Node.js.
One is by using decorators and other is by using the generic method type(by defining request and response types - Usage of interfaces.)
The question is -> Which approach is preferable and which to use.(I am aware that there is no good or bad way I but still want to know the answer) In addition to performance, I also want to know which approach is easier for others to understand because in my opinion, both are quite difficult to understand.
Or is there any other and easier way to implement typescript with Node.JS?
There are some tools to help run TS in NodeJS, such as ts-node (https://www.npmjs.com/package/ts-node), but if you don't want to rely on that or, like me, can't figure out how to get it to work, you will want to have TS do what TS does, and transpile it to JS. Then in package.json, you'll want to have your start script reference the initial .js file.
To transpile TypeScript, simply use the command tsc if you have a tsconfig, or tsc [starting file] if you do not. This should compile the code first, and if compilation is successful, it will then transpile to JS in the designated folder.
In your package.json, ensure the command executed refers to the output folder's initial file. For example: "start": "node dist/app"

Why don't for..of loops over Iterables work when run within Jest?

I have the following TypeScript code:
const myMap = new Map([["name", 5]]);
for (const foo of myMap.values()) {
console.log(foo);
}
When I run this code in node (v8.12.0) directly, it works and prints out "5" to console.
If I run this exact same code in a Jest test, it never executes the contents of the for loop. It runs the for condition and then just skips past the loop, never actually enumerating the values.
Why is that? Is there something about the JS runtime used by Jest (isn't it node?) that doesn't support for..of over iterables?
Thanks!
After a very long investigation, I have gotten to the bottom of this. Important background information about the solution:
When targeting older ECMAscript versions like ES3 and ES5 with the TypeScript compiler, using for..of loops to iterate over Iterable collections is not supported by default. If you want to use for..of with Iterable, you have to either target something newer than ES5 or use the --downlevelIteration flag.
To use Jest with a TypeScript project, you use ts-jest. At least, I was. I think you can also use babel somehow but I think ts-jest is preferred.
When using ts-jest, by default it tries to use the tsconfig.json file that the project uses -- which, as far as I can tell, means the one that is next to the jest.config.js file you are using (or the current directory if you aren't specifying a jest.config.js file). If it cannot find a tsconfig.json file in the project directory, it uses the default TypeScript compiler options. The default compiler options cause the TypeScript compiler to target ES3 or ES5 (the ts-jest docs claim it defaults to ES3 but that ts-jest overrides the default in this case to be ES5). --downlevelIteration is not on by default.
With all this in mind, I was able to figure out that ts-jest was not able to find my project's tsconfig.json file and so it was running my tests using the default settings, which meant targeting ES5 and not allowing downlevelIteration, so all my for..of loops over Iterable didn't work. The reason it couldn't find my tsconfig.json file is because my jest.config.js file was in a different directory (higher up in the tree) and even though I was running jest from a directory with a tsconfig.json file, ts-jest was not looking in the "current" directory but was instead looking in the directory that I pointed jest at for my jest.config.js file, which did not contain a tsconfig.json.
My solution to this was to rework my directory structure a bit and leverage the tsConfig option of ts-jest to tell it where to find my tsconfig.json file, which made everything "magically" work since my tsconfig.json file targets es2018, which supports for..of iteration over Iterable.
One alternative solution I considered but quickly disregarded was feature of the aforementioned tsConfig setting to directly set the --downlevelIteration compiler option in the jest config. I chose not to do that because, while it would have fixed this specific problem, it would not have fixed the larger problem which is that my Jest tests were compiling my TypeScript with different flags than my production code! It just so happens that only current problem caused by this was my for..of loop misery.
A quick postscript: the way I eventually made headway on this issue is by stumbling across the diagnostics option in ts-jest. Once I set it to true, when I tried to run my tests, an error like this was displayed:
TypeScript diagnostics (customize using [jest-config].globals.ts-jest.diagnostics option): src/foo.ts:163:47 - error TS2569: Type 'Map<Guid, FooInfo>' is not an array type or a string type. Use compiler option '--downlevelIteration' to allow iterating of iterators.
It seems like TS compiler errors should be displayed (and cause test failures) regardless of whether or not ts-jest "diagnostics" are enabled but shrug.

How to set up typescript 0.9.5 in Visual Studio 2012

I'm trying to write a game in Typescript but I am having a hard time setting things up.
I am using visual studio 2012 and I installed typescript 0.9.5.
What I want is to build an app/game like I would in C# or AS3, meaning using putting classes in seperate files and using modules to seperate/connect code. This would then compile to either a single file or some kind of require.js like solution (which I'm also not clear about).
But I have done a lot of research and ran in to a lot of hurdles.
-There are a lot of references to calling something like "tsc greeter.ts" but when I use this in the visual studio command window I get back "Command "tsc" is not valid." I tried adding the tsc folder to environment variables path, but this didn't change anything. So I can't really run it. Also I don't understand how tsc would know where greeter.ts is located.
-I'm confused between the "///" and the import statement. How do these factor in the structuring of an app?
-It seems there are a lot of ways to make a typescript app, which all have different requirements and code style and structure. Is there no standard way, or am I just mistaken and is there a good way to approach this?
So the main question is: How do I build a typescript app/game structured like a c# or AS3 app?
To answer just some of your question, you no longer need the /// reference like this:
/// <reference path="../typings/jquery.d.ts"/> This was used in earlier versions of typescript, however now it will find any typescript files in your project for you.
I don't think there is a 'standard' way to create a typescript project any more than there is C#, there are many design patterns and you will have to research the pros and cons of both and choose one.
You should also no longer need to run "tsc greeter.ts" to compile your code. It will compile on build of the project.

How to suppress typescript errors when compiling a single file by nodejs?

When I use Node.js to compile a single TypeScript file from project, which has dependencies on other files I get multiple "Could not find symbol .." errors. Despite these errors JS file is created correctly. There are no explicit references in TypeScript files.
Is there a way to suppress these errors? Or tell compiler where to look for dependencies, but not recompile all files?
The reason I want to do this is performance. My goal is to use Grunt to watch for TypeScript files. On change it would compile them to JS, do some transformations, minimize, bundle and run unit tests. However, only a single step to compile all 160 typescript files to JS takes around 8 seconds, which is painfully slow for development process. Compiling only single changed file should speed it up.
There isn't an option at the moment. I've been planning on adding it to grunt-ts for /// <reference's https://github.com/basarat/grunt-ts/issues/34 but the same can apply for node.

Visual Studio Error List: Ignore a JavaScript reference

There are probably like three people doing what I'm doing but here goes:
Visual Studio 2012
Latest Web Essentials
TypeScript project
AngularJS framework
Running Chutzpah tests with Jasmine
When creating tests for Chutzpah, I need to add references not only to my typescript files but also to the javascript libraries that I'm using. For example:
// Typescript References (for tsc)
/// <reference path="../ref/angular-1.0.d.ts" />
// JavaScript references (for chutzpah)
/// <reference path="../lib/angular.min.js" />
// TS references for what we're actually testing...
/// <reference path="../src/modules.ts" />
With this setup, my typescript-authored jasmine tests are running great. However, the angular.min.js file is filling up my error list with hundreds of complaints. This makes it impossible to find errors that are reported by the typescript syntax checker.
If I remove the reference to angular.min.js, then Chutzpah cannot run since my code depends on the library.
Is there a way to force Visual Studio to ignore errors in a particular JavaScript file reference?
This issue is now solved in Chutzpah 2.4.
Chutzpah Specific Reference
With the addition of TypeScript support a few releases ago several
people reported issues when using Chutzpah with the TypeScript plugin
in VS. The problem occurs since both TypeScript and Chutzpah are using
the comments for different purposes. To get around
this issue Chutzpah now supports two ways to reference dependent
files.
The existing general way /// <reference path="foo.js" />
The new Chutzpah specific way /// <chutzpah_reference path="foo.js" />
Using the latter will let Chutzpah know about your dependency graph
and should not confuse the TypeScript compiler.
This is a bug with Chutzpah which the developer now appears to be aware of:
http://chutzpah.codeplex.com/discussions/404083#post1008911
The problem you have here is that you are including a .js file as a reference.
You should only be using .ts files as references.
Including the .js file is causing TypeScript to treat is as a typescript file, hence the errors.
Have a look on DefinetelyTyped and switch the angular.min.js to the Angular.d.ts file to allow for your TypeScript compilation to pass.
I had the same problem with jasmine tests needing /// comments in order to run. In my case they were needed because I'm using Resharper and want to be able to take advantage of their javascript test runner.
The solution (although, not ideal) is based on the discussion at http://typescript.codeplex.com/workitem/466. As of v9.1.1 typescript, the compiler ignores references that include a space after the '='. So, instead of using
/// <reference path="~/somefile.js"/>
You use this instead:
/// <reference path= "~/somefile.js"/>
Beware: this may break in future versions of Typescript, but, hopefully by then, the language will support a way to include references for javascript files that are ignored by the compiler.

Resources