chore: lint-format-docs-tests-bugfixes (#105)
* docs: add jsdoc * feat: change enums to as const objects * chore(test): add themeColors.test.ts * fix: fix tests and bugs with strings.ts util * fix: path alias imports and tsconfig file bug * fix: remove --max-warnings 0
This commit is contained in:
@@ -1,39 +1,44 @@
|
||||
import { Course, InstructionMode, ScrapedRow, Semester, Status } from '@shared/types/Course';
|
||||
import type { InstructionMode, ScrapedRow, Semester } from '@shared/types/Course';
|
||||
import { Course, Status } from '@shared/types/Course';
|
||||
import { CourseSchedule } from '@shared/types/CourseSchedule';
|
||||
import Instructor from '@shared/types/Instructor';
|
||||
import { SiteSupport } from '@views/lib/getSiteSupport';
|
||||
import type { SiteSupportType } from '@views/lib/getSiteSupport';
|
||||
|
||||
/**
|
||||
* The selectors that we use to scrape the course catalog list table (https://utdirect.utexas.edu/apps/registrar/course_schedule/20239/results/?fos_fl=C+S&level=U&search_type_main=FIELD)
|
||||
*/
|
||||
enum TableDataSelector {
|
||||
COURSE_HEADER = 'td.course_header',
|
||||
UNIQUE_ID = 'td[data-th="Unique"]',
|
||||
REGISTER_URL = 'td[data-th="Add"] a',
|
||||
INSTRUCTORS = 'td[data-th="Instructor"] span',
|
||||
INSTRUCTION_MODE = 'td[data-th="Instruction Mode"]',
|
||||
STATUS = 'td[data-th="Status"]',
|
||||
SCHEDULE_DAYS = 'td[data-th="Days"]>span',
|
||||
SCHEDULE_HOURS = 'td[data-th="Hour"]>span',
|
||||
SCHEDULE_LOCATION = 'td[data-th="Room"]>span',
|
||||
FLAGS = 'td[data-th="Flags"] ul li',
|
||||
}
|
||||
const TableDataSelector = {
|
||||
COURSE_HEADER: 'td.course_header',
|
||||
UNIQUE_ID: 'td[data-th="Unique"]',
|
||||
REGISTER_URL: 'td[data-th="Add"] a',
|
||||
INSTRUCTORS: 'td[data-th="Instructor"] span',
|
||||
INSTRUCTION_MODE: 'td[data-th="Instruction Mode"]',
|
||||
STATUS: 'td[data-th="Status"]',
|
||||
SCHEDULE_DAYS: 'td[data-th="Days"]>span',
|
||||
SCHEDULE_HOURS: 'td[data-th="Hour"]>span',
|
||||
SCHEDULE_LOCATION: 'td[data-th="Room"]>span',
|
||||
FLAGS: 'td[data-th="Flags"] ul li',
|
||||
} as const;
|
||||
|
||||
type TableDataSelectorType = (typeof TableDataSelector)[keyof typeof TableDataSelector];
|
||||
|
||||
/**
|
||||
* The selectors that we use to scrape the course details page for an individual course (https://utdirect.utexas.edu/apps/registrar/course_schedule/20239/52700/)
|
||||
*/
|
||||
enum DetailsSelector {
|
||||
COURSE_NAME = '#details h2',
|
||||
COURSE_DESCRIPTION = '#details p',
|
||||
}
|
||||
const DetailsSelector = {
|
||||
COURSE_NAME: '#details h2',
|
||||
COURSE_DESCRIPTION: '#details p',
|
||||
} as const;
|
||||
|
||||
type DetailsSelectorType = (typeof DetailsSelector)[keyof typeof DetailsSelector];
|
||||
|
||||
/**
|
||||
* A class that allows us to scrape information from UT's course catalog to create our internal representation of a course
|
||||
*/
|
||||
export class CourseCatalogScraper {
|
||||
support: SiteSupport;
|
||||
support: SiteSupportType;
|
||||
|
||||
constructor(support: SiteSupport) {
|
||||
constructor(support: SiteSupportType) {
|
||||
this.support = support;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import initSqlJs from 'sql.js/dist/sql-wasm';
|
||||
|
||||
import DB_FILE_URL from '@public/database/grades.db?url';
|
||||
import initSqlJs from 'sql.js/dist/sql-wasm';
|
||||
import WASM_FILE_URL from 'sql.js/dist/sql-wasm.wasm?url';
|
||||
// import WASM_FILE_URL from '../../../../public/database/sql-wasm.wasm?url';
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Course, Semester } from '@shared/types/Course';
|
||||
import { CourseSQLRow, Distribution } from '@shared/types/Distribution';
|
||||
import type { Course, Semester } from '@shared/types/Course';
|
||||
import type { CourseSQLRow, Distribution } from '@shared/types/Distribution';
|
||||
|
||||
import { initializeDB } from './initializeDB';
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,21 +4,27 @@ import { isExtensionPage, isExtensionPopup } from 'chrome-extension-toolkit';
|
||||
* An enum that represents the different types of pages that we support
|
||||
* a given url/page can correspond to many of these enum values
|
||||
*/
|
||||
export enum SiteSupport {
|
||||
COURSE_CATALOG_LIST = 'COURSE_CATALOG_LIST',
|
||||
COURSE_CATALOG_DETAILS = 'COURSE_CATALOG_DETAILS',
|
||||
UT_PLANNER = 'UT_PLANNER',
|
||||
WAITLIST = 'WAITLIST',
|
||||
EXTENSION_POPUP = 'EXTENSION_POPUP',
|
||||
MY_CALENDAR = 'MY_CALENDAR',
|
||||
}
|
||||
export const SiteSupport = {
|
||||
COURSE_CATALOG_LIST: 'COURSE_CATALOG_LIST',
|
||||
COURSE_CATALOG_DETAILS: 'COURSE_CATALOG_DETAILS',
|
||||
UT_PLANNER: 'UT_PLANNER',
|
||||
WAITLIST: 'WAITLIST',
|
||||
EXTENSION_POPUP: 'EXTENSION_POPUP',
|
||||
MY_CALENDAR: 'MY_CALENDAR',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Represents the type of SiteSupport.
|
||||
* It is a union type that includes all the values of the SiteSupport object.
|
||||
*/
|
||||
export type SiteSupportType = (typeof SiteSupport)[keyof typeof SiteSupport];
|
||||
|
||||
/**
|
||||
* We use this function to determine what page the user is on, and then we can use that information to determine what to do
|
||||
* @param url the url of the current page
|
||||
* @returns a list of page types that the current page is
|
||||
*/
|
||||
export default function getSiteSupport(url: string): SiteSupport | null {
|
||||
export default function getSiteSupport(url: string): SiteSupportType | null {
|
||||
if (isExtensionPopup()) {
|
||||
return SiteSupport.EXTENSION_POPUP;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,22 @@ import getCourseTableRows from './getCourseTableRows';
|
||||
|
||||
const NEXT_PAGE_BUTTON_SELECTOR = '#next_nav_link';
|
||||
const PREV_PAGE_BUTTON_SELECTOR = '#prev_nav_link';
|
||||
|
||||
/**
|
||||
* Represents all the states that we care about when autoloading the next page of courses
|
||||
*/
|
||||
export enum AutoLoadStatus {
|
||||
LOADING = 'LOADING',
|
||||
IDLE = 'IDLE',
|
||||
ERROR = 'ERROR',
|
||||
DONE = 'DONE',
|
||||
}
|
||||
export const AutoLoadStatus = {
|
||||
LOADING: 'LOADING',
|
||||
IDLE: 'IDLE',
|
||||
ERROR: 'ERROR',
|
||||
DONE: 'DONE',
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* Represents the type of the auto load status.
|
||||
* It is a union type that includes all the values of the AutoLoadStatus object.
|
||||
*/
|
||||
export type AutoLoadStatusType = (typeof AutoLoadStatus)[keyof typeof AutoLoadStatus];
|
||||
|
||||
let isLoading = false;
|
||||
let nextPageURL = getNextButton(document)?.href;
|
||||
@@ -22,7 +29,7 @@ let nextPageURL = getNextButton(document)?.href;
|
||||
* or if there was an error loading the next page) and an array of the table rows from the next page (or an empty array
|
||||
* if we have reached the end of the course catalog
|
||||
*/
|
||||
export async function loadNextCourseCatalogPage(): Promise<[AutoLoadStatus, HTMLTableRowElement[]]> {
|
||||
export async function loadNextCourseCatalogPage(): Promise<[AutoLoadStatusType, HTMLTableRowElement[]]> {
|
||||
// if there is no more nextPageURL, then we have reached the end of the course catalog, so we can stop
|
||||
if (!nextPageURL) {
|
||||
return [AutoLoadStatus.DONE, []];
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
import { createMessenger } from "chrome-extension-toolkit";
|
||||
import { createMessenger } from 'chrome-extension-toolkit';
|
||||
|
||||
type MyMessages = {
|
||||
openNewTab: {
|
||||
data: { url: string };
|
||||
data: { url: string };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
const messenger = createMessenger<MyMessages>('background');
|
||||
|
||||
/**
|
||||
* Content scripts and background scripts are isolated environments.
|
||||
/**
|
||||
* Content scripts and background scripts are isolated environments.
|
||||
* Content scripts are where our code interacting with the webpage lives,
|
||||
* whereas the background script is where we can open a tab from.
|
||||
* This function allows us to open a new tab from the content script by communicating
|
||||
* with the background script.
|
||||
* This function allows us to open a new tab from the content script by communicating
|
||||
* with the background script.
|
||||
*/
|
||||
export async function openTabFromContentScript(url: string) {
|
||||
// @ts-ignore
|
||||
messenger.openNewTab({ url }).then(() => {
|
||||
console.log('New tab opened with URL:', url);
|
||||
}).catch((error) => {
|
||||
console.error('Error opening new tab:', error);
|
||||
});
|
||||
messenger
|
||||
.openNewTab({ url })
|
||||
.then(() => {
|
||||
console.log('New tab opened with URL:', url);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error opening new tab:', error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* The course schedule page has a search form that allows users to search for courses by department and course level.
|
||||
* The problem is that once the user triggers a search and refreshes the page,
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import React from 'react';
|
||||
import type React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
|
||||
/**
|
||||
* Renders a React element into a container.
|
||||
* @param element - The React element to render.
|
||||
* @param container - The container element where the React element will be rendered.
|
||||
* @throws Error if the container is null.
|
||||
*/
|
||||
export default function render(element: React.ReactElement, container: HTMLElement | ShadowRoot | null) {
|
||||
if (!container) {
|
||||
throw new Error('Container is null');
|
||||
|
||||
Reference in New Issue
Block a user