-
Notifications
You must be signed in to change notification settings - Fork 306
compose_box: Replace compose box with a banner when cannot post in a channel #886
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
Changes from all commits
6714098
bb867b4
a06b1d5
6b4c569
25c088a
4de8c23
388b83b
157418c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -247,6 +247,104 @@ void main() { | |
}); | ||
}); | ||
|
||
group('PerAccountStore.hasPassedWaitingPeriod', () { | ||
final store = eg.store(initialSnapshot: | ||
eg.initialSnapshot(realmWaitingPeriodThreshold: 2)); | ||
|
||
final testCases = [ | ||
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 0, 10, 00), false), | ||
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1, 10, 00), false), | ||
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 09, 59), false), | ||
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 2, 10, 00), true), | ||
('2024-11-25T10:00+00:00', DateTime.utc(2024, 11, 25 + 1000, 07, 00), true), | ||
]; | ||
Comment on lines
+254
to
+260
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to #886 comment, I wrote the tests only for the UTC format as There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, since we're doing the computations all in terms of UTC (which is good news), that's the right way for the tests to work too.
Unfortunately there doesn't seem to be such a way. We have a comment on one test where that came up, in // We show the dates in the user's timezone. Dart's standard library
// doesn't give us a way to control which timezone is used — only to
// choose between UTC and the user's timezone, whatever that may be.
// So we do the latter, and that means these dates come out differently
// depending on the timezone in the environment running the tests.
// Related upstream issues:
// https://github.com/dart-lang/sdk/issues/28985 (about DateTime.now, not timezone)
// https://github.com/dart-lang/sdk/issues/44928 (about the Dart implementation's own internal tests)
// For this test, just accept outputs corresponding to any possible timezone.
tester.widget(find.textContaining(RegExp("Dec 1[89], 2022")));
tester.widget(find.textContaining(RegExp("Aug 2[23], 2022"))); |
||
|
||
for (final (String dateJoined, DateTime currentDate, bool hasPassedWaitingPeriod) in testCases) { | ||
test('user joined at $dateJoined ${hasPassedWaitingPeriod ? 'has' : "hasn't"} ' | ||
'passed waiting period by $currentDate', () { | ||
final user = eg.user(dateJoined: dateJoined); | ||
check(store.hasPassedWaitingPeriod(user, byDate: currentDate)) | ||
.equals(hasPassedWaitingPeriod); | ||
}); | ||
} | ||
}); | ||
|
||
group('PerAccountStore.hasPostingPermission', () { | ||
final testCases = [ | ||
(ChannelPostPolicy.unknown, UserRole.unknown, true), | ||
(ChannelPostPolicy.unknown, UserRole.guest, true), | ||
(ChannelPostPolicy.unknown, UserRole.member, true), | ||
(ChannelPostPolicy.unknown, UserRole.moderator, true), | ||
(ChannelPostPolicy.unknown, UserRole.administrator, true), | ||
(ChannelPostPolicy.unknown, UserRole.owner, true), | ||
(ChannelPostPolicy.any, UserRole.unknown, true), | ||
(ChannelPostPolicy.any, UserRole.guest, true), | ||
(ChannelPostPolicy.any, UserRole.member, true), | ||
(ChannelPostPolicy.any, UserRole.moderator, true), | ||
(ChannelPostPolicy.any, UserRole.administrator, true), | ||
(ChannelPostPolicy.any, UserRole.owner, true), | ||
(ChannelPostPolicy.fullMembers, UserRole.unknown, true), | ||
(ChannelPostPolicy.fullMembers, UserRole.guest, false), | ||
// The fullMembers/member case gets its own tests further below. | ||
// (ChannelPostPolicy.fullMembers, UserRole.member, /* complicated */), | ||
(ChannelPostPolicy.fullMembers, UserRole.moderator, true), | ||
(ChannelPostPolicy.fullMembers, UserRole.administrator, true), | ||
(ChannelPostPolicy.fullMembers, UserRole.owner, true), | ||
(ChannelPostPolicy.moderators, UserRole.unknown, true), | ||
(ChannelPostPolicy.moderators, UserRole.guest, false), | ||
(ChannelPostPolicy.moderators, UserRole.member, false), | ||
(ChannelPostPolicy.moderators, UserRole.moderator, true), | ||
(ChannelPostPolicy.moderators, UserRole.administrator, true), | ||
(ChannelPostPolicy.moderators, UserRole.owner, true), | ||
(ChannelPostPolicy.administrators, UserRole.unknown, true), | ||
(ChannelPostPolicy.administrators, UserRole.guest, false), | ||
(ChannelPostPolicy.administrators, UserRole.member, false), | ||
(ChannelPostPolicy.administrators, UserRole.moderator, false), | ||
(ChannelPostPolicy.administrators, UserRole.administrator, true), | ||
(ChannelPostPolicy.administrators, UserRole.owner, true), | ||
]; | ||
|
||
for (final (ChannelPostPolicy policy, UserRole role, bool canPost) in testCases) { | ||
test('"${role.name}" user ${canPost ? 'can' : "can't"} post in channel ' | ||
'with "${policy.name}" policy', () { | ||
final store = eg.store(); | ||
final actual = store.hasPostingPermission( | ||
inChannel: eg.stream(channelPostPolicy: policy), user: eg.user(role: role), | ||
// [byDate] is not actually relevant for these test cases; for the | ||
// ones which it is, they're practiced below. | ||
byDate: DateTime.now()); | ||
check(actual).equals(canPost); | ||
}); | ||
} | ||
|
||
group('"member" user posting in a channel with "fullMembers" policy', () { | ||
PerAccountStore localStore({required int realmWaitingPeriodThreshold}) => | ||
eg.store(initialSnapshot: eg.initialSnapshot( | ||
realmWaitingPeriodThreshold: realmWaitingPeriodThreshold)); | ||
|
||
User memberUser({required String dateJoined}) => eg.user( | ||
role: UserRole.member, dateJoined: dateJoined); | ||
|
||
test('a "full" member -> can post in the channel', () { | ||
final store = localStore(realmWaitingPeriodThreshold: 3); | ||
final hasPermission = store.hasPostingPermission( | ||
inChannel: eg.stream(channelPostPolicy: ChannelPostPolicy.fullMembers), | ||
user: memberUser(dateJoined: '2024-11-25T10:00+00:00'), | ||
byDate: DateTime.utc(2024, 11, 28, 10, 00)); | ||
check(hasPermission).isTrue(); | ||
}); | ||
|
||
test('not a "full" member -> cannot post in the channel', () { | ||
final store = localStore(realmWaitingPeriodThreshold: 3); | ||
final actual = store.hasPostingPermission( | ||
inChannel: eg.stream(channelPostPolicy: ChannelPostPolicy.fullMembers), | ||
user: memberUser(dateJoined: '2024-11-25T10:00+00:00'), | ||
byDate: DateTime.utc(2024, 11, 28, 09, 59)); | ||
check(actual).isFalse(); | ||
}); | ||
}); | ||
}); | ||
|
||
group('PerAccountStore.handleEvent', () { | ||
// Mostly this method just dispatches to ChannelStore and MessageStore etc., | ||
// and so most of the tests live in the test files for those | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,7 +46,7 @@ Future<void> setupToMessageActionSheet(WidgetTester tester, { | |
|
||
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot()); | ||
store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
await store.addUser(eg.user(userId: message.senderId)); | ||
await store.addUsers([eg.selfUser, eg.user(userId: message.senderId)]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This seems like a reasonable change to the action-sheet tests, but why is it needed in this commit, which is about the compose box? …Ah, I think I understand: it's a boring but necessary bit of setup so that the simulated action sheet doesn't crash in the code that decides whether to show the error banner. Is that right? There are quite a few other changes in this commit that look like they're made for the same reason. Would you move those to a prep commit before this commit? That should make it easier to focus on the interesting changes here. 🙂 |
||
if (message is StreamMessage) { | ||
final stream = eg.stream(streamId: message.streamId); | ||
await store.addStream(stream); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,10 +77,12 @@ Future<Finder> setupToTopicInput(WidgetTester tester, { | |
addTearDown(testBinding.reset); | ||
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot()); | ||
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
await store.addUser(eg.selfUser); | ||
Comment on lines
78
to
+80
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if we instead adjust I guess there might be a lot of existing tests that separately add that user, and they'd hit errors from adding a duplicate. In that case that change might still be a good idea; but it'd require a bigger effort, which let's leave out of scope for this PR. |
||
final connection = store.connection as FakeApiConnection; | ||
|
||
// prepare message list data | ||
final stream = eg.stream(); | ||
await store.addStream(stream); | ||
final message = eg.streamMessage(stream: stream, sender: eg.selfUser); | ||
connection.prepare(json: GetMessagesResult( | ||
anchor: message.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.
Looks like this should come before
maxFileUploadSizeMib
.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.
Moved it before the line for
maxFileUploadSizeMib
.Also, looking at these "realm and server" section properties, I'm unsure if they follow a specific order. If they're meant to follow the order of
InitialSnapshot
, then they'll have an order like 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.
The constructor arguments at this call site should match the order of the parameters in the constructor's declaration, which in turn should match the order the fields are declared in.
For the field declarations, generally we've tried to keep them in a logical order (which is our default approach for ordering things). So
realmUrl
comes before all the miscellaneous settings, because it's the value that identifies the whole realm in the first place. I don't think there's a strong reason the other five you listed are ordered in the way they currently are, though.That logical ordering may differ from what's in
InitialSnapshot
, because: