Skip to content

Commit

Permalink
mock debounce for unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Parajuli Kiran <kiranparajuli589@gmail.com>
  • Loading branch information
kiranparajuli589 committed Mar 31, 2022
1 parent 58a4d3e commit 751c79f
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 60 deletions.
17 changes: 5 additions & 12 deletions src/components/tab/SearchInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
</template>

<script>
import debounce from 'lodash/debounce'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { translate as t } from '@nextcloud/l10n'
Expand All @@ -38,13 +39,12 @@ import WorkPackage from './WorkPackage'
import { showError } from '@nextcloud/dialogs'
import { workpackageHelper } from '../../utils/workpackageHelper'
const _ = require('lodash')
const STATE_OK = 'ok'
const STATE_ERROR = 'error'
const STATE_NO_TOKEN = 'no-token'
const STATE_LOADING = 'loading'
const SEARCH_CHAR_LIMIT = 3
const DEBOUNCE_THRESHOLD = 500
export default {
name: 'SearchInput',
Expand Down Expand Up @@ -113,22 +113,15 @@ export default {
}
},
async asyncFind(query) {
// save current query to check if we display
// recommendations or search results
console.log(query)
query = query.trim()
if (query) {
this.resetState()
if (query.length <= SEARCH_CHAR_LIMIT) return
await this.debounceGetWorkPackages(query)
await this.debounceMakeSearchRequest(query)
}
},
/**
* debounce get work packages to avoid too many requests
*/
debounceGetWorkPackages: _.debounce(function(...args) {
debounceMakeSearchRequest: debounce(function(...args) {
return this.makeSearchRequest(...args)
}, 500),
}, DEBOUNCE_THRESHOLD),
async linkWorkPackageToFile(selectedOption) {
const params = new URLSearchParams()
params.append('workpackageId', selectedOption.id)
Expand Down
3 changes: 0 additions & 3 deletions src/utils/workpackageHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,13 @@ export const workpackageHelper = {
const typeId = this.replaceHrefToGetId(workPackage._links.type.href)
const userId = this.replaceHrefToGetId(workPackage._links.assignee.href)
const userName = workPackage._links.assignee.title

const avatarUrl = generateUrl('/apps/integration_openproject/avatar?')
+ encodeURIComponent('userId')
+ '=' + userId
+ '&' + encodeURIComponent('userName')
+ '=' + userName
const statusColor = await this.getColorAttributes('/apps/integration_openproject/statuses/', statusId)
console.log(statusColor)
const typeColor = await this.getColorAttributes('/apps/integration_openproject/types/', typeId)

return {
id: workPackage.id,
subject: workPackage.subject,
Expand Down
45 changes: 29 additions & 16 deletions tests/jest/components/tab/SearchInput.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ jest.mock('@nextcloud/l10n', () => ({
translate: jest.fn((app, msg) => msg),
getLanguage: jest.fn(() => ''),
}))
jest.mock('lodash/debounce', () =>
jest.fn(fn => {
fn.cancel = jest.fn()
return fn
})
)

const localVue = createLocalVue()
const simpleWorkPackageSearchResponse = [{
Expand Down Expand Up @@ -43,7 +49,8 @@ describe('SearchInput.vue tests', () => {
let wrapper

const stateSelector = '.stateMsg'
const searchListSelector = '.workpackage'
const multiSelectContentSelector = '.multiselect__content'
const workPackageStubSelector = 'workpackage-stub'
const inputSelector = '.multiselect__input'
const assigneeSelector = '.filterAssignee'
const loadingIconSelector = '.icon-loading-small'
Expand Down Expand Up @@ -159,17 +166,20 @@ describe('SearchInput.vue tests', () => {
await wrapper.setData({
searchResults: [],
})
const searchList = wrapper.find(searchListSelector)
expect(searchList.exists()).toBeFalsy()
const multiSelectCont = wrapper.find(multiSelectContentSelector)
expect(multiSelectCont).toMatchSnapshot()
})
it('should display correct options list of search results', async () => {
await wrapper.setData({
searchResults: workPackagesSearchResponse,
})
const searchList = wrapper.find(searchListSelector)

expect(searchList.exists()).toBeTruthy()
expect(searchList).toMatchSnapshot()
const multiSelectContent = wrapper.find(multiSelectContentSelector)
expect(multiSelectContent.exists()).toBeTruthy()
const workPackages = multiSelectContent.findAll(workPackageStubSelector)
expect(workPackages).toHaveLength(workPackagesSearchResponse.length)
for (let i = 0; i < workPackagesSearchResponse.length; i++) {
expect(workPackages.at(i).props()).toMatchSnapshot()
}
})
it('should not display the "avatar" and "name" if the "assignee" is not present in a work package', async () => {
await wrapper.setData({
Expand All @@ -178,11 +188,11 @@ describe('SearchInput.vue tests', () => {
const assignee = wrapper.find(assigneeSelector)
expect(assignee.exists()).toBeFalsy()
})
it.only('should only use the options from the latest search response', async () => {
it('should only use the options from the latest search response', async () => {
await wrapper.setData({
searchResults: workPackageSearchReqResponse,
})
expect(wrapper.findAll('workpackage-stub').length).toBe(3)
expect(wrapper.findAll(workPackageStubSelector).length).toBe(3)
const axiosSpy = jest.spyOn(axios, 'get')
.mockImplementationOnce(() => Promise.resolve({
status: 200,
Expand All @@ -196,9 +206,11 @@ describe('SearchInput.vue tests', () => {
for (let i = 0; i <= 10; i++) {
await wrapper.vm.$nextTick()
}
const workPackages = wrapper.findAll('workpackage-stub')
const workPackages = wrapper.findAll(workPackageStubSelector)
expect(workPackages.length).toBe(simpleWorkPackageSearchResponse.length)
expect(workPackages.at(0).props()).toMatchSnapshot()
for (let i = 0; i < workPackages.length; i++) {
expect(workPackages.at(i).props()).toMatchSnapshot()
}
axiosSpy.mockRestore()
})
it('should not display work packages that are already linked', async () => {
Expand Down Expand Up @@ -392,9 +404,7 @@ describe('SearchInput.vue tests', () => {

describe('fileInfo prop', () => {
it('should reset the input state when the prop is changed', async () => {
wrapper = mountSearchInput({ id: 111, name: 'file.txt' })
await wrapper.find(inputSelector).setValue('org')
await wrapper.setData({
wrapper = mountSearchInput({ id: 111, name: 'file.txt' }, [], {
searchResults: [{
id: 999,
}],
Expand All @@ -412,7 +422,7 @@ describe('SearchInput.vue tests', () => {
})
})
})
function mountSearchInput(fileInfo = {}, linkedWorkPackages = []) {
function mountSearchInput(fileInfo = {}, linkedWorkPackages = [], data = {}) {
return mount(SearchInput, {
localVue,
mocks: {
Expand All @@ -421,13 +431,16 @@ function mountSearchInput(fileInfo = {}, linkedWorkPackages = []) {
return '/'
},
},
data: () => ({
...data,
}),
stubs: {
Avatar: true,
WorkPackage: true,
},
propsData: {
fileInfo,
linkedWorkPackages
linkedWorkPackages,
},
})
}
52 changes: 23 additions & 29 deletions tests/jest/components/tab/__snapshots__/SearchInput.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,29 @@ exports[`SearchInput.vue tests state messages no-token: should display the corre
`;

exports[`SearchInput.vue tests work packages multiselect search list should display correct options list of search results 1`] = `
<div class="workpackage">
<div class="row">
<div class="row__status" style="background-color: blue;">
<div class="row__status__title">
in-progress
</div>
</div>
<div class="row__workpackage">
#1 - test
</div>
</div>
<div class="row">
<div class="row__subject"><span class="row__subject__type" style="color: red;">
task
</span>
Organize work-packages
</div>
</div>
<div class="row">
<div class="row__assignee">
<div class="row__assignee__avatar">
<avatar-stub size="23" url="/server/index.php/apps/integration_openproject/avatar?userId=1&amp;userName=System" user="test" display-name="test" class="item-avatar"></avatar-stub>
</div>
<div class="row__assignee__assignee">
test
</div>
</div>
</div>
</div>
Object {
"workpackage": Object {
"assignee": "test",
"id": "1",
"picture": "/server/index.php/apps/integration_openproject/avatar?userId=1&userName=System",
"project": "test",
"statusCol": "blue",
"statusTitle": "in-progress",
"subject": "Organize work-packages",
"typeCol": "red",
"typeTitle": "task",
},
}
`;

exports[`SearchInput.vue tests work packages multiselect search list should not be displayed if the search results is empty 1`] = `
<ul class="multiselect__content" style="display: block;">
<!---->
<li style="display: none;"><span class="multiselect__option"><span>No results</span></span></li>
<li><span class="multiselect__option">
Start typing to search
</span></li>
</ul>
`;

exports[`SearchInput.vue tests work packages multiselect search list should only use the options from the latest search response 1`] = `
Expand Down

0 comments on commit 751c79f

Please sign in to comment.