-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[shared_preferences] Add shared preferences devtools #6749
base: main
Are you sure you want to change the base?
[shared_preferences] Add shared preferences devtools #6749
Conversation
packages/shared_preferences/shared_preferences/extension/devtools/.pubignore
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences/extension/devtools/config.yaml
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tools/pubspec.yaml
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tools/pubspec.yaml
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all the new dart files in this PR need the Flutter copyright:
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@kenzieschmoll Done, all the requested changes were applied. One thing that I'd like to do, though, is some integrations tests. I was exploring the devtools github repo and saw that you already have a devtools_test package, but it doesn't have the fixture tooling used in the Do you have plans of extracting this tooling to the |
3faacf4
to
4a4dca7
Compare
packages/shared_preferences/shared_preferences/extension/devtools/.pubignore
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/async_state.dart
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/pubspec.yaml
Outdated
Show resolved
Hide resolved
@stuartmorgan depending on the size of the app, maybe a minute or two? The build command builds the extensions flutter web app in release mode, and then copies the assets to the |
Adding a minute or two to the publish step is fine. We'll need to add repo tooling for packages to be able to specify a pre-publish hook, probably via a |
@kenzieschmoll and @stuartmorgan also the tests need to run with the flutter test --platform chrome |
We are not planning on publishing the You can use the integration test of the simulated environment in |
@stuartmorgan WRT to testing, is there a way to add an integration test hook to the CI? For example, the flutter/devtools CI has this code to run the flutter web integration tests for the devtools_extensions package: https://github.com/flutter/devtools/blob/master/tool/ci/bots.sh#L91-L94 |
It's possible to run arbitrary bespoke tests with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Done with first round of review on the extension content itself.
packages/shared_preferences/shared_preferences_tool/lib/main.dart
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/async_state.dart
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/shared_preferences_state.dart
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/shared_preferences_state.dart
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/shared_preferences_state.dart
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/ui/keys_panel.dart
Outdated
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/ui/keys_panel.dart
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/lib/src/ui/keys_panel.dart
Outdated
Show resolved
Hide resolved
...eferences/shared_preferences_tool/test/src/shared_preferences_state_notifier_test.mocks.dart
Show resolved
Hide resolved
packages/shared_preferences/shared_preferences_tool/web/favicon.png
Outdated
Show resolved
Hide resolved
…al/packages into add-shared-preferences-devtools
@kenzieschmoll and @stuartmorgan I can't make both I see two options here: 1 - Drop mockito altogether. WDYT? I'll start with |
@kenzieschmoll this PR is ready for review again. |
/// | ||
/// It is only visible for testing and eval. | ||
@visibleForTesting | ||
class DevtoolsExtension { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we rename this DevToolsExtensionDataProvider
or SharedPreferencesDevToolsExtensionData
or similar? This class name is very close to DevToolsExtension
, which is the wrapper widget from package:devtools_extensions
, which is a bit confusing.
Map<String, Object?> eventData, | ||
); | ||
|
||
/// A helper class that provides data to the devtool extension. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit r/devtools/DevTools
|
||
const String _eventPrefix = 'shared_preferences:'; | ||
|
||
/// A typedef for the post event function |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super-nit: period at the end of sentences
/// The default constructor for [DevtoolsExtension]. | ||
/// | ||
/// Accepts an optional [PostEvent] that should only be overwritten when testing. | ||
DevtoolsExtension([this._postEvent = developer.postEvent]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be a const constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question, just followed @sigmundch's suggestion. I'll try the const constructor to see if the web runner keeps the library.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be const, just changed it.
}); | ||
} | ||
|
||
/// Requests the value for a given key and post and event with the result. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: r/and event/an event. Also r/post/posts
}); | ||
} | ||
|
||
/// Requests the a value change for the give key and post an empty event when finished; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typos:
- remove first "a"
- r/give/given
- r/post/posts
- period at end of sentence instead of semi colon
final SharedPreferences legacyPrefs = | ||
await SharedPreferences.getInstance(); | ||
// we need to check the kind because sometimes a double | ||
// gets interpreted as an int. If this was not and issue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r/and/an
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dyslexia hitting hard 😬
// we'd only need to do a simple pattern matching on value. | ||
switch (kind) { | ||
case 'int': | ||
await legacyPrefs.setInt(key, value! as int); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will value
ever be null? if so, should we handle the null case instead of null asserting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not in the way it is implemented. There is no way to set it as null. The only option is removing it, but this is another method.
} else { | ||
final SharedPreferencesAsync prefs = SharedPreferencesAsync(); | ||
// we need to check the kind because sometimes a double | ||
// gets interpreted as an int. If this was not and issue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r/and/an
|
||
import '../shared_preferences.dart'; | ||
|
||
const String _eventPrefix = 'shared_preferences:'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: should this be shared_preferences.
instead of shared_preferences:
? Using dot is a more common convention for event names than using a colon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I copied this from somewhere, gonna change it to .
.
_postEvent('${_eventPrefix}change_value', <String, Object?>{}); | ||
} | ||
|
||
/// Requests a key removal and post an empty event when removed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: r/post/posts
); | ||
}); | ||
|
||
test('should request value from async api', () async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for this test case and the test below, can you include what type the value is in the test name so that the tests are easy to differentiate (like you did for the async api test below)? Also, it looks like we are only testing bool and int values for the legacy API. Should we be testing every type like you do for the async api below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're using the get
method in the requestValue
implementation, which returns a Object?
I thought that doing a test for each type would be redundant. But I see the value of doing a test for each type, we could check if the 'kind'
value is being set accordingly. I'll create a helper function and write tests for all types.
); | ||
}); | ||
|
||
test('should request value from async api', () async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider putting all legacy API tests in a testing group and all async API tests in a testing group
Future<void> _runCommand({ | ||
required String message, | ||
required String executable, | ||
required List<String> arguments, | ||
}) async { | ||
stdout.write(message); | ||
final Directory rootDir = Directory( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you rename this to sharedPreferencesToolParent
or similar so that it is clear that the .parent.parent
call is to walk up to the shared_preferences_tool parent? adding a comment could help too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! I was struggling to find a good name for this.
serviceManager.registerLifecycleCallback( | ||
ServiceManagerLifecycle.afterCloseVmService, | ||
(_) { | ||
setState(() {}); | ||
}, | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this have any implications when not using the simulated environment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gonna double check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just tested it again and we have no implications when running on the actual DevTools.
@@ -150,8 +162,8 @@ sealed class SharedPreferencesData implements _SharedPreferencesData<Object> { | |||
}; | |||
} | |||
|
|||
/// The type of the value formatted in a pretty way. | |||
String get prettyType { | |||
/// The kind of the value as string. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: "as a String."
import 'package:devtools_app_shared/service.dart'; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove unnecessary new line between package imports
|
||
late final StreamSubscription<Event> streamSubscription; | ||
streamSubscription = _service.onExtensionEvent.listen((Event event) { | ||
if (event.extensionKind == 'shared_preferences:$eventKind') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a comment describing where the event prefix and event kinds are defined
This PR adds the shared_preferences_tools package. This package user the devtools_extension tooling to create a tool for shared preferences. The idea of this PR came from @kenzieschmoll on this issue. Initially I've published this tool as a separate package, but this PR aims to bring the functionality to the main shared_preferences package. Once this PR gets merged I'll archive the
shared_preferences_tools
package.shared_preferences_tools.mp4
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.