How to use UnitTests with Jest in a Jovo v3 project correctly?

unit-testing

#1

I used the Jest UnitTest functionality in my jovo project before and it worked.
After the upgrade to jovo v3.0.4 the “npm test” command has the following output:

console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
    Error: Cross origin http://localhost forbidden
        at dispatchError (D:\...\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:65:19)
        at validCORSHeaders (D:\...\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:77:5)
        at validCORSPreflightHeaders (D:\...\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:91:8)
        at Request.<anonymous> (D:\...\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:380:12)
        at Request.emit (events.js:210:5)
        at Request.onRequestResponse (D:\...\node_modules\request\request.js:1059:10)
        at ClientRequest.emit (events.js:210:5)
        at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:583:27)
        at HTTPParser.parserOnHeadersComplete (_http_common.js:115:17)
        at Socket.socketOnData (_http_client.js:456:22) undefined

and

Network Error

  at createError (node_modules/axios/lib/core/createError.js:16:15)
  at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:83:14)
  at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
  at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:193:27)
  at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:119:9)
  at XMLHttpRequestEventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:82:17)
  at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:157:21)
  at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:132:7)
  at dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:62:3)
  at validCORSHeaders (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:77:5)
  at validCORSPreflightHeaders (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:91:8)
  at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:380:12)
  at Request.onRequestResponse (node_modules/request/request.js:1059:10)

If I put the following decorater at the top of the compiled JavaScript-File it works again.

/**
 * @jest-environment node
  */

But if I put it in my Typescript-File and use the “npm run tsc” command, it compiles the string “use strict” on top of the decorator in the JavaScript-File and the tests don’t work anymore.

Is there another way to get it working again? Did I miss some necessary configurations?
Thanks for your help!


#2

Hey @Simon! Add this to your package.json

"jest": {
    "testEnvironment": "node"
  }

#3

hmmm. I didn’t like the solution.

I added a CORS middleware to the server that accepts requests from localhost. The jest property won’t be needed :slight_smile:


#4

Hey @AlexSwe thank you for your help!
Your first answer solves my problem. Why do you think that solution isn’t good? Are there some side effects?

For your second solution, did you change something in the jovo-framework? Or can it be done as some configuration? I’m relativly new in this environment :slight_smile:


#5

The first solution is good enough, but would mean that we would have to adapt this everywhere in our templates :slight_smile:

Yes, I added a CORS middleware. An extra configuration is no longer required.

const corsJest = (req: any, res: any, next:Function) => {
  if (req.headers['jovo-test'] ||
    (req.headers['access-control-request-headers'] && req.headers['access-control-request-headers'].includes('jovo-test'))) {
    res.header('Access-Control-Allow-Origin', 'http://localhost');
    res.header('Access-Control-Allow-Methods', 'OPTIONS,POST');
    res.header('Access-Control-Allow-Headers', 'Content-Type, jovo-test');
  }
  next();
};

Btw. You can also take a look at this example

You can test the app directly without running it in another window.


#6

Ok, but if I alter stuff in the jovo-framework directory, wouldn’t it be gone, after an update?

I checked the example and the idea of only using one window for unittesting would be great. While trying it out, I saw, that it doesn’t work in a typescript environment. After adding “/dist” to the path in the Conversation.ts of jovo-core it works.

if (this.config.runtime === 'app') {
try {
    // TODO: cleaner solution required
    process.env.JOVO_CONFIG = process.cwd() + '/src/config.js';
    this.app = require(process.cwd() + '/src/app').app;
}

#7

Good point. Will publish the fix today or tomorrow.