Skip to content

Commit

Permalink
Implemented Clean Function (#828)
Browse files Browse the repository at this point in the history
* implemented cleansing function

* Explains what NBS is

* Format
  • Loading branch information
zachary-kent authored May 3, 2023
1 parent 8096cef commit 0afd370
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 42 deletions.
40 changes: 40 additions & 0 deletions scripts/__test__/util.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { clean } from '../util';

describe('Courses Populate Test Suite', () => {
it('Primitives and strings w/o NBS unchanged', () => {
expect(clean(5)).toBe(5);
expect(clean(null)).toBe(null);
expect(clean(undefined)).toBe(undefined);
expect(clean('hello')).toBe('hello');
});

it('String with NBS cleaned', () => {
expect(clean('\u00a0')).toBe(' ');
expect(clean('\u00a0\u00a0')).toBe(' ');
expect(clean('\u00a0a\u00a0')).toBe(' a ');
});

it('Array with NBS cleaned', () => {
expect(clean(['hi', '\u00a0', 'goodbye'])).toEqual(['hi', ' ', 'goodbye']);
});

it('Object with NBS cleansed', () => {
const dirty = {
foo: '\u00a0',
foos: ['hello', '\u00a0', '\u00a0', 'goodbye'],
bar: {
baz: '\u00a0',
buzz: 'farewell',
},
};
const cleansed = clean(dirty);
expect(cleansed).toEqual({
foo: ' ',
foos: ['hello', ' ', ' ', 'goodbye'],
bar: {
baz: ' ',
buzz: 'farewell',
},
});
});
});
46 changes: 4 additions & 42 deletions scripts/population/courses-populate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
availableRostersForCourseCollection,
crseIdToCatalogNbrCollection,
} from '../firebase-config';
import { Course, CourseFullDetail } from '../../src/requirements/types';
import { CourseFullDetail } from '../../src/requirements/types';
import { clean } from '../util';

/** A helper function to generate a wait promise. Used for cooldown to limit API usage. */
export const wait = (time: number) =>
Expand All @@ -50,54 +51,15 @@ export const retrieveAvailableSubjects = async (
return (await res.json()).data.subjects.map(({ value }) => ({ roster, subject: value }));
};

/* Retrieves and formats available courses for a {roster: string, subject: string} object */

export const cleanField = (value: string | null | undefined) =>
value?.replace(/\u00a0/g, ' ') || undefined;

export const courseFieldFilter = ({
subject,
crseId,
catalogNbr,
titleLong,
enrollGroups,
catalogWhenOffered,
catalogBreadth,
catalogDistr,
catalogComments,
catalogSatisfiesReq,
catalogCourseSubfield,
catalogAttribute,
acadCareer,
acadGroup,
}: Course): Course => ({
subject: cleanField(subject) || '',
crseId,
catalogNbr: cleanField(catalogNbr) || '',
titleLong: cleanField(titleLong) || '',
enrollGroups: enrollGroups.map(({ unitsMaximum, unitsMinimum }) => ({
unitsMaximum,
unitsMinimum,
})),
catalogWhenOffered: cleanField(catalogWhenOffered),
catalogBreadth: cleanField(catalogBreadth),
catalogDistr: cleanField(catalogDistr),
catalogComments: cleanField(catalogComments),
catalogSatisfiesReq: cleanField(catalogSatisfiesReq),
catalogCourseSubfield: cleanField(catalogCourseSubfield),
catalogAttribute: cleanField(catalogAttribute),
acadCareer: cleanField(acadCareer) || '',
acadGroup: cleanField(acadGroup) || '',
});

/** Retrieves and formats available courses for a {roster: string, subject: string} object */
export const retrieveAvailableCourses = async (
roster: string,
subject: string
): Promise<CourseFullDetail[]> => {
const res = await fetch(
`${classRosterURL}/search/classes.json?roster=${roster}&subject=${subject}`
);
return (await res.json()).data.classes.map(jsonCourse => courseFieldFilter(jsonCourse));
return (await res.json()).data.classes.map(jsonCourse => clean(jsonCourse));
};

/*
Expand Down
28 changes: 28 additions & 0 deletions scripts/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,32 @@ export const writeToFile = (value, fileName: string) => {
}
};

/**
* Strips Non-breaking space (NBS) from a string and returns the result
*
* @param value the field to clean
* @returns the cleansed field
*/
export const cleanField = (value: string | null | undefined) =>
value?.replace(/\u00a0/g, ' ') || undefined;

/**
* Recursively strips NBS from an expression
*
* @param field the field to clean
* @returns the cleansed field
*/
export const clean = <E>(field: E) => {
switch (typeof field) {
case 'string':
return cleanField(field);
case 'object':
if (field == null) return field;
if (Array.isArray(field)) return field.map(clean);
return Object.fromEntries(Object.entries(field).map(([k, v]) => [k, clean(v)]));
default:
return field;
}
};

export default { writeToFile };

0 comments on commit 0afd370

Please sign in to comment.