- 
                Notifications
    You must be signed in to change notification settings 
- Fork 347
Respect realm setting for mandatory topics #1296
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
Conversation
ce0794e    to
    dce220f      
    Compare
  
    f0dccf5    to
    7c6e2ba      
    Compare
  
    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.
Thanks! Small comments below.
| Future<void> prepareComposeBox(WidgetTester tester, { | ||
| required Narrow narrow, | ||
| User? selfUser, | ||
| int? realmWaitingPeriodThreshold, | 
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.
Commit-message nit:
    compose test [nfc]: Remove unused prepareComposeBox param
    
    The parameter `realmWaitingPeriodThreshold` was added in
    commit 157418c26f003b783036dd5184364434cee7d197 but it was never used.
    
    Signed-off-by: Zixuan James Li <[email protected]>
For readability, I like use just the first 9 characters of a commit ID.
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.
Bump on truncating commit IDs to 9 characters :)
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.
Oops, missed that. Fixed!
        
          
                test/widgets/compose_box_test.dart
              
                Outdated
          
        
      | controller = tester.state<ComposeBoxState>(find.byType(ComposeBox)).controller; | ||
| } | ||
|  | ||
| Future<void> prepare(WidgetTester tester, { | 
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.
compose test [nfc]: Extract prepareComposeBox
In a file that's entirely about compose-box tests (compose_box_test.dart), and in the same scope (just at the top of the main method), it feels confusing to have one function named prepare and another named prepareComposeBox. If I were writing a test, I don't think I would know which function to use, except by reading their implementations.
How about instead of this refactor, we make prepare more flexible (if needed) so it can be used in the new tests?
        
          
                test/widgets/compose_box_test.dart
              
                Outdated
          
        
      | assert(store.streams.values.any((stream) => stream.streamId == streamId), | ||
| 'Add a channel with "streamId" the same as of $narrow.streamId to the store.'); | ||
| assert(store.users.values.any((user) => user.userId == account.userId), | ||
| 'Add an user with "userId" the same as of $account.userId to the store.'); | 
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: "a user"
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.
The assertion will be removed as account is replaced with zulipFeatureLevel.
        
          
                lib/widgets/compose_box.dart
              
                Outdated
          
        
      | PerAccountStore store; | ||
|  | ||
| // TODO: subscribe to this value: | ||
| // https://zulip.com/help/require-topics | 
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.
What's the condition for this existing TODO to be finished, and can we be more concrete about it? It looks like it's meant to be a TODO(#668), right? Does ComposeTopicController need to add a PerAccountStore listener?
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 ComposeTopicController need to add a PerAccountStore listener?
Right. We may include that as a part of #668 or its follow-up. This would be something for the future us to triage. I will update to mention the issue.
        
          
                lib/widgets/compose_box.dart
              
                Outdated
          
        
      | case ChannelNarrow(): | ||
| _controller = StreamComposeBoxController(); | ||
| final store = PerAccountStoreWidget.of(context); | ||
| _controller ??= StreamComposeBoxController(store: store); | 
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 the old value of _controller (if non-null) need to be dispose()d?
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 _controller shouldn't be disposed until the ComposeBox is disposed; we only set it once when initializing, and update its reference to the store if there is a new store.
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.
Ah right, I see; I read too fast and thought we were replacing the controller here, rather than updating its reference to the store.
| Updated the PR. Thanks for the review! | 
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.
Thanks! LGTM except some nits; I'll mark for Greg's review.
| Future<void> prepareComposeBox(WidgetTester tester, { | ||
| required Narrow narrow, | ||
| User? selfUser, | ||
| int? realmWaitingPeriodThreshold, | 
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.
Bump on truncating commit IDs to 9 characters :)
| required Narrow narrow, | ||
| User? selfUser, | ||
| List<User> users = const [], | ||
| List<User> otherUsers = const [], | 
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: the commit message says otherUser which doesn't match this name
da29ecb    to
    2e0e38a      
    Compare
  
    | Looks like CI is failing, and there are also a number of added commits that weren't in yesterday's revision of the branch. Are those meant for a later PR? | 
| Ahh yes. Those are for general chat (whose base is the tip of this PR). Pushed to fix this. | 
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.
Thanks both! Generally this all looks good. A few comments, mainly in the tests.
        
          
                test/example_data.dart
              
                Outdated
          
        
      | emojiset: Emojiset.google, | ||
| ), | ||
| userTopics: userTopics, | ||
| realmMandatoryTopics: realmMandatoryTopics ?? false, | 
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.
Probably true is the best default for test data — test data should be boring, and Zulip's behavior when a topic is empty/omitted is a lot more complicated (both before and after introducing "general chat") than the behavior of not allowing that.
        
          
                lib/widgets/compose_box.dart
              
                Outdated
          
        
      | _controller ??= StreamComposeBoxController(store: store); | ||
| (controller as StreamComposeBoxController).topic.store = store; | 
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.
Only one of these two lines does anything on a given call of this function, right? So this would probably be clearer as an if/else on whether the controller is null.
        
          
                lib/widgets/compose_box.dart
              
                Outdated
          
        
      | return _ComposeBoxContainer(body: null, errorBanner: errorBanner); | ||
| } | ||
|  | ||
| final controller = _controller!; | 
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 / handy pattern:
| final controller = _controller!; | |
| final controller = this.controller; | 
        
          
                test/widgets/compose_box_test.dart
              
                Outdated
          
        
      | checkMessageNotSent(tester); | ||
| }); | ||
|  | ||
| testWidgets('if topics are mandatory, reject (no topic)', (tester) 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.
nit:
| testWidgets('if topics are mandatory, reject (no topic)', (tester) async { | |
| testWidgets('if topics are mandatory, reject "(no topic)"', (tester) async { | 
Otherwise it reads like: "if topics are mandatory, reject. And by the way, no topic."
        
          
                test/widgets/compose_box_test.dart
              
                Outdated
          
        
      | testWidgets('empty topic -> (no topic)', (tester) async { | ||
| await setupAndTapSend(tester, topicInputText: ''); | 
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.
Regardless of the defaults in the example data, this test case should make explicit that it's setting realmMandatoryTopics to false — that's critical to understanding the intended behavior of the test.
To understand any given test case, the reader shouldn't have to look up any of the details in example_data.dart — any details that matter should be explicit in the test case.
        
          
                test/widgets/compose_box_test.dart
              
                Outdated
          
        
      | ..bodyFields.deepEquals({ | ||
| 'type': 'stream', | ||
| 'to': channel.streamId.toString(), | ||
| 'topic': '(no topic)', | ||
| 'content': 'test content', | ||
| 'read_by_sender': 'true', | ||
| }); | 
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.
Let's simplify this to focus on just the part that this test is about:
| ..bodyFields.deepEquals({ | |
| 'type': 'stream', | |
| 'to': channel.streamId.toString(), | |
| 'topic': '(no topic)', | |
| 'content': 'test content', | |
| 'read_by_sender': 'true', | |
| }); | |
| ..bodyFields['topic'].equals('(no topic)'); | 
(The .method and .url.path checks probably still belong, as they're part of confirming that the request was to the expected endpoint — effectively they provide the namespace that the parameter name 'topic' draws its meaning from.)
| Thanks for the review! The PR has been updated. | 
This covers some of the fields that can be inconsistent (`zulipFeatureLevel` in particular) when a test is not set up properly Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
The parameter `realmWaitingPeriodThreshold` was added in commit 157418c but it was never used. Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
| Thanks! Looks good; merging. | 
This tracks
mandatory_topicsfrom realm settings and set up the compose box to read it. This does not yet track for updates to the setting (that'd be #668, out-of-scope for this PR).This prepares for #1250.