How to do Jest testing in Node app with added React components - node.js

We have a Node app that we're going to rewrite in React next year so we're building all of our new .jsx components in React and injecting them into ReactDOM like they describe here: https://reactjs.org/docs/add-react-to-a-website.html
We build the .jsx React components with Babel/webpack before we deploy the site and this works pretty well.
But now I'm trying to write Jest tests for these components and I'm getting an error when I import the React component file into my test:
createRoot(...): Target container is not a DOM element.
How do I get my test to see the container as a DOM element? I've tried using happy-dom and jsdom but they don't see the document object.

Related

Use React to build parts of the application features

Consider having a web application that is based on a complex platform, however, you can design HTML Forms using its designer, and insert standard HTML elements, one of which is HTML Component. You can use this component to add HTLM/JavaScript code as usual.
I followed a tutorial to create a react app without using create-react-app. I managed to develop a sample React app using NodeJs, Babel, and Webpack and managed to deploy the final bundled JavaScript main.js on the target application. All worked fine. Below are the main two files with the source code:
index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.querySelector("#root"));
App.js
import React, {useState} from "react";
const App = () => {
let [counter, setCounter] = useState(0);
const increment = () => {
counter++;
setCounter(counter);
}
return <div>This was created from React and Hello World!
<h1>This is a test Header</h1>
<button onClick={increment}>Click here to increment</button>
<br/>
<span>{counter}</span>
</div>
}
export default App;
The Form HTML Component in the Target Web Application:
<div id="root">This Text should be replaced by the React App</div>
<script src="./target/app/path/public/main.js"></script>
Mind you that I ran the command npm run build and it generated the final script main.js which is deployed to the target application.
I am planning to start using React to build specific components for example a combination of Drop-Down Fields and Grid elements which are populated using REST APIs.
The problem is that I have to have one entry JavaScript source file that will render the component using ReactDOM.render(<App />, document.querySelector("#root")), and if I develop say 100 components, but not all of them will be rendered when any Application Form is loaded. I think if the React render() function is invoked and the target DOM element is not present, then it will throw an error (I am not sure though).
So the question is how to design the application so that I can follow the above approach and ensure that the intended React Component will kick in only when the related Form is loaded or active.
I am thinking to import all the Components in index.js and develop a method to detect if the Form is active and needs a component, then it will invoke the function ReactDOM.render(<MyComponent />, document.querySelector("#MyComponentId")).
I am not sure how to implement that and I need help. I appreciate your feedback.

Issue: window, document, local storage undefined in node modules during server side rendering using react and express js

I have tried to implement SSR in react js using express js. While we render the client page from server file it throwing browser level object not supported/undefined error in node modules.
If the window/document/localstorage is undefined in application file then can able to solve the issue making some conditions as recommended in this link React - “localStorage is not defined” error showing
but the error occurred in node modules.
Here I have attached link for the reference for browser level object only working on client side rendering.
https://stackoverflow.com/questions/32126003/node-js-document-is-not-defined#:~:text=The%20short%20answer%20is%20don,are%20not%20available%20in%20node.
My application is,
React: ^16.12.0 (Created by using create-react-app, build done by using react-scripts command)
Node: v14.17.1
Express: ^4.17.3
Screenshot for reference:
document undefined

importing React component file with node js

I have this node js application:
require('babel-register');
const router = require("./src/web/router");
and I am getting this error:
how can I import react component in node js?
possible using esm node pacakge, esm is a fast, production ready, zero-dependency ES module loader for Node 6+.
esm on github
If you are not interested in server side rendering your react component I made a small library that makes it easy to render react components from a node application https://github.com/tswayne/react-helper#getting-started. If you are trying to server side render, or import the react component for any other reason, you will need to compile your server side code with babel or use something like babel-node to compile at runtime.

Sails + react on a single heroku server ?

I have a single project which runs sails app on 1337 port and react on 3000. How can I deploy both to single heroku instance ? Which runs sails on 1337 and react on 3000.
You need to integrate React with Sails.
React is all about static files (e.g. HTML, JS and CSS). To integrate React with Sails, a naive solution is to copy the compiled React files to the Sails assets folder.
Below is what I have tried with a brand new Sails app. It just works.
Edit config/blueprints.js to change the API prefix. From now on, the APIs changes from http://localhost:1337/<RESOURCE> to http://localhost:1337/api/<RESOURCE>.
module.exports.blueprints = {
// ...
prefix: '/api',
// ...
}
Edit config/routes.js. Remove the following lines if they exist. This makes sure that when someone visit http://localhost:1337, Sails will search for index.html inside the assets folder.
'/': {
view: 'homepage'
}
Update the React application in case it consumes the APIs from Sails (Remember that we have changed the API prefix). Also make sure that the application entry point is index.html.
Compile your React application (by Webpack or Grunt or whatever packaging tool you are using) and copy the compiled files to the Sails assets folder.
Deploy the Sails app to Heroku.
Done!
A better but more tedious solution is to migrate the React development to Sails. I found an example on Google. It might be outdated because the last update was Feb 2016, but you shall use it as a reference.

Webpack-dev-server and isomorphic react-node application

I've managed to properly use webpack dev server alongside with a node server (express), using the plugin section inside webpack's config.
It all works fine but now I'm trying to go isomorphic and use client-side components inside the express application.
So far the only problem I'm encountering is that without webpack 'parsing' my server-side code I get to a situation where I require components but the paths are not solved
I.E.
Inside a component
'use strict';
import React from 'react';
import { RouteHandler, Link } from 'react-router';
import Header from 'components/header/main'; // <-- This line causes the error because webpack is not working when parsing this JSX server-side
export default React.createClass({
displayName: 'App',
render() {
return ( // ... More code
Shall I configure webpack in another way or do I have to change all the imports to be valid server-side?
the codebase is here in case you want to see the actual state https://github.com/vshjxyz/es6-react-flux-node-quickstart
In order to be able to require components in a way such as require('components/Header.js'); and avoid using long relative paths such as require('../../../../../../Header.js'); you can add this code to your node app before any require() calls:
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();
However, since this relies on a private Node.js core method, this is
also a hack that might stop working on the previous or next version of
node.
Other possible solutions to this problem can be found at https://gist.github.com/branneman/8048520
I see 2 options:
Compile client code with webpack as well. If client's entry
point is in the same dir as server's - it should work with your
present code. This looks natural to me.
Use relative paths i.e.
import Header from './components/header/main'

Resources