app scaffold
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import 'package:core_foundation/core_foundation.dart';
|
||||
import 'package:core_logging/core_logging.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('scrubber', () {
|
||||
test('敏感 key 整体抹掉', () {
|
||||
final Map<String, Object?> out = scrubMap(<String, Object?>{
|
||||
'accessToken': 'eyJhbGciOi...',
|
||||
'Authorization': 'Bearer abc',
|
||||
'ticket': 'T-123',
|
||||
'path': '/api/v1/stores',
|
||||
});
|
||||
|
||||
expect(out['accessToken'], redacted);
|
||||
expect(out['Authorization'], redacted);
|
||||
expect(out['ticket'], redacted);
|
||||
expect(out['path'], '/api/v1/stores');
|
||||
});
|
||||
|
||||
test('手机号走掩码而不是整体抹掉', () {
|
||||
expect(scrubMap(<String, Object?>{'phone': '13812345678'})['phone'], '138****5678');
|
||||
expect(maskPhone('123'), '***');
|
||||
});
|
||||
|
||||
test('嵌套结构递归处理', () {
|
||||
final Map<String, Object?> out = scrubMap(<String, Object?>{
|
||||
'user': <String, Object?>{'userId': 'u1', 'password': 'p'},
|
||||
'list': <Object?>[
|
||||
<String, Object?>{'refreshToken': 'r'},
|
||||
],
|
||||
});
|
||||
|
||||
final Map<String, Object?> user = out['user']! as Map<String, Object?>;
|
||||
expect(user['userId'], 'u1');
|
||||
expect(user['password'], redacted);
|
||||
final List<Object?> list = out['list']! as List<Object?>;
|
||||
expect((list.first! as Map<String, Object?>)['refreshToken'], redacted);
|
||||
});
|
||||
|
||||
test('原始 Map 不被修改', () {
|
||||
final Map<String, Object?> src = <String, Object?>{'token': 'x'};
|
||||
scrubMap(src);
|
||||
expect(src['token'], 'x');
|
||||
});
|
||||
|
||||
test('URL 去掉 query 和 fragment', () {
|
||||
expect(scrubUrl('https://h5.example.com/p?ticket=abc&x=1#frag'), 'https://h5.example.com/p');
|
||||
});
|
||||
|
||||
test('URL 解析失败时整条抹掉,而不是原样返回', () {
|
||||
expect(scrubUrl('http://[bad'), redacted);
|
||||
});
|
||||
});
|
||||
|
||||
group('LogBuffer', () {
|
||||
test('超出容量丢最旧的', () {
|
||||
final LogBuffer buffer = LogBuffer(capacity: 3);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
buffer.add(LogRecord(level: 'I', message: '$i', timestamp: DateTime(2026)));
|
||||
}
|
||||
expect(buffer.length, 3);
|
||||
expect(buffer.recent().map((LogRecord r) => r.message), <String>['2', '3', '4']);
|
||||
});
|
||||
|
||||
test('recent 默认只取 30 条', () {
|
||||
final LogBuffer buffer = LogBuffer();
|
||||
for (int i = 0; i < 500; i++) {
|
||||
buffer.add(LogRecord(level: 'I', message: '$i', timestamp: DateTime(2026)));
|
||||
}
|
||||
expect(buffer.length, 500);
|
||||
expect(buffer.recent().length, 30);
|
||||
expect(buffer.recent().first.message, '470');
|
||||
});
|
||||
});
|
||||
|
||||
group('LoggerAppLogger', () {
|
||||
AppEnv envOf(AppFlavor flavor) => AppEnv(
|
||||
flavor: flavor,
|
||||
apiBaseUrl: 'https://example.com',
|
||||
enableLog: true,
|
||||
sentryDsn: '',
|
||||
h5AllowedHosts: const <String>{},
|
||||
);
|
||||
|
||||
test('prod 只收 warning 及以上', () {
|
||||
final LogBuffer buffer = LogBuffer();
|
||||
final AppLogger log = LoggerAppLogger(env: envOf(AppFlavor.prod), buffer: buffer);
|
||||
|
||||
log
|
||||
..d('debug')
|
||||
..i('info')
|
||||
..w('warn')
|
||||
..e('error');
|
||||
|
||||
expect(buffer.recent().map((LogRecord r) => r.message), <String>['warn', 'error']);
|
||||
});
|
||||
|
||||
test('dev 收全部级别', () {
|
||||
final LogBuffer buffer = LogBuffer();
|
||||
LoggerAppLogger(env: envOf(AppFlavor.dev), buffer: buffer)
|
||||
..d('debug')
|
||||
..i('info');
|
||||
|
||||
expect(buffer.length, 2);
|
||||
});
|
||||
|
||||
test('结构化 data 进缓冲前已脱敏', () {
|
||||
final LogBuffer buffer = LogBuffer();
|
||||
LoggerAppLogger(
|
||||
env: envOf(AppFlavor.uat),
|
||||
buffer: buffer,
|
||||
).i('login', data: <String, Object?>{'phone': '13812345678'});
|
||||
|
||||
expect(buffer.recent().single.message, contains('138****5678'));
|
||||
expect(buffer.recent().single.message, isNot(contains('13812345678')));
|
||||
});
|
||||
});
|
||||
|
||||
group('throwTestException', () {
|
||||
AppEnv envOf(AppFlavor flavor) => AppEnv(
|
||||
flavor: flavor,
|
||||
apiBaseUrl: 'https://example.com',
|
||||
enableLog: false,
|
||||
sentryDsn: '',
|
||||
h5AllowedHosts: const <String>{},
|
||||
);
|
||||
|
||||
test('dev 抛测试异常', () {
|
||||
expect(() => throwTestException(envOf(AppFlavor.dev)), throwsA(isA<Exception>()));
|
||||
});
|
||||
|
||||
test('prod 拒绝调用', () {
|
||||
expect(() => throwTestException(envOf(AppFlavor.prod)), throwsA(isA<StateError>()));
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user