davestewart / alias-hq

The end-to-end solution for configuring, refactoring, maintaining and using path aliases
https://davestewart.co.uk/projects/open-source/alias-hq/
MIT License
333 stars 12 forks source link

Jest plugin does not properly handle modules in parent dir #45

Closed chrissantamaria closed 1 year ago

chrissantamaria commented 2 years ago

👋 big fan of this package! Ran into a subtle issue in my (unconventional) repo structure.

Problem

Consider this highly simplified and somewhat contrived example:

.
├── README.md
├── app
│   ├── jest.config.js
│   ├── package.json
│   └── src
│       └── index.test.js
├── jest.config.js
├── jsconfig.json
├── package.json
├── src
│   ├── index.test.js
│   └── utils
│       └── some-util.js
└── yarn.lock

The bulk of the code lives in src, though there's also an app directory which functionally is its own package. However, it does share modules (and aliases) with src. Consider this jsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "@utils/*": ["./src/utils/*"],
      "@app/*": ["./app/src/*"]
    }
  }
}

Both the top-level package and app have their own set of tests and corresponding jest.config.js files. In the top-level config, I would expect (and do correctly get!) the following moduleNameMapper value generated by alias-hq:

{
  '^@utils/(.*)$': '<rootDir>/src/utils/$1',
  '^@app/(.*)$': '<rootDir>/app/src/$1'
}

Likewise for app, I would expect this in its config (app/jest.config.js):

{
  '^@utils/(.*)$': '<rootDir>/../src/utils/$1',
  '^@app/(.*)$': '<rootDir>/../app/src/$1'
}

However, I instead get this:

{
  '^@utils/(.*)$': 'src/utils/$1',
  '^@app/(.*)$': 'app/src/$1'
}

Root cause

This seems to be due to the Jest plugin's implementation using path.join: https://github.com/davestewart/alias-hq/blob/dfb0446a1af3d8eb2e44cb14ae66a26de7347837/src/plugins/jest/index.js#L16

When baseUrl is .., join removes the <rootDir> segment entirely. However, in this case (I think) we always want that to exist. Paths like <rootDir>/../src/utils/$1 resolve just fine with Jest's parser.

I've created a reproduction repo matching this described case for easier testing. I also have a branch up which (from what I can tell) fixes the issue - happy to open a PR if you think this is sufficient.

Possible misconfiguration

I wasn't entirely sure how to configure alias-hq for this sort of situation. I did the following in app/jest.config.js:

const {
  get: getModuleAliases,
  config: aliasConfig,
  load: loadAliasConfig,
} = require('alias-hq');
const path = require('path');

loadAliasConfig(path.resolve('../jsconfig.json'));
aliasConfig.baseUrl = '..';

module.exports = {
  roots: ['<rootDir>/src'],
  moduleNameMapper: getModuleAliases('jest'),
};

(I think) I had to manually point to jsconfig.json since it's not in a standard location relative to this config. I also manually set a baseUrl so that paths would be set relative to the parent dir. Still fairly new to this package so please let me know if there's a better / simpler way to configure this!

Happy to clarify any details - thanks!

davestewart commented 2 years ago

Hey! Sorry for the delay in seeing this.

Thanks for the detailed issues; I'll be able to take a look in a couple of days.

jensbodal commented 2 years ago

Hey FYI I was able to just use the webpack plugin instead of the jest one in my jest.config file and seems to work fine that way.

chrissantamaria commented 2 years ago

Hi! Sorry for the bump but just wanted to check in on the status of this. I think my branch may fix the issue, so I'd be happy to open a PR if you'd like and we can go from there. Thanks!

davestewart commented 2 years ago

Hey Chris!

Sorry to miss this, I've been a bit busy. Have a list of things to get to, so let me review this, add you to the list and let you know at what position of the queue you will be in!

One moment, caller...

davestewart commented 2 years ago

Blimey, I'm useless at picking up PRs at the moment. Sorry.