Skip to content

Survey handler feature #109

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

Merged
merged 35 commits into from
Aug 3, 2023
Merged

Survey handler feature #109

merged 35 commits into from
Aug 3, 2023

Conversation

eliasyishak
Copy link
Contributor

Reference issue tracker:


  • I’ve reviewed the contributor guide and applied the relevant portions to this PR.
Contribution guidelines:

Note that many Dart repos have a weekly cadence for reviewing PRs - please allow for some latency before initial review feedback.

* Add constant for endpoint that stores metadata json file

* Development began on survey handler class with fetch

* Update survey_handler.dart

* Parsing functionality added in `survey_handler`

* Condition class `operator` relabeled to `operatorString`

* `Analytics` test and default constructors to use `SurveyHandler`

* Refactor + cleanup + error handling

* `dart format` fix

* Evaluating functionality added to `Analytics`

* Format fix

* `!=` operator added to `Condition` class

* Refactor for fake survey handler to use list of surveys or string

* Initial test cases added

* Tests added to use json in `FakeSurveyHandler`

* Fix nit

* Early exit if on null `logFileStats`

* Test to check each field in `Survey` and `Condition`

* Documentation update
* Check `okToSend` before fetching surveys

* Added test

* dart format fix

* Update CHANGELOG.md
@eliasyishak eliasyishak closed this Jun 1, 2023
@eliasyishak eliasyishak reopened this Jun 1, 2023
* Sampling rate functionality added

* Update tests to have 100% sampling rate

* Tests added to test sampling rate

* Update survey_handler_test.dart

* Fix type for `jsonDecode`

* New utility function to convert string into integer

* Fix tests with new outputs for sample rate

* Use uniqueId for survey instead of description

* Add hyphen to lookup

* Fix documentation
* Add constant for new file name + clean up session handler

Removing NoOp session instance since that was only being used before `2.0.0`

* Updating survey handler to create file to persist ids

* Revert changes to session handler

* Update constant to be a json file

* Initialize dismiss surveys file with empty json

* Initializer for dismissed file made static

* Functionality added to check if survey snoozed or dismissed

* Dismiss functionality added

* `dismissForDays` -> `dismissForMinutes`

* Update survey_handler_test.dart

* Clean up external functions to be class methods

* Tests added for snoozing and dismissing permanently

* Test added for malformed json

* Check sample rate before using LogFileStats

* Add `surveyShown` API to snooze surveys

* Use new URL for survey metadata

* Error handling for missing json file
* Added example file

* Including example's output in code

* Update sample_rate.dart

* Fix nits
* Added enum and event constructor survey actions

* Fix format errors

* Using two events for survey shown and survey action

* Created mock class to confirm events are sent

* Clean up constructors

* Fix nits
* Added newe `SurveyButton` class

* Fix tests

* Add documentation for enums

* Update sample_rate.dart

* Update tests to check for `SurveyButton` classes

* Remove enum for status of action

* Use `snoozeForMinutes` instead of dismiss

* Expose `SurveyButton`

* Fixing documentation for event class

* Order members in survey handler

* Refactor to pass button to `surveyInteracted(..)`

* `surveyButtonList` --> `buttonList` renaming

* Adding example file for how to use survey handler feature

* Adding conditional check for url to display
@eliasyishak eliasyishak marked this pull request as ready for review August 2, 2023 14:10
@eliasyishak eliasyishak changed the title [wip] Survey handler feature Survey handler feature Aug 2, 2023
Only checking if `logFileStats` is null if there is a condition in the condition array in the json
@eliasyishak
Copy link
Contributor Author

@christopherfujino the new example files should provide a general workflow for this new feature if you want to start there. And thank you! 😁

@github-actions
Copy link

github-actions bot commented Aug 2, 2023

Package publishing

Package Version Status Publish tag (post-merge)
package:unified_analytics 3.1.0 ready to publish unified_analytics-v3.1.0
package:extension_discovery 1.0.0 already published at pub.dev
package:cli_config 0.1.1 already published at pub.dev
package:graphs 2.3.2-wip pre-release version (no publish necessary)

Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

//
// Test with your own seed and alter other parameters
// as needed
final uuidGenerator = Uuid(123);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually think we should ONLY be providing hard-coded seeds for tests that we expect to be deterministic.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually not for the tests, it's meant to be repeatable because I include the stdout when running the script to demonstrate that the sampling rate is working as expected

Example of the run below

// Output from run above with set parameters
//
// '''
// Test sample rate = 0.3
// Number of iterations = 10000
// ---

// Count of iterations sampled (successes) = 3046
// Actual sample rate = 0.3046
// ---

// Runtime = 8ms
// '''

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added documentation to the top of the example file that should make it clearer

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assume example code would be copy pasted, and best practices.

@@ -204,6 +214,15 @@ abstract class Analytics {
/// that need to be sent off
void close();

/// Method to fetch surveys from the specified endpoint [kContextualSurveyUrl]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and throughout, dartdocs should be complete sentences with periods at the end: https://dart.dev/effective-dart/documentation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have this captured in this issue

that will be a large diff so didn't want to add noise here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you adding more dartdocs that you'll need to update later though?

// [Survey.conditionList]
var conditionsMet = 0;
for (final condition in survey.conditionList) {
if (logFileStats == null) continue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't we check for this outside this for loop, and if so skip the entire loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea, i'll wrap the loop in the loop instead

await withClock(Clock.fixed(DateTime(2023, 3, 3, 12, 0)), () async {
// Use a memory file system to repeatedly run this example
// file with the test instance
fs = MemoryFileSystem.test(style: FileSystemStyle.posix);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these examples to demonstrate how to use the package, or are they test code? I'm guessing we wouldn't want someone to copy paste this to their production code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are meant to demonstrate how to use the package.. and that is correct we don't want anyone to copy and paste this into production code.

I will add more documentation at the top to indicate that this file is meant to be used for guidance

// that fail to parse
try {
return Survey.fromJson(element as Map<String, dynamic>);
// ignore: avoid_catches_without_on_clauses
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than ignoring this, can you catch a more specific exception you're expecting? I'm guessing TypeError?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I try to do the following

        try {
          element as Map<String, dynamic>;
          element.remove('startDate');
          return Survey.fromJson(element);
        } on TypeError {
          return null;
        }

I get the following lint message

The type 'TypeError' should not be caught
because it is a subclass of 'Error'. (avoid_catching_errors)

(https://dart.dev/lints/avoid_catching_errors)

What's the best approach for catching type errors? I can add the // ignore: avoid_catching_errors line to prevent this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think it's better to ignore that lint than to catch everything.

Copy link
Contributor

@christopherfujino christopherfujino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM provided you catch TypeError and // ignore: avoid_catching_errors

@eliasyishak eliasyishak merged commit 921611a into main Aug 3, 2023
@eliasyishak eliasyishak deleted the survey-handler-feature branch August 3, 2023 19:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants