Looking for errors in a React component export/import - reactjs

I'm new to the React stack, trying to build a library of simple shared components. The components work fine in their home project. I've configured them using this advice. Dropped them into a local git, npm installed them a new project with git+https. The components show up in the new project /node_modules/.../lib, as expected.
When the following runs, I end up with undefined exports:
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NeonFooter = exports.default = undefined;
var _NeonFooter = require('./components/NeonFooter');
var _NeonMenu = require('./components/NeonMenu');
exports.default = _NeonMenu.NeonMenu;
exports.NeonFooter = _NeonFooter.NeonFooter;
Dropping into chrome's debugger and using some console statements, (for instance) _NeonFooter does show up as an _esModule, with a correctly pathed closure to the NeonFooter.js file in scope. No direct _NeonFooter.NeonFooter field, though. When _NeonFooter.NeonFooter is referenced it comes up undefined.
I can't seem to get the vscode debugger or chrome to bind to a breakpoint on the require, and there's no exception occurring to break on. How do I dig into this further to find the actual error that leads to the undefined value?

So, it looks like the issue is with a Babel transformation, or with how that transformation is being consumed by React. Changing the transformed code to
exports.NeonMenu = _NeonMenu.default;
exports.NeonFooter = _NeonFooter.default;
solves the issue.
Still trying to determine the correct Babel/React behavior, but it's a step forward.

Related

Cypress: access custom defined css property

I am building an APP using React + chakra-ui and I am in the process of adding Cypress tests to it, but I am facing a blocker and I was wondering if anyone had faced a similar problem and that could help!
Problem:
The test I am trying to pass is to verify that my element contains a CSS property, however, the CSS was generated by Charkaui with their unique syntax (e.g --chakra-scale-x)
My test case is as follow
cy.get('MY_ELEMENT')
.should('be.visible')
.should('have.css', '--chakra-scale-y', 1);
This test gave me the error
expected '<div.css-o64oke>' to have CSS property '--chakra-scale-x'
even though I can see from inspect element that it does have the following property.
Does anyone know a solution or a workaround for this? Thanks in advance!
Edit:
--chakra-scale-y is a css variable, which will be applied (probably as a transform) by the browser css engine.
Take a look in the devtools Computed tab (unselect Show all to see just those applied). If a transform shows up, this is what you need to test for.
In the test use getComputedStyle to check the value identified above.
cy.get('MY_ELEMENT')
.then($el => {
const win = cy.state('window')
const styles = win.getComputedStyle($el[0])
const transform = styles.getPropertyValue('transform')
console.log(transform)
expect(transform).to.eq(...)
})
It looks like you need to check scaleY, this is from the chakra library
const transformTemplate = [
"rotate(var(--chakra-rotate, 0))",
"scaleX(var(--chakra-scale-x, 1))",
"scaleY(var(--chakra-scale-y, 1))",
"skewX(var(--chakra-skew-x, 0))",
"skewY(var(--chakra-skew-y, 0))",
]

How to keep this keyword points to window object in webpack?

I have convert AngularJS application to es6 using webpack and import/export syntax.
Everything works perfect except this keyword.
Since webpack wrap all my code during compilation into iife function (modules), the keyword this gets undefined in functions like:
.controller( …, function() {
...
this.myFunc = function() {
someFunction().then(function(data) {
this.someVar = data;
// this === window
});
});
});
In normal angular application without bundling this gets window Object.
I do not want to make a big changes except working with webpack (I have a lot of code places that have that). Is there any way to keep this to point window object in webpack?
Webpack does force code to use "strict mode". The problem comes from the use of ES6 import statements.
From the Docs:
The static import statement is used to import bindings which are exported by another module. Imported modules are in strict mode whether you declare them as such or not.
For more information, see
MDN JavaScript Reference - import statement

Grunt-Karma-Jasmine: can not find module

I am trying to set up tests for my Angular.js project and I keep getting "$injector:nomod, Module 'result' is not available! You either misspelled..." error. I am sure that I am including "result" module in the "files" array inside "karma.config.js", basically it looks like this:
files: [
'../javascripts/jquery-2.1.4.min.js',
'../jquery-ui/jquery-ui.min.js',
'../D3/d3.js',
'libs/angular.min.js',
'libs/angular-route.min.js',
'libs/angular-animate.min.js',
'libs/selectize.js',
'libs/angular-selectize.js',
'libs/angular-mocks.js',
'simulator.js',
'*.js',
'services/**/*.js',
'qa/tests-*.js'
],
...
I thought initially that the ordering of the main module: 'simulator' (defined inside 'simulator.js' file) is wrong, so I specifically moved it upwards, before
the other modules, like the following stackoverflow thread recommends:
Angular module not available in Karma Jasmine test run
It did not help. Then I tried to make sure that the files are imported in the same order as in my angular apps' main entry file (except for angular-mocks.js and qa/tests-*.js), importing each single file, instead of using wildcards, but no success.
Jasmine definitely goes inside the test files but stumbles upon the line where I am trying to import the module "result":
describe('simulator.chartService', function() {
var chartService;
var graphConfig;
console.log("instantiating module result");
beforeEach(module('result'));
console.log("finished instantiating");
beforeEach(inject(function($injector) {
graphConfig = $injector.get('graphConfig');
chartService = $injector.get('chartService');
}));
it('should be created', function() {
expect(chartService.calcColors(10)).not.toBeNull();
});
});
So, I see that the error happens in-between two console.log() statements.
I suspect that still something can be wrong with the ordering of my files inside the array "files" in "karma.config.js". I have main module "simulator" which is dependent on other modules:
angular.module('simulator', ['ngRoute','ngAnimate','selectize','newexp2','newexp','login','edit','exps', 'result','templates','commons'])
Modules 'newexp2', 'newexp', 'login', 'edit', 'exps', 'result', 'templates' are all dependent on the module 'commons'.
How to correctly import interdependent modules inside the "files" array?
Is it just enough to place "simulator.js", main module, above all others,
or I also need to place all other modules before "commons.js"?
Another my suspicion is that angular.js library version that I downloaded from the official angular website, "angular-mocks.js", can be incompatible with other modules that I am using. I had such an issue with "angular-animate.js" file before.
As long as I surround my test code with $(function(){...}) (and all other my modules ARE surrounded with it) it does not generate the error while importing the result module, so I start seeing two console.log() statements without an error in-between, however, this generates some unknown error which prevents me from invoking the it part at all, whereas when I do not surround it with $(function(){...}), the it test is invoked, but the module result import fails.
So far I am pretty much stuck and do not know where to move and what to try. Any suggestion would be greatly appreciated.
OK, I figured it out. The issue was that ALL of my angular code was enclosed inside $(function(){...}). The solution is to remove all of the $function(){...}), then reorder javascript imports inside the main entry .html file, and then all of the testing starts working good.
The question might be better to mark as duplicate with:
Angular document.ready() issue

Some of your tests did a full page reload - error when running Jasmine tests

I'm running into an issue where when I run my tests on Jasmine, I get this error below. The problem is, it seems to happen when I try to execute a certain amount of tests. It doesn't seem to be tied to a particular test, as if I comment out some, the tests pass. If I uncomment some tests, the error appears. If I comment out ones that were uncommented before, they all pass again. (ie if I have red, green, blue and orange test and it fails, I comment out orange and blue it passes, then I uncomment blue and orange it fails again, but if I comment out red and green it passes again).
Chrome 41.0.2272 (Mac OS X 10.10.1) ERROR Some of your tests did a
full page reload! Chrome 41.0.2272 (Mac OS X 10.10.1): Executed 16 of
29 (1 FAILED) ERROR (0.108 secs / 0.092 secs)
I'm stumped as to what is going on. The more tests I add, that's when this becomes an issue. Has anyone encountered this before? I have no idea what could be causing it, as nothing in any of my tests do any kind of redirection, and they all pass universally on another persons machine.
In my case the problem was that in my source code I had code directly setting the href on the location object, like window.location.href = 'somewhere';
In my specs I set up a onbeforeunload listener that just returns a string instead of allowing the redirect to take place:
beforeAll(() => {
window.onbeforeunload = () => 'Oh no!';
});
I suppose you are using window.location somewhere in your targeted code. In order to pass it just create a spy for the window.onbeforeunload
Example:
window.onbeforeunload = jasmine.createSpy();
Or even better use $window instead, and this will not happen.
Make sure that your tests are properly isolating all modules under test with mocks/spies. The behavior you are seeing says to me that your tests are not truly running in isolation - they are changing some state somewhere that will trigger a reload.
I recently encountered this error with Karma 0.13.12. I upgraded to Karma 0.13.14 and my tests work again. The problem for me (and probably also for #mqklin) was related to https://github.com/karma-runner/karma/issues/1656 and https://github.com/jasmine/jasmine/issues/945.
There are many ways this error can happen.
If your component has a form element, this might be the cause.
Whenever a button on the form is clicked, this error can happen, even tho your component contains no navigation logic.
What worked for me was upgrading Karma from 1.4.0 to 1.4.1 and changing the maximumSpecCallbackDepth in my jasmine.js file from 20 to 100.
creating a spy on the function which has the window.location / reload fixed the issue for me
Hope you have used window.location = "some url" in your code;
Faced similar problem, and solved by using the below changes.
Replaced window.location in the code with,
window.location.assign("some url");
Do the below in unit test:
spyOn(window.location, "assign").and.callFake(() => {
// Dummy assign call - so that your actual call will be faked and the reload will not happen.
});
You also need to make sure that modules are not being loaded twice. In my case, I had an AngularJS module file -e.g., auth.controller.js which contents were already bundled in a core.js file. Once I excluded the bundled files on karma, the error disappeared.
Try to reduce amount of describe sections or completely remove them. I don't know why, but it works for me.
I was using setTimeout(() => window.location.replace('/'), 10);
I used below code in my unit test and it worked for me.
spyOn(global, 'setTimeout');
In case it was ng-submit callback, which doesn't call "event.preventDefault()" and the browser reloads page. Mocking $location doesn't help in that situation.
According to angularjs documentation you should inject the $window module to be able to solve the testability issue you get. If you really want to do a full page refresh while routing, which will reload the whole application. But anyway...
So for example in component
.controller('ExampleController', ['$scope', '$window', function($scope, $window**)
{
$scope.doRerouteWithPageReload = function() {
return this.$window.location.href = "/myUrl";
};
And then in your test-file you import $window to the test-controller your way, then where you assign spies you can do something like this:
$window = { location: {href: jasmine.createSpy() };
And then the actual test is something like this:
expect($window.location.href).toBe("/myUrl");
Angularjs documentation for reading more about $window.
It will solve this Karma redirect error!
var html = '<script type="text/javascript">';
html += 'window.location = "' + urlToRedirect +'"';
html += '</script>';
$( '.wrapper' ).append( html );

$on('value...) gives me "undefined is not a function" in angularfire

I have started to use angularjs and now am following a tutorial about angularjs with angularfire. In the tutorial there is a section to learn how to use child_added
angular.module('firebaseApp').service('MessageService', function(FBURL, $q, $firebase) {
var messageRef = new Firebase(FBURL).child('messages');
var fireMessage = $firebase(messageRef).$asArray();
return {
childAdded: function childAdded(limitNumber, cb) {
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
},
and main controller :
MessageService.childAdded(5, function(addedChild){
$timeout(function() {
$scope.messages.push(addedChild);
});
});
When I use the code, chrome developer tools is giving an error :
TypeError: undefined is not a function
adressing .$on in MessageService and .childadded in controller.
This is a video tutorial and I can see him working like this. I checked many answers but could not find a way. My best shot is I guess different versions of angularjs and angularfire. But that did not help me either. Can you help me to solve it?
Thank you in advance.
I thought I'd offer a bit of clarity on the topic for those who are taking this tutorial on tutsplus. First, we should pay attention to the versions of firebase and angularfire that we are using, compared to what the instructor is using. This might seem obvious, but there are many out there who fail to realize it. Whenever watching a tutorial, you should always check the version of ANY package you are using. This world of software moves really fast, and up-to-date tutorials are a luxury.
Pay attention to your bower.json file in your project. Note the version of the following lines:
"firebase": "~2.0.4",
"angularfire": "~0.9.0"
You can see here the version of the dependencies I used. Chances are, you were like me, and your version will differ from what you find in the teacher's version. The instructor offers his source files on the course main page. Download those files, which should be titled SourceFiles_RTWebAppAngularFirebase.zip. Once downloaded, open it, and you will see a list of packaged zip files contained in a file called Firebase Source. Find lesson-16-angularfire.zip, and also open it. A folder titled "Firebase" should be provided, and there you will find the instructor's app that he created during the tutorial. Check out his bower.json file, and check it against what you have. According to what I found, both versions of firebase and angularfire were vastly different. This means only one thing: we have some reading to do.
Go here and check out the releases of AngularFire: https://github.com/firebase/angularfire/releases
Scroll down, and read the release notes of v0.8.0. A very important note is found here.
$on() and $off() no longer exist. Similar functionality can be obtained with $watch() but should be discouraged for trying to manually manage server events (manipulation should be done with data transformations through $extendFactory() instead).
Obviously now, we understand that we can't follow blindly in the instructor's footsteps. We have to try mimicking his app's functionality. Reading what I posted above, we can use $watch to obtain similar functionality. However, I honestly tried to make this work, and the functionality that $watch delivers is not exactly the functionality we are trying to achieve. Ideally, we should synchronize our empty messages array $scope.messages with $firebase(messageRef).$asArray(). That wouldn't be as fun though.
The route I took was this: I looked at what cb.call() was doing, which is the following
MessageService.childAdded(function(addedChild) {
$scope.messages.push(addedChild);
});
This call back function pushes an object created from cherry picked values obtained from a snapshot returned from a 'child_added' event. The real leverage here is the snapshot, which is provided by the $firebase module itself with Firebase.on(). If you read the docs for the "Child_Added" event, it says
This event will be triggered once for each initial child at this location, and it will be triggered again every time a new child is added. The DataSnapshot passed into the callback will reflect the data for the relevant child
The DataSnapshot returned for every "initial" child at this location, is what initially populates the list of messages. This means that we can change this:
fireMessage.$on('child_added', function(snapshot){
console.log(snapshot);
var val = snapshot.val();
cb.call(this,{
user: val.user,
text: val.text,
name: snapshot.name()
});
});
back to this:
messageRef.on('child_added', function(snapshot) {
var val = snapshot.val();
cb.call(this,
user: val.user,
text: val.text,
name: snapshot.key()
});
});
The messages should populate again on the front page. Your code should be stable enough as well to follow the instructor during the remainder of the Refactor lesson.

Resources