Turning an ES5 React + Flux dispatcher test into ES6 fails - reactjs

Their __tests__/TodoStore-test.js file:
https://github.com/facebook/flux/blob/master/examples/flux-todomvc/js/stores/tests/TodoStore-test.js
And their js/dispatcher/AppDispatcher.js file:
https://github.com/facebook/flux/blob/master/examples/flux-todomvc/js/dispatcher/AppDispatcher.js
In their case, the dispatcher is simply this:
var Dispatcher = require('flux').Dispatcher;
module.exports = new Dispatcher();
And in their test's beforeEach it resets:
AppDispatcher = require('../../dispatcher/AppDispatcher');
Now, in my own project I'd like to use ES6's way of doing things. I'm not sure how, though. The differences between require and import elude me.
My dispatcher:
import { Dispatcher } from 'flux';
var dispatcher = new Dispatcher({
logLevel: 'ALL'
});
export default dispatcher;
Which–as a piece in the app–works fine in my app, but the require example above isn't having it.
The part of the test that needs to be converted to ES6's import:
beforeEach(function() {
AppDispatcher = require('./../src/dispatcher/dispatcher');
TodoStore = require('./../src/stores/TodoStore');
callback = AppDispatcher.register.mock.calls[0][0];
});
But, of course, this does not work:
beforeEach(function() {
AppDispatcher = import './../src/dispatcher/dispatcher';
// snip
});
Or:
import dispatcher from './../src/dispatcher/dispatcher';
beforeEach(function() {
AppDispatcher = new dispatcher();
// snip
});
I'm just doing by trial and error now and it's taking way too much time just to write a test.
My thought process:
They require whatever their dispatcher file outputs, which is always a new Dispatcher().
In my case, I'm creating a new Dispatcher and export that instance. Instead, I'd probably need to not instantiate it in the dispatcher file, but leave that up to the export, e.g.: export default new Dispatcher(), but that looks awful.
But no matter what I try I keep getting errors like:
TypeError: Cannot read property 'register' of undefined
Does anybody have a clue how to get this one up and running?
Much obliged!

The ES6 import Syntax is actually import defaultMember from 'module-name';
So in your case it would be
import AppDispatcher from './../src/dispatcher/dispatcher';
import TodoStore from './../src/stores/TodoStore';
For further info on ES6 import read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

Related

renderHook in context wrapper function only works when at the top of imports

So I sort of found a fix for this, but I want to understand what's happening and why.
The background is that I'm testing some classes, each class has a field for the result of a hook for reasons that aren't relevant here. All that happens with the hook in the constructor of each class is that it gets assigned to the member variable.
In order to test each of these classes, I had originally mocked out a few things so that the hook behaved just like a normal function, and that worked fine. But then I discovered the renderHook feature of react testing library and figured it was probably better to use a mature tool instead.
The hook depends on a react context, so I followed the instructions and created this helper function to get my hook
import { mockContext } from './mockContext';
import { renderHook } from '#testing-library/react';
import { OAuthRequests } from '../lib/core/models/auth/OAuthRequests';
import { useOAuth } from '../lib/core/hooks/useOAuth';
import { ClientConfig } from '../lib/core/models/auth/RedditConfig';
export const mockClient: ClientConfig = { clientId: '', clientSecret: '' };
export const mockOAuth = () => {
const wrapper = mockContext();
const {
result: { current: requests },
} = renderHook<OAuthRequests, ClientConfig>(() => useOAuth(mockClient), { wrapper });
return requests;
};
The problem came when I refactored these test suites, all of which were passing. ONLY those suites which were subclasses of one particular superclass were failing. The message with the failure was
TypeError: Class extends value undefined is not a constructor or null
mockOAuth works just fine in every test suite except the ones that extend a certain abstract superclass. I get no runtime errors in my actual app using any of these classes, and like I said, before refactoring to use renderHook it was also all working fine with passing tests. Also, the error seemed to happen at the import stage, not at construction of any objects.
So, after a lot of debugging and trial and error, I discovered that if I placed my import of mockOAuth at the top of the file above the class imports, it works, but if it's below them, it breaks.
It's great that I have a working solution, but I really want to understand why this is happening in case it is a canary for some very obscure bug in my code that won't pop up easily.
Also, I'm tagging the hooks testing library as well here, but I am using react testing library 13.4.0 and react 18.1.0.

What is the equivalent of Java singleton in React Native?

Actually I am a Android Native Developer. I am new to React-Native. In Java i keep the users data and others data in Singleton Class and access from other activities. Then how i achieve this process in React native for access data's from other components or any alternative of singleton in React native.
I just try this but i received the error like getInstance() not defined.
class AppDelegate {
log = "This is AppDelegate";
static myInstance = null;
static getInstance() {
if (AppDelegate.myInstance == null) {
AppDelegate.myInstance = new AppDelegate();
}
return this.myInstance;
}
}
Thank you.
React is UI library, this isn't its responsibility. The question affects any JavaScript application, not only React.
JavaScript modules and ES modules in particular are evaluated only once under normal circumstances, this makes exports singletons:
// exported for extensibility
export class AppDelegate {...}
// a singleton
export default new AppDelegate;
Singleton class is potentially an antipattern in JavaScript. If there's a need for one object, it could be written as object literal.
Imports are cached, so if you export a class, the class will be cached, if you export an instance, the instance will be cached
If you need a singleton don't use a class at all.
Export the methods as a function instead.
// File app-delegate.js
let privateIstanceValue;
export const method1 = () => //do something;
export const method2 = () => //do something again;
Import using import * as
import * as appDelegate from './app-delegate.js';

Sonarqube : Create a custom page using react

I would like to create a custom page using react but I cannot find the documentation to do this. On the Sonarqube documentation, there only the way to create a custom page using javascript only and I don’t understand how the example plugin works with react.
Can you tell me if there is a documentation that I can use.
Short answer: There isn't. There is barely anyone (no one in fact, as far as I've seen) using custom pages currently.
However, it IS possible. You need to create a react project with Webpack (or a similar JS packager).
I also recommend using Create-React-App. This fixes a lot of the setup for you. After that, in your index.js you use the example code from the SonarQube wiki.
Here is an example:
/*
PRODUCTION ENTRYPOINT
*/
import React from 'react';
import ReactDOM from 'react-dom';
import Project from './components/Project';
import './main.css';
window.registerExtension('myplugin/coverage', function (options) {
appendCustomCSS();
let isDisplayed = true;
window.SonarRequest.getJSON('/api/measures/component', {
component: options.component.key,
metricKeys: 'coverage'
}).then(function (response) {
if (isDisplayed) {
let obj = JSON.parse(response.component.measures[0].value);
let div = document.createElement('div');
render(obj, div);
options.el.appendChild(div);
}
});
return function () {
isDisplayed = false;
};
});
function appendCustomCSS() {
let fileref = document.createElement("link");
fileref.setAttribute("rel", "stylesheet");
fileref.setAttribute("type", "text/css");
fileref.setAttribute("href", "/static/myplugin/coverage.css");
document.head.append(fileref);
}
function render(objectArray, container) {
ReactDOM.render(<div className="Coverage"><Project objects={objectArray}/></div>, container);
}

Using Browserify to create React Bundle

It's the same question as here, but I don't understand the answer. So, my question is about the answer.
The answer is
Your react.js file/module isn't exposing the variables React and
ReactDOM you instantiate. In node, you make these methods public by
modifying the module.exports object like so:
module.exports = { React: React, ReactDOM: ReactDOM }
Finally, my question is: Where do "you make these methods public"?
You are making these methods public by defining them on the module.exports property. For instance, say you have a file reactExports.js with
var iWontGetThere = 'I am in this module only';
module.exports = { React: React, ReactDOM: ReactDOM }
now in another file, you can require these methods and use them, like so:
var React = require('reactExports').React;
var SweetComponent = React.createClass({
render: function() {
return (
<div>React is cool and I can use it in here!</div>
);
}
});
module.exports = SweetComponent;
Now imagine you want to render SweetComponent in another component. If I hadn't written module.exports = SweetComponent, requiring this module in another component would have no effect as all as you would be importing an empty object {}.
Let's say I tried to console.log(React.iWontGetThere); What would happen? I would get a reference error, as it was not exported with the contents of reactExports.js-it only exists in that module, but it is not exposed.
This is a contrived example, but the interesting story here is the ability to bring in encapsulated modules. I suggest reading more about node modules here
and checking out this answer as well.
and making some examples to get the hang of it.
tl;dr: defining variables and not having a module.exports = some_value statement then requiring that same file will default to an empty object.

React Mocha rendering, DOMException Wrong Document

Using React 13.2 and looking to test lifecyles with a setup like the one shown on this gist. If I don't stop subsequent renders (via the shouldComponentUpdate method) then anything causes a render (after the initial) explodes with a DOMException Wrong Document:
DOMException: Wrong document
at core.Node.insertBefore (D:\development\projects\fsm\node_modules\jsdom\lib\jsdom\level1\core.js:583:13)
at core.Node.insertBefore (D:\development\projects\fsm\node_modules\jsdom\lib\jsdom\level2\events.js:326:32)
at insertChildAt (D:\development\projects\fsm\node_modules\react\lib\DOMChildrenOperations.js:34:14)
at Object.DOMChildrenOperations.processUpdates (D:\development\projects\fsm\node_modules\react\lib\DOMChildrenOpertions.js:106:11)
JSDOM bails because the parent node is not a document and it don't share the same owner document as the child being inserted. Yeah. How could the owning document be anything other than that the global unless React is doing something funky under the hood.
Just surprised that I don't see more people having a similar problem? There is nothing odd-ball with my Mocha setup nor the JSX components being rendered. Plus the initial render goes fine.
Update for node 4
With node 4 we can use the latest jsdom and solve this issue in a better way, e.g. using testdom.
This is how I test a React 0.13 component with mocha on node 4:
import testDom from "testdom";
import { expect } from "chai";
testDom("<html><body></body></html>");
const React = require("react/addons");
const MyTestableComponent = require("../src/MyTestableComponent");
const ExecutionEnvironment = require("react/lib/ExecutionEnvironment");
ExecutionEnvironment.canUseDOM = true;
describe("MyTestableComponent", () => {
it("works!", () => {
const component = <MyTestableComponent />;
expect(true).to.equal(true);
})
})
Note that we should require rather than import React and the component.
Previous answer
I could fix this issue by following the OP's own comment to the question.
Since React stores the document in an internal variable when it is required, we need to remove React from the require.cache object, before requiring it again:
var jsdom = require("jsdom").jsdom;
var React, TestUtils;
describe("Example", function() {
beforeEach(function() {
// remove react from the require cache
for (var key in require.cache) {
if (key.match(/\/node_modules\/react\//)) {
delete require.cache[key];
}
}
// init the DOM
global.document = jsdom("<html><head><script></script></head><body></body></html>");
global.window = document.parentWindow;
// require react again
React = require("react/addons");
TestUtils = React.addons.TestUtils;
});
// my tests...
});

Resources