chore: Replace query-string with URLSearchParams (#613)
Co-authored-by: diana-villalvazo-wgu <dianaximena.villalva@wgu.edu>
This commit is contained in:
committed by
GitHub
parent
11a7512fea
commit
a9194261c8
19
package-lock.json
generated
19
package-lock.json
generated
@@ -32,7 +32,6 @@
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"prop-types": "15.8.1",
|
||||
"query-string": "7.1.3",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
@@ -16469,24 +16468,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/query-string": {
|
||||
"version": "7.1.3",
|
||||
"resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
|
||||
"integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"decode-uri-component": "^0.2.2",
|
||||
"filter-obj": "^1.1.0",
|
||||
"split-on-first": "^1.0.0",
|
||||
"strict-uri-encode": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/querystringify": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
|
||||
|
||||
@@ -52,7 +52,6 @@
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.4",
|
||||
"prop-types": "15.8.1",
|
||||
"query-string": "7.1.3",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-helmet": "^6.1.0",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
import queryString from 'query-string';
|
||||
|
||||
import { ListPageSize, SortKeys } from 'data/constants/app';
|
||||
import { reduxHooks } from 'hooks';
|
||||
import { StrictDict } from 'utils';
|
||||
@@ -27,12 +25,13 @@ export const useCourseListData = () => {
|
||||
|
||||
const [sortBy, setSortBy] = module.state.sortBy(SortKeys.enrolled);
|
||||
|
||||
const querySearch = queryString.parse(window.location.search, { parseNumbers: true });
|
||||
const querySearch = new URLSearchParams(window.location.search);
|
||||
const disablePagination = querySearch.get('disable_pagination');
|
||||
|
||||
const { numPages, visibleList } = reduxHooks.useCurrentCourseList({
|
||||
sortBy,
|
||||
filters,
|
||||
pageSize: querySearch?.disable_pagination === 1 ? 0 : ListPageSize,
|
||||
pageSize: Number(disablePagination) === 1 ? 0 : ListPageSize,
|
||||
});
|
||||
|
||||
const handleRemoveFilter = (filter) => () => removeFilter(filter);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import queryString from 'query-string';
|
||||
|
||||
import { MockUseState } from 'testUtils';
|
||||
import { reduxHooks } from 'hooks';
|
||||
import { ListPageSize, SortKeys } from 'data/constants/app';
|
||||
@@ -15,8 +13,10 @@ jest.mock('hooks', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('query-string', () => ({
|
||||
parse: jest.fn(() => ({})),
|
||||
const mockGet = jest.fn(() => ({}));
|
||||
|
||||
global.URLSearchParams = jest.fn().mockImplementation(() => ({
|
||||
get: mockGet,
|
||||
}));
|
||||
|
||||
const state = new MockUseState(hooks);
|
||||
@@ -67,7 +67,7 @@ describe('CourseList hooks', () => {
|
||||
it('loads current course list with page size 0 if/when there is query param disable_pagination=1', () => {
|
||||
state.mock();
|
||||
state.mockVal(state.keys.sortBy, testSortBy);
|
||||
queryString.parse.mockReturnValueOnce({ disable_pagination: 1 });
|
||||
mockGet.mockReturnValueOnce('1');
|
||||
out = hooks.useCourseListData();
|
||||
expect(reduxHooks.useCurrentCourseList).toHaveBeenCalledWith({
|
||||
sortBy: testSortBy,
|
||||
|
||||
@@ -1,6 +1,34 @@
|
||||
import queryString from 'query-string';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
|
||||
/**
|
||||
* stringify(query, existingQuery)
|
||||
* simple wrapper to convert an object to a query string
|
||||
* @param {object} query - object to convert
|
||||
* @param {string} existingQuery - existing query string
|
||||
* @returns {string} - query string
|
||||
*/
|
||||
|
||||
export const stringify = (query, existingQuery = '') => {
|
||||
const searchParams = new URLSearchParams(existingQuery);
|
||||
|
||||
Object.entries(query).forEach(([key, value]) => {
|
||||
if (value === undefined || value === null || value === '') {
|
||||
searchParams.delete(key);
|
||||
} else if (Array.isArray(value)) {
|
||||
searchParams.delete(key);
|
||||
value.forEach((val) => {
|
||||
if (val !== undefined && val !== null && val !== '') {
|
||||
searchParams.append(key, val);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
searchParams.set(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return searchParams.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* get(url)
|
||||
* simple wrapper providing an authenticated Http client get action
|
||||
@@ -10,21 +38,23 @@ export const get = (...args) => getAuthenticatedHttpClient().get(...args);
|
||||
/**
|
||||
* post(url, data)
|
||||
* simple wrapper providing an authenticated Http client post action
|
||||
* queryString.stringify is used to convert the object to query string with = and &
|
||||
* stringify is used to convert the object to query string with = and &
|
||||
* @param {string} url - target url
|
||||
* @param {object|string} body - post payload
|
||||
*/
|
||||
export const post = (url, body) => getAuthenticatedHttpClient().post(url, queryString.stringify(body));
|
||||
export const post = (url, body) => getAuthenticatedHttpClient().post(url, stringify(body));
|
||||
|
||||
export const client = getAuthenticatedHttpClient;
|
||||
|
||||
/**
|
||||
* stringifyUrl(url, query)
|
||||
* simple wrapper around queryString.stringifyUrl that sets skip behavior
|
||||
* simple wrapper to convert a url and query object to a full url
|
||||
* @param {string} url - base url string
|
||||
* @param {object} query - query parameters
|
||||
* @returns {string} - full url
|
||||
*/
|
||||
export const stringifyUrl = (url, query) => queryString.stringifyUrl(
|
||||
{ url, query },
|
||||
{ skipNull: true, skipEmptyString: true },
|
||||
);
|
||||
export const stringifyUrl = (url, query) => {
|
||||
const [baseUrl, existingQuery = ''] = url.split('?');
|
||||
const queryString = stringify(query, existingQuery);
|
||||
return queryString ? `${baseUrl}?${queryString}` : baseUrl;
|
||||
};
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import queryString from 'query-string';
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import * as utils from './utils';
|
||||
|
||||
jest.mock('query-string', () => ({
|
||||
stringifyUrl: jest.fn((url, options) => ({ url, options })),
|
||||
stringify: jest.fn((data) => data),
|
||||
}));
|
||||
jest.mock('@edx/frontend-platform/auth', () => ({
|
||||
getAuthenticatedHttpClient: jest.fn(),
|
||||
}));
|
||||
@@ -20,28 +15,25 @@ describe('lms service utils', () => {
|
||||
});
|
||||
});
|
||||
describe('post', () => {
|
||||
it('forwards arguments to authenticatedHttpClient().post', () => {
|
||||
it('forwards arguments to authenticatedHttpClient().post, removes undefined attributes and appends array values', () => {
|
||||
const post = jest.fn((...args) => ({ post: args }));
|
||||
getAuthenticatedHttpClient.mockReturnValue({ post });
|
||||
const url = 'some url';
|
||||
const body = {
|
||||
some: 'body',
|
||||
for: 'the',
|
||||
for: undefined,
|
||||
test: 'yay',
|
||||
array: ['one', 'two', undefined],
|
||||
};
|
||||
const expectedUrl = utils.post(url, body);
|
||||
expect(queryString.stringify).toHaveBeenCalledWith(body);
|
||||
expect(expectedUrl).toEqual(post(url, body));
|
||||
expect(expectedUrl).toEqual(post(url, 'some=body&test=yay&array=one&array=two'));
|
||||
});
|
||||
});
|
||||
describe('stringifyUrl', () => {
|
||||
it('forwards url and query to stringifyUrl with options to skip null and ""', () => {
|
||||
it('forwards url and query to stringifyUrl skipping null and ""', () => {
|
||||
const url = 'here.com';
|
||||
const query = { some: 'set', of: 'queryParams' };
|
||||
const options = { skipNull: true, skipEmptyString: true };
|
||||
expect(utils.stringifyUrl(url, query)).toEqual(
|
||||
queryString.stringifyUrl({ url, query }, options),
|
||||
);
|
||||
expect(utils.stringifyUrl(url, query)).toEqual('here.com?some=set&of=queryParams');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ config.resolve.modules = [
|
||||
'node_modules',
|
||||
];
|
||||
|
||||
config.module.rules[0].exclude = /node_modules\/(?!(query-string|split-on-first|strict-uri-encode|@edx))/;
|
||||
config.module.rules[0].exclude = /node_modules\/(?!(split-on-first|strict-uri-encode|@edx))/;
|
||||
|
||||
config.plugins.push(
|
||||
new CopyPlugin({
|
||||
|
||||
@@ -9,7 +9,7 @@ config.resolve.modules = [
|
||||
'node_modules',
|
||||
];
|
||||
|
||||
config.module.rules[0].exclude = /node_modules\/(?!(query-string|split-on-first|strict-uri-encode|@edx))/;
|
||||
config.module.rules[0].exclude = /node_modules\/(?!(split-on-first|strict-uri-encode|@edx))/;
|
||||
|
||||
config.plugins.push(
|
||||
new CopyPlugin({
|
||||
|
||||
Reference in New Issue
Block a user