Angular2: Unit-test router with cached template - unit-testing

I'm dealing with some problems doing test on different environments:
SRC: unminified components, using both .js and .html/.css template files
DIST: minified components (only .js, no templates)
I made two different karma-conf and karma-test-shim, one for SRC and one for DIST.
In the SRC's one, since i mostly execute tests on components in fakeAsync contexts, i'm caching all my templates and .css at karma's startup, as shown in the following karma-test-shim, to avoid XHR errors.
karma-test-shim.src.js
// Turn on full stack traces in errors to help debugging
Error.stackTraceLimit = Infinity;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
var karmaFiles = Object.keys(window.__karma__.files); // All files served by Karma.
window.$templateCache = {}; // deckaring Window template cache for caching .html template and .css
// Cancel Karma's synchronous start,
// we will call `__karma__.start()` later, once all the specs are loaded.
__karma__.loaded = function () { };
// Just a special configuration for Karma and coverage
System.config({
packages: {
"#angular/core/testing": { main: "../../../../../../node_modules/#angular/core/bundles/core-testing.umd.js" },
"#angular/compiler/testing": { main: "../../../../base/node_modules/#angular/compiler/bundles/compiler-testing.umd.js" },
"#angular/common/testing": { main: "../../../../base/node_modules/#angular/common/bundles/common-testing.umd.js" },
"#angular/http/testing": { main: "../../../../base/node_modules/#angular/http/bundles/http-testing.umd.js" },
"#angular/router/testing": { main: "../../../../../../node_modules/#angular/router/bundles/router-testing.umd.js" },
"#angular/platform-browser/testing": { main: "../../../../base/node_modules/#angular/platform-browser/bundles/platform-browser-testing.umd.js" },
"#angular/platform-browser-dynamic/testing": { main: "../../../../base/node_modules/#angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js" }
},
meta: {
"src/*": { format: "register" }, // Where covered files located
"packages/*": { format: "register" } // Where covered files located
}
});
Promise.all([
System.import('#angular/core/testing'),
System.import('#angular/platform-browser-dynamic/testing'),
System.import('#angular/platform-browser-dynamic') // Contains RESOURCE_CACHE_PROVIDER
]).then(function (providers) {
var testing = providers[0];
var testingBrowserDynamic = providers[1];
var browserDynamic = providers[2];
testing.TestBed.initTestEnvironment(
testingBrowserDynamic.BrowserDynamicTestingModule,
testingBrowserDynamic.platformBrowserDynamicTesting()
);
testing.TestBed.configureCompiler({
providers: [
browserDynamic.RESOURCE_CACHE_PROVIDER
]
})
// Import main module
}).then(function () {
return Promise.all(
karmaFiles
.filter(onlySpecFiles)
.map(file2moduleName)
.map(function (path) {
return System.import(path).then(function (module) {
if (module.hasOwnProperty('main')) {
module.main();
} else {
throw new Error('Module ' + path + ' does not implement main() method.');
}
});
}));
})
// Caching all component's templates files (.html/.css)
.then(function () {
return Promise.all(
karmaFiles
.filter(function (filename) {
var template = filename.endsWith('.html');
var css = filename.endsWith('.css');
return template || css;
})
.map(function (filename) {
return new Promise(function(resolve, reject) {
$.ajax({
type: 'GET',
url: filename,
dataType: 'text',
success: function (contents) {
filename = filename.replace("/base", "..");
window.$templateCache[filename] = contents;
resolve();
}
})
})
})
)
})
.then(function () {
__karma__.start();
}, function (error) {
console.error(error.stack || error);
__karma__.start();
});
// Filter spec files
function onlySpecFiles(path) {
return /\.spec\.js$/.test(path);
}
// Normalize paths to module names.
function file2moduleName(filePath) {
return filePath.replace(/\\/g, '/')
.replace(/^\/base\//, '');
}
So far so good but i started getting problems on the following spec:
loginPage.spec.js
[...]
import { LoginPageComponent } from "loginPage";
import { RESOURCE_CACHE_PROVIDER } from "#angular/platform-browser-dynamic";
#Component({
selector: "loginpage-host",
template: "<loginPage></loginPage>"
})
export class LoginPageHostComponent {
#ViewChild(LoginPageComponent)
public loginPageComponent;
}
export function main() {
describe('LoginPageComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([]),CommonModule, HttpModule, CoreModule, ComponentsModule, GlobalizationModule],
declarations: [LoginPageHostComponent, LoginPageComponent],
providers: [
MockBackend,
BaseRequestOptions,
{
provide: AuthHttp,
useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
deps: [MockBackend, BaseRequestOptions]
},
{
provide: Http,
useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
deps: [MockBackend, BaseRequestOptions]
},
{
provide: Configuration,
useFactory: () => new Configuration()
}
]
})
// TestBed.configureCompiler({
// providers: [RESOURCE_CACHE_PROVIDER]
// });
});
it('should work',
fakeAsync(() => {
TestBed
.compileComponents()
.then(() => {
let fixture = TestBed.createComponent(LoginPageHostComponent);
let logPageHostComponentInstance = fixture.debugElement.componentInstance;
expect(logPageHostComponentInstance).toEqual(jasmine.any(LoginPageHostComponent));
expect(logPageHostComponentInstance.loginPageComponent).toEqual(jasmine.any(LoginPageComponent));
fixture.destroy();
discardPeriodicTasks();
});
}));
});
}
On SRC i get this error:
Chrome 56.0.2924 (Windows 10 0.0.0) LoginPageComponent should work
FAILED Error: Cannot make XHRs from within a fake async test.
If i manually provide the RESOURCE_CACHED_PROVIDER to the spec it works:
TestBed.configureCompiler({
providers: [RESOURCE_CACHE_PROVIDER]
});
but it fails on DIST due to the fact that there's no cached template to load for loginPage.

See: Angular2 tests and RESOURCE_CACHE_PROVIDER global
We have found a solution but not based on Angular provider.
We developed a simple karma preprocessor just for test as:
preprocessors: {
"**/*.component.js": ["generic"]
},
Then preprocessor just uses gulp-inline-ng2-template parser
genericPreprocessor: {
rules: [{
process: function (content, file, done, log) {
// Prepare content for parser
file.contents = new Buffer(content);
// Every file has a parser
var parse = require('gulp-inline-ng2-template/parser')(file, { base: "packages/", useRelativePaths: false });
// Call real parse function
parse(function (err, contents) {
// Callback with content with template and style inline
done(contents);
});
}
}]
},

Related

How to mock an imported function into a test suite in NestJs?

I want to write a unit test for my payment service but I'm receiving this error:
source.subscribe is not a function
at ./node_modules/rxjs/src/internal/lastValueFrom.ts:60:12
This is my service
import { HttpService } from '#nestjs/axios';
import { Injectable } from '#nestjs/common';
import { lastValueFrom } from 'rxjs';
import { PaymentInfo } from 'src/utils/types/paymentInfo';
#Injectable()
export class PaymentsService {
constructor(private readonly httpService: HttpService) {}
private createHeaderWithAuth(auth, contentType = 'application/json') {
return {
headers: {
authorization: auth.replace('Bearer', '').trim(),
'Content-Type': contentType,
},
};
}
async makePayment(auth: string, paymentInfo: PaymentInfo) {
const configs = this.createHeaderWithAuth(auth);
const response = await lastValueFrom(
await this.httpService.post(
`${process.env.PAYMENT_URL}/transaction/pay`,
paymentInfo,
configs
)
).catch((error) => {
console.log(error);
throw new Error(error.response.data.message);
});
return response.data;
}
}
So with a bit of searching and tinkering found out that this is caused by my import of a rxjs function to resolve the observable setted by axios.
I've searched ways to mock this function so I can properly test my service. But none of them gave me a solution, the questions i found only revolved around functions with modules, but these have none since is imported from a third party lib.
This is my test suite:
describe('Payments Service', () => {
let service: PaymentsService;
let mockedHttpService = {
post: jest
.fn()
.mockImplementation(
async (
url: string,
paymentInfo: PaymentInfo,
header = mockedHeader
) => {
return { mockedSuccessfulResponse };
}
),
get: jest
.fn()
.mockImplementation(async (url: string, header = mockedHeader) => {
return { ...mockedSuccessfulResponse, data: mockedUserCards };
}),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
PaymentsService,
{
provide: HttpService,
useValue: mockedHttpService,
},
],
}).compile();
service = module.get<PaymentsService>(PaymentsService);
});
describe('Initialize', () => {
it('should define service', () => {
expect(service).toBeDefined();
});
describe('makePayment', () => {
it('should make a payment', async () => {
const payment = await service.makePayment(mockedAuth, mockedPaymentInfo);
expect(mockedHttpService.post).toHaveBeenCalledWith(
`${process.env.PAYMENT_URL}/transaction/pay`,
mockedPaymentInfo,
mockedHeader
);
expect(payment).toBe(mockedSuccessfulResponse);
});
});
});
Ps.: I removed the mocked objects to reduce the amount of code to read
you should use the of operator from rxjs, and drop the async keyword. Like:
.mockImplementation(
(
url: string,
paymentInfo: PaymentInfo,
header = mockedHeader
) => {
return of({ mockedSuccessfulResponse });
}
otherwise lastValueFrom won't receive an observable object.

How to handle bootstrap-daterangepicker in angular component unit test?

I am trying to write a unit test of an angular 6 component which is initializing the bootstrap-daterangepicker in the ngAfterViewInit() method. When I run my unit test it gives the following error:
TypeError: $(...).daterangepicker is not a function
this is the code from the actual component(EmployeeComponent):
ngAfterViewInit(): void {
this.initializeDatePicker(this);
}
initializeDatePicker(that: any) {
const start = moment().subtract(7, 'days');
const end = moment();
$('#reportrange').daterangepicker({
startDate: start,
endDate: end,
maxDate: moment(),
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')]
}
}, cb);
cb(start, end);
}
this is the code from my test class:
describe('EmployeeComponent', () => {
let component: EmployeeComponent;
let fixture: ComponentFixture<EmployeeComponent>;
let messageService: NotificationService;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EmployeeComponent]
})
.overrideComponent(EmployeeComponent, {
set: {
template: '',
providers: [
{ provide: NotificationService, useValue: messageService },
{ provide: ActivatedRoute, useValue: { queryParams: of({ emp: "123" }) } }
]
}
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmployeeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
You don't need to handle it in your test cases. That component should be initialized in a separate service and you can simply mock that method from the service. In the way you can avoid this error.
let say you move all the code of the initializeDatePicker() in a method in some service let say common-service.ts and you can simply call that service from this method like
this.commonServiceObj.initializeDatePicker();
Now after doing this, you can simply mock initializeDatePicker() from the service object and error should be gone.

Aurelia unit testing access component's viewModel

I am unit testing one of my components in an Aurelia project. I'd like to access my component's viewModel in my unit test but haven't had any luck so far.
I followed the example available at https://aurelia.io/docs/testing/components#manually-handling-lifecycle but I keep getting component.viewModel is undefined.
Here is the unit test:
describe.only('some basic tests', function() {
let component, user;
before(() => {
user = new User({ id: 100, first_name: "Bob", last_name: "Schmoe", email: 'joe#schmoe.com'});
user.save();
});
beforeEach( () => {
component = StageComponent
.withResources('modules/users/user')
.inView('<user></user>')
.boundTo( user );
});
it('check for ', () => {
return component.create(bootstrap)
.then(() => {
expect(2).to.equal(2);
return component.viewModel.activate({user: user});
});
});
it('can manually handle lifecycle', () => {
return component.manuallyHandleLifecycle().create(bootstrap)
.then(() => component.bind({user: user}))
.then(() => component.attached())
.then(() => component.unbind() )
.then(() => {
expect(component.viewModel.name).toBe(null);
return Promise.resolve(true);
});
});
afterEach( () => {
component.dispose();
});
});
Here is the error I get:
1) my aurelia tests
can manually handle lifecycle:
TypeError: Cannot read property 'name' of undefined
Here is the the line that defines the viewModel on the component object but only if aurelia.root.controllers.length is set. I am not sure how to set controllers in my aurelia code or if I need to do so at all.
I guess my question is:
How do I get access to a component's viewModel in my unit tests?
Edit #2:
I'd also like to point out that your own answer is essentially the same solution as the one I first proposed in the comments. It is the equivalent of directly instantiating your view model and not verifying whether the component is actually working.
Edit:
I tried this locally with a karma+webpack+mocha setup (as webpack is the popular choice nowadays) and there were a few caveats with getting this to work well. I'm not sure what the rest of your setup is, so I cannot tell you precisely where the error was (I could probably point this out if you told me more about your setup).
In any case, here's a working setup with karma+webpack+mocha that properly verifies the binding and rendering:
https://github.com/fkleuver/aurelia-karma-webpack-testing
The test code:
import './setup';
import { Greeter } from './../src/greeter';
import { bootstrap } from 'aurelia-bootstrapper';
import { StageComponent, ComponentTester } from 'aurelia-testing';
import { PLATFORM } from 'aurelia-framework';
import { assert } from 'chai';
describe('Greeter', () => {
let el: HTMLElement;
let tester: ComponentTester;
let sut: Greeter;
beforeEach(async () => {
tester = StageComponent
.withResources(PLATFORM.moduleName('greeter'))
.inView(`<greeter name.bind="name"></greeter>`)
.manuallyHandleLifecycle();
await tester.create(bootstrap);
el = <HTMLElement>tester.element;
sut = tester.viewModel;
});
it('binds correctly', async () => {
await tester.bind({ name: 'Bob' });
assert.equal(sut.name, 'Bob');
});
it('renders correctly', async () => {
await tester.bind({ name: 'Bob' });
await tester.attached();
assert.equal(el.innerText.trim(), 'Hello, Bob!');
});
});
greeter.html
<template>
Hello, ${name}!
</template>
greeter.ts
import { bindable } from 'aurelia-framework';
export class Greeter {
#bindable()
public name: string;
}
setup.ts
import 'aurelia-polyfills';
import 'aurelia-loader-webpack';
import { initialize } from 'aurelia-pal-browser';
initialize();
karma.conf.js
const { AureliaPlugin } = require('aurelia-webpack-plugin');
const { resolve } = require('path');
module.exports = function configure(config) {
const options = {
frameworks: ['source-map-support', 'mocha'],
files: ['test/**/*.ts'],
preprocessors: { ['test/**/*.ts']: ['webpack', 'sourcemap'] },
webpack: {
mode: 'development',
entry: { setup: './test/setup.ts' },
resolve: {
extensions: ['.ts', '.js'],
modules: [
resolve(__dirname, 'src'),
resolve(__dirname, 'node_modules')
]
},
devtool: 'inline-source-map',
module: {
rules: [{
test: /\.html$/i,
loader: 'html-loader'
}, {
test: /\.ts$/i,
loader: 'ts-loader',
exclude: /node_modules/
}]
},
plugins: [new AureliaPlugin()]
},
singleRun: false,
colors: true,
logLevel: config.browsers && config.browsers[0] === 'ChromeDebugging' ? config.LOG_DEBUG : config.LOG_INFO, // for troubleshooting mode
mime: { 'text/x-typescript': ['ts'] },
webpackMiddleware: { stats: 'errors-only' },
reporters: ['mocha'],
browsers: config.browsers || ['ChromeHeadless'],
customLaunchers: {
ChromeDebugging: {
base: 'Chrome',
flags: [ '--remote-debugging-port=9333' ]
}
}
};
config.set(options);
};
tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"importHelpers": true,
"lib": ["es2018", "dom"],
"module": "esnext",
"moduleResolution": "node",
"sourceMap": true,
"target": "es2018"
},
"include": ["src"]
}
package.json
{
"scripts": {
"test": "karma start --browsers=ChromeHeadless"
},
"dependencies": {
"aurelia-bootstrapper": "^2.3.0",
"aurelia-loader-webpack": "^2.2.1"
},
"devDependencies": {
"#types/chai": "^4.1.6",
"#types/mocha": "^5.2.5",
"#types/node": "^10.12.0",
"aurelia-testing": "^1.0.0",
"aurelia-webpack-plugin": "^3.0.0",
"chai": "^4.2.0",
"html-loader": "^0.5.5",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.5",
"karma-source-map-support": "^1.3.0",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^3.0.5",
"mocha": "^5.2.0",
"path": "^0.12.7",
"ts-loader": "^5.2.2",
"typescript": "^3.1.3",
"webpack": "^4.23.1",
"webpack-dev-server": "^3.1.10"
}
}
Original answer
If you're manually doing the lifecycle, you need to pass in a ViewModel yourself that it can bind to :)
I don't remember exactly what's strictly speaking needed so I'm quite sure there's some redundancy (e.g. one of the two bindingContexts passed in shouldn't be necessary). But this is the general idea:
const view = "<div>${msg}</div>";
const bindingContext = { msg: "foo" };
StageComponent
.withResources(resources/*optional*/)
.inView(view)
.boundTo(bindingContext)
.manuallyHandleLifecycle()
.create(bootstrap)
.then(component => {
component.bind(bindingContext);
}
.then(component => {
component.attached();
}
.then(component => {
expect(component.host.textContent).toEqual("foo");
}
.then(component => {
bindingContext.msg = "bar";
}
.then(component => {
expect(component.host.textContent).toEqual("bar");
};
Needless to say, since you create the view model yourself (the variable bindingContext in this example), you can simply access the variable you declared.
In order to get it to work, I had to use Container:
import { UserCard } from '../../src/modules/users/user-card';
import { Container } from 'aurelia-dependency-injection';
describe.only('some basic tests', function() {
let component, user;
before(() => {
user = new User({ id: 100, first_name: "Bob", last_name: "Schmoe", email: 'joe#schmoe.com'});
user.save();
});
beforeEach(() => {
container = new Container();
userCard = container.get( UserCard );
component = StageComponent
.withResources('modules/users/user-card')
.inView('<user-card></user-card>')
.boundTo( user );
});
it('check for ', () => {
return component.create(bootstrap)
.then(() => {
expect(2).to.equal(2);
return userCard.activate({user: user});
});
});
});

Angular2, jasmine: Component changes not seen in test spec function

I'm still writing tests for my Angular app. I've a test that modifies an Org object, saves the changes, and then proves that the changes have been kept. However, the test isn't seeing the changes.
My mock Org service that saves the changes:
#Injectable()
export class MockOrgService {
constructor() { }
public save(org: Org): Observable<Org> {
let savedOrg: Org = new Org(org);
savedOrg.address2 = 'Saved with id: ' + org.id;
return Observable.of(savedOrg);
}
}
My mock router:
beforeEach(async(() => {
routeStub = { data: Observable.of( { org: org1 } ), snapshot: {} } ;
TestBed.configureTestingModule({
imports: [ FormsModule, RouterTestingModule ],
providers : [
{ provide: DialogService, useClass: MockDialogService },
{ provide: GlobalsService, useClass: MockGlobalsService },
{ provide: OrgService, useClass: MockOrgService },
{ provide: ActivatedRoute, useValue: routeStub }
],
declarations: [ OrgDetailComponent ],
})
.compileComponents();
}));
My component function being tested:
private gotoParent(): void {
this.router.navigate(['../'], { relativeTo: this.route });
}
public save(): void {
this.error = null;
let that = this;
this.orgService
.save(that.org)
.subscribe(
(org: Org): void => {
that.org = org;
that.savedOrg = new Org(org);
that.gotoParent();
},
error => this.error = error
);
}
My test:
it('responds to the Save click by saving the Org and refilling the component', async(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
comp.org.id = 2;
comp.org.name = 'Another Org';
let elButton = fixture.debugElement.query(By.css('#save'));
elButton.nativeElement.click();
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(comp.error).toBeNull();
expect(comp.savedOrg.id).toEqual(2);
expect(comp.savedOrg.name).toEqual('Another Org');
expect(routeStub).toHaveBeenCalledWith(['../']);
});
});
When I use breakpoints I see that the OrgService.save() is called when click() is run, and that in the component save() function the that.savedOrg is being set. But when the test gets into the expect() functions comp.savedOrg is at its original value. It is as though there are two component instances.
FWIW, after setting, or not setting, my savedOrg my function then tries to route. I instead get an error:
Error: Expected a spy, but got Object({ data: ScalarObservable({ _isScalar: true, value: Object({ org: Org({ id: 2, [SNIP]
I'm not sure what I'm supposed to do to tell that the "goToParent" routing has been called.
Thanks in advance for help,
Jerome.
I figured out the "not seen in test spec function" issue. I am missing a line, right after the first whenStable(), which should be:
comp = fixture.componentInstance;
That makes everything sync OK. Now I must figure out how to make route testing work. That's another job.
Jerome.

Module not found: Error: Cannot resolve 'file' or 'directory'

Can you guys please help me fixing this issue.
I have two .jsx files one imported under another one.
Lets say,
A.jsx(Inside A.jsx I have imported the B.jsx)
B.jsx
When both the files are written under same file in that case unit test cases working fine. The moment I am separating it out, still the component is working fine but the unit test cases are not running. Webpack karma throwing an error saying
ERROR in ./src/components/thpfooter/index.jsx Module not found: Error: Cannot resolve 'file' or 'directory' ./ThpFooterList in /Users/zi02/projects/creps_ui_components_library/src/components/thpfooter # ./src/components/thpfooter/index.jsx 9:1725-1751
karma.conf.js
/*eslint-disable*/
var webpack = require('karma-webpack');
var argv = require('yargs').argv;
var componentName = "**";
if (typeof argv.comp !== 'undefined' && argv.comp !== null && argv.comp !== "" && argv.comp !== true) {
componentName = argv.comp;
}
var testFiles = 'src/components/'+componentName+'/test/*.js';
var mockFiles = 'src/components/'+componentName+'/test/mock/*.json';
module.exports = function (config) {
config.set({
frameworks: ['jasmine'],
files: [
'./node_modules/phantomjs-polyfill/bind-polyfill.js',
testFiles,
mockFiles
],
plugins: [webpack,
'karma-jasmine',
'karma-phantomjs-launcher',
'karma-coverage',
'karma-spec-reporter',
'karma-json-fixtures-preprocessor',
'karma-junit-reporter'],
browsers: ['PhantomJS'],
preprocessors: {
'src/components/**/test/*.js': ['webpack'],
'src/components/**/*.jsx': ['webpack'],
'src/components/**/test/mock/*.json': ['json_fixtures']
},
jsonFixturesPreprocessor: {
// strip this from the file path \ fixture name
stripPrefix: 'src/components/',
// strip this to the file path \ fixture name
prependPrefix: '',
// change the global fixtures variable name
variableName: '__mocks__',
// camelize fixture filenames
// (e.g 'fixtures/aa-bb_cc.json' becames __fixtures__['fixtures/aaBbCc'])
camelizeFilenames: true,
// transform the filename
transformPath: function (path) {
return path + '.js';
}
},
reporters: ['spec', 'coverage','junit'],
coverageReporter: {
dir: 'build/reports/coverage',
reporters: [
{ type: 'html', subdir: 'report-html' },
{ type: 'lcov', subdir: 'report-lcov' }
]
},
junitReporter: {
outputDir: 'build/reports/coverage/junit/'+componentName,
suite: ''
},
webpack: {
module: {
loaders: [{
test: /\.(js|jsx)$/, exclude: /node_modules/,
loader: 'babel-loader'
}],
postLoaders: [{
test: /\.(js|jsx)$/, exclude: /(node_modules|test)/,
loader: 'istanbul-instrumenter'
}]
}
},
webpackMiddleware: { noInfo: true }
});
};
footer.jsx
import React from 'react';
import ThpFooterList from './ThpFooterList';
class ThpFooter extends React.Component {
//footer code here
}
ThpFooterList.jsx
import React from 'react';
class ThpFooterList extends React.Component {
//footer list code here
}
See above component is working but I am not able to execute the unit test case. When you keep both of them in one file means footer and footerlist.jsx then component as well as the unit test cases are executing.
unit test case file
/* eslint-env jasmine */
import React from 'react';
import TestUtils from 'react/lib/ReactTestUtils';
import ThpFooter from '../index.jsx';
describe('ThpFooter', () => {
let component;
let content;
let shallowRenderer;
let componentShallow;
beforeAll(() => {
content = window.__mocks__['thpfooter/test/mock/content'];
component = TestUtils.renderIntoDocument(<ThpFooter data={content}/>);
shallowRenderer = TestUtils.createRenderer();
shallowRenderer.render(<ThpFooter data={content}/>);
componentShallow = shallowRenderer.getRenderOutput();
});
describe('into DOM', () => {
it('Should be rendered into DOM', () => {
expect(component).toBeTruthy();
});
it('Should have classname as footer-container', () => {
const classname = TestUtils.scryRenderedDOMComponentsWithClass(component, 'footer-container');
expect(classname[0].className).toBe('footer-container');
});
it('Should have className as footer-wrapper', () => {
const classname = TestUtils.scryRenderedDOMComponentsWithClass(component, 'footer-wrapper');
expect(classname[0].className).toBe('footer-wrapper');
});
});
describe('into shallow renderer', () => {
it('Should be rendered as shallow renderer', () => {
expect(componentShallow).toBeTruthy();
});
it('Should have classname as footer-container', () => {
expect(componentShallow.props.className).toBe('footer-container');
});
it('Should have className as footer-wrapper', () => {
expect(componentShallow.props.children.props.children[0].props.className).toBe('footer-wrapper');
});
});
});
I experienced the same error on one of the development machines. Although gulp and webpack-stream was used in my case, I think you may reference my method to try solving it.
On my mac, everything is fine but when I pushed the code to the ubuntu development platform, this problem was observed. After some googling I cannot solve it but then I tried to make the file path to be shorter and then suddenly it works on the ubuntu development platform too! You may try to shorten the file name or place it in a shorter path and test to see if it works.
Watch for case sensitivity. Mac file system is not case-sensitive, windows/linux is.