Node.js+React automating tests with Jest - javascript

Edit (07/02/2015)
Found out what I was doing wrong. Leaving this for reference if anyone stumbles upon the same issue. Check my answer bellow.
I am currently trying to test my Node.js+React components using Jest. I've installed jest-cli and created a task on my gulpfile to run 'npm test'.
I somehow followed the instructions found here: http://www.undefinednull.com/2015/05/03/react-tdd-example-unit-testing-and-building-a-react-component-with-jest-gulp-and-react-test-utils/
And went to the project git repo to find how to configure some other stuff.
When I run the command 'gulp test' however, apparently all I get is the eslint code validation. I don't think my tests are running at all.
my relevant folder structure is as follows:
/__tests__
searchComponent-spec.js
/src
/components
/Search
Search.js
package.json
gulpfile.babel.js
there are many other stuff but I don't believe they are relevant.
My Search.js
/*! React Starter Kit | MIT License | http://www.reactstarterkit.com/ */
import React, { PropTypes } from 'react';
import styles from './Search.less';
import withStyles from '../../decorators/withStyles';
import Link from '../../utils/Link';
#withStyles(styles)
class Search {
static contextTypes = {
onSetTitle: PropTypes.func.isRequired
};
render() {
let title = 'Pesquisa de desenvolvedores';
this.context.onSetTitle(title);
return (
<div className="Search">
<div className="Search-container">
<a className="Search-brand" href="/" onClick={Link.handleClick}>
<span className="Search-brandTxt">Dev-Shop</span>
</a>
<div className="Search-banner">
<h1 className="Search-bannerTitle">Loja de desenvolvedores</h1>
</div>
</div>
</div>
);
}
}
export default Search;
My searchComponent-spec.js:
/**
* Created by urielbertoche on 02/07/15.
*/
"use strict";
jest.dontMock('../src/components/Search/Search.js');
describe('Search', function () {
var React = require('react/addons');
var TestUtils = React.addons.TestUtils;
var Search;
beforeSearch(function () {
Search = require('../src/components/Search');
});
it('should exists', function () {
// Render into document
var search = TestUtils.renderIntoDocument(<Search />);
expect(TestUtils.isCompositeComponent(search)).toBeTruthy();
});
});
anyone got any idea why my tests may not be running?
Thanks a lot

I found the problem. My package.json had an entry:
"jest": {
"rootDir": "./src",
"scriptPreprocessor": "../preprocessor.js",
"unmockedModulePathPatterns": [
"../node_modules/react"
]
},
what I screwed up was that my tests folder was not on the same rootDir declared there, it was on it's parent, moving the tests folder into my src folder fixed it.

Related

How to use vue-toastification

I just migrated my project created in vue 3 to nuxt 3. Previously I used the vue-toastification module but now I don't know how to import it correctly. My code using this module.
import { useToast, POSITION } from 'vue-toastification'
const toast = useToast()
export default {
methods: {
copy(text) {
toast.success('Copied!', {
timeout: 2000,
position: POSITION.BOTTOM_CENTER,
})
navigator.clipboard.writeText(text)
}
}
}
In Vue I had to do app.use(Toast) but Nuxt does not have an index.js file. Adding modules: ['vue-toastification/nuxt'] in nuxt.config.js does not work because I get an error.
Answers suggested by kissu and Ricardo de Paula worked for me while I was using development server (npm run dev).
After building and running the project I encountered error 500:
Named export 'useToast' not found. The requested module 'vue-toastification' is a CommonJS module, which may not support all module.exports as named exports. CommonJS modules can always be imported via the default export, for example using: import pkg from 'vue-toastification';
To fix this, I registered toast as plugin helper (I'm using Nuxt 3.1.1 with Nitro 2.1.1):
Inside vue-toastificaton.client.js:
import { defineNuxtPlugin } from '#app'
import * as vt from 'vue-toastification'
import '#/assets/css/toast.scss'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(vt.default)
return {
provide: {
toast: vt.useToast()
}
}
})
Then in my component script setup:
//throws an error after production build
//import { useToast } from 'vue-toastification'
//const toast = useToast()
//toast.success('Yay!!!')
//works after production build
const { $toast } = useNuxtApp()
$toast.success('Yay!!!')
If you want it to be available globally, you can install it as a Nuxt plugin as explained in the official docs or in this other answer.
vue-toastification is probably a client-side only plugin, hence you would probably want to use it as
/plugins/vue-toastificaton.client.js like this
import { defineNuxtPlugin } from '#app'
import Toast from "vue-toastification"
import "vue-toastification/dist/index.css" // if needed
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(Toast)
})
Then, you should be able to use it in your components with either Composition API or Options API (I think).
I was wanting to do the same thing. I read kissu's answer and did the following:
1 - I created a folder for the puglin - plugins
2 - Inside the plugins folder I created a file called vue-toastificaton.client.js
Inside vue-toastificaton.client.js:
import { defineNuxtPlugin } from '#app'
import Toast from 'vue-toastification'
import 'vue-toastification/dist/index.css' // if needed
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(Toast)
})
And I used it that way:
<script setup>
import { useToast } from 'vue-toastification'
const toast = useToast()
const onSubmit = () => {
// use the toast notification plugin to show a success message
toast.success('Hello world!')
}
</script>

Got the error "Build optimization failed: found page without a React Component as default export in pages/" Help me

In developer mode worked great. Later in CMD, I sent "npm run build. Got error...
info - Checking validity of types
info - Creating an optimized production build
info - Compiled successfully
> Build optimization failed: found pages without a React Component as default export in
pages/js/TimeClock
pages/js/ChangePage
I tried to fix it. Nothing on the internet helped. Here are my files:
index.js
import Head from 'next/head'
import Time from './js/TimeClock.page';
import { ChangePage0, ChangePage1, ChangePage2 } from './js/ChangePage.page';
export default function Home() {
...
}
TimeClock.page.js
import ReactDOM from 'react-dom'
export function tick()
{
const site = (
<div>
<span className="time">
{new Date().toLocaleTimeString()}
</span>
</div>
);
ReactDOM.render(site, document.getElementById('time'));
}
setInterval(tick, 1000);
next.config.js
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
module.exports = {
pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'], nextConfig
}
Not sure to understrand what you're trying to do with the setIinterval on a component but you probably need to export default instead of a naming export.
In TimeClock.page.js
function Tick() {
...
}
export default Tick;

Working Vue 3 app empties mounted element when using Vue as an npm package

I'm working with a very simple Vue 3 app, listed below.
This works like a charm when including Vue as a script, see code snippet.
I need to use it with webpack however, and therefore include it as an npm package.
In this case the app loads, but Vue empties everything inside the div it's mounted on.
See CodeSandbox example
I've tried different ways to export and import the App object, but none work.
What am I overlooking?
const {ref} = Vue;
const App = {
setup() {
const count = ref(0);
const inc = () => {
count.value++;
};
return {count, inc};
}
}
Vue.createApp(App).mount('#simple-example')
<head>
<script src="https://unpkg.com/vue#3.2.29/dist/vue.global.prod.js"></script>
</head>
<body>
<div id="simple-example">
<h1>Hello Vue 3!</h1>
<button #click="inc">Clicked {{ count }} times.</button>
</div>
</body>
Changing this:
import { createApp } from "vue";
into this:
import { createApp } from "vue/dist/vue.esm-bundler";
fixed the problem. Thanks to Estus Flask
UPDATE
The fix can be further improved by creating an alias for vue in the webpack config file:
resolve: {
alias: {
vue: "vue/dist/vue.esm-bundler.js"
}
}
That will make it possible to use "vue" again in the import statement, which then points to the vue.esm-bundler.js instead of the default vue.runtime.es.js.

Error when run the test "Cannot find module "

I am new to writing Unit tests and i am trying to write unit tests to my react application using testing-library/react and jest
Here is the test code "Home.test.js"
import React from 'react';
import {render, cleanup} from '#testing-library/react';
import '#testing-library/jest-dom/extend-expect';
import Home from "../src/Home";
afterEach(cleanup);
describe("Tests for HomePage", function() {
it("should render without throwing an error", function() {
const { homePage } = render(<Home />);
//check something here
});
});
Here is my code in component "Home.js"
import * as React from "react";
import { Panel, Shell, Button } from "#myorg/core";
import { home_icon, new_icon } from "#myorg/icons";
function Home(props) {
const openDialog = React.useCallback(() => {
//do something
});
return (
<Shell.Page breadcrumbs={[t("demo:Home")]}>
<Panel style={{ height: "100%" }}>
<h2>App Header</h2>
<Button onClick={openDialog} variant="primary">
<img src={new_icon} width="20" />
{t("demo:New Asset")}
</Button>
</Panel>
</Shell.Page>
);
}
error I get when I run "npm run test"
Cannot find module '#myorg/icons' from 'Home.js'
I believe you are trying to use the tsconfig.json options paths, which will be ignored by jest (or by other testing frameworks). You need to manually replicate all your paths definition in jest.config.js and manually keep them updated using the jest config option moduleNameMapper like this:
moduleNameMapper: {
// translate all your custom paths here, read the doc in the link above
'^#finder/(.*)$': '<rootDir>/files-manipulation/$1',
'^#metadata/(.*)$': '<rootDir>/folder-metadata/$1',
'^#logger/(.*)$': '<rootDir>/logging/$1',
// ...and so on
},

Unexpected undefined while import with Webpack

I have a problem that has never happened to me before: I'm compiling a little basic starter browser web app (with React) using Webpack + Babel 7.
I've got three different file:
withAuth.js The Auth High Order Component
NavBar.js The NavBar Component
Login.js The Login Form
If I import the withAuth HOC in the NavBar is everything alright, but if I import the withAuth component in the Login.js file it return undefined
/** withAuth.js */
console.log('withAuth Loaded');
const withAuth = Child => ChildProps => (
<AuthContext.Consumer>
{ authClient => <Child {...ChildProps} authClient={authClient} }
</AuthContext.Consumer>
)
export { withAuth };
/** NavBar.js */
import { withAuth } from 'HOC/Auth';
console.log('NavBar Loaded', withAuth); // <- My HOC
const NavBarComponent = (authClient) => { /* ... My Code ... */ }
const NavBar = withAuth(NavBarComponent);
export default NavBar;
/** Login.js */
import { withAuth } from 'HOC/Auth';
console.log('Login Loaded', withAuth); // <- undefined ??
const LoginFormComponent = (authClient) => { /* ... My Code ... */ }
const LoginForm = withAuth(LoginFormComponent);
// /|\
// |
// Will produce an Error, withAuth is Undefined
This is my Webpack Configuration:
/** webpack.config.js */
module.exports = {
entry: { core: 'index.js' },
resolve: {
alias: {
HOC: './path/to/hoc/folder'
}
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all'
}
},
plugins: [ /* Various Plugin */ ],
module: {
rules: [ /* My Rules */ ]
}
}
Any one know why my HOC is undefined?
Edit:
I've placed Console Log in the tree file. The result are:
'Login Loaded' - undefined
'withAuth Loaded'
'NavBar Loaded' - function() { }
Edit 2:
This is the files structure:
app/
|-high-order-component/
| |-auth/
| |-withAuth.js
|
|-layout-component/
| |-navbar/
| |-index.js
|
|-pages/
|-auth/
|-login.js
Resolved
After much testing and research throughout the afternoon I came to the solution of the problem. As I said in the question, mine is a larger project and I only partially wrote its structure because I thought the problem was located in those three files.
In reality, the problem was a Circular Dependency problem and not a Webpack configuration problem.
In my project I have a module called 'Route' that store all Path and all Component for Path, so I can build the React Router using Array Map function. That module has a function that allow me to Route through path and that can return me a path string to a Component.
My problem was due to the fact that this module is often called in the project and this has created a Circular Dependency.
Webpack doesn't show the Circular Dependency during compiling, but I found useful adding a plugin, called CircualDependencyPlugin. This plugin will break Webpack compiling when a Circual Dependency will be found.
Splitting the Route module into two files solved my problem.

Categories

Resources