123 lines
4.2 KiB
Dart
123 lines
4.2 KiB
Dart
|
|
import 'dart:convert';
|
||
|
|
import 'dart:io';
|
||
|
|
|
||
|
|
import 'package:archive/archive.dart';
|
||
|
|
import 'package:halkyon_learn_curator/src/sources/krdict.dart';
|
||
|
|
import 'package:halkyon_learn_curator/src/sources/wiktionary.dart';
|
||
|
|
import 'package:halkyon_learn_curator/src/wordfreq.dart';
|
||
|
|
import 'package:test/test.dart';
|
||
|
|
|
||
|
|
void main() {
|
||
|
|
/// The fixture packed as KRDict packs its export: its first file.
|
||
|
|
List<int> export() => ZipEncoder().encodeBytes(
|
||
|
|
Archive()..add(
|
||
|
|
ArchiveFile.bytes(
|
||
|
|
'1_5000_20260919.json',
|
||
|
|
File('test/fixtures/krdict-sample.json').readAsBytesSync(),
|
||
|
|
),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
|
||
|
|
Future<List<Map<String, Object?>>> converted({
|
||
|
|
WordFrequencies? frequencies,
|
||
|
|
WiktionaryKorean? korean,
|
||
|
|
}) async {
|
||
|
|
final (:version, :entries) = krdictExport(export());
|
||
|
|
return [
|
||
|
|
for (final line in await krdictDictionary(
|
||
|
|
entries,
|
||
|
|
sourceVersion: version,
|
||
|
|
frequencies: frequencies,
|
||
|
|
korean: korean,
|
||
|
|
).toList())
|
||
|
|
jsonDecode(line) as Map<String, Object?>,
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
test("KRDict's words with their level, pronunciation where it differs from "
|
||
|
|
'the spelling, Hanja, forms and English senses', () async {
|
||
|
|
final [header, ...entries] = await converted();
|
||
|
|
|
||
|
|
expect(header['source'], 'krdict');
|
||
|
|
expect(header['language'], 'ko');
|
||
|
|
expect(header['sourceVersion'], '2026-09-19');
|
||
|
|
expect(
|
||
|
|
[
|
||
|
|
for (final credit in header['credits']! as List)
|
||
|
|
(credit as Map)['name'],
|
||
|
|
],
|
||
|
|
['한국어기초사전 (Basic Korean Dictionary)'],
|
||
|
|
);
|
||
|
|
final school = entries.singleWhere((entry) => entry['headword'] == '학교');
|
||
|
|
expect(school['id'], '73276');
|
||
|
|
expect(school['reading'], '학꾜');
|
||
|
|
expect(school['labels'], ['level:beginner']);
|
||
|
|
expect(school['keys'], containsAll(['학교', '學校', 'school']));
|
||
|
|
const definition =
|
||
|
|
'An institution that educates students according to a specific '
|
||
|
|
'purpose, curriculum, system, etc.';
|
||
|
|
expect(school['entry'], {
|
||
|
|
'pos': 'noun',
|
||
|
|
'hanja': ['學校'],
|
||
|
|
'senses': [
|
||
|
|
{
|
||
|
|
'glosses': ['school'],
|
||
|
|
'info': [definition],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
});
|
||
|
|
final read = entries.singleWhere((entry) => entry['headword'] == '읽다');
|
||
|
|
expect(read['reading'], '익따');
|
||
|
|
expect(read['textKeys'], containsAll(['읽다', '읽어', '읽고']));
|
||
|
|
expect(
|
||
|
|
(read['entry']! as Map)['inflections'],
|
||
|
|
contains(equals({'text': '읽어'})),
|
||
|
|
);
|
||
|
|
final together = entries.where((entry) => entry['headword'] == '같이');
|
||
|
|
expect(
|
||
|
|
[for (final entry in together) (entry['entry']! as Map)['pos']],
|
||
|
|
['particle', 'adv'],
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test('an idiom or a proverb is an entry of its own, never found in running '
|
||
|
|
'text, with an id told apart from its word', () async {
|
||
|
|
final [_, ...entries] = await converted();
|
||
|
|
|
||
|
|
final proverb = entries.singleWhere(
|
||
|
|
(entry) => entry['headword'] == '가는 날이 장날',
|
||
|
|
);
|
||
|
|
expect(proverb['id'], '27500:가는 날이 장날');
|
||
|
|
expect((proverb['entry']! as Map)['pos'], 'proverb');
|
||
|
|
expect(proverb.containsKey('textKeys'), isFalse);
|
||
|
|
expect(
|
||
|
|
entries.singleWhere((entry) => entry['headword'] == '가다')['id'],
|
||
|
|
'27500',
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("Wiktionary's forms find a word in text; a verb rarely written as "
|
||
|
|
'the dictionary writes it ranks by its most used form', () async {
|
||
|
|
final korean = WiktionaryKorean()..forms['가다'] = {'가요', '갔어요', '갑니다'};
|
||
|
|
final [_, ...entries] = await converted(
|
||
|
|
korean: korean,
|
||
|
|
frequencies: WordFrequencies(const {'갔어요': 50}),
|
||
|
|
);
|
||
|
|
|
||
|
|
final go = entries.singleWhere((entry) => entry['headword'] == '가다');
|
||
|
|
expect(go['textKeys'], containsAll(['가다', '가요', '갔어요']));
|
||
|
|
expect(go['labels'], contains('common'));
|
||
|
|
expect(go['rank'], 100000 + 100);
|
||
|
|
});
|
||
|
|
|
||
|
|
test("the export's JSON download is the third its page offers", () {
|
||
|
|
expect(
|
||
|
|
krdictJsonDownloadOf('''
|
||
|
|
<button onclick="batchDownload('215')">엑셀</button>
|
||
|
|
<button onclick="batchDownload('216')">XML</button>
|
||
|
|
<button onclick="batchDownload('217')">Json</button>'''),
|
||
|
|
'217',
|
||
|
|
);
|
||
|
|
expect(krdictJsonDownloadOf("batchDownload('0')"), isNull);
|
||
|
|
});
|
||
|
|
}
|