Test case failing in mocha & chai - LitElement - mocha.js

I have started looking at the lit-html and was trying to write some unit test cases using mocha & chai with a simple component file, but it is failing with the below error.
Test case:
var assert = require('chai').assert;
var emp = require('../src/components/employee/emp-component').greeting;
describe('Emp', function () {
it('should return hello', function () {
assert.equal(emp(), 'hello');
});
});
Component:
import {
LitElement,
html
} from 'lit-element';
class EmpComponent extends LitElement {
constructor() {
super();
}
greeting() {
return 'hello';
}
}
customElements.define('emp-component', EmpComponent);
Is there an other way to do this?

you can use open-wc helpers to create lit-element test cases. open-wc helpers
step 1: once., installed open-wc., import fixture
import {fixture, html} from '#open-wc/testing'
step 2: use async & await till your component is loaded. fixture helps understand lit-element
import {fixture, html} from '#open-wc/testing'
describe('test case', () => {
it('case', async () => {
const elem = await fixture(html`<your-component></your-component`);
})
})
Once component is loaded., your test cases starts triggering. For more information on polymer 3 & lit. refer Sabarinath blog on polymer & litElements

Related

Cypress.io page objects cause 'cy.click() failed because it requires a DOM element.' error

New to cypress, but did a couple projects in Protractor and TestCafe.
I'm aware of the controversy using PO's in cypress, but due to the complexity / nature of our app, we're going with it.
Refactoring the test to remove PO's and include the app ID's works. With the page objects, we get the 'requires a DOM element' error.
// myPo.js
class LoginPage {
loginPageCon() {
return cy.get('#page-login');
}
forgotPasswordLnk() {
return cy.get('#forgotPassword');
}
emailTxt() {
return cy.get('#email');
}
forgotPasswordCon() {
return cy.get('#page-forgot-password');
}
}
export default LoginPage;
// myTest.spec.js
import loginPage from '../pageObjects/myPo.js';
const loginPage = new LoginPage();
describe('Authorization', () => {
it('can direct to the azure instance', () => {
cy.visitHome();
cy.get(loginPage.loginPageCon);
});
describe('Forgot Password', () => {
it('clicking forgot password sends you to the correct screen', () => {
cy.get(loginPage.forgotPasswordLnk).click();
cy.get(loginPage.forgotPasswordCon);
});
});
});
You are returning a function reference to cy.get() when you call cy.get(loginPage.forgotPasswordLink).
Change It to:
loginPage.forgotPasswordLink().click()
Your page object is already returning a chainable of cy.get()

Testing an Async function using Jest / Enzyme

Trying run a test case for the following:
async getParents() {
const { user, services, FirmId } = this.props;
let types = await Models.getAccounts({ user, services, firmId: FirmId });
let temp = types.map((type) => {
if(this.state.Parent_UID && this.state.Parent_UID.value === type.Account_UID) {
this.setState({Parent_UID: {label: type.AccountName, value: type.Account_UID}})
}
return {
label: type.AccountName,
value: type.Account_UID,
}
})
this.setState({ParentOptions: temp});
}
here is what i have so far for my test:
beforeEach(() => wrapper = mount(<MemoryRouter keyLength={0}><AccountForm {...baseProps} /></MemoryRouter>));
it('Test getParents function ',async() => {
wrapper.setProps({
user:{},
services:[],
FirmId:{},
})
wrapper.find('AccountForm').setState({
SourceOptions:[[]],
Parent_UID: [{
label:[],
value:[],
}],
});
wrapper.update();
await
expect(wrapper.find('AccountForm').instance().getParents()).toBeDefined()
});
If i try to make this ToEqual() it expects a promise and not anobject, what else could I add into this test to work properly.
Goal: Make sure the functions gets called correctly. The test is passing at the moment and has a slight increase on test coverage.
Using Jest and Enzyme for React Js
you can put the await before the async method, like:
await wrapper.find('AccountForm').instance().getParents()
and compare if the state was changed.
In another way, if can mock your API request, because this is a test, then you do not need the correct API, but know if the function calls the API correctly and if the return handling is correct.
And, you cand spy the function like:
const spy = jest.spyOn(wrapper.find('AccountForm').instance(), 'getParents');
and campare if the function was called if they are triggered by some action:
expect(spy).toBeCalled()

Why am I receiving this warning in a cypress task?

I'm running a task to seed my database in a before hook. Cypress is complaining that
Cypress Warning: Cypress detected that you returned a promise in a test, but also invoked one or more cy commands inside of that promise.
Here is the task
import { seed } from '../../../src/server/db/seed'
const pluginHandler = on => {
on('task', {
'seed:db': () => {
return seed()
}
})
}
export default pluginHandler
This is the seed function
import { exec } from 'child_process'
import util from 'util'
const execP = util.promisify(exec)
export const seed = () => {
// Drop notes.
return execP('mongo starter_test --eval "db.notes.drop()"')
.then(async () => {
// Insert notes fixtures.
await execP(
'mongoimport --db starter_test --collection notes --file ./src/server/db/notes.json'
)
})
.then(() => {
return 0
})
}
And finally the test, which doesn't do anything yet
describe('My First Test', () => {
before(async () => {
await cy.task('seed:db')
})
it('Does not do much!', () => {
cy.visit(Cypress.env('HOST'))
})
})
I'm not, as far as I can see, using commands inside the promise as the warning suggests.
As far as I know, async should not be used inside Cypress before, or any other command (unless you install a 3rd-party lib).
Please try with before(() => cy.task('seed:db'))

Using classes in different .ts files in jasmine

I am writting simple test in jasmine framework. I have following files stored in one folder:
maintest.ts
helper.ts
Workflow1.ts
Workflow2.ts
Workflow files have content as following (example):
import {element, by, browser, protractor} from "protractor";
import {Helper} from "../../helper";
export class Workflow1/2
{
static Foo1() {
let element1;
let element2;
describe('check all fields', function () {
it('check foobar', function () {
element1.isVisible();
});
it('check foobar2', function () {
element2.isVisible();
});
}
static Foo2() {
let element3;
let element4;
describe('check all fields', function () {
it('check foobar', function () {
element4.isVisible();
});
it('check foobar2', function () {
element3.isVisible();
});
}
}
And the maintest.ts is:
import {browser} from "protractor";
import {Helper} from "./helper";
import {Workflow1} from "./Workflow1";
import {Workflow2} from "./Workflow2";
describe ('Regression Tests', function() {
beforeAll(function () {
console.log('====================Start');
});
describe('Basic workflow', function () {
Workflow1.Foo1();
Workflow1.Foo2();
Workflow2.Foo2();
Workflow2.Foo2();
});
});
but when I run it, nothing has run correctly - I get this error:
Error: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
but if I comment:
//Workflow1.Foo2();
//Workflow2.Foo2();
//Workflow2.Foo2();
the Workflow1.Foo1 works perfectly fine.
Can't I use different methods from different files? It works with helper, where I have login and logout methods...
I think I got this. My code was 'quite' long with different describes, when I minimalized it to 2, it started working :)
EDIT: As I mentioned in comment below, each method in Workflow1 and Workflow2 files must have at least one describe and at least one it inside - having only describe without it throws error

Vuejs Unit Test - Backing Mocks with Tests

I am writing unit testing for a vuejs 2 application that uses Vuex as a store. I have the following pattern in many of my components:
example component thing.vue:
<template>
<div>
{{ thing.label }}
</div>
</template>
<script>
export default {
name: 'thing',
data() { return { } },
computed: {
thing () {
return this.$store.state.thing;
}
}
}
</script>
Example Store State:
export const state = {
thing: { label: 'test' }
};
Example Unit for Thing.vue:
describe('thing ', () => {
const storeMock = new Vuex.Store( state: { thing: { label: 'test' } } );
it('should pull thing from store', () => {
const Constructor = Vue.extend(thing);
const component new Constructor({ store }).$mount();
expect(component.thing).toEqual({ label: 'test' });
});
});
Example Unit test for Store:
import store from './store';
describe('Vuex store ', () => {
it('should have a thing object', () => {
expect(store.state.thing).toEqual({ label: 'test' });
});
});
There is a huge problem with this pattern. When another developer refractors the store state, they will see the Store test fail, but because the thing unit test is based on a mocked version of the store that test with continue to pass, even though that component will never work. There isn't a good way to know a refactor invalidated a Mock.
So how do people unit test this type of dependence?
One way would be to cheat a little on the unit test and use the real store state, but then it isn't really a unit test. The other way is rely on integration testing to catch the mock - store mismatch, but that feels like it would be painful to debug why the unit tests pass but the integration tests are failing.
What we ended up doing is using the actual store. Because the store state is just an object we figured it was acceptable.
We also use the store getters, actions and mutations as templates for jasmine spyies.
// Vuex needs polyfill
import { polyfill } from 'es6-promise';
polyfill();
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import test from 'app/components/test.vue';
import module from 'app/store/modules/module';
describe('Spec for Test.vue', () => {
var props;
var state;
var actions;
var mutations;
var getters;
var store;
beforeEach( () => {
jasmine.addMatchers(customMatchers);
props = { };
// Don't change the modules
state = Object.assign({}, module.state);
actions = Object.assign({}, module.actions);
mutations = Object.assign({}, module.mutations);
getters = Object.assign({}, module.getters);
// Add require global actions, mutations, and getters here...
actions.globalActionHere = 'anything'; // this turns into a spy
// Update State with required fields
state.defaults = { id: 1 } // default expected when the component loads
// Replace modules copies with mocks
actions = jasmine.createSpyObj('actions', actions);
mutations = jasmine.createSpyObj('mutations', mutations);
getters = jasmine.createSpyObj('getters', getters);
store = new Vuex.Store( { state: { module: state }, getters, actions, mutations } );
} );
it('should have a name of test', () => {
const Constructor = Vue.extend(thing);
const component new Constructor({ store, props }).$mount();
expect(component.$options.name).toBe('test');
});
});
Note the part
jasmine.createSpyObj('actions', actions);
Jasmine spies will use the module to create spyies for each of the methods, which is very useful.

Resources