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

Testing with TypeScript and TS-Jest #519

Open
lamuertepeluda opened this issue Mar 2, 2023 · 2 comments
Open

Testing with TypeScript and TS-Jest #519

lamuertepeluda opened this issue Mar 2, 2023 · 2 comments
Labels
bug Something isn't working P2

Comments

@lamuertepeluda
Copy link

Hi there,

I was following the TypeScript and Testing guides but I had to work a lot in order to get the tests run with ts-jest.

Setup

This is my setup:

index.ts defines the handler

import { Request, Response, http } from "@google-cloud/functions-framework";

// Register an HTTP function with the Functions Framework

export async function helloHTTPFunction(req: Request, res: Response) {
  // Your code here

  // Send an HTTP response
  res.send("OK");
}

http("helloHTTPFunction", helloHTTPFunction);

index.test.ts defines the handler's test

import {
  HttpFunction,
  Request,
  Response,
} from "@google-cloud/functions-framework";
// @ts-ignore
import { getFunction } from "@google-cloud/functions-framework/testing";

describe("HelloTests", () => {
  beforeAll(async () => {
    // load the module that defines HelloTests
    await import("./index");
  });

  it("is testable", () => {
    // get the function using the name it was registered with
    const helloHTTPFunction = getFunction(
      "helloHTTPFunction"
    ) as HttpFunction;

    // a Request stub with a simple JSON payload
    const req = {
      body: { foo: "bar" },
    } as Request;
    // a Response stub that captures the sent response
    const res = {
      send: (result) => {
        // assert the response matches the expected value
        expect(result).toBe("OK");
      },
    } as Response;

    // invoke the function
    helloHTTPFunction(req, res);
  });
});

jest.config.ts ts-jest config file

import type { JestConfigWithTsJest } from "ts-jest";

const config: JestConfigWithTsJest = {
  preset: "ts-jest",
  slowTestThreshold: 5000,
  testEnvironment: "node",
  silent: true,
  modulePathIgnorePatterns: ["<rootDir>/dist/", "/node_modules/"],
  testPathIgnorePatterns: [
    "<rootDir>/src/fixtures/",
    "<rootDir>/dist/",
    "/node_modules/",
  ],
  coveragePathIgnorePatterns: [
    "<rootDir>/src/fixtures/",
    "<rootDir>/dist/",
    "/node_modules/",
  ],
};

export default config;

tsconfig.json defines TS settings

{
  "compilerOptions": {
    "target": "ES2020",
     "module": "CommonJS",
     "moduleResolution": "nodenext",
     "outDir": "dist",
     "esModuleInterop": true,
     "strict": true,
     "skipLibCheck": true 
  }
}

Environment

Node 18.12.1
TypeScript 4.9.5
jest 29.4.3
ts-jest 29.0.5
@google-cloud/functions-framework 3.1.3

OS: macOS Ventura on M1 Pro processor

Error

I get this error when I try to import the testing submodule without the // @ts-ignore in the test file

image

I think it's related to this TypeScript issue and the way the package.json is declared in @google-cloud/functions-framework module.

The test will also fail if not using the --experimental-vm-modules whith jest, but that's because of the await import("./index") statement in the hook.

So you need to add this to the package.json scripts

"test": "NODE_OPTIONS=--experimental-vm-modules jest"

and then launch npm test.

Workaround

Adding the // @ts-ignore does the trick. However, if I am not messing up with the TS settings too much, wouldn't it be nice to have a more TS-friendly testing module package declaration?

And if you think (and I might agree with you) that this issue is more a TS problem than your library's, then could you please extend the documentation by adding a "testing with typescript" section in the docs (feel free to add my workaround if deemed good enough)?

@cblodgett-sauce
Copy link

Goes without saying this is weird because the method exist if you import this way
import functionsFramework from '@google-cloud/functions-framework/build/src/testing';

But does not function properly after being ran actively, needs to be reverted and ignored to be useful. I'm sure I'm missing a setting somewhere, but this is ridiculous in the year 2023.

@Livshitz
Copy link

Something is wrong in the way the types are exported.
As a workaround you should be able to use this instead:
const {getFunction} = require('@google-cloud/functions-framework/testing');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working P2
Projects
None yet
Development

No branches or pull requests

5 participants