Skip to content

Commit e71e838

Browse files
committed
Added some tests
1 parent 6ad7dfc commit e71e838

File tree

10 files changed

+241
-40
lines changed

10 files changed

+241
-40
lines changed

lib/config.dart

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0
44

5+
import 'package:dio/dio.dart';
6+
import 'package:dio/io.dart';
57
import 'package:fluent_ui/fluent_ui.dart';
68
import 'package:inference/utils.dart';
79
import 'dart:convert';
@@ -22,23 +24,51 @@ class Config {
2224
static String _proxy = '';
2325
static bool _proxyEnabled = false;
2426
static ThemeMode _mode = ThemeMode.system;
27+
static Envvars envvars = Envvars();
2528

2629
static String get proxy => _proxy;
27-
static set proxy(String value) {
30+
static setProxy(String value) async {
2831
_proxy = value;
29-
_save('proxy', value);
32+
await _save('proxy', value);
3033
}
3134

3235
static bool get proxyEnabled => _proxyEnabled;
33-
static set proxyEnabled(bool value) {
36+
static setProxyEnabled(bool value) async {
3437
_proxyEnabled = value;
35-
_save('proxyEnabled', value);
38+
await _save('proxyEnabled', value);
3639
}
3740

3841
static ThemeMode get themeMode => _mode;
39-
static set themeMode(ThemeMode value) {
42+
static setThemeMode(ThemeMode value) async {
4043
_mode = value;
41-
_save('mode', value.index);
44+
await _save('mode', value.index);
45+
}
46+
47+
static Future<String> _getProxy() async {
48+
final dio = Dio(BaseOptions(connectTimeout: const Duration(seconds: 10)));
49+
dio.httpClientAdapter = IOHttpClientAdapter(
50+
createHttpClient: () {
51+
final client = HttpClient();
52+
client.findProxy = (uri) {
53+
return "DIRECT";
54+
};
55+
return client;
56+
},
57+
);
58+
try {
59+
final response = await dio.get('http://wpad/wpad.dat');
60+
if (response.statusCode == 200) {
61+
return parseWpad(response.data);
62+
}
63+
} catch (e) {
64+
print(e.toString());
65+
}
66+
67+
final proxyEnv = envvars.proxy;
68+
if (proxyEnv.isNotEmpty) {
69+
return proxyEnv;
70+
}
71+
return '';
4272
}
4373

4474
static Future<void> loadFromFile() async {
@@ -51,7 +81,7 @@ class Config {
5181
if (json['proxy'] is String && json['proxy'].isNotEmpty) {
5282
_proxy = json['proxy'];
5383
} else if (_proxyEnabled) {
54-
_proxy = await getProxy();
84+
_proxy = await _getProxy();
5585
}
5686
_mode = ThemeMode.values[json['mode'] ?? 0];
5787
}
@@ -68,4 +98,5 @@ class Config {
6898
json[key] = value;
6999
await file.writeAsString(jsonEncode(json));
70100
}
71-
}
101+
102+
}

lib/pages/settings/settings.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ class _SettingsPageState extends State<SettingsPage> {
122122
ToggleSwitch(
123123
checked: Config.proxyEnabled,
124124
onChanged: (value) {
125-
setState(() {
126-
Config.proxyEnabled = value;
125+
setState(() async{
126+
await Config.setProxyEnabled(value);
127127
});
128128
},
129129
),
@@ -133,8 +133,8 @@ class _SettingsPageState extends State<SettingsPage> {
133133
child: TextBox(
134134
controller: _proxyController,
135135
placeholder: '<username>:<password>@<proxy>:<port>',
136-
onChanged: (value) {
137-
Config.proxy = value;
136+
onChanged: (value) async {
137+
Config.setProxy(value);
138138
},
139139
),
140140
),

lib/theme_fluent.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class AppTheme extends ChangeNotifier {
4949

5050
ThemeMode get mode => Config.themeMode;
5151
set mode(ThemeMode value) {
52-
Config.themeMode = value;
52+
Config.setThemeMode(value);
5353
notifyListeners();
5454
}
5555

lib/utils.dart

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,33 +37,6 @@ Dio dioClient() {
3737
return dio;
3838
}
3939

40-
Future<String> getProxy() async {
41-
final dio = Dio(BaseOptions(connectTimeout: const Duration(seconds: 10)));
42-
dio.httpClientAdapter = IOHttpClientAdapter(
43-
createHttpClient: () {
44-
final client = HttpClient();
45-
client.findProxy = (uri) {
46-
return "DIRECT";
47-
};
48-
return client;
49-
},
50-
);
51-
try {
52-
final response = await dio.get('http://wpad/wpad.dat');
53-
if (response.statusCode == 200) {
54-
return parseWpad(response.data);
55-
}
56-
} catch (e) {
57-
print(e.toString());
58-
}
59-
60-
final proxyEnv = Platform.environment['https_proxy'] ?? Platform.environment['HTTPS_PROXY'] ?? Platform.environment['http_proxy'] ?? Platform.environment['HTTP_PROXY'];
61-
if (proxyEnv != null) {
62-
return proxyEnv;
63-
}
64-
return '';
65-
}
66-
6740
String parseWpad(String wpad) {
6841
final regex = RegExp(r'return\s+"PROXY ([^"]+)";');
6942
final matches = regex.allMatches(wpad);
@@ -126,4 +99,14 @@ extension StringExtensions on String {
12699
if (isEmpty) return this;
127100
return "${this[0].toUpperCase()}${substring(1)}";
128101
}
102+
}
103+
104+
class Envvars {
105+
String get proxy {
106+
final proxyEnv = Platform.environment['https_proxy'] ?? Platform.environment['HTTPS_PROXY'] ?? Platform.environment['http_proxy'] ?? Platform.environment['HTTP_PROXY'];
107+
if (proxyEnv != null) {
108+
return proxyEnv;
109+
}
110+
return '';
111+
}
129112
}

pubspec.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,14 @@ packages:
641641
url: "https://pub.dev"
642642
source: hosted
643643
version: "1.0.6"
644+
mocktail:
645+
dependency: "direct dev"
646+
description:
647+
name: mocktail
648+
sha256: "890df3f9688106f25755f26b1c60589a92b3ab91a22b8b224947ad041bf172d8"
649+
url: "https://pub.dev"
650+
source: hosted
651+
version: "1.0.4"
644652
msix:
645653
dependency: "direct dev"
646654
description:

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ dev_dependencies:
8585
path_provider_platform_interface: ^2.1.2
8686
plugin_platform_interface: ^2.1.8
8787
build_runner: ^2.4.13
88+
mocktail: ^1.0.4
8889

8990
# For information on the generic Dart part of this file, see the
9091
# following page: https://dart.dev/tools/pub/pubspec

test/config_test.dart

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import 'package:fluent_ui/fluent_ui.dart';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:inference/config.dart';
4+
import 'package:mocktail/mocktail.dart';
5+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
6+
7+
import 'mocks.dart';
8+
import 'utils.dart';
9+
10+
void main() {
11+
late MockEnvvars envvars;
12+
13+
setUpAll(() {
14+
envvars = MockEnvvars();
15+
PathProviderPlatform.instance = FakePathProviderPlatform();
16+
});
17+
18+
setUp(() async {
19+
await deleteConfigFile();
20+
});
21+
22+
test('Config proxy settings', () async {
23+
await Config.setProxy('http://proxy.example.com:8080');
24+
expect(Config.proxy, 'http://proxy.example.com:8080');
25+
26+
await Config.setProxyEnabled(true);
27+
expect(Config.proxyEnabled, true);
28+
29+
await Config.setProxyEnabled(false);
30+
expect(Config.proxyEnabled, false);
31+
});
32+
33+
test('Config theme mode', () async {
34+
await Config.setThemeMode(ThemeMode.dark);
35+
expect(Config.themeMode, ThemeMode.dark);
36+
37+
await Config.setThemeMode(ThemeMode.light);
38+
expect(Config.themeMode, ThemeMode.light);
39+
40+
await Config.setThemeMode(ThemeMode.system);
41+
expect(Config.themeMode, ThemeMode.system);
42+
});
43+
44+
test('Config load and save', () async {
45+
expect(Config.proxyEnabled, false);
46+
expect(Config.proxy, '');
47+
expect(Config.themeMode, ThemeMode.system);
48+
49+
await Config.setProxy('http://proxy.example.com:8080');
50+
await Config.setProxyEnabled(true);
51+
await Config.setThemeMode(ThemeMode.dark);
52+
53+
await Config.loadFromFile();
54+
expect(Config.proxy, 'http://proxy.example.com:8080');
55+
expect(Config.proxyEnabled, true);
56+
expect(Config.themeMode, ThemeMode.dark);
57+
});
58+
59+
test('Load proxy from envvar', () async {
60+
const proxy = 'http://proxy.foo.bar:8080';
61+
when(() => envvars.proxy).thenReturn(proxy);
62+
Config.envvars = envvars;
63+
64+
await Config.loadFromFile();
65+
expect(Config.proxy, '');
66+
67+
await Config.setProxyEnabled(true);
68+
await Config.loadFromFile();
69+
expect(Config.proxy, proxy);
70+
});
71+
}

test/mocks.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2024 Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
import 'package:inference/utils.dart';
6+
import 'package:mocktail/mocktail.dart';
7+
8+
class MockEnvvars extends Mock implements Envvars {}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:fluent_ui/fluent_ui.dart';
3+
import 'package:inference/config.dart';
4+
import 'package:inference/pages/settings/settings.dart';
5+
import 'package:inference/theme_fluent.dart';
6+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
7+
import 'package:provider/provider.dart';
8+
9+
import '../../mocks.dart';
10+
import '../../utils.dart';
11+
12+
13+
void main() {
14+
setUpAll(() {
15+
PathProviderPlatform.instance = FakePathProviderPlatform();
16+
});
17+
18+
setUp(() async {
19+
await deleteConfigFile();
20+
});
21+
22+
testWidgets('SettingsPage displays and updates theme mode', (WidgetTester tester) async {
23+
final appTheme = AppTheme();
24+
await tester.pumpWidget(
25+
ChangeNotifierProvider<AppTheme>(
26+
create: (_) => appTheme,
27+
child: const FluentApp(
28+
home: SettingsPage(),
29+
),
30+
),
31+
);
32+
33+
expect(find.text('Appearance'), findsOneWidget);
34+
expect(find.text('Select the color theme for the application.'), findsOneWidget);
35+
36+
await tester.tap(find.byType(ComboBox<ThemeMode>));
37+
await tester.pumpAndSettle();
38+
39+
await tester.tap(find.text('Dark').first);
40+
await tester.pumpAndSettle();
41+
42+
expect(appTheme.mode, ThemeMode.dark);
43+
});
44+
45+
testWidgets('SettingsPage displays and updates proxy settings', (WidgetTester tester) async {
46+
await tester.pumpWidget(
47+
MultiProvider(
48+
providers: [
49+
ChangeNotifierProvider<AppTheme>(create: (_) => AppTheme()),
50+
],
51+
child: const FluentApp(
52+
home: SettingsPage(),
53+
),
54+
),
55+
);
56+
57+
expect(find.text('HTTPS Proxy'), findsOneWidget);
58+
expect(find.text('Configure the proxy settings for network connections. Leave empty to auto-configure.'), findsOneWidget);
59+
60+
await tester.tap(find.byType(ToggleSwitch));
61+
await tester.pumpAndSettle();
62+
63+
expect(Config.proxyEnabled, true);
64+
65+
await tester.enterText(find.byType(TextBox), 'http://proxy.example.com:8080');
66+
await tester.pumpAndSettle();
67+
68+
expect(Config.proxy, 'http://proxy.example.com:8080');
69+
});
70+
}

test/utils.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) 2024 Intel Corporation
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
import 'dart:io';
6+
7+
import 'package:path_provider/path_provider.dart';
8+
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
9+
10+
class FakePathProviderPlatform extends PathProviderPlatform {
11+
@override
12+
Future<String?> getApplicationSupportPath() async {
13+
const path = 'com.openvino.console.TestDir';
14+
final fullPath = '${Directory.systemTemp.path}/$path';
15+
final directory = Directory(fullPath);
16+
if (!(await directory.exists())) {
17+
await directory.create(recursive: true);
18+
}
19+
return fullPath;
20+
}
21+
}
22+
23+
Future<void> deleteConfigFile() async {
24+
final directory = await getApplicationSupportDirectory();
25+
final file = File('${directory.path}/config.json');
26+
if (await file.exists()) {
27+
await file.delete();
28+
}
29+
}

0 commit comments

Comments
 (0)