Jest not creating snapshot or failing tests - unit-testing

I’m going through a course for React, and after running jest on my first test, it seems like it should be creating my snapshot, but it doesn’t say it has, and I don't see a snapshot file.
When I change the content in the component and run Jest again, it doesn’t fail like I would expect. I'm just running jest from the command line, and it finds the test, but always passes, regardless of how I change the component. (I assume because it's not creating a snapshot to compare against?)
What might I be doing wrong?
Here is the test:
import React from 'react'
import Search from './Search'
import renderer from 'react-test-renderer'
test('Search snapshot test', () => {
const component = renderer.create(<Search />)
const tree = component.toJSON()
expect(tree).toMatchSnapshot
})

You missed the () at the end:
expect(tree).toMatchSnapshot()

Related

Why is createLocalVue needed when testing Vue components with Vuex?

I'm reading through the Vue Testing Cookbook and Vue Test Utils's docs, where they touch on testing components with Vuex. Both sources advise using createLocalVue, but I don't fully understand why. We already have a couple of tests that use Vuex but don't use createLocalVue, and they work. So why do these sources suggest using createLocalVue?
Here's the test that appears to be a bad practice according to those sources. Is this code going to break something down the road? Is it causing unwanted side-effects we're not aware of?
import { mount } from '#vue/test-utils';
import Vuex from 'vuex';
import Component from 'somewhere';
// We don't use this and yet the code seems to work
// const localVue = createLocalVue()
// localVue.use(Vuex)
describe('Foo Component', () => {
let wrapper;
beforeEach(() => {
wrapper = mount(Component, {
// localVue, <-- We don't use this
store: new Vuex.Store({
modules: {
app: {
namespaced: true,
// ... more store stuff
}
}
})
})
});
it('should contain foo', () => {
expect(wrapper.contains('.foo')).toBe(true);
});
});
From docs:
localVue: A local copy of Vue created by createLocalVue to use when mounting the component. Installing plugins on this copy of Vue prevents polluting the original Vue copy.
In your tests, you might want to make particular changes and install plugins on the tested Vue instance. Using localVue ensures those changes are reset for every test.
An obvious advantage is you don't have to install all plugins for all tests. So your tests will be faster.
Also, when your tests get a bit more complex, if you don't use localVue you'll experience tests failing erratically based on their order, because the previously ran test, even though it passed, modified the Vue instance in a way that breaks your next test. But the next test passes when ran in isolation.
The type of errors which typically imply hair loss.
Using localVue provides a type of certainty most developers welcome when running tests. If you feel adventurous, don't use it.
It's a recommendation, not an imposition.

Unit testing Nativescript application logic on a browser

I am trying to set up unit testing for a Nativescript application, run by ng test on a browser. The problem is that whenever there is a tns-core-modules or another plugin import, the module cannot be resolved because of the platform specific files (e.g. "tns-core-modules/application/application.android.js") that never get compiled into the bundle, thus throwing an error like "Module not found: Error: Can't resolve 'tns-core-modules/application'".
I know there is a built-in unit test support in Nativescript. The problem I have with it is that it can't run on CI. I would like to be a ble to have lightweight tests for my business logic, mocking out all platform dependencies.
I have looked for a way to mock the module imports at runtime with no luck. I looked into rewire package but it only runs on node.
I finally managed to get it working. Not a very elegant solution and I have yet to see how much maintenance it requires. Key points here:
Use paths section of the tsconfig.json to add mock import
locations
In the mocks directory create files for any unresolved module
Some nativescript modules are referencing helper functions on global
scope but they're undefined. My solution was to define them in
test.ts like this
window['__decorate'] = () => {};
window['__extends'] = () => {};
window['__metadata'] = () => {};
window['__param'] = () => {};
window['layout_base_1'] = { CSSType: () => {} };
window['Crashlytics'] = {};
window['Fabric'] = {};
You simply can not run NativeScript application on Browser.
In case if you are looking for something like headless mode, Appium has one too, isHeadless in capabilities.
Between, may I know why you think you can not run the {N} unit tests on CI? It should work on CI too, after all it's a machine that runs the same commands based on some trigger.

Testing Vue Single File Components which use a Global Event Bus

I'm testing my Vue components for the first time using Mocha and Webpack and set everything up according to the docs.
However, in many of my components, I use a global event bus to communicate and emit events between components. For example, the following snippet is in the created hook of one of my single file components.
created() {
Event.$on("activate-edit-modal", (listing) => {
this.isModalActive = true; // show delete modal
this.listing = listing; // set listing as the emitted listing
});
},
Unfortunately, when I run the following test code in my test file (npm run test), I get the following error.
import { mount } from '#vue/test-utils';
import editModal from '../../../src/components/admin/editModal.vue';
const wrapper = mount(editModal);
console.log(wrapper);
Error Msg: I'm aware the error msg is referring to the created hook (in the code snippet above) and highlighting that "Event.$on" in that created hook is not a function.
WEBPACK Compiled successfully in 2331ms
MOCHA Testing...
[Vue warn]: Error in config.errorHandler: "TypeError: Event.$on is not
a function" TypeError: Event.$on is not a function
at VueComponent.created ...
How should I test my components that use a global event bus? Note that I am not interested in testing the event bus itself; however, I'm unaware on how I can proceed to test other aspects of the component with this error.
The global event bus "Event" that I use in all my components is declared in /src/main.js as shown below
import Vue from 'vue';
import App from './App.vue';
import router from "./router";
import store from "./store";
window.Event = new Vue();
let app = new Vue({
el: '#app',
router,
store,
render: h => h(App)
});
You're trying to reference a local event bus called Event. You should call the bus you registered on the window object, like this: window.Event.$on("activate-edit-modal"....
After you've ensured that your component is calling the bus registered on the window object as shown above, make sure you also add the following before you mount your component in the test file like so:
import Vue from 'vue';
window.Event = new Vue();
const wrapper = mount(adminResults);
Your global event bus "Event": where is it defined? I can't see it being imported anywhere into the component with the error. I suspect this is your problem.
Beware global event bus is a top five antipattern, according to one of the presentations at the recent vue conf. I much prefer a plain global javascript object as a global state store.
You can mock your event bus and assert that methods are called on it with correct parameters.
For instance, in the above scenario try window.Event = { $on: sinon.spy() }.
After mounting you should be able to assert that $on was called with correct parameters.
Here's documentation on Mocha and spies. https://github.com/mochajs/mocha/wiki/Spies
I'm not as familiar with mocha so I'm not exactly sure I've got the details correct.

Why do my test fail intermittently when running the whole suite?

One of my tests is failing intermittently when running the whole suite, but it doesn't fail when running it by itself.
I created a very basic repository with a vanilla application that reproduces the issue:
https://github.com/juanazam/ember-cli-test-issue.
Basically, I created a component with a text field and a button. The button is disabled while the text is empty.
The issues happens when two tests use the fillIn helper on the input.
Here is the testing code taken from the vanilla app:
test('test 1', function(assert) {
visit('/');
fillIn('input[type=text]', "Algo");
andThen(function() {
assert.equal(currentRouteName(), "index");
});
});
test('test 2', function(assert) {
visit('/');
andThen(function() {
assert.ok(find('input[type=submit]').is(':disabled'));
});
fillIn('input[type=text]', "Algo");
andThen(function() {
assert.ok(!find('input[type=submit]').is(':disabled'));
});
});
As you can see test 1 only fills the input but doesn't do anything with it. The second test tests if the button is disabled.
Test 2 fails intermittently when running the whole suite. If you run ember test -s it fails, if you reload the browser tab (re running the whole suite without restarting the server process) it passes. The same behavior happens with multiple runs (one run fails, the next succeeds).
I didn't create a twiddle reproduction case because the test runner doesn't behave the same way.
With you app:
ember test will always fail.
ember test --filter 'test 1' will always pass.
ember test --filter 'test 2' will always pass.
If you split your 2 test functions into different acceptance tests ember test will always pass.
Qunit in the browser tries to execute failing tests first. (I think to reduce the time until the most interesting failing tests are executed.). With ember -s your tests are always executed in order and tests are failing (I guess test 2 failes because test1 already filled your input and it is not initially disabled as expected).
When reloading qunit in browser after the first failed test, the failing test2 is executed first (and passes).
Also have a look on https://dockyard.com/blog/2014/04/17/ember-object-self-troll . There might be a problem within your component definition leading to the unexpectedly filled input in test2.

Jasmine Spec as Typescript File

I'm attempting to set up unit testing in my project, using Jasmine. I am writing my specs in Typescript. My first test is simply checking that a config file returns a value as expected. However, when I import the config, Jasmine can't find the spec. If I take out the import and fill in dummy values, everything works fine.
My spec file is:
/// <reference path="../typings/index.d.ts"/>
process.env.ENV = "test";
process.env.TEST_DB_NAME= "test";
import environment = require("../config/config");
describe("Config Tests:", () => {
it("db returns string", () => {
expect(environment.db).toEqual(process.env.TEST_DB_NAME);
});
});
environment.db should simply return my process.env.TEST_DB_NAME.
I feel this has to do something with the import at the beginning making Jasmine not find the describe(). Anyone know of a way to get Jasmine to work with imports or am I just going about testing this the wrong way?
If you call require directly in your file I think you need to create a module and export it. Another way that I have used import successfully has been to create an interface, export it, and then did something like this.
import IUser = UserList.Interfaces.IUser;
You can then use this as the type for a mock object.