Skip to content
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

Respect realm setting for mandatory topics #1296

Merged
merged 5 commits into from
Jan 30, 2025
Merged

Conversation

PIG208
Copy link
Member

@PIG208 PIG208 commented Jan 21, 2025

This tracks mandatory_topics from 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.

@PIG208 PIG208 added the a-compose Compose box, autocomplete, attaching files/images label Jan 21, 2025
@PIG208 PIG208 force-pushed the pr-mandatory branch 3 times, most recently from ce0794e to dce220f Compare January 21, 2025 23:27
@PIG208 PIG208 requested a review from chrisbobbe January 21, 2025 23:27
@PIG208 PIG208 added the maintainer review PR ready for review by Zulip maintainers label Jan 22, 2025
@PIG208 PIG208 mentioned this pull request Jan 22, 2025
@PIG208 PIG208 force-pushed the pr-mandatory branch 2 times, most recently from f0dccf5 to 7c6e2ba Compare January 23, 2025 17:35
Copy link
Collaborator

@chrisbobbe chrisbobbe left a 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.

@@ -44,7 +44,6 @@ void main() {
Future<void> prepareComposeBox(WidgetTester tester, {
required Narrow narrow,
User? selfUser,
int? realmWaitingPeriodThreshold,
Copy link
Collaborator

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.

Copy link
Collaborator

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 :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, missed that. Fixed!

@@ -75,6 +62,25 @@ void main() {
controller = tester.state<ComposeBoxState>(find.byType(ComposeBox)).controller;
}

Future<void> prepare(WidgetTester tester, {
Copy link
Collaborator

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?

@@ -48,6 +48,8 @@ void main() {
if (narrow case ChannelNarrow(:var streamId) || TopicNarrow(: var streamId)) {
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.');
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: "a user"

Copy link
Member Author

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.

_update();
}

PerAccountStore store;

// TODO: subscribe to this value:
// https://zulip.com/help/require-topics
Copy link
Collaborator

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?

Copy link
Member Author

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.

switch (widget.narrow) {
case ChannelNarrow():
_controller = StreamComposeBoxController();
final store = PerAccountStoreWidget.of(context);
_controller ??= StreamComposeBoxController(store: store);
Copy link
Collaborator

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?

Copy link
Member Author

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.

Copy link
Collaborator

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.

@PIG208
Copy link
Member Author

PIG208 commented Jan 27, 2025

Updated the PR. Thanks for the review!

Copy link
Collaborator

@chrisbobbe chrisbobbe left a 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.

@@ -44,7 +44,6 @@ void main() {
Future<void> prepareComposeBox(WidgetTester tester, {
required Narrow narrow,
User? selfUser,
int? realmWaitingPeriodThreshold,
Copy link
Collaborator

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 :)

List<User> users = const [],
List<User> otherUsers = const [],
Copy link
Collaborator

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

@chrisbobbe chrisbobbe requested a review from gnprice January 28, 2025 20:29
@chrisbobbe chrisbobbe assigned gnprice and unassigned gnprice Jan 28, 2025
@chrisbobbe chrisbobbe added integration review Added by maintainers when PR may be ready for integration and removed maintainer review PR ready for review by Zulip maintainers labels Jan 28, 2025
@PIG208 PIG208 force-pushed the pr-mandatory branch 2 times, most recently from da29ecb to 2e0e38a Compare January 28, 2025 21:07
@gnprice
Copy link
Member

gnprice commented Jan 29, 2025

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?

@PIG208
Copy link
Member Author

PIG208 commented Jan 29, 2025

Ahh yes. Those are for general chat (whose base is the tip of this PR).

Pushed to fix this.

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.

Thanks both! Generally this all looks good. A few comments, mainly in the tests.

@@ -890,6 +891,7 @@ InitialSnapshot initialSnapshot({
emojiset: Emojiset.google,
),
userTopics: userTopics,
realmMandatoryTopics: realmMandatoryTopics ?? false,
Copy link
Member

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.

Comment on lines 1324 to 1325
_controller ??= StreamComposeBoxController(store: store);
(controller as StreamComposeBoxController).topic.store = store;
Copy link
Member

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.

@@ -1370,15 +1375,16 @@ class _ComposeBoxState extends State<ComposeBox> implements ComposeBoxState {
return _ComposeBoxContainer(body: null, errorBanner: errorBanner);
}

final controller = _controller!;
Copy link
Member

Choose a reason for hiding this comment

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

nit / handy pattern:

Suggested change
final controller = _controller!;
final controller = this.controller;

checkMessageNotSent(tester);
});

testWidgets('if topics are mandatory, reject (no topic)', (tester) async {
Copy link
Member

Choose a reason for hiding this comment

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

nit:

Suggested change
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."

Comment on lines 593 to 594
testWidgets('empty topic -> (no topic)', (tester) async {
await setupAndTapSend(tester, topicInputText: '');
Copy link
Member

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.

Comment on lines 598 to 604
..bodyFields.deepEquals({
'type': 'stream',
'to': channel.streamId.toString(),
'topic': '(no topic)',
'content': 'test content',
'read_by_sender': 'true',
});
Copy link
Member

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:

Suggested change
..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.)

@PIG208
Copy link
Member Author

PIG208 commented Jan 29, 2025

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]>
The parameter `realmWaitingPeriodThreshold` was added in
commit 157418c but it was never used.

Signed-off-by: Zixuan James Li <[email protected]>
@gnprice
Copy link
Member

gnprice commented Jan 30, 2025

Thanks! Looks good; merging.

@gnprice gnprice merged commit f1646c4 into zulip:main Jan 30, 2025
@PIG208 PIG208 deleted the pr-mandatory branch January 30, 2025 23:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a-compose Compose box, autocomplete, attaching files/images integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants