How to unit test dom manipulating functions in angular tests - unit-testing

I have an angular-cli based project, with a component that has some logic like this:
colorLine() {
let svgDoc = this.svg.nativeElement.contentDocument;
JSON.parse(this.stations).forEach(station => {
station.element = svgDoc.getElementById(station.name);
station.element.removeAttribute('class');
if (station.status === 'running') {
station.element.setAttribute('fill', 'lime');
}
return station;
})
}
I am trying to unit test this with the following test:
it('should color running stations green', async(() => {
component.svg.nativeElement = new DOMParser().parseFromString(svgDoc, 'application/xml');
component.load();
expect(component.stations[0].element.getAttribute('fill')).toBe('lime');
}));
where svgDoc is a string representation of the element to query. However, I am getting the issue:
TypeError: Cannot read property 'getAttribute' of undefined
How can I test this sort of functionality?

Related

Angular testing mocking store.pipe in component

I have a container which host different component. The angular service call the restAPI and update the store with data. Now the component fetch data from store something like below on nginit() below getEmloyeeState is selector which gets data from store.
ngOnInit(): void {
this.store.pipe(select(getEmployeeState)).subscribe(emp => {
this.employee = emp;
});
}
To test the component I am trying to mock store.pipe like below.
beforeEach(() => {
mockStore = jasmine.createSpyObj('store', ['pipe']);
it('When ngOnInit called, it should initlize emp object',
() => {
mockStore.pipe.and.callFake(() => {
return {
subscribe: (callback) => {
callback({
empObj: empObj
})
}
}
});
empComponent.ngOnInit();
expect(empComponent.employee.empId).toEqual('EMP1000');
});
});
looks like mocking store.pipe pass through but in ngOnInit the employee object is not getting initialize as it return Expected undefined to equal EMP1000
any suggestion/help would be appreciated.

How to test react component correctly?

Recently I am learning to test React with jest and enzyme, It seems hard to understand what a unit test is it, my code
import React from "react";
class App extends React.Component {
constructor() {
super();
this.state = {
value: ""
};
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
const value = e.target.value;
this.setState({
value
});
}
render() {
return <Nest value={this.state.value} handleChange={this.handleChange} />;
}
}
export const Nest = props => {
return <input value={props.value} onChange={props.handleChange} />;
};
export default App;
and my test
import React from "react";
import App, { Nest } from "./nest";
import { shallow, mount } from "enzyme";
it("should be goood", () => {
const handleChange = jest.fn();
const wrapper = mount(<App />);
wrapper.find("input").simulate("change", { target: { value: "test" } });
expect(handleChange).toHaveBeenCalledTimes(1);
});
IMO, the mocked handleClick will intercept the handleClick on App,
if this is totally wrong, what's the right way to use mock fn and test the handleClick be called.
Another: I search a lot, read the similar situations, seem like this iscontra-Unit Test,
Probably I should test the two component separately, I can test both components,
test the
<Nest value={value} handleChange={handleChange} />
by pass the props manually, and then handleChangeinvoked by simulate change
it passed test.
but how can I test the connection between the two?
I read
some work is React Team's Work
...
I don't know which parts I have to test in this case, and Which parts react already tested and don't need me to test. That's confusing.
You should take the path of testing the Nest component in isolation first, passing your mocked handleChange as a prop, to verify that input changes are being propagated.
If you want to test the state part, then you can get the instance of your App class from enzyme and call that method directly:
it("should update the Nest value prop when change is received", () => {
const wrapper = mount(<App />);
const instance = wrapper.instance()
instance.handleChange( { target: { value: "test" } })
const nestComponent = wrapper.find("Nest").first()
expect(nestComponent).prop('value').toEqual('test');
});
This a very very basic, almost not needed to test piece of code, but it will get your test coverage up if that's what you're after.
Doc for instance: http://airbnb.io/enzyme/docs/api/ReactWrapper/instance.html
If you want to test for the connection. From what I see, the nest component is a child component inside the App component. You could test that <App /> contains `.
describe('<App />', () => {
it('should contain a nest component', () => {
const wrapper = mount(<App />);
expect(wrapper.find(<Nest />)).toHaveLength(1);
});
});
Secondly, since the onChange event on the nest component updates the state in the App component, you can also test for state changes since its a behavior you expect.
it('should update state', () => {
//find input and simulate change with say {value: 'new value'} and then
expect(wrapper.state().value).toBe('newValue');
});
I hope this helps.

How to unit test if Vuex action has been dispatched in VueJS

I just want to test if myAwesome action is dispatched when my App.vue component is created(). Is this something you would test? I'm using Jasmine for these tests. Any help would be awesome!
App.js
describe('when app is created()', () => {
it('should dispatch myAwesomeAction', (done) => {
const actions = {
myAwesomeAction() {
console.log('myAwesomeAction')
// commit()
}
}
const state = {
myAwesomeAction: false
}
const mutations = {
LOAD_SUCCESS(state) {
state.myAwesomeAction = true
}
}
const options = {
state,
mutations,
actions
}
const mockStore = new Vuex.Store(options)
spyOn(mockStore, 'dispatch')
const vm = new Vue({
template: '<div><component></component></div>',
store: mockStore,
components: {
'component': App
}
}).$mount()
Vue.nextTick(() => {
expect(mockStore.dispatch).toHaveBeenCalled()
expect(mockStore.dispatch).toHaveBeenCalledWith('myAwesomeAction')
done()
})
})
})
Errors:
1) should dispatch myAwesomeAction
App
Expected spy dispatch to have been called.
webpack:///src/views/App/test/App.spec.js:49:6 <- index.js:50916:50
webpack:///~/vue/dist/vue.esm.js:505:15 <- index.js:3985:24
nextTickHandler#webpack:///~/vue/dist/vue.esm.js:454:0 <- index.js:3934:16
Expected spy dispatch to have been called with [ 'loadOrganisation' ] but it was never called.
webpack:///src/views/App/test/App.spec.js:50:54 <- index.js:50918:54
webpack:///~/vue/dist/vue.esm.js:505:15 <- index.js:3985:24
nextTickHandler#webpack:///~/vue/dist/vue.esm.js:454:0 <- index.js:3934:16
The thing is, you are trying to unit test a store from a component, so there's a little bit of a problem when you are mocking some elements and relying in true functionality in other elements. I'm no expert in vuex, I had a similar problem trying to spy on a store action and call a component's method (can't remember what the problem was, i remember i did waste half a day with it).
My suggestion: test component as unit, then test store module as unit, that means in your app component you can spy
spyOn(vm, 'myAwesomeAction');
Vue.nextTick(() => {
expect(vm.myAwesomeAction).toHaveBeenCalled()
done()
});
(that is, check if initializing your component, your method that calls the store action is called, in my example myawesomeaction will be a mapAction name in the methods object)
And then, you can unit test your store, and check that if you call myawesomeaction the mutation on that component will occur
check the test action helper here: https://vuex.vuejs.org/en/testing.html

How can I test computed properties in VueJS?

I'm using VueJS from Vue CLI. So all my components are in .vue format.
In one of my components, I have an array called fields in the data section.
//Component.vue
data() {
return {
fields : [{"name" : "foo", "title" : "Foosteria"}, {"name" : "bar", "title" : "Barrista"}]
}
}
I have a computed property that is a subset of fields
//Component.vue
computed : {
subsetOfFields () {
// Something else in component data determines this list
}
}
I've set up all of my unit tests in jasmine like this and they work fine.
//Component.spec.js
import Vue from 'vue'
import MyComponent from 'Component.vue'
describe("Component test", function() {
var myComponentVar = new Vue(MyComponent);
var vm = myComponentVar.$mount();
beforeEach(function() {
vm = myComponentVar.$mount();
);
afterEach(function() {
vm = myComponentVar.$destroy();
});
it("First spec tests something", function() {
...
});
});
For everything else, doing something inside the spec, then running assertions on the data objects works just fine. However, running an assertion on subsetOfFields always returns an empty array. Why so? What should I do, in order to be able to test it?
FYI, I even tried nesting the spec inside another describe block and then adding a beforeEach which initializes the fields array. It did not work.
However, initializing fields inside the generic beforeEach function worked. But I don't want to initialize the fields array with that mock data for the other specs.
I came across this link that talks about testing and the section you'll need to look at is the Vue.nextTick(...) section
https://alligator.io/vuejs/unit-testing-karma-mocha/
The block I'm talking about is below:
import Vue from 'vue';
// The path is relative to the project root.
import TestMe2 from 'src/components/TestMe2';
describe('TestMe2.vue', () => {
...
it(`should update when dataText is changed.`, done => {
const Constructor = Vue.extend(TestMe2);
const comp = new Constructor().$mount();
comp.dataProp = 'New Text';
Vue.nextTick(() => {
expect(comp.$el.textContent)
.to.equal('New Text');
// Since we're doing this asynchronously, we need to call done() to tell Mocha that we've finished the test.
done();
});
});
});

React unit testing

I am trying to write test cases of react component in Mocha + Enzyme. I have used Sinon to spy document elements.
In a react component method i have below statement, where trying to add a value for Select element on Button click event.
handleClick(e){
e.preventDefault();
if(e.target.value!='select')
this.setState({
selectedValue: e.target.value
})
else
document.getElementsByName("foodSelector")[0].value="select";
}
So i tried mocking this method as below using Mocha,
describe('(Container) ReactContainer', () => {
beforeEach(function(){
wrapper = shallow(<SelectContainer/>);
})
it('should trigger change event when policy dropdown is clicked', function(){
const selectElt = wrapper.find('#foodSelector');
selectElt.simulate('change', { preventDefault() {}, target: { value: 'TestingValue' } });
selectElt.simulate('change', { preventDefault() {}, target: { value: 'select' } });
});
});
I am getting an error as 'TypeError: Cannot set property 'value' of undefined', so can anyone help me on how to mock the document.getElementById?
I tried using sinon as below,
var selectElt = document.createElement('select');
selectElt.id = 'foodSelector';
var f = sinon.stub(document, 'getElementById').withArgs('foodSelector').returns(selectElt);
expect(f.value).to.be.equal('select');
Even then i am getting the same error as below,
TypeError: Cannot set property 'value' of undefined