help icon indicating copy to clipboard operation
help copied to clipboard

node:test with typescript, code coverage and typing for mock

Open MorningLightMountain713 opened this issue 1 year ago • 1 comments

Details

Just FYI, testing works fine when using the following:

node --import tsx  --test test/myfile.ts

Problem 1

When trying to use code coverage with node --import tsx --experimental-test-coverage --test test/myfile.ts

I get the following warning (and no code coverage):

ℹ Warning: Could not report code coverage. TypeError: Cannot read properties of undefined (reading 'line')

What can I do to get code coverage?

Problem 2

Whenever I spy in the ts file, intellisense gives warnings about type missing for mock. Eg:

    t.mock.method(serverFromOtherTsFile, "myMockedMethod");

    assert.strictEqual(serverFromOtherTsFile.myMockedMethod.mock.calls.length, 0);
    await serverFromOtherTsFile.myMockedMethod();
    assert.strictEqual(serverFromOtherTsFile.myMockedMethod.mock.calls.length, 1);

The mock property doesn't exist on type myMockedMethod. How can I type this? For clarity, the tests still run, it's just in VSCode I get the warnings as mock doesn't exist on myMockedMethod.

Thanks for your help

Node.js version

v20.10.0

Example code

No response

Operating system

macOS

Scope

code / runtime

Module and version

Not applicable.

MorningLightMountain713 avatar Jan 12 '24 14:01 MorningLightMountain713

I have ended up doing the following:

assert.strictEqual((serverFromOtherTsFile.myMockedMethod as any).mock.calls.length, 0);

I don't like it, but it lets me run tsc without throwing errors

MorningLightMountain713 avatar Jan 17 '24 12:01 MorningLightMountain713

ℹ Warning: Could not report code coverage. TypeError: Cannot read properties of undefined (reading 'line')

test.ts

import { a } from "./a.ts";

a.ts

// no imports <-- TypeError: Cannot read properties of undefined (reading 'line')
export function a(): string {
  return "a";
}

NikitaIT avatar Apr 05 '24 01:04 NikitaIT

+1 also having this issue. (... as any) does work but... it's not the prettiest solution

liza-unito avatar May 14 '24 20:05 liza-unito

Fixed by https://github.com/nodejs/node/pull/53000

avivkeller avatar May 15 '24 11:05 avivkeller

Keep in mind the coverage won't exactly be useful in the transpiled code, see https://github.com/nodejs/node/issues/52775#issuecomment-2111926554

avivkeller avatar May 15 '24 11:05 avivkeller

Btw, if someone is having the same thing, please first check if the transpiler (if you're using any) provides an inline source map generation for the code, the underlying problem in that case is that the generated transpiled code does not map to anything in the original code, hence there's no way to tell which function is which and the code coverage won't work properly.

Weird thing though, if the code is simple enough, the coverage works, even with transpilers

khaosdoctor avatar May 21 '24 15:05 khaosdoctor

Did anyone figure out a solution to Problem 2 in the original issue? How come this issue was closed without that problem being addressed?

onlywei avatar Jun 25 '24 02:06 onlywei

This issue was closed because the described issue involved an issue with Typescript code, which is not maintained by Node.js. If you can reproduce in purely JS, please open a new issue.

avivkeller avatar Jun 25 '24 02:06 avivkeller

@RedYetiDev I see. I found a good solution, though. I'll post it below:

@liza-unito @MorningLightMountain713 this is the solution I used:

import { beforeEach, describe, it, mock, Mock } from 'node:test';
import { object } from './object';

describe('solution', () => {
  let mockedMethod: Mock<typeof object.myMethod>;

  beforeEach(() => {
    mockedMethod = mock.method(object, 'myMethod');
  });

  it('should not make TypeScript complain', () => {
    assert.strictEqual(mockedMethod.mock.calls.length, 0);
  });
});

onlywei avatar Jun 25 '24 02:06 onlywei

This was resolved in https://github.com/nodejs/node/issues/52775 and implemented on https://github.com/nodejs/node/pull/53315

Turns out it was a code issue in the test runner that wasn't correctly checking for the lines

khaosdoctor avatar Jun 25 '24 08:06 khaosdoctor

If anyone else were to end up here:

const mockedMethod = t.mock.method(serverFromOtherTsFile, "myMockedMethod"); assert.strictEqual(mockedMethod.mock.calls.length, 0);

MartenOlofsson avatar Dec 17 '24 11:12 MartenOlofsson