Skip to content

Commit

Permalink
refactor: typings and return of taxonomy import api
Browse files Browse the repository at this point in the history
  • Loading branch information
rpenido committed Dec 9, 2023
1 parent d91716b commit 244b83b
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 39 deletions.
2 changes: 1 addition & 1 deletion src/generic/loading-button/LoadingButton.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe('<LoadingButton />', () => {
});

it('renders the spinner correctly even with error', () => {
const longFunction = () => new Promise((resolve, reject) => {
const longFunction = () => new Promise((_resolve, reject) => {
setTimeout(reject, 1000);
});
const { getByRole, getByText, getByTestId } = render(RootWrapper(longFunction));
Expand Down
9 changes: 8 additions & 1 deletion src/generic/loading-button/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import {
Stack,
} from '@edx/paragon';

/**
* A button that shows a loading spinner when clicked.
* @param {object} props
* @param {React.ReactNode=} props.children
* @param {boolean=} props.disabled
* @param {function=} props.onClick
* @returns {JSX.Element}
*/
const LoadingButton = ({
onClick,
children,
Expand Down Expand Up @@ -48,7 +56,6 @@ LoadingButton.propTypes = {

LoadingButton.defaultProps = {
...Button.defaultProps,
disabled: null,
};

export default LoadingButton;
37 changes: 21 additions & 16 deletions src/taxonomy/import-tags/ImportTagsWizard.jsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
import React, { useState } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';
import {
Expand Down Expand Up @@ -209,35 +210,39 @@ const ImportTagsWizard = ({

const [file, setFile] = useState(/** @type {null|File} */ (null));

const [importPlan, setImportPlan] = useState(null);
const [importPlan, setImportPlan] = useState(/** @type {null|string[]} */ (null));
const [importPlanError, setImportPlanError] = useState(null);

const importTagsMutation = useImportTags();

const generatePlan = async () => {
try {
const plan = await planImportTags(taxonomy.id, file);
let planArrayTemp = plan.split('\n');
planArrayTemp = planArrayTemp.slice(2); // Removes the first two lines
planArrayTemp = planArrayTemp.slice(0, -1); // Removes the last line
const planArray = planArrayTemp
.filter((line) => !(line.includes('No changes'))) // Removes the "No changes" lines
.map((line) => line.split(':')[1].trim()); // Get only the action message
setImportPlan(planArray);
setImportPlanError(null);
setCurrentStep('plan');
if (file) {
const plan = await planImportTags(taxonomy.id, file);
let planArrayTemp = plan.split('\n');
planArrayTemp = planArrayTemp.slice(2); // Removes the first two lines
planArrayTemp = planArrayTemp.slice(0, -1); // Removes the last line
const planArray = planArrayTemp
.filter((line) => !(line.includes('No changes'))) // Removes the "No changes" lines
.map((line) => line.split(':')[1].trim()); // Get only the action message
setImportPlan(planArray);
setImportPlanError(null);
setCurrentStep('plan');
}
} catch (/** @type {any} */ error) {
setImportPlanError(error.message);
}
};

const confirmImportTags = async () => {
try {
await importTagsMutation.mutateAsync({
taxonomyId: taxonomy.id,
file,
});
close();
if (file) {
await importTagsMutation.mutateAsync({
taxonomyId: taxonomy.id,
file,
});
close();
}
// ToDo: show success toast
} catch (error) {
// ToDo: show error message
Expand Down
26 changes: 11 additions & 15 deletions src/taxonomy/import-tags/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ export const getTagsPlanImportApiUrl = (taxonomyId) => new URL(
* @param {string} taxonomyName
* @param {string} taxonomyDescription
* @param {File} file
* @returns {Promise<Object>}
* @returns {Promise<import(../../taxonomy-detail/data/types).TaxonomyData}

Check failure on line 36 in src/taxonomy/import-tags/data/api.js

View workflow job for this annotation

GitHub Actions / tests

Type expected.

Check failure on line 36 in src/taxonomy/import-tags/data/api.js

View workflow job for this annotation

GitHub Actions / tests

String literal expected.

Check failure on line 36 in src/taxonomy/import-tags/data/api.js

View workflow job for this annotation

GitHub Actions / tests

Identifier expected.

Check failure on line 36 in src/taxonomy/import-tags/data/api.js

View workflow job for this annotation

GitHub Actions / tests

Identifier expected.
*/
export async function importNewTaxonomy(taxonomyName, taxonomyDescription, file) {
// ToDo: transform this to use react-query like useImportTags
const formData = new FormData();
formData.append('taxonomy_name', taxonomyName);
formData.append('taxonomy_description', taxonomyDescription);
Expand Down Expand Up @@ -69,18 +70,18 @@ export const useImportTags = () => {
const formData = new FormData();
formData.append('file', file);

await getAuthenticatedHttpClient().put(
const { data } = await getAuthenticatedHttpClient().put(
getTagsImportApiUrl(taxonomyId),
formData,
);

return camelCaseObject(data);
},
onSuccess: (_data, variables) => {
onSuccess: (data, variables) => {
queryClient.invalidateQueries({
queryKey: ['tagList', variables.taxonomyId],
});
queryClient.invalidateQueries({
queryKey: ['taxonomyDetail', variables.taxonomyId],
});
queryClient.setQueryData(['taxonomyDetail', variables.taxonomyId], data);
},
});
};
Expand All @@ -89,7 +90,7 @@ export const useImportTags = () => {
* Plan import tags to an existing taxonomy, overwriting existing tags
* @param {number} taxonomyId
* @param {File} file
* @returns {Promise<Object>}
* @returns {Promise<string>}
*/
export async function planImportTags(taxonomyId, file) {
const formData = new FormData();
Expand All @@ -101,13 +102,8 @@ export async function planImportTags(taxonomyId, file) {
formData,
);

return camelCaseObject(data.plan);
} catch (err) {
// @ts-ignore
if (err.response?.data?.error) {
// @ts-ignore
throw new Error(err.response.data.error);
}
throw err;
return data.plan;
} catch (/** @type {any} */ err) {
throw new Error(err.response?.data?.error || err.message);
}
}
10 changes: 4 additions & 6 deletions src/taxonomy/import-tags/data/api.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ describe('import taxonomy api calls', () => {
});

it('should call import tags', async () => {
axiosMock.onPut(getTagsImportApiUrl(1)).reply(200);
const taxonomy = { id: 1, name: 'taxonomy name' };
axiosMock.onPut(getTagsImportApiUrl(1)).reply(200, taxonomy);
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');
const mockSetQueryData = jest.spyOn(queryClient, 'setQueryData');

const { result } = renderHook(() => useImportTags(), { wrapper });

Expand All @@ -68,9 +70,7 @@ describe('import taxonomy api calls', () => {
expect(mockInvalidateQueries).toHaveBeenCalledWith({
queryKey: ['tagList', 1],
});
expect(mockInvalidateQueries).toHaveBeenCalledWith({
queryKey: ['taxonomyDetail', 1],
});
expect(mockSetQueryData).toHaveBeenCalledWith(['taxonomyDetail', 1], taxonomy);
});

it('should call plan import tags', async () => {
Expand All @@ -81,10 +81,8 @@ describe('import taxonomy api calls', () => {

it('should handle errors in plan import tags', async () => {
axiosMock.onPut(getTagsPlanImportApiUrl(1)).reply(400, { error: 'test error' });
const mockInvalidateQueries = jest.spyOn(queryClient, 'invalidateQueries');

expect(planImportTags(1)).rejects.toEqual(Error('test error'));
expect(axiosMock.history.put[0].url).toEqual(getTagsPlanImportApiUrl(1));
expect(mockInvalidateQueries).not.toHaveBeenCalled();
});
});

0 comments on commit 244b83b

Please sign in to comment.