feat: unit tests for utils (#92)

* init

* get unit test working for course.ts file

* added some other tests

* tests halfway + change config to accomodate js files

* utility functions tests done

* fix: config file + miscellaneous fixes

* fix: prepare script

* fix lock file

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Toyin Muhammed
2023-12-20 14:28:40 +03:00
committed by GitHub
co-authored by Rotimi Best
parent 4b2e58b1de
commit 6d689ede45
24 changed files with 2293 additions and 35 deletions
@@ -1,4 +1,5 @@
<script lang="ts">
import { browser } from '$app/environment';
import Modal from '$lib/components/Modal/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
@@ -98,7 +99,7 @@
}, 500);
}
$: note = getTextFromHTML($lesson?.materials?.note || '');
$: note = browser ? getTextFromHTML($lesson?.materials?.note || '') : '';
</script>
<Modal
@@ -1,4 +1,5 @@
<script lang="ts">
import { browser } from '$app/environment';
import isEmpty from 'lodash/isEmpty';
import { useCompletion } from 'ai/svelte';
import MODES from '$lib/utils/constants/mode.js';
@@ -84,7 +85,7 @@
if (!document) return false;
return getTextFromHTML(note) === '';
return browser ? getTextFromHTML(note) === '' : false;
}
function isMaterialsEmpty(materials: LessonPage['materials']) {
@@ -0,0 +1,30 @@
import isSubmissionEarly from './isSubmissionEarly';
describe('isSubmissionEarly', () => {
test('should return true when createdAt is earlier than dueDate', () => {
const dueDate = Date.now();
const createdAt = new Date('2023-12-15');
const result = isSubmissionEarly(createdAt, dueDate);
expect(result).toBe(true);
});
test('should return true when both createdAt and dueDate are null', () => {
const dueDate = null;
const createdAt = null;
const result = isSubmissionEarly(createdAt, dueDate);
expect(result).toBe(true);
});
test('should return true when createdAt is the same as dueDate', () => {
const dueDate = new Date('2023-12-15');
const createdAt = new Date('2023-12-15');
const result = isSubmissionEarly(createdAt, dueDate);
expect(result).toBe(true);
});
test('should return false when createdAt is later than dueDate', () => {
const dueDate = new Date('2023-12-15');
const createdAt = new Date('2023-12-16');
const result = isSubmissionEarly(createdAt, dueDate);
expect(result).toBe(false);
});
});
@@ -0,0 +1,18 @@
import { isCourseFree } from './course';
describe('course.ts', () => {
test('Should return True when cost is 0', () => {
const result = isCourseFree(0);
expect(result).toBeTruthy();
});
test('Should return true when cost is negative', () => {
const result = isCourseFree(-10);
expect(result).toBeTruthy();
});
test('Should return True when cost is Not A Number', () => {
const result = isCourseFree(NaN);
expect(result).toBeTruthy();
});
});
@@ -1,4 +1,3 @@
import { browser } from '$app/environment';
import type { Course } from '../types';
export const isCourseFree = (cost: number) => !(Number(cost) > 0);
@@ -19,8 +18,6 @@ export const getStudentInviteLink = (_course: Course, orgSiteName: string, origi
};
export const getTextFromHTML = (html: string): string => {
if (!browser) return html;
const dummyDiv = document.createElement('div');
dummyDiv.innerHTML = html;
@@ -0,0 +1,36 @@
import { calDateDiff, getGreeting } from './date';
describe('calDateDiff', () => {
test('should return the correct time difference when the input date is in the past', () => {
const inputDate = new Date('2022-01-01');
const expectedOutput = '2 years ago';
const result = calDateDiff(inputDate);
expect(result).toBe(expectedOutput);
});
test('should return the correct time difference when the input date is a number', () => {
const inputDate = new Date(1640995200000); // January 1, 2022
const expectedOutput = '2 years ago';
const result = calDateDiff(inputDate);
expect(result).toBe(expectedOutput);
});
});
describe('getGreeting', () => {
test("should return 'Good Morning' when the current time is before 12pm", () => {
jest.useFakeTimers().setSystemTime(new Date('2023-12-10T00:21:01.691Z'));
expect(getGreeting()).toBe('Good Morning');
});
test("should return 'Good Afternoon' when the current time is after 12pm", () => {
jest.useFakeTimers().setSystemTime(new Date('2023-12-10T14:21:01.691Z'));
expect(getGreeting()).toBe('Good Afternoon');
});
test("should return 'Good Evening' when the current time is after 6pm", () => {
jest.useFakeTimers().setSystemTime(new Date('2023-12-10T19:21:01.691Z'));
expect(getGreeting()).toBe('Good Evening');
});
});
@@ -0,0 +1,46 @@
import { formatYoutubeVideo, getEmbedId } from './formatYoutubeVideo';
describe('format youtube video', () => {
test('should return the same url when given a valid youtube embed url', () => {
const url = 'https://www.youtube.com/embed/qajK1J1neAM';
const errors = { video: '' };
const result = formatYoutubeVideo(url, errors);
expect(result).toBe(url);
});
test('should return the correct embed url when given a youtube url with a start time parameter', () => {
const url = 'https://www.youtube.com/watch?v=qajK1J1neAM&start=123';
const errors = { video: '' };
const result = formatYoutubeVideo(url, errors);
expect(result).toBe('https://www.youtube.com/embed/qajK1J1neAM');
});
});
describe('getEmbedId', () => {
test('should return the correct embed id when the url contains "embed"', () => {
const url = 'https://www.youtube.com/embed/qajK1J1neAM';
const expectedEmbedId = 'qajK1J1neAM';
const result = getEmbedId(url);
expect(result).toBe(expectedEmbedId);
});
test('should return an empty string when the url does not contain "watch" or "embed" and is not in the format "youtu.be/"', () => {
const url = 'https://www.youtube.com/invalid-url';
const expectedEmbedId = '';
const result = getEmbedId(url);
expect(result).toBe(expectedEmbedId);
});
test('should return an empty string when the url is an empty string', () => {
const url = '';
const expectedEmbedId = '';
const result = getEmbedId(url);
expect(result).toBe(expectedEmbedId);
});
});
@@ -0,0 +1,25 @@
import genUniqueId from './genUniqueId';
describe('Generate Unique Ids', () => {
test('should start with letter', () => {
const result = genUniqueId();
const firstChar = result.charAt(0);
expect(firstChar).toMatch(/[a-zA-Z]/);
});
test('should not contain special characters', () => {
const result = genUniqueId();
expect(result).toMatch(/^[a-zA-Z0-9]+$/);
});
test('should return different ids on multiple calls', () => {
const result1 = genUniqueId();
const result2 = genUniqueId();
expect(result1).not.toEqual(result2);
});
test('multiple calls in closer time frames should have same first 3 letters', () => {
const result1 = genUniqueId();
const result2 = genUniqueId();
expect(result1.substring(0, 4)).toEqual(result2.substring(0, 4));
});
});
@@ -0,0 +1,17 @@
import generateSlug from './generateSlug';
describe('generateSlug', () => {
test('should return a string with lowercase letters and hyphens when given a valid title', () => {
const title = 'This is a Valid Title';
const expected = 'this-is-a-valid-title' + `-${new Date().getTime()}`;
const result = generateSlug(title);
expect(result).toBe(expected);
});
test('should include the current timestamp at the end of the string', () => {
const title = 'This is a Valid Title';
const result = generateSlug(title);
const timestamp = result.split('-').pop();
expect(Number(timestamp)).toBeGreaterThan(0);
});
});
@@ -0,0 +1,26 @@
import generateUUID from './generateUUID';
import { isUUID } from './isUUID';
// This test suite tests both the generateUUID and isUUID functions
describe('GenerateUUID', () => {
test('should be true when tested with the uuid function', () => {
const result = generateUUID();
expect(isUUID(result)).toBe(true);
});
test('should generate unique UUIDs each time', () => {
const uuid1 = generateUUID();
const uuid2 = generateUUID();
expect(uuid1).not.toBe(uuid2);
});
test('should return true for a valid UUID', () => {
const uuid = '123e4567-e89b-12d3-a456-426614174000';
expect(isUUID(uuid)).toBe(true);
});
test('should return false for an invalid UUID', () => {
const uuid = 'invalid-uuid';
expect(isUUID(uuid)).toBe(false);
});
});
@@ -0,0 +1,27 @@
import getCurrencyFormatter from './getCurrencyFormatter';
describe('GetCurrencyFormatter', () => {
test('should return a new instance of Intl.NumberFormat with the correct locale and currency options when currency is "NGN"', () => {
const result = getCurrencyFormatter('NGN');
expect(result).toBeInstanceOf(Intl.NumberFormat);
expect(result.resolvedOptions().locale).toBe('en-NG');
expect(result.resolvedOptions().currency).toBe('NGN');
expect(result.resolvedOptions().minimumFractionDigits).toBe(2);
});
test('should return a new instance of Intl.NumberFormat with the correct locale and currency options when currency is "USD"', () => {
const result = getCurrencyFormatter('USD');
expect(result).toBeInstanceOf(Intl.NumberFormat);
expect(result.resolvedOptions().locale).toBe('en-US');
expect(result.resolvedOptions().currency).toBe('USD');
expect(result.resolvedOptions().minimumFractionDigits).toBe(2);
});
test('should return a new instance of Intl.NumberFormat with the correct locale and currency options when currency is "EUR"', () => {
const result = getCurrencyFormatter('EUR');
expect(result).toBeInstanceOf(Intl.NumberFormat);
expect(result.resolvedOptions().locale).toBe('en-US');
expect(result.resolvedOptions().currency).toBe('EUR');
expect(result.resolvedOptions().minimumFractionDigits).toBe(2);
});
});
@@ -0,0 +1,23 @@
import { isObject } from './isObject';
describe('isObject', () => {
test('should return true for an empty object', () => {
const obj = {};
expect(isObject(obj)).toBe(true);
});
test('should return false for a non-object', () => {
const obj = 'not an object';
expect(isObject(obj)).toBe(false);
});
test('should return true for a nested object', () => {
const obj = { prop1: { prop2: 'value2' } };
expect(isObject(obj)).toBe(true);
});
test('should return true for an object with properties', () => {
const obj = { prop1: 'value1', prop2: 'value2' };
expect(isObject(obj)).toBe(true);
});
});
@@ -1,3 +1,4 @@
//
export function isObject(obj) {
return obj === Object(obj);
}
@@ -0,0 +1,60 @@
import { genQuizPin, generateSitename } from './org';
describe('Generate Quiz Pin', () => {
test('should return a random 6-digit pin', () => {
const result = genQuizPin();
expect(result.toString().length).toBe(6);
});
test('should return random pin each time', () => {
const result1 = genQuizPin();
const result2 = genQuizPin();
expect(result1).not.toBe(result2);
});
test('should generate a pin between 100000 and 999999', () => {
const result = genQuizPin();
expect(result).toBeGreaterThanOrEqual(100000);
expect(result).toBeLessThanOrEqual(999999);
});
test('should not generate a negative pin', () => {
const result = genQuizPin();
expect(result).toBeGreaterThanOrEqual(0);
});
test('should generate an integer pin', () => {
const result = genQuizPin();
expect(Number.isInteger(result)).toBe(true);
});
test('should not generate a zero pin', () => {
const result = genQuizPin();
expect(result).not.toBe(0);
});
});
describe('Generate Site name', () => {
test('should return slug-like string', () => {
const result = generateSitename('classroom org international');
const expected = 'classroom-org-international';
expect(result).toBe(expected);
});
test('should remove special characters', () => {
const result = generateSitename('classroom@ org! international');
const expected = 'classroom-org-international';
expect(result).toBe(expected);
});
test('should return empty string when orgName is an empty string', () => {
const result = generateSitename('');
const expected = '';
expect(result).toBe(expected);
});
test('should return slug-like string with all uppercase characters converted to lowercase', () => {
const result = generateSitename('Classroom Org International');
const expected = 'classroom-org-international';
expect(result).toBe(expected);
});
});
@@ -0,0 +1,38 @@
import { removeDuplicate } from './removeDuplicate';
describe('removeDuplicate', () => {
test('should remove duplicate elements of an array', () => {
const result = removeDuplicate([1, 1, 2, 3, 3, 4, 5]);
const expected = [1, 2, 3, 4, 5];
expect(result).toStrictEqual(expected);
expect(result.length).toBe(5);
});
test('should return an empty array', () => {
const result = removeDuplicate([]);
const expected = [];
expect(result).toStrictEqual(expected);
expect(result.length).toBe(0);
});
test('should return an array with the same element', () => {
const result = removeDuplicate([1]);
const expected = [1];
expect(result).toStrictEqual(expected);
expect(result.length).toBe(1);
});
test('should return an array with only one element', () => {
const result = removeDuplicate([1, 1, 1, 1]);
const expected = [1];
expect(result).toStrictEqual(expected);
expect(result.length).toBe(1);
});
test('should return an array with the unique elements in the same order as the original array', () => {
const result = removeDuplicate([1, 2, 3, 4, 5, 1, 2, 3, 4, 5]);
const expected = [1, 2, 3, 4, 5];
expect(result).toStrictEqual(expected);
expect(result.length).toBe(5);
});
});
@@ -0,0 +1,26 @@
import showAppsSideBar from './showAppsSideBar';
describe('ShowAppSideBar', () => {
test("should return true when path includes '/lessons/' and does not include 'landingpage'", () => {
const path = '/lessons/example';
const result = showAppsSideBar(path);
expect(result).toBe(true);
});
test("should return false when path does not include '/lessons/'", () => {
const path = '/home';
const result = showAppsSideBar(path);
expect(result).toBe(false);
});
test("should return false when path includes 'landingpage'", () => {
const path = '/lessons/landingpage';
const result = showAppsSideBar(path);
expect(result).toBe(false);
});
test('should return false when path is empty', () => {
const path = '';
const result = showAppsSideBar(path);
expect(result).toBe(false);
});
});
@@ -0,0 +1,28 @@
import { capitalizeFirstLetter } from './string';
describe('capitalize first letter', () => {
test('should return the same string with the first letter capitalized', () => {
const result = capitalizeFirstLetter('classroom');
expect(result).toEqual('Classroom');
});
test('should return an empty string when given an empty string', () => {
const result = capitalizeFirstLetter('');
expect(result).toEqual('');
});
test('should return the same string when given a string with all uppercase letters', () => {
const result = capitalizeFirstLetter('UPPERCASE');
expect(result).toEqual('UPPERCASE');
});
test('should return the same string when given a string with a non-alphabetical first character', () => {
const result = capitalizeFirstLetter('123abc');
expect(result).toEqual('123abc');
});
test('should return the first letter of the first word capitalized when given a sentence', () => {
const result = capitalizeFirstLetter('classroomio is an open source project');
expect(result).toEqual('Classroomio is an open source project');
});
});
@@ -0,0 +1,28 @@
import { validateEmail } from './validateEmail';
describe('validate email', () => {
test('should return true for a valid email format', () => {
const result = validateEmail('test@example.com');
expect(result).toBeTruthy();
});
test('should return false for an empty email', () => {
const result = validateEmail('');
expect(result).toBeFalsy();
});
test('should return true for a valid email with uppercase letters', () => {
const result = validateEmail('Test@Example.com');
expect(result).toBeTruthy();
});
test('should return false for an invalid email format', () => {
const result = validateEmail('test@example');
expect(result).toBeFalsy();
});
test('should return true for a valid email with special characters', () => {
const result = validateEmail('test+123@example.com');
expect(result).toBeTruthy();
});
});