Jest changed test directory resulting beforeAll is not defined - node.js

I used to put all my tests together inside of __test__ directory. But I decided to put each test files into each component's directory with different name convention.
Old Structure:
src/
__test__/
example.test.js
example2.test.js
New Structure:
src/
components/
example/
example-controller.js
example-model.js
example-route.js
example-test.js
As naming and location of a directory changed, I updated all import statement and namings for according files. I was using default feature of Jest but since I changed test file name to example-test from example.test I also updated package.json
"jest": {
"testRegex": "./src/components/*/.*.-test.js$"
},
Problem is when I run the project, npm run it throws
beforeAll((0, _asyncToGenerator3.default)( /#PURE/_regenerator2.default.mark(function _callee() {
ReferenceError: beforeAll is not defined
any idea why it is happening?

Try regextester with your file-paths before getting frustrated. Also, look at some popular existing javascript projects using jest and check their jest configurations to see how the community is settling on project structure. It may seem simple to follow others, but most software engineers don't work alone, and usually agree on good practices.
Consider coming back to this project in a year; You are changing the default behavior of a simple process that works beautifully out of the box. Someone may hate you later after a git blame.
If all you want to do is check all -test.js files, slowly modify the default config until you match the file paths you want.
(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$
Should probably (for you) be:
(.*/src/.*(-test).jsx?)

Related

Package.json - set main directory

I'm building a library with no default export, but a whole set of sub-exports. It's documentation for a set of APIs, so each API is exported from its own sub-directory. There is no central API info that should be exported from, say, dist/index.js, but instead, there's dist/api-one/index.js, dist/api-two/index.js, etc.
Currently, I'm importing like so: import { SomeFeatureOfApiOne } from 'my-package/dist/api-one
But it'd be nice to be able to get rid of the dist in the import path, since everything will have it. I know the files parameter just determines which directories are included in the export, so that doesn't work, and it appears that main is for the actual module file, not a directory.
Is there a way to do this? I was thinking of maybe a postinstall script that moves the sub-directories from /dist to root, but that feels super hacky to me, so I was hoping there was a neater way.
Add:
"exports": {
"./*": "./dist/*.js"
},
to your package.json
You can read more about "exports" here - https://nodejs.org/api/packages.html#subpath-exports

Using type-checker ESLint rules with a Nx monorepo

I am trying to use the rule "#typescript-eslint/naming-convention".
My understanding is that this rule requires linting with type information, described here: https://typescript-eslint.io/docs/linting/type-linting/
When trying to use 'plugin:#typescript-eslint/recommended-requiring-type-checking' I then get the following error:
You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for #typescript-eslint/parser.
However I cannot see how parserOptions.project this should work when using a Nx monorepo.
In the monorepo, there is a variety of different files created for each project. At the top level there is a tsconfig.base.json, then each project has a tsconfig.json, and its own .eslintrc.json. I have tried a variety of combinations (including some great advice here) but I haven't managed to get anything working yet.
If changes to individual project files are required, I could add some custom generator logic, but ideally I'd work with global rules.
Also searching GitHub doesn't bring up any example repositories either.
Q: May anyone advise me how to use TypeScript linter rules which require type information with a Nx monorepo?
So it looks like you can use
"parserOptions": {
"project": ["./tsconfig.base.json"]
},
with Nx and that seems to work at the top level, meaning that you shouldn't need to edit individual .eslintrc files for each project.
You do also need to just apply the "parserOptions" and the "extends": ["plugin:#typescript-eslint/recommended-requiring-type-checking"] within the "overrides" array, just for TypeScript files only, as described in this answer: "parserOptions.project" has been set for #typescript-eslint/parser.
This was actually enough to get me working, running nx lint from the command line... my problem was that I also have an issue with WebStorm settings on top of all this too, which was obscuring things further. It might be this open issue, https://youtrack.jetbrains.com/issue/WEB-47201, but that is really a completely different question... my original question is answered.

NodeJS import file with the same name as a folder

I have the following file structure: ([] are folders)
[MySQL]
ConnectionPool.ts
Connection.ts
MySQL.ts
In my code, I am using typescript to develop the app, which will be built to javascript for the production version. The development version is tested directly from the uncompiled typescript files, using babel with the following configurations:
{
"presets": [
["#babel/preset-env", {
"targets": {
"node": "current"
}
}],
"#babel/preset-typescript"
],
"plugins": [
"#babel/plugin-transform-runtime",
[
"module-resolver",
{
"alias": {
... list of some aliases
}
}
]
]
}
My problem is the following, I do most of my imports like this:
import ConnectionPool from 'MySQL/ConnectionPool`
which works for me, as when I run my dev code, the compiler correctly identifies the file extension to .ts, and it also correctly identifies the built versions file extension to .js.
But if I want to import my MySQL.ts file, I can't do it this way, as I will get the following error: Error: Cannot find module './'. If I specify in my import statement the file extension, everything works correctly, but then, when I build my code, there will be no more .ts files in there, so I will get errors there.
Strangely, on the frontend, where I use webpack, I get no complaints about importing files without extension whose name is the same as a folders name in the same directory. What solutions do I have for this issue, which does not revolve around renaming my files or folders in the structure?
Rename your file MySQL.ts to index.ts and move it into the folder MySQL
In the meantime, I resolved my problem by explicitly specifying .ts as the file extension, and when building the code, using the babel-plugin-transform-rename-import to replace the .ts extensions to .js extension.
I won't accept this as the correct answer, as this is too hacky for me, so if a better solution comes up, I am still open for it.
I don't believe what you want to do is possible, node will automatically include either the file or the directory but if both of them are called the same thing node will have no idea which one to import and it will always prefer one over the other.
Using import Example from 'example' will have node search either for any files called example.js or directories called example with an index.js and it will only load one of them.
The reason webpack does it correctly is because webpack will never bundle a "directory", it will take what you've specified as an import and try all of the resolves extensions until it finds one and then it will import that file, so you'll never have conflicting files with directories with webpack.
I thought maybe a solution is to use aliasing in your typescript config so that you can use import Example from '#example' and differentiate between your directories and files that way. Then you can also do import Example from 'example' if you just want to load the file itself. But even then I don't think that will even work because once it gets compiled to javascript you'll just have the same issue as before with conflicting paths.
That being said, while I understand being a little bit obsessed with naming conventions and small things, I really don't think you should be storing "mysql" outside of the "mysql" directory, for two reasons. The first reason is that it's part of that directory, that's what that directory is for, it contains the "mysql" stuff, so why would you want to store it outside. Secondly using a "index.ts" communicates something to other developers, when I open up a new project or directory I'm immediately looking for something called "index.ts" or similar, otherwise I have no idea where to even begin. Using "index.ts" is a good way to communicate to anyone that "this file right here is the one you're looking for, everything starts here". That being said, just call it index.ts and store it where it belongs.
You can try in your tsconfig.json to set moduleResolution to the classic strategy:
{
"compilerOptions": {
"moduleResolution": "classic"
}
}
Unfortunately, looking at the code, this seems to be impossible in your setup:
import is handled by module-resolver
module-resolver calls the NPM package resolve
resolve.sync checks for the no-extension case before testing extensions.
Given that most systems are going to follow Node module resolution, I think you're out of luck, without some manual aliases or moving files around.
FWIW, NodeJS says that extensions in import are mandatory.

Intellij IDEA resolve local require() path [ node.js ]

I'm trying to avoid relative require() calls in my express setup. I'd also like to avoid placing my code in the node_modules folder. In short, I'm trying to implement any of the methods described in this gist.
Any of those solutions will work fine for executing code with node or npm. However, I'm trying to find a solution that will also be supported by Intellij IDEA's code resolver, i.e. trying to make sure "go to declaration" and autocomplete hinting works.
I've tried the following
Setting NODE_PATH in the run configuration.
Using a global prefix, i.e. require( global.__base + "mylib").
Adding a symlinked folder to node_modules/.
Adding a symlink from a lib/ folder to node_modules/lib/ does work, but comes with two caveats:
Changes to the source files aren't picked up automatically, so I have to manually "synchronize" node_modules/lib, and
When "going to declaration", IntelliJ (of course) opens node_modules/lib/mylib instead of lib/mylib. This can lead to confusion as the actual file and the symlinked file can be open in separate windows.
Instead of a different way to require local paths (all these methods do work with node after all), I'd be happy with a way to hint to IDEA that it should search the lib/ folder for sources.
So, I realised that if you add a library through Project Structure > Libraries, it won't actually be enabled.
Instead, go to Preferences > Languages & Frameworks > Javascript > Libraries and add a new library. Set the framework type to node_modules, Visibility to Project and add your lib folder.
After adding it, make sure the Enabled checkbox is checked.
That's it, Intellij can now resolve your require('mylib') paths.
Use whatever method from the gist mentioned in the question to actually get node to resolve the paths.

What naming conventions exist for the primary Node.js file?

This question has been completely edited in hopes that it will be reopened.
The naming of the main Node.js file is something left to the user and and does not seem to be defined by any well established convention. In hopes of finding a good name, I am curious if there are naming conventions in other parts of the Node.js ecosystem that might suggest a name to use.
Some names I have seen are: app.js, index.js, main.js, server.js, etc.
Please provide only well documented standards in answers.
NPM seems to suggest a standard whereby one can define the primary file in the package.json file like so:
"scripts": {"start": "node server.js"}
If no such property is set, NPM looks for a server.js file in the root of the package. If server.js exists, it will be run with Node.
This default seems to be a strong suggestion that the name server.js should be the standard.
index.js has a special usage in Node.js. From the Module docs.
...
If there is no package.json file present in the directory, then node
will attempt to load an index.js or index.node file out of that
directory. For example, if there was no package.json file in the above
example, then require('./some-library') would attempt to load:
./some-library/index.js
./some-library/index.node
I prefer to use app.js or even main.js
The two predominant filenames are 'app.js' & 'server.js'. Its better to go with 'server.js'. This is for nodejs applications. In the case of libraries, most libraries use 'index.js' and specify it in their 'main' param in the package.json file.
From what I have seen, app.js is the most universally accepted.
I personally prefer server.js, but this is probably biased in that I run a massive Single Page Application so all my files are .... javascript ..... and I have an app.js controller for my front-end. So it helps me distinguish the two.
do you know how well-established conventions start? you make a decision that is logical, and forthrightly forward it with resolute certainty - then others will follow. there clearly is no well established convention, so pick one and tell it to others.

Resources