Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support to Run TypeScript test file(.ts) directly without Precompiling(tsc) #1109

Closed
huan opened this issue Nov 15, 2016 · 75 comments
Closed
Assignees
Labels
💵 Funded on Issuehunt This issue has been funded on Issuehunt enhancement new functionality help wanted scope:typescript

Comments

@huan
Copy link

huan commented Nov 15, 2016

Issuehunt badges

Description

AVA now support ES6 by using Babel, run directly without any precompiling, this is very convenience. But for TypeScript, AVA has to precompile ts files by run tsc.

I use TypeScript in my project wechaty, run TS code directly by ts-node like this: ts-node demo.ts. This is a convenience way for developing.

If we can run TypeScript file directly by AVA, just like ava test.ts, that will be wonderful.

About this topic, there has already an issue #631 on it. I saw @sindresorhus agree that use TypeScript without precompiling is a better way.

@niieani You can already use TypeScript by precompiling it. I know it's not optimal, but it's not like anyone has done a pull request fixing this. #631 (comment)

I love AVA, because I'm a TAP fan, and AVA is based on TAP. So I tried to hack AVA to support TypeScript directly. After some study & work, I finished it finally, and in the past month, I was using it in my own project and it worked as my expected.

I'll share my idea here, and send a Pull Request later. Hope we can support TypeScript without precompiling soon.

ava-typescript

About the Hack

I added a --ext ts argument parameter to CLI, then pass ext to AVA API. If ext is ts then I use TypeScript Compiler to replace the Babel Compiler, because TypeScript is the superset of ES6/7.

  1. Add CLI Arg: --ext/-e

    In order to support TypeScript without precompiling, first, we need to add a CLI args to support that. I use the name --ext and the alias -e for this, like ava -e ts. Set the ext automatically is considered, but I think maybe it should be done later. If set ext automatically, then we can just run TS tests by ava test.ts

  2. Get Test Files from ava-files

    AVA use a submodule ava-files to get all test files list. It had to be modified to support the ext parameter. I use exts in the ava-files module and it is an Array type, that's for the future support of multiple file extensions.

  3. new API options: ext

    in API call, we get file extension name from options.ext, pass it to AvaFiles/CachingPrecompiler/Watcher.

  4. Add a Switcher between Babel with TypeScript

    AVA compile ES6 by Babel in CachingPrecompiler, so we could compile TypeScript here. If the file extension is set to ts, then CachingPrecompiler will use a new module extTs to compile the source.

  5. Introduce a new Module: extTs(lib/ext/ts.js)

    For ts file extension, the compiler module ext/ts.js will be loaded. In the furture, other extension could modulize their own compile code in different file in ext/ directory. i.e. ext/jsx.js for a new extJsx compiling module.

  6. Enable Run TypeScript in test-worker.js

    AVA use subprocess to run tests, the worker needs to register to TypeScript compiler.

  7. Add TypeScript dependence to package.json

  8. Make XO happy

Test Source

test.ts:

import { test } from 'ava'

test('AVA run TypeScript without tsc', t => {
  let i: number = 42
  t.is(i, <number>42, 'meaning of life')
})

Run:

$ ava --ext ts test.ts

  ✔ AVA run TypeScript without tsc

  1 test passed [02:55:58]

Yeah~

Relevant Links

There is a $142.00 open bounty on this issue. Add more on Issuehunt.

@huan
Copy link
Author

huan commented Nov 16, 2016

Hi,

Is there any feedback or suggestion?

I want to know:

  1. is the parameter name all right? now they are:
    1. --ext / -e for AVA CLI
    2. exts a new key for AvaFile options
  2. how about to set --ext automatically? if we run ava test.ts then let ava know .ts should support typescript.

looking forward to getting feedback, then I can make the Pull Request fit better.

@sindresorhus
Copy link
Member

Thanks for picking this up @zixia :)

Your proposal looks pretty good.

Some random feedback:

  • It should be possible to set --ext multiple times.
  • .js files should always be included.
  • TypeScript should not be a dependency of AVA, but rather in the user's package.json. If it's not, we should throw a friendly error message. We bundle Babel because we depend on it in AVA for other things too.
  • Setting extension automatically works fine when you specify exact files, but most users specify globs, so not sure whether it's worth the inconsistency of only working in some cases.
  • I think --extension/-e CLI flag and extensions option name would be better.
  • Make sure you handle caching correctly.

@huan
Copy link
Author

huan commented Nov 21, 2016

Got it.

I'll follow your great feedback then make the PR later. :)

  • It should be possible to set --ext multiple times.
  • .js files should always be included.
  • TypeScript should not be a dependency of AVA, but rather in the user's package.json. We bundle Babel because we depend on it in AVA for other things too.
  • If it's not, we should throw a friendly error message.
  • Setting extension automatically works fine when you specify exact files, but most users specify globs, so not sure whether it's worth the inconsistency of only working in some cases.
  • I think --extension/-e CLI flag and extensions option name would be better.
  • Make sure you handle caching correctly.

@huan
Copy link
Author

huan commented Nov 21, 2016

Hi @sindresorhus ,

I had followed all your feedbacks and made two PRs: one is for AvaFiles, the other is for AVA.

Please notice that CI for AVA will be expected to report failure because the ava-files NPM modules do not support extensions parameter now.

All unit tests had passed in my dev box with the PR code.

Please let me know if I missed anything in PR, thanks.

@jednano
Copy link
Contributor

jednano commented Nov 23, 2016

@zixia this is awesome work and I'm excited to use it, but can you tell me if it works fine with the --watch flag too? Or is there more work to do for that?

@huan
Copy link
Author

huan commented Nov 24, 2016

@jedmao Hi buddy thanks you for like my work, and I'm sure you are a TypeScript fan like me.

In theory, I think it should work with the --watch flag, because I modified all the parts in AVA to support ts, including Watcher class and all the Watcher unit tests. But I did not test it yet, and there's possible I missed part of it. So if you find any problem with that, please let me know, and I'll get it worked.

If you want to try it before @sindresorhus merge this PR, you can pull my clone at https://github.com/zixia/ava (branch: typescript) , and also don't forget to link ava-files too: https://github.com/zixia/ava-files

@patrick91
Copy link

Is there any update on this? I'm starting a new TS project and I really would like to use ava without compiling TS scripts first!

@zixia amazing work so far!

@huan
Copy link
Author

huan commented Feb 12, 2017

@patrick91 Thanks!

AVA decide to re-design the total code structure of how to use Babel, which delayed the TypeScript support progress.

See: #1159

@bitjson
Copy link
Contributor

bitjson commented Feb 13, 2017

@patrick91 (and anyone else coming across this thread) – I've been getting into Typescript a lot recently, and had some trouble getting a lot of the packages I wanted to use working together.

I spent a little time starter project which I think it might accomplish what you're looking for: es7-typescript-starter

  • Write your library and AVA tests in Typescript
  • everything uses tsconfig.json properly (so tooling/build/test settings match)
  • source-mapped code coverage, typedoc API doc generation, etc.
  • type definitions are linked properly for projects depending on yours
  • and there are a few examples of how to use both the main (commonjs) and module (es6 module) output formats

I'd love input/feedback on how it could be improved, especially when AVA restarts work on this issue.

@lukescott
Copy link

@novemberborn I know I can do tsc && ava, but that won't work with --watch, will it? Is there a solution to make it work with watch?

@tomdavidson
Copy link

@lukescott you can add "compileOnSave": true to your tsconfig.json if you use an editor that recognizes it. You can also change your watch/dev run script to be something like tsc -w & ava --watch so tsc will watch in the background while you run ava watch.

I think ava is super interesting but I have not replaced mocha over the typescript issue so the suggestion is not in use for me.

@lukescott
Copy link

Ah, got it. So I need need to run them separately. Tsc will watch and save files, which Ava will pick those up. It's too bad there isn't a way to do a single watcher and have it all happen in memory.

@jednano
Copy link
Contributor

jednano commented May 27, 2017

Yep, I've been waiting for the same feature.

@novemberborn
Copy link
Member

The plan is here, but there hasn't been progress on that lately: https://github.com/avajs/ava/blob/master/docs/specs/001%20-%20Improving%20language%20support.md

@unional
Copy link

unional commented Jun 21, 2017

@lukescott for watch, you can do this:
https://github.com/unional/color-map/blob/master/scripts/watch.js

'use strict';

const cp = require('child_process');

let ava;
cp.spawn('tsc', ['-w'], { shell: true })
  .stdout.on('data', (data) => {
    if (!ava) {
      ava = cp.spawn('ava', ['-w'], {
        stdio: 'inherit',
        shell: true
      })
    }
    const text = data.toString()
    process.stdout.write(text)
    if (/.*Compilation complete/.test(text)) {
      let lint = cp.spawnSync('npm', ['run', 'lint'], {
        stdio: 'inherit',
        shell: true
      })
      if (lint.status === 0) {
        cp.spawnSync('npm', ['run', 'build-commonjs'])
      }
    }
  })

@sebinsua
Copy link

The plan is here, but there hasn't been progress on that lately: https://github.com/avajs/ava/blob/master/docs/specs/001%20-%20Improving%20language%20support.md

Has there been any work on this since then?

@patrick91
Copy link

babel has recently merged a PR that allows to parse typescript, so maybe soon enough we will be able to use ava for typescript via babel :)

babel/babylon#523 (comment)

@huan
Copy link
Author

huan commented Jun 30, 2017

Looking forward it, or I have to consider other solutions like tap which had already supported the TypeScript(tapjs/tapjs#313) and Concurrency.

@ORESoftware
Copy link

@novemberborn
Copy link
Member

If we can run TypeScript through Babel then yea we can land some sort of support for that. Though you'd still need the equivalent to babel-register to load TypeScript source files.

@lukescott
Copy link

With TypeScript support in babel, wouldn't babel-register (or what ever Ava uses) work? I would imagine babel adding the .ts extension w/ native support.

@adieuadieu
Copy link

I came to this thread/issue while trying to use Ava's --watch feature with TypeScript. @tomdavidson's suggestion of tsc --watch & ava --watch works well enough as an intermediate solution for anyone who wants to watch their TypeScript code for changes and rerun those tests.

@bitjson
Copy link
Contributor

bitjson commented Jul 5, 2017

If anyone is interested, the solution @adieuadieu mentioned (from @tomdavidson) is what typescript-starter uses right now.

@novemberborn
Copy link
Member

I'm closing this issue since it's not directly actionable.

Our plan for making AVA precompiler-agnostic can be found here: https://github.com/avajs/ava/blob/master/docs/specs/001%20-%20Improving%20language%20support.md — we'll need help achieving that.

Further, we'd be willing to support TypeScript test files sooner if we can run them through our existing Babel infrastructure.

@btkostner
Copy link
Contributor

It's worth mentioning that AVA 1.0 is now out 🎊. You can use typescript with this recipe. I've been using it in production for a while now, and it works great. This issue can be closed.

@SleeplessByte
Copy link
Contributor

@btkostner ts-node is not a drop-in replacement for tsc, even though many people think so. Running ts-node/register will give most people a similar experience, but each time there is a typescript release, ts-node potentially has compile errors again.

IMO ava should be able to run this itself.

@screendriver
Copy link
Contributor

The latest Jest 24 release supports TypeScript via @babel/preset-typescript

@issuehunt-oss issuehunt-oss bot added the 💵 Funded on Issuehunt This issue has been funded on Issuehunt label May 9, 2019
@IssueHuntBot
Copy link

@0maxxam0 has funded $2.00 to this issue.


@IssueHuntBot
Copy link

@IssueHunt has funded $140.00 to this issue.


@schmod
Copy link

schmod commented Jun 26, 2019

Should we close this and make a new issue that better summarizes the current state of affairs?


Right now, the included recipe does a pretty-okay job of providing TypeScript support via ts-node.

Current downsides are:
-- Cannot be used with compileEnhancements
-- Extra overhead for compiling tests & any dependencies for each test file. (This ends up being a huge performance hit if you need to run ava with --serial -- in my test suite, this adds about ~4sec to each test file, completely destroying any performance benefits that Ava might have over Mocha)


As an alternative to ts-node (even if we address the above drawbacks) , it seems like there's a good opportunity to also allow users to use @babel/preset-typescript instead. This preset has quickly gained a ton of popularity in frontend projects, and is small enough that Ava could provide it as an "out of the box" solution that builds on Ava's existing Babel support.

@sindresorhus
Copy link
Member

@schmod ts-node works, but it's not perfect and it requires various boilerplate config. @novemberborn and I would ideally prefer as close to zero config TypeScript support as possible. Our goal has always been for AVA to just work in the common cases, and TypeScript can be considered common these days. We also have extra incentive to push this as we both have started to use TypeScript ourselves.

Last time I chatted privately with @novemberborn about this, we discussed adding a config property like typescript: true, ava.babel.typescript: true, typescript.usingBabel: true, and eventually integrating the TypeScript compiler itself.

@schmod
Copy link

schmod commented Jul 1, 2019

@sindresorhus – I'd certainly be happy with any of those options!

@cdaringe
Copy link
Contributor

cdaringe commented Jul 2, 2019

ya, last i tried, a good debug experience still essentially requires that boilerplate (e.g. disabling compile enhancements) otherwise sourceMaps get real weird. i'm not sure i've tried w/ babel7 yet though, to be fair. disabling compile enhancements + ts-node still allow me to use breakpoints naturally in my editor and use the launch config recipes 👨‍🍳 without a headache.

@shellscape
Copy link

ts-node is a dumpster fire for anything beyond a very simple setup. Harsh, but fair.

I'd like to get the Rollup org on Ava across the board, but TypeScript support is a major blocker. What's the chance that this is still something that's getting consideration?

@mightyiam
Copy link
Contributor

Just a question here. What's so wrong with pre-compiling? Why does a testing framework need to be concerned with TypeScript beyond providing types? Wouldn't it introduce more complexity into ava?

@kirillgroshkov
Copy link

Well, that was (partially) a secret of Jest's success. Would happily consider Ava if it has built-in TS support.

If testing framework supports it - it automatically unlocks 1-click to run test in IDEs (e.g Jetbrains) which is a big DX win

@mightyiam
Copy link
Contributor

What about separation of concerns? Isn't that a DX win in the long term?

@novemberborn
Copy link
Member

My current thinking (once the extraction of Babel matures) is to support a TypeScript integration which knows how to load the pre-compiled files. So you specify src/test.ts and it loads build/test.js.

I'm less convinced of the need to compile the entire project.

What do folks think?

@shellscape
Copy link

shellscape commented Nov 19, 2019

Just a question here. What's so wrong with pre-compiling? Why does a testing framework need to be concerned with TypeScript beyond providing types? Wouldn't it introduce more complexity into ava?

Simply put: it's yet more friction for the adoption of Ava by TypeScript developers, where it doesn't exist elsewhere in other tools. As was mentioned by @kirillgroshkov, Jest has for a long time supported worriless, (relatively) frictionless TypeScript support. Yes, it would introduce more complexity. Supporting a larger user base tends to do that.

Well, that was (partially) a secret of Jest's success. Would happily consider Ava if it has built-in TS support.

Agreed.

What about separation of concerns? Isn't that a DX win in the long term?

I would argue that DX is made worse. Separation of concerns works very well in many aspects of our trade, but this is not one.

What do folks think? @novemberborn

Jest has really set the gold standard here. If there's different path from what Jest has done as a means to accomplish frictionless support of TypeScript, I'm all for it. But increased friction is a very hard sell for any team/org. I'd argue Ava is better than Jest in a myriad of ways, but forcing additional build steps is not appealing to folks. Config is generally fine, as even Jest requires being told about how it needs to hand TS (https://github.com/rollup/rollup-pluginutils/blob/master/jest.config.js)

once the extraction of Babel matures

Is there a timeline on this? If this is an unknown quantity, that's going to make for another point on a hard sell.

@SleeplessByte
Copy link
Contributor

as even Jest requires being told about how it needs to hand TS

I think that's outdated. If one is using babel with jest, everything is automagic, if babel is set-up correctly. Only when using ts-jest, you need to add the three lines (or the single `preset: 'ts-jest') iirc.

What I want to say with that is, yes, setup is fine (in terms of friction), and it can be as easy as flipping a switch, as suggested above.

@cdaringe
Copy link
Contributor

cdaringe commented Nov 19, 2019

@novemberborn, I really love that idea as a stop gap--it would make most of my projects just work, even if i had to turn off Babel and compile enhancements still. However, it does however have holes. First, many people compile to a different output dir, so a sibling is file isn't always an option. next, noEmit compiler flag is used often in projects--especially projects with some ui (which Ava generally doesn't support atm). I think the "detect ts file > Babel with ts plugin > run" pipeline will probably be most fruitful, so long as source maps work. Now that were on Babel 7, I'm actually unclear on what the barriers to this are beyond file type detection 🤔

@novemberborn
Copy link
Member

Regarding extracting Babel: the goal is for AVA to work with just Node.js, without any compilation. But, you'll be able to install @ava/babel and enable it in AVA's configuration. That package would take care of compiling test & helpers (for AVA 2.0 compatibility) and can then be improved to take on source compilation as well.

As alluded to by others, you could use Babel to strip TypeScript.

But I'd love to also have a separate @ava/typescript package that can be integrated in the same way. One mode of operation would be to load test files from a TS output directory, but like with @ava/babel it could take on TypeScript compilation as well.

I'm hoping to have a decent chunk of time to work on the Babel stuff, and other changes for an AVA 3 release as work breaks up for the holidays.

@SephReed
Copy link
Contributor

SephReed commented Jan 5, 2020

Does this work with TS or not?

@mightyiam
Copy link
Contributor

@novemberborn
Copy link
Member

Babel compilation has now been moved into a separate package, which means we can now do the same for TypeScript. See references to https://github.com/avajs/ava/blob/master/lib/babel-manager.js and beyond for ideas on how this might work.

Ultimately this should be hosted at https://github.com/avajs/typescript so if you're keen to work on this give me a shout and I can get all that set up.

@novemberborn
Copy link
Member

Rudimentary support is now in progress at avajs/typescript#1. See also #2379.

Example usage at novemberborn/got#1.

This will go out in AVA 3.1; beyond that I'll create some issues in the https://github.com/avajs/typescript repository for where we can take this next.

@novemberborn
Copy link
Member

AVA 3.1 is now available: https://github.com/avajs/ava/releases/tag/v3.1.0

I've opened some issues to track enhancements here: https://github.com/avajs/typescript/issues

Thank you all for your interest!

@paulshryock
Copy link

Is there a TypeScript / ESM / Ava boilerplate repo? I'm having trouble getting it set up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💵 Funded on Issuehunt This issue has been funded on Issuehunt enhancement new functionality help wanted scope:typescript
Projects
None yet
Development

No branches or pull requests