Using Jest with ReactDOM.findDOMNode - javascript

Jest (technically, Jest snapshot testing with ReactTestRenderer) does not work with ReactDOM.findDOMNode.
I've seen where I can work around this using Jest mocks. For example, if my ChannelScanner component uses my RadioButtonSet component, which wraps react-widgets' SelectList, then putting the following code in ChannelScanner.test.js allows snapshot testing to work:
jest.mock('../../src/components/forms/RadioButtonSet', () => 'RadioButtonSet');
However, this seems to break encapsulation: RadioButtonSet's tests have to set up mocks based on the components it uses, and the transitive components that they use, and this work has to be repeated for every component.
What's the best way to handle this? Short of enabling automock, is there a good way to say, "This module knows that it needs to mock itself whenever it appears?"

Related

Smoke Test with ReactJS and Jest

I found this example of Smoke Test with ReactJS and Jest, but I can't understand it. Someone can explain it to me, please?
Well, first I can't see the difference between 'smoke tests' and 'unit tests' I see people say smoke tests are superficial and obvious. But every unit test isn't it? I mean, every one of them isn't made to check if things are working the way they should work? When a test isn't obvious and can be understanded not as a "smoke test", but as a "unit test"? Second, I'm starting with unit tests and I can't understand Jest mechanism. In this case, it creates a div trough "document.Element('div')" and then compare with my project div, "MyCard"?
Thanks in advance.
// MyCard.js
import React from "react";
const MyCard = () => {
const [counter, setCounter] = React.useState(0);
const handleClick = () => {
setCounter(counter++);
}
return (
<div>
<p>Counter: {counter}</p>
<button onClick={handleClick}>Increment</button>
</div>
);
}
export default MyCard;
//MyCard.test.js
import React from "react";
import ReactDOM from "react-dom";
import MyCard from "./MyCard";
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(<MyCard />, div);
});
I tried the example, it worked. But I can't understand why.
Why wouldn't it work? It's testing that the component just does something; quoting Wikipedia on smoke tests,
For example, a smoke test may address basic questions like "does the program run?", "does the user interface open?", or "does clicking the main button do anything?"
In this case, the test addresses the question "does it render at all".
So based on your comment there are two components to this question. What makes a smoke test different to a unit test? and What is this smoke test doing, and why?
A unit test has a very limited scope. A proper unit test will cover a single unit of a larger system. Compare that to, for example, an integration test or an end-to-end test which have a larger scope. Good, thorough unit tests will also cover all relevant aspects of the module they are testing, which can mean testing every line and every conditional. Writing and running a full suite of unit tests can verify a lot about the behaviour of your code, but it's possible to have a broken program in which every unit test passes, due to some of the integrations being broken, for example.
A smoke test, instead, is a low-effort sanity check to make sure that something works. It doesn't guarantee that it works well, or that there are no bugs, or that the behaviour or appearance are correct, just that that aspect of the system hasn't been completely broken. Smoke tests are less powerful than a full suite of tests but they tend to be faster to write, easier to update if the code is refactored or changed, and much better than no automated testing at all.
It can be useful to look at what would cause a smoke test to fail, in order to understand why it's useful. In this case the test is creating an empty element, then adding our custom component as a child element. The test passes as long as we are able to do this without ReactDOM.render() throwing an error. So when would this fail? Simply put, this fails if our element has invalid syntax. Let's say we accidentally delete the closing tag in the HTML - this would throw an error, the smoke test would fail, and we would know that the component needs looking at.
Is it as thorough as a proper set of unit tests where we check that the counter works as expected? No. At the same time, though, this is a very fast test to write, and even if we have other unit tests it can be good for debugging to know whether this test passes or fails. If we add another unit test that checks whether the counter is working, and that test fails but this one passes, we know the counter is broken. However if this test fails too, we know that the counter isn't the problem, it's the whole component.

Dependancy injection using Tsyringe for multiple implementation of interface in Typescript

Context
I am currently working on a Typescript Lambda project where we are planning to refactor our code to make use of dependency injection using the Tsyringe library. We have a typical MVC structure for projects except instead of the Repo/Database layer we have a proxy layer which calls a third-party service over the rest API to fetch the required data.
The catch is that the proxy layer will have a single interface defined and it will have multiple implementations among which one needs to be injected depending upon the business decision. For example AuthProxy is an interface which contains a login method, and it has two different implementation classes KeycloakAuthProxyImpl and AuthZeroAuthProxyImpl. These two implementations will be in 2 separate folders say AuthZero and KeyCloak and while building we pass an argument like --folderName so only one implementation will be available in runtime for dependency injection.
The problem
The problem we are facing with Tsyringe (I have evaluated some other libraries too) is that interface-based dependency injection needs explicit token-based registration with ioc-container in the main.ts page(In my case, the handler function file). So as per theory, I should be registering it as follows.
.
But in our case, this is not possible. Because say we are building it as --keycloak as an argument, then AuthZearoAuthProxyimpl will be ignored while compiling and hence the code will break in line 14 at runtime.
We tried to move that dependency registration logic to the corresponding implementation class so that each implementation class will be self-contained and isolated so that there won't be any runtime issues. But then these are not even being registered for dependency injection and we get an error saying Attempted to resolve unregistered dependency token: "AuthProxy". This is expected as per the file loading of javascript.
KeycloakImpl class.
.
We even tried using #registry decorator which can be found commented in the images, but it also didn't make any difference.
Even though I haven't tried any other dependency injection libraries of Typescript, from my little research, most of them follow more or less the same pattern for interface-based dependency injection and I am anticipating the same issue in those also. Is there any other workaround through which I can resolve this issue, or is it even possible with typescript?
PS: I don't have much expertise in js and typescript, the above keywords are based on my experience with spring and java. Please ignore if I have misused any js specific terminologies while explaining the issue.
Code and project structure
I had similar problems with tsyringe and I found a much better approach.
Here is how I would solve this with a different DI lib iti and also remove many lines of code:
import { createContainer } from "iti"
import express from "express"
// import other deps
const container = createContainer()
.add({
authProxy: () =>
Math.random() > 0.5
? new KeycloakAuthProxyImpl()
: new AuthZearoAuthProxyImpl(),
})
.add((ctx) => ({
authService: () => new AuthServiceV3(ctx.authProxy),
}))
.add((ctx) => ({
server: () => {
const app = express()
app.all("/login", async (req, res) => handler(req, ctx.authService))
return app
},
}))
// start your server / lambda
const server = container.get("server")
server.listen(3000)
I've also refactor other parts of the app and got rid of singletons and made code IMO a bit simpler to read
I’ve created an interactive playground with a mock your app:
https://stackblitz.com/edit/json-server-ntssfj?file=index.ts
Here are some links to the lib:
https://github.com/molszanski/iti
https://itijs.org/

How to get react component Name inside componentDidCatch in producation build?

I used error boundary inside (componentDidCatch)I want to log which react component is break in producation build.
conclusion is get react component Name inside componentDidCatch in producation build.
I read many article and below link this is same as I asked in question but it's not solve my problem.
Getting React Component by name
and I also saw some webpack related things (production config's uglify) but it's not proper clear.
let me know if any simplest way to solve this issue
By design, you should never be able to see debugging information in a production build. What you are trying to accomplish here is an anti-pattern. However, if you still want to go through with it, you can use:
this._reactInternalFiber.elementType.name
Note that it might be instable due to using a private property that belongs to React.

Difference between mock and unmock test in Jest

Recently I've become familiar with Jest library and unit test concepts and everything due to jest's documentation is right in my codes.
But I need to know what's difference between mocking and unmocking concept in Jest and other unit test libraries.
Thanks
Mock means to replace an instance with another one. In jest its used to replace the implementation of imported modules with your own one.
jest.mock('yourModule', () => {test: ()=> 'test'})
The main idea behind it, is to isolate your code in unit test, so that you only test one module without the influence of other parts of your application or external code. This has a bunch advantages. First of all if the code in one module breaks, only the test for this part will fail and not a all test for parts that just import this module. Second you can simplify the test itself as you dont need to start up a server that returns with specific data, which would also slow down your code.
The unmock feature is there cause of the automock feature, which was the default in the past. Automocking will replace all imported modules with default mock. As this make sense for some modules but is not wanted for lodash for example you could then unmock the mocking of them. So unmock is mostly needed with automock switched on to get the original implementation if needed.

Injecting dependencies in unit tests in Angular 2 2.0.0-rc.5

Are there any instructions or example set ups for how to inject dependencies in Angular 2, latest release?
The Testing Guide is still incomplete, and only takes you so far. If, for example, you want to test a component that takes #Input() parameters, my understanding is that you specifically need to inject it, but I've run into some problems getting this to work.
When I try to follow examples such as this one I get errors about configureCompiler not being a part of #angular/core/testing. I believe this may have been moved into TestBed but when I try to use call TestBed.createComponent(MyComponent) I get an error that there's No provider for TestingCompilerFactory! And when I try to import it from #angular/compiler/testing I get a Typescript compiler error that it isn't there. Doing a grep, I can find the file it's in in my local node_nodiles but then that file gives a bunch of Typescript errors if I try to import it!
Is there any straightforward guide on how to do this?
Getting testing in RC5 can be difficult as it's still so new. You can look at this angular2-starter (https://github.com/antonybudianto/angular2-starter) and see how he has implemented testing in RC5.

Categories

Resources