testdouble / testdouble-jest

A testdouble.js extension to add support for Jest module mocking
MIT License
37 stars 5 forks source link

td.replace(path) is relative to the setupTestFrameworkScriptFile not the path of the test #2

Closed skbolton closed 6 years ago

skbolton commented 6 years ago

I will do some more digging to see what is going on but wanted to give you a heads up in case you know anything about this.

I was getting really weird behavior when trying to td.replace() in my test. Here is the situation. I am currently writing a test for model.js that needs to mock a dependency it has on query.js. The test is happening in __test__/model.test.js

screen shot 2018-03-11 at 10 38 54 pm

Here is the setup of my test

screen shot 2018-03-11 at 10 49 08 pm

I get the following error. jestSetup.js is my SetupTestFrameworkScriptFile:

screen shot 2018-03-11 at 10 50 11 pm

As soon as I change the td.replace() path relative to that setup file things work

screen shot 2018-03-11 at 10 48 33 pm screen shot 2018-03-11 at 10 52 22 pm

Here is my package.json for completeness

{
  "name": "arbiter-salesforce",
  "version": "0.1.1",
  "description": "A Salesforce ORM powered by jsforce",
  "main": "index.js",
  "tonicExample": "const arbiter = require('arbiter-salesforce')",
  "repository": {
    "type": "git",
    "url": "git://github.com/skbolton/Arbiter"
  },
  "scripts": {
    "test": "standard && jest",
    "fix": "standard --fix"
  },
  "jest": {
    "setupTestFrameworkScriptFile": "test/jestSetup.js"
  },
  "keywords": [],
  "author": "Stephen Bolton",
  "license": "ISC",
  "standard": {
    "env": "jest",
    "globals": [
      "td",
      "specify"
    ]
  },
  "devDependencies": {
    "jest": "^22.4.2",
    "rimraf": "^2.6.1",
    "standard": "^10.0.2",
    "testdouble": "^3.5.2",
    "testdouble-jest": "^1.0.1"
  },
  "dependencies": {
    "dot-prop": "^4.1.1",
    "jsforce": "^1.8.0",
    "superstruct": "^0.5.1",
    "type-detect": "^4.0.0"
  }
}

Sorry for the dump of images I just thought they show some things better

skbolton commented 6 years ago

After a little more digging it is reproducible by changing the setupTestFrameworkScriptFile in the example code in this repo to being different from the folder the tests are in.

searls commented 6 years ago

Thanks for the report @skbolton, it turns out you are exactly correct!

The issue appears to be that jest.requireActual resolves the path relative to the file from which it is called (the helper, in this case), which of course will be the Wrong Thing from the perspective of almost every Jest test.

I just spent about an hour digging through the source and attempting to see if I could use a similar trick to what we do in quibble, but then realized that finding the caller's location using stack traces isn't quite possible due to the way Jest runs every test in a v8 VM instance.

It's a shame that jest does not expose more of its LocalModuleRequire goodies (like its resolve function), because it'd probably make this a lot easier. (What is actually exported and what is available.

I wonder if Jest's runner offers any way to get the absolute path of the currently running test. If we had that, we could use its directory to join whatever relative paths were passed in at least, which should work

searls commented 6 years ago

Ok, I think I have this fixed. This should work as of testdouble@3.6.0 and testdouble-jest@2.0.0

searls commented 6 years ago

I just created a test project using only the npm versions of testdouble, quibble, and testdouble-jest (prior to release I had to use links which made me a little wary), and everything seems to work ok.

Hopefuly the mechanism used to absolutify paths works in all cases

skbolton commented 6 years ago

Sounds good. I did the same thing. Their source takes some serious time to digest and I got to that same module you are talking about. I will give the new versions a go. Thanks for tackling this!