Writing test case for react-native component [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have never written test cases so I am totally not sure on how to achieve this (and have never worked with travis as well).
I have react-native-formly npm library written entirely in javascript.
Every time dependent bot creates a request, before merging, I want it run test cases and only merge if the app loads and does not crashes. I have seen other open source repo have travis.yml which they used to achieve this but it is still vague to me on how I could achieve it.
Can someone guide me on how to achieve this? what kind of test cases/library I should use. I know there are libraries like jest for snapshot testing but I don't care much if the UI renders differently.

Added a PR for your repository. https://github.com/irohitb/rn-formly/pull/14
This will be quite a long answer, as the question lacks focus, since it's asking for react native jest setup, CI/CD and TDD which could take up multiple Q&A.
Every time dependent bot creates a request, before merging, I want it run test cases and only merge if the app loads and does not crashes. I have seen other open source repo have travis.yml which they used to achieve this but it is still vague to me on how I could achieve it.
Travis CI - you can follow the tutorial
for Circle CI - getting-started
for cypress - e2e cypress
Can someone guide me on how to achieve this? what kind of test cases/library I should use. I know there are libraries like jest for snapshot testing but I don't care much if the UI renders differently.
In this PR - we have introduced jest and react-native-testing-library.
jest is the standard React testing suite which is similar to mocha/chai/assert in the node ecosphere.
react-native-testing-library - allows us to query components and the value/text render that the component should have. You can find more info or the docs
in the PR - we have included one test to get you setup, you should be able to continue with the other components.
import React from "react";
import { render } from "react-native-testing-library";
import { InputText } from "../formComponent/text";
describe("render app components", () => {
it("should render text", () => {
const props = {
upsideEmit: () => {},
textInputStyle: [],
value: "Hello World",
};
const component = render(<InputText {...props} />);
expect(component.toJSON()).toMatchSnapshot();
expect(component.getByDisplayValue("Hello World")).toBeDefined();
});
});
We're able to
1. assert whether the component.toJSON matches the snapshot
expect(component.toJSON()).toMatchSnapshot();
2. given props with value `"Hello World" we can assert that the displayValue is rendered.
const props = {
upsideEmit: () => {},
textInputStyle: [],
value: "Hello World",
};
const component = render(<InputText {...props} />);
expect(component.getByDisplayValue("Hello World")).toBeDefined();
in relation to how you test your components - you should be able to:
check if the component renders.
determine based on the props, that the component renders.
2.1. success case.
2.2. error case.
2.3. normal case.
You may want to add integration tests (e.g. userflow
render component -> interact with component -> check above test cases) more details in terms of libraries can be found on this previous stackoverflow question

You need some kind of end-to-end test if you want to run the app, and ensure it doesn't crash.
Have a look at Cypress (http://cypress.io) or webdriverio (http://webdriver.io)
Cypress has docs on setting up with CI/CD https://docs.cypress.io/guides/guides/continuous-integration.html#Setting-up-CI
Edit... Sorry I missed the react-native part. The above would work for web apps, have a look at something like Detox for React Native (https://github.com/wix/Detox)

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/

In React, making contents of a component available to child components without relying on a chain of props

I have kind of a unique situation. I'm building a react app with a web version and a desktop version (run by NW.js). They essentially have the same UI, but there are some differences in functionality between the desktop and the web version. I want to reuse the exact UI code base, but depending on whether its web or local, wrap the component with another component that provides the necessary differing functionality. (As an example of this, there's a button that launches a desktop process. If you're on web and you click the button, it will use a URL schema to launch the local app and then run it, but if you're local it'll just run it).
The idea is that the function that either launches the app through the URL schema or simply launches the desktop process will be referenced in the single UI codebase, but do nothing unless the alternate functionality is provided by the wrapper component.
The question I have is, how can I get the functionality in the wrapper component to the correct child component without having to pass it down through a chain of props from top to bottom? I'm thinking of, for example, how Provider works in React-redux, making the store available to the other components without relying on props, provided you use the proper functions/hooks to access it.
I hope my explanation of what I'm thinking is clear. Please let me know if I need to explain more.
Context is the React sanctioned way of doing things:
// MyWrapperComponent.js
import { createContext } from 'react';
const MyAppContext = createContext();
const MyWrapperComponent = () => {
return (
<MyAppContext.Provider value={someValue}>
<App/>
</MyAppContext.Provider>
);
};
// SomeDeeplyNestedComponent.js
const SomeDeeplyNestedComponent = () => {
const thing = useContext(MyAppContext);
return <Something/>
}

How to check/test the output of a function without compiling the app in React?

Let's say that I have a class in javascript with a method that takes a number and multiplies it by two:
class Foo {
timesTwo(n) {
return n * 2;
}
...
}
const foo = new Foo();
foo.timesTwo(2); // returns 4
What I'd normally do if I wanted to check the output would be to run node foo.js and see the output on my console.
Now I'm going to use a real life example in React, I'm trying to query something from my database (in this case firebase), It'll look something like this:
import firebase from 'firebase'
import 'firebase/firestore';
class User {
constructor() {
this.auth = firebase.auth();
this.db = firebase.db();
}
getUsers() {
// code that queries the db for
// all users and returns them
}
...
}
const user = new User();
user.(getUsers); // returns all users
If I wanted to quickly check the output of that method my original approach doesn't work (probably because this is more than just vanilla javascript), if I try to run node user.js a bunch of errors regarding the imports and ems modules appear.
My biggest delay while programming is having to test the output of something; waiting for the app to compile and then going to that specific screen (react & react-native) to see what the console.log() says. My question is: is there any way I could get the output of a specific function / method without having to compile my entire app?
I've tried solving the issues with the ems modules by importing the libraries by specific path with no luck. And I've checked some testing libraries, most of which specify that their main goal is to test user-related interactions and not functions or methods, but if there's any way that I could use one of these libraries to get the output of a method inside a class based component or a functional component without doing the steps I described above that'll save me incredible amounts of time. So far I haven't been able to find examples on how to do this with a testing library.
If the output is determined by a specific set of user interaction, it is tough to avoid doing it without compiling the entire app. Your suggested way of console.log right before the return method would work, otherwise places you can insert a console.log can be in componentDidMount and componentDidUpdate. This is an ES6 approach to testing things.
If the output is very easily replicable, and able to be encapsulated into an API instead of a client app interaction, I recommend you just do it as a regular NodeJS project preferably in your backend, especially when the logic is rather heavy and requires more testing. That would allow you to use your node user.js method on the command line. This is an ES5 approach to testing things.

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.

Categories

Resources