Reactjs & jest -> How to use global varaiables for tests - reactjs

I am trying to set a JS variable set by facebook sdk in my test file
beforeall() { global.FB = true; }
I want to change this to false, for one specific test case,Can this be achieved?
I tried setting setting it to false within the test case, and updating the wrapper. but it does not refresh
it('test case', () => {
global.FB = false;
wrapper.update();
});

Related

React & Jest global.confirm not updating between tests

I have an existing application that I am trying to write tests for. I have a component function that uses a window.confirm box to get user input (not my code) like this:
if (window.confirm('Are you sure to unassign?')) {
NetworkWebAPIUtils.unassignSeat(this.state.seatnetwork.seat.id, this.state.seatnetwork.network.id, this.props.rank);
}
I am trying to write tests for both paths:
it('should call endpoint when user selects yes', function () {
global.confirm = jest.fn(() => true);
seatUpdateRow.instance().handleChangeAssigned({target: {value: true}});
expect(NetworkWebAPIUtils.unassignSeat.mock.calls.length).toBe(1);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0].length).toBe(3);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][0]).toBe(1234);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][1]).toBe(5678);
expect(NetworkWebAPIUtils.unassignSeat.mock.calls[0][2]).toBe(1);
});
it('should not call endpoint when user selects no', function () {
global.confirm = jest.fn(() => false);
seatUpdateRow.instance().handleChangeAssigned({target: {value: true}});
expect(NetworkWebAPIUtils.unassignSeat).not.toHaveBeenCalled();
});
The problem is that global.confirm will not update for the second test. If I set the first test to false then it obviously fails but the second one passes. If I set the first to true then the first passes but the second fails because global.confirm = jest.fn(() => false) doesn't actually cause window.confirm to evaluate to false. If I comment out the first then the second passes just fine.
I have tried mocking window.confirm and I get the exact same behavior.
It was an obvious issue. I forgot to clear the mock calls from NetworkWebAPIUtils.unassignSeat.
afterEach(function () {
NetworkWebAPIUtils.unassignSeat.mockClear();
});

Angular 1.x/2 Hybrid, karma tests not bootstrapping ng1 app

I currently have a Hybrid Angular app (2.4.9 and 1.5.0) using angular-cli. Currently, when running our application, we are able to bootstrap the 1.5 app correctly:
// main.ts
import ...
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
angular.element(document).ready(() => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, ['myApp'], {strictDi: true});
});
});
However, in our test.ts file:
// test.ts
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import ...;
declare var __karma__: any;
declare var require: any;
__karma__.loaded = function () {};
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
// I'm assuming that I need to call 'boostrapModule()' somehow here...
platformBrowserDynamicTesting()
);
const context = require.context('./', true, /\.spec\.ts$/);
context.keys().map(context);
__karma__.start();
I'm not exactly sure how to bootstrap our 1.5 application into the test environment, all I've gotten is Module 'myApp' is not available!, and my Google skills have failed trying to find an example.
I was hoping the bounty I added last night would mean I could log on this morning to a nice solution laid out for me. Alas, it did not. So instead I spent the day cruising around many SO answers and github issues getting it to work. I'm sorry I did not keep track of everything that helped me to credit them, but here is my solution. It is probably not ideal, but it is working so far so I hope it is a good start.
This github issue indicates that downgradeComponent isn't going to work for now, so I went with what I assume is an older technique using UpgradeAdapter. Note that this technique does not use initTestEnvironment. Here are the relevant snippets, with some explanations below:
// downgrade.ts:
export const componentsToDowngrade = {
heroDetail: HeroDetailComponent,
...
};
export function downgradeForApp() {
forOwn(componentsToDowngrade, (component, name) => {
app.directive(name!, downgradeComponent({ component }));
});
}
// main.ts:
downgradeForApp();
platformBrowser().bootstrapModuleFactory(AppModuleNgFactory).then((platformRef) => {
...
});
// test.ts:
require("../src/polyfills.ts");
require("zone.js/dist/proxy");
require('zone.js/dist/sync-test');
require("zone.js/dist/mocha-patch");
// test-helper.ts
let upgradeAdapterRef: UpgradeAdapterRef;
const upgradeAdapter = new UpgradeAdapter(AppModule);
forEach(componentsToDowngrade, (component, selectorName) => {
angular.module("app").directive(
selectorName!,
upgradeAdapter.downgradeNg2Component(component) as any,
);
});
export function useAdaptedModule() {
beforeEach(() => {
upgradeAdapterRef = upgradeAdapter.registerForNg1Tests(["app"]);
});
}
export function it(expectation: string, callback: () => void) {
test(expectation, (done) => {
inject(() => { }); // triggers some kind of needed initialization
upgradeAdapterRef.ready(() => {
try {
callback();
done();
} catch (ex) { done(ex); }
});
});
}
// hero-detail.component.spec.ts
import { it, useAdaptedModule } from "test-helpers/sd-app-helpers";
describe("", () => {
useAdaptedModule();
it("behaves as expected", () => { ... });
});
A few of the highlights from that code:
I downgrade components differently for tests than for the app, so I made a DRY list of them in downgrade.ts
I downgrade components for the main app from main.ts by calling downgradeForApp() as shown above (used with AOT for a production bundle), and also main-jit.ts, not shown above (used for development)
I showed the imports I needed to add to start integrating Angular components into my AngularJS tests. You may need more/different ones depending e.g. on whether your tests are asynchronous, or you use Jasmine instead of Mocha.
At the beginning of each test that needs to use downgraded components, I "bootstrap" things with useAdaptedModule() instead of beforeEach(angular.mock.module("app"));
I import an alternative it from my helpers, which wraps the it provided by Mocha. None of my tests are asynchronous; if you have some that are it may require tweaking. I do not know how it may need to be adapted for Jasmine.
A caveat: Instantiating the component must happen within an it callback so that it happens within upgradeAdapterRef.ready(...). Trying to do it within a beforeEach is too soon.

Shareds Behavior Jasmine + Protractor

I'm new with Protractor and jasmine framework to test an AngularJS Application.
I whould like to reuse some of my scenarios, like Login feature can call in all scenarios of my suite.
This is my login_test.js
module.exports = function(testName, testFn) {
const loginPage = pages.login;
const mainPage = pages.main;
var protractor;
describe('common Login suite', function() {
browser.ignoreSynchronization = true;
beforeEach(function() {
});
afterAll(function() {
browser.manage().deleteAllCookies();
});
it(testName, function() {
browser.get('http://localhost:9000/');
loginPage.typeUserName('bxxxxx');
loginPage.typePassword('xxxxxx');
loginPage.clickLogin();
});
});
}
And here I have the remote_terminal feature, here I need call Login feature to perfom login in my scenario.
var loginSuite = require('./login_test.js');
loginSuite('login Suite terminal feature', function(browser) {
describe('description', function() {
console.log('describe');
it('it', function() {
console.log('it');
});
});
});
But when this spec (remote_terminal) is called to run I got this message on my console
Started
Spec started
.
common Login suite
✓ login Suite terminal feature
As you can see the describe and IT in the remote_terminal spec aren't ran.
Demo:
http://pavelbogomolenko.github.io/dry-principles-with-protractor.html
You can use pageObjects to achieve reusable code accross your test,
Let us create a new js file for login page as login_page.js as below,
var login_page = function(){
this.performLogin = function(){
//add code for performing login operation.
}
}
module.exports = new login_page();
Now you can import the login_page.js in all 'specs' and can call the performLogin() method whenever required.
Look at the example spec.js below,
describe("Test pageobject code",function(){
var login_page = require("login_page.js");
beforeAll(function(){
login_page.performLogin();
})
it("simple test to perform after login action is performed",function()
//do whatever you want to test
})
})

How can I make my protractor test pass?

I created a simple protractor test for my angular app. When I click a button an input value gets set:
$scope.fillForm=function(){
console.log('fillform');
$scope.myText='hoera';
};
The e2e test expects the input to be populated with 'hoera':
describe('fill in form e2e test', function () {
it('should test form', function () {
browser.get('http://localhost:63342/protractor_new/index.html');
element(by.buttonText('go')).click().then(function () {
var el = element(by.model('myText')).getText();
expect(el).toEqual('hoera');
});
});
});
When I run the test with 'protractor conf' I get:
Expected '' to equal 'hoera'.
I would expect something like : expected 'hoera' to equal 'hoera'? How can I make it pass maybe there is a delay before angular sets the value? Here is a link to the code: https://github.com/dimitri-a/protractor_new
You were close. Your get and click should be added to the controlFlow, so no need to have a then on the click. But you DO need a then on your getText. This should work...
describe('fill in form e2e test', function () {
it('should test form', function () {
browser.get('http://localhost:63342/protractor_new/index.html');
element(by.buttonText('go')).click();
element(by.model('myText')).getText().then(function(el) {
expect(el).toEqual('hoera');
});
});
});

Error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread

React Tests Fails after set State causes second render
Up until now testing has been going well with JSDOM and Mocha. So far have not had to test any components that change their state. I found my first issue testing a component that changes it's state.
The Error
1) Reduced Test Case - #current Tests that Fail when Component changes state and renders "before each" hook:
Error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use React.renderToString for server rendering.
at Context.<anonymous> (test/react-reflux/parts/Reduced-spec.js:47:32)
The Component : Reduced.js
var React = require('react');
var Reduced = React.createClass({
getInitialState() {
console.log("start off with editing as false");
return {editing: false};
},
edit() {
console.log("Setting State to Edit");
this.setState({editing: true});
},
render() {
console.log("Rendering");
return (
<span onClick={this.edit}>
{(this.state.editing) ? "Editing" : "Click To Edit"}
</span>
);
}
});
module.exports = Reduced;
The Tests : 1-pass, 1-fail
var React, TestUtils, jsdom, Reduced, expect;
describe('Reduced Test Case', function () {
before(function () {
jsdom = require('jsdom');
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = global.document.parentWindow;
React = require('react/addons');
TestUtils = React.addons.TestUtils;
Reduced = require('./Reduced');
expect = require('chai').expect;
this.component = TestUtils.renderIntoDocument(
<Reduced />
);
var root = TestUtils.findRenderedDOMComponentWithTag(this.component, 'span');
this.el = root.getDOMNode();
});
describe("Tests Pass without simulate", function () {
it("Root Element Reads 'Click To Edit'", function () {
expect(this.el.innerHTML).to.equal('Click To Edit');
});
});
describe("Tests that Fail when Component changes state and renders", function () {
beforeEach(function () {
//
// Simulate invokes edit, invokes set state, invokes render, then error occures
//
TestUtils.Simulate.click(this.el);
});
it("Root Element Reads 'Editing'", function () {
expect(this.el.innerHTML).to.equal('Editing');
});
});
});
The Results
> mocha --compilers js:babel/register
Reduced Test Case - #current
start off with editing as false
Rendering
Tests Pass without simulate
✓ Root Element Reads 'Click To Edit'
Tests that Fail when Component changes state and renders
Setting State to Edit
Rendering
1) "before each" hook
1 passing (379ms)
1 failing
1) Reduced Test Case Tests that Fail when Component changes state and renders "before each" hook:
Error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use React.renderToString for server rendering.
at Context.<anonymous> (test/Reduced-spec.js:47:32)
I've been going crazy
Everything is loaded after global.window and global.document
The Simulate Event invokes edit(), then render() before error
All React Mocha JSDOM tests have been working well until this state change issue
Please help ???
The setup JSDOM setup was missing global.navigator.
global.navigator = {
userAgent: 'node.js'
};
Insert your global object modifying(passing window and document objects to global) before React is required.
Because React creates its ExecutionEnvironment object while required and don't modify it while works.

Resources