nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.44k stars 276 forks source link

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

Closed MorningLightMountain713 closed 1 month ago

MorningLightMountain713 commented 5 months ago

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 commented 5 months ago

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

NikitaIT commented 3 months ago
ℹ 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";
}
liza-unito commented 1 month ago

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

RedYetiDev commented 1 month ago

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

RedYetiDev commented 1 month ago

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

khaosdoctor commented 1 month ago

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

onlywei commented 1 week ago

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

RedYetiDev commented 1 week ago

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.

onlywei commented 1 week ago

@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);
  });
});
khaosdoctor commented 1 week ago

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