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

Communication: Fix announcement emails not rendering correctly #9850

Conversation

PaRangger
Copy link
Contributor

@PaRangger PaRangger commented Nov 22, 2024

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the server coding and design guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I documented the Java code using JavaDoc style.

Motivation and Context

Currently, attachments and references are not properly displayed in announcement e-mails. They are shown as text with their text (e.g. [programming]Test(/link/to/exercise)[/programming]).

Description

I added a custom parser that matches the tags and replaces them accordingly. Additionally, for images and attachments I added absolute links instead of relative ones to make them display properly. User references should just display their names.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Course with communication enabled
  1. Log in to Artemis
  2. Navigate to course
  3. Navigate to the communication tab
  4. Navigate to the announcement channel
  5. Create an announcement
  6. Check your e-mails
  7. Check if the tags are rendered as links, which should forward you to the according resource. Images should also render as links. User and channel references should be rendered as Text with an @ for users and a # for channels.

Testserver States

Note

These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.







Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Screenshots

Bildschirmfoto 2024-11-22 um 16 20 55

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced email notifications with efficient markdown rendering and caching.
    • Introduced services for rendering custom markdown links and references.
    • Added functionality for converting relative URLs to absolute URLs during rendering.
  • Bug Fixes

    • Improved error handling for markdown rendering processes.
  • Tests

    • Added unit tests for the new markdown rendering services to ensure correct functionality.

@PaRangger PaRangger self-assigned this Nov 22, 2024
@github-actions github-actions bot added tests server Pull requests that update Java code. (Added Automatically!) communication Pull requests that affect the corresponding module labels Nov 22, 2024
@github-actions github-actions bot added the tests label Nov 22, 2024
@PaRangger PaRangger marked this pull request as ready for review November 22, 2024 17:42
@PaRangger PaRangger requested a review from a team as a code owner November 22, 2024 17:42
Copy link

coderabbitai bot commented Nov 22, 2024

Walkthrough

The changes in this pull request involve enhancements to the MailService and the introduction of several new classes for rendering custom markdown content. The MailService now includes caching for rendered posts and utilizes new services for rendering markdown links and references. Additionally, new classes for rendering images and converting relative URLs to absolute paths have been added. Unit tests for the new rendering services have also been implemented to ensure functionality.

Changes

File Change Summary
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MailService.java - Added fields for caching rendered posts and new markdown renderer services.
- Updated constructor and modified sendNotification method for caching.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java - Introduced a service for rendering custom markdown links to HTML anchor tags with error handling.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java - Introduced a service for rendering custom markdown references for users and channels, implementing error handling.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomRendererService.java - Added an interface defining a contract for markdown rendering services.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java - Introduced a class for rendering markdown image nodes as HTML anchor elements with error handling.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java - Added a factory class for creating instances of MarkdownImageBlockRenderer.
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java - Introduced a class for converting relative URLs to absolute during markdown rendering.
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java - Updated tests to include new dependencies for the MailService constructor.
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java - Added unit tests for MarkdownCustomLinkRendererService to validate rendering functionality.
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java - Added unit tests for MarkdownCustomReferenceRendererService to validate rendering of user and channel references.

Possibly related PRs

Suggested labels

ready to merge, client

Suggested reviewers

  • JohannesStoehr
  • SimonEntholzer
  • florian-glombik
  • cremertim
  • az108

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Outside diff range and nitpick comments (14)
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java (1)

7-10: Consider using package-private access for the class.

Following the principle of least privilege, if this factory is only used within the notifications package, consider removing the public modifier to restrict access.

-public class MarkdownImageBlockRendererFactory implements HtmlNodeRendererFactory {
+class MarkdownImageBlockRendererFactory implements HtmlNodeRendererFactory {
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java (2)

8-10: Consider adding input validation for baseUrl.

While the implementation is clean, the baseUrl field should be validated to ensure it's not null or empty and ends with a trailing slash if required for proper URL concatenation.

 private final String baseUrl;
+
+private static String validateBaseUrl(String baseUrl) {
+    if (baseUrl == null || baseUrl.trim().isEmpty()) {
+        throw new IllegalArgumentException("baseUrl must not be null or empty");
+    }
+    return baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
+}

12-14: Add validation in constructor.

Update the constructor to use the suggested validation method.

 public MarkdownRelativeToAbsolutePathAttributeProvider(String baseUrl) {
-    this.baseUrl = baseUrl;
+    this.baseUrl = validateBaseUrl(baseUrl);
 }
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java (1)

13-18: Add class-level JavaDoc documentation.

As per the PR objectives, Java code should be documented using JavaDoc style. Please add class-level documentation explaining the purpose and usage of this renderer.

Add the following documentation:

+/**
+ * A custom renderer for Markdown image nodes that converts them into HTML anchor elements.
+ * This renderer is specifically designed for email notifications where images need to be
+ * rendered as absolute URLs.
+ */
 public class MarkdownImageBlockRenderer implements NodeRenderer {
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java (2)

10-18: Add JavaDoc to document the test class purpose.

Consider adding class-level documentation to describe the purpose and scope of these tests, especially since this is part of the email rendering enhancement feature.

+/**
+ * Tests for {@link MarkdownCustomReferenceRendererService} which handles the rendering
+ * of user and channel references in announcement emails.
+ */
 class MarkdownCustomReferenceRendererServiceTest {

19-59: Consider adding more edge cases and boundary tests.

While the current tests cover the basic scenarios well, consider adding the following test cases:

  1. Handling of null input
  2. Malformed tags (e.g., unclosed tags, missing parentheses)
  3. Performance test with large input containing many references
  4. Nested tags

Example test additions:

@Test
void shouldHandleNullInputGracefully() {
    assertThat(service.render(null)).isNull();
}

@Test
void shouldHandleMalformedTags() {
    String input = "[user]Max Muster(ga1234as)[/wrongtag]";
    assertThat(service.render(input)).isEqualTo(input);
}

@Test
void shouldHandleLargeInput() {
    StringBuilder input = new StringBuilder();
    for (int i = 0; i < 1000; i++) {
        input.append("[user]User").append(i).append("(id").append(i).append(")[/user] ");
    }
    String result = service.render(input.toString());
    assertThat(result).contains("@User0").contains("@User999");
}
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java (2)

19-24: Consider improving the test setup approach.

The current setup has a few potential improvements to consider:

  1. Using ReflectionTestUtils to set private fields might indicate that the artemisServerUrl should be injectable through constructor or setter.
  2. The hard-coded URL could be moved to a constant or test configuration.

Consider this alternative approach:

-    @BeforeEach
-    void setUp() throws MalformedURLException, URISyntaxException {
-        markdownCustomLinkRendererService = new MarkdownCustomLinkRendererService();
-
-        ReflectionTestUtils.setField(markdownCustomLinkRendererService, "artemisServerUrl", new URI("http://localhost:8080").toURL());
-    }
+    private static final String TEST_SERVER_URL = "http://localhost:8080";
+
+    @BeforeEach
+    void setUp() {
+        markdownCustomLinkRendererService = new MarkdownCustomLinkRendererService(URI.create(TEST_SERVER_URL).toURL());
+    }

26-70: Consider adding more edge cases to improve test coverage.

While the current tests cover the basic scenarios well, consider adding tests for:

  1. Special characters in URLs and text
  2. XSS prevention (e.g., <script> tags in input)
  3. Very long inputs
  4. Nested tags (e.g., [programming][quiz]text[/quiz][/programming])

Here's an example of additional test cases:

@Test
void shouldEscapeSpecialCharactersInUrls() {
    String input = "[programming]Test (/path with spaces/test?param=value&other=123)[/programming]";
    String expected = "<a href=\"http://localhost:8080/path%20with%20spaces/test?param=value&amp;other=123\">Test</a>";
    
    String result = markdownCustomLinkRendererService.render(input);
    
    assertThat(result).isEqualTo(expected);
}

@Test
void shouldPreventXssInLinks() {
    String input = "[programming]Test (/test?param=<script>alert('xss')</script>)[/programming]";
    String result = markdownCustomLinkRendererService.render(input);
    
    assertThat(result).doesNotContain("<script>");
}

@Test
void shouldHandleNestedTags() {
    String input = "[programming][quiz]Nested (/quiz/1)[/quiz][/programming]";
    String result = markdownCustomLinkRendererService.render(input);
    
    assertThat(result).contains("href=\"http://localhost:8080/quiz/1\"");
}
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java (3)

17-20: Enhance class-level documentation

While the documentation explains the basic purpose, it would be beneficial to add:

  • Example input/output
  • List of supported tags
  • Format requirements for the markdown tags
 /**
  * This service implements the rendering of markdown tags that represent a link.
  * It takes the tag, transforms it into an <a></a> tag, and sets the corresponding href.
+ * 
+ * Example:
+ * Input: [programming]Course Overview(/courses/123)[/programming]
+ * Output: <a href="https://artemis.example.com/courses/123">Course Overview</a>
+ * 
+ * Supported tags: programming, modeling, quiz, text, file-upload, lecture, 
+ * attachment, lecture-unit, slide, faq
+ * 
+ * Format: [tag]text(/relative/path)[/tag]
  */

27-30: Make fields final and private

Fields should be marked as final when they're only set once.

-    private final Set<String> supportedTags;
+    private static final Set<String> SUPPORTED_TAGS;
 
     @Value("${server.url}")
-    private URL artemisServerUrl;
+    private final URL artemisServerUrl;

43-70: Consider using StringBuilder for better performance

When performing multiple string modifications, StringBuilder would be more efficient.

     public String render(String content) {
         Matcher matcher = MARKDOWN_PATTERN.matcher(content);
-        String parsedContent = content;
+        StringBuilder result = new StringBuilder(content);
+        int offset = 0;
 
         while (matcher.find()) {
             try {
                 // ... existing validation code ...
 
-                parsedContent = parsedContent.substring(0, matcher.start()) +
-                    "<a href=\"" + absoluteUrl + "\">" + text + "</a>" +
-                    parsedContent.substring(matcher.end());
+                String replacement = "<a href=\"" + absoluteUrl + "\">" + text + "</a>";
+                result.replace(matcher.start() + offset,
+                             matcher.end() + offset,
+                             replacement);
+                offset += replacement.length() - (matcher.end() - matcher.start());
 
-                matcher = pattern.matcher(parsedContent);
             } catch (Exception e) {
                 // ... error handling ...
             }
         }
 
-        return parsedContent;
+        return result.toString();
     }
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java (2)

15-21: Enhance class-level documentation

While the current documentation provides a basic overview, consider enhancing it with:

  • Examples of supported reference formats
  • Description of the interface contract being implemented
  • Expected input/output format examples
 /**
  * This service implements the rendering of markdown tags that represent a reference (to e.g. a user).
  * These references cannot directly represent a link, so they are rendered as their text only.
+ * 
+ * Supported formats:
+ * - User reference: [user]@username(id)[/user] -> @username
+ * - Channel reference: [channel]#channel-name(id)[/channel] -> #channel-name
+ * 
+ * Implements MarkdownCustomRendererService to provide consistent rendering behavior
+ * across the application's markdown processing pipeline.
  */

25-34: Consider using EnumMap for type-safety and performance

The current implementation using Set and HashMap could be improved for better type-safety and maintainability.

Consider using an enum to represent the reference types:

public enum ReferenceType {
    USER("user", "@"),
    CHANNEL("channel", "#");

    private final String tag;
    private final String prefix;

    ReferenceType(String tag, String prefix) {
        this.tag = tag;
        this.prefix = prefix;
    }

    public String getTag() { return tag; }
    public String getPrefix() { return prefix; }
}

Then modify the fields and constructor:

-    private final Set<String> supportedTags;
-    private final HashMap<String, String> startingCharacters;
+    private final EnumMap<ReferenceType, String> startingCharacters;
 
     public MarkdownCustomReferenceRendererService() {
-        supportedTags = Set.of("user", "channel");
-        startingCharacters = new HashMap<>();
-        startingCharacters.put("user", "@");
-        startingCharacters.put("channel", "#");
+        startingCharacters = new EnumMap<>(ReferenceType.class);
+        for (ReferenceType type : ReferenceType.values()) {
+            startingCharacters.put(type, type.getPrefix());
+        }
     }
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java (1)

Line range hint 142-170: Add test coverage for new rendering functionality.

The current test suite focuses on email sending and exception handling but lacks coverage for the new rendering features. To ensure the PR objectives are met, consider adding the following test cases:

  1. Attachment rendering tests:

    • Test proper rendering of attachment links
    • Verify conversion of relative to absolute URLs
    • Check handling of invalid attachments
  2. Reference rendering tests:

    • Test proper rendering of user references
    • Verify proper name display format
    • Check handling of invalid references

Example test structure:

@Test
void testAttachmentRendering() {
    // Given
    Post post = createPostWithAttachment();
    when(linkRendererService.render(any())).thenReturn("rendered_attachment_link");
    
    // When
    mailService.sendNotification(...);
    
    // Then
    verify(linkRendererService).render(any());
    // Add assertions for proper rendering
}

@Test
void testUserReferenceRendering() {
    // Given
    Post post = createPostWithUserReference();
    when(referenceRendererService.render(any())).thenReturn("@username");
    
    // When
    mailService.sendNotification(...);
    
    // Then
    verify(referenceRendererService).render(any());
    // Add assertions for proper rendering
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 31bd52c and 36571c2.

📒 Files selected for processing (10)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MailService.java (4 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomRendererService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java (2 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java (1 hunks)
  • src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomRendererService.java
🧰 Additional context used
📓 Path-based instructions (9)
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MailService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java (1)

Pattern src/main/java/**/*.java: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java (1)

Pattern src/test/java/**/*.java: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true

🔇 Additional comments (13)
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java (2)

1-6: LGTM! Clean and minimal imports.

The package structure and imports are well-organized, using specific imports rather than wildcard imports.


17-17: Verify the MarkdownImageBlockRenderer implementation.

Let's ensure that the MarkdownImageBlockRenderer class exists and is properly implemented.

✅ Verification successful

Let me try a different approach to search for the implementation.


Let me check the complete implementation of MarkdownImageBlockRenderer to verify it properly implements NodeRenderer.


MarkdownImageBlockRenderer implementation is properly verified

The class correctly implements the NodeRenderer interface with both required methods:

  • getNodeTypes(): Returns a Set containing Image.class
  • render(Node): Implements image rendering logic by creating an HTML anchor tag with the image destination
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for the existence and implementation of MarkdownImageBlockRenderer

# Search for the class definition
echo "Searching for MarkdownImageBlockRenderer class definition:"
ast-grep --pattern 'class MarkdownImageBlockRenderer {
  $$$
}'

# Search for NodeRenderer implementation
echo "Verifying NodeRenderer implementation:"
ast-grep --pattern 'class MarkdownImageBlockRenderer implements NodeRenderer {
  $$$
}'

Length of output: 617


Script:

#!/bin/bash
# Search for MarkdownImageBlockRenderer using ripgrep
echo "Searching for MarkdownImageBlockRenderer class:"
rg -l "class MarkdownImageBlockRenderer"

echo -e "\nSearching for MarkdownImageBlockRenderer implementation details:"
rg "class MarkdownImageBlockRenderer" -A 10

Length of output: 3607


Script:

#!/bin/bash
# Get the complete implementation of MarkdownImageBlockRenderer
echo "Complete MarkdownImageBlockRenderer implementation:"
cat src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java

Length of output: 1372

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownRelativeToAbsolutePathAttributeProvider.java (2)

1-7: LGTM! Clean and well-organized imports.

Package structure and imports follow best practices with specific imports and proper organization.


1-32: Verify coverage of all announcement email rendering requirements.

While the implementation handles relative to absolute URL conversion, let's verify if this covers all the requirements mentioned in the PR objectives regarding attachments and references.

✅ Verification successful

Let me gather more information about the email rendering implementation to verify the requirements.


Implementation correctly handles URL transformations for email rendering

The implementation is verified to be complete and working as intended:

  1. The MarkdownRelativeToAbsolutePathAttributeProvider is properly integrated into the MailService along with other complementary components:
    • Works alongside MarkdownImageBlockRenderer for image handling
    • Used in conjunction with MarkdownCustomLinkRendererService for link transformations
  2. The implementation handles both attachments and references through:
    • Converting relative URLs to absolute ones for links (href attributes)
    • Supporting image blocks through dedicated renderer
    • Proper base URL injection from the server configuration
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related test files to ensure all scenarios are covered
fd -e java -e kt "Test.*\.java$|.*Test\.java$" | grep -i "announcement\|email\|notification"

# Search for attachment and reference related code
rg -t java "attachment|reference" --glob "src/main/**/notification/**"

Length of output: 6401


Script:

#!/bin/bash
# Check for email rendering related tests and implementations
rg -t java "MarkdownRelativeToAbsolutePathAttributeProvider" -B 2 -A 5

# Look for other URL or path transformation logic in notifications
rg -t java "baseUrl|setAttributes|href" --glob "src/main/**/notifications/**"

# Check for markdown rendering tests
ast-grep --pattern 'class $_ {
  $$$
  @Test
  $_() {
    $$$
    MarkdownRelativeToAbsolutePathAttributeProvider $$$
    $$$
  }
}'

Length of output: 7239

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRenderer.java (3)

1-12: LGTM! Package and imports are well-organized.

The package naming and import statements follow Java best practices with specific imports.


24-27: LGTM! Clean and efficient implementation.

The method correctly specifies that this renderer handles Image nodes using an immutable set.


1-44: Verify integration with MailService.

Let's verify that this renderer is properly integrated with the email service and handles all image scenarios correctly.

✅ Verification successful

Let me check the integration details by examining the MailService implementation and the factory class.


Let me check how the image URLs are handled in the rest of the codebase to ensure this implementation aligns with the existing patterns.


Integration verified and implementation looks correct

The implementation is properly integrated and works as intended:

  • MailService correctly uses the renderer through MarkdownImageBlockRendererFactory
  • The renderer handles image URLs by prepending the artemisServerUrl
  • The implementation gracefully handles both cases: when image has text (through firstChild) and fallback to destination
  • The factory properly initializes the renderer with the required baseUrl
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of MarkdownImageBlockRenderer in MailService
echo "Checking MailService integration..."
rg -l "MarkdownImageBlockRenderer" "src/main/java/de/tum/cit/aet/artemis/communication/service/"

# Search for test coverage
echo "Checking test coverage..."
fd -e java -e kt "MarkdownImageBlockRenderer.*Test" "src/test/"

Length of output: 607


Script:

#!/bin/bash
# Check MailService implementation
echo "Checking MailService implementation..."
rg -A 10 "MarkdownImageBlockRenderer" "src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MailService.java"

# Check factory implementation
echo "Checking factory implementation..."
cat "src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownImageBlockRendererFactory.java"

Length of output: 1657


Script:

#!/bin/bash
# Search for image URL handling patterns
echo "Checking image URL handling patterns..."
rg -g '*.java' -B 2 -A 2 'getDestination\(\)' --no-filename

# Check if there are any existing image-related tests
echo "Checking existing image-related tests..."
rg -g '*Test.java' -l 'Image|image.*attachment'

Length of output: 3431

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java (1)

1-9: LGTM! Clean and minimal imports.

The package structure and imports follow best practices with static imports for assertions and specific JUnit 5 annotations.

src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java (1)

1-71: Test implementation follows coding guidelines.

The test class demonstrates good compliance with the project's testing guidelines:

  • Descriptive test names following behavior-driven style
  • Small, focused test methods
  • Proper use of JUnit 5 features
  • AssertJ assertions with specific checks
  • Fixed test data
src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomLinkRendererService.java (1)

43-70: Verify rendering behavior with integration tests

While the implementation looks correct, we should verify the rendering behavior with integration tests.

✅ Verification successful

Tests already cover the rendering functionality comprehensively

The implementation is already well-tested with unit tests that cover:

  • Basic tag rendering with proper URL construction
  • Multiple tag rendering in the same content
  • Handling of unsupported tags
  • Edge cases (missing links, empty input)
  • Integration with MailService

The test cases align perfectly with the implementation's objectives and verify the proper handling of announcement email rendering issues.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Look for existing integration tests that cover this functionality

# Search for test files related to announcements and emails
echo "Searching for related test files..."
fd -e java -e groovy -e kt test announcement email

# Search for specific test patterns
echo "Searching for specific test patterns..."
rg -l "announcement.*email" -t java -t groovy -t kt

# Look for existing markdown rendering tests
echo "Searching for markdown rendering tests..."
rg -l "markdown.*render" -t java -t groovy -t kt

Length of output: 626


Script:

#!/bin/bash
# Let's try a different approach to find test files

# Search for test files related to MarkdownCustomLinkRendererService
echo "Searching for test files related to MarkdownCustomLinkRendererService..."
fd -e java "MarkdownCustomLinkRendererService.*Test"

# Search for test files containing "markdown" in their name
echo "Searching for markdown-related test files..."
fd -e java ".*[Mm]arkdown.*Test"

# Look for test files that might test this functionality
echo "Searching for test content..."
rg -l --type java "class.*Test.*Markdown|class.*Test.*Notification|class.*Test.*Email"

# Search for usage of the renderer service in tests
echo "Searching for renderer service usage in tests..."
rg -l --type java "MarkdownCustomLinkRendererService" "src/test"

Length of output: 1331


Script:

#!/bin/bash
# Let's examine the content of the test files we found

# Check the MarkdownCustomLinkRendererServiceTest content
echo "Content of MarkdownCustomLinkRendererServiceTest.java:"
cat "src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java"

# Check how it's used in MailServiceTest
echo -e "\nRelevant parts of MailServiceTest.java:"
rg -A 5 -B 5 "MarkdownCustomLinkRendererService" "src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java"

Length of output: 4452

src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MarkdownCustomReferenceRendererService.java (1)

1-72: Verify complete implementation of PR objectives

While this class handles reference rendering, the PR objectives mention fixing both references and attachments in announcement emails. Please verify:

  1. Where is the attachment rendering implementation?
  2. How does this service integrate with the email rendering pipeline?
src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MailServiceTest.java (2)

34-35: LGTM: Import statements are properly organized.

The new imports align with the PR's objective of improving email rendering capabilities.


Line range hint 1-170: Verify integration with related components.

To ensure proper integration of the new rendering services, let's verify the related components:

✅ Verification successful

Integration is properly implemented and tested

The verification shows that:

  • Both renderer services are properly integrated into MailService through constructor injection and stored in markdownCustomRendererServices list
  • Both services have comprehensive test coverage with dedicated test classes
  • MarkdownCustomLinkRendererServiceTest covers URL rendering scenarios
  • MarkdownCustomReferenceRendererServiceTest covers user and channel reference rendering
  • Error cases and edge conditions are properly tested in both services
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for proper integration of renderer services

# Check for test coverage in related test files
echo "Checking for related test files..."
fd -e java -p "MarkdownCustom.*RendererServiceTest"

# Check for proper usage of renderer services in MailService
echo "Checking MailService implementation..."
rg -A 5 "class MailService" src/main/java

Length of output: 1237


Script:

#!/bin/bash
# Let's check the implementation details of MailService and its integration with renderer services

# Check how MailService uses the renderer services
echo "Checking MailService usage of renderer services..."
rg -A 10 "MarkdownCustom.*RendererService" src/main/java/de/tum/cit/aet/artemis/communication/service/notifications/MailService.java

# Check if renderer services are properly tested
echo "Checking renderer service test implementations..."
cat src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomLinkRendererServiceTest.java
echo "---"
cat src/test/java/de/tum/cit/aet/artemis/communication/notifications/service/MarkdownCustomReferenceRendererServiceTest.java

Length of output: 6196

Copy link

@HawKhiem HawKhiem left a comment

Choose a reason for hiding this comment

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

Tested on TS3. Everything works perfectly. Images and tags are indeed rendered as links and bring me to the material upon clicking on

Screenshot 2024-11-22 194246
Screenshot 2024-11-22 194412
image

Copy link

@zagemello zagemello left a comment

Choose a reason for hiding this comment

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

image
All works as expected, tested on TS3

Copy link
Contributor

@cremertim cremertim left a comment

Choose a reason for hiding this comment

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

Code changes lgtm

Copy link

@alekspetrov9e alekspetrov9e left a comment

Choose a reason for hiding this comment

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

Works as expected. Email was received.

@krusche krusche changed the title Communication: Fix announcement e-mails not rendering attachments and references properly Communication: Fix announcement emails not rendering correctly Nov 25, 2024
Copy link
Member

@krusche krusche left a comment

Choose a reason for hiding this comment

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

Great work 👍

@krusche krusche added this to the 7.7.3 milestone Nov 26, 2024
@krusche krusche added the maintainer-approved The feature maintainer has approved the PR label Nov 26, 2024
@krusche krusche merged commit e8ecd40 into develop Nov 26, 2024
21 of 25 checks passed
@krusche krusche deleted the bugfix/communication/render-attachments-in-announcement-e-mails branch November 26, 2024 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugfix communication Pull requests that affect the corresponding module component:Communication maintainer-approved The feature maintainer has approved the PR ready to merge server Pull requests that update Java code. (Added Automatically!) tests
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

9 participants