Testing in Meteor - reactjs

I am trying to add tests in Meteor. I added my tests in the folder 'imports'. This is the test file:
import { Meteor } from 'meteor/meteor';
import { chai } from 'meteor/practicalmeteor:chai';
if (Meteor.isClient) {
describe('Client Tasks', () => {
describe('methods', () => {
it('can delete owned task', () => {
Meteor.call('getVideoData', function (error, res) {
if (error) console.log('error', error)
console.log('ok', res);
})
});
});
});
}
I tried to call a method and log the result but I get the following error:
There is no route for the path: /
The result from the console log is:
error {"isClientSafe":true,"error":404,"reason":"Method 'getVideoData' not found","message":"Method 'getVideoData' not found [404]","errorType":"Meteor.Error"}
and
ok undefined
I used Meteor for the back end and React for the front end.
Am I missing something in the test file or is it related to something else?
This is the link to the repo github

The immediate problem you are seeing is "Method 'getVideoData' not found". That is because running meteor test will only load the modules you have specifically imported. It does not eagerly load your project as we are used to when serving meteor in local development mode. You've only imported Meteor and chai into this test so the test knows nothing about any methods you've written in other files in your project.
However, that leads to a more fundamental problem in that meteor test does not run a front end and back end anyways, so methods are not testable as a way to retrieve data from the server when testing the front end. Instead, when testing the front end you need to stub/mock the call to Meteor.call('getVideoData') and all you can really do is assert that it's been called and supply your own fake return data, as shown in this example.
Then you would need to write separate backend tests to verify the method (and hopefully the compartmentalized functions it calls) are properly retrieving the correct data.

Related

process is undefined in React

I am building a simple React app that generates a QR code from data. I am interested in inspecting the memory usage when the QR code is generated. I am using the built process.memoryUsage() function but the app throws and exception
Uncaught TypeError: process__WEBPACK_IMPORTED_MODULE_1__.process is undefined
I have tested some different solution, i tried to rollback the react script version to "4.0.3" i tried to download the npm polyfill webpack but there is no success.
I am currently using these imports
import React, { useState, useEffect } from 'react';
import process from 'process';
import './App.css';
const QRCode = require('qrcode');
The function looks like this
let stringData = JSON.stringify(qrData);
console.log("Number of chars in data" + " " + stringData.length);
QRCode.toDataURL(stringData, function (err, url) {
if(err) return console.log("error occured")
//window.location.href = url;
})
const used = process.memoryUsage();
for (let key in used) {
console.log(`${key} ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
}
}
process is a Node.js API and is not available in the browser where your React app is running, which is why you see that error. If there is an available global process object, it is being polyfilled by something in your build tools, and will not have the memoryUsage method.
There is no equivalent API for the browser, but some related APIs do exist. Note that this is an evolving space and some are non-standard, so be sure to read both the spec and documentation before considering any usage:
Device Memory API (MDN)
Performance.memory (MDN)
You are using a built in nodejs package in a react app. Node executes on the server and has access to system level resources. React runs in the browser and does not. See this article for some tips measuring performance in React.

ReactJS Jest Puppeteer tests no longer working: ReferenceError: document is not defined

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.

React -- getting ".map is not a function" on PRODUCTION build, but not on regular dev build?

I can't seem to debug this... not sure what's wrong.
This is a React front-end communicating using AXIOS to a Java/MySQL backend. Axios is making CRUD requests over localhost to fetch/update data.
When I run NPM START (development - port 3000) for my React application, it runs fine. However, when I run NPM RUN BUILD and then serve the production build (port 5000), I am getting the following error messages in the console:
Uncaught (in promise) TypeError: this.state.reportData.map is not a function
at t.value (TotalsPerCustomer.js:378)
at Oi (react-dom.production.min.js:3785)
at Ni (react-dom.production.min.js:3776)
at Ri (react-dom.production.min.js:3960)
at Va (react-dom.production.min.js:5514)
at Qa (react-dom.production.min.js:5536)
at Ou (react-dom.production.min.js:5958)
at Pu (react-dom.production.min.js:5925)
at ku (react-dom.production.min.js:5860)
at Ja (react-dom.production.min.js:5787)
I faced this ".map is not a function" previously when I wasn't properly using an ARRAY - but I know this isn't causing the issue now since it works fine on development (Port 3000).
I've tried to do some research on why this is occurring but haven't found any clear answers.
I have added "localhost:5000" to the allowed Origins for CORS in Java back end:
package com.example.groupproject;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#SpringBootApplication
public class GroupProjectApplication {
public static void main(String[] args) {
SpringApplication.run(GroupProjectApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:3000","http://localhost:3001","http://localhost:5000");
}
};
}
}
I think I need to understand better what is occurring when a production build is created - I know it creates an minified version of the code -- does this mean that if I have functions named the same thing in different React components then it will create an issue?
Do I need to add the axios dependency somewhere in my WebPack folder? Or is there a different dependency or something missing in my WebPack?
See below screenshot of the console:
I don't really know how to begin debugging using these console errors - can someone shed some light on this?
My apologies for being a little clueless on this production build - any help is much appreciated.
Thanks!
This happen to me as well. First I tried to resolve as it is problem with Array and then finally realized that in reality it is not - because front end (port 5000, production build) lost connection with back end (port 8080) when building for production, hence array was empty.
So this is how I resolved it:
created .env file in root of my React project:
REACT_APP_API_URL_PROD=http://xxx.xxx.xxx.xxx:8080
REACT_APP_API_URL_TEST=http://xxx.xxx.xxx.xxx:8080
REACT_APP_API_URL_DEV=http://localhost:8080
and then in requests.js file (code snippet)
import axios from 'axios';
import endpoints from './endpoints';
if (process.env.NODE_ENV === 'production') {
axios.defaults.baseURL = process.env.REACT_APP_API_URL_PROD;
} else if (process.env.NODE_ENV === 'test') {
axios.defaults.baseURL = process.env.REACT_APP_API_URL_TEST;
} else {
axios.defaults.baseURL = process.env.REACT_APP_API_URL_DEV;
}
export const getRequest = async url => axios.get(url);
export const get = (type, params, options = null) => dispatch => {
const fn = endpoints[type];
axios.defaults.headers.common = {'Authorization': `Bearer ${localStorage.getItem('token')}`};
axios.get(fn(params), options)
.then(response => {
dispatch({
type: type,
payload: response.data
});
});
};
Now, why this is late answer for you, might happen to someone in the future to lose few hours trying to resolve this.
After this, static pages were properly served with 'serve -s build' as well as with Apache HTTP server, and I guess it could be served with any other server.
Please read this for further info.
marked as duplicate of this question:
data.map is not a function
In general, when getting ".map is not a function", this means that you aren't giving an array to map. Only array types can be mapped. So if needed, set the initial state as an empty array (then fetch data, set state, etc.). Bear in mind that if you are mapping certain keys into your page, you may need to set the initial empty array with a 'blank' object, with empty or null values for those keys.
Thanks to those who helped answer this question initially.

React Remote Console Logging

I setup an Express Server with Mongo to record console logs during debug testing of an Electron app using React.
I simply use ajax to send what I would normally print with console.log. This works fine with individual events I want logged, but how do I export the entire chrome style console as an object so that anything that would reach the console (example: webpack messages, messages from other components etc) would all be accessible as one object that I can do a POST on.
Basically a way to record everything that you would see in the console whether it was from a 3rd party package or that I expressly logged myself. Is there a console dump all method of some sort I'm not seeing in the chromium/electron/react docs?
example:
//import some debugger method to POST to server collecting logs
export function debugpost(logobject) {
$.ajax({
type: "POST",
url: "http://" + "192.168.0.94" + ":3000/tasks",
headers: {
},
data: {
log: logobject
},
success: function(data) {
}.bind(this),
error: function(errMsg) {
console.log(errMsg);
}.bind(this)
});
}
//simple way of recording logs in other component.
var testlogmessage = "This isn't right"
debugpost(testlogmessage);
Logging individual events to the server is easy. How do I dump the entire console?
UPDATE
Mentioned below was to tie into the process stdout and stderr. I tried the recommended package capture-console and also this code snippet:
var logs = [],
hook_stream = function(_stream, fn) {
// Reference default write method
var old_write = _stream.write;
// _stream now write with our shiny function
_stream.write = fn;
return function() {
// reset to the default write method
_stream.write = old_write;
};
},
// hook up standard output
unhook_stdout = hook_stream(process.stdout, function(string, encoding, fd) {
logs.push(string);
});
However both give me this error with write when using with react:
TypeError: Cannot read property 'write' of undefined
hook_stream
That particular method seems to log the electron node side fine when I use it in the electron main.js. However I can't get it to work within my react components.
One way of doing this is to overwrite the console.log with your custom implementation, so whenever any part of the code calls the console.log the call will be intercepted by your custom function where you can log the message to your remote server using some API calls.
Once you have logged your message you can call the original console.log method.
Following example shows a custom implementation of console.log method.
var orgLog = console.log;
console.log = function(message) {
alert("Intercepted -> " + message); //Call Remote API to log the object.
//Invoke the original console.log
return orgLog(message);
}
let a = {
foo: "bar"
};
console.log(a);
You tie into the stdout, stderr streams in the process module.
Take a look at npm capture-console. You will need to capture console output from any renderer process as well as the main process.
UPDATE
It appears electron has done some strange things with renderer process stdout stream. You are better off using a custom logging solution like electron-log and syncing logs from the written log file.

How to catch React propTypes warnings on server?

While rendering React components on server all of the propTypes warning messages are falling to general output or process.stdout. For example, this is visible only in terminal or in general application log:
Warning: Failed propType: Required prop `title` was not specified in `Page`.
Is there any way to catch this warnings and transform them or pipe them into another direction? For instance, I want to separate application log and React (as template engine) log. How can I do it?
Like #m01, I wanted to make sure that any react errors (and in fact any js errors) cause my unit tests to fail, but I found a much simpler way to do it. At the top level of your tests, put this:
beforeAll(() => {
console.error = (error) => {
throw new Error(error);
};
});
I needed the same thing, but for a different use case. I wanted to make sure that all my unit tests pass without any React warnings.
I use this in my test utils:
expectNoConsoleErrors: function() {
var savedErrors;
beforeEach(function () {
savedErrors = [];
spyOn(console, 'error').and.callFake(function () {
var stack = new Error(_.map(arguments).join(' ')).stack;
// if you need workarounds for come components, put them here
savedErrors.push(stack);
});
});
afterEach(function () {
if (savedErrors.length > 0) {
fail(savedErrors.join('\n'));
}
});
},
Then in describe block I put
myTestUtils.expectNoConsoleErrors()
And it works like a charm.
This is not very clean because it will also catch all other calls to console.error, but I don't want them during test anyway, so this seems ok for me.
Also, when I have some misbehaving component producing unnecessary warnings, like e.g. react-input-autosize I can ignore it using:
// Workaround for https://github.com/JedWatson/react-select/issues/371
if (_.contains(stack, 'react-input-autosize')) {
return;
}
Btw, note that before v0.14, React was using console.warn instead of console.error to produce these warnings.
I tried looking into the React src how they print those output messages, but then I realized that it should only be printing those messages in development mode. If your node/iojs runtime is set to the "production" env, React should not even be doing those checks and that's what you want for a real app running. Those warnings are meant just for devs running locally.

Resources