test(17-01): add failing test + view model + message bubble CSS (RED)
- Append .message-row/.message-own/.message-other/.message-bubble/.message-meta CSS classes to app.css - Create discussion_view.go with DiscussionMessageView, DiscussionTabData, NewDiscussionTabData - Create discussion_view_test.go with TestChatMainContentRendersBubbleClasses (RED: compile error expected)
This commit is contained in:
parent
ba48c2c74f
commit
dd1133d7cc
3 changed files with 127 additions and 0 deletions
|
|
@ -1894,3 +1894,55 @@ td.text-right .borderless-icon-button.ui-icon-button-ghost.ui-icon-button-danger
|
||||||
padding: 1.25rem;
|
padding: 1.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Message bubbles ── */
|
||||||
|
|
||||||
|
.message-row {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-own {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-other {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-bubble {
|
||||||
|
border: 1px solid var(--color-border-subtle);
|
||||||
|
border-radius: 0.25rem 0.75rem 0.75rem 0.75rem;
|
||||||
|
max-width: 70%;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-own .message-bubble {
|
||||||
|
background: rgba(128, 78, 236, 0.10);
|
||||||
|
border-radius: 0.75rem 0.75rem 0.25rem 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-other .message-bubble {
|
||||||
|
background: var(--color-surface-default);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-own .message-meta {
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-meta .message-author {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
|
||||||
47
go-backend/internal/web/views/discussion_view.go
Normal file
47
go-backend/internal/web/views/discussion_view.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package views
|
||||||
|
|
||||||
|
// DiscussionMessageView holds the data for a single chat message row.
|
||||||
|
type DiscussionMessageView struct {
|
||||||
|
Author string
|
||||||
|
Timestamp string
|
||||||
|
Body string
|
||||||
|
IsOwn bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// DiscussionTabData holds the full data set for the discussion tab.
|
||||||
|
type DiscussionTabData struct {
|
||||||
|
Messages []DiscussionMessageView
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDiscussionTabData returns a DiscussionTabData populated with hardcoded demo
|
||||||
|
// messages that alternate IsOwn values for visual verification of bubble styles.
|
||||||
|
func NewDiscussionTabData() DiscussionTabData {
|
||||||
|
return DiscussionTabData{
|
||||||
|
Messages: []DiscussionMessageView{
|
||||||
|
{
|
||||||
|
Author: "you@xtablo.com",
|
||||||
|
Timestamp: "09:14",
|
||||||
|
Body: "Hey, any update on the design review?",
|
||||||
|
IsOwn: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Author: "other@xtablo.com",
|
||||||
|
Timestamp: "09:17",
|
||||||
|
Body: "Just finished — sharing the file in the tablo now.",
|
||||||
|
IsOwn: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Author: "you@xtablo.com",
|
||||||
|
Timestamp: "09:19",
|
||||||
|
Body: "Perfect, I'll take a look this afternoon.",
|
||||||
|
IsOwn: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Author: "other@xtablo.com",
|
||||||
|
Timestamp: "09:22",
|
||||||
|
Body: "Sounds good. Let me know if you need changes.",
|
||||||
|
IsOwn: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
28
go-backend/internal/web/views/discussion_view_test.go
Normal file
28
go-backend/internal/web/views/discussion_view_test.go
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
package views
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestChatMainContentRendersBubbleClasses(t *testing.T) {
|
||||||
|
data := DiscussionTabData{
|
||||||
|
Messages: []DiscussionMessageView{
|
||||||
|
{Author: "you@xtablo.com", Timestamp: "09:14", Body: "Hello", IsOwn: true},
|
||||||
|
{Author: "other@xtablo.com", Timestamp: "09:17", Body: "Hi there", IsOwn: false},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
html := renderViewToString(t, ChatMainContent(data))
|
||||||
|
|
||||||
|
for _, want := range []string{
|
||||||
|
`class="ui-card"`,
|
||||||
|
`message-own`,
|
||||||
|
`message-other`,
|
||||||
|
`message-bubble`,
|
||||||
|
} {
|
||||||
|
if !strings.Contains(html, want) {
|
||||||
|
t.Fatalf("expected %q in rendered HTML, got:\n%s", want, html)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue