-
Notifications
You must be signed in to change notification settings - Fork 306
internal_links: Add "/" before fragment identifier #874
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
test/model/internal_link_test.dart
Outdated
for (final testCase in testCases) { | ||
final String inputUrl = testCase.$1; | ||
final String expectedUrl = testCase.$2; |
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:
for (final testCase in testCases) { | |
final String inputUrl = testCase.$1; | |
final String expectedUrl = testCase.$2; | |
for (final (inputUrl, expectedUrl) in testCases) { |
I can see that this helper parallels testExpectedNarrows
, where the same pattern is also applicable.
@@ -98,7 +98,7 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) { | |||
fragment.write('/near/$nearMessageId'); | |||
} | |||
|
|||
return store.realmUrl.replace(fragment: fragment.toString()); |
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.
96593ba internal_links [nit]: Add path: '/' to store.realmUrl.replace for proper Url handling
I think we don't ever use [nit]
in commit summaries, so we can just drop that.
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.
We don't have tests in this commit, and the tests added in the other commit do not fail if we remove this change. We need to do some testing here.
test/model/internal_link_test.dart
Outdated
@@ -54,6 +54,37 @@ void main() { | |||
} |
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.
3010732 internal_link_test: Create 'parseInternalLink full url cases' test
We usually use internal_link test
for changes like this. git log --oneline -- path/to/file
is a way to look for predecessors.
test/model/internal_link_test.dart
Outdated
('https://example.com/#narrow/stream/check', 'https://example.com/#narrow/stream/check'), | ||
('https://example.com/#narrow/stream/3-mobile/topic/topic1', 'https://example.com/#narrow/stream/3-mobile/topic/topic1'), | ||
('https://another.com/#narrow/stream/mobile', 'https://another.com/#narrow/stream/mobile'), | ||
('https://example.com/#narrow/stream/check/topic/test', 'https://example.com/#narrow/stream/check/topic/test'), |
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'm not sure if I understand the purpose of these test cases, as the input and the expected output are the same.
Thanks for the PR! Left some comments. |
231512d
to
e617802
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 for the update! Went over this and left some comments. One other suggestion is to add the tests in the same commit that makes the change.
lib/model/internal_link.dart
Outdated
@@ -59,7 +59,7 @@ String? decodeHashComponent(String str) { | |||
Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) { | |||
// TODO(server-7) | |||
final apiNarrow = resolveDmElements( | |||
narrow.apiEncode(), store.connection.zulipFeatureLevel!); | |||
narrow.apiEncode(), store.connection.zulipFeatureLevel!); |
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 the indentation change here is unintentional.
@@ -95,8 +95,11 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) { | |||
if (nearMessageId != null) { | |||
fragment.write('/near/$nearMessageId'); | |||
} | |||
final realmUrlWithSlash = store.realmUrl.path.endsWith('/') | |||
? store.realmUrl | |||
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); |
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:
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); | |
final realmUrlWithSlash = store.realmUrl.path.endsWith('/') | |
? store.realmUrl | |
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); |
test/model/internal_link_test.dart
Outdated
final messageLink = narrowLink(store, narrow, nearMessageId: 12345); | ||
final urlString = messageLink.toString(); | ||
final fragmentIndex = urlString.indexOf('#'); | ||
expect(fragmentIndex, greaterThan(0)); |
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.
We usually use checks for our tests. So this can be check(fragmentIndex).isGreaterThan(0);
instead. This applies to the other checks here too.
test/model/internal_link_test.dart
Outdated
eg.stream(streamId: 123, name: 'check'), | ||
]; | ||
test('narrowLink should generate the full URL correctly', () async { | ||
final store = await setupStore(realmUrl: realmUrl, streams: streams); |
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.
This realmUrl
is https://example.com/
, which comes with a trailing /
. So we might want to override this for testing.
test/model/internal_link_test.dart
Outdated
expect( | ||
urlString.startsWith('https://example.com/#narrow/stream/123-check/topic'), | ||
isTrue | ||
); |
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 this test and the one before it can be combined into one. However, looking at this more, it might be simpler to just check if urlString
equals the URL we expect (i.e.: 'https://example.com/#narrow/stream/123-check/topic'
).
Or, even better, we can add the test to test/widgets/action_sheet_test.dart
, as a test similar to "copies message link to clipboard". This way we get to test it end-to-end. In this case, no change is needed for test/model/internal_link_test.dart
.
lib/model/internal_link.dart
Outdated
@@ -59,7 +59,7 @@ String? decodeHashComponent(String str) { | |||
Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) { |
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.
Some nits on commit message:
updates
->Updates
...fragment identifier This...
->...fragment identifier. This...
likified
->linkified
and an empty space between the paragraph and Fixes: #845
.
74b44f3
to
0bc2e39
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 for the update! The implementation now looks good to me. Added some comments on the new test.
test/widgets/action_sheet_test.dart
Outdated
@@ -553,6 +553,21 @@ void main() { | |||
}); | |||
}); | |||
|
|||
|
|||
group('narrowLink URL generation tests', () { | |||
|
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.
Extra empty line here and above the group.
test/widgets/action_sheet_test.dart
Outdated
testWidgets('Full Url Testing', (tester) async { | ||
final message = eg.streamMessage(); | ||
final narrow = TopicNarrow.ofMessage(message); | ||
await setupToMessageActionSheet(tester, message: message, narrow: narrow); |
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.
For this test, it matters for us that the store.realmUrl
used does not end with a slash. However, the default value is "https://chat.example/"
(see eg.account
). We should find a way to override that when setting up the store.
test/widgets/action_sheet_test.dart
Outdated
final narrow = TopicNarrow.ofMessage(message); | ||
await setupToMessageActionSheet(tester, message: message, narrow: narrow); | ||
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
final generatedLink = narrowLink(store, narrow, nearMessageId: message.id).toString(); |
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.
To make this end-to-end, let's generate the link through tapCopyMessageLinkButton
. We should move this test to the "CopyMessageLinkButton" group.
test/widgets/action_sheet_test.dart
Outdated
const expectedPrefix = 'https://chat.example/#narrow/stream/123-stream-123/topic'; | ||
final truncatedLink = generatedLink.split('/example').first; | ||
check(truncatedLink).equals(expectedPrefix); |
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:
const expectedPrefix = 'https://chat.example/#narrow/stream/123-stream-123/topic'; | |
final truncatedLink = generatedLink.split('/example').first; | |
check(truncatedLink).equals(expectedPrefix); | |
check(generatedLink).startsWith('https://chat.example/#narrow/stream/123-stream-123/topic'); |
@@ -96,7 +96,11 @@ Uri narrowLink(PerAccountStore store, Narrow narrow, {int? nearMessageId}) { | |||
fragment.write('/near/$nearMessageId'); |
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 I missed this in the last round. "Variable" in the commit summary is capitalized, but we should use "variable" instead.
0bc2e39
to
9a69094
Compare
test/widgets/action_sheet_test.dart
Outdated
@@ -24,6 +24,7 @@ import '../api/fake_api.dart'; | |||
import '../example_data.dart' as eg; | |||
import '../flutter_checks.dart'; | |||
import '../model/binding.dart'; | |||
import '../model/internal_link_test.dart'; | |||
import '../model/test_store.dart'; |
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.
Import internal_link_test.dart to use setupstore to generate link without an '/' before '#'.
test/widgets/action_sheet_test.dart
Outdated
final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString(); | ||
final generatedLink = (await Clipboard.getData('text/plain'))?.text ?? ''; | ||
final normalizedExpectedLink = expectedLink.replaceAll('123-unknown', '123-stream-123'); | ||
check(generatedLink).equals(normalizedExpectedLink); |
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.
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.
Hmm, interesting. Looks like that could be a result of not having the stream in store. This is because expectedLink
and generatedLink
are generated from separate instances of PerAccountStore
:
expectedLink
uses the store created with setupStore
above;
generatedLink
uses the store set up from setupToMessageActionSheet
.
How about adding an optional parameter Account? account
to setupToMessageActionSheet
, which can be used to override the realmUrl
?
PTAL @PIG208 |
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 for the revision! Left a comment regarding the output mismatch issue.
test/widgets/action_sheet_test.dart
Outdated
final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString(); | ||
final generatedLink = (await Clipboard.getData('text/plain'))?.text ?? ''; | ||
final normalizedExpectedLink = expectedLink.replaceAll('123-unknown', '123-stream-123'); | ||
check(generatedLink).equals(normalizedExpectedLink); |
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.
Hmm, interesting. Looks like that could be a result of not having the stream in store. This is because expectedLink
and generatedLink
are generated from separate instances of PerAccountStore
:
expectedLink
uses the store created with setupStore
above;
generatedLink
uses the store set up from setupToMessageActionSheet
.
How about adding an optional parameter Account? account
to setupToMessageActionSheet
, which can be used to override the realmUrl
?
bc34132
to
51a53fb
Compare
@@ -38,11 +38,12 @@ late FakeApiConnection connection; | |||
Future<void> setupToMessageActionSheet(WidgetTester tester, { | |||
required Message message, | |||
required Narrow narrow, | |||
Account? account, | |||
}) 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.
Add parameter Account so that we can override realmUrl to produce Url without '/' before '#'.
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.
LGTM overall! Some small comments, and I going to mark this for integration review.
test/widgets/action_sheet_test.dart
Outdated
testWidgets('Full Url Testing', (tester) async { | ||
final message = eg.streamMessage(); | ||
final narrow = TopicNarrow.ofMessage(message); | ||
await setupToMessageActionSheet(tester, message: message, narrow: narrow); |
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.
We shouldn't need to setup the action sheet again. We did that at line 566.
await tapCopyMessageLinkButton(tester); | ||
await tester.pump(Duration.zero); |
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: Move this to just before the line where we define expectedLink
, so the reader gets the contextual information about where the clipboard data comes from
test/widgets/action_sheet_test.dart
Outdated
final customAccount = eg.selfAccount.copyWith(id: 2, realmUrl: Uri.parse('https://chat.example')); | ||
await setupToMessageActionSheet(tester, message: message, narrow: narrow, account: customAccount); | ||
final customAccountStore = await testBinding.globalStore.perAccount(customAccount.id); | ||
|
||
final expectedLink = narrowLink(customAccountStore, narrow, nearMessageId: message.id).toString(); |
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.
These lines are too long. Try to wrap them so that they are under 80 columns wide.
For example:
- await setupToMessageActionSheet(tester, message: message, narrow: narrow, account: customAccount);
+ await setupToMessageActionSheet(
+ tester, message: message, narrow: narrow, account: customAccount);
11d5c2f
to
3169ff4
Compare
test/widgets/action_sheet_test.dart
Outdated
@@ -60,8 +63,8 @@ Future<void> setupToMessageActionSheet(WidgetTester tester, { | |||
historyLimited: false, | |||
messages: [message], | |||
).toJson()); | |||
|
|||
await tester.pumpWidget(TestZulipApp(accountId: eg.selfAccount.id, | |||
await tester.pumpAndSettle(); |
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 can be removed, unless I missed something?
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 @satyam372 for the contribution, and @PIG208 for the previous reviews!
Initial comments from me below, in addition to @PIG208's remaining comments above.
This PR also lacks the kind of test that was specified in the issue:
as part of a PR fixing this issue, we should also add a few tests that include, verbatim, the full URL they expect as the output.
It will need to add those.
lib/model/internal_link.dart
Outdated
final realmUrlWithSlash = store.realmUrl.path.endsWith('/') | ||
? store.realmUrl | ||
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); |
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.
This logic seems too broad. If the realm URL looks like https://chat.example/foo
, we don't have a reason to turn that to https://chat.example/foo/
.
Unless https://chat.example/foo#narrow/etc
fails to linkify in a Zulip message, that is. Does it?
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.
Yes, I tested some URLs and Here are the results:
In a browser: The browser automatically adds a / before the #.
In Zulip Flutter application: When I paste the URL, it does not linkify and is not clickable.
Based on this behavior, I have added a / before the #.
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 question is about what Zulip does, though, when you put such a URL into a message. That's what this issue #845 is about:
This is still a valid URL, I believe — but it looks funny, and more concretely it means that if you post it in a Zulip message it doesn't get linkified.
So I tested that just now. The answer is that it does linkify:
https://chat.zulip.org/#narrow/stream/7-test-here/topic/linkification/near/1957680
That is, if you send a message with this text:
https://chat.example/foo#narrow/etc
it becomes a link.
That's the same as what happens if you send a message with this text:
https://chat.example/#narrow/etc
By contrast if you send a message with this text:
https://chat.example#narrow/etc
it doesn't become a link. That's the reason #845 is an issue.
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.
In Zulip Flutter application: When I paste the URL, it does not linkify and is not clickable.
This is puzzling because it's different from what I observed in my test just now. (I used the web app to send that test message — but the message content gets turned to HTML on the server, so it doesn't matter what client is used.)
Can you post a link to a test message where you found the URL did not linkify? That would make it possible to pin down what variable is controlling the difference in behavior.
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 link https://chat.example/foo#narrow/etc
does linkify for me. So we probably don't need the slash in this case.
I think the fix for this will just be using startswith
instead of endsWith
, so that we don't process https://chat.example/foo
, but still handle https://chat.example#anything
.
These are something that are good to have tests for.
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.
Or even simpler than startsWith
— check path.isNotEmpty
. I believe a URL path will always either be empty or start with /
.
test/widgets/action_sheet_test.dart
Outdated
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot()); | ||
final store = await testBinding.globalStore.perAccount(eg.selfAccount.id); | ||
account ??= eg.selfAccount; | ||
final initialSnapshot = eg.initialSnapshot(zulipFeatureLevel: account.zulipFeatureLevel); |
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 this need to start mentioning zulipFeatureLevel? If not, keep the story simpler by leaving it out.
test/widgets/action_sheet_test.dart
Outdated
@@ -616,4 +634,4 @@ void main() { | |||
check(mockSharePlus.sharedString).isNull(); | |||
}); | |||
}); | |||
} | |||
} |
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.
(Not an empty line — the problem is that every line should end with a newline, and this commit is editing the file's last line by removing its terminating newline. Previous discussion: #534 (comment) )
Thanks @gnprice and @PIG208 for the review. just a small question. |
Yes. As the issue says:
For further questions about how to complete the PR, I recommend a chat thread in |
3169ff4
to
68e8325
Compare
PTAL @PIG208 |
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 for the revision! I know there has been many review comments, but we are making some progress. I think the structure of the test looks fine. You can go to #mobile-dev-help anytime if you run into issues.
test/widgets/action_sheet_test.dart
Outdated
@@ -616,4 +634,4 @@ void main() { | |||
check(mockSharePlus.sharedString).isNull(); | |||
}); | |||
}); | |||
} | |||
} |
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 newline still seems to be missing. Could you add it there?
lib/model/internal_link.dart
Outdated
final realmUrlWithSlash = store.realmUrl.path.endsWith('/') | ||
? store.realmUrl | ||
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); |
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 link https://chat.example/foo#narrow/etc
does linkify for me. So we probably don't need the slash in this case.
I think the fix for this will just be using startswith
instead of endsWith
, so that we don't process https://chat.example/foo
, but still handle https://chat.example#anything
.
These are something that are good to have tests for.
test/widgets/action_sheet_test.dart
Outdated
|
||
await tapCopyMessageLinkButton(tester); | ||
await tester.pump(Duration.zero); | ||
const expectedLink = 'https://chat.zulip.org/#narrow/stream/123-stream-123/topic/example.20topic.20341/near/13579'; |
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.
These expectedLink
s look good to me.
test/widgets/action_sheet_test.dart
Outdated
testWidgets('Copies message link with verbatim, full URL output', (tester) async { | ||
final stream = eg.stream(streamId: 123, name: 'stream 123'); | ||
final message = eg.streamMessage( | ||
id: 13579, stream: stream, topic: 'example topic 341'); |
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: indentation, and some other places in this file.
test/widgets/action_sheet_test.dart
Outdated
}); | ||
|
||
group('Message link verbatim URL tests', () { | ||
|
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: we can remove the line here.
test/widgets/action_sheet_test.dart
Outdated
id: 98765, stream: stream, topic: 'Whats up? 123!'); | ||
final narrow = TopicNarrow.ofMessage(message); | ||
final account = eg.selfAccount.copyWith( | ||
realmUrl: Uri.parse('https://chat.zulip.org')); |
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.
It should be fine to reuse the same set of stream and topic, because we are more interested in the variants of realmUrl
. In addition to this one, let's also try something like https://chat.zulip.org/path
and https://chat.zulip.org/
. Since most of these tests will be similar, extracting a helper will be simplify the code.
test/widgets/action_sheet_test.dart
Outdated
@@ -551,6 +554,93 @@ void main() { | |||
final expectedLink = narrowLink(store, narrow, nearMessageId: message.id).toString(); | |||
check(await Clipboard.getData('text/plain')).isNotNull().text.equals(expectedLink); | |||
}); | |||
|
|||
testWidgets('Full Url Testing', (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.
Now that we have the new tests, we should be able to remove this one.
ba6047e
to
d4733c3
Compare
Updates the URL construction to include a trailing slash before the fragment identifier. This ensures that the URL is properly formatted and makes the url linkified. Co-authored-by: Greg Price <[email protected]> Fixes: zulip#845
d4733c3
to
6c884ee
Compare
PTAL @PIG208 |
Please review @gnprice. |
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.
Looking again at this PR, the commit still doesn't make it at all clear to me that it makes things work the way we want them to. When sending a PR to Zulip (or really anywhere), it's important to make the code clear and the explanations clear. See the Zulip guide on submitting reviewable PRs:
https://zulip.readthedocs.io/en/latest/contributing/reviewable-prs.html
This has been a long thread, because @PIG208 and I have already spent a substantial amount of time working with you to try to improve the PR. But given the PR's current state, it would still take a substantial amount more work to get it to be something that we can merge.
It's particularly concerning that even the latest revision introduces new problems that should have been easy to catch if you re-read your changes and think through what they're doing. (I've flagged two such problems below.) As our guide says, it's important to review your own work before asking others to do so.
Closing this PR because it's not on track to become something we can merge with a reasonable amount of effort from the core team.
Based on this thread and #1013, I think you don't yet have the skills to learn to contribute productively in the Zulip project. You're welcome to try again after at least 6 months.
I recommend you spend time working on other projects, and reading a lot of code, especially reading code in well-maintained codebases like Zulip or upstream Flutter (i.e., any of the main repositories at https://github.com/zulip or https://github.com/flutter). This advice from our contributing guide is applicable to a wide variety of codebases:
- Set up a development environment following the instructions in the project README.
- Start reading recent commits to see the code we’re writing. Use either a graphical Git viewer like
gitk
, orgit log -p
with the “secret” to reading its output.- Pick some of the code that appears in those Git commits and that looks interesting. Use your IDE to visit that code and to navigate to related code, reading to see how it works and how the codebase is organized.
I recommend also investing effort in clearly explaining why your changes work correctly. As our guide to reviewable PRs says, that begins with clearly reasoning through that question yourself:
When you write code, you should make sure that you understand why it works as intended. This is the foundation for being able to explain your proposed changes to others.
Even in personal projects where nobody else is reading your explanations, taking the time to clearly write them down will help you write higher-quality code. It will also be useful practice for contributing to projects like Zulip where there are other people you need to explain your changes to.
final realmUrlWithSlash = store.realmUrl.path.isNotEmpty | ||
? store.realmUrl | ||
: store.realmUrl.replace(path: '${store.realmUrl.path}/'); |
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.
In the "else" case here, the path will have to be empty. So this expression is unnecessarily complicated.
testWidgets('Copies link with custom realm path', (tester) async { | ||
await testMessageLink( | ||
tester: tester, | ||
realmUrl: 'https://chat.example/foo', |
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.
This is difficult to read because it's missing indentation:
testWidgets('Copies link with custom realm path', (tester) async { | |
await testMessageLink( | |
tester: tester, | |
realmUrl: 'https://chat.example/foo', | |
testWidgets('Copies link with custom realm path', (tester) async { | |
await testMessageLink( | |
tester: tester, | |
realmUrl: 'https://chat.example/foo', |
The same is true of each of the other test cases.
Fixes: #845
This adds a '/ ' after hostname. when this Url is posted in Zulip message it gets linkified.
