Im using Create React App and have set up my test files like this:
import React from 'react';
import { shallow, configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
Then I set up wrapper using shallow() like this:
let wrapper;
beforeEach(() => {
const defaultProps = {
color: 'orange',
value: 17,
title: 'live services',
link: 'htttp://google.com'
};
wrapper = shallow(<Callout {...defaultProps} />);
});
Im using assertions that I have been using for a while such as
expect(wrapper.find('h5').html()).toContain('some title');
expect(wrapper.containsMatchingElement(<Foo />)).toBe(true);
These assertions work but i want to find more.
I have no idea where to find the docs for the assertions that are available to me.
The assertions I have working so far look a bit like Jasmine assertions in that they are using camel case but the methods are still named differently.
https://jasmine.github.io/
I thought I was using jest and enzyme but the assertions are completely different to those in the Enzyme docs
https://airbnb.io/enzyme/
For example
expect(wrapper.find(Foo)).to.have.lengthOf(3);
Does not work. These methods of find() are not available to my current set up.
In the Jest Docs I can only find assertions for testing javaScript functions and can't find any methods for traversing and testing Virtual DOM or shadow DOM elements like the ones I have been using( see above)
https://jestjs.io/docs/en/jest-object
How do I see what assertions are available to shallow() and shallow.find() with my current setup?
You can find the Jest assertion methods here Jest assertion methods
You could also look at this library package https://www.npmjs.com/package/jest-enzyme
Related
I have mixed application that uses Apollo for both React and non-react code.
However, I can’t find documentation or code examples around testing non-react code with the apollo client,not using MockedProvider. I did, however, notice that apollo exports a mock client from the testing directory.
import { createMockClient } from '#apollo/client/testing';
I haven’t found any documentation about this API and am wondering if it’s intended to be used publicly and, if not, what the supported approach is for this.
The reason I need this is simple: When using Next.js’ SSR and/or SSG features data fetching and actual data rendering are split into separate functions.
So the fetching code is not using React, but Node.js to fetch data.
Therefore I use apolloClient.query to fetch the data I need.
When trying to wrap a react component around that fetching code in a test an wrap MockedProvider around that the apolloClient’s query method always returns undefined for mocked queries - so it seems this only works for the useQuery hook?
Do you have any idea how to mock the client in non-react code?
Thank you for your support in advance. If you need any further information from me feel free to ask.
Regards,
Horstcredible
I was in a similar position where I wanted to use a MockedProvider and mock the client class, rather than use useQuery as documented here: https://www.apollographql.com/docs/react/development-testing/testing/
Though it doesn't seem to be documented, createMockClient from '#apollo/client/testing' can be passed the same mocks as MockedProvider to mock without useQuery. These examples assume you have a MockedProvider:
export const mockGetAssetById = async (id: Number): Promise<any> => {
const client = createMockClient(mocks, GetAsset)
const data = await client.query({
query: GetAsset,
variables: id,
})
return data
}
Accomplishes the same as:
const { data } = useQuery(
GetAsset,
{ variables: { id } }
)
I am writing Jasmine tests for my Javascript application. A major time-sink has been testing my code which depends on StripeCheckout. Stripe does not want you to use it offline. I realized I should mock the service, but that has not been easy in Jasmine.
How can I mock "custom" (instead of "simple") usage of StripeCheckout?
I tried to use spies, like so,
var StripeCheckout = jasmine.createSpyObj('StripeCheckout', ['configure']);
But I think the created object needs to attach to the global object (window).
So, I can add an object to the global
object. This worked,
but it feels lame.
Another option could be to tell
Karma to load the
page over the network. This worked for me, but it seems lame to make
a network request for tests.
I'm not sure if you have figured this out yet but an easy way to do this would be to just create a simple mocked implementation for StripeCheckout. Something like this should work.
beforeEach(function() {
module(function($provide) {
$provide.factory('StripeCheckout', function() {
//your mocked custom implementation goes here
configure: function() {
//do something
}
}
}
inject(function($injector) {
StripeCheckoutMock = $injector.get('StripeCheckout');
}
)
This way you are not making a request in order to run your tests. The test will just use the mocked service that you have set up.
Using protractor and jasmine(wd) we want to check that a table on the web page contains expected values. We get fetch the table from the page using a CSS selector:
var table = element(by.css('table#forderungenTable')).all(by.tagName('tr'));
We then set our expectations:
table.then(function(forderungen){
...
forderungen[2].all(by.tagName('td')).then(function(columns){
expect(columns[1].getText()).toEqual('1');
expect(columns[5].getText()).toEqual('CHF 277.00');
});
});
Is it possible to change this code so that we don't have to pass functions to then, in the same way that using jasminewd means that we don't have to do this? See this page, which states:
Protractor uses jasminewd, which wraps around jasmine's expect so that you can write:
expect(el.getText()).toBe('Hello, World!')
Instead of:
el.getText().then(function(text) {
expect(text).toBe('Hello, World!');
});
I know that I could write my own functions in a way similar to which jasminewd does it, but I want know if there is a better way to construct such expectations using constructs already available in protractor or jasminewd.
You can actually call getText() on an ElementArrayFinder:
var texts = element(by.css('table#forderungenTable')).all(by.tagName('tr')).get(2).all(by.tagName('td'));
expect(texts).toEqual(["text1", "text2", "text3"]);
I have promisified Mongoose. I have some methods that extent Mongoose Query that now would need to be added to Bluebird. I don't mind extending Mongoose but do not want to take the same approach for this more gobal library. Looking through the docs I see some potentials but I am not sure.
I would like to come as close/clean as the following:
Model.findAsync().toCustom();
toCustom is basically a form of toJSON which 1) execs the query and 2) custom outputs the results/create custom errors etc... pretty straighforward.
What is the cleanest way to achieve something like the above? I would like to avoid doing this each time:
Model.findAsync().then(function(docs) {
return toCustom(docs);
}, function(err) {
return toCustom(err);
});
You get the idea...
Bluebird actually supports your use case directly. If you need to publish a library that extends bluebird in your own custom way you can get a fresh copy of bluebird by doing:
var Promise = require("bluebird/js/main/promise")();
Promise.promisifyAll(require("mongoose")); // promisify with a local copy
Promise.prototype.toCustom = function(){
return this.then(toCustom, toCustom); // assuming this isn't just `.finally`
};
You might also want to export it somehow. This feature is designed for library authors and for getting an isolated copy of bluebird. See the for library authors section in the wiki.
I started using Protractor and the first thing I've tried to do is to use Mocha and Chai instead of Jasmine. Although now I'm not sure if that was a good idea.
first I needed to make Chai accessible from all the spec files, without having to import everytime, I found it's possible to do in protractor.conf file:
onPrepare: ->
global.chai = require 'chai'
chai.use require 'chai-string'
chai.use require 'chai-as-promised'
global.expect = chai.expect
now in a spec like this:
it "when clicked should sort ",->
headerColumns.get(0).click()
firstCellText = $$(".first-cell").getText()
secondCellText = $$(".second-cell").getText()
# this won't work
expect(firstCellText).eventually.be.above(secondCellText)
to make it work I could do:
# now this works
$$(".second-cell").getText().then (secondCellText)->
expect(firstCellText).eventually.be.above(secondCellText)
but that's ugly, and I don't want to wrap stuff inside of .then all the time. I'm thinking there should be a better way(?)
I was having the same problem. The issue for me was to add a longer timeout to mocha through the Protractor config.js.
This works because Protractor tests take considerably longer relative to other modules like supertest since an actual browser is being interacted with.
I added
mochaOpts: {
timeout: 5000
}
to my protractor config and the tests passed.
Either you need to mention timeout for the whole test suite using "this.timeout(1000);" just below the describe block, or you can change it for individual test cases by explicitly defining timeout for each "it" block.
example for describe block:
describe("test-suite",function () {
this.timeout(5000);
it("test-case",function () {
//test case code goes here
});
});
example for it block:
it("test-case",function () {
this.timeout("20000");
});
I found this question while I was trying to do the same thing in TypeScript, but the approach in the protractor.conf.js is identical.
Making chai available globally
It appears to achieve this you're right that it needs to be done in the on prepare. a fairly terse example is below. As I understand it this is needed because chai is of course not apart of mocha but some additional candy that we can use with mocha. Unlike jasmine where everything is bundled into the framework.
protractor.conf.js fragment
onPrepare: function() {
var chai = require('chai'); // chai
var chaiAsPromised = require("chai-as-promised"); // deal with promises from protractor
chai.use(chaiAsPromised); // add promise candy to the candy of chai
global.chai = chai; // expose chai globally
}
example spec
Once you've got chai and chai-as-promised setup globally you need to add a "little" boiler plate to your spec to expose expect which comes from chai.
example.e2e-spec.ts fragment
const expect = global['chai'].expect; // obviously TypeScript
it('will display its title', () => {
pageObject.navigateTo();
const title = element(by.css('app-root h1')).getText();
expect(title).to.eventually.contain('An awesome title');
});
Avoiding then
I can't tell what your $$ references are, but if you're using the protractor components browser and by etc. then things clean up a little bit.
The call const title = element(by.css('app-root h1')).getText(); seems to return a promise which jasmine seems to deal with out of the box while mocha+chai doesn't. That's where chai-as-promised comes in.
using our additional syntax candy expect(title).to.eventually.contain('An awesome title'); resolves the promise quite neatly and we've avoided all those then calls, but we do need the eventually.
I've provided you a link to a working TypeScript example that might help demonstrate.