├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .release-it.json ├── .travis.yml ├── LICENSE ├── README.md ├── lib ├── index.ts ├── table.ts ├── timetable-list.ts ├── timetable.ts └── types.ts ├── package-lock.json ├── package.json ├── test ├── expected │ ├── class-days.json │ ├── plain-class-days.json │ └── room-days.json ├── fixtures │ ├── index.html │ ├── lista-expandable.html │ ├── lista-select.html │ ├── lista-unordered.html │ ├── oddzial.html │ ├── plain-oddzial.html │ └── sala.html └── test.ts ├── tsconfig.build.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | end_of_line = lf 10 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "airbnb-base", 4 | "airbnb-typescript/base" 5 | ], 6 | "parserOptions": { 7 | "project": "./tsconfig.json" 8 | }, 9 | "root": true, 10 | "rules": { 11 | "prefer-destructuring": "off" 12 | }, 13 | "overrides": [ 14 | { 15 | "files": [ 16 | "test/**" 17 | ], 18 | "env": { 19 | "mocha": true 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .vscode 3 | .idea 4 | dist 5 | -------------------------------------------------------------------------------- /.release-it.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "release": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" # Latest stable Node.js release 4 | 5 | script: 6 | - npm run lint 7 | - npm run test 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Wulkanowy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![license](https://img.shields.io/github/license/wulkanowy/timetable-parser-js?logo=github&style=for-the-badge)](https://github.com/wulkanowy/timetable-parser-js) 2 | [![stars](https://img.shields.io/github/stars/wulkanowy/timetable-parser-js?logo=github&style=for-the-badge)](https://github.com/wulkanowy/timetable-parser-js) 3 | [![npm](https://img.shields.io/npm/v/@wulkanowy/timetable-parser?style=for-the-badge&logo=npm)](https://www.npmjs.com/package/@wulkanowy/timetable-parser) 4 | # VULCAN Optivum Timetable parser for JS 5 | Based on [wulkanowy/timetable-parser-php](https://github.com/wulkanowy/timetable-parser-php) *(not 1:1 copy)* 6 | 7 | # Installation 8 | 9 | ### Via NPM 10 | 11 | ```bash 12 | $ npm install @wulkanowy/timetable-parser 13 | ``` 14 | 15 | # Usage 16 | 17 | ## Parsing Timetable Index Page 18 | ```js 19 | import { Timetable } from '@wulkanowy/timetable-parser'; 20 | 21 | const timetable = new Timetable(/*Content of index.html file*/); 22 | 23 | // Returns: String containing title of the timetable 24 | const title = timetable.getTitle() 25 | 26 | // Returns: String containing path to lista.html file 27 | const list = timetable.getListPath() 28 | ``` 29 | 30 | ## Parsing Timetable List 31 | ```js 32 | import { TimetableList } from '@wulkanowy/timetable-parser'; 33 | 34 | const timetableList = new TimetableList(/*Content of lista.html file*/); 35 | 36 | // Returns: Object of 3 lists 37 | const list = timetableList.getList(); 38 | 39 | // Returns: String containing path to school logo 40 | const logo = timetableList.getLogoSrc() 41 | ``` 42 | 43 | ## Parsing Table 44 | ```js 45 | import { Table } from '@wulkanowy/timetable-parser'; 46 | 47 | const table = new Table(/*Content of plany/XYY.html file*/); 48 | 49 | // Returns: String containing title of the timetable 50 | const title = table.getTitle(); 51 | 52 | // Returns: Array of days from timetable headers 53 | const dayNames = table.getDayNames() 54 | 55 | // Returns: Object of hours 56 | const hours = table.getHours() 57 | 58 | // Returns: Array of lessons sorted by lesson number 59 | const rawDays = table.getRawDays() 60 | 61 | // Returns: Array of lessons sorted by days 62 | const days = table.getDays() 63 | 64 | // Returns: String containing timetable generation date 65 | const generated = title.getGeneratedDate() 66 | 67 | // Returns: String containing timetable effective date 68 | const generated = title.getVersionInfo() 69 | ``` 70 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import Table from './table'; 2 | import TimetableList from './timetable-list'; 3 | import Timetable from './timetable'; 4 | 5 | export { 6 | Table, TimetableList, Timetable, 7 | }; 8 | export * from './types'; 9 | -------------------------------------------------------------------------------- /lib/table.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AnyNode, Cheerio, CheerioAPI, Element, load, 3 | } from 'cheerio'; 4 | import { TableHour, TableLesson } from './types'; 5 | 6 | export default class Table { 7 | public $: CheerioAPI; 8 | 9 | public constructor(html: string) { 10 | this.$ = load(html); 11 | } 12 | 13 | /* 14 | * Parses the text from the header, for instance class name 15 | */ 16 | public getTitle(): string { 17 | return this.$('.tytulnapis').text(); 18 | } 19 | 20 | public getDayNames(): string[] { 21 | return this.$('.tabela tr:first-of-type th') 22 | .toArray() 23 | .map((element: Element): string => this.$(element).text()) 24 | .slice(2); 25 | } 26 | 27 | public getHours(): Record { 28 | const rows = this.$('.tabela tr:not(:first-of-type)'); 29 | const hours: Record = {}; 30 | rows.each((_, row): void => { 31 | const number = parseInt(this.$(row).find('.nr').text().trim(), 10); 32 | const timesText = this.$(row).find('.g').text(); 33 | const [timeFrom, timeTo] = timesText 34 | .split('-') 35 | .map((e): string => e.trim()); 36 | hours[number] = { 37 | number, 38 | timeFrom, 39 | timeTo, 40 | }; 41 | }); 42 | return hours; 43 | } 44 | 45 | /* 46 | * Return table in original form (without transposing) for easier displaying. 47 | */ 48 | public getRawDays(): TableLesson[][][] { 49 | const rows = this.$('.tabela tr:not(:first-of-type)').toArray(); 50 | 51 | const days: TableLesson[][][] = []; 52 | 53 | rows.forEach((row, index): void => { 54 | const lessons = this.$(row).find('.l').toArray(); 55 | lessons.forEach((lesson): void => { 56 | if (!days[index]) days.push([]); 57 | if (this.$(lesson).text().trim() === '') { 58 | days[index].push([]); 59 | } else if (this.$(lesson).children().length === 0) { 60 | days[index].push([{ subject: this.$(lesson).text().trim() }]); 61 | } else { 62 | const groups = this.parseLessons(this.$(lesson).contents()); 63 | days[index].push(groups); 64 | } 65 | }); 66 | }); 67 | 68 | return days; 69 | } 70 | 71 | public getDays(): TableLesson[][][] { 72 | const rows = this.$('.tabela tr:not(:first-of-type)').toArray(); 73 | 74 | const days: TableLesson[][][] = [ 75 | [], 76 | [], 77 | [], 78 | [], 79 | [], 80 | ]; 81 | 82 | rows.forEach((row): void => { 83 | this.$(row) 84 | .find('.l') 85 | .each((index, lesson): void => { 86 | if (this.$(lesson).text().trim() === '') { 87 | days[index].push([]); 88 | } else if (this.$(lesson).children().length === 0) { 89 | days[index].push([{ subject: this.$(lesson).text().trim() }]); 90 | } else { 91 | const groups = this.parseLessons(this.$(lesson).contents()); 92 | days[index].push(groups); 93 | } 94 | }); 95 | }); 96 | 97 | return days; 98 | } 99 | 100 | /* 101 | Date in ISO 8601 format 102 | */ 103 | public getGeneratedDate(): string | null { 104 | const regex = /wygenerowano (\d{1,4})[./-](\d{1,2})[./-](\d{1,4})/; 105 | return this.$('td') 106 | .toArray() 107 | .map((e): string | null => { 108 | const match = regex.exec(this.$(e).text()); 109 | if (match === null) return null; 110 | const parts = [match[1], match[2], match[3]]; 111 | if (parts[0].length !== 4) parts.reverse(); 112 | return `${parts[0]}-${parts[1].padStart(2, '0')}-${parts[2].padStart(2, '0')}`; 113 | }) 114 | .filter((e): boolean => e != null)[0] || null; 115 | } 116 | 117 | /* 118 | Usually includes the dates when the table is valid. 119 | */ 120 | public getVersionInfo(): string { 121 | const regex = /^Obowiązuje od: (.+)$/; 122 | return this.$('td') 123 | .toArray() 124 | .map((e): string | null => { 125 | const match = regex.exec(this.$(e).text().trim()); 126 | if (match === null) return ''; 127 | return match[1].trim(); 128 | }) 129 | .filter((e): boolean => e !== '')[0] || ''; 130 | } 131 | 132 | private static getId(el: Cheerio, letter: string): string | undefined { 133 | const href = el.attr('href') || ''; 134 | return new RegExp(`^${letter}(.+)\\.html$`).exec(href)?.[1]; 135 | } 136 | 137 | private parseLessons(nodes: Cheerio): TableLesson[] { 138 | const lines: Cheerio[][] = [[]]; 139 | 140 | nodes.each((_, node) => { 141 | if ('tagName' in node && node.tagName === 'br') { 142 | lines.push([]); 143 | return; 144 | } 145 | lines[lines.length - 1].push(this.$(node)); 146 | }); 147 | 148 | return lines.flatMap((line): TableLesson[] => { 149 | const common: Pick = { subject: '' }; 150 | const groups: Partial>[] = [{}]; 151 | line.forEach((el) => { 152 | if (el[0].type === 'text') { 153 | el.text().split(',').forEach((part, index) => { 154 | if (index > 0) groups.push({}); 155 | if (part.trim() === '') return; 156 | const groupNameMatch = part.trim().match(/-(\d+\/\d+)/); 157 | if (groupNameMatch !== null) groups[groups.length - 1].groupName = groupNameMatch[1]; 158 | }); 159 | return; 160 | } 161 | 162 | const group = groups[groups.length - 1]; 163 | 164 | const withElement = ( 165 | className: string, 166 | callback: (child: Cheerio) => void, 167 | ) => { 168 | if (el.hasClass(className)) { 169 | callback(el); 170 | return; 171 | } 172 | const children = el.find(`.${className}`); 173 | if (children.length > 0) callback(children); 174 | }; 175 | 176 | withElement('p', (child): void => { 177 | const match = child.text().trim().match(/^(.*?)(?:-(\d+\/\d+))?$/); 178 | if (!match) return; 179 | if (match[2]) group.groupName = match[2]; 180 | if (match[1]) { 181 | if (common.subject) common.subject += ' '; 182 | common.subject += match[1].trim(); 183 | } 184 | }); 185 | 186 | withElement('o', (child): void => { 187 | group.className = child.text(); 188 | group.classId = Table.getId(child, 'o'); 189 | }); 190 | 191 | withElement('n', (child): void => { 192 | common.teacher = child.text(); 193 | common.teacherId = Table.getId(child, 'n'); 194 | }); 195 | 196 | withElement('s', (child): void => { 197 | common.room = child.text(); 198 | common.roomId = Table.getId(child, 's'); 199 | }); 200 | }); 201 | if (common.subject.trim() === '') return []; 202 | return groups.map((group) => ({ 203 | ...common, 204 | ...group, 205 | })); 206 | }); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /lib/timetable-list.ts: -------------------------------------------------------------------------------- 1 | import { CheerioAPI, load } from 'cheerio'; 2 | import { List, ListItem } from './types'; 3 | 4 | export default class TimetableList { 5 | public $: CheerioAPI; 6 | 7 | public constructor(html: string) { 8 | this.$ = load(html); 9 | } 10 | 11 | public getList(): List { 12 | if (this.getListType() === 'select') { 13 | return this.getSelectList(); 14 | } if (this.getListType() === 'unordered') { 15 | return this.getUnorderedList(); 16 | } 17 | 18 | return this.getExpandableList(); 19 | } 20 | 21 | public getListType(): string { 22 | if (this.$('form[name=form]').length > 0) { 23 | return 'select'; 24 | } 25 | 26 | if (this.$('body table').length > 0) { 27 | return 'expandable'; 28 | } 29 | 30 | return 'unordered'; 31 | } 32 | 33 | public getLogoSrc(): string | null { 34 | return this.$('.logo img').attr('src') || null; 35 | } 36 | 37 | private getSelectList(): List { 38 | return { 39 | classes: this.getSelectListValues('oddzialy'), 40 | teachers: this.getSelectListValues('nauczyciele'), 41 | rooms: this.getSelectListValues('sale'), 42 | }; 43 | } 44 | 45 | private getSelectListValues(name: string): ListItem[] { 46 | const nodes = this.$(`[name=${name}] option`).toArray(); 47 | nodes.shift(); 48 | 49 | const values: ListItem[] = []; 50 | nodes.forEach((node): void => { 51 | values.push({ 52 | name: this.$(node).text(), 53 | value: this.$(node).attr('value') || '', 54 | }); 55 | }); 56 | 57 | return values; 58 | } 59 | 60 | private getExpandableList(): List { 61 | return this.getTimetableUrlSubType( 62 | '#oddzialy a', 63 | '#nauczyciele a', 64 | '#sale a', 65 | ); 66 | } 67 | 68 | private getUnorderedList(): List { 69 | let teachersQuery = 'ul:nth-of-type(2) a'; 70 | let roomsQuery = 'ul:nth-of-type(3) a'; 71 | if (this.$('h4').length === 1) { 72 | teachersQuery = 'undefined'; 73 | roomsQuery = 'undefined'; 74 | } else if (this.$('h4:nth-of-type(2)').text() === 'Sale') { 75 | teachersQuery = 'undefined'; 76 | roomsQuery = 'ul:nth-of-type(2) a'; 77 | } 78 | return this.getTimetableUrlSubType( 79 | 'ul:first-of-type a', 80 | teachersQuery, 81 | roomsQuery, 82 | ); 83 | } 84 | 85 | private getTimetableUrlSubType( 86 | classQuery: string, 87 | teachersQuery: string, 88 | roomsQuery: string, 89 | ): List { 90 | return { 91 | classes: this.getSubTypeValue(classQuery, 'o'), 92 | teachers: this.getSubTypeValue(teachersQuery, 'n'), 93 | rooms: this.getSubTypeValue(roomsQuery, 's'), 94 | }; 95 | } 96 | 97 | private getSubTypeValue(query: string, prefix: string): ListItem[] { 98 | const values: ListItem[] = []; 99 | 100 | this.$(query).each((_, node) => { 101 | values.push({ 102 | name: this.$(node).text(), 103 | value: this.$(node).attr('href')?.replace('.html', '').replace(`plany/${prefix}`, '') || '', 104 | }); 105 | }); 106 | 107 | return values; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/timetable.ts: -------------------------------------------------------------------------------- 1 | import { CheerioAPI, load } from 'cheerio'; 2 | 3 | export default class Timetable { 4 | public $: CheerioAPI; 5 | 6 | public constructor(html: string) { 7 | this.$ = load(html); 8 | } 9 | 10 | public getTitle(): string { 11 | return this.$('title').text(); 12 | } 13 | 14 | public getListPath(): string { 15 | return this.$('frame[name="list"]').attr('src') || ''; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lib/types.ts: -------------------------------------------------------------------------------- 1 | export interface TableHour { 2 | number: number; 3 | timeFrom: string; 4 | timeTo: string; 5 | } 6 | 7 | export interface TableLesson { 8 | subject: string; 9 | room?: string; 10 | roomId?: string; 11 | groupName?: string; 12 | teacher?: string; 13 | teacherId?: string; 14 | className?: string; 15 | classId?: string; 16 | } 17 | 18 | export interface List { 19 | classes: ListItem[]; 20 | teachers?: ListItem[]; 21 | rooms?: ListItem[]; 22 | } 23 | 24 | export interface ListItem { 25 | name: string; 26 | value: string; 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wulkanowy/timetable-parser", 3 | "version": "1.6.0", 4 | "description": "VULCAN Optivum Timetable parser for JavaScript", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "files": [ 8 | "/dist" 9 | ], 10 | "scripts": { 11 | "build": "del-cli dist && tsc --p tsconfig.build.json", 12 | "lint": "eslint ./lib/ ./test/ --ext .js,.ts", 13 | "lint:fix": "eslint ./lib/ ./test/ --ext .js,.ts --fix", 14 | "prepare": "npm run build", 15 | "release": "release-it --only-version", 16 | "test": "mocha --reporter spec --require ts-node/register test/**/*.ts" 17 | }, 18 | "author": "Dominik Korsa ", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/wulkanowy/timetable-parser-js.git" 22 | }, 23 | "license": "MIT", 24 | "devDependencies": { 25 | "@types/chai": "^4.3.6", 26 | "@types/mocha": "^10.0.1", 27 | "@typescript-eslint/eslint-plugin": "^6.6.0", 28 | "@typescript-eslint/parser": "^6.6.0", 29 | "chai": "^4.3.6", 30 | "del-cli": "^5.1.0", 31 | "eslint": "^8.49.0", 32 | "eslint-config-airbnb-typescript": "^17.1.0", 33 | "mocha": "^10.2.0", 34 | "release-it": "^15.10.3", 35 | "ts-node": "^10.9.1", 36 | "typescript": "^5.2.2" 37 | }, 38 | "dependencies": { 39 | "cheerio": "^1.0.0-rc.12" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /test/expected/class-days.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | { 5 | "groupName": "2/2", 6 | "subject": "sieci.komput", 7 | "teacher": "Dr", 8 | "teacherId": "14", 9 | "room": "35", 10 | "roomId": "13" 11 | } 12 | ], 13 | [ 14 | { 15 | "groupName": "2/2", 16 | "subject": "sieci.komput", 17 | "teacher": "Dr", 18 | "teacherId": "14", 19 | "room": "35", 20 | "roomId": "13" 21 | } 22 | ], 23 | [ 24 | { 25 | "groupName": "1/2", 26 | "subject": "tw.apl.inter", 27 | "teacher": "Ko", 28 | "teacherId": "27", 29 | "room": "33", 30 | "roomId": "11" 31 | }, 32 | { 33 | "groupName": "2/2", 34 | "subject": "sieci.komput", 35 | "teacher": "Dr", 36 | "teacherId": "14", 37 | "room": "35", 38 | "roomId": "13" 39 | } 40 | ], 41 | [ 42 | { 43 | "groupName": "1/2", 44 | "subject": "tw.apl.inter", 45 | "teacher": "Ko", 46 | "teacherId": "27", 47 | "room": "33", 48 | "roomId": "11" 49 | }, 50 | { 51 | "groupName": "2/2", 52 | "subject": "sieci.komput", 53 | "teacher": "Dr", 54 | "teacherId": "14", 55 | "room": "35", 56 | "roomId": "13" 57 | } 58 | ], 59 | [ 60 | { 61 | "subject": "j.polski", 62 | "teacher": "ZJ", 63 | "teacherId": "67", 64 | "room": "21", 65 | "roomId": "4" 66 | } 67 | ], 68 | [ 69 | { 70 | "groupName": "1/2", 71 | "subject": "r_fizyka", 72 | "teacher": "Ba", 73 | "teacherId": "1", 74 | "room": "19", 75 | "roomId": "3" 76 | }, 77 | { 78 | "groupName": "2/2", 79 | "subject": "met.programo", 80 | "teacher": "PB", 81 | "teacherId": "41", 82 | "room": "32", 83 | "roomId": "10" 84 | } 85 | ], 86 | [ 87 | { 88 | "groupName": "1/2", 89 | "subject": "r_fizyka", 90 | "teacher": "Ba", 91 | "teacherId": "1", 92 | "room": "19", 93 | "roomId": "3" 94 | }, 95 | { 96 | "groupName": "2/2", 97 | "subject": "s.operacyjne", 98 | "teacher": "Oż", 99 | "teacherId": "39", 100 | "room": "32", 101 | "roomId": "10" 102 | } 103 | ], 104 | [ 105 | { 106 | "groupName": "1/2", 107 | "subject": "s.operacyjne", 108 | "teacher": "Oż", 109 | "teacherId": "39", 110 | "room": "32", 111 | "roomId": "10" 112 | }, 113 | { 114 | "groupName": "2/2", 115 | "subject": "tw.baz.dan", 116 | "teacher": "Dę", 117 | "teacherId": "13", 118 | "room": "34", 119 | "roomId": "12" 120 | } 121 | ], 122 | [], 123 | [] 124 | ], 125 | [ 126 | [], 127 | [], 128 | [ 129 | { 130 | "groupName": "1/2", 131 | "subject": "angielski g", 132 | "teacher": "BM", 133 | "teacherId": "4", 134 | "room": "W11", 135 | "roomId": "20" 136 | }, 137 | { 138 | "groupName": "2/2", 139 | "subject": "angielski g", 140 | "teacher": "Pi", 141 | "teacherId": "42", 142 | "room": "W3", 143 | "roomId": "19" 144 | } 145 | ], 146 | [ 147 | { 148 | "groupName": "1/2", 149 | "subject": "angielski g", 150 | "teacher": "BM", 151 | "teacherId": "4", 152 | "room": "W11", 153 | "roomId": "20" 154 | }, 155 | { 156 | "groupName": "2/2", 157 | "subject": "angielski g", 158 | "teacher": "Pi", 159 | "teacherId": "42", 160 | "room": "W3", 161 | "roomId": "19" 162 | } 163 | ], 164 | [ 165 | { 166 | "subject": "u_hist.i sp.", 167 | "teacher": "Ho", 168 | "teacherId": "25", 169 | "room": "21", 170 | "roomId": "4" 171 | } 172 | ], 173 | [ 174 | { 175 | "subject": "matematyka", 176 | "teacher": "PB", 177 | "teacherId": "41", 178 | "room": "23", 179 | "roomId": "6" 180 | } 181 | ], 182 | [ 183 | { 184 | "subject": "godz.wych", 185 | "teacher": "PB", 186 | "teacherId": "41", 187 | "room": "32", 188 | "roomId": "10" 189 | } 190 | ], 191 | [ 192 | { 193 | "groupName": "1/2", 194 | "subject": "sieci.komput", 195 | "teacher": "Dr", 196 | "teacherId": "14", 197 | "room": "35", 198 | "roomId": "13" 199 | }, 200 | { 201 | "groupName": "2/2", 202 | "subject": "r_fizyka #3fi", 203 | "room": "19", 204 | "roomId": "3" 205 | } 206 | ], 207 | [ 208 | { 209 | "groupName": "1/2", 210 | "subject": "sieci.komput", 211 | "teacher": "Dr", 212 | "teacherId": "14", 213 | "room": "35", 214 | "roomId": "13" 215 | }, 216 | { 217 | "groupName": "2/2", 218 | "subject": "r_fizyka #3fi", 219 | "room": "19", 220 | "roomId": "3" 221 | } 222 | ], 223 | [ 224 | { 225 | "groupName": "1/2", 226 | "subject": "r_fizyka", 227 | "teacher": "Ba", 228 | "teacherId": "1", 229 | "room": "19", 230 | "roomId": "3" 231 | } 232 | ] 233 | ], 234 | [ 235 | [ 236 | { 237 | "groupName": "1/2", 238 | "subject": "sieci.komput", 239 | "teacher": "Dr", 240 | "teacherId": "14", 241 | "room": "35", 242 | "roomId": "13" 243 | } 244 | ], 245 | [ 246 | { 247 | "groupName": "1/2", 248 | "subject": "met.programo", 249 | "teacher": "PB", 250 | "teacherId": "41", 251 | "room": "34", 252 | "roomId": "12" 253 | }, 254 | { 255 | "groupName": "2/2", 256 | "subject": "sieci.komput", 257 | "teacher": "Dr", 258 | "teacherId": "14", 259 | "room": "35", 260 | "roomId": "13" 261 | } 262 | ], 263 | [ 264 | { 265 | "groupName": "1/2", 266 | "subject": "met.programo", 267 | "teacher": "PB", 268 | "teacherId": "41", 269 | "room": "34", 270 | "roomId": "12" 271 | }, 272 | { 273 | "groupName": "2/2", 274 | "subject": "sieci.komput", 275 | "teacher": "Dr", 276 | "teacherId": "14", 277 | "room": "35", 278 | "roomId": "13" 279 | } 280 | ], 281 | [ 282 | { 283 | "groupName": "1/2", 284 | "subject": "angielski g", 285 | "teacher": "BM", 286 | "teacherId": "4", 287 | "room": "W11", 288 | "roomId": "20" 289 | }, 290 | { 291 | "groupName": "2/2", 292 | "subject": "angielski g", 293 | "teacher": "Pi", 294 | "teacherId": "42", 295 | "room": "W3", 296 | "roomId": "19" 297 | } 298 | ], 299 | [ 300 | { 301 | "subject": "matematyka", 302 | "teacher": "PB", 303 | "teacherId": "41", 304 | "room": "34", 305 | "roomId": "12" 306 | } 307 | ], 308 | [ 309 | { 310 | "groupName": "1/2", 311 | "subject": "s.operacyjne", 312 | "teacher": "Oż", 313 | "teacherId": "39", 314 | "room": "32", 315 | "roomId": "10" 316 | }, 317 | { 318 | "groupName": "2/2", 319 | "subject": "tw.apl.inter", 320 | "teacher": "Ko", 321 | "teacherId": "27", 322 | "room": "33", 323 | "roomId": "11" 324 | } 325 | ], 326 | [ 327 | { 328 | "groupName": "1/2", 329 | "subject": "s.operacyjne", 330 | "teacher": "Oż", 331 | "teacherId": "39", 332 | "room": "32", 333 | "roomId": "10" 334 | }, 335 | { 336 | "groupName": "2/2", 337 | "subject": "tw.apl.inter", 338 | "teacher": "Ko", 339 | "teacherId": "27", 340 | "room": "33", 341 | "roomId": "11" 342 | } 343 | ], 344 | [ 345 | { 346 | "groupName": "1/2", 347 | "subject": "sieci.komput", 348 | "teacher": "Dr", 349 | "teacherId": "14", 350 | "room": "35", 351 | "roomId": "13" 352 | }, 353 | { 354 | "groupName": "2/2", 355 | "subject": "tw.baz.dan", 356 | "teacher": "Dę", 357 | "teacherId": "13", 358 | "room": "34", 359 | "roomId": "12" 360 | } 361 | ], 362 | [], 363 | [] 364 | ], 365 | [ 366 | [], 367 | [ 368 | { 369 | "subject": "religia", 370 | "teacher": "KG", 371 | "teacherId": "20", 372 | "room": "3", 373 | "roomId": "16" 374 | } 375 | ], 376 | [ 377 | { 378 | "subject": "j.polski", 379 | "teacher": "ZJ", 380 | "teacherId": "67", 381 | "room": "16", 382 | "roomId": "1" 383 | } 384 | ], 385 | [ 386 | { 387 | "subject": "j.polski", 388 | "teacher": "ZJ", 389 | "teacherId": "67", 390 | "room": "16", 391 | "roomId": "1" 392 | } 393 | ], 394 | [ 395 | { 396 | "groupName": "1/2", 397 | "subject": "sieci.komput", 398 | "teacher": "Dr", 399 | "teacherId": "14", 400 | "room": "35", 401 | "roomId": "13" 402 | }, 403 | { 404 | "groupName": "2/2", 405 | "subject": "s.operacyjne", 406 | "teacher": "Oż", 407 | "teacherId": "39", 408 | "room": "32", 409 | "roomId": "10" 410 | } 411 | ], 412 | [ 413 | { 414 | "groupName": "1/2", 415 | "subject": "sieci.komput", 416 | "teacher": "Dr", 417 | "teacherId": "14", 418 | "room": "35", 419 | "roomId": "13" 420 | }, 421 | { 422 | "groupName": "2/2", 423 | "subject": "s.operacyjne", 424 | "teacher": "Oż", 425 | "teacherId": "39", 426 | "room": "32", 427 | "roomId": "10" 428 | } 429 | ], 430 | [ 431 | { 432 | "groupName": "1/2", 433 | "subject": "wf", 434 | "teacher": "CK", 435 | "teacherId": "9", 436 | "room": "WG4", 437 | "roomId": "33" 438 | }, 439 | { 440 | "groupName": "2/2", 441 | "subject": "wf", 442 | "teacher": "Bu", 443 | "teacherId": "8", 444 | "room": "WG3", 445 | "roomId": "32" 446 | } 447 | ], 448 | [ 449 | { 450 | "groupName": "1/2", 451 | "subject": "wf", 452 | "teacher": "CK", 453 | "teacherId": "9", 454 | "room": "WG4", 455 | "roomId": "33" 456 | }, 457 | { 458 | "groupName": "2/2", 459 | "subject": "wf", 460 | "teacher": "Bu", 461 | "teacherId": "8", 462 | "room": "WG3", 463 | "roomId": "32" 464 | } 465 | ], 466 | [], 467 | [ 468 | { 469 | "groupName": "2/3", 470 | "subject": "r_geografia #2ge", 471 | "room": "16", 472 | "roomId": "1" 473 | }, 474 | { 475 | "groupName": "3/3", 476 | "subject": "r_informat. #2in", 477 | "room": "33", 478 | "roomId": "11" 479 | } 480 | ] 481 | ], 482 | [ 483 | [], 484 | [ 485 | { 486 | "groupName": "1/2", 487 | "subject": "tw.baz.dan", 488 | "teacher": "Dę", 489 | "teacherId": "13", 490 | "room": "34", 491 | "roomId": "12" 492 | }, 493 | { 494 | "groupName": "2/2", 495 | "subject": "s.operacyjne", 496 | "teacher": "Oż", 497 | "teacherId": "39", 498 | "room": "32", 499 | "roomId": "10" 500 | } 501 | ], 502 | [ 503 | { 504 | "groupName": "1/2", 505 | "subject": "tw.baz.dan", 506 | "teacher": "Dę", 507 | "teacherId": "13", 508 | "room": "34", 509 | "roomId": "12" 510 | }, 511 | { 512 | "groupName": "2/2", 513 | "subject": "met.programo", 514 | "teacher": "PB", 515 | "teacherId": "41", 516 | "room": "33", 517 | "roomId": "11" 518 | } 519 | ], 520 | [ 521 | { 522 | "subject": "r_matematyka", 523 | "teacher": "PB", 524 | "teacherId": "41", 525 | "room": "W15", 526 | "roomId": "22" 527 | } 528 | ], 529 | [ 530 | { 531 | "subject": "matematyka", 532 | "teacher": "PB", 533 | "teacherId": "41", 534 | "room": "34", 535 | "roomId": "12" 536 | } 537 | ], 538 | [ 539 | { 540 | "subject": "religia", 541 | "teacher": "KG", 542 | "teacherId": "20", 543 | "room": "16", 544 | "roomId": "1" 545 | } 546 | ], 547 | [ 548 | { 549 | "groupName": "1/2", 550 | "subject": "wf", 551 | "teacher": "CK", 552 | "teacherId": "9", 553 | "room": "WG4", 554 | "roomId": "33" 555 | }, 556 | { 557 | "groupName": "2/2", 558 | "subject": "wf", 559 | "teacher": "Bu", 560 | "teacherId": "8", 561 | "room": "WG3", 562 | "roomId": "32" 563 | } 564 | ], 565 | [ 566 | { 567 | "groupName": "1/2", 568 | "subject": "s.operacyjne", 569 | "teacher": "Oż", 570 | "teacherId": "39", 571 | "room": "32", 572 | "roomId": "10" 573 | }, 574 | { 575 | "groupName": "2/2", 576 | "subject": "r_fizyka #3fi", 577 | "room": "19", 578 | "roomId": "3" 579 | } 580 | ], 581 | [], 582 | [ 583 | { 584 | "subject": "Zajęcia dodatkowe" 585 | } 586 | ] 587 | ] 588 | ] 589 | -------------------------------------------------------------------------------- /test/expected/plain-class-days.json: -------------------------------------------------------------------------------- 1 | [ 2 | [[{ "subject": "ckz" }], [], [], [], [], [], [], [], [], [], []], 3 | [ 4 | [], 5 | [ 6 | { 7 | "subject": "zaj. wych.", 8 | "teacher": "LG", 9 | "teacherId": "29", 10 | "room": "27", 11 | "roomId": "18" 12 | } 13 | ], 14 | [ 15 | { 16 | "subject": "r_matematyka", 17 | "teacher": "LG", 18 | "teacherId": "29", 19 | "room": "27", 20 | "roomId": "18" 21 | } 22 | ], 23 | [ 24 | { 25 | "subject": "religia", 26 | "teacher": "RG", 27 | "teacherId": "67", 28 | "room": "33", 29 | "roomId": "21" 30 | } 31 | ], 32 | [ 33 | { 34 | "subject": "j.angielski", 35 | "teacher": "KT", 36 | "teacherId": "41", 37 | "room": "37", 38 | "roomId": "23", 39 | "groupName": "1/2" 40 | }, 41 | { 42 | "subject": "r_informat.", 43 | "teacher": "NA", 44 | "teacherId": "56", 45 | "room": "13", 46 | "roomId": "4", 47 | "groupName": "2/2" 48 | } 49 | ], 50 | [ 51 | { 52 | "subject": "j.angielski", 53 | "teacher": "KT", 54 | "teacherId": "41", 55 | "room": "47", 56 | "roomId": "25", 57 | "groupName": "1/2" 58 | }, 59 | { 60 | "subject": "r_informat.", 61 | "teacher": "NA", 62 | "teacherId": "56", 63 | "room": "13", 64 | "roomId": "4", 65 | "groupName": "2/2" 66 | } 67 | ], 68 | [ 69 | { 70 | "subject": "wf", 71 | "teacher": "PK", 72 | "teacherId": "63", 73 | "room": "SGM", 74 | "roomId": "31", 75 | "groupName": "1/2" 76 | }, 77 | { 78 | "subject": "j.niemiecki", 79 | "teacher": "KD", 80 | "teacherId": "47", 81 | "room": "13a", 82 | "roomId": "5", 83 | "groupName": "2/2" 84 | } 85 | ], 86 | [ 87 | { 88 | "subject": "wf", 89 | "teacher": "PK", 90 | "teacherId": "63", 91 | "room": "SI", 92 | "roomId": "32", 93 | "groupName": "1/2" 94 | }, 95 | { 96 | "subject": "j.angielski", 97 | "teacher": "KT", 98 | "teacherId": "41", 99 | "room": "A21", 100 | "roomId": "27", 101 | "groupName": "2/2" 102 | } 103 | ], 104 | [ 105 | { 106 | "subject": "UiS", 107 | "teacher": "SC", 108 | "teacherId": "73", 109 | "room": "23", 110 | "roomId": "13" 111 | } 112 | ], 113 | [ 114 | { 115 | "subject": "UiS", 116 | "teacher": "SC", 117 | "teacherId": "73", 118 | "room": "23", 119 | "roomId": "13" 120 | } 121 | ], 122 | [] 123 | ], 124 | [[{ "subject": "ckz" }], [], [], [], [], [], [], [], [], [], []], 125 | [ 126 | [ 127 | { 128 | "subject": "j.polski", 129 | "teacher": "KA", 130 | "teacherId": "33", 131 | "room": "22", 132 | "roomId": "12" 133 | } 134 | ], 135 | [ 136 | { 137 | "subject": "j.polski", 138 | "teacher": "KA", 139 | "teacherId": "33", 140 | "room": "22", 141 | "roomId": "12" 142 | } 143 | ], 144 | [ 145 | { 146 | "subject": "wos", 147 | "teacher": "WE", 148 | "teacherId": "80", 149 | "room": "28", 150 | "roomId": "19" 151 | } 152 | ], 153 | [ 154 | { 155 | "subject": "matematyka", 156 | "teacher": "LG", 157 | "teacherId": "29", 158 | "room": "18", 159 | "roomId": "10" 160 | } 161 | ], 162 | [ 163 | { 164 | "subject": "matematyka", 165 | "teacher": "LG", 166 | "teacherId": "29", 167 | "room": "18", 168 | "roomId": "10" 169 | } 170 | ], 171 | [ 172 | { 173 | "subject": "historia", 174 | "teacher": "KB", 175 | "teacherId": "46", 176 | "room": "37", 177 | "roomId": "23" 178 | } 179 | ], 180 | [ 181 | { 182 | "subject": "biologia", 183 | "teacher": "EP", 184 | "teacherId": "59", 185 | "room": "11", 186 | "roomId": "1" 187 | } 188 | ], 189 | [ 190 | { 191 | "subject": "fizyka", 192 | "teacher": "CZ", 193 | "teacherId": "19", 194 | "room": "12", 195 | "roomId": "3" 196 | } 197 | ], 198 | [ 199 | { 200 | "subject": "j.angielski", 201 | "teacher": "KT", 202 | "teacherId": "41", 203 | "room": "17", 204 | "roomId": "9", 205 | "groupName": "1/2" 206 | }, 207 | { 208 | "subject": "wf", 209 | "teacher": "PK", 210 | "teacherId": "63", 211 | "room": "SGM", 212 | "roomId": "31", 213 | "groupName": "2/2" 214 | } 215 | ], 216 | [], 217 | [] 218 | ], 219 | [ 220 | [], 221 | [], 222 | [ 223 | { 224 | "subject": "j.polski", 225 | "teacher": "KA", 226 | "teacherId": "33", 227 | "room": "22", 228 | "roomId": "12" 229 | } 230 | ], 231 | [ 232 | { 233 | "subject": "wf", 234 | "teacher": "PK", 235 | "teacherId": "63", 236 | "room": "SGM", 237 | "roomId": "31", 238 | "groupName": "1/2" 239 | }, 240 | { 241 | "subject": "j.angielski", 242 | "teacher": "KT", 243 | "teacherId": "41", 244 | "room": "A21", 245 | "roomId": "27", 246 | "groupName": "2/2" 247 | } 248 | ], 249 | [ 250 | { 251 | "subject": "j.niemiecki", 252 | "teacher": "SB", 253 | "teacherId": "34", 254 | "room": "37", 255 | "roomId": "23", 256 | "groupName": "1/2" 257 | }, 258 | { 259 | "subject": "j.angielski", 260 | "teacher": "KT", 261 | "teacherId": "41", 262 | "room": "A21", 263 | "roomId": "27", 264 | "groupName": "2/2" 265 | } 266 | ], 267 | [ 268 | { 269 | "subject": "r_informat.", 270 | "teacher": "NA", 271 | "teacherId": "56", 272 | "room": "13", 273 | "roomId": "4", 274 | "groupName": "1/2" 275 | }, 276 | { 277 | "subject": "wf", 278 | "teacher": "PK", 279 | "teacherId": "63", 280 | "room": "SGM", 281 | "roomId": "31", 282 | "groupName": "2/2" 283 | } 284 | ], 285 | [ 286 | { 287 | "subject": "r_informat.", 288 | "teacher": "NA", 289 | "teacherId": "56", 290 | "room": "13", 291 | "roomId": "4", 292 | "groupName": "1/2" 293 | }, 294 | { 295 | "subject": "wf", 296 | "teacher": "PK", 297 | "teacherId": "63", 298 | "room": "SI", 299 | "roomId": "32", 300 | "groupName": "2/2" 301 | } 302 | ], 303 | [ 304 | { 305 | "subject": "chemia", 306 | "teacher": "MW", 307 | "teacherId": "81", 308 | "room": "25", 309 | "roomId": "15" 310 | } 311 | ], 312 | [ 313 | { 314 | "subject": "matematyka", 315 | "teacher": "LG", 316 | "teacherId": "29", 317 | "room": "27", 318 | "roomId": "18" 319 | } 320 | ], 321 | [ 322 | { 323 | "subject": "religia", 324 | "teacher": "RG", 325 | "teacherId": "67", 326 | "room": "33", 327 | "roomId": "21" 328 | } 329 | ], 330 | [ 331 | { 332 | "subject": "geografia", 333 | "teacher": "GV", 334 | "teacherId": "35", 335 | "room": "32", 336 | "roomId": "20" 337 | } 338 | ] 339 | ] 340 | ] 341 | -------------------------------------------------------------------------------- /test/expected/room-days.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | [ 4 | { 5 | "teacher": "Kr", 6 | "teacherId": "29", 7 | "className": "4Tm", 8 | "classId": "28", 9 | "subject": "u_hist.i sp." 10 | } 11 | ], 12 | [ 13 | { 14 | "teacher": "Kr", 15 | "teacherId": "29", 16 | "className": "4Tp", 17 | "classId": "29", 18 | "subject": "u_hist.i sp." 19 | } 20 | ], 21 | [ 22 | { 23 | "teacher": "Ho", 24 | "teacherId": "25", 25 | "className": "4Ti", 26 | "classId": "27", 27 | "subject": "u_hist.i sp." 28 | } 29 | ], 30 | [ 31 | { 32 | "teacher": "Kr", 33 | "teacherId": "29", 34 | "className": "2Tc", 35 | "classId": "8", 36 | "subject": "historia" 37 | } 38 | ], 39 | [ 40 | { 41 | "teacher": "ZJ", 42 | "teacherId": "67", 43 | "className": "3Ti", 44 | "classId": "19", 45 | "subject": "j.polski" 46 | } 47 | ], 48 | [ 49 | { 50 | "teacher": "ZJ", 51 | "teacherId": "67", 52 | "className": "2Ti", 53 | "classId": "10", 54 | "subject": "j.polski" 55 | } 56 | ], 57 | [ 58 | { 59 | "teacher": "ZJ", 60 | "teacherId": "67", 61 | "className": "1Ti", 62 | "classId": "2", 63 | "subject": "j.polski" 64 | } 65 | ], 66 | [ 67 | { 68 | "teacher": "RM", 69 | "teacherId": "50", 70 | "className": "1Ti", 71 | "classId": "2", 72 | "subject": "biologia" 73 | } 74 | ], 75 | [ 76 | { 77 | "teacher": "RM", 78 | "teacherId": "50", 79 | "className": "1Zp", 80 | "classId": "7", 81 | "subject": "biologia" 82 | } 83 | ], 84 | [], 85 | [] 86 | ], 87 | [ 88 | [ 89 | { 90 | "teacher": "Kr", 91 | "teacherId": "29", 92 | "className": "4Tp", 93 | "classId": "29", 94 | "groupName": "2/3", 95 | "subject": "r_geografia" 96 | } 97 | ], 98 | [ 99 | { 100 | "teacher": "Kr", 101 | "teacherId": "29", 102 | "className": "4Tp", 103 | "classId": "29", 104 | "groupName": "2/3", 105 | "subject": "r_geografia" 106 | } 107 | ], 108 | [ 109 | { 110 | "teacher": "JP", 111 | "teacherId": "43", 112 | "className": "1Tp", 113 | "classId": "4", 114 | "subject": "chemia" 115 | } 116 | ], 117 | [ 118 | { 119 | "teacher": "Ho", 120 | "teacherId": "25", 121 | "className": "3Tc", 122 | "classId": "17", 123 | "subject": "u_hist.i sp." 124 | } 125 | ], 126 | [ 127 | { 128 | "teacher": "Ho", 129 | "teacherId": "25", 130 | "className": "3Ti", 131 | "classId": "19", 132 | "subject": "u_hist.i sp." 133 | } 134 | ], 135 | [ 136 | { 137 | "teacher": "Ho", 138 | "teacherId": "25", 139 | "className": "2Tn", 140 | "classId": "12", 141 | "subject": "historia" 142 | } 143 | ], 144 | [ 145 | { 146 | "teacher": "BR", 147 | "teacherId": "7", 148 | "className": "1Zp", 149 | "classId": "7", 150 | "subject": "religia" 151 | } 152 | ], 153 | [], 154 | [], 155 | [], 156 | [] 157 | ], 158 | [ 159 | [ 160 | { 161 | "teacher": "Kr", 162 | "teacherId": "29", 163 | "className": "4Tp", 164 | "classId": "29", 165 | "groupName": "2/3", 166 | "subject": "r_geografia" 167 | } 168 | ], 169 | [ 170 | { 171 | "teacher": "Kr", 172 | "teacherId": "29", 173 | "className": "4Tp", 174 | "classId": "29", 175 | "groupName": "2/3", 176 | "subject": "r_geografia" 177 | } 178 | ], 179 | [ 180 | { 181 | "teacher": "JW", 182 | "teacherId": "65", 183 | "className": "1Tc", 184 | "classId": "1", 185 | "subject": "r_matematyka" 186 | } 187 | ], 188 | [ 189 | { 190 | "teacher": "Ho", 191 | "teacherId": "25", 192 | "className": "1Tc", 193 | "classId": "1", 194 | "subject": "wos" 195 | } 196 | ], 197 | [ 198 | { 199 | "teacher": "Ho", 200 | "teacherId": "25", 201 | "className": "4Ti", 202 | "classId": "27", 203 | "subject": "u_hist.i sp." 204 | } 205 | ], 206 | [ 207 | { 208 | "teacher": "Ho", 209 | "teacherId": "25", 210 | "className": "4Ti", 211 | "classId": "27", 212 | "subject": "u_hist.i sp." 213 | } 214 | ], 215 | [ 216 | { 217 | "teacher": "AP", 218 | "teacherId": "48", 219 | "className": "2Ti", 220 | "classId": "10", 221 | "subject": "godz.wych" 222 | } 223 | ], 224 | [ 225 | { 226 | "teacher": "Ho", 227 | "teacherId": "25", 228 | "className": "2Tp", 229 | "classId": "13", 230 | "subject": "historia" 231 | } 232 | ], 233 | [ 234 | { 235 | "teacher": "Ho", 236 | "teacherId": "25", 237 | "className": "3Za", 238 | "classId": "22", 239 | "subject": "wos" 240 | } 241 | ], 242 | [], 243 | [ 244 | { 245 | "teacher": "Ho", 246 | "teacherId": "25", 247 | "className": "3Ze", 248 | "classId": "24", 249 | "subject": "wos" 250 | } 251 | ] 252 | ], 253 | [ 254 | [ 255 | { 256 | "teacher": "Dę", 257 | "teacherId": "13", 258 | "className": "3Tk", 259 | "classId": "20", 260 | "groupName": "3/3", 261 | "subject": "r_informat." 262 | }, 263 | { 264 | "teacher": "Dę", 265 | "teacherId": "13", 266 | "className": "3Tp", 267 | "classId": "21", 268 | "groupName": "3/3", 269 | "subject": "r_informat." 270 | }, 271 | { 272 | "teacher": "Dę", 273 | "teacherId": "13", 274 | "className": "3Te", 275 | "classId": "18", 276 | "groupName": "3/3", 277 | "subject": "r_informat." 278 | } 279 | ], 280 | [ 281 | { 282 | "teacher": "Ho", 283 | "teacherId": "25", 284 | "className": "1Tt", 285 | "classId": "5", 286 | "subject": "wos" 287 | } 288 | ], 289 | [ 290 | { 291 | "teacher": "Ho", 292 | "teacherId": "25", 293 | "className": "4Ti", 294 | "classId": "27", 295 | "subject": "u_hist.i sp." 296 | } 297 | ], 298 | [ 299 | { 300 | "teacher": "Ho", 301 | "teacherId": "25", 302 | "className": "2Ti", 303 | "classId": "10", 304 | "subject": "historia" 305 | } 306 | ], 307 | [ 308 | { 309 | "teacher": "Ho", 310 | "teacherId": "25", 311 | "className": "3Tk", 312 | "classId": "20", 313 | "subject": "u_hist.i sp." 314 | } 315 | ], 316 | [ 317 | { 318 | "teacher": "PB", 319 | "teacherId": "41", 320 | "className": "3Te", 321 | "classId": "18", 322 | "subject": "matematyka" 323 | } 324 | ], 325 | [ 326 | { 327 | "teacher": "Kr", 328 | "teacherId": "29", 329 | "className": "1Tm", 330 | "classId": "3", 331 | "subject": "wos" 332 | } 333 | ], 334 | [ 335 | { 336 | "teacher": "Kr", 337 | "teacherId": "29", 338 | "className": "2Tm", 339 | "classId": "11", 340 | "subject": "historia" 341 | } 342 | ], 343 | [ 344 | { 345 | "teacher": "Kr", 346 | "teacherId": "29", 347 | "className": "1Zm", 348 | "classId": "6", 349 | "subject": "historia" 350 | } 351 | ], 352 | [], 353 | [] 354 | ], 355 | [ 356 | [ 357 | { 358 | "teacher": "Ho", 359 | "teacherId": "25", 360 | "className": "3Tp", 361 | "classId": "21", 362 | "subject": "u_hist.i sp." 363 | } 364 | ], 365 | [ 366 | { 367 | "teacher": "ZJ", 368 | "teacherId": "67", 369 | "className": "1Ti", 370 | "classId": "2", 371 | "subject": "j.polski" 372 | } 373 | ], 374 | [ 375 | { 376 | "teacher": "ZJ", 377 | "teacherId": "67", 378 | "className": "1Ti", 379 | "classId": "2", 380 | "subject": "j.polski" 381 | } 382 | ], 383 | [ 384 | { 385 | "teacher": "Ho", 386 | "teacherId": "25", 387 | "className": "1Tc", 388 | "classId": "1", 389 | "subject": "historia" 390 | } 391 | ], 392 | [ 393 | { 394 | "teacher": "Ho", 395 | "teacherId": "25", 396 | "className": "1Tc", 397 | "classId": "1", 398 | "subject": "godz.wych" 399 | } 400 | ], 401 | [ 402 | { 403 | "teacher": "Ho", 404 | "teacherId": "25", 405 | "className": "1Tt", 406 | "classId": "5", 407 | "subject": "historia" 408 | } 409 | ], 410 | [ 411 | { 412 | "teacher": "Kr", 413 | "teacherId": "29", 414 | "className": "1Ti", 415 | "classId": "2", 416 | "subject": "historia" 417 | } 418 | ], 419 | [ 420 | { 421 | "teacher": "Ho", 422 | "teacherId": "25", 423 | "className": "1Zp", 424 | "classId": "7", 425 | "subject": "historia" 426 | } 427 | ], 428 | [ 429 | { 430 | "teacher": "Ho", 431 | "teacherId": "25", 432 | "className": "3Zb", 433 | "classId": "23", 434 | "subject": "wos" 435 | } 436 | ], 437 | [], 438 | [] 439 | ] 440 | ] 441 | -------------------------------------------------------------------------------- /test/fixtures/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Publiczna szkoła Wulkanowego nr 1. Plan lekcji 6 | 7 | 8 | 9 | 10 | 11 | <body> 12 | <p>Ta strona używa ramek, których Twoja przeglądarka nie obsługuje! 13 | Możesz skorzystać ze <a href="lista.html">strony nawigacyjnej</a>.</p> 14 | </body> 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/fixtures/lista-expandable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lista oddziałów, nauczycieli i sal 5 | 6 | 7 | 8 | 9 | 14 | 17 | 18 | 19 | 20 | 26 | 27 | 28 | 33 | 36 | 37 | 38 | 39 | 45 | 46 | 47 | 52 | 55 | 56 | 57 | 58 | 64 | 65 |
10 | 11 | 12 | 13 | 15 | Oddziały 16 |
21 |
22 |

1Tc

23 |

1Ti

24 |
25 |
29 | 30 | 31 | 32 | 34 | Nauczyciele 35 |
40 | 44 |
48 | 49 | 50 | 51 | 53 | Sale 54 |
59 | 63 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/fixtures/lista-select.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lista oddziałów, nauczycieli i sal 5 | 6 | 7 |
8 | 13 | 18 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /test/fixtures/lista-unordered.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Lista oddziałów, nauczycieli i sal 5 | 6 | 7 | 10 |

Oddziały

11 | 15 |

Nauczyciele

16 | 20 |

Sale

21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/fixtures/oddzial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | Plan lekcji oddziału - 3Ti 10 | 11 | 16 | 17 | 18 | 25 | 26 | 30 | 31 |
27 | 28 | 3Ti 29 |
32 | 33 |
34 | 35 | 36 | 434 | 435 | 436 | 439 | 440 | 441 | 444 | 472 | 478 | 479 | 480 | 481 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | 58 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 78 | 79 | 90 | 95 | 106 | 107 | 108 | 109 | 110 | 121 | 132 | 143 | 148 | 159 | 160 | 161 | 162 | 163 | 174 | 185 | 196 | 201 | 206 | 207 | 208 | 209 | 210 | 215 | 220 | 225 | 236 | 241 | 242 | 243 | 244 | 245 | 256 | 261 | 272 | 283 | 288 | 289 | 290 | 291 | 292 | 303 | 308 | 319 | 330 | 341 | 342 | 343 | 344 | 345 | 356 | 364 | 375 | 386 | 394 | 395 | 396 | 397 | 398 | 399 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 422 | 423 | 430 | 431 | 432 |
NrGodzPoniedziałekWtorekŚrodaCzwartekPiątek
28:00- 8:45 51 | sieci.komput-2/2 53 | Dr 54 | 35 56 |   59 | sieci.komput-1/2 61 | Dr 62 | 35 64 |   
38:50- 9:35 72 | sieci.komput-2/2 74 | Dr 75 | 35 77 |   80 | met.programo-1/2 82 | PB 83 | 34
sieci.komput-2/2 86 | Dr 87 | 35 89 |
91 | religia 92 | KG 93 | 3 94 | 96 | tw.baz.dan-1/2 98 | 99 | 34
s.operacyjne-2/2 102 | 103 | 32 105 |
49:40-10:25 111 | tw.apl.inter-1/2 113 | Ko 114 | 33
sieci.komput-2/2 117 | Dr 118 | 35 120 |
122 | angielski g-1/2 124 | BM 125 | W11
angielski g-2/2 128 | Pi 129 | W3 131 |
133 | met.programo-1/2 135 | PB 136 | 34
sieci.komput-2/2 139 | Dr 140 | 35 142 |
144 | j.polski 145 | ZJ 146 | 16 147 | 149 | tw.baz.dan-1/2 151 | 152 | 34
met.programo-2/2 155 | PB 156 | 33 158 |
510:40-11:25 164 | tw.apl.inter-1/2 166 | Ko 167 | 33
sieci.komput-2/2 170 | Dr 171 | 35 173 |
175 | angielski g-1/2 177 | BM 178 | W11
angielski g-2/2 181 | Pi 182 | W3 184 |
186 | angielski g-1/2 188 | BM 189 | W11
angielski g-2/2 192 | Pi 193 | W3 195 |
197 | j.polski 198 | ZJ 199 | 16 200 | 202 | r_matematyka 203 | PB 204 | W15 205 |
611:30-12:15 211 | j.polski 212 | ZJ 213 | 21 214 | 216 | u_hist.i sp. 217 | Ho 218 | 21 219 | 221 | matematyka 222 | PB 223 | 34 224 | 226 | sieci.komput-1/2 228 | Dr 229 | 35
s.operacyjne-2/2 232 | 233 | 32 235 |
237 | matematyka 238 | PB 239 | 34 240 |
712:20-13:05 246 | r_fizyka-1/2 248 | Ba 249 | 19
met.programo-2/2 252 | PB 253 | 32 255 |
257 | matematyka 258 | PB 259 | 23 260 | 262 | s.operacyjne-1/2 264 | 265 | 32
tw.apl.inter-2/2 268 | Ko 269 | 33 271 |
273 | sieci.komput-1/2 275 | Dr 276 | 35
s.operacyjne-2/2 279 | 280 | 32 282 |
284 | religia 285 | KG 286 | 16 287 |
813:10-13:55 293 | r_fizyka-1/2 295 | Ba 296 | 19
s.operacyjne-2/2 299 | 300 | 32 302 |
304 | godz.wych 305 | PB 306 | 32 307 | 309 | s.operacyjne-1/2 311 | 312 | 32
tw.apl.inter-2/2 315 | Ko 316 | 33 318 |
320 | wf-1/2 322 | CK 323 | WG4
wf-2/2 326 | Bu 327 | WG3 329 |
331 | wf-1/2 333 | CK 334 | WG4
wf-2/2 337 | Bu 338 | WG3 340 |
914:00-14:45 346 | s.operacyjne-1/2 348 | 349 | 32
tw.baz.dan-2/2 352 | 353 | 34 355 |
357 | sieci.komput-1/2 359 | Dr 360 | 35
r_fizyka-2/2 362 | #3fi 19 363 |
365 | sieci.komput-1/2 367 | Dr 368 | 35
tw.baz.dan-2/2 371 | 372 | 34 374 |
376 | wf-1/2 378 | CK 379 | WG4
wf-2/2 382 | Bu 383 | WG3 385 |
387 | s.operacyjne-1/2 389 | 390 | 32
r_fizyka-2/2 392 | #3fi 19 393 |
1014:50-15:35  400 | sieci.komput-1/2 402 | Dr 403 | 35
r_fizyka-2/2 405 | #3fi 19 406 |
   
1115:40-16:25  416 | r_fizyka-1/2 418 | Ba 419 | 19 421 |   424 | r_geografia-2/3 425 | #2ge 16
r_informat.-3/3 427 | #2in 428 | 33 429 |
Zajęcia dodatkowe
433 |
437 | Obowiązuje od: 19 lutego 2018r. 438 |
442 | Drukuj plan 443 | 445 | 446 | 447 | 458 | 468 | 469 |
448 | wygenerowano 17.02.2018
449 | za pomocą programu 450 | Plan lekcji Optivum
455 | firmy 456 | VULCAN 457 |
459 | logo programu Plan lekcji Optivum 467 |
470 | 471 |
473 | 477 |
482 |
483 | 484 | 485 | -------------------------------------------------------------------------------- /test/fixtures/plain-oddzial.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | Plan lekcji oddziału - 4as 4TMt 10 | 11 | 16 | 29 | 30 | 31 | 38 | 39 | 40 | 44 | 45 | 46 |
41 | 42 | 4as 4TMt 43 |
47 |
48 | 49 | 50 | 51 | 327 | 328 | 329 | 330 | 331 | 332 | 335 | 366 | 367 | 368 | 375 | 376 | 377 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 85 | 86 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 102 | 103 | 108 | 113 | 114 | 115 | 116 | 117 | 118 | 123 | 124 | 129 | 140 | 141 | 142 | 143 | 144 | 145 | 156 | 157 | 162 | 173 | 174 | 175 | 176 | 177 | 178 | 189 | 190 | 195 | 206 | 207 | 208 | 209 | 210 | 211 | 222 | 223 | 228 | 239 | 240 | 241 | 242 | 243 | 244 | 255 | 256 | 261 | 266 | 267 | 268 | 269 | 270 | 271 | 276 | 277 | 288 | 293 | 294 | 295 | 296 | 297 | 298 | 303 | 304 | 305 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 323 | 324 | 325 |
NrGodzPoniedziałekWtorekŚrodaCzwartekPiątek
07:10- 7:55ckz ckz 70 | j.polski 71 | KA 72 | 22 73 |  
18:00- 8:45  81 | zaj. wych. 82 | LG 83 | 27 84 |   87 | j.polski 88 | KA 89 | 22 90 |  
28:50- 9:35  98 | r_matematyka 99 | LG 100 | 27 101 |   104 | wos 105 | WE 106 | 28 107 | 109 | j.polski 110 | KA 111 | 22 112 |
39:40-10:25  119 | religia 120 | RG 121 | 33 122 |   125 | matematyka 126 | LG 127 | 18 128 | 130 | wf-1/2 132 | PK 133 | SGM
j.angielski-2/2 136 | KT 137 | A21 139 |
410:40-11:25  146 | j.angielski-1/2 148 | KT 149 | 37
r_informat.-2/2 152 | NA 153 | 13 155 |
  158 | matematyka 159 | LG 160 | 18 161 | 163 | j.niemiecki-1/2 165 | SB 166 | 37
j.angielski-2/2 169 | KT 170 | A21 172 |
511:30-12:15  179 | j.angielski-1/2 181 | KT 182 | 47
r_informat.-2/2 185 | NA 186 | 13 188 |
  191 | historia 192 | KB 193 | 37 194 | 196 | r_informat.-1/2 198 | NA 199 | 13
wf-2/2 202 | PK 203 | SGM 205 |
612:20-13:05  212 | wf-1/2 214 | PK 215 | SGM
j.niemiecki-2/2 218 | KD 219 | 13a 221 |
  224 | biologia 225 | EP 226 | 11 227 | 229 | r_informat.-1/2 231 | NA 232 | 13
wf-2/2 235 | PK 236 | SI 238 |
713:10-13:55  245 | wf-1/2 247 | PK 248 | SI
j.angielski-2/2 251 | KT 252 | A21 254 |
  257 | fizyka 258 | CZ 259 | 12 260 | 262 | chemia 263 | MW 264 | 25 265 |
814:00-14:45  272 | UiS 273 | SC 274 | 23 275 |   278 | j.angielski-1/2 280 | KT 281 | 17
wf-2/2 284 | PK 285 | SGM 287 |
289 | matematyka 290 | LG 291 | 27 292 |
914:50-15:35  299 | UiS 300 | SC 301 | 23 302 |    306 | religia 307 | RG 308 | 33 309 |
1015:40-16:25     319 | geografia 320 | GV 321 | 32 322 |
326 |
Obowiązuje od: 13 lutego 2023 r.
333 | Drukuj plan 334 | 336 | 337 | 338 | 339 | 352 | 362 | 363 | 364 |
340 | wygenerowano 09.02.2023
341 | za pomocą programu 342 | Plan lekcji Optivum
347 | firmy 348 | VULCAN 351 |
353 | logo programu Plan lekcji Optivum 361 |
365 |
369 | 373 |

Plan lekcji

374 |
378 |
379 | 380 | 381 | -------------------------------------------------------------------------------- /test/fixtures/sala.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | Plan lekcji sali - 21 prac. historii 10 | 11 | 16 | 17 | 18 | 25 | 26 | 30 | 31 |
27 | 28 | 21 prac. historii 29 |
32 | 33 |
34 | 35 | 36 | 328 | 329 | 330 | 333 | 334 | 335 | 338 | 366 | 372 | 373 | 374 | 375 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 55 | 60 | 65 | 74 | 79 | 80 | 81 | 82 | 83 | 88 | 93 | 98 | 103 | 108 | 109 | 110 | 111 | 112 | 117 | 122 | 127 | 132 | 137 | 138 | 139 | 140 | 141 | 146 | 151 | 156 | 161 | 166 | 167 | 168 | 169 | 170 | 175 | 180 | 185 | 190 | 195 | 196 | 197 | 198 | 199 | 204 | 209 | 214 | 219 | 224 | 225 | 226 | 227 | 228 | 233 | 238 | 243 | 248 | 253 | 254 | 255 | 256 | 257 | 262 | 263 | 268 | 273 | 278 | 279 | 280 | 281 | 282 | 287 | 288 | 293 | 298 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 323 | 324 | 325 | 326 |
NrGodzPoniedziałekWtorekŚrodaCzwartekPiątek
18:00- 8:45 51 | Kr 52 | 4Tm 53 | u_hist.i sp.
54 |
56 | Kr 57 | 4Tp-2/3 58 | r_geografia
59 |
61 | Kr 62 | 4Tp-2/3 63 | r_geografia
64 |
66 | 67 | 3Tk-3/3,3Tp-3/3,3Te-3/3 72 | r_informat.
73 |
75 | Ho 76 | 3Tp 77 | u_hist.i sp.
78 |
28:50- 9:35 84 | Kr 85 | 4Tp 86 | u_hist.i sp.
87 |
89 | Kr 90 | 4Tp-2/3 91 | r_geografia
92 |
94 | Kr 95 | 4Tp-2/3 96 | r_geografia
97 |
99 | Ho 100 | 1Tt wos
102 |
104 | ZJ 105 | 1Ti 106 | j.polski
107 |
39:40-10:25 113 | Ho 114 | 4Ti 115 | u_hist.i sp.
116 |
118 | JP 119 | 1Tp 120 | chemia
121 |
123 | JW 124 | 1Tc 125 | r_matematyka
126 |
128 | Ho 129 | 4Ti 130 | u_hist.i sp.
131 |
133 | ZJ 134 | 1Ti 135 | j.polski
136 |
410:40-11:25 142 | Kr 143 | 2Tc 144 | historia
145 |
147 | Ho 148 | 3Tc 149 | u_hist.i sp.
150 |
152 | Ho 153 | 1Tc wos
155 |
157 | Ho 158 | 2Ti 159 | historia
160 |
162 | Ho 163 | 1Tc 164 | historia
165 |
511:30-12:15 171 | ZJ 172 | 3Ti 173 | j.polski
174 |
176 | Ho 177 | 3Ti 178 | u_hist.i sp.
179 |
181 | Ho 182 | 4Ti 183 | u_hist.i sp.
184 |
186 | Ho 187 | 3Tk 188 | u_hist.i sp.
189 |
191 | Ho 192 | 1Tc 193 | godz.wych
194 |
612:20-13:05 200 | ZJ 201 | 2Ti 202 | j.polski
203 |
205 | Ho 206 | 2Tn 207 | historia
208 |
210 | Ho 211 | 4Ti 212 | u_hist.i sp.
213 |
215 | PB 216 | 3Te 217 | matematyka
218 |
220 | Ho 221 | 1Tt 222 | historia
223 |
713:10-13:55 229 | ZJ 230 | 1Ti 231 | j.polski
232 |
234 | BR 235 | 1Zp 236 | religia
237 |
239 | AP 240 | 2Ti 241 | godz.wych
242 |
244 | Kr 245 | 1Tm wos
247 |
249 | Kr 250 | 1Ti 251 | historia
252 |
814:00-14:45 258 | RM 259 | 1Ti 260 | biologia
261 |
  264 | Ho 265 | 2Tp 266 | historia
267 |
269 | Kr 270 | 2Tm 271 | historia
272 |
274 | Ho 275 | 1Zp 276 | historia
277 |
914:50-15:35 283 | RM 284 | 1Zp 285 | biologia
286 |
  289 | Ho 290 | 3Za wos
292 |
294 | Kr 295 | 1Zm 296 | historia
297 |
299 | Ho 300 | 3Zb wos
302 |
1015:40-16:25     
1116:35-17:20   319 | Ho 320 | 3Ze wos
322 |
  
327 |
331 | Obowiązuje od: 19 grudnia 2022 r. (wersja 5.0.0) 332 |
336 | Drukuj plan 337 | 339 | 340 | 341 | 352 | 362 | 363 |
342 | wygenerowano 2018-2-17
343 | za pomocą programu 344 | Plan lekcji Optivum
349 | firmy 350 | VULCAN 351 |
353 | logo programu Plan lekcji Optivum 361 |
364 | 365 |
367 | 371 |
376 |
377 | 378 | 379 | -------------------------------------------------------------------------------- /test/test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import * as fs from 'fs'; 3 | import * as path from 'path'; 4 | import { 5 | Timetable, TimetableList, Table, 6 | } from '../lib/index'; 7 | 8 | describe('Timetable test', (): void => { 9 | const indexFilename = path.join(__dirname, 'fixtures', 'index.html'); 10 | const indexHTML = fs.readFileSync(indexFilename, { 11 | encoding: 'utf8', 12 | }); 13 | it('Cheerio init', (): void => { 14 | expect((): Timetable => new Timetable(indexHTML)).not.to.throw(); 15 | }); 16 | 17 | const timetable = new Timetable(indexHTML); 18 | 19 | it('Title check', (): void => { 20 | expect(timetable.getTitle()).to.equal('Publiczna szkoła Wulkanowego nr 1. Plan lekcji'); 21 | }); 22 | 23 | it('Path text', (): void => { 24 | expect(timetable.getListPath()).to.equal('lista.html'); 25 | }); 26 | }); 27 | 28 | describe('Timetable list test', (): void => { 29 | describe('Expandable list', (): void => { 30 | const expandableListFilename = path.join(__dirname, 'fixtures', 'lista-expandable.html'); 31 | const expandableListHTML = fs.readFileSync(expandableListFilename, { 32 | encoding: 'utf8', 33 | }); 34 | 35 | const list: TimetableList = new TimetableList(expandableListHTML); 36 | 37 | it('Cheerio init', (): void => { 38 | expect((): TimetableList => new TimetableList(expandableListHTML)).not.to.throw(); 39 | }); 40 | 41 | it('List type check', (): void => { 42 | expect(list.getListType()).to.equal('expandable'); 43 | }); 44 | 45 | it('Return value check', (): void => { 46 | const nodesList = list.getList(); 47 | expect(nodesList.classes).not.to.equal(undefined); 48 | expect(nodesList.teachers).not.to.equal(undefined); 49 | expect(nodesList.rooms).not.to.equal(undefined); 50 | 51 | expect(nodesList.classes[0].name).to.equal('1Tc'); 52 | expect(nodesList.classes[0].value).to.equal('1'); 53 | expect(nodesList.classes[1].name).to.equal('1Ti'); 54 | expect(nodesList.classes[1].value).to.equal('2'); 55 | 56 | expect(nodesList.teachers![0].name).to.equal('I.Ochocki (Io)'); 57 | expect(nodesList.teachers![0].value).to.equal('1'); 58 | expect(nodesList.teachers![1].name).to.equal('M.Oleszkiewicz (Mo)'); 59 | expect(nodesList.teachers![1].value).to.equal('3'); 60 | 61 | expect(nodesList.rooms![0].name).to.equal('16 prac. geograficzna'); 62 | expect(nodesList.rooms![0].value).to.equal('1'); 63 | expect(nodesList.rooms![1].name).to.equal('17 prac. fizyczna'); 64 | expect(nodesList.rooms![1].value).to.equal('2'); 65 | }); 66 | 67 | it('Logo check', (): void => { 68 | expect(list.getLogoSrc()).to.equal(null); 69 | }); 70 | }); 71 | 72 | describe('Select list', (): void => { 73 | const selectListFilename = path.join(__dirname, 'fixtures', 'lista-select.html'); 74 | const selectListHTML = fs.readFileSync(selectListFilename, { 75 | encoding: 'utf8', 76 | }); 77 | 78 | const list: TimetableList = new TimetableList(selectListHTML); 79 | 80 | it('Cheerio init', (): void => { 81 | expect((): TimetableList => new TimetableList(selectListHTML)).not.to.throw(); 82 | }); 83 | 84 | it('List type check', (): void => { 85 | expect(list.getListType()).to.equal('select'); 86 | }); 87 | 88 | it('Return value check', (): void => { 89 | const nodesList = list.getList(); 90 | expect(nodesList.classes).not.to.equal(undefined); 91 | expect(nodesList.teachers).not.to.equal(undefined); 92 | expect(nodesList.rooms).not.to.equal(undefined); 93 | 94 | expect(nodesList.classes[0].name).to.equal('1Tc'); 95 | expect(nodesList.classes[0].value).to.equal('1'); 96 | expect(nodesList.classes[1].name).to.equal('1Ti'); 97 | expect(nodesList.classes[1].value).to.equal('2'); 98 | 99 | expect(nodesList.teachers![0].name).to.equal('I.Ochocki (Io)'); 100 | expect(nodesList.teachers![0].value).to.equal('1'); 101 | expect(nodesList.teachers![1].name).to.equal('M.Oleszkiewicz (Mo)'); 102 | expect(nodesList.teachers![1].value).to.equal('3'); 103 | 104 | expect(nodesList.rooms![0].name).to.equal('16 prac. geograficzna'); 105 | expect(nodesList.rooms![0].value).to.equal('1'); 106 | expect(nodesList.rooms![1].name).to.equal('17 prac. fizyczna'); 107 | expect(nodesList.rooms![1].value).to.equal('2'); 108 | }); 109 | 110 | it('Logo check', (): void => { 111 | expect(list.getLogoSrc()).to.equal(null); 112 | }); 113 | }); 114 | 115 | describe('Unordered list', (): void => { 116 | const unorderedListFilename = path.join(__dirname, 'fixtures', 'lista-unordered.html'); 117 | const unorderedListHTML = fs.readFileSync(unorderedListFilename, { 118 | encoding: 'utf8', 119 | }); 120 | 121 | const list: TimetableList = new TimetableList(unorderedListHTML); 122 | 123 | it('Cheerio init', (): void => { 124 | expect((): TimetableList => new TimetableList(unorderedListHTML)).not.to.throw(); 125 | }); 126 | 127 | it('List type check', (): void => { 128 | expect(list.getListType()).to.equal('unordered'); 129 | }); 130 | 131 | it('Return value check', (): void => { 132 | const nodesList = list.getList(); 133 | expect(nodesList.classes).not.to.equal(undefined); 134 | expect(nodesList.teachers).not.to.equal(undefined); 135 | expect(nodesList.rooms).not.to.equal(undefined); 136 | 137 | expect(nodesList.classes[0].name).to.equal('1Tc'); 138 | expect(nodesList.classes[0].value).to.equal('1'); 139 | expect(nodesList.classes[1].name).to.equal('1Ti'); 140 | expect(nodesList.classes[1].value).to.equal('2'); 141 | 142 | expect(nodesList.teachers![0].name).to.equal('I.Ochocki (Io)'); 143 | expect(nodesList.teachers![0].value).to.equal('1'); 144 | expect(nodesList.teachers![1].name).to.equal('M.Oleszkiewicz (Mo)'); 145 | expect(nodesList.teachers![1].value).to.equal('3'); 146 | 147 | expect(nodesList.rooms![0].name).to.equal('16 prac. geograficzna'); 148 | expect(nodesList.rooms![0].value).to.equal('1'); 149 | expect(nodesList.rooms![1].name).to.equal('17 prac. fizyczna'); 150 | expect(nodesList.rooms![1].value).to.equal('2'); 151 | }); 152 | 153 | it('Logo check', (): void => { 154 | expect(list.getLogoSrc()).to.equal('images/logo.png'); 155 | }); 156 | }); 157 | }); 158 | 159 | describe('Table test', (): void => { 160 | describe('Room table', (): void => { 161 | const roomTableFilename = path.join(__dirname, 'fixtures', 'sala.html'); 162 | const roomTableHTML = fs.readFileSync(roomTableFilename, { 163 | encoding: 'utf8', 164 | }); 165 | 166 | const roomDaysValuesFilename = path.join(__dirname, 'expected', 'room-days.json'); 167 | const roomDaysValuesJSON = fs.readFileSync(roomDaysValuesFilename, { 168 | encoding: 'utf8', 169 | }); 170 | const roomDaysValues = JSON.parse(roomDaysValuesJSON); 171 | 172 | const table = new Table(roomTableHTML); 173 | it('Cheerio init', (): void => { 174 | expect((): Table => new Table(roomTableHTML)).not.to.throw(); 175 | }); 176 | 177 | it('Day names return value check', (): void => { 178 | const dayNames = table.getDayNames(); 179 | expect(dayNames).to.eql([ 180 | 'Poniedziałek', 181 | 'Wtorek', 182 | 'Środa', 183 | 'Czwartek', 184 | 'Piątek', 185 | ]); 186 | }); 187 | 188 | it('Table hours return check', (): void => { 189 | const tableHours = table.getHours(); 190 | expect(tableHours).to.eql({ 191 | 1: { 192 | number: 1, 193 | timeFrom: '8:00', 194 | timeTo: '8:45', 195 | }, 196 | 2: { 197 | number: 2, 198 | timeFrom: '8:50', 199 | timeTo: '9:35', 200 | }, 201 | 3: { 202 | number: 3, 203 | timeFrom: '9:40', 204 | timeTo: '10:25', 205 | }, 206 | 4: { 207 | number: 4, 208 | timeFrom: '10:40', 209 | timeTo: '11:25', 210 | }, 211 | 5: { 212 | number: 5, 213 | timeFrom: '11:30', 214 | timeTo: '12:15', 215 | }, 216 | 6: { 217 | number: 6, 218 | timeFrom: '12:20', 219 | timeTo: '13:05', 220 | }, 221 | 7: { 222 | number: 7, 223 | timeFrom: '13:10', 224 | timeTo: '13:55', 225 | }, 226 | 8: { 227 | number: 8, 228 | timeFrom: '14:00', 229 | timeTo: '14:45', 230 | }, 231 | 9: { 232 | number: 9, 233 | timeFrom: '14:50', 234 | timeTo: '15:35', 235 | }, 236 | 10: { 237 | number: 10, 238 | timeFrom: '15:40', 239 | timeTo: '16:25', 240 | }, 241 | 11: { 242 | number: 11, 243 | timeFrom: '16:35', 244 | timeTo: '17:20', 245 | }, 246 | }); 247 | }); 248 | 249 | it('Table days return check', (): void => { 250 | const tableDays = table.getDays(); 251 | expect(tableDays).to.eql(roomDaysValues); 252 | }); 253 | 254 | it('Table title', (): void => { 255 | const title = table.getTitle(); 256 | expect(title).to.eql('21 prac. historii'); 257 | }); 258 | 259 | it('Table version info', (): void => { 260 | const versionInfo = table.getVersionInfo(); 261 | expect(versionInfo).to.eql('19 grudnia 2022 r. (wersja 5.0.0)'); 262 | }); 263 | 264 | it('Table generated date', (): void => { 265 | const generatedDate = table.getGeneratedDate(); 266 | expect(generatedDate).to.eql('2018-02-17'); 267 | }); 268 | }); 269 | 270 | describe('Class table', (): void => { 271 | const classTableFilename = path.join(__dirname, 'fixtures', 'oddzial.html'); 272 | const classTableHTML = fs.readFileSync(classTableFilename, { 273 | encoding: 'utf8', 274 | }); 275 | 276 | const classDaysValuesFilename = path.join(__dirname, 'expected', 'class-days.json'); 277 | const classDaysValuesJSON = fs.readFileSync(classDaysValuesFilename, { 278 | encoding: 'utf8', 279 | }); 280 | const classDaysValues = JSON.parse(classDaysValuesJSON); 281 | 282 | const table = new Table(classTableHTML); 283 | it('Cheerio init', (): void => { 284 | expect((): Table => new Table(classTableHTML)).not.to.throw(); 285 | }); 286 | 287 | it('Day names return value check', (): void => { 288 | const dayNames = table.getDayNames(); 289 | expect(dayNames).to.eql([ 290 | 'Poniedziałek', 291 | 'Wtorek', 292 | 'Środa', 293 | 'Czwartek', 294 | 'Piątek', 295 | ]); 296 | }); 297 | 298 | it('getRawDays does not throw an error', (): void => { 299 | table.getRawDays(); 300 | }); 301 | 302 | it('Table hours return check', (): void => { 303 | const tableHours = table.getHours(); 304 | expect(tableHours).to.eql({ 305 | 2: { 306 | number: 2, 307 | timeFrom: '8:00', 308 | timeTo: '8:45', 309 | }, 310 | 3: { 311 | number: 3, 312 | timeFrom: '8:50', 313 | timeTo: '9:35', 314 | }, 315 | 4: { 316 | number: 4, 317 | timeFrom: '9:40', 318 | timeTo: '10:25', 319 | }, 320 | 5: { 321 | number: 5, 322 | timeFrom: '10:40', 323 | timeTo: '11:25', 324 | }, 325 | 6: { 326 | number: 6, 327 | timeFrom: '11:30', 328 | timeTo: '12:15', 329 | }, 330 | 7: { 331 | number: 7, 332 | timeFrom: '12:20', 333 | timeTo: '13:05', 334 | }, 335 | 8: { 336 | number: 8, 337 | timeFrom: '13:10', 338 | timeTo: '13:55', 339 | }, 340 | 9: { 341 | number: 9, 342 | timeFrom: '14:00', 343 | timeTo: '14:45', 344 | }, 345 | 10: { 346 | number: 10, 347 | timeFrom: '14:50', 348 | timeTo: '15:35', 349 | }, 350 | 11: { 351 | number: 11, 352 | timeFrom: '15:40', 353 | timeTo: '16:25', 354 | }, 355 | }); 356 | }); 357 | 358 | it('Table days return check', (): void => { 359 | const tableDays = table.getDays(); 360 | expect(tableDays).to.eql(classDaysValues); 361 | }); 362 | 363 | it('Table title', (): void => { 364 | const title = table.getTitle(); 365 | expect(title).to.eql('3Ti'); 366 | }); 367 | 368 | it('Table version info', (): void => { 369 | const versionInfo = table.getVersionInfo(); 370 | expect(versionInfo).to.eql('19 lutego 2018r.'); 371 | }); 372 | 373 | it('Table generated date', (): void => { 374 | const generatedDate = table.getGeneratedDate(); 375 | expect(generatedDate).to.eql('2018-02-17'); 376 | }); 377 | }); 378 | 379 | // Plain text 380 | describe('Plain class table', (): void => { 381 | const plainClassTableFilename = path.join(__dirname, 'fixtures', 'plain-oddzial.html'); 382 | const plainClassTableHTML = fs.readFileSync(plainClassTableFilename, { 383 | encoding: 'utf8', 384 | }); 385 | 386 | const plainClassDaysValuesFilename = path.join(__dirname, 'expected', 'plain-class-days.json'); 387 | const plainClassDaysValuesJSON = fs.readFileSync(plainClassDaysValuesFilename, { 388 | encoding: 'utf8', 389 | }); 390 | const plainClassDaysValues = JSON.parse(plainClassDaysValuesJSON); 391 | 392 | const table = new Table(plainClassTableHTML); 393 | it('Cheerio init', (): void => { 394 | expect((): Table => new Table(plainClassTableHTML)).not.to.throw(); 395 | }); 396 | 397 | it('Day names return value check', (): void => { 398 | const dayNames = table.getDayNames(); 399 | expect(dayNames).to.eql([ 400 | 'Poniedziałek', 401 | 'Wtorek', 402 | 'Środa', 403 | 'Czwartek', 404 | 'Piątek', 405 | ]); 406 | }); 407 | 408 | it('getRawDays does not throw an error', (): void => { 409 | table.getRawDays(); 410 | }); 411 | 412 | it('Table hours return check', (): void => { 413 | const tableHours = table.getHours(); 414 | expect(tableHours).to.eql({ 415 | 0: { number: 0, timeFrom: '7:10', timeTo: '7:55' }, 416 | 1: { number: 1, timeFrom: '8:00', timeTo: '8:45' }, 417 | 2: { number: 2, timeFrom: '8:50', timeTo: '9:35' }, 418 | 3: { number: 3, timeFrom: '9:40', timeTo: '10:25' }, 419 | 4: { number: 4, timeFrom: '10:40', timeTo: '11:25' }, 420 | 5: { number: 5, timeFrom: '11:30', timeTo: '12:15' }, 421 | 6: { number: 6, timeFrom: '12:20', timeTo: '13:05' }, 422 | 7: { number: 7, timeFrom: '13:10', timeTo: '13:55' }, 423 | 8: { number: 8, timeFrom: '14:00', timeTo: '14:45' }, 424 | 9: { number: 9, timeFrom: '14:50', timeTo: '15:35' }, 425 | 10: { number: 10, timeFrom: '15:40', timeTo: '16:25' }, 426 | }); 427 | }); 428 | 429 | it('Table days return check', (): void => { 430 | const tableDays = table.getDays(); 431 | expect(tableDays).to.eql(plainClassDaysValues); 432 | }); 433 | 434 | it('Table title', (): void => { 435 | const title = table.getTitle(); 436 | expect(title).to.eql('4as 4TMt'); 437 | }); 438 | 439 | it('Table version info', (): void => { 440 | const versionInfo = table.getVersionInfo(); 441 | expect(versionInfo).to.eql('13 lutego 2023 r.'); 442 | }); 443 | 444 | it('Table generated date', (): void => { 445 | const generatedDate = table.getGeneratedDate(); 446 | expect(generatedDate).to.eql('2023-02-09'); 447 | }); 448 | }); 449 | }); 450 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["lib/**.ts"], 4 | "compilerOptions": { 5 | "outDir": "./dist" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "strict": true 7 | } 8 | } 9 | --------------------------------------------------------------------------------