Skip to content

Conversation

@chrisbobbe
Copy link
Contributor

And a bugfix caught by one of the new tests!

I'm going down the list at #5188 (comment), and Greg's comment on CZO:

These do give us a reminder that it'd be good to have HTML snapshots testing those features of the message list, though:

  • reactions
  • polls
  • starred messages
  • muted senders

This PR does those HTML snapshots in those four bullet points, and most of this part of #5188 (comment):

And for within a given message:

  • Add/remove reactions to a message.

  • Update a poll's data.

  • Star/unstar a message.

  • Change a sender's name or avatar.

  • Mute/unmute a sender.

I haven't done "Change a sender's name or avatar" yet because I think we can't until #5208 settles.

@chrisbobbe
Copy link
Contributor Author

chrisbobbe commented Feb 9, 2022

Still to do are these:

  • Insert/delete the first message of a block that share a sender name/avatar, i.e. the message-full HTML-element that's followed by some message-brief HTML-elements.
  • Insert/delete all the messages of such a block, coming in between messages that would otherwise make up one such block, so that block splits/rejoins. Also between messages that wouldn't do that.
  • Similarly with a block of messages that have a common recipient, in between messages with some other common recipient, and also between messages with different recipients.
  • Similarly with a block of messages that have a common date. Inserting/deleting the first one (when there are more after it) will change which message the date header is associated with; inserting/deleting all of them will make the date header appear/disappear.

But I figured this much was a good amount to start with.

Copy link
Member

@gnprice gnprice left a comment

Choose a reason for hiding this comment

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

Great! I haven't yet read this all in detail, but generally it looks good. Small comments below from what I've read so far.

(Plus a longer comment that's a bit of a digression from this PR itself, more a thought for the next one and about other tests.)

|| oldBackgroundData.mutedUsers.get(oldElement.message.sender_id)
!== newBackgroundData.mutedUsers.get(newElement.message.sender_id)
Copy link
Member

Choose a reason for hiding this comment

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

Hmm, yeah, good catch!

In fact -- does this work correctly in the live code today? It looks to me like it probably doesn't:

  if (
    !isEqual(
      prevProps.messageListElementsForShownMessages,
      nextProps.messageListElementsForShownMessages,
    )
    || !equalFlagsExcludingRead(prevProps.backgroundData.flags, nextProps.backgroundData.flags)
  ) {
    uevents.push(updateContent(prevProps, nextProps));
  }

Not coincidentally, we don't really have tests for that bit of existing logic.

Copy link
Contributor Author

@chrisbobbe chrisbobbe Feb 11, 2022

Choose a reason for hiding this comment

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

Hmm, yeah, good catch!

You get the credit for this one: you asked for the test case that caught the bug! 😛

In fact -- does this work correctly in the live code today? It looks to me like it probably doesn't

Ha, right! We'll hope to switch to message-list diffing soon, right.

I could put in a fix in this deprecated live code—basically check for any change at all to the muted-users state—but maybe not, in case I introduce some regression while trying to do so?

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, yeah, good catch!

You get the credit for this one: you asked for the test case that caught the bug! 😛

:-)

In fact -- does this work correctly in the live code today? It looks to me like it probably doesn't

Ha, right! We'll hope to switch to message-list diffing soon, right.

I could put in a fix in this deprecated live code—basically check for any change at all to the muted-users state—but maybe not, in case I introduce some regression while trying to do so?

Yeah. For this PR I think just adding a TODO comment in the live code would be fine.

Comment on lines +816 to +817
// TODO(#5208): We haven't settled how we want to track name/avatar
test.todo("sender's name/avatar changed");
Copy link
Member

Choose a reason for hiding this comment

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

I haven't done "Change a sender's name or avatar" yet because I think we can't until #5208 settles.

Yeah, sounds good.

Comment on lines 593 to 598
// Should match realmEmojiReaction.
'80': {
deactivated: false,
code: '80',
name: 'github_parrot',
source_url: '/user_avatars/2/emoji/images/80.gif',
Copy link
Member

Choose a reason for hiding this comment

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

It's fine to rely on this kind of comment when necessary, but here I think we can straightforwardly encode that relationship in the code itself -- something like:

Suggested change
// Should match realmEmojiReaction.
'80': {
deactivated: false,
code: '80',
name: 'github_parrot',
source_url: '/user_avatars/2/emoji/images/80.gif',
[realmEmojiReaction.emoji_code]: {
deactivated: false,
code: realmEmojiReaction.emoji_code,
name: realmEmojiReaction.emoji_name,
source_url: `/user_avatars/2/emoji/images/${realmEmojiReaction.emoji_code}.gif`,

In the case of the source_url it's not really even necessary for us to mimic the shape of the actual URLs -- that isn't promised in the API, might vary, and we shouldn't rely on it. But I do kind of want it to be something that won't easily collide by accident with some other URL we'd make up (though even that probably shouldn't matter either), and this seems like an easy way to do that.

Comment on lines +838 to +850
check(
{
messages: [message],
backgroundData: {
...eg.backgroundData,
mutedUsers: Immutable.Map([[message.sender_id, 1644366787]]),
},
},
{
messages: [message],
backgroundData: { ...eg.backgroundData, mutedUsers: Immutable.Map() },
},
);
Copy link
Member

Choose a reason for hiding this comment

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

Seeing the test cases like this one, here's one thought that occurs to me. This idea isn't really a request for this PR -- I'd actually rather go ahead and merge a version of this PR close to how it currently is and then have this refactor come in the next PR.

I think that rather than have check take an old and a new BackgroundData value, it'd be better to have it take an old and a new PerAccountState, from which it would compute the BackgroundData.

One reason is that that would feel a bit more end-to-end -- I'd worry a bit less about a gap between what these tests are testing, and what we actually do as events come in and update our state.

In particular, we could factor out the selector MessageList uses for computing the BackgroundData, and export it only for tests, and call it from here. (I guess it would also need to take a GlobalSettings and a Debug, as well as a PerAccountState. But check could still take just the PerAccountState, and supply the other two because they're boring here.) But even if check were to basically copy-paste that chunk of MessageList.js, which looks like this:

    const backgroundData: BackgroundData = {
      alertWords: state.alertWords,
      allImageEmojiById: getAllImageEmojiById(state),
      auth: getAuth(state),

then I feel like that'd be an improvement; it'd mostly be pretty hard for a copy of that to become out of sync and wrong without the type-checker telling us so.

Then a further thing that that would enable is that because it'd make this test data closer to the form in which we actually construct and update the data, it'd let us construct it using that same code -- that is, we could construct it using the reducers, rather than with object literals and so on. (That's a direction you've seen me move in for other tests in some recent PRs.)

That would further enhance the end-to-end-ness of these tests. It'd also make it so that they don't have to change so much whenever we rearrange things in the state.

The ideal version might even be that each of these test cases sets up some state, then sets up the new state by hitting that not with one of our Redux actions but with a server event. That's the one really stable API that this all needs to work to, after all -- everything inward of that, we can freely refactor on a whim. But doing it with reducers is basically directly on the path to that, and doing it with state objects (however constructed) is in turn on the path to that, so for the next PR I'd be happy to see just switching from BackgroundData to state objects as the arguments passed to check.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool! I'm excited to go in that direction for the tests in a separate PR.

@chrisbobbe chrisbobbe force-pushed the pr-more-msglist-diffing-tests branch from 4ff7551 to d059496 Compare February 11, 2022 04:42
@chrisbobbe
Copy link
Contributor Author

Thanks for the review! Revision pushed.

@gnprice
Copy link
Member

gnprice commented Feb 17, 2022

Thanks for the revision!

All looks good, modulo adding one TODO comment in the existing code: #5225 (comment)

I'll go ahead and add that and merge. And then #5225 (comment) describes a direction for the next PR in this series, alongside adding more tests as you described near the top at #5225 (comment) .

chrisbobbe and others added 6 commits February 16, 2022 17:43
…nges

A new test (coming up) caught this bug. Yay, tests!
In the previous commit, we learned we weren't updating an existing
message list on an event saying that a user was muted or unmuted.

This had gone unnoticed in part because we don't have good
systematic tests for this logic in the existing code; we
discovered it on writing tests for the new message-list-diffing
logic.  (Thanks, tests!)

The other reason this had gone unnoticed is that it actually takes
a bit of a coincidence for you to have a message list open while
muting or unmuting someone -- because we don't actually have any
UI for doing so in the mobile app!  There's one existing TODO
comment related to that; give it a reference to the issue for this
feature, zulip#4655.
The order of the parameters can represent "new" and "old" just as
well as those words can, and this lets us save a few lines of code
(and maybe more, when we add new tests that'll do more interesting
things with background data).
As suggested by Greg at
  zulip#5188 (comment)

This caught the bug that we fixed in a recent commit (message
elements not updating when sender was muted/unmuted).
As suggested by Greg at
  https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/msglist-diffing.20tests/near/1320910

In particular:

- reactions
- polls
- starred messages (and all other flags in FlagsState)
- muted senders

I've gone ahead and removed the

  // TODO: Test with a variety of different things in
  // `backgroundData`.

-- not because I've thought hard enough to say we've exhausted every
possible thing we'd eventually want to test, but because this seems
like decent progress, and definitely a "variety" of things. :-) As
we do with all our tests, we'll naturally add more cases as we think
of them.
@gnprice gnprice force-pushed the pr-more-msglist-diffing-tests branch from d059496 to 942ff39 Compare February 17, 2022 01:57
@gnprice gnprice merged commit 942ff39 into zulip:main Feb 17, 2022
@chrisbobbe chrisbobbe deleted the pr-more-msglist-diffing-tests branch February 17, 2022 02:00
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Mar 10, 2022
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Mar 10, 2022
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Mar 10, 2022
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Mar 11, 2022
chrisbobbe added a commit to chrisbobbe/zulip-mobile that referenced this pull request Mar 15, 2022
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