Skip to content

Conversation

@psybuzz
Copy link
Contributor

@psybuzz psybuzz commented Oct 6, 2020

Diffbase: #4220

When cards are pinned/un-pinned in Time Series, their
state is now reflected in the URL, while the user is on a
route of kind EXPERIMENT or COMPARE_EXPERIMENTS.

Pinned cards will persist across tab reloads. This behavior
can be configured per-route via updating the use of
CoreDeepLinkProvider.

Googlers, see test sync cl/335898836

@psybuzz psybuzz marked this pull request as ready for review October 6, 2020 22:21
@psybuzz psybuzz force-pushed the psybuzz-urlpins3 branch 3 times, most recently from d4be201 to 86c18d3 Compare October 7, 2020 17:28
Base automatically changed from psybuzz-urlpins2 to master October 13, 2020 00:54
@psybuzz psybuzz force-pushed the psybuzz-urlpins3 branch 2 times, most recently from b045107 to f2938c0 Compare October 13, 2020 19:22
@psybuzz psybuzz marked this pull request as draft October 13, 2020 20:56
@psybuzz psybuzz marked this pull request as ready for review October 16, 2020 00:10
@psybuzz psybuzz requested a review from bmd3k October 16, 2020 00:10
});

describe('getUnresolvedImportedPinnedCards', () => {
it('returns false if no card exists', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

test description is incorrect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, done.


const state = appStateFromMetricsState(
buildMetricsState({
unresolvedImportedPinnedCards: [
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd feel a little more confident about the test if there were multiple pinned cards. Can that be done without getting too verbose?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, the test does cover 2 unresolved pinned cards here, so no action needed iiuc.

let pinnedCards = null;
for (const {key, value} of queryParams) {
if (key === 'pinnedCards') {
pinnedCards = pinnedCards || extractPinnedCardsFromURLText(value);
Copy link
Contributor

Choose a reason for hiding this comment

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

Trying to understand why this isn't written as:

if (key === 'pinnedCards') {
  pinnedCards = extractPinnedCardsFromUrlText(value);
  break;
}

Is it because you're trying to gracefully handle scenarios where pinnedCards appears multiple times but the first appearance is somehow malformed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, the intent was only to take the first instance, in case there are multiple.

I can switch to use break if that reads better.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes I think it would read and behave better if we used break;. As written it did cause a bit of head scratching.

const result = [];
for (const item of object) {
// Validate types.
const isPluginString = typeof item.plugin === 'string';
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: For consistency should one of isRunString or isTagTypeValid be renamed? They do the same check but are named differently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

if (!item.tag) {
continue;
}
if (isRunString && (!item.runId || !isSingleRunPlugin(item.plugin))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm having a little bit of a hard time following what is happening on this line. I think it is two different error cases?

  1. runId is specified but is empty
  2. runId is specified and is non-empty but the plugin does not support runId being specified because it assumes multiple runs?

Maybe refactor and/or add a comment?

(On the other hand, the validation for sampleNumber is a bit more verbose but easier to read).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, these are 2 cases. Refactored a bit with comments.

});
});

it('sanitizes pinned cards on deserialization', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

My preference would be that each of these is there own test case for several reasons: It's best practice to avoid control structures in tests; A particular test failure would be easier to identify by line number; tests would be easier to debug (wouldn't have to wait for any particular test cases's turn in the for loop).

It wouldn't be very much more verbose, if at all.

Copy link
Contributor

Choose a reason for hiding this comment

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

But I see now this exact use case ("data-driven testing") is the one exception to the advice not to avoid control structures in testing:

go/unit-test-practices?polyglot=java#control-structures

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 think the current pattern fits "data-driven testing", though I can see why we'd want to split them up if the test had even a bit more complexity. Will keep as is, but I'll keep this in mind in the future.

@psybuzz psybuzz merged commit 60ade15 into master Oct 22, 2020
@psybuzz psybuzz deleted the psybuzz-urlpins3 branch October 22, 2020 01:16
psybuzz added a commit that referenced this pull request Oct 22, 2020
Diffbase: #4221
Followup: #4245

Introduces an alert snackbar UI, which surfaces application
errors to the user in the corner of the screen.

App, feature modules may now register actions that trigger
an alert on screen:

```
AlertActionModule.registerActionAlerts([
  {localizedMessage: "Fetch failed"},
  ...
])
```

This change hides away the composite action using Angular's
DI framework. The actions that should trigger alerts are registered
once, and are dispatched by the AlertEffects, rather than specific
features.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants