mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-10-06 16:07:03 +02:00
first working version
This commit is contained in:
1 parent
c95171a3ad
commit
54ef1b8afc
26 files changed
+745
-27
No files matched your search
@@ -0,0 +1,164 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
|
||||
import 'package:deflockapp/services/osm_block_service.dart';
|
||||
import 'package:deflockapp/state/settings_state.dart';
|
||||
|
||||
void main() {
|
||||
group('OSMBlockService', () {
|
||||
test('returns null in simulate mode without making a request', () async {
|
||||
var requested = false;
|
||||
final client = MockClient((request) async {
|
||||
requested = true;
|
||||
return http.Response('{"user_blocks":[]}', 200);
|
||||
});
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.simulate,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
expect(requested, isFalse);
|
||||
});
|
||||
|
||||
test('returns null when access token is null', () async {
|
||||
final client = MockClient((request) async => http.Response('{"user_blocks":[]}', 200));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: null,
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('returns null when access token is empty', () async {
|
||||
final client = MockClient((request) async => http.Response('{"user_blocks":[]}', 200));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: '',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('returns false when user_blocks is empty', () async {
|
||||
final client = MockClient((request) async => http.Response('{"user_blocks":[]}', 200));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isFalse);
|
||||
});
|
||||
|
||||
test('returns true when user_blocks is non-empty', () async {
|
||||
final client = MockClient((request) async => http.Response(
|
||||
'{"user_blocks":[{"id":101,"needs_view":true}]}',
|
||||
200,
|
||||
));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isTrue);
|
||||
});
|
||||
|
||||
test('sends the request to the correct production host with auth header', () async {
|
||||
Uri? capturedUri;
|
||||
String? capturedAuth;
|
||||
final client = MockClient((request) async {
|
||||
capturedUri = request.url;
|
||||
capturedAuth = request.headers['Authorization'];
|
||||
return http.Response('{"user_blocks":[]}', 200);
|
||||
});
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
await service.checkActiveBlock(
|
||||
accessToken: 'my-token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(capturedUri?.host, 'api.openstreetmap.org');
|
||||
expect(capturedUri?.path, '/api/0.6/user/blocks/active.json');
|
||||
expect(capturedAuth, 'Bearer my-token');
|
||||
});
|
||||
|
||||
test('sends the request to the sandbox host in sandbox mode', () async {
|
||||
Uri? capturedUri;
|
||||
final client = MockClient((request) async {
|
||||
capturedUri = request.url;
|
||||
return http.Response('{"user_blocks":[]}', 200);
|
||||
});
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
await service.checkActiveBlock(
|
||||
accessToken: 'my-token',
|
||||
uploadMode: UploadMode.sandbox,
|
||||
);
|
||||
|
||||
expect(capturedUri?.host, 'api06.dev.openstreetmap.org');
|
||||
});
|
||||
|
||||
test('returns null on non-200 response', () async {
|
||||
final client = MockClient((request) async => http.Response('Unauthorized', 401));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('returns null on malformed JSON response', () async {
|
||||
final client = MockClient((request) async => http.Response('not json', 200));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('returns null when user_blocks field is missing', () async {
|
||||
final client = MockClient((request) async => http.Response('{}', 200));
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
|
||||
test('returns null when the client throws (e.g. no network)', () async {
|
||||
final client = MockClient((request) async {
|
||||
throw Exception('network error');
|
||||
});
|
||||
final service = OSMBlockService(client: client);
|
||||
|
||||
final result = await service.checkActiveBlock(
|
||||
accessToken: 'token',
|
||||
uploadMode: UploadMode.production,
|
||||
);
|
||||
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/testing.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:deflockapp/services/osm_block_service.dart';
|
||||
import 'package:deflockapp/state/account_block_state.dart';
|
||||
import 'package:deflockapp/state/settings_state.dart';
|
||||
|
||||
void main() {
|
||||
setUp(() {
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
});
|
||||
|
||||
group('AccountBlockState', () {
|
||||
test('defaults to not blocked before init()', () {
|
||||
final state = AccountBlockState();
|
||||
expect(state.isBlocked, isFalse);
|
||||
});
|
||||
|
||||
test('init() loads persisted blocked state for the given upload mode', () async {
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'account_blocked_production': true,
|
||||
});
|
||||
|
||||
final state = AccountBlockState();
|
||||
await state.init(UploadMode.production);
|
||||
|
||||
expect(state.isBlocked, isTrue);
|
||||
});
|
||||
|
||||
test('init() defaults to false when nothing is persisted', () async {
|
||||
final state = AccountBlockState();
|
||||
await state.init(UploadMode.production);
|
||||
|
||||
expect(state.isBlocked, isFalse);
|
||||
});
|
||||
|
||||
test('init() is scoped per upload mode', () async {
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'account_blocked_production': true,
|
||||
});
|
||||
|
||||
final state = AccountBlockState();
|
||||
await state.init(UploadMode.sandbox);
|
||||
|
||||
expect(state.isBlocked, isFalse);
|
||||
});
|
||||
|
||||
test('check() updates and persists state on a conclusive true result', () async {
|
||||
final client = MockClient((request) async => http.Response(
|
||||
'{"user_blocks":[{"id":1}]}',
|
||||
200,
|
||||
));
|
||||
final state = AccountBlockState(blockService: OSMBlockService(client: client));
|
||||
await state.init(UploadMode.production);
|
||||
|
||||
final result = await state.check(accessToken: 'token', uploadMode: UploadMode.production);
|
||||
|
||||
expect(result, isTrue);
|
||||
expect(state.isBlocked, isTrue);
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
expect(prefs.getBool('account_blocked_production'), isTrue);
|
||||
});
|
||||
|
||||
test('check() updates and persists state on a conclusive false result', () async {
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'account_blocked_production': true,
|
||||
});
|
||||
final client = MockClient((request) async => http.Response('{"user_blocks":[]}', 200));
|
||||
final state = AccountBlockState(blockService: OSMBlockService(client: client));
|
||||
await state.init(UploadMode.production);
|
||||
expect(state.isBlocked, isTrue);
|
||||
|
||||
final result = await state.check(accessToken: 'token', uploadMode: UploadMode.production);
|
||||
|
||||
expect(result, isFalse);
|
||||
expect(state.isBlocked, isFalse);
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
expect(prefs.getBool('account_blocked_production'), isFalse);
|
||||
});
|
||||
|
||||
test('check() leaves state unchanged on an inconclusive (null) result', () async {
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'account_blocked_production': true,
|
||||
});
|
||||
final client = MockClient((request) async {
|
||||
throw Exception('offline');
|
||||
});
|
||||
final state = AccountBlockState(blockService: OSMBlockService(client: client));
|
||||
await state.init(UploadMode.production);
|
||||
expect(state.isBlocked, isTrue);
|
||||
|
||||
final result = await state.check(accessToken: 'token', uploadMode: UploadMode.production);
|
||||
|
||||
expect(result, isNull);
|
||||
expect(state.isBlocked, isTrue); // unchanged
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
expect(prefs.getBool('account_blocked_production'), isTrue); // unchanged
|
||||
});
|
||||
|
||||
test('clear() resets in-memory blocked state', () async {
|
||||
SharedPreferences.setMockInitialValues({
|
||||
'account_blocked_production': true,
|
||||
});
|
||||
final state = AccountBlockState();
|
||||
await state.init(UploadMode.production);
|
||||
expect(state.isBlocked, isTrue);
|
||||
|
||||
state.clear();
|
||||
|
||||
expect(state.isBlocked, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user