So, I am new to React. Apologies if I am missing something obvious, I'm wrestling with a weird issue with my ES6 imports.
I'm using the #typeform/embed module (0.12.1), which oddly links to a GitHub repo on npm but that repo doesn't exist. So I haven't been able to look into potentially related issues.
Anyways, whenever I do the following:
import typeformEmbed from '#typeform/embed'
My text editor shows that the type of typeformEmbed is a string, and when I go to invoke a function on it, it is always undefined. Gives me the 'ole cannot invoke property X on undefined TypeError. It almost looks as if it is trying to import the README?
But, then I opened up my Node REPL and could write:
const typeformEmbed = require('#typeform/embed')
and it works like a charm.
Is there some discrepancy between the two that I am missing?
Edit: I know that this question is pretty text-heavy, let me know if there is crucial information that I'm missing. I should mention that I built this project with create-react-app.
import * as typeformEmbed from '#typeform/embed';
const popUpHandler = () => {
typeformEmbed.makePopup(
'https://admin.typeform.com/to/PlBzgL',
{
mode: 'drawer_left',
autoOpen: true,
autoClose: 3,
hideScrollbars: true,
onSubmit: function () {
console.log('Typeform successfully submitted')
}
}
)}
Should work for you
Related
When ever I try to use require or require.requireActual in jest, to import '#material-ui/icons', jest claims it to be undefined.
I'm guessing this is a bug/issue, as I cant imagine any export to be undefined for require. The file being referenced by this ('#material-ui/icons/index.js') uses code like this to define its exports:
Object.defineProperty(exports, "AccessAlarm", {
enumerable: true,
get: function get() {
return _AccessAlarm.default;
}
});
I know jest does do funky stuff with the base require, perhaps this method of export definition is tripping jest up?
Does anyone have any insight into this, solutions or workarounds, etc?
Also does anybody know of a way to get a list of icons in '#material-ui/icons' given this restriction (get a list of the icons is all I'm trying to do in the first place), and no, I do not want to use a file reader.
To be clear, this is on a simple test file with no mocking.
So I am now using the following solution (automock all material-ui icons) since it looks like jest cant handle them to begin with, so no harm in just permanently automocking them:
const mockIconsList = new Map();
jest.mock('#material-ui/icons', () => new Proxy({__esModule: true}, {
get: (target, prop) => {
if (prop in target)
return target[prop];
if (!mockIconsList.has(prop))
mockIconsList.set(prop, mockComponent(`mockMaterialIcon${prop}`));
return mockIconsList.get(prop);
},
}));
I am still however curious about the above issue and any information regarding it.
Scenario
npm test used to work without issue. Over the course of a month or so (I neglected tests) something changed and now I receive ReferenceError: document is not defined when trying to run Jest-Puppeteer tests via npm test.
This error shows up even with document removed so it seems like a puppeteer issue but I'm not sure why this is showing up now. I've checked out code from over a month ago and the tests still work but so much has changed that it's difficult to chase down the actually issue.
Attempted Solutions
upgrade node
reinstall npm packages
revert jest-puppeteer.config.js to previous version
add #jest-environment jsdom to tests which fixes the document issue but then causes ReferenceError: page is undefined
Question
How can I troubleshoot this problem short of starting over from scratch? That said, I'm prepared to start over if that's what it's going to take, which sometimes it does.
Code
this is a basic jest file
import "core-js/stable";
import "regenerator-runtime/runtime";
import {Provider} from "react-redux"
import mockState from "./mocks/mockState"
import configureStore from "redux-mock-store"
import ShallowRenderer from 'react-test-renderer/shallow'
import API from '../src/API'
import getNavigationResponse from '../src/nocks/getNavigation'
import expectedNavigationState from "./static/expectedNavigationState"
import pageObjects from "./static/pageObjects"
import utils from './utils'
import constants from '../src/constants'
describe('API tests', () => {
beforeEach(async() => {
await page.goto('http://localhost:3000');
await page.setViewport({ width: 900, height: 600 });
await page.goto('http://localhost:3000/');
await page.evaluate(() => {
document.getElementById('root').classList.add('animated-test');
});
await page.waitForSelector(pageObjects.navFactory);
});
// PASS
test('API data to be in store', async () => {
await page.waitForSelector(pageObjects.primaryNavLink);
// get state from root
const store = await utils.getStore();
expect(store[0].navigation.urlHashMap).toEqual(expectedNavigationState);
});
test.todo('Make sure content==true on vanity urls (home)')
test.todo('Make sure content==false on url items with children (visitor)')
// PASS
test('API cancel should cancel the API request', async () => {
API.dispatch = () => {
};
API.fetch(constants.NAVIGATION_HREF, 'API_FETCH_TYPE_NAVIGATION');
const promiseCanceled = API.cancel('API_FETCH_TYPE_NAVIGATION');
expect(promiseCanceled).hasOwnProperty('promise');
expect(promiseCanceled).hasOwnProperty('cancel');
});
});
** EDIT **
From what I can find out, this "ReferenceError" seems to be a babel error that is caused because babel can't seem to figure out what "document" is. I traced down where the issue is happening and it is within a third party plugin so I left a note on the developer's github page in the mean time. Currently my "solution" is to comment this test out - I'll put more effort into this again when I have time to find a proper solution
** EDIT 2 **
If I add <rootDir>/node_modules/react-json-view/dist/main.js to babel config's transformIgnorePatterns then I get a different error of
ReferenceError: regeneratorRuntime is not defined
Which is odd because I explicitly have import "regenerator-runtime/runtime" at the top. This seems to be a step closer but I'm not sure. I switched back to babel-polyfill (deprecated) just to try it but ended with a different error of TypeError: jest: failed to cache transform results.
Normally you can do something like this answer which is to add:
npm test --env=jsdom
But since I also need Puppeteer's environment there's a clash because node only seems to support ONE environment.
Ultimately I removed the troubled plugin.
I'm trying to use the react-csv-reader package in a React project that was created with create-react-app --typescript. Since react-csv-reader doesn't come with a types declaration file, I created one myself. I created a file types/react-csv-reader/index.d.ts. VS Code's Intellisense can find it just fine (I can command-click on the function name in module where I'm using react-csv-reader, and it takes me to my declarations file. It also complains when I don't have all the required props, etc.).
But when I run npm start, I get this:
Failed to compile.
./src/screens/ReadCsv.tsx
Module not found: Can't resolve '../types/react-csv-reader' in '/my/proj/root/src/screens'
Here's my index.d.ts:
import React from 'react'
interface CSVReaderProps {
cssClass?: string
cssInputClass?: string
label?: string
onFileLoaded: (data: any, filename: string) => void
onError: () => void
inputId?: string
inputStyle?: any
parserOptions?: any
}
declare const CSVReader: React.SFC<CSVReaderProps>
export default CSVReader
Because typescript don't know where are your definition files, so you have to tell him in your tsonfig.json.
{
"compilerOptions": {
"typeRoots" : [
"node_modules/#types",
"./your/types/folder"
]
}
}
Note that I added node_modules, otherwise its types are not included.
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#types-typeroots-and-types
The right combination of things to make this work was:
Put everything in index.d.ts inside a declare module 'react-csv-reader' {} block
import it as import CSVReader from 'react-csv-reader' instead of what I was doing, which was import CSVReader from '../types/react-csv-reader'.
I did not have to change anything in tsconfig.json. I still don't understand why it worked before as far as VS Code Intellisense was concerned, but this way works with that and is compiled happily by React.
I use isMobileOnly from "react-device-detect" npm package in my React component say(SampleComponent.js).
I would like to customize the return value of isMobileOnly in my jest unit tests.
I have tried Jest manual mocks as mentioned in the link below:
https://jestjs.io/docs/en/manual-mocks
But it does not seem to work for me.
I have also tried:
jest's mockImplementation
jest's mockImplementationOnce
jest's spyOn
import {isMobileOnly} from 'react-device-detect;
In my jest unit tests, i would like to mock the function isMobileOnly in such a way that i should be able to customize its return value to "true". The default value is "false".
This worked for me.
In your test file, add this: import * as deviceDetect from 'react-device-detect';
then you can change things like: deviceDetect.isMobileOnly = true;
eg.
import * as deviceDetect from 'react-device-detect'; //<--important
it.only('clicking on myAccount redirects to /user/myAccount', () => {
///make sure this is before mount or shallow
deviceDetect.isMobileOnly = true; //<--important
component = mount(<Provider store={store}><Sidebar history={mockedHistory} /></Provider>);
component.find('[test-id="myAccount"]').first().simulate('click');
expect(mockedHistory.push).toHaveBeenCalledWith('/user/myAccount');
});
Finally! I figured it out myself after hours of struggle. Here is what i did:
Created __mocks__ folder in the same level as node_modules directory where the package "react-device-detect" is available. Note: smaller case is important for __mocks__.
Created a file named "react-device-detect.js" within the __mocks__ folder.
Added the following code in it:
const deviceDetect = jest.genMockFromModule('react-device-detect');
deviceDetect.isMobileOnly = true;
module.exports = deviceDetect;
Within the test file, i imported the "isMobileOnly" as i did in the original
component:
import { isMobileOnly } from 'react-device-detect';
Now, i can change value of "deviceDetect.isMobileOnly" to true or false in the
mocked file as per the unit test case's need .
For more details, refer the official documentation here https://jestjs.io/docs/en/manual-mocks
Thanks #Roman for reaching out!
I use the " import * as deviceDetect" answer, it worked but I ran into an issue because of typescript and the readonly property of isMobile.
So this solution worked for me :
Object.defineProperty(reactDeviceDetect, 'isIOS', { get: () => true });
as describe here
I hope that help!
You can possibly override the User Agent for testing purposes so react-device-detect package will identify it like You need, here's how to do that.
This topic should also be helpful.
I've been working on a project using Meteor and React, which needs a PDF viewer with the ability to select text.
I'm currently trying to achieve this with Mozilla's PDF.js, but am having some trouble getting started. I'm a long time reader, first time asker at stackoverflow.
I've installed PDF.js with npm.
npm install pdfjs-dist --save
Now I'm trying to modify the example from pdf.js's github project here to create a React component that will render a PDF from a supplied file path and include a text layer.
imports/ui/components/PDF/PDFText.jsx
import React from 'react';
require ('pdfjs-dist/build/pdf.combined');
require ('pdfjs-dist/web/compatibility');
export default class PDFText extends React.Component {
renderPDF() {
PDFJS.workerSrc = '/node_modules/pdfjs-dist/build/pdf.worker.js';
const container = document.getElementById('pdf-container');
const scale = 1;
const pageNumber = 1;
PDFJS.getDocument(this.props.file).then(function(pdf) {
return pdf.getPage(pageNumber).then(function(page) {
var pdfPageView = new PDFJS.PDFPageView({
container: container,
id: pageNumber,
scale: scale,
defaultViewport: page.getViewport(scale),
textLayerFactory: new PDFJS.DefaultTextLayerFactory()
});
pdfPageView.setPdfPage(page);
return pdfPageView.draw();
});
});
}
render() {
this.renderPDF()
return (
<div id='pdf-container'></div>
);
}
}
If I include this component in page I get the following error:
Uncaught (in promise) TypeError: PDFJS.DefaultTextLayerFactory is not a constructor
The next thing I tried was including 'pdfjs-dist/web/pdf_viewer' in my code, as this is where DefaultTextLayerFactory is declared. I modified the code above to add the following line above the class declaration:
require ('pdfjs-dist/web/pdf_viewer');
When I run the code now, I get a different error.
Uncaught TypeError: Cannot read property 'PDFJS' of undefined
at Object.<anonymous> (modules.js?hash=9dd20a3…:114918)
at __w_pdfjs_require__ (modules.js?hash=9dd20a3…:114838)
at Object.<anonymous> (modules.js?hash=9dd20a3…:117449)
at __w_pdfjs_require__ (modules.js?hash=9dd20a3…:114838)
at Object.<anonymous> (modules.js?hash=9dd20a3…:118157)
at __w_pdfjs_require__ (modules.js?hash=9dd20a3…:114838)
at module.exports (modules.js?hash=9dd20a3…:114884)
at modules.js?hash=9dd20a3…:114887
at webpackUniversalModuleDefinition (modules.js?hash=9dd20a3…:114811)
at pdf_viewer.js (modules.js?hash=9dd20a3…:114818)
I'm really unsure what is going on here. I noticed that the function complaining refers to webpack - which I haven't been using.
I've also tried including the following check at the start of my code (this is taken from pageviewer.js in the github link above).
if (!PDFJS.PDFViewer || !PDFJS.getDocument) {
alert('Please build the pdfjs-dist library using\n' +
' `gulp dist`');
}
My code does in fact trigger that alert (PDFJS.PDFViewer is undefined) but the message doesn't seem correct as I installed the built pdfjs-dist library using npm. That message seems for people who cloned the repo. There isn't a gulp file in the pdfjs-dist directory - which makes sense.
I'm sure part of thep problem is that I'm experimenting with a lot of new tools here. This is my first time working with meteor, react, node, and pdf.js, so apologies in advance if I've made an obvious rookie mistake.
For the record I've tried a few other libraries, including:
mikecousins/react-pdf-js (worked reasonably well for simply displaying a pdf with no text layer).
peerlibrary/meteor-pdf.js (I hit some errors with this one as well, and I didn't pursue it too much further as the repo hasn't been touched in a couple of years).
Hopefully that's enough information for someone to spot the issue. My theory is that there's some other set up step I need to do to get this working for meteor or react (and that's why it hasn't been obvious from the "getting started" in the PDF.js website.
Also, I'm not locked in to PDF.js, so if the easiest solution to my problem is to use something else, I'd be happy to try that.
Thanks for your time