mirror of
https://github.com/go-vikunja/vikunja.git
synced 2026-03-11 17:48:44 -05:00
test: add tests for conversational email system
Add tests for conversational header generation, HTML rendering with p-tag wrapping, plain-text conversion, footer handling, and conditional action links. Update mention test fixtures with Project field.
This commit is contained in:
@@ -117,6 +117,8 @@ func TestSendingMentionNotification(t *testing.T) {
|
||||
|
||||
task, err := GetTaskByIDSimple(s, 32)
|
||||
require.NoError(t, err)
|
||||
project, err := GetProjectSimpleByID(s, task.ProjectID)
|
||||
require.NoError(t, err)
|
||||
tc := &TaskComment{
|
||||
Comment: `<p>Lorem Ipsum <mention-user data-id="user1">@user1</mention-user> <mention-user data-id="user2">@user2</mention-user> <mention-user data-id="user3">@user3</mention-user> <mention-user data-id="user4">@user4</mention-user> <mention-user data-id="user5">@user5</mention-user> <mention-user data-id="user6">@user6</mention-user></p>`,
|
||||
TaskID: 32, // user2 has access to the project that task belongs to
|
||||
@@ -127,6 +129,7 @@ func TestSendingMentionNotification(t *testing.T) {
|
||||
Doer: u,
|
||||
Task: &task,
|
||||
Comment: tc,
|
||||
Project: project,
|
||||
}
|
||||
|
||||
_, err = notifyMentionedUsers(s, &task, tc.Comment, n)
|
||||
@@ -171,6 +174,8 @@ func TestSendingMentionNotification(t *testing.T) {
|
||||
|
||||
task, err := GetTaskByIDSimple(s, 32)
|
||||
require.NoError(t, err)
|
||||
project, err := GetProjectSimpleByID(s, task.ProjectID)
|
||||
require.NoError(t, err)
|
||||
tc := &TaskComment{
|
||||
Comment: `<p>Lorem Ipsum <mention-user data-id="user2">@user2</mention-user></p>`,
|
||||
TaskID: 32, // user2 has access to the project that task belongs to
|
||||
@@ -181,6 +186,7 @@ func TestSendingMentionNotification(t *testing.T) {
|
||||
Doer: u,
|
||||
Task: &task,
|
||||
Comment: tc,
|
||||
Project: project,
|
||||
}
|
||||
|
||||
_, err = notifyMentionedUsers(s, &task, tc.Comment, n)
|
||||
|
||||
@@ -134,7 +134,7 @@ This is a line
|
||||
assertHTMLContainsDarkModeSupport(t, mailopts.HTMLMessage)
|
||||
|
||||
// Check for expected content
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p>This is a line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p style="margin-top: 10px; margin-bottom: 10px;">This is a line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `Hi there,`)
|
||||
|
||||
// Verify no action button is present
|
||||
@@ -224,8 +224,8 @@ This is a footer line
|
||||
assertHTMLContainsDarkModeSupport(t, mailopts.HTMLMessage)
|
||||
|
||||
// Check for content
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p>This is a line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p>This is a footer line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p style="margin-top: 10px; margin-bottom: 10px;">This is a line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `This is a footer line`)
|
||||
|
||||
// Verify no action button
|
||||
assert.NotContains(t, mailopts.HTMLMessage, `class="email-button"`)
|
||||
@@ -277,7 +277,7 @@ This is a footer line
|
||||
assert.Contains(t, mailopts.HTMLMessage, `href="https://example.com"`)
|
||||
|
||||
// Check for footer
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<p>This is a footer line</p>`)
|
||||
assert.Contains(t, mailopts.HTMLMessage, `This is a footer line`)
|
||||
})
|
||||
t.Run("with thread ID", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
@@ -488,3 +488,224 @@ This is a footer line
|
||||
assert.Contains(t, mailopts.HTMLMessage, `<strong>attention</strong>`)
|
||||
})
|
||||
}
|
||||
|
||||
func TestConversationalMail(t *testing.T) {
|
||||
t.Run("Conversational flag", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Conversational().
|
||||
Line("This is a conversational message")
|
||||
|
||||
assert.True(t, mail.IsConversational())
|
||||
})
|
||||
|
||||
t.Run("Default is not conversational", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Line("This is a formal message")
|
||||
|
||||
assert.False(t, mail.IsConversational())
|
||||
})
|
||||
|
||||
t.Run("Conversational template selection", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Conversational().
|
||||
Line("This is a conversational message").
|
||||
Action("View Task", "https://example.com/task/123")
|
||||
|
||||
mailopts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should not contain greeting section
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "<p>\n\t\t\n\t</p>")
|
||||
|
||||
// Should use conversational styling
|
||||
assert.Contains(t, mailopts.HTMLMessage, "background: #f6f8fa")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "font-family: -apple-system")
|
||||
|
||||
// Should NOT have logo (completely removed)
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "logo.png")
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "Vikunja")
|
||||
|
||||
// Should have inline action link with arrow
|
||||
assert.Contains(t, mailopts.HTMLMessage, "View Task →")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "color: #0969da")
|
||||
|
||||
// Should not have the formal button styling
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "background-color: #1973ff")
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "width:280px")
|
||||
|
||||
// Plain text should not have greeting
|
||||
assert.NotContains(t, mailopts.Message, "Hi there,")
|
||||
assert.Contains(t, mailopts.Message, "This is a conversational message")
|
||||
})
|
||||
|
||||
t.Run("Formal template still works", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Greeting("Hi there,").
|
||||
Line("This is a formal message").
|
||||
Action("View Task", "https://example.com/task/123")
|
||||
|
||||
mailopts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should contain greeting
|
||||
assert.Contains(t, mailopts.HTMLMessage, "Hi there,")
|
||||
|
||||
// Should use formal styling
|
||||
assert.Contains(t, mailopts.HTMLMessage, "background: #f3f4f6")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "font-family: 'Open Sans'")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "width: 600px")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "height: 75px")
|
||||
|
||||
// Should HAVE logo in formal emails
|
||||
assert.Contains(t, mailopts.HTMLMessage, "logo.png")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "Vikunja")
|
||||
|
||||
// Should have formal button styling
|
||||
assert.Contains(t, mailopts.HTMLMessage, "background-color: #1973ff")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "width:280px")
|
||||
|
||||
// Should not have conversational arrow
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "View Task →")
|
||||
|
||||
// Plain text should have greeting
|
||||
assert.Contains(t, mailopts.Message, "Hi there,")
|
||||
})
|
||||
|
||||
t.Run("Conversational without action", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Conversational().
|
||||
Line("This is a conversational message without action")
|
||||
|
||||
mailopts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should use conversational styling
|
||||
assert.Contains(t, mailopts.HTMLMessage, "background: #f6f8fa")
|
||||
|
||||
// Should not have action section
|
||||
assert.NotContains(t, mailopts.HTMLMessage, "border-top: 1px solid #e5e7eb")
|
||||
})
|
||||
|
||||
t.Run("Conversational with footer", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
From("test@example.com").
|
||||
To("test@otherdomain.com").
|
||||
Subject("Testmail").
|
||||
Conversational().
|
||||
Line("This is a conversational message").
|
||||
FooterLine("This is a footer line")
|
||||
|
||||
mailopts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should have footer with conversational styling
|
||||
assert.Contains(t, mailopts.HTMLMessage, "color: #656d76")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "font-size: 12px")
|
||||
assert.Contains(t, mailopts.HTMLMessage, "This is a footer line")
|
||||
})
|
||||
|
||||
t.Run("Conversational header line format", func(t *testing.T) {
|
||||
action := "testuser left a comment"
|
||||
taskURL := "https://example.com/task/123"
|
||||
projectTitle := "Test Project"
|
||||
taskTitle := "Test Task"
|
||||
taskIdentifier := "#1"
|
||||
|
||||
headerLine := CreateConversationalHeader("", action, taskURL, projectTitle, taskIdentifier, taskTitle)
|
||||
|
||||
// Should contain action with username
|
||||
assert.Contains(t, headerLine, "testuser left a comment")
|
||||
|
||||
// Should contain task link with identifier and GitHub blue color
|
||||
assert.Contains(t, headerLine, `<a href="https://example.com/task/123"`)
|
||||
assert.Contains(t, headerLine, `color: #0969da`)
|
||||
assert.Contains(t, headerLine, `(Test Project > Test Task) #1`)
|
||||
})
|
||||
|
||||
t.Run("Conversational action link font size", func(t *testing.T) {
|
||||
mail := NewMail().
|
||||
Conversational().
|
||||
Subject("Test").
|
||||
Line("Content").
|
||||
Action("View Task", "https://example.com/task/123")
|
||||
|
||||
mailOpts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Action link should have smaller font size than main content
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `font-size: 14px; line-height: 1.5`) // Main content
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `font-weight: 500; font-size: 12px`) // Action link
|
||||
})
|
||||
|
||||
t.Run("Conversational with header line", func(t *testing.T) {
|
||||
header := CreateConversationalHeader("", "testuser left a comment", "https://example.com/task/123", "Project", "#1", "Task")
|
||||
mail := NewMail().
|
||||
Conversational().
|
||||
Subject("Test").
|
||||
HeaderLine(header).
|
||||
HTML("<p>This is the comment body</p>").
|
||||
Action("View Task", "https://example.com/task/123")
|
||||
|
||||
mailOpts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Header should be in its own section
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `color: #57606a`)
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `testuser left a comment`)
|
||||
|
||||
// Body content should be separate from the header
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `This is the comment body`)
|
||||
|
||||
// Plain text should contain the header text
|
||||
assert.Contains(t, mailOpts.Message, "testuser left a comment")
|
||||
})
|
||||
|
||||
t.Run("Conversational header line only (no body)", func(t *testing.T) {
|
||||
header := CreateConversationalHeader("", "testuser assigned you", "https://example.com/task/123", "Project", "#1", "Task")
|
||||
mail := NewMail().
|
||||
Conversational().
|
||||
Subject("Test").
|
||||
HeaderLine(header).
|
||||
Action("View Task", "https://example.com/task/123")
|
||||
|
||||
mailOpts, err := RenderMail(mail, "en")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Header should render
|
||||
assert.Contains(t, mailOpts.HTMLMessage, `testuser assigned you`)
|
||||
|
||||
// Should not have the content section when there are no intro/outro lines
|
||||
assert.NotContains(t, mailOpts.HTMLMessage, `padding: 20px; padding-bottom: 0; color: #24292f`)
|
||||
})
|
||||
|
||||
t.Run("Translation system integration", func(t *testing.T) {
|
||||
// Test that translation keys are properly structured
|
||||
// This verifies the translation keys exist and are accessible
|
||||
|
||||
// Test action translations
|
||||
headerLine1 := CreateConversationalHeader("", "John left a comment", "https://example.com", "Project", "#1", "Task")
|
||||
assert.Contains(t, headerLine1, "John left a comment")
|
||||
|
||||
headerLine2 := CreateConversationalHeader("", "Jane assigned you", "https://example.com", "Project", "#2", "Task")
|
||||
assert.Contains(t, headerLine2, "Jane assigned you")
|
||||
|
||||
// Verify header structure is maintained
|
||||
assert.Contains(t, headerLine1, `color: #0969da`)
|
||||
assert.Contains(t, headerLine1, "(Project > Task) #1")
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user