Karma is reporting an error with TypeScript, saying it cannot locate the variable 'exports'

Currently, I am in the process of mastering how to write Unit Test cases for an angular project coded in Typescript. To facilitate this, I have opted for utilizing Karma and Mocha. Below lays out the structure of the application:

Project/
├── app/
│   └── components/
│       └── mycoolcomponent/
│           ├── coolcomp.spec.ts
│           └── coolcomp.ts
│   
├── node_modules/
│
├── gulpfile.js
│── karma.conf.js
│── package.json 
└── tsconfig.json  

Displayed is the configuration file for karma.conf.js:

module.exports = function (config) {
    config.set({        
        basePath: '',
        frameworks: ['mocha', 'chai', 'sinon'],

        files: [
            'app/components/mycoolcomponent/coolcomp.ts',
            'app/components/mycoolcomponent/coolcomp.spec.ts'
        ],

        exclude: [
        ],

        preprocessors: {
            '**/*.ts': ['typescript']
        },

        typescriptPreprocessor: {
            options: {
                sourceMap: true,
                noResolve: false
            },
            transformPath: function (path) {
                return path.replace(/\.ts$/, '.js');
            }
        },       

        reporters: ['progress'],        
        port: 9876,        
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,        
        browsers: ['Chrome', 'IE', 'PhantomJS'],
        singleRun: true,
        concurrency: Infinity
    })
}  

The definition within tsconfig.json:

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "system",
    "moduleResolution": "node",
    "noImplicitAny": false,
    "outDir": "Scripts/app",
    "removeComments": false,
    "sourceMap": true,
    "target": "es6",
    "inlineSources": true
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "typings/boot",
    "typings/boot.d.ts"
  ]
}

Detailed Gulp task:

gulp.task('test', function (done) {
    new Server({
        configFile: __dirname + '/karma.conf.js',
        singleRun: true
    }, done).start();
});  

Included within Package.json are these dev-dependencies:

 "devDependencies": {
    "@types/chai": "^4.0.1",
    // Other dependencies listed here
  }

Inside coolcomp.ts :

export class Calculator {
    add(x: number, y: number): number {
        return x + y;
    }        
}

This is what's found in coolcomp.spec.ts:

import { Calculator } from "./coolcomp";    
var expect = chai.expect;

describe("Calculator Mocha", () => {
    var calculator;
    beforeEach(() => {
        calculator = new Calculator();
    });

    xit("can add", () => {
        var result = calculator.add(5, 5);
        expect(result).to.be.equal(1);    
    });
});  

Upon initiating the gulp task, an error surfaces:

ReferenceError: Can't find variable: exports

Interestingly, by removing the export keyword from coolcomp.ts and the import line from coolcomp.spec.ts, the tests operate without a hitch. Despite previous questions on similar topics on StackOverflow, none were applicable or rendered the needed guidance.
Could someone kindly direct me towards identifying where the issue lies?

UPDATE: After receiving support from both StackOverflow and other forums, I've uncovered the solution to the current problem. For those interested in viewing it, follow this link to access the code repository: GitHub Link

Answer №1

Here is your solution. Temporarily remove sinon.

Uninstall @types/sinon: npm uninstall @types/sinon Uninstall sinon: npm uninstall sinon

Test if tsc works from the command line. Then run: "karma start" from the command line without using gulp.

    // Karma configuration
    module.exports = function (config) {
        config.set({
            basePath: "",
            frameworks: [ "karma-typescript" , "mocha", "chai" ],
            files: [
                { pattern: "app/components/mycoolcomponent/**/*.ts", included: true, watches: false  }
            ],
            preprocessors: { "app/components/mycoolcomponent/**/*.ts": ["karma-typescript"] },
            port: 8081,
            typescriptPreprocessor: {
                options: {
                    sourceMap: true,
                    noResolve: false
                },
                transformPath: function(path) {
                    return path.replace(/\.ts$/, ".js");
                }
            },
            browsers: [ "Chrome" ],
            reporters: [ "progress", "mocha", "karma-typescript" ],
            autoWatch: true,
            singleRun: false,
            concurrency: Infinity,
            plugins: [
                require("karma-typescript"),
                require("karma-chrome-launcher"),
                require("karma-sourcemap-writer"),
                require("karma-mocha-reporter"),
                require("karma-mocha"),
                require("karma-chai")
            ]
        })
    }

// TSCONFIG

{
"compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "noEmitOnError": false,
    "noImplicitAny": false,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "allowJs": true,
    "removeComments": true,
    "inlineSourceMap": true
},
"types": [
  "node",
  "mocha",
  "chai",
  "expect"
],
"version": "2.4.1",
"include": [
    "app/**/*.ts"
]

}

// PACKAGE.JSON

{
  "name": "unittestingwithkarmamocha",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/chai": "^4.0.1",
    "@types/expect": "^1.20.1",
    "@types/mocha": "^2.2.41",
    "chai": "^4.1.0",
    "gulp": "^3.9.1",
    "karma": "^1.7.0",
    "karma-chai": "^0.1.0",
    "karma-chrome-launcher": "^2.2.0",
    "karma-coverage": "^1.1.1",
    "karma-ie-launcher": "^1.0.0",
    "karma-mocha": "^1.3.0",
    "karma-mocha-reporter": "^2.2.3",
    "karma-sinon": "^1.0.5",
    "karma-source-map-support": "^1.2.0",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-sourcemap-writer": "^0.1.2",
    "karma-typescript": "^3.0.4",
    "karma-typescript-preprocessor": "^0.3.1",
    "mocha": "^3.4.2",
    "phantomjs": "^2.1.7",
    "systemjs": "^0.20.17",
    "typescript": "^2.4.2"
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips on how to highlight a clicked list item:

I'm currently attempting to access the key={1} Element within my li. My goal is to set the activeItem in State in order to compare it with the clicked item later on. If they are equivalent, I want to apply an active class to that specific element. How ...

Activating controllers with 2 independent sliders

(Using the WordPress Slider Revolution plugin) I have set up two sliders next to each other - one displaying the service name and description, and the other showing images. The goal is for clicking a specific bullet on the service slider to also trigger t ...

Fetching SFTP directory listings asynchronously using Node.js

I'm currently working on fetching SFTP listings using Node.js from multiple servers. To achieve this, I am utilizing the ssh2-sftp-client library and trying to manage the asynchronous connections by implementing a customized Promise.all() approach. T ...

Choosing a JSON item based on its numerical position rather than by its name

I am attempting to store a JSON object containing information in multiple languages. I am uncertain if the way I have implemented it is optimal, so any suggestions are appreciated. My current issue is that I am unsure how to access the first language with ...

Simple way to retrieve the first and last date of the current month using Node.js

I need help with retrieving the first and last date of the current month using the code below:- let currentDate = new Date(); let month = currentDate.getMonth() + 1; console.log(month); let firstDate = new Date(currentDate.getFullYear(), currentDate.getMon ...

Is there a term in JavaScript that denotes an object that can be serialized into JSON format?

Can you help me find a term for basic objects that accentuates their simplicity? Particularly, objects that do not reference themselves and do not have any methods or bindings (i.e. JSON-serializable). The terms I am currently using are: "flat object" " ...

NodeJs: Dealing with package vulnerabilities stemming from dependent npm packages - Tips for resolving the issue

Is there a way to address npm vulnerabilities that are dependent on another package? For instance, I'm encountering an error where the undici package relies on the prismix package. Things I have attempted: Executed npm audit fix Ensured Prismix is u ...

Having trouble with using findByIdAndUpdate and push in MongoDB?

As someone who is new to Mongodb, I have been using the findByIdAndUpdate function to update a document in my project. However, I noticed that it returns the old document instead of the updated one. Below is the code snippet of my function: exports.crea ...

Trick to keep horizontal element alignment intact when scroll bar appears

Currently, all my pages are designed with the standard fixed-width-margin-left-right-auto layout. .container{ width:900px; margin:0 auto; } An issue arises when some of these pages exceed the height of the window, requiring a vertical scroll ba ...

Issue with Angular Factory not being invoked

I am currently using a tutorial to create a MEAN app with Google Maps. However, I have encountered an issue where the map is not appearing on the page. Surprisingly, there are no errors in the browser console and even when debugging with node-inspector, I ...

Replacing an array element by a specific index number in a React application

I am dealing with an array of [false,true,false,false,true] and I am looking to update the boolean values based on their index numbers. I have been trying to solve this problem in react, but haven't found a workable solution yet. this.setState({ ...

Dealing with the problem of delayed image loading in AngularJS due to a setTimeout conflict

The issue: Upon page load, some images are still processing and not displaying (even though the image URLs are known). The resolution: To address this problem, a customized directive was developed to showcase a loading spinner as a placeholder until the i ...

How can one retrieve the x and y coordinates from the client's browser and pass them to the server in a Bokeh server setup?

I'm currently working on a Bokeh server app called getcoords.py. To start the server, I use the command: bokeh serve getcoords.py. The app includes a HoverTool with a CustomJS callback function and a quad glyph configured to trigger a selected event o ...

What is the best method for displaying a radio button as selected based on a variable value?

I have a variable that stores the value of a radio button. After checking certain conditions, I want to dynamically select the radio button based on this value. if(cheque_date == system_date) { cheque_value='Current'; } else { cheque_value ...

Tips for creating a universal function for two interlinked types

My goal is to establish an abstract relationship between different sub-types of Message and Response, allowing for a generic function that takes a Message as input and returns a corresponding Response. Specifically, when the function is called with type Me ...

Puppeteer encounters difficulty when attempting to click on a particular div element within Gmail

I am attempting to click on the three dots in Gmail by following this link: 1 After that, I want to click on the 'mark all as read' option: 2 Clicking on the three dots works without any issues. However, I am encountering difficulty when tryin ...

Creating internal utility functions in Angular without exporting them as part of the module can be achieved by following a

Currently, I'm in the process of creating an angular module called MyModule. This module includes several sub-modules. angular.module('MyModule', [ 'MyModule.SubModule1', 'MyModule.SubModule2', 'MyModule.SubMo ...

Display the concealed mat-option once all other options have been filtered out

My current task involves dynamically creating multiple <mat-select> elements based on the number of "tag types" retrieved from the backend. These <mat-select> elements are then filled with tag data. Users have the ability to add new "tag types, ...

Guide to displaying a particular item in Vue 3

Currently, I am embarking on a project that requires the functionality to print a specific element of my webpage. After some research, I came across a mixin/plugin known as VueHtmlToPaper which seems to be the perfect solution for what I need. However, I a ...

Updating the head() properties in Nuxt.js via asyncData() is not possible

After creating a server-side rendered Vue.js blog with Nuxt.js using Typescript and Ghost, I encountered a problem updating html metatags with data from asyncData(). According to the Nuxt.js documentation, asyncData() is triggered before loading page comp ...