Skip to content

Commit 5304045

Browse files
committed
Add utility functions and tests
This adds some utility functions for common functionality when working with config files. It also adds some super basic tests that tests those functionalities. These tests at present rely on the host to have the Steam snap installed with at least 1 game installed, and will modify the host's Steam configs. In the future this needs to be mocked instead.
1 parent 0cf8994 commit 5304045

File tree

4 files changed

+152
-33
lines changed

4 files changed

+152
-33
lines changed

packages/game_center/lib/steam/steam_model.dart

+49-4
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,31 @@ class SteamModel extends _$SteamModel {
4747
installLocation = install;
4848

4949
// global config
50+
final file = File(steamGlobalConfig(installLocation));
51+
globalConfig = vdfDecode(await file.readAsString());
52+
5053
final fileSystem = FileWatcher(steamGlobalConfig(installLocation));
5154
fileSystem.events.listen((event) async {
5255
switch (event.type) {
5356
case ChangeType.MODIFY:
5457
await updateGlobalConfig();
5558
}
5659
});
57-
final file = File(steamGlobalConfig(installLocation));
58-
globalConfig = vdfDecode(await file.readAsString());
5960

6061
// user configs
6162
final users = await listUserDirs();
6263
userConfigs = new Map();
6364
for (final steamID in users) {
65+
final file = File(steamUserConfig(installLocation, steamID));
66+
userConfigs[steamID] = vdfDecode(await file.readAsString());
67+
6468
final fileSystem = FileWatcher(steamUserConfig(installLocation, steamID));
6569
fileSystem.events.listen((event) async {
6670
switch (event.type) {
6771
case ChangeType.MODIFY:
6872
await updateUserConfig(steamID);
6973
}
7074
});
71-
final file = File(steamUserConfig(installLocation, steamID));
72-
userConfigs[steamID] = vdfDecode(await file.readAsString());
7375
}
7476

7577
return (
@@ -103,4 +105,47 @@ class SteamModel extends _$SteamModel {
103105
userConfigs: userConfigs,
104106
));
105107
}
108+
109+
/// Enable/disable Steam Play (Proton) for all titles globally. This is
110+
/// disabled by default on Steam for Linux, but enabled by default on Steam
111+
/// Deck.
112+
Future<void> enableSteamPlay(
113+
{required bool enable, String? protonVersion}) async {
114+
Map<String, dynamic> config = Map.from(globalConfig);
115+
if (enable) {
116+
config['InstallConfigStore']['Software']['Valve']['Steam']
117+
['CompatToolMapping']['0'] = {
118+
'name': protonVersion ?? 'proton_experimental',
119+
'config': '',
120+
'priority': '75'
121+
};
122+
} else {
123+
config['InstallConfigStore']['Software']['Valve']['Steam']
124+
['CompatToolMapping'] = {};
125+
}
126+
127+
final file = File(steamGlobalConfig(installLocation));
128+
await file.writeAsString(vdf.encode(config));
129+
}
130+
131+
/// Get a map of installed Steam apps for the given user.
132+
Future<Map<String, dynamic>> listApps({required String steamID}) async {
133+
Map<String, dynamic> config = Map.from(userConfigs[steamID]!);
134+
Map<dynamic, dynamic> apps =
135+
config['UserLocalConfigStore']['Software']['Valve']['Steam']['apps'];
136+
return apps.cast<String, dynamic>();
137+
}
138+
139+
/// Set the raw launch options for a specific app.
140+
Future<void> setGameLaunchOptions({
141+
required String steamID,
142+
required String appID,
143+
required String options,
144+
}) async {
145+
Map<String, dynamic> config = Map.from(userConfigs[steamID]!);
146+
config['UserLocalConfigStore']['Software']['Valve']['Steam']['apps'][appID]
147+
['LaunchOptions'] = options;
148+
final file = File(steamUserConfig(installLocation, steamID));
149+
await file.writeAsString(vdf.encode(config));
150+
}
106151
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:game_center/steam/steam_model.dart';
3+
4+
import 'test_utils.dart';
5+
6+
void main() {
7+
test('build', () async {
8+
final container = createContainer();
9+
final provider = steamModelProvider();
10+
final buildResult = await container.read(provider.future);
11+
12+
expect(buildResult.globalConfig, isNotEmpty);
13+
expect(buildResult.userConfigs, isNotEmpty);
14+
});
15+
16+
test('list users', () async {
17+
final container = createContainer();
18+
final model = container.read(steamModelProvider().notifier);
19+
await container.read(steamModelProvider().future);
20+
21+
expect(await model.listUserDirs(), isNotEmpty);
22+
});
23+
24+
test('enable Steam Play', () async {
25+
final container = createContainer();
26+
final model = container.read(steamModelProvider().notifier);
27+
await container.read(steamModelProvider().future);
28+
29+
model.enableSteamPlay(enable: false);
30+
expect(
31+
model.globalConfig['InstallConfigStore']['Software']['Valve']['Steam']
32+
['CompatToolMapping'],
33+
isEmpty,
34+
);
35+
36+
model.enableSteamPlay(enable: true);
37+
expect(
38+
model.globalConfig['InstallConfigStore']['Software']['Valve']['Steam']
39+
['CompatToolMapping'],
40+
isNotEmpty,
41+
);
42+
expect(
43+
model.globalConfig['InstallConfigStore']['Software']['Valve']['Steam']
44+
['CompatToolMapping']['0'],
45+
isNotEmpty,
46+
);
47+
});
48+
49+
test('list apps', () async {
50+
final container = createContainer();
51+
final model = container.read(steamModelProvider().notifier);
52+
await container.read(steamModelProvider().future);
53+
54+
final users = await model.listUserDirs();
55+
for (final user in users) {
56+
final apps = await model.listApps(steamID: user);
57+
expect(apps, isNotEmpty);
58+
}
59+
});
60+
61+
test('set launch options', () async {
62+
final container = createContainer();
63+
final model = container.read(steamModelProvider().notifier);
64+
await container.read(steamModelProvider().future);
65+
66+
final users = await model.listUserDirs();
67+
for (final user in users) {
68+
final apps = await model.listApps(steamID: user);
69+
model.setGameLaunchOptions(
70+
steamID: user,
71+
appID: apps.keys.toList()[0],
72+
options: '%command%',
73+
);
74+
expect(
75+
model.userConfigs[user]!['UserLocalConfigStore']['Software']['Valve']
76+
['Steam']['apps'][apps.keys.toList()[0]]['LaunchOptions'],
77+
equals('%command%'),
78+
);
79+
}
80+
});
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:riverpod/riverpod.dart';
3+
4+
/// A testing utility which creates a [ProviderContainer] and automatically
5+
/// disposes it at the end of the test.
6+
///
7+
/// https://riverpod.dev/docs/essentials/testing
8+
ProviderContainer createContainer({
9+
ProviderContainer? parent,
10+
List<Override> overrides = const [],
11+
List<ProviderObserver>? observers,
12+
}) {
13+
final container = ProviderContainer(
14+
parent: parent,
15+
overrides: overrides,
16+
observers: observers,
17+
);
18+
19+
addTearDown(container.dispose);
20+
21+
return container;
22+
}

packages/game_center/test/widget_test.dart

-29
This file was deleted.

0 commit comments

Comments
 (0)