85 lines
4.5 KiB
Dart
85 lines
4.5 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:jj_mkvmaker/app/settings.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
/// 설정 A 약속 시험: 설정 파일 (settings.json) 을 읽고 다시 쓴 결과가 나누기 전 판과 같다 (키 순서를 뺀 바이트 - 키를 정렬해 견줌).
|
|
/// - 합성: 모든 키의 값을 바꾼 입력 (test/fixtures/settings_golden_in.json) → 나누기 전 판의 출력 (…_out.json)
|
|
/// - 사용자 파일: JJ_USER_SETTINGS_EXPECT 가 있으면 사용자 설정 파일 (com.jj\jj_mkvmaker\settings.json) 을 시험 폴더에 복사해 읽기만 하고,
|
|
/// 나누기 전 판이 같은 파일로 낸 출력 (scratch, 커밋하지 않음) 과 견준다. 사용자 파일에는 쓰지 않는다
|
|
/// JJ_SETTINGS_GOLDEN_WRITE=1 이면 견주지 않고 기준을 만든다 (나누기 전 판에서 한 번)
|
|
void main() {
|
|
final write = Platform.environment['JJ_SETTINGS_GOLDEN_WRITE'] == '1';
|
|
const fixtures = 'test/fixtures';
|
|
|
|
/// 키를 정렬한 JSON (키 순서는 분야를 옮기면 바뀐다 - 값 · 키 집합만 견줌)
|
|
String canonical(Object? v) {
|
|
Object? sort(Object? x) => x is Map
|
|
? {for (final k in (x.keys.map((e) => '$e').toList()..sort())) k: sort(x[k])}
|
|
: x is List
|
|
? [for (final e in x) sort(e)]
|
|
: x;
|
|
return const JsonEncoder.withIndent(' ').convert(sort(v));
|
|
}
|
|
|
|
/// 읽고 다시 쓴 것 + 읽을 때 정한 "바뀐 기본값 알림" 목록 (파일에는 없지만 읽기의 결과)
|
|
String roundTrip(String text) {
|
|
final s = AppSettings.fromJson(jsonDecode(text) as Map<String, dynamic>);
|
|
return canonical({...s.toJson(), '__migrated': s.migrated});
|
|
}
|
|
|
|
/// 모든 키의 값을 바꾼 입력 (bool 은 반대, 수는 +7, 글은 앞에 x_, 안쪽 묶음도) - 읽기의 검사 · 고침도 함께 지나게
|
|
Object? change(Object? v) => switch (v) {
|
|
final bool b => !b,
|
|
final int n => n + 7,
|
|
final double d => d + 0.5,
|
|
final String s => 'x_$s',
|
|
final Map<dynamic, dynamic> m => {for (final e in m.entries) '${e.key}': change(e.value)},
|
|
_ => v,
|
|
};
|
|
Map<String, Object?> mutated() => {for (final e in AppSettings().toJson(plainSecrets: true).entries) e.key: change(e.value)};
|
|
|
|
test('합성: 모든 키를 바꾼 설정을 읽고 쓰면 나누기 전 판과 같다 · 처음 값도', () {
|
|
final inFile = File(p.join(fixtures, 'settings_golden_in.json'));
|
|
final outFile = File(p.join(fixtures, 'settings_golden_out.json'));
|
|
final defFile = File(p.join(fixtures, 'settings_golden_default.json'));
|
|
if (write) {
|
|
Directory(fixtures).createSync(recursive: true);
|
|
inFile.writeAsStringSync(const JsonEncoder.withIndent(' ').convert(mutated()));
|
|
outFile.writeAsStringSync(roundTrip(inFile.readAsStringSync()));
|
|
defFile.writeAsStringSync(canonical(AppSettings().toJson()));
|
|
return;
|
|
}
|
|
// git 이 줄 끝을 CRLF 로 바꿔 꺼낼 수 있다 - LF 로 맞춰 견줌
|
|
String read(File f) => f.readAsStringSync().replaceAll('\r\n', '\n');
|
|
expect(roundTrip(read(inFile)), read(outFile));
|
|
expect(canonical(AppSettings().toJson()), read(defFile));
|
|
});
|
|
|
|
test('옛 판 설정 (옮김 표시 없음 · 예전 처음 값): 읽은 값과 바뀐 기본값 알림이 나누기 전 판과 같다', () {
|
|
const legacy = {'explorerLayout': 'auto', 'explorerClick': 'open', 'explorerOrientation': 'auto', 'screenOrientation': 'landscape'};
|
|
final outFile = File(p.join(fixtures, 'settings_golden_legacy_out.json'));
|
|
if (write) {
|
|
outFile.writeAsStringSync(roundTrip(jsonEncode(legacy)));
|
|
return;
|
|
}
|
|
expect(roundTrip(jsonEncode(legacy)), outFile.readAsStringSync().replaceAll('\r\n', '\n'));
|
|
});
|
|
|
|
final expectPath = Platform.environment['JJ_USER_SETTINGS_EXPECT'];
|
|
test('사용자 설정 파일 (복사본): 읽고 쓰면 나누기 전 판과 같다', () {
|
|
final user = File(p.join(Platform.environment['APPDATA'] ?? '', 'com.jj', 'jj_mkvmaker', 'settings.json'));
|
|
final tmp = Directory.systemTemp.createTempSync('jj_settings_user_');
|
|
addTearDown(() => tmp.deleteSync(recursive: true));
|
|
final copy = user.copySync(p.join(tmp.path, 'settings.json'));
|
|
final got = roundTrip(copy.readAsStringSync());
|
|
if (write) {
|
|
File(expectPath!).writeAsStringSync(got);
|
|
return;
|
|
}
|
|
expect(got, File(expectPath!).readAsStringSync().replaceAll('\r\n', '\n'));
|
|
}, skip: expectPath == null ? '사용자 파일 기준 (JJ_USER_SETTINGS_EXPECT) 이 없으면 건너뜀 - 이 PC 에서만' : null);
|
|
}
|