Skip to content

Commit 3967fc1

Browse files
Write tests for search-store (#286)
Add initial query values Handle media reset on query change only in `search` page Update src/utils/prepare-search-query-params.js Co-authored-by: sarayourfriend <24264157+sarayourfriend@users.noreply.github.com>
1 parent 7d517f9 commit 3967fc1

File tree

6 files changed

+314
-377
lines changed

6 files changed

+314
-377
lines changed

src/components/ContentReport/ContentReportForm.vue

-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ export default {
144144
} else if (this.selectedReason === 'dmca') {
145145
this.selectedCopyright = true
146146
} else {
147-
console.log('sending content report')
148147
this.sendContentReport()
149148
}
150149
},

src/constants/mutation-types.js

+1
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,4 @@ export const SET_SEARCH_TYPE = 'SET_SEARCH_TYPE'
3636
export const UPDATE_FILTERS = 'UPDATE_FILTERS'
3737
export const SET_ACTIVE_MEDIA_ITEM = 'SET_ACTIVE_MEDIA_ITEM'
3838
export const UNSET_ACTIVE_MEDIA_ITEM = 'UNSET_ACTIVE_MEDIA_ITEM'
39+
export const RESET_MEDIA = 'RESET_MEDIA'

src/store-modules/search-store.js

+50-148
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
1-
import isEmpty from 'lodash.isempty'
21
import findIndex from 'lodash.findindex'
32
import prepareSearchQueryParams from '~/utils/prepare-search-query-params'
43
import decodeMediaData from '~/utils/decode-media-data'
54
import {
6-
FETCH_MEDIA,
75
FETCH_AUDIO,
86
FETCH_IMAGE,
9-
FETCH_COLLECTION_IMAGES,
10-
HANDLE_NO_MEDIA,
7+
FETCH_MEDIA,
118
HANDLE_MEDIA_ERROR,
12-
UPDATE_SEARCH_TYPE,
9+
HANDLE_NO_MEDIA,
1310
SET_SEARCH_TYPE_FROM_URL,
11+
UPDATE_SEARCH_TYPE,
1412
} from '~/constants/action-types'
1513
import {
1614
FETCH_END_MEDIA,
1715
FETCH_MEDIA_ERROR,
1816
FETCH_START_MEDIA,
1917
MEDIA_NOT_FOUND,
18+
RESET_MEDIA,
2019
SET_AUDIO,
2120
SET_IMAGE,
2221
SET_IMAGE_PAGE,
@@ -26,8 +25,8 @@ import {
2625
UPDATE_FILTERS,
2726
} from '~/constants/mutation-types'
2827
import {
29-
SEND_SEARCH_QUERY_EVENT,
3028
SEND_RESULT_CLICKED_EVENT,
29+
SEND_SEARCH_QUERY_EVENT,
3130
} from '~/constants/usage-data-analytics-types'
3231
import { queryStringToSearchType } from '~/utils/search-query-transform'
3332
import { ALL_MEDIA, AUDIO, IMAGE } from '~/constants/media'
@@ -38,77 +37,6 @@ import { USAGE_DATA } from '~/constants/store-modules'
3837
// ? window.location.pathname
3938
// : '/search'
4039

41-
/**
42-
* hides the search results in case the user is performing a new search.
43-
* This prevents results from a previous search from showing while the
44-
* new search results are still loading
45-
*/
46-
const hideSearchResultsOnNewSearch = (commit, pageNumber) => {
47-
if (!pageNumber) {
48-
commit(SET_MEDIA, { mediaType: IMAGE, media: [] })
49-
commit(SET_MEDIA, { mediaType: AUDIO, media: [] })
50-
}
51-
}
52-
53-
const allKeysUndefinedExcept = (value, keyName) => {
54-
const keys = Object.keys(value)
55-
return keys.reduce((matchedUndefinedCriteria, key) => {
56-
const shouldBeUndefined = key !== keyName
57-
const isUndefined = isEmpty(value[key])
58-
59-
return matchedUndefinedCriteria && shouldBeUndefined === isUndefined
60-
}, true)
61-
}
62-
63-
const fetchCollectionImages = (commit, params, imageService) => {
64-
hideSearchResultsOnNewSearch(commit, params.page)
65-
66-
const queryParams = {
67-
q: params.q,
68-
provider: params.provider,
69-
searchBy: params.searchBy,
70-
}
71-
// the provider collection API doesn't support the `q` parameter.
72-
// so if the `q`, or any other search filter is provided, and
73-
// since the `provider` parameter is passed, we can just call the search API instead
74-
const searchMethod = allKeysUndefinedExcept(queryParams, 'provider')
75-
? imageService.getProviderCollection
76-
: imageService.search
77-
const newParams = { ...params, source: params.provider }
78-
delete newParams.provider
79-
return searchMethod(prepareSearchQueryParams(newParams))
80-
}
81-
82-
/**
83-
* With the API response: set loading to false, set the
84-
* store `images` or `audios` property to the result,
85-
* and handle possible errors
86-
* @param {import('vuex').Commit} commit
87-
* @param {import('vuex').Dispatch} dispatch
88-
* @param {import('../store/types').MediaResult} data
89-
* @param {Object} params
90-
* @param {'image'|'audio'} params.mediaType
91-
* @param {boolean} params.shouldPersistMedia
92-
* @param {number} params.page
93-
*/
94-
const handleSearchResponse = async (
95-
commit,
96-
dispatch,
97-
data,
98-
{ mediaType, shouldPersistMedia, page }
99-
) => {
100-
commit(FETCH_END_MEDIA, { mediaType })
101-
commit(SET_MEDIA, {
102-
mediaType,
103-
media: data.results,
104-
mediaCount: data.result_count,
105-
pageCount: data.page_count,
106-
shouldPersistMedia: shouldPersistMedia,
107-
page: page,
108-
})
109-
return dispatch(HANDLE_NO_MEDIA, mediaType)
110-
}
111-
11240
/**
11341
* @type {{ audios: import('../store/types').AudioDetail[],
11442
* audiosCount: number, audioPage:number,
@@ -143,12 +71,8 @@ const state = {
14371
query: {},
14472
}
14573

146-
/**
147-
* @param {Object} AudioService
148-
* @param {Object} ImageService
149-
*/
150-
const actions = (AudioService, ImageService) => ({
151-
[FETCH_MEDIA]({ commit, dispatch, rootState }, params) {
74+
const actions = (services) => ({
75+
async [FETCH_MEDIA]({ commit, dispatch, rootState }, params) {
15276
// does not send event if user is paginating for more results
15377
const { page, mediaType, q } = params
15478
if (!page) {
@@ -159,40 +83,42 @@ const actions = (AudioService, ImageService) => ({
15983
}
16084

16185
commit(FETCH_START_MEDIA, { mediaType })
162-
hideSearchResultsOnNewSearch(commit, page)
86+
if (!params.page) {
87+
commit(RESET_MEDIA, { mediaType })
88+
}
16389
const queryParams = prepareSearchQueryParams(params)
164-
let service
165-
if (mediaType === IMAGE) {
166-
service = ImageService
167-
} else if (mediaType === AUDIO) {
168-
service = AudioService
169-
} else {
90+
if (!Object.keys(services).includes(mediaType)) {
17091
throw new Error(`Cannot fetch unknown media type "${mediaType}"`)
17192
}
172-
return service
93+
await services[mediaType]
17394
.search(queryParams)
174-
.then(
175-
async ({ data }) =>
176-
await handleSearchResponse(commit, dispatch, data, params)
177-
)
95+
.then(({ data }) => {
96+
commit(FETCH_END_MEDIA, { mediaType })
97+
const mediaCount = data.result_count
98+
commit(SET_MEDIA, {
99+
mediaType,
100+
media: data.results,
101+
mediaCount,
102+
pageCount: data.page_count,
103+
shouldPersistMedia: params.shouldPersistMedia,
104+
page: page,
105+
})
106+
dispatch(HANDLE_NO_MEDIA, { mediaType, mediaCount })
107+
})
178108
.catch((error) => {
179109
dispatch(HANDLE_MEDIA_ERROR, { mediaType, error })
180110
})
181111
},
182-
// eslint-disable-next-line no-unused-vars
183-
[FETCH_AUDIO]({ commit, dispatch, state, rootState }, params) {
112+
async [FETCH_AUDIO]({ commit, dispatch, state, rootState }, params) {
184113
dispatch(`${USAGE_DATA}/${SEND_RESULT_CLICKED_EVENT}`, {
185114
query: state.query.q,
186115
resultUuid: params.id,
187116
resultRank: findIndex(state.audios, (img) => img.id === params.id),
188-
sessionId: rootState.usageSessionId,
117+
sessionId: rootState.user.usageSessionId,
189118
})
190-
191-
commit(FETCH_START_MEDIA, { mediaType: AUDIO })
192119
commit(SET_AUDIO, { audio: {} })
193-
return AudioService.getMediaDetail(params)
120+
await services[AUDIO].getMediaDetail(params)
194121
.then(({ data }) => {
195-
commit(FETCH_END_MEDIA, { mediaType: AUDIO })
196122
commit(SET_AUDIO, { audio: data })
197123
})
198124
.catch((error) => {
@@ -203,8 +129,7 @@ const actions = (AudioService, ImageService) => ({
203129
}
204130
})
205131
},
206-
// eslint-disable-next-line no-unused-vars
207-
[FETCH_IMAGE]({ commit, dispatch, state, rootState }, params) {
132+
async [FETCH_IMAGE]({ commit, dispatch, state, rootState }, params) {
208133
dispatch(`${USAGE_DATA}/${SEND_RESULT_CLICKED_EVENT}`, {
209134
query: state.query.q,
210135
resultUuid: params.id,
@@ -213,30 +138,19 @@ const actions = (AudioService, ImageService) => ({
213138
})
214139

215140
commit(SET_IMAGE, { image: {} })
216-
return ImageService.getMediaDetail(params)
141+
await services[IMAGE].getMediaDetail(params)
217142
.then(({ data }) => {
218143
commit(SET_IMAGE, { image: data })
219144
})
220145
.catch((error) => {
221146
if (error.response && error.response.status === 404) {
222147
commit(MEDIA_NOT_FOUND, { mediaType: IMAGE })
223148
} else {
224-
throw new Error(`Error fetching the image: ${error}`)
149+
throw new Error(`Error fetching the image: ${error.message}`)
225150
}
226151
})
227152
},
228-
[FETCH_COLLECTION_IMAGES]({ commit, dispatch }, params) {
229-
commit(FETCH_START_MEDIA, { mediaType: IMAGE })
230-
return fetchCollectionImages(commit, params, ImageService)
231-
.then(
232-
async ({ data }) =>
233-
await handleSearchResponse(commit, dispatch, data, params)
234-
)
235-
.catch((error) => {
236-
dispatch(HANDLE_MEDIA_ERROR, { mediaType: IMAGE, error })
237-
})
238-
},
239-
[HANDLE_MEDIA_ERROR]({ commit }, { mediaType, error }) {
153+
async [HANDLE_MEDIA_ERROR]({ commit }, { mediaType, error }) {
240154
let errorMessage
241155
if (error.response) {
242156
errorMessage =
@@ -266,41 +180,21 @@ const actions = (AudioService, ImageService) => ({
266180
},
267181
})
268182

269-
function setQuery(_state, params) {
270-
const query = Object.assign({}, _state.query, params.query)
271-
_state.query = query
272-
_state.images = []
273-
274-
// if (params.shouldNavigate === true) {
275-
// redirect({ path, query })
276-
// }
277-
}
278-
279-
/* eslint no-param-reassign: ["error", { "props": false }] */
280183
const mutations = {
281184
[FETCH_START_MEDIA](_state, { mediaType }) {
282-
if (mediaType === IMAGE) {
283-
_state.isFetching.images = true
284-
_state.isFetchingError.images = false
285-
} else if (mediaType === AUDIO) {
286-
_state.isFetching.audios = true
287-
_state.isFetchingError.audios = false
288-
}
185+
const mediaPlural = `${mediaType}s`
186+
_state.isFetching[mediaPlural] = true
187+
_state.isFetchingError[mediaPlural] = false
289188
},
290189
[FETCH_END_MEDIA](_state, { mediaType }) {
291-
mediaType === IMAGE
292-
? (_state.isFetching.images = false)
293-
: (_state.isFetching.audios = false)
190+
const mediaPlural = `${mediaType}s`
191+
_state.isFetching[mediaPlural] = false
294192
},
295193
[FETCH_MEDIA_ERROR](_state, params) {
296194
const { mediaType, errorMessage } = params
297-
if (mediaType === IMAGE) {
298-
_state.isFetchingError.images = true
299-
_state.isFetching.images = false
300-
} else if (mediaType === AUDIO) {
301-
_state.isFetchingError.audios = true
302-
_state.isFetching.audios = false
303-
}
195+
const mediaPlural = `${mediaType}s`
196+
_state.isFetching[mediaPlural] = false
197+
_state.isFetchingError[mediaPlural] = true
304198
_state.errorMessage = errorMessage
305199
},
306200
[SET_AUDIO](_state, params) {
@@ -335,14 +229,22 @@ const mutations = {
335229
_state.pageCount[mediaPlural] = pageCount
336230
},
337231
[SET_QUERY](_state, params) {
338-
setQuery(_state, params)
232+
_state.query = Object.assign({}, _state.query, params.query)
233+
_state.images = []
339234
},
340-
[MEDIA_NOT_FOUND](params) {
235+
[MEDIA_NOT_FOUND](_state, params) {
341236
throw new Error(`Media of type ${params.mediaType} not found`)
342237
},
343238
[SET_SEARCH_TYPE](_state, params) {
344239
_state.searchType = params.searchType
345240
},
241+
[RESET_MEDIA](_state, params) {
242+
const { mediaType } = params
243+
_state[`${mediaType}s`] = []
244+
_state[`${mediaType}sCount`] = 0
245+
_state[`${mediaType}Page`] = undefined
246+
_state.pageCount[`${mediaType}s`] = 0
247+
},
346248
}
347249

348250
export default {

src/store/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import SearchStore from '~/store-modules/search-store'
44
import FilterStore from '~/store-modules/filter-store'
55
import { FETCH_MEDIA_PROVIDERS } from '~/constants/action-types'
66
import { PROVIDER } from '~/constants/store-modules'
7+
import { AUDIO, IMAGE } from '~/constants/media'
8+
9+
const mediaServices = { [AUDIO]: AudioService, [IMAGE]: ImageService }
710

811
export const actions = Object.assign(
9-
SearchStore.actions(AudioService, ImageService),
12+
SearchStore.actions(mediaServices),
1013
FilterStore.actions,
1114
{
1215
async nuxtServerInit({ dispatch }) {

src/utils/prepare-search-query-params.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
export default function prepareSearchQueryParams(searchParams) {
2+
if (typeof searchParams.mediaType !== 'undefined') {
3+
delete searchParams.mediaType
4+
}
25
const params = {
36
...searchParams,
47
}

0 commit comments

Comments
 (0)