Skip to content

Commit b882c68

Browse files
Feature/test parse config rebase/679 (#779)
* Test parsing of convert config * Re-add the test files * svelte update changes, prettier * Remove discrepancies from test files * more annoying quantitative comparison changes * another quantitative change * trying project conditional tests * quantitative once more * quantitative hmmm * quantitative aha! * dab sab separation of tests * dumb pathname bug * fix for tsconfig.js error * include minimal build for lint * lint.yml add carriage return --------- Co-authored-by: AslanRules <[email protected]>
1 parent 82de9e7 commit b882c68

File tree

7 files changed

+557
-270
lines changed

7 files changed

+557
-270
lines changed

.github/workflows/lint.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ jobs:
2121
npm --version
2222
npm i
2323
24-
- name: Add config
24+
- name: Add minimal config
2525
run: |
2626
echo "export default {};" > src/lib/data/config.js
2727
echo "export const firebaseConfig = null;" > src/lib/data/firebase-config.js
28+
echo "export const catalog = [];" > src/lib/data/catalog.js
29+
echo "export default {}" > src/lib/data/contents.js
2830
29-
- name: Add catalog
30-
run: echo "export const catalog = [];" > src/lib/data/catalog.js
31+
- name: Run minimal build
32+
run: |
33+
npx vite build
3134
3235
- name: TypeScript/Svelte Check
3336
run: |

.github/workflows/test.yml

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,19 @@ jobs:
4646
for PROGRAM in sab dab; do
4747
echo "Processing projects for $PROGRAM"
4848
mkdir -p "$HOME/projects/$PROGRAM"
49-
PROJECTS=$(jq -r ".${PROGRAM}.projects[]" "test_data/projects/index.json")
50-
for PROJECT_ZIP in $PROJECTS; do
49+
50+
# Get all projects as JSON array
51+
PROJECTS_JSON=$(jq -r ".${PROGRAM}.projects" "test_data/projects/index.json")
52+
53+
# Get number of projects
54+
NUM_PROJECTS=$(echo "$PROJECTS_JSON" | jq '. | length')
55+
56+
# Iterate through projects using index
57+
for ((i=0; i<$NUM_PROJECTS; i++)); do
58+
# Get project path and test directories
59+
PROJECT_ZIP=$(echo "$PROJECTS_JSON" | jq -r ".[$i].path")
60+
TEST_DIRS=$(echo "$PROJECTS_JSON" | jq -r ".[$i].tests[]")
61+
5162
PROJECT_NAME=$(basename "$PROJECT_ZIP" .zip)
5263
echo "Project: $PROJECT_NAME"
5364
PROJECT_DIR="$HOME/projects/${PROGRAM}/$PROJECT_NAME"
@@ -60,6 +71,11 @@ jobs:
6071
popd > /dev/null
6172
npm run build
6273
npm run convert
63-
npm run test
74+
75+
# Run tests for each specified directory
76+
for TEST_DIR in $TEST_DIRS; do
77+
echo "Running tests in directory: $TEST_DIR"
78+
npm run test "$TEST_DIR"
79+
done
6480
done
6581
done

convert/convertConfig.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { existsSync, PathLike, readdirSync, readFileSync } from 'fs';
1+
import { existsSync, readdirSync, readFileSync, type PathLike } from 'fs';
22
import path, { basename, extname } from 'path';
33
import type {
44
AppConfig,
@@ -13,7 +13,7 @@ import type {
1313
import jsdom from 'jsdom';
1414
import { convertMarkdownsToHTML } from './convertMarkdown';
1515
import { splitVersion } from './stringUtils';
16-
import { Task, TaskOutput } from './Task';
16+
import { Task, type TaskOutput } from './Task';
1717

1818
const fontFamilies: string[] = [];
1919

@@ -26,13 +26,13 @@ function decodeFromXml(input: string): string {
2626
.replace('&amp;', '&');
2727
}
2828

29-
function parseConfigValue(value: any) {
29+
export function parseConfigValue(value: any) {
3030
if (!value.includes(':') && !isNaN(parseInt(value))) value = parseInt(value);
3131
else if (['true', 'false'].includes(value)) value = value === 'true' ? true : false;
3232
// else {} // " " split array, string, enum or time
3333
return value;
3434
}
35-
function parseAdditionalNames(namesTag: Element, verbose: number) {
35+
export function parseAdditionalNames(namesTag: Element, verbose: number) {
3636
const additionalNames = [];
3737
const nameTags = namesTag?.getElementsByTagName('name');
3838
for (const tag of nameTags) {
@@ -46,7 +46,7 @@ function parseAdditionalNames(namesTag: Element, verbose: number) {
4646
}
4747
return additionalNames;
4848
}
49-
function parseStyles(stylesTag: Element, verbose: number) {
49+
export function parseStyles(stylesTag: Element, verbose: number) {
5050
const styles = [];
5151
const styleTags = stylesTag?.getElementsByTagName('style');
5252
if (!styleTags) throw new Error('Styles tag not found in xml');
@@ -77,7 +77,7 @@ function parseStyles(stylesTag: Element, verbose: number) {
7777

7878
return styles;
7979
}
80-
function parseStylesInfo(stylesInfoTag: Element, verbose: number): StyleConfig {
80+
export function parseStylesInfo(stylesInfoTag: Element, verbose: number): StyleConfig {
8181
return {
8282
font: stylesInfoTag.getElementsByTagName('text-font')[0].attributes.getNamedItem('family')!
8383
.value,
@@ -101,7 +101,7 @@ function parseStylesInfo(stylesInfoTag: Element, verbose: number): StyleConfig {
101101
};
102102
}
103103

104-
function parseTrait(tag: Element, name: string): string {
104+
export function parseTrait(tag: Element, name: string): string {
105105
const traitTags = tag.getElementsByTagName('trait');
106106
for (const tag of traitTags) {
107107
if (tag.attributes.getNamedItem('name')!.value === name) {
@@ -161,7 +161,7 @@ function changeAndroidToRem(propValue: string) {
161161
}
162162
}
163163

164-
function convertFooter(markdown: string | undefined, appdef: Document): string | undefined {
164+
export function convertFooter(markdown: string | undefined, appdef: Document): string | undefined {
165165
const footer = markdown?.length ? convertMarkdownsToHTML(removeCData(markdown)) : undefined;
166166
const appName = appdef.getElementsByTagName('app-name')[0].innerHTML;
167167
const versionName = appdef.getElementsByTagName('version')[0].getAttribute('name');
@@ -176,7 +176,7 @@ function convertFooter(markdown: string | undefined, appdef: Document): string |
176176
?.replace(/%program-version%/g, programVersion ?? '');
177177
}
178178

179-
function convertCollectionFooter(collectionTag: Element, document: Document) {
179+
export function convertCollectionFooter(collectionTag: Element, document: Document) {
180180
const footerTags = Array.from(collectionTag.children).filter(
181181
(child) => child.tagName === 'footer'
182182
);
@@ -360,7 +360,7 @@ function convertConfig(dataDir: string, verbose: number) {
360360
return filterFeaturesNotReady(data);
361361
}
362362

363-
function parseFeatures(document: Document, verbose: number) {
363+
export function parseFeatures(document: Document, verbose: number) {
364364
const mainFeatureTags = document
365365
.querySelector('features[type=main]')
366366
?.getElementsByTagName('e');
@@ -384,7 +384,7 @@ function parseFeatures(document: Document, verbose: number) {
384384
return mainFeatures;
385385
}
386386

387-
function parseFonts(document: Document, verbose: number) {
387+
export function parseFonts(document: Document, verbose: number) {
388388
const fontTags = document.getElementsByTagName('fonts')[0].getElementsByTagName('font');
389389
const fonts = [];
390390

@@ -407,7 +407,7 @@ function parseFonts(document: Document, verbose: number) {
407407
return fonts;
408408
}
409409

410-
function parseColorThemes(document: Document, verbose: number) {
410+
export function parseColorThemes(document: Document, verbose: number) {
411411
const colorThemeTags = document
412412
.getElementsByTagName('color-themes')[0]
413413
.getElementsByTagName('color-theme');
@@ -468,7 +468,7 @@ function parseColorThemes(document: Document, verbose: number) {
468468
return { themes, defaultTheme };
469469
}
470470

471-
function parseTraits(document: Document, dataDir: string, verbose: number) {
471+
export function parseTraits(document: Document, dataDir: string, verbose: number) {
472472
const traitTags = document.getElementsByTagName('traits')[0]?.getElementsByTagName('trait');
473473
const traits: { [key: string]: any } = {};
474474

@@ -488,7 +488,7 @@ function parseTraits(document: Document, dataDir: string, verbose: number) {
488488
return traits;
489489
}
490490

491-
function parseBookCollections(document: Document, verbose: number) {
491+
export function parseBookCollections(document: Document, verbose: number) {
492492
const booksTags = document.getElementsByTagName('books');
493493
const bookCollections = [];
494494

@@ -701,7 +701,7 @@ function parseBookCollections(document: Document, verbose: number) {
701701
return bookCollections;
702702
}
703703

704-
function parseInterfaceLanguages(document: Document, data: AppConfig, verbose: number) {
704+
export function parseInterfaceLanguages(document: Document, data: AppConfig, verbose: number) {
705705
const interfaceLanguagesTag = document.getElementsByTagName('interface-languages')[0];
706706
const useSystemLanguage = parseTrait(interfaceLanguagesTag, 'use-system-language') === 'true';
707707
const interfaceLanguages: {
@@ -729,7 +729,7 @@ function parseInterfaceLanguages(document: Document, data: AppConfig, verbose: n
729729
return interfaceLanguages;
730730
}
731731

732-
function parseWritingSystem(element: Element, verbose: number): WritingSystemConfig {
732+
export function parseWritingSystem(element: Element, verbose: number): WritingSystemConfig {
733733
const type = element.attributes.getNamedItem('type')!.value;
734734
const fontFamily = element.getElementsByTagName('font-family')[0].innerHTML;
735735
const textDirection = parseTrait(element, 'text-direction');
@@ -747,7 +747,7 @@ function parseWritingSystem(element: Element, verbose: number): WritingSystemCon
747747

748748
return writingSystem;
749749
}
750-
function parseDictionaryWritingSystem(
750+
export function parseDictionaryWritingSystem(
751751
element: Element,
752752
verbose: number
753753
): DictionaryWritingSystemConfig {
@@ -799,7 +799,7 @@ function parseDictionaryWritingSystem(
799799
};
800800
}
801801

802-
function parseMenuLocalizations(document: Document, verbose: number) {
802+
export function parseMenuLocalizations(document: Document, verbose: number) {
803803
const translationMappingsTags = document.getElementsByTagName('translation-mappings');
804804
let translationMappings: {
805805
defaultLang: string;
@@ -832,7 +832,7 @@ function parseMenuLocalizations(document: Document, verbose: number) {
832832
return translationMappings;
833833
}
834834

835-
function parseKeys(document: Document, verbose: number) {
835+
export function parseKeys(document: Document, verbose: number) {
836836
if (document.getElementsByTagName('keys').length > 0) {
837837
const keys = Array.from(
838838
document.getElementsByTagName('keys')[0].getElementsByTagName('key')
@@ -844,7 +844,7 @@ function parseKeys(document: Document, verbose: number) {
844844
return [];
845845
}
846846

847-
function parseAnalytics(document: Document, verbose: number) {
847+
export function parseAnalytics(document: Document, verbose: number) {
848848
const analyticsElements = document.getElementsByTagName('analytics');
849849

850850
const analytics: { enabled: boolean; providers: any[] } = {
@@ -893,7 +893,7 @@ function parseAnalytics(document: Document, verbose: number) {
893893
return analytics;
894894
}
895895

896-
function parseFirebase(document: Document, verbose: number) {
896+
export function parseFirebase(document: Document, verbose: number) {
897897
const firebaseElements = document.getElementsByTagName('firebase');
898898
let firebase: { features: { [key: string]: any } } = { features: {} };
899899

@@ -920,7 +920,7 @@ function parseFirebase(document: Document, verbose: number) {
920920
return firebase;
921921
}
922922

923-
function parseAudioSources(document: Document, verbose: number) {
923+
export function parseAudioSources(document: Document, verbose: number) {
924924
const audioSources = document
925925
.getElementsByTagName('audio-sources')[0]
926926
?.getElementsByTagName('audio-source');
@@ -987,7 +987,7 @@ function parseAudioSources(document: Document, verbose: number) {
987987
return { sources, files };
988988
}
989989

990-
function parseVideos(document: Document, verbose: number) {
990+
export function parseVideos(document: Document, verbose: number) {
991991
const videoTags = document.getElementsByTagName('videos')[0]?.getElementsByTagName('video');
992992
const videos: any[] = [];
993993
if (videoTags?.length > 0) {
@@ -1030,7 +1030,7 @@ function parseVideos(document: Document, verbose: number) {
10301030
return videos;
10311031
}
10321032

1033-
function parseIllustrations(document: Document, verbose: number) {
1033+
export function parseIllustrations(document: Document, verbose: number) {
10341034
const imagesTags = document.getElementsByTagName('images');
10351035
const illustrations: any[] = [];
10361036
if (imagesTags?.length > 0) {
@@ -1067,7 +1067,7 @@ function parseIllustrations(document: Document, verbose: number) {
10671067
return illustrations;
10681068
}
10691069

1070-
function parseLayouts(document: Document, bookCollections: any, verbose: number) {
1070+
export function parseLayouts(document: Document, bookCollections: any, verbose: number) {
10711071
const layoutRoot = document.getElementsByTagName('layouts')[0];
10721072
let defaultLayout = layoutRoot?.getAttribute('default');
10731073
const layouts = [];
@@ -1109,7 +1109,7 @@ function parseLayouts(document: Document, bookCollections: any, verbose: number)
11091109
return { layouts, defaultLayout };
11101110
}
11111111

1112-
function parseBackgroundImages(document: Document, verbose: number) {
1112+
export function parseBackgroundImages(document: Document, verbose: number) {
11131113
const backgroundImageTags = document
11141114
.querySelector('images[type=background]')
11151115
?.getElementsByTagName('image');
@@ -1127,7 +1127,7 @@ function parseBackgroundImages(document: Document, verbose: number) {
11271127
return backgroundImages;
11281128
}
11291129

1130-
function parseWatermarkImages(document: Document, verbose: number) {
1130+
export function parseWatermarkImages(document: Document, verbose: number) {
11311131
const watermarkImageTags = document
11321132
.querySelector('images[type=watermark]')
11331133
?.getElementsByTagName('image');
@@ -1145,7 +1145,7 @@ function parseWatermarkImages(document: Document, verbose: number) {
11451145
return watermarkImages;
11461146
}
11471147

1148-
function parseMenuItems(document: Document, type: string, verbose: number) {
1148+
export function parseMenuItems(document: Document, type: string, verbose: number) {
11491149
const firstMenuItemsByType = document.querySelector(`menu-items[type="${type}"]`);
11501150
const menuItemTags = firstMenuItemsByType?.getElementsByTagName('menu-item');
11511151
const menuItems = [];
@@ -1208,7 +1208,7 @@ function parseMenuItems(document: Document, type: string, verbose: number) {
12081208
return menuItems;
12091209
}
12101210

1211-
function parsePlans(document: Document, verbose: number) {
1211+
export function parsePlans(document: Document, verbose: number) {
12121212
const features: { [key: string]: string } = {};
12131213
const plans: {
12141214
id: string;
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { readFileSync } from 'fs';
2+
import path from 'path';
3+
import type { DictionaryConfig, DictionaryWritingSystemConfig } from '$config';
4+
import jsdom from 'jsdom';
5+
import { expect, test } from 'vitest';
6+
import { parseDictionaryWritingSystem, parseFeatures } from '../../convertConfig';
7+
8+
const dataDir = './data/';
9+
const dom = new jsdom.JSDOM(readFileSync(path.join(dataDir, 'appdef.xml')).toString(), {
10+
contentType: 'text/xml'
11+
});
12+
const { document } = dom.window;
13+
const appDefinition = document.getElementsByTagName('app-definition')[0];
14+
const programType = appDefinition.attributes.getNamedItem('type')!.value;
15+
16+
if (programType === 'SAB') {
17+
test('Dummy test for DAB testing for SAB file', () => {
18+
expect(0).toEqual(0);
19+
});
20+
} else if (programType === 'DAB') {
21+
test('convertConfig: parse dictionary writing systems', () => {
22+
const result: { [key: string]: DictionaryWritingSystemConfig } = {};
23+
const writingSystemsTag = document.getElementsByTagName('writing-systems')[0];
24+
const writingSystemTags = writingSystemsTag.getElementsByTagName('writing-system');
25+
for (const tag of writingSystemTags) {
26+
const writingSystem = parseDictionaryWritingSystem(tag, 1);
27+
const code: string = tag.attributes.getNamedItem('code')!.value;
28+
result[code] = writingSystem;
29+
}
30+
31+
for (const lang in result.writingSystems) {
32+
expect(result[lang].fontFamily).not.toEqual('');
33+
expect(result[lang].textDirection).toSatisfy((r) => r === 'LTR' || r === 'RTL');
34+
expect(Object.keys(result[lang].displayNames)).not.toHaveLength(0);
35+
36+
// TRAITS NOT IN SAB
37+
expect(Object.keys(result[lang].sortMethod)).toHaveLength(2);
38+
expect(result[lang]).toHaveProperty('alphabet');
39+
expect(result[lang].alphabet!.length).toBeGreaterThan(0);
40+
expect(result[lang]).toHaveProperty('inputButtons');
41+
expect(result[lang].inputButtons!.length).toBeGreaterThan(0);
42+
expect(Object.keys(result[lang])).not.toHaveLength(0);
43+
}
44+
});
45+
46+
test('convertConfig: parse features', () => {
47+
const result = parseFeatures(document, 1);
48+
expect(Object.keys(result)).not.toHaveLength(0);
49+
});
50+
} else {
51+
throw new Error(`Unsupported program type parsed: ${programType}`);
52+
}

0 commit comments

Comments
 (0)