117 lines
5.1 KiB
Dart
117 lines
5.1 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:jj_mkvmaker/app/net_guard.dart';
|
|
import 'package:jj_mkvmaker/core/download_detect.dart' show CookieExport, CookieRecord;
|
|
import 'package:jj_mkvmaker/core/web_translate.dart' show webTranslateRestoreScript;
|
|
import 'package:jj_mkvmaker/ui/browser/dns_block.dart';
|
|
import 'package:jj_mkvmaker/ui/browser/page_translation.dart';
|
|
import 'package:jj_mkvmaker/ui/browser/web_nav.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
/// 받은 조작을 적어 두는 WebNav (NavWatch 가 무엇을 그대로 넘기는지 보려고)
|
|
class _Log implements WebNav {
|
|
final calls = <String>[];
|
|
@override
|
|
Future<void> load(String url) async => calls.add('load $url');
|
|
@override
|
|
Future<void> back() async => calls.add('back');
|
|
@override
|
|
Future<void> forward() async => calls.add('forward');
|
|
@override
|
|
Future<void> reload() async => calls.add('reload');
|
|
@override
|
|
Future<void> stop() async => calls.add('stop');
|
|
@override
|
|
Future<void> exportCookies() async => calls.add('cookies');
|
|
@override
|
|
Future<void> pauseMedia() async => calls.add('pause');
|
|
@override
|
|
Future<void> runScript(String js) async => calls.add('run $js');
|
|
@override
|
|
Future<void> clearData() async => calls.add('clear');
|
|
@override
|
|
Future<Object?> evaluate(String js) async {
|
|
calls.add('eval $js');
|
|
return 7;
|
|
}
|
|
|
|
@override
|
|
Future<void> setJavaScript(bool on) async => calls.add('js $on');
|
|
}
|
|
|
|
void main() {
|
|
test('약속 NavWatch: 사용자가 옮길 때 (주소 · 뒤로 · 앞으로 · 새로고침) 만 알리고, 모든 조작은 그대로 넘긴다', () async {
|
|
final inner = _Log();
|
|
var moved = 0;
|
|
final w = NavWatch(inner, () => moved++);
|
|
await w.load('https://a.example/');
|
|
await w.back();
|
|
await w.forward();
|
|
await w.reload();
|
|
expect(moved, 4);
|
|
await w.stop();
|
|
await w.exportCookies();
|
|
await w.pauseMedia();
|
|
await w.runScript('x');
|
|
await w.clearData();
|
|
expect(await w.evaluate('y'), 7);
|
|
await w.setJavaScript(false);
|
|
expect(moved, 4, reason: '멈춤 · 쿠키 · 스크립트 등은 페이지를 옮기지 않는다');
|
|
expect(inner.calls,
|
|
['load https://a.example/', 'back', 'forward', 'reload', 'stop', 'cookies', 'pause', 'run x', 'clear', 'eval y', 'js false']);
|
|
});
|
|
|
|
test('약속 writeLoginCookies · deleteExportedCookies: cookies.txt 를 한 번에 바꿔 넣고, 지우면 임시 파일까지 없앤다', () async {
|
|
final dir = await Directory.systemTemp.createTemp('jj_cookie_');
|
|
addTearDown(() => dir.delete(recursive: true));
|
|
final file = File(p.join(dir.path, CookieExport.fileName));
|
|
await writeLoginCookies(dir.path, const []);
|
|
expect(file.existsSync(), isFalse, reason: '쿠키가 없으면 쓰지 않는다');
|
|
await writeLoginCookies('', [const CookieRecord(name: 'a', value: 'b', domain: '.youtube.com')]);
|
|
await writeLoginCookies(dir.path, [const CookieRecord(name: 'SID', value: 'v1', domain: '.youtube.com', expires: 0)]);
|
|
expect(file.readAsStringSync(), contains('SID\tv1'));
|
|
expect(File('${file.path}.tmp').existsSync(), isFalse, reason: '임시 파일은 바꿔 넣은 뒤 남지 않는다');
|
|
File('${file.path}.tmp').writeAsStringSync('half');
|
|
await deleteExportedCookies(dir.path);
|
|
expect([file.existsSync(), File('${file.path}.tmp').existsSync()], [false, false]);
|
|
await deleteExportedCookies(''); // 데이터 폴더가 없으면 아무것도 안 함
|
|
});
|
|
|
|
test('약속 PageTranslation: 꺼져 있거나 할 수 없을 때는 페이지를 건드리지 않고, 끄면 원문으로 되돌린다', () async {
|
|
final nav = _Log();
|
|
var can = false;
|
|
final gaveUp = <Object>[];
|
|
final t = PageTranslation(on: false, nav: () => nav, canRun: () => can, onGiveUp: gaveUp.add);
|
|
addTearDown(t.dispose);
|
|
t.now();
|
|
expect(nav.calls, isEmpty, reason: '꺼져 있음');
|
|
t.setOn(true, force: true);
|
|
expect([t.on, t.force], [true, true]);
|
|
await Future<void>.delayed(Duration.zero);
|
|
expect(nav.calls, isEmpty, reason: '화면이 가려졌거나 웹 주소가 아님');
|
|
can = true;
|
|
t.now();
|
|
await Future<void>.delayed(Duration.zero);
|
|
expect(nav.calls.where((c) => c.startsWith('eval ')).length, 1, reason: '모을 글자를 한 번 묻는다 (받은 값이 글자 묶음이 아니면 멈춤)');
|
|
nav.calls.clear();
|
|
t.setOn(false, force: true);
|
|
expect([t.on, t.force], [false, false]);
|
|
expect(nav.calls, ['eval $webTranslateRestoreScript']);
|
|
expect(gaveUp, isEmpty);
|
|
});
|
|
|
|
test('약속 DnsBlockWatch: 실패 기록이 없으면 막지 않고, 덮개가 있는 동안만 아래 알림을 막는다', () {
|
|
final w = DnsBlockWatch();
|
|
final g = NetGuard.instance.noticeBlockers;
|
|
final before = g.value;
|
|
expect(w.find(host: ''), isNull);
|
|
expect(w.find(host: 'never-failed.example'), isNull);
|
|
w.set(('a.example', '8.8.8.8'));
|
|
w.set(('b.example', '8.8.8.8'));
|
|
expect([w.blocked, g.value], [('b.example', '8.8.8.8'), before + 1], reason: '덮개를 바꿔도 한 번만 막는다');
|
|
w.set(null);
|
|
expect([w.blocked, g.value], [null, before]);
|
|
});
|
|
}
|