Testing NextJS and Jest ReferenceError: TextEncoder is not defined - next.js

I am getting this error message while trying to learn how to test next.js applications
I have tried import the Text Encoder from utils at the top of the config as well as test file with no success
ReferenceError: TextEncoder is not defined
at Object.<anonymous> (node_modules/whatwg-url/lib/encoding.js:2:21)
at Object.<anonymous> (node_modules/whatwg-url/lib/url-state-machine.js:5:34)
at Object.<anonymous> (node_modules/whatwg-url/lib/URL-impl.js:2:13)
at Object.<anonymous> (node_modules/whatwg-url/lib/URL.js:442:14)
at Object.<anonymous> (node_modules/whatwg-url/webidl2js-wrapper.js:3:13)
at Object.<anonymous> (node_modules/whatwg-url/index.js:3:34)
at Object.<anonymous> (node_modules/mongodb-connection-string-url/src/index.ts:1:1)
at Object.<anonymous> (node_modules/mongodb/src/connection_string.ts:3:1)
at Object.<anonymous> (node_modules/mongodb/src/mongo_client.ts:11:1)
at Object.<anonymous> (node_modules/mongodb/src/change_stream.ts:17:1)
at Object.<anonymous> (node_modules/mongodb/src/index.ts:3:1)
at Object.<anonymous> (node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js:8:16)
at Object.<anonymous> (node_modules/mongoose/lib/drivers/node-mongodb-native/index.js:7:18)
at Object.<anonymous> (node_modules/mongoose/lib/index.js:7:25)
at Object.<anonymous> (node_modules/mongoose/index.js:8:18)
at Object.<anonymous> (library/mongoDB.js:15:56)
at Object.<anonymous> (library/players.js:15:18)
at Object.<anonymous> (pages/index.js:18:18)
at Object.<anonymous> (tests/index.test.js:6:53)
Jest Config File
const nextJest = require('next/jest')
const createJestConfig = nextJest({
dir: './',
})
const customJestConfig = {
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
}
module.exports = createJestConfig(customJestConfig)
Package.json
"devDependencies": {
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"eslint": "8.23.1",
"eslint-config-next": "12.3.0",
"jest": "^29.1.1",
"jest-environment-jsdom": "^29.1.1"
}
index.test.js
import Home from '../pages/index'
import '#testing-library/jest-dom'
import { fireEvent, render, screen } from '#testing-library/react'
describe('Home Page', () => {
it('renders home component',
() => {
render(<Home />)
expect(screen.getByTestId('home-page')).toBeInTheDocument()
})
})

I would do it by mocking TextEncoder on a dedicated file which will be placed as a setup file on jest config.
This way I think you should get rid of that error.
// text-encoder.mock.ts
import { TextEncoder } from 'util';
global.TextEncoder = TextEncoder;
// jest.config.ts
const nextJest = require('next/jest');
const createJestConfig = nextJest({
dir: './',
});
const customJestConfig = {
moduleDirectories: ['node_modules', '<rootDir>/'],
testEnvironment: 'jest-environment-jsdom',
setupFiles: [
'<rootDir>/path/to/text-encoder.mock.ts',
],
};
module.exports = createJestConfig(customJestConfig)

Related

I have an error when migrating from Laravel mix to Laravel vite, I think the problem is in the app.js also I am using vue laravel sail WSL 2 and doock

this is the error that shows when i run the npm run dev after deleting all the laravel mix plugin etc
failed to load config from /var/www/html/vite.config.js
error when starting dev server:
Error: Cannot find module 'laravel-vite-plugin'
Require stack:
- /var/www/html/vite.config.js
- /var/www/html/node_modules/vite/dist/node/chunks/dep-5e7f419b.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1039:15)
at Module._load (node:internal/modules/cjs/loader:885:27)
at Module.require (node:internal/modules/cjs/loader:1105:19)
at require (node:internal/modules/cjs/helpers:103:18)
at Object.<anonymous> (/var/www/html/vite.config.js:36:42)
at Module._compile (node:internal/modules/cjs/loader:1218:14)
at _require.extensions.<computed> [as .js] (file:///var/www/html/node_modules/vite/dist/node/chunks/dep-5e7f419b.js:62103:24)
at Module.load (node:internal/modules/cjs/loader:1081:32)
at Module._load (node:internal/modules/cjs/loader:922:12)
at Module.require (node:internal/modules/cjs/loader:1105:19)
#[tag:error]
app.js with all required changed with inport + in my project there is not a bootstrap.js folder or a app.css file
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
import * as Vue from 'vue';
import * as VueRouter from 'vue-router';
import routes from './routes';
import axios from 'axios'
import VueAxios from 'vue-axios'
import Form from './utilities/Form';
import lodash from 'lodash';
import VueAutosuggest from "vue-autosuggest";
import BootstrapVue3 from 'bootstrap-vue-3'
import mitt from 'mitt';
import Vuetable from 'vue3-vuetable';
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue-3/dist/bootstrap-vue-3.css'
import VueSweetalert2 from 'vue-sweetalert2';
import 'sweetalert2/dist/sweetalert2.min.css';
import Toast, { POSITION } from "vue-toastification";
import "vue-toastification/dist/index.css";
import VueApexCharts from "vue3-apexcharts";
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes,
});
const emitter = mitt();
export default router;
const app = Vue.createApp({});
app.config.performance = true;
import('./functions').functions(app);
app.config.globalProperties.emitter = emitter;
app.use(router);
app.use(VueAxios, axios);
app.use(VueAutosuggest);
app.use(lodash)
app.use(BootstrapVue3)
app.use(Vuetable)
app.use(Toast, {
position: POSITION.BOTTOM_RIGHT
});
app.use(VueApexCharts);
app.use(VueSweetalert2);
import lodash from 'lodash';
import axios from 'axios';
window.Form = Form;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
//LOGIN COMPONENTS/PARTIALS//
app.component('login-header', require('./components/login-header').default);
app.component('fill-email', require('./components/Partials/fillEmail').default);
app.component('side-bar', require('./components/Partials/side-bar').default);
app.component('top-nav-bar', require('./components/Partials/top-nav-bar').default);
app.component('laravel-pagination', require('./components/Partials/laravel-pagination').default);
app.component('row-height', require('./components/Partials/row-height').default);
app.component('validation-errors', require('./components/Partials/validation-errors').default);`
file containing vite.config.js with plugin for vue and vite
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
// import react from '#vitejs/plugin-react';
import vue from '#vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
// react(),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
resolve: {
alias: {
'#': '/resources/js'
}
}
});

Storybook gives error on hotreload in Nextjs with Material ui 5

When I refresh the page, I get correct component loaded up. If the component is Typography and i edit a text. It works fine. The error occurs when i change Typography to Button component. Tried storybook-addon-next-material-ui. Same error there
index.js:56 Unexpected error while loading ./pages/test.stories.tsx: Cannot read properties of undefined (reading 'call')
TypeError: Cannot read properties of undefined (reading 'call')
at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6006/runtime~main.iframe.bundle.js:339:21)
at ./components/test-component.tsx (http://localhost:6006/main.436c782e1c77c7940bf8.hot-update.js:14:71)
at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6006/runtime~main.iframe.bundle.js:339:21)
at ./stories/pages/test.stories.tsx (http://localhost:6006/main.iframe.bundle.js:44:84)
at __webpack_require__ (http://localhost:6006/runtime~main.iframe.bundle.js:28:33)
at fn (http://localhost:6006/runtime~main.iframe.bundle.js:339:21)
at webpackContext (http://localhost:6006/main.iframe.bundle.js:118:9)
at http://localhost:6006/vendors-node_modules_mui_material_Button_Button_js-node_modules_storybook_addon-actions_previ-68b32d.iframe.bundle.js:14244:29
.storybook/main.js
module.exports = {
stories: [
'../stories/**/*.stories.mdx',
'../stories/**/*.stories.#(js|jsx|ts|tsx)',
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'storybook-addon-next',
],
framework: '#storybook/react',
core: {
builder: 'webpack5',
},
};
test.stories.tsx
import { TestComponent } from '../../components/test-component';
export default {
title: 'Pages',
component: TestComponent,
};
export const TestScreen = () => <TestComponent />;
test-component.tsx
import { Button, Typography } from '#mui/material';
import React from 'react';
export const TestComponent = () => {
return <Typography>TestComponent</Typography>;
};

NextJS Build Errors with SSR and Styled-Components

I'm deploying a NextJS app to Vercel and I use styled-components. This is my _document.tsx file:
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'
import flush from 'styled-jsx/server'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
})
const initialProps = await Document.getInitialProps(ctx)
const styledJSXStyles = flush()
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
{styledJSXStyles}
</>
),
}
} finally {
sheet.seal()
}
}
}
The error I'm seeing from Vercel is that document is not defined at new StyleSheet:
02:22:23 > Build error occurred
02:22:23 ReferenceError: document is not defined
02:22:23 at new StyleSheet (/vercel/workpath0/node_modules/styled-jsx/dist/lib/stylesheet.js:40:35)
02:22:23 at new StyleSheetRegistry (/vercel/workpath0/node_modules/styled-jsx/dist/stylesheet-registry.js:26:33)
02:22:23 at Object.<anonymous> (/vercel/workpath0/node_modules/styled-jsx/dist/style.js:15:26)
02:22:23 at Module._compile (internal/modules/cjs/loader.js:1063:30)
02:22:23 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
02:22:23 at Module.load (internal/modules/cjs/loader.js:928:32)
02:22:23 at Function.Module._load (internal/modules/cjs/loader.js:769:14)
02:22:23 at Module.require (internal/modules/cjs/loader.js:952:19)
02:22:23 at require (internal/modules/cjs/helpers.js:88:18)
02:22:23 at Object.<anonymous> (/vercel/workpath0/node_modules/styled-jsx/dist/server.js:9:14)
02:22:23 at Module._compile (internal/modules/cjs/loader.js:1063:30)
02:22:23 at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
02:22:23 at Module.load (internal/modules/cjs/loader.js:928:32)
02:22:23 at Function.Module._load (internal/modules/cjs/loader.js:769:14)
02:22:23 at Module.require (internal/modules/cjs/loader.js:952:19)
02:22:23 at require (internal/modules/cjs/helpers.js:88:18)
I was under the assumption that using SeverStyleSheet in my document file would have fixed this situation, but it does not seem to be the case.
Here are the things I've tried since:
Updating _document.tsx (shown above) to support styled-components and styled-jsx (I don't use the latter, this is a dependency part of NextJS and the source of the error)
Attempted to build locally (builds just fine with npm run build)
Check for presence of the window object in index.tsx and _app.tsx
Checking for the presence of window.fetch before calling fetch in any component
Commented out a rendered iFrame w/ dangerouslySetInnerHTML
What have I not yet considered?
You can test your _document.tsx with this example:
import React from 'react'
import Document, {
DocumentContext,
DocumentInitialProps,
Head,
Html,
Main,
NextScript
} from 'next/document'
import { ServerStyleSheet } from 'styled-components'
export default class MyDocument extends Document {
static async getInitialProps(
ctx: DocumentContext
): Promise<DocumentInitialProps> {
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: App => props => sheet.collectStyles(<App {...props} />)
})
const initialProps = await Document.getInitialProps(ctx)
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
)
}
} finally {
sheet.seal()
}
}
render(): JSX.Element {
return (
<Html lang="en">
<Head>
<title>your app title</title>
<meta charSet="utf-8" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
It turns out the issue was with an older version of NextJS, bumping my version from 10.0.6 to 10.0.9 resolved this.

Uncaught TypeError: require.ensure is not a function at Object.getComponent (ECMASCRIPT)

Am porting over my meteor project to use ecmascript instead of using webpack / babel. Also upgrading my meteor (from 1.4 to 1.7) and react (from 15.3.2 to 16.8.6) too.
routes.jsx
import * as React from 'react';
export default function (injectDeps, {Store, Routes}) {
const route = {
path: 'tickets',
onEnter: (nextState, replace) => {
if (!Meteor.userId() || !Roles.userIsInRole(Meteor.userId(), 'staff', Roles.GLOBAL_GROUP)) {
replace('/login');
}
},
getComponent(nextState, cb) {
require.ensure([], (require) => {
Store.injectReducer('tickets', require('./reducers'));
cb(null, require('./containers/list.js'));
}, 'tickets');
},
childRoutes: [
{
path: ':_id',
getComponent(nextState, cb) {
require.ensure([], (require) => {
Store.injectReducer('tickets', require('./reducers'));
cb(null, require('./containers/view.js'));
}, 'tickets.view');
}
}
]
};
Routes.injectChildRoute(route);
}
Got this error:
Uncaught TypeError: require.ensure is not a function
at Object.getComponent (routes.jsx:20)
at getComponentsForRoute (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38035)
at modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38053
at modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37842
at Array.forEach (<anonymous>)
at mapAsync (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37841)
at getComponents (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:38052)
at finishEnterHooks (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37263)
at next (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37810)
at loopAsync (modules.js?hash=d04d5856a2fe2fa5c3dc6837e85d41adc321ecb2:37814
Any suggestion how to port this?
This is how it was done to get rid of require.ensure:
routes.jsx (final)
{
path: 'config',
getComponent(nextState, cb) {
import('./containers/config').then(mod => {
Store.injectReducer('config', require('./reducers/config').default);
cb(null, mod.default);
});
}
}
NOTE:
1) This is how the to migrate from require.ensure (used by webpack) to without relying on webpack (which was my case as am fully using Meteor Atmosphere to run)
2) mod and require(...).xxx had changed to mod.default and require(...).default if reducer function is exported as export default, otherwise said reducer will not be called.

Cannot destructure property `OAuth2` of 'undefined' or 'null'

I am trying run rocket.chat on CentOS 7. But it throw exception:
I20191120-09:44:42.581(7)? Exception in callback of async function: TypeError: Cannot destructure property `OAuth2` of 'undefined' or 'null'.
I20191120-09:44:42.582(7)? at routes.js (app/livestream/server/routes.js:8:27)
I20191120-09:44:42.582(7)? at fileEvaluate (packages/modules-runtime.js:336:7)
I20191120-09:44:42.582(7)? at Module.require (packages/modules-runtime.js:238:14)
I20191120-09:44:42.582(7)? at Module.moduleLink [as link] (/root/.meteor/packages/modules/.0.13.0.1ny9ohg.lqq5++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/reify/lib/runtime/index.js:38:38)
I20191120-09:44:42.582(7)? at index.js (app/livestream/server/index.js:1:8)
I20191120-09:44:42.583(7)? at fileEvaluate (packages/modules-runtime.js:336:7)
I20191120-09:44:42.583(7)? at Module.require (packages/modules-runtime.js:238:14)
I20191120-09:44:42.583(7)? at Module.moduleLink [as link] (/root/.meteor/packages/modules/.0.13.0.1ny9ohg.lqq5++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/reify/lib/runtime/index.js:38:38)
I20191120-09:44:42.583(7)? at importPackages.js (server/importPackages.js:1:1667)
I20191120-09:44:42.584(7)? at fileEvaluate (packages/modules-runtime.js:336:7)
I20191120-09:44:42.584(7)? at Module.require (packages/modules-runtime.js:238:14)
I20191120-09:44:42.584(7)? at Module.moduleLink [as link] (/root/.meteor/packages/modules/.0.13.0.1ny9ohg.lqq5++os+web.browser+web.browser.legacy+web.cordova/npm/node_modules/reify/lib/runtime/index.js:38:38)
I20191120-09:44:42.584(7)? at main.js (server/main.js:1:8)
I20191120-09:44:42.584(7)? at fileEvaluate (packages/modules-runtime.js:336:7)
I20191120-09:44:42.585(7)? at Module.require (packages/modules-runtime.js:238:14)
I20191120-09:44:42.585(7)? at require (packages/modules-runtime.js:258:21)
I20191120-09:44:42.585(7)? at /usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/app/app.js:145189:15
I20191120-09:44:42.585(7)? at /usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/boot.js:419:36
I20191120-09:44:42.585(7)? at Array.forEach (<anonymous>)
I20191120-09:44:42.586(7)? at /usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/boot.js:228:19
I20191120-09:44:42.586(7)? at /usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/boot.js:479:5
I20191120-09:44:42.586(7)? at Function.run (/usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/profile.js:510:12)
I20191120-09:44:42.586(7)? at /usr/app_chat/Rocket.Chat/.meteor/local/build/programs/server/boot.js:478:11
import { Meteor } from 'meteor/meteor';
import google from 'googleapis';
import { settings } from '../../settings';
import { Users } from '../../models';
import { API } from '../../api';
const { OAuth2 } = google.auth;
API.v1.addRoute('livestream/oauth', {
get: function functionName() {
const clientAuth = new OAuth2(settings.get('Broadcasting_client_id'), settings.get('Broadcasting_client_secret'), `${ settings.get('Site_Url') }/api/v1/livestream/oauth/callback`.replace(/\/{2}api/g, '/api'));
const { userId } = this.queryParams;
const url = clientAuth.generateAuthUrl({
access_type: 'offline',
scope: ['https://www.googleapis.com/auth/youtube'],
state: JSON.stringify({
userId,
}),
});
return {
statusCode: 302,
headers: {
Location: url,
},
body: 'Oauth redirect',
};
},
});
API.v1.addRoute('livestream/oauth/callback', {
get: function functionName() {
const { code, state } = this.queryParams;
const { userId } = JSON.parse(state);
const clientAuth = new OAuth2(settings.get('Broadcasting_client_id'), settings.get('Broadcasting_client_secret'), `${ settings.get('Site_Url') }/api/v1/livestream/oauth/callback`.replace(/\/{2}api/g, '/api'));
const ret = Meteor.wrapAsync(clientAuth.getToken.bind(clientAuth))(code);
Users.update({ _id: userId }, { $set: {
'settings.livestream': ret,
} });
return {
headers: {
'content-type': 'text/html',
},
body: '<script>window.close()</script>',
};
},
});
Like https://stackoverflow.com/users/7080548/sebastian-kaczmarek already indicated, you need to replace:
import google from 'googleapis';
with
import { google } from 'googleapis';
Also see
https://www.npmjs.com/package/googleapis#first-example

Resources