Unit Testing on Computed Property while running SQL query - javascript

I have a computed property in a Vue app I'm tasked with creating unit tests with using jest. I've never used jest before and confused if there's a way to test for a returned value I'm injecting using DBeaver. All I'm getting on the jest side of things is undefined from my attempts while seeing the app locally displaying the desired state change when that value is being adding/removing with SQL using DBeaver. Is there a way to unit test this??
For example sake, let's say I have a default config key and a custom config key. I'd like to use the custom config key if it's present and use the default when it's not.
My computed logic is:
customConfigKey () {
return this.customConfigKey ?? this.defaultConfigKey;
}
I'm confused how to test this when the value for the customConfigKey is being set via DBeaver via a SQL querie.
Here's what I have for the unit test (the only thing I've been able to see a test pass due to obvious shortcomings.
describe('custom config key ', () => {
it('returns undefined if configKey does not exist', () => {
expect(wrapper.vm.CustomConfigKey).toBe(undefined); // value_returned
});
});

Related

How can I add properties to a component in a unit test before init?

I'm working on an Ember component with an init function that I'd like to add a unit test for. The component has the following properties:
1) The init function must not be run more than once, and
2) The component depends on having a model (currentUser) passed to it.
So far I have tried writing a test like this:
test('#init', function(assert) {
const component = this.owner.lookup('component:component-that-depends-on-property');
const currentUser = make('user');
component.set('currentUser', user);
component.init();
assert.ok(component.somethingHasHappened);
});
My problem is that init method is run on the owner.lookup line, meaning I have no way of getting the currentUser into the component before it runs. Again, I cannot run the init method more than once without blowing up the component's state.
I noticed that the lookup method takes an options argument and thought I might be able to use that to pass currentUser in, but that doesn't seem to work and I couldn't find much documentation on the lookup method.
I'd like to avoid writing an integration test for this, if possible. Is there a good way of doing this/workaround I'm not seeing?
I would suggest writing integration tests for components. Avoid writing unit test cases for components rather write unit test cases for controllers, mixins, models, routes, services
If you do unit test the component, you can do:
const component = this.owner.factoryFor('component:component-that-depends-on-property').create({
currentUser: user,
});
That will create an instance of your component with currentUser set. You will not need to call init() explicitly because it is called on create().

Cannot mock external node module

I am trying to mock an external module (jwt_decode for those interested), and I have seen many examples of how to mock external an node module using Jest both for all tests in a test suite, as well as on a per-test basis.
I have been able to mock the dependency so that it mocks the return value for all tests in the suite, although the default function is all that i'm really concerned with.
import jwt_decode from 'jwt-decode';
jest.mock('jwt-decode', () => jest.fn().mockReturnValue({
exp: 12345,
somethingElse: 'test_value'
}));
This works well, except I would like to test a scenario where the returned token has expired, so that I can verify that certain Redux actions were dispatched when this situation arises.
import jwt_decode from 'jwt-decode';
const decoded = jwt_decode(localStorage.jwtToken);
// set user info and isAuthenticated
store.dispatch(setCurrentUser(decoded));
// this is the scenario I am looking to test
const currentTime = Date.now() / 1000;
if (decoded.exp < currentTime) {
store.dispatch(logoutUser());
store.dispatch(clearCurrentProfile());
window.location.href = '/login';
}
I would like to modify the returned mock for an individual test so that I can ensure that the 'if' statement shown equates to false, and other parts of the code base are executed.
How can one go about this?
Some of the examples I have tried and failed with so far include:
test('some test that will use a different mock' () => {
// re-assign value of the imported module using the its given alias
jwt_decode = jest.fn().mockImplementation(() => {
return {
exp: 'something_different 9999999999',
somethingElse: 'I_changed_too'
};
});
});
As well as
jwt_decode.default = jest.fn().mockImplementation(() => {
return {
exp: 'something_different 9999999999',
somethingElse: 'I_changed_too'
};
});
And also jest.spyOn(), as seen in this SO question, as well as A Jar of Clay's answers on the same question, which proposes the following:
import { funcToMock } from './somewhere';
jest.mock('./somewhere');
beforeEach(() => {
funcToMock.mockImplementation(() => { /* default implementation */ });
});
test('case that needs a different implementation of funcToMock', () => {
funcToMock.mockImplementation(() => { /* implementation specific to this test */ });
// ...
});
I also found a suggestion for creating a util which changes the global localStorage on a test by test basis, but I would rather not use a real jsonwebtoken, or have to worry about storing sign-in credentials.
What I keep ending up with is that jwt_decode is not updated when running the test that should have the different mock value returned, or what's more common is that I get an error saying that ".default is not a function".
If you have suggestions, I would be very grateful.
Assuming I understand your ultimate goal, how about this approach:
In your project directory, at the same level as node_modules, create a directory called "__mocks__" and in that directory, put a file called "jwt-decode.js" -- with this in place there is no need to explicitly mock jwt-decode in your test module, as it will always be mocked automatically.
Put the following code in your __mocks__/jst_decode.js file:
export default token => token;
Thus, when the code that you're testing calls jwt_decode(something), the return value will be exactly what was passed in.
Now you can write unit tests that test the behavior of your module given various valid or invalid values in the token; just mock the token value in your module and your mocked implementation of jwt_decode() will simply pass it through.

Jest Testing with React Native and Contentful

I am trying to test my React Native Application with Jest. I am using Contentful as a CMS to hold my backend information. I am currently trying to test that I am initializing the correct client.
Here is the code I used to initialize the client:
var client = contentful.createClient({
space: 'w20789877', // whatever the space id is
accessToken: '883829200101001047474747737' // some accessToken
})
Here is the code I used to test initializing the client:
describe ('should initialize the correct client', () => {(
it('should initialize the correct client info from contentful', () =>{
expect(client).toEqual('w20789877', '883829200101001047474747737')
});
)};
However, I am getting an error message stating that:
Difference: Comparing two different types of values. Expected undefined but received string.
For some reason I am receiving undefined for the space and accessToken but I correctly initialize the client, as I am able to use the space later on. Even when trying to print out the space and accessToken an undefined value prints.
These are several issues here:
The toEqual matcher receives a single value parameter; you're sending 2
parameters, so effectively only the first one is being used.
The client in this case is a function and you're trying to compare it to a string. Regardless of the fact that the client is not a string, in your case it's also undefined, hence the message "Expected undefined but received string". You are not testing the space or accessToken here, you are testing the client.
I'm not completely sure what you're trying to test here, but this is not specifically related to Contentful.
I'm assuming that the client initialization part is somewhere in the code which you want to unit-test (and not initialized in the test file). I suggest a test that checks that the createClient function of the contentful is being called with your expected parameters when your code is executed; there's no need to test that the client is created - that's Contentful's responsibility to make sure they return a valid client object. What's important is that you pass the correct "space" and "accessToken" parameters required for your app.
Generally speaking, external services should be mocked, and you should only test your own logic and interaction with the external services.
Example
To make it simple, lets say that the code that initializes your client looks like this:
//client.js
var contentful = require('contentful')
export default function initializeClient() {
var client = contentful.createClient({
space: 'w20789877', // whatever the space id is
accessToken: '883829200101001047474747737' // some accessToken
});
}
The test might look something like this:
//client.test.js
describe('contentful client', () => {
let contentful;
let initializeClient;
beforeEach(() => {
jest.mock('contentful');
contentful = require('contentful');
initializeClient = require('./client').default;
});
it('should initialize the contentful client with the correct params', async () => {
initializeClient();
expect(contentful.createClient).toHaveBeenCalledWith({
space: 'w20789877',
accessToken: '883829200101001047474747737'
});
});
});
Note: I didn't actually run or test the above code, but this is the general concept.

Testing with Jest a method in React that calls another irrelevant method to the test

Learning unit-testing, I am trying to use Jest to test React components. But i ran into an error while testing a method of a component that calls another method, that resides into another project entirely and then the parent method changes the state of it's component, so everything on the other method that is being called is normally undefined, therefore resulting on this test error. Can anyone guide me how to approach this problem? Supposing that the method being tested is:
methodToBeTested() {
methodResidingIntoAnotherProject();
this.setState({someState: true}); // someState is initially false
}
And the testing:
describe("testing the component's behaviour"), () => {
it("testing the methodToBeTested", () => {
const {wrapper} = setup();
wrapper.setState({someState: false});
wrapper.instance().methodToBeTested();
expect(wrapper.state().someState).toEqual(true);
});
});
The wrapper and the whole setup works, because i have tried some other structural tests, that have passed. The error that is being thrown is:
"TypeError: Cannot read property 'someVariable' of undefined". The 'someVariable' is in the nested method.

Testing a React component - determining where the functionality should be tested

I am extremely new to testing in general, not just React testing, so I'm still trying to figure out not only how to test, but what to test.
Here is my login callback that gets called on submit of a form:
login() {
let typedUsername = React.findDOMNode(this.refs.username).value;
if (!typedUsername) {
return this.setState({
errored: true
});
}
// we don't actually send the request from here, but set the username on the AuthModel and call the `login` method below
AuthModel.set('username', typedUsername);
AuthModel.login();
},
AuthModel is a Backbone.js Model. But for this question, lets just say it's an external module that I'm importing into my Login.jsx component.
I'm writing a test to see that if a username is typed, then AuthModel.login() gets called. Do I want to test that in my test.Login.js test file, do I test that in my test.AuthModel.js test file?
it('calls login when there\'s a username present', () => {
React.findDOMNode(LoginElement.refs.username).value = 'foo';
TestUtils.Simulate.submit(form);
// not sure which direction to take this test
});
Current test (in test.login.js) for context...
Any advice is appreciated, as like I said, this is genuinely the first testing I've ever done.
Sounds like you want a spy. This will stub out the real implementation of AuthModel and replace it with an object you can make expectations against:
spyOn(AuthModel, 'login');
// trigger login somehow
expect(AuthModel.login).toHaveBeenCalled();
Or if you also want to test the arguments which are passed:
expect(AuthModel.login).toHaveBeenCalledWith('username', 's3cretpassw0rd);

Categories

Resources