This is my code for a quasar component that I want to mock
emits: [
"buyer-protection",
...useDialogPluginComponent.emits
]
But I get the following error:
TypeError: _quasar.useDialogPluginComponent.emits is not iterable
I'd like to mock useQuasar and usePluginDialogComponent from the quasar module. I tried to mock them this way:
jest.mock('quasar', () => ({
useDialogPluginComponent: () => ({
emits: []
}),
useQuasar: () => ({
platform: {
is: {
desktop: true
}
}
})
}))
How can I mock these quasar components?
I tried to mock useDialogPluginComponent, too.
But I realized that installQuasarPlugin() will handle all Quasar plugins, so I don't need to mock any plugin by myself.
But It has to create the instance by mount, don't use shallowMount, that is make sure dialogRef = vue.ref(null) will catch q-dialog.
For my example, I want to check 'onDialogOK' has been called, but I can't track 'onDialogOK' by spyOn, so I check the wrapper.vm emitted.
expect(vueWrapper.emitted()).toHaveProperty('ok');
It works.
I am not sure why useDialogPluginComponent is both a function instance and object instance.
As a workaround, I have defined a function and assigned emits object to it.
jest.mock("quasar", () => {
let t1 = () => {
return {
dialogRef: {},
onDialogHide: () => {},
onDialogOK: () => {},
onDialogCancel: () => {}
}
};
t1.emits = ['ok', 'hide'];
return {
useQuasar: () => ({
platform: {
is: {
Mobile: true,
},
},
}),
useDialogPluginComponent: t1
}
});
Related
I'm testing a service in my NestJs application which calls a factory to receive an object with a method up(), which I'm mocking like this:
export const mockExecutorFactory = {
getExecutor: jest.fn().mockImplementation(() => {
return {
up: jest.fn().mockImplementation((_updatedInstance, _parameters) => {
console.log('****************************');
return Promise.resolve({ successful: true });
}),
};
}),
};
In my describe block for the service test I initialize the executor like this:
let executor;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
InstanceService,
{ provide: getRepositoryToken(Instance), useValue: mockInstanceRepository },
ExecutorFactory,
],
})
.overrideProvider(ExecutorFactory)
.useValue(mockExecutorFactory)
.compile();
service = module.get<InstanceService>(InstanceService);
executor = module.get<ExecutorFactory>(ExecutorFactory).getExecutor();
});
And the test its self is written like this:
it('should create a new instance with default settings', async () => {
// Check if instance created correctly
expect(
await service.createInstance(
MOCK_INSTANCE_CREATE_PARAMS.solutionId,
MOCK_INSTANCE_CREATE_PARAMS.instanceType,
MOCK_INSTANCE_CREATE_PARAMS.orgId,
MOCK_INSTANCE_CREATE_PARAMS.parameters,
MOCK_INSTANCE_CREATE_PARAMS.customPrice,
true,
MOCK_INSTANCE_CREATE_PARAMS.req,
),
).toEqual({ instance: MOCK_INSTANCE_DEFAULT });
console.log(executor);
expect(executor.up).toHaveBeenCalled();
});
Essentially, the createInstance() runs through some logic and at the end is supposed to call the executor's up() function.
From the terminal output (photo below) I can see by the console logs that the the up() is being called, but the test fails... Any idea why?
I am using Cypress for my end to end Integration tests. I have a use case which involves returning a list of objects from Cypress Custom Commands and I have a difficulty in doing so. Here is my code pointer:
index.ts
declare global {
namespace Cypress {
interface Chainable<Subject> {
getTestDataFromElmoDynamoDB({locale, testType}): Cypress.Chainable<JQuery<expectedData[]>> // ??? not sure what return type should be given here.
}
}
}
Cypress.Commands.add('getTestDataFromDynamoDB', ({locale, testType}) => {
// expectedData is an interface declared. My use case is to return the list of this type.
let presetList: expectedData[]
cy.task('getTestDataFromDynamoDB', {
locale: locale,
testType: testType
}).then((presetData: any) => {
presetList = presetData;
// the whole idea here is to return presetList from cypress task
return cy.wrap(presetList) //??? not sure what should be written here
})
})
sampleSpec.ts
describe('The Sample Test', () => {
it.only('DemoTest', () => {
cy.getTestDataElmoDynamoDB({
locale: env_parameters.env.locale,
testType: "ChangePlan"
}).then((presetlist) => {
// not sure on how to access the list here. Tried wrap and alias but no luck.
presetList.forEach((preset: expectedData) => {
//blah blah blah
})
})
})
})
Did anyone work on similar use case before?
Thanks,
Saahith
Here My own command for doing exactly that.
Cypress.Commands.add("convertArrayOfAlliasedElementsToArrayOfInteractableElements", (arrayOfAlliases) => {
let arrayOfRecievedAlliasValues = []
for (let arrayElement of arrayOfAlliases) {
cy.get(arrayElement)
.then(aelement =>{
arrayOfRecievedAlliasValues.push(aelement)
})
}
return cy.wrap(arrayOfRecievedAlliasValues)
})
The way I do it is to pass it in an array and cy.wrap the array, Because it lets you chain the command with an interactable array.
The key point is - it has to be passed as array or object, because they are Reference types, and in cypress it is hard to work with let/var/const that are value types.
You can also allias the cy.wrapped object if you like.
The way to use it in code is:
cy.convertArrayOfAlliasedElementsToArrayOfInteractableElements(ArayOfElements)
What you asked for can be implemented as follows, but I do not know what type expectedData is, so let's assume that expectedData:string [], but you can replace string[] with your type.
plugins/index.ts
module.exports = (on: any, config: any) => {
on('task', {
getDataFromDB(arg: {locale: string, testType: string}){
// generate some data for an example
const list: string[] = [];
list.push('a', 'b');
return list;
},
});
};
commands.ts
declare global {
namespace Cypress {
interface Chainable<Subject> {
getTestDataElmoDynamoDB(arg: {locale: string, testType: string}): Cypress.Chainable<string[]>
}
}
}
Cypress.Commands.add('getTestDataElmoDynamoDB', (arg: {locale: string, testType: string}) => {
let presetList: string[] = [];
cy.task('getDataFromDB', arg)
.then((presetData?: string[]) => {
expect(presetData).not.be.undefined.and.not.be.empty;
// if the data is incorrect, the code will break earlier on expect, this line for typescript compiler
if (!presetData || !presetData.length) throw new Error('Present data are undefined or empty');
presetList = presetData;
return cy.wrap(presetList); // or you can return cy.wrap(presetData)
});
});
db.spec.ts
describe('Test database methods', () => {
it('When take some test data, expect that the data was received successfully ', () => {
cy.getTestDataElmoDynamoDB({ locale: 'someEnvVar', testType: 'ChangePlan' })
.then((list) => {
expect(list).not.empty.and.not.be.undefined;
cy.log(list); // [a,b]
// You can interact with list here as with a regular array, via forEach();
});
});
});
You can also access and receive data from cy.task directly in the spec file.
describe('Test database methods', () => {
it('When take some test data, expect that the data was received successfully ', () => {
cy.task('getDataFromDB', arg)
.then((list?: string[]) => {
expect(list).not.be.empty.and.not.be.undefined;
cy.log(list); // [a,b] — the same list as in the version above
});
});
});
I'm trying to a test a async function of a service in nestJS.
this function is async... basically get a value (JSON) from database (using repository - TypeORM), and when successfully get the data, "transform" to a different class (DTO)...
the implementation:
async getAppConfig(): Promise<ConfigAppDto> {
return this.configRepository.findOne({
key: Equal("APPLICATION"),
}).then(config => {
if (config == null) {
return new class implements ConfigAppDto {
clientId = '';
clientSecret = '';
};
}
return JSON.parse(config.value) as ConfigAppDto;
});
}
using a controller, I checked that this worked ok.
Now, I'm trying to use Jest to do the tests, but with no success...
My problem is how to mock the findOne function from repository..
Edit: I'm trying to use #golevelup/nestjs-testing to mock Repository!
I already mocked the repository, but for some reason, the resolve is never called..
describe('getAppConfig', () => {
const repo = createMock<Repository<Config>>();
beforeEach(async () => {
await Test.createTestingModule({
providers: [
ConfigService,
{
provide: getRepositoryToken(Config),
useValue: repo,
}
],
}).compile();
});
it('should return ConfigApp parameters', async () => {
const mockedConfig = new Config('APPLICATION', '{"clientId": "foo","clientSecret": "bar"}');
repo.findOne.mockResolvedValue(mockedConfig);
expect(await repo.findOne()).toEqual(mockedConfig); // ok
const expectedReturn = new class implements ConfigAppDto {
clientId = 'foo';
clientSecret = 'bar';
};
expect(await service.getAppConfig()).toEqual(expectedReturn);
// jest documentation about async -> https://jestjs.io/docs/en/asynchronous
// return expect(service.getAppConfig()).resolves.toBe(expectedReturn);
});
})
the expect(await repo.findOne()).toEqual(mockedConfig); works great;
expect(await service.getAppConfig()).toEqual(expectedReturn); got a timeout => Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout;
using debug, I see that the service.getAppConfig() is called, the repository.findOne() too, but the .then of repository of findOne is never called.
Update: I'm trying to mock the repository using #golevelup/nestjs-testing, and for some reason, the mocked result don't works on service.
If I mock the repository using only jest (like code below), the test works... so, I think my real problem it's #golevelup/nestjs-testing.
...
provide: getRepositoryToken(Config),
useValue: {
find: jest.fn().mockResolvedValue([new Config()])
},
...
So, my real problem is how I'm mocking the Repository on NestJS.
For some reason, when I mock using the #golevelup/nestjs-testing, weird things happens!
I really don't found a good documentation about this on #golevelup/nestjs-testing, so, I gave up using it.
My solution for the question was to use only Jest and NestJS functions... the result code was:
Service:
// i'm injecting Connection because I need for some transactions later;
constructor(#InjectRepository(Config) private readonly configRepo: Repository<Config>, private connection: Connection) {}
async getAppConfig(): Promise<ConfigApp> {
return this.configRepo.findOne({
key: Equal("APPLICATION"),
}).then(config => {
if (config == null) {
return new ConfigApp();
}
return JSON.parse(config.value) as ConfigApp;
})
}
Test:
describe('getAppConfig', () => {
const configApi = new Config();
configApi.key = 'APPLICATION';
configApi.value = '{"clientId": "foo", "clientSecret": "bar"}';
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [
ConfigAppService,
{
provide: getRepositoryToken(Config),
useValue: {
findOne: jest.fn().mockResolvedValue(new
Config("APPLICATION", '{"clientId": "foo", "clientSecret": "bar"}')),
},
},
{
provide: getConnectionToken(),
useValue: {},
}
],
}).compile();
service = module.get<ConfigAppService>(ConfigAppService);
});
it('should return ConfigApp parameters', async () => {
const expectedValue: ConfigApp = new ConfigApp("foo", "bar");
return service.getAppConfig().then(value => {
expect(value).toEqual(expectedValue);
})
});
})
some sources utilized for this solution:
https://github.com/jmcdo29/testing-nestjs/tree/master/apps/typeorm-sample
I think expect(await repo.findOne()).toEqual(mockedConfig); works because you mocked it, so it returns right away.
In the case of expect(await service.getAppConfig()).toEqual(expectedReturn);, you did not mock it so it is probably taking more time, thus the it function returns before the Promise resolved completely.
The comments you posted from jest documentation should do the trick if you mock the call to getAppConfig().
service.getAppConfig = jest.fn(() => Promise.resolve(someFakeValue))
or
spyOn(service, 'getAppConfig').and.mockReturnValue(Promise.resolve(fakeValue))
This answer from #roberto-correia made me wonder if there must be something wrong with the way we are using createMock from the package #golevelup/nestjs-testing.
It turns out that the reason why the method exceeds the execution time has to do with the fact that createMock does not implement the mocking, and does not return anything, unless told to do so.
To make the method work, we have to make the mocked methods resolve something at the beginning of the test:
usersRepository.findOneOrFail.mockResolvedValue({ userId: 1, email: "some-random-email#email.com" });
A basic working solution:
describe("UsersService", () => {
let usersService: UsersService;
const usersRepository = createMock<Repository<User>>();
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
UsersService,
{
provide: getRepositoryToken(User),
useValue: usersRepository,
},
}).compile();
usersService = module.get(UsersService);
});
it("should be defined", () => {
expect(usersService).toBeDefined();
});
it("finds a user", async () => {
usersRepository.findOne.mockResolvedValue({ userId: 1, email: "some-random-email#email.com" });
expect(await usersRepository.findOne()).toBe({ userId: 1, email: "some-random-email#email.com" });
});
});
My react component should do some change to the state according to the current location.
There is custom hook, that is called upon component loading.
In the hook there is a check of useLocation().pathname and the result in switch/case for the correct change.
Can this be Jest tested in one file/describe?
I tried to jest.mock useLocation but I just can't do it inside Jest describe...
This is the mock, currently out of the describe - and this works, but can't be changed from test to test:
const mockUseLocation = () => {
jest.mock('react-router-dom', () => ({
useLocation: jest.fn().mockReturnValue({
pathname: '/val1'
})
}))
};
How can I test all the switch/case branches?
switch (pathname) {
case 'val1':
return 100;
case 'val2':
return 200;
...
...
}
To go off of #skyboyer answer I got this working well using renderHook
The first argument is your hook you want to test and the second argument is your wrapper which I wraps <MemoryRouter>, <Route> around children prop.
// test.js
import React, { FC } from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import { renderHook } from '#testing-library/react-hooks';
it('returns value from url query', () => {
const wrapper: FC = ({ children }) => (
<MemoryRouter initialEntries={[`/?user=authorized`]}>
<Route path="*" />
{children}
</MemoryRouter>
);
const { result } = renderHook(() => useLocation(), { wrapper });
expect(result.current).toBe('authorized');
});
easiest way is use MemoryRouter instead mocking useLocation. Also this would be helpful if your component has <Link>(otherwise you will get the error "Link cannot be used outside the Router"). Also it allows you to check if navigation happens. So with such many benefits mocking useLocation directly does not have any value.
Take a look into examples in official docs. It would be something alike:
test("current user is active in sidebar", () => {
const wrapper = mount(
<MemoryRouter initialEntries={["/users/2"]}>
<YourComp />
</MemoryRouter>
);
expected(wrapper.find(User)).toHaveLength(2);
});
You can change the value of pathname by changing the value of this variable in the appropriate places in the tests.
For example:
let mockPATH = 'val1';
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useLocation: () => ({
pathname: mockPATH
})
}));
test('1st', () => {
mockPATH = 'val2';
//...
})
try:
const locationMock = jest.fn();
const mockUseLocation = () => {
jest.mock('react-router-dom', () => ({
useLocation: () => locationMock()
}))
};
it('test1', () => {
locationMock.mockReturnValue({
pathname: '/val1'
})
expect()
})
it('test2', () => {
locationMock.mockReturnValue({
pathname: '/val2'
})
expect()
})
Hope it work for u ^^
I am using jest and enzyme for unit testing. Below is my index.js file. I need to test openNotification and uploadErrorNotification function of the file. However, only uploadErrorNotification function is exported. So, How do I test both the functions.
Also, I don't want to use any other libray except jest and enzyme.
//index.js
import {
notification
} from 'antd';
const openNotification = (message, description, className) => {
notification.open({
key: 'upload-template',
message,
description,
placement: "bottomRight",
duration: null,
});
};
const uploadErrorNotification = (uploadFailedText, errorMsg) => {
openNotification(uploadFailedText, errorMsg, 'error');
};
export {
uploadErrorNotification
}
This is my test file:
//test.js
import { uploadErrorNotification } from '../index.js
jest.mock('notification', () => ({ open: () => jest.fn() })); // was trying this but I couldn't understand how it will work
describe('Notification validation functions testing', () => {
uploadErrorNotification('Upload failed', 'Something went wrong.');
expect("openNotification").toHaveBeenCalledTimes(1); // want to do something like this
});
You have to mock the external depenency:
first mock antd so that notification.open is a spy
jest.mock('antd', () => ({notification: open: {jest.fn()}}))
Then import the module into your test
import { notification } from 'antd';
Know you can use it like this:
expect(notification.open).toHaveBeenCalledTimes(1);
If you want to test notification without overwrite other antd component, you can add jest.requireActual('antd').
jest.mock('antd', () => {
return {
...jest.requireActual('antd'),
notification: {
open: jest.fn(),
},
};
});