Jest Not Find Mock Module - jestjs

My folder structure:
├──wrapper.js
├──lib
| └──zwportal.js
├── __tests__
│   └── wrapper.test.js
── __mocks__
│   └── zwportal.js
|
In wrapper.js:
const portal = require('./lib/zwportal.js')
Since zwportal.js is very complex, I use a mock put in the mocks folder. So in my test:
'use strict';
// Mocking dependencies
jest.mock('../lib/zwportal.js');
zwportal = require('../lib/zwportal.js');
Hower, when I run:
jest
it says:
FAIL __tests__/wrapper.test.js
● Test suite failed to run
Cannot find module 'abstract-socket' from 'avro-utils.js'
Actually, those files, abstract-socket and avro-utils, are in the original "non mocked" zwportal.js. It seems that jest does not mock this file. Why?
EDIT
In my test suite, if I write:
jest.mock('../lib/zwportal.js', () => {});
zwportal = require('../lib/zwportal.js');
no problems occur. However, I need to mock with some behaviour the mock.

Manual mocks are defined by writing a module in a mocks/ subdirectory immediately adjacent to the module. For example, to mock a module called user in the models directory, create a file called user.js and put it in the models/mocks directory.
try to move mocks directory to lib directory

Related

Unable to inject a class-based provider in a function expression in nestjs

I have created the following project structure using NestJS
.
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── config
│   ├── config.controller.ts
│   ├── config.module.ts
│   └── config.service.ts
├── handlers
│   ├── handler1.ts
│   ├── handler2.ts
│   └── handlers.module.ts
├── main.ts
└── producer
└── producer.ts
Both the handler files wiz. handler1.ts & handler2.ts look something like this:
export const handler = async (args) {
...
...
}
I've ConfigModule in which I've registered ConfigService as a provider. What I want to do is I want to somehow use ConfigService in handler1.ts & handler2.ts. Now mind you, these handlers are not classes, but just normal function expressions. I know if they were classes, I could have injected ConfigService in the handler's constructor using Dependency Injection. But, unfortunately, declaring these handlers as classes is no more an option now. The reason behind that is that these handler files are being consumed by producer.ts and producer.ts reads the entire file and expects an exported function.
I went through the NestJS documentation and found about property-based injection, module-ref, but they were of no help. I also found this link which I think is very close to my problem, But after going through the comments I found out this is not possible.
I don't have much liberty in changing the existing code but I'd still like to know what options do I have here. A solution that would require fewer changes and solve my problem. Thanks!
Note: File handlers.module.ts is serving no purpose in this scenario.

how to call Cucumber stepDefinitions from another project from the same level?

I have a project integration_test that contains all test projects.
I am using the cucumberjs/typescript/nodejs.
In Project1 is implemented the login and I want just to call in Scenarios from Project2 and Project3. The login step use the login implementation from Project1.
How should be the script from package.json from Project2, in case the login step implementation is in Project1?
current script in package.json Project2:
"test:project2": cucumber-js ./tests/ --require '.tests/**/*.ts' --exit"
See below the folder structures:
integration_test
Project1
-tests
-features
-step_definitions
-package.json
-cucumber.js
Project2
-tests
-features
-step_definitions
-package.json
-cucumber.js
Project3
-tests
-features
-step_definitions
-package.json
-cucumber.js
cucumber.js contains:
let common = [
'features/**/*.feature', // Specify our feature files
'--require-module ts-node/register', // Load TypeScript module
'--format node_modules/cucumber-pretty' // Load custom formatter
].join(' ');
You can use cucumberjs 'require' option to make this use case success. Just define your cucumber.js file with this content:
let common = [
'./**/tests/features/', // Specify our feature files
'--require ./../**/tests/step_definitions/**/', // Load step definitions
'--require ./support/', // Load hooks
].join(' ');
By this way, cucumberjs loads all step definitions defined in all projects listed..

Trying to build a Firebase functions project while importing types from an outer project (one level up). Losing folder structure after `tsc` compiles

Sorry in advance for the long question, but project structure issues/bugs are kind of hard to explain.
I have a Next.js project, which is my root project. It's a Typescript project so it has its own tsconfig.json
Here is the basic structure:
> app // APP COMPONENTS
> pages // NEXT.JS PAGES
> types // SOME GLOBAL TYPES FOR THE PROJECT
firebase.json
firestore.rules
storage.rules
tsconfig.json
I need to add cloud functions to this project. So I've followed the docs on:
https://firebase.google.com/docs/functions/typescript
Basically I've typed firebase init functions and followed the instructions from the CLI.
It then created a functions as following (the > sign is denoting a folder):
> app
> functions // NEW FOLDER FOR THE FUNCTIONS PROJECT
> src
index.ts
package.json
tsconfig.json
> pages
> types
firebase.json
firestore.rules
package.json
storage.rules
tsconfig.json
See now that the functions folder has its own tsconfig.json file and its own package.json file. In essence, it is a project of its own. I'm fine with that idea.
Here is the tsconfig.json file that was created:
{
"compilerOptions": {
"module": "commonjs",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017"
},
"compileOnSave": true,
"include": [
"src"
]
}
It also adds a predeploy hook to my firebase.json file.
"functions": {
"predeploy": "npm --prefix \"$RESOURCE_DIR\" run build"
}
This is necessary to build the .ts file before deployment. It will build the files on the functions/src folder to the functions/lib folder, as per the tsconfig.json.
The basic helloWorld example builds and deploys just fine. I've added some files to the functions folder and its all working.
See my files on functions/src:
See the compiled files on functions/lib:
It's the very same structure and files, just as you'd expect.
THE PROBLEM
The problem begins when I'm importing a type from the "outer" root project. For example:
I go on functions/src/index.ts and do something like the following:
import SomeType from "../../types/whatever"
// USE THE TYPE HERE
Now see what the build result is (i.e: the functions/lib folder):
Now it basically creates another functions under the lib folder. And it also basically copies the files from my types folder. I have no idea why it is doing that.
I wasn't expecting that at all. I'd like to use my types from the outer root project, but without messing with the structure of the resulting functions/lib folder.
What could be happening?
A way around it, that is not too hacky, is to declare your shared type as a namespace and import them with a /// <reference path="..."> command.
That way, you will be able to access your type through the declared namespace and the build will keep the required directory structure.
Assuming the following project
my-project/
functions/
src/
index.ts
shared/
type.d.ts
...otherFiles
shared.ts
declare namespace shared {
interface IType {
name: string
}
}
index.ts
// eslint-disable-next-line
/// <reference path="../../shared/model.d.ts" />
import * as functions from "firebase-functions";
export const helloWorld = functions.https.onRequest((request, response) => {
const type:shared.IType = {name: "John"};
functions.logger.info("Hello logs!", {structuredData: true});
response.send(`Hello ${type.name}!`);
});
The // eslint-disable-next-line comments is required if you use eslint default rules from firebase template because of the #typescript-eslint/triple-slash-reference rules.
I just solved a similar issue where I wanted to import the types from the project folder into the firebase functions folder.
// Default folder structure for Next.js and firebase functions
project-folder/
├── functions/
│ ├── src/
│ │ ├── index.ts
│ │ └── interfaces.ts // (See explanation for this one)
│ ├── package.json
│ └── tsconfig.json
├── interfaces/
│ └── index.ts
├── lib/
├── pages/
│ ├── _app.tsx
│ └── index.tsx
├── package.json
└── tsconfig.json
The functions/src/interfaces.ts simply exports the types from the project folder, like so:
export * from "../../interfaces";
If you run tsc in the functions-folder now, it will generate a file structure that looks different from before:
// Output when not importing from outside functions src folder
lib/
├── index.js
└── index.js.map
// Output when importing interfaces from outside src folder
lib/
├── functions/
│ └── src/
│ ├── index.js
│ └── index.js.map
└── interfaces/
All you now have to do is change package.json a little bit:
{
"main": "lib/functions/src/index.js"
}
That's it! Files in your functions folder can import from the project folder.
Note about interfaces.ts: I added this file because it seemed cleaner to have only one file that imports from outside the functions folder. Also, this way importing interfaces in the functions folder is similar to everywhere else in the project.

AWS Lambda Layers - Typescript - Problem with specifying imports in index handler since, in the layer, then need to be in form /opt/nodejs/

I'm using Typescript to write AWS Lambda code (both handlers and shared code) and then I transpile the code, add node_modules to the dir where transpiled code exist and publish the Lambda. This works correctly.
Now, if I want to add shared code as part of AWS Lambda layer, this is where it gets tricky with Typescript.
Consider following code structure that I have:
.
├── index.ts
├── lib
│   └── userData.ts
├── node_modules
├── package-lock.json
├── package.json
└── tsconfig.json
I would like to have a layer which contains:
node_modules
userData.ts
I'm aware of the structure that needs to exist when publishing the layer and also how to reference it in the index.ts (handler method) code.
Before layers, my index.ts code looks like this:
import { UserData } from "./lib/userData";
export const handler = async (event: any = {}): Promise<any> => {
# some code here
}
Because I want to import UserData from the layer, import would need to look like this:
import { UserData } from "./opt/nodejs/userData";
However, if I specify this, and try to transpile code (before creating a aws lambda package), I will get an obvious error:
index.ts:1:26 - error TS2307: Cannot find module '/opt/nodejs/userData' or its corresponding type declarations.
1 import { UserData } from "/opt/nodejs/userData";
~~~~~~~~~~~~~~~~~~~~~~
There are some ways to avoid this:
Adding // #ts-ignore before the actual import will silent this error
Dirty/hacky way would be to edit this import on transpiled code which is not what I want to do.
Now, this seems like a chicken and egg problem and I'm new to the AWS Lambdas, so any advice on how to handle this situation without these hacky ways to avoid it?
I solved this using typescript path mappings. You can add this to your tsconfig.json.
"baseUrl": ".",
"paths": {
"/opt/nodejs/*": ["src/testLayer/nodejs/*"]
This specifies to the TS compiler that the /opt/nodejs/ path is really pointing to src/testLayer/nodejs/ in our local directory structure, so it gets the files from there

Express.js Project Structure

I found that Express has an application generator, however the documentation does not explain the purpose of each directory and file. If someone could just give me a short explanation of which files I should be putting where, that would be much appreciated. Here's the generated app structure:
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
7 directories, 9 files
The app.js file is the entry-point of your application.
The package.json file contains all of your dependencies and various details regarding your project.
The bin folder should contain the various configuration startup scripts for your application.
For example, instead of applying all the Express middleware in the app.js file, you module.exports = {} them from their own configuration file and require them in app.js. [additional info LINK]
The views folder contains all of your server-side views.
The public folder contains all of your front-end code.
The routes folder contains all the routes that you have created for your application.
As stated in the official documentation, be aware that this is just one way to organize your code.
You should test it out and see if it fits your project.
This thread gives a deeper answer about the www file specifically: What does "./bin/www" do in Express 4.x?
Basically, running your app from the www file (which calls app.js) allows you to start your app with different configurations. You might have a "www" file representing the way the app should be run when on the web, a "dev" file that you, as the developer, would run, a "test" file you would run when running tests, etc. Read the thread linked above for more detail!
This structure is a standard organization for web-app
public contains all client static files (css, client javascript (ex. jQuery), images, fonts...)
routes contains the main back-end code (server side), which compute data before calling a template engine (see below) or respond to the client (via json of xml).
views contains each page template, see jade template. These files are used by scripts in "route"
app.js contains the express core, such as uri parser, modules, database...
package.json is the project descriptor file (used by npm for dependencies and sharing)
If the application generator provide a full example, don't hesitate to open each file (starting from app.js) to understand the project's organization.

Resources