Ts-jest: Test global modules

Created on 27 Sep 2018  路  12Comments  路  Source: kulshekhar/ts-jest

Issue :

I'm trying to test some Typescript modules that are basically global modules, they don't have any imports or exports, i.e something like this:

// module foo.ts
function foobar(): string {
    return 'Hello world!';
}

I use the include property in the tsconfig.json file to include these files in the project, and Typescript will compile them so that the functions end up the global scope.

However, in Jest I don't seem to be able to use / import these methods / variables and can't test them.

Expected behavior :

I want to be able to unit test these global modules.

Debug log:


log file content

# content of ts-jest.log :
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"23.10.2"},"message":"creating Importer singleton","sequence":1,"time":"2018-09-27T15:13:06.110Z"}
{"context":{"allowJs":false,"logLevel":20,"namespace":"jest-preset","package":"ts-jest","version":"23.10.2"},"message":"creating jest presets not handling JavaScript files","sequence":2,"time":"2018-09-27T15:13:06.116Z"}
{"context":{"actualVersion":"23.6.0","expectedVersion":">=22 <24","logLevel":20,"namespace":"versions","package":"ts-jest","version":"23.10.2"},"message":"checking version of jest: OK","sequence":3,"time":"2018-09-27T15:13:06.119Z"}
{"context":{"baseOptions":{},"logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"23.10.2"},"message":"created new transformer","sequence":4,"time":"2018-09-27T15:13:06.119Z"}
{"context":{"fileName":"C:\\Users\\dealloc\\Desktop\\atavistic\\src\\foo.spec.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"instrument":false,"rootDir":"C:\\Users\\dealloc\\Desktop\\atavistic"},"transformerId":1,"version":"23.10.2"},"message":"computing cache key for C:\\Users\\dealloc\\Desktop\\atavistic\\src\\foo.spec.ts","sequence":5,"time":"2018-09-27T15:13:06.120Z"}
{"context":{"logLevel":30,"namespace":"jest-transformer","package":"ts-jest","transformerId":1,"version":"23.10.2"},"message":"no matching config-set found, creating a new one","sequence":6,"time":"2018-09-27T15:13:06.120Z"}
{"context":{"config":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"C:\\Users\\dealloc\\AppData\\Local\\Temp\\jest","clearMocks":false,"coveragePathIgnorePatterns":["\\\\node_modules\\\\"],"cwd":"C:\\Users\\dealloc\\Desktop\\atavistic","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"filter":null,"forceCoverageMatch":[],"globals":{"window":{}},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":["node_modules"],"moduleFileExtensions":["ts","tsx","js","jsx","json","node"],"moduleNameMapper":{},"modulePathIgnorePatterns":[],"name":"e483f13e7f20d4de2bc75002922b4968","prettierPath":"C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\prettier\\index.js","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"C:\\Users\\dealloc\\Desktop\\atavistic","roots":["C:\\Users\\dealloc\\Desktop\\atavistic\\src"],"runner":"jest-runner","setupFiles":[],"setupTestFrameworkScriptFile":"C:\\Users\\dealloc\\AppData\\Local\\JetBrains\\Toolbox\\apps\\PhpStorm\\ch-0\\182.4323.68\\plugins\\JavaScriptLanguage\\helpers\\jest-intellij\\lib\\jest-intellij-jasmine.js","skipFilter":false,"snapshotSerializers":[],"testEnvironment":"jest-environment-jsdom","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":["\\\\node_modules\\\\"],"testRegex":"(\\\\__tests__\\\\.*|(\\.|\\\\)(test|spec))\\.(tsx?|js)$","testRunner":"C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\jest-jasmine2\\build\\index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\ts-jest\\dist\\index.js"]],"transformIgnorePatterns":["\\\\node_modules\\\\","^C:\\\\Users\\\\dealloc\\\\AppData\\\\Local\\\\JetBrains\\\\Toolbox\\\\apps\\\\PhpStorm\\\\ch-0\\\\182\\.4323\\.68\\\\plugins\\\\JavaScriptLanguage\\\\helpers"],"unmockedModulePathPatterns":["^C:\\\\Users\\\\dealloc\\\\AppData\\\\Local\\\\JetBrains\\\\Toolbox\\\\apps\\\\PhpStorm\\\\ch-0\\\\182\\.4323\\.68\\\\plugins\\\\JavaScriptLanguage\\\\helpers"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"backports","package":"ts-jest","transformerId":1,"version":"23.10.2"},"message":"backporting config","sequence":7,"time":"2018-09-27T15:13:06.121Z"}
{"context":{"jestConfig":{"automock":false,"browser":false,"cache":true,"cacheDirectory":"C:\\Users\\dealloc\\AppData\\Local\\Temp\\jest","clearMocks":false,"coveragePathIgnorePatterns":["\\\\node_modules\\\\"],"cwd":"C:\\Users\\dealloc\\Desktop\\atavistic","detectLeaks":false,"detectOpenHandles":false,"errorOnDeprecated":false,"filter":null,"forceCoverageMatch":[],"globals":{"ts-jest":{},"window":{}},"haste":{"providesModuleNodeModules":[]},"moduleDirectories":["node_modules"],"moduleFileExtensions":["ts","tsx","js","jsx","json","node"],"moduleNameMapper":{},"modulePathIgnorePatterns":[],"name":"e483f13e7f20d4de2bc75002922b4968","prettierPath":"C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\prettier\\index.js","resetMocks":false,"resetModules":false,"resolver":null,"restoreMocks":false,"rootDir":"C:\\Users\\dealloc\\Desktop\\atavistic","roots":["C:\\Users\\dealloc\\Desktop\\atavistic\\src"],"runner":"jest-runner","setupFiles":[],"setupTestFrameworkScriptFile":"C:\\Users\\dealloc\\AppData\\Local\\JetBrains\\Toolbox\\apps\\PhpStorm\\ch-0\\182.4323.68\\plugins\\JavaScriptLanguage\\helpers\\jest-intellij\\lib\\jest-intellij-jasmine.js","skipFilter":false,"snapshotSerializers":[],"testEnvironment":"jest-environment-jsdom","testEnvironmentOptions":{},"testLocationInResults":false,"testMatch":[],"testPathIgnorePatterns":["\\\\node_modules\\\\"],"testRegex":"(\\\\__tests__\\\\.*|(\\.|\\\\)(test|spec))\\.(tsx?|js)$","testRunner":"C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\jest-jasmine2\\build\\index.js","testURL":"http://localhost","timers":"real","transform":[["^.+\\.tsx?$","C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\ts-jest\\dist\\index.js"]],"transformIgnorePatterns":["\\\\node_modules\\\\","^C:\\\\Users\\\\dealloc\\\\AppData\\\\Local\\\\JetBrains\\\\Toolbox\\\\apps\\\\PhpStorm\\\\ch-0\\\\182\\.4323\\.68\\\\plugins\\\\JavaScriptLanguage\\\\helpers"],"unmockedModulePathPatterns":["^C:\\\\Users\\\\dealloc\\\\AppData\\\\Local\\\\JetBrains\\\\Toolbox\\\\apps\\\\PhpStorm\\\\ch-0\\\\182\\.4323\\.68\\\\plugins\\\\JavaScriptLanguage\\\\helpers"],"watchPathIgnorePatterns":[]},"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"23.10.2"},"message":"normalized jest config","sequence":8,"time":"2018-09-27T15:13:06.121Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsJestConfig":{"compiler":"typescript","diagnostics":{"ignoreCodes":[6059,18002,18003],"pretty":true,"throws":true},"isolatedModules":false,"transformers":[],"tsConfig":{"kind":"file"}},"version":"23.10.2"},"message":"normalized ts-jest config","sequence":9,"time":"2018-09-27T15:13:06.121Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"version":"23.10.2"},"message":"babel is disabled","sequence":10,"time":"2018-09-27T15:13:06.122Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","requireResult":{"exists":true,"given":"typescript","path":"C:\\Users\\dealloc\\Desktop\\atavistic\\node_modules\\typescript\\lib\\typescript.js"},"version":"23.10.2"},"message":"loaded module typescript","sequence":11,"time":"2018-09-27T15:13:06.293Z"}
{"context":{"logLevel":20,"namespace":"Importer","package":"ts-jest","version":"23.10.2"},"message":"patching typescript","sequence":12,"time":"2018-09-27T15:13:06.293Z"}
{"context":{"actualVersion":"3.0.3","expectedVersion":">=2.7 <4","logLevel":20,"namespace":"versions","package":"ts-jest","version":"23.10.2"},"message":"checking version of typescript: OK","sequence":13,"time":"2018-09-27T15:13:06.294Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsConfigFileName":"C:/Users/dealloc/Desktop/atavistic/tsconfig.json","version":"23.10.2"},"message":"readTsConfig(): reading C:/Users/dealloc/Desktop/atavistic/tsconfig.json","sequence":14,"time":"2018-09-27T15:13:06.294Z"}
{"context":{"logLevel":20,"namespace":"config","package":"ts-jest","transformerId":1,"tsconfig":{"input":{"compilerOptions":{"allowSyntheticDefaultImports":true,"alwaysStrict":true,"composite":true,"declaration":true,"emitDecoratorMetadata":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":false,"module":"amd","noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outFile":"./dist/garbage.js","sourceMap":true,"strict":true,"strictFunctionTypes":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":"es3"},"exclude":["node_modules","**/*.spec.ts","**/*.spec.tsx","**/*.test.ts","**/*.test.tsx"],"include":["./src/loader/**/*","./src/**/*"]},"resolved":{"compileOnSave":false,"configFileSpecs":{"excludeSpecs":["node_modules","**/*.spec.ts","**/*.spec.tsx","**/*.test.ts","**/*.test.tsx"],"includeSpecs":["./src/loader/**/*","./src/**/*"],"validatedExcludeSpecs":["node_modules","**/*.spec.ts","**/*.spec.tsx","**/*.test.ts","**/*.test.tsx"],"validatedIncludeSpecs":["./src/loader/**/*","./src/**/*"],"wildcardDirectories":{"c:/users/dealloc/desktop/atavistic/src":1}},"errors":[],"fileNames":["C:/Users/dealloc/Desktop/atavistic/src/loader/define.ts","C:/Users/dealloc/Desktop/atavistic/src/loader/module.ts","C:/Users/dealloc/Desktop/atavistic/src/loader/require.ts","C:/Users/dealloc/Desktop/atavistic/src/foo.ts"],"options":{"allowSyntheticDefaultImports":true,"alwaysStrict":true,"configFilePath":"C:/Users/dealloc/Desktop/atavistic/tsconfig.json","declaration":false,"emitDecoratorMetadata":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":false,"inlineSourceMap":false,"inlineSources":true,"module":1,"noEmit":false,"noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"$$ts-jest$$","removeComments":false,"sourceMap":true,"strict":true,"strictFunctionTypes":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":0},"raw":{"compileOnSave":false,"compilerOptions":{"allowSyntheticDefaultImports":true,"alwaysStrict":true,"composite":true,"declaration":true,"emitDecoratorMetadata":true,"esModuleInterop":true,"experimentalDecorators":true,"importHelpers":false,"module":"amd","noFallthroughCasesInSwitch":true,"noImplicitAny":true,"noImplicitReturns":true,"noImplicitThis":true,"noUnusedLocals":true,"noUnusedParameters":true,"outFile":"./dist/garbage.js","sourceMap":true,"strict":true,"strictFunctionTypes":true,"strictNullChecks":true,"strictPropertyInitialization":true,"target":"es3"},"exclude":["node_modules","**/*.spec.ts","**/*.spec.tsx","**/*.test.ts","**/*.test.tsx"],"include":["./src/loader/**/*","./src/**/*"]},"typeAcquisition":{"enable":false,"exclude":[],"include":[]},"wildcardDirectories":{"c:/users/dealloc/desktop/atavistic/src":1}}},"version":"23.10.2"},"message":"normalized typescript config","sequence":15,"time":"2018-09-27T15:13:06.306Z"}
{"context":{"fileName":"C:\\Users\\dealloc\\Desktop\\atavistic\\src\\foo.ts","logLevel":20,"namespace":"jest-transformer","package":"ts-jest","transformOptions":{"instrument":false,"rootDir":"C:\\Users\\dealloc\\Desktop\\atavistic"},"transformerId":1,"version":"23.10.2"},"message":"computing cache key for C:\\Users\\dealloc\\Desktop\\atavistic\\src\\foo.ts","sequence":16,"time":"2018-09-27T15:13:06.312Z"}

Minimal repo :

All 12 comments

@dealloc can you provide the link to a minimal repository please.

@huafu Sorry, I was writing this issue during a meeting, I'll update ASAP with a minimal reproduction

@huafu I think this more or less demonstrates what I try to achieve

https://github.com/dealloc/ts-jest-issue-770

@dealloc I'll look around, but I think you must export function xyz(... and package it using umd or so. What is the purpose of volatile functions? I might be wrong but I don't see today the goal except to copy/paste them in the browser's console, or in a script tag of a 90s' website 馃ぃ
Where/how are you going to use those functions?

@huafu I have to support IE6 for a project, I plan to use non-exported functions to polyfill module loading and some of the Typescript helper methods (such as __extend, ...)
However you can't have the code to load modules wrapped up in module code ;)

So I need them to be working without export

But UMD will work for you (I have some internet issues here, tryin to yarn install and it's telling me that I might have internet issues haha.... but I have some patch for your minimal repo)

I have to support IE6 for a project

OMG I'm sorry for you :D

Here is best option I think:

diff --git a/.gitignore b/.gitignore
index 40b878d..0bf769c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
-node_modules/
+node_modules/
+dist
diff --git a/jest.config.js b/jest.config.js
index 93b656f..60151d2 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -1,20 +1,8 @@
 module.exports = {
-   'roots': [
-       '<rootDir>/src',
-   ],
-   'transform': {
-       '^.+\\.tsx?$': 'ts-jest',
+   preset: 'ts-jest',
+   globals: {
+       'ts-jest': {
+           diagnostics: { ignoreCodes: [151001] },
+       },
    },
-   'testRegex': '(/__tests__/.*|(\\.|/)(test|spec))\\.(tsx?|js)$',
-   'moduleFileExtensions': [
-       'ts',
-       'tsx',
-       'js',
-       'jsx',
-       'json',
-       'node',
-   ],
-   "globals": {
-       "window": {}
-   }
 };
diff --git a/package.json b/package.json
index 0d8c987..5e0e5d9 100644
--- a/package.json
+++ b/package.json
@@ -6,11 +6,11 @@
   "license": "MIT",
   "private": true,
   "scripts": {
-    "test": "jest"
+    "test": "jest",
+    "build": "tsc -p tsconfig.build.json"
   },
   "devDependencies": {
     "@types/jest": "^23.3.2",
-    "@types/node": "^10.11.1",
     "jest": "^23.6.0",
     "ts-jest": "^23.10.2",
     "typescript": "^3.1.1"
diff --git a/src/foo.spec.ts b/src/foo.spec.ts
index e03bc2e..4bac263 100644
--- a/src/foo.spec.ts
+++ b/src/foo.spec.ts
@@ -1,9 +1,9 @@
-require('./foo');
+import './foo'

 test('"foobar" should be declared', function () {
-    expect(foobar).not.toBeUndefined();
+    expect(window.foobar).not.toBeUndefined();
 });

 test('"foobar" should return "Hello world!"', function () {
-    expect(foobar()).toBe('Hello world!');
+    expect(window.foobar()).toBe('Hello world!');
 });
diff --git a/src/foo.ts b/src/foo.ts
index 818f578..077c147 100644
--- a/src/foo.ts
+++ b/src/foo.ts
@@ -1,3 +1,5 @@
-function foobar(): string {
-    return 'Hello world!';
-}
+declare interface Window {
+    foobar: () => string
+}
+
+window.foobar = () =>  'Hello world!'
diff --git a/tsconfig.build.json b/tsconfig.build.json
new file mode 100644
index 0000000..3dcc918
--- /dev/null
+++ b/tsconfig.build.json
@@ -0,0 +1,10 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "noEmit": false
+  },
+  "exclude": [
+    "**/*.spec.ts",
+    "node_modules"
+  ]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..f4737cf
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "target": "es3",
+    "rootDir": "src",
+    "outDir": "dist",
+    "skipLibCheck": true,
+    "noEmit": true
+  }
+}

I'm closing this since the above fixes your issue. Feel free to re-open if needed.

@huafu using the UMD target produces code like the following:

(function (factory) {
    if (typeof module === "object" && typeof module.exports === "object") {
        var v = factory(require, exports);
        if (v !== undefined) module.exports = v;
    }
    else if (typeof define === "function" && define.amd) {
        define(["require", "exports"], factory);
    }
})(function (require, exports) {
    "use strict";
    exports.__esModule = true;
    function foobar() {
        return 'Hello world!';
    }
    exports.foobar = foobar;
});
//# sourceMappingURL=foo.js.map

As you can see, this code requires a define function and an AMD loader to be present.
The code that I wanted to test is exactly this; I'm writing a minimal, IE6 compatible AMD loader at this point and I wanted to test it.

The main problem is that if I use import/export Typescript will generate code that loads modules, while I'm trying to write the code to load modules; so I really can't use import/export in this code.

Another option is to not test the parts of the framework that require to be present globally, but that doesn't look like the right approach.

Use the diff I gave you @dealloc, it's not using UMD neither import/export

THe thing is that you want to be able to import a no module (ie not exportable) code, which is not possible.

@huafu I'll give it a spin tonight.
I figured it'd be a bit difficult, blame IE6 ;)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ahnpnl picture ahnpnl  路  3Comments

qm3ster picture qm3ster  路  3Comments

jbreckmckye picture jbreckmckye  路  3Comments

mikeyakymenko picture mikeyakymenko  路  3Comments

TKJohn picture TKJohn  路  4Comments