Skip to content
This repository was archived by the owner on May 23, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,10 @@ Every template must use this boilerplate:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
```
Expand Down
7 changes: 2 additions & 5 deletions avatar-upload/avatar-upload.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -80,10 +82,5 @@
</article>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
7 changes: 2 additions & 5 deletions chat/chat.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -58,10 +60,5 @@
</article>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
7 changes: 2 additions & 5 deletions counter/counter.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand All @@ -33,10 +35,5 @@
</article>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
7 changes: 2 additions & 5 deletions dialog-patterns/dialog-patterns.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -73,10 +75,5 @@
</article>
</dialog>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
62 changes: 39 additions & 23 deletions dialog-patterns/dialog_patterns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,45 +259,64 @@ func TestDialogPatternsE2E(t *testing.T) {
})

t.Run("Add_Empty_Title_Error", func(t *testing.T) {
// Open the dialog and submit with empty title
// Navigate fresh to get clean polyfill state (command/commandfor listeners
// are lost after WebSocket DOM updates from the previous test)
err := chromedp.Run(ctx,
chromedp.Navigate(e2etest.GetChromeTestURL(serverPort)),
e2etest.WaitForWebSocketReady(5*time.Second),
chromedp.WaitVisible(`h1`, chromedp.ByQuery),
)
if err != nil {
t.Fatalf("Failed to reload page: %v", err)
}

// Open the dialog
err = chromedp.Run(ctx,
chromedp.Click(`button[commandfor="add-dialog"][command="show-modal"]`, chromedp.ByQuery),
e2etest.WaitFor(`document.getElementById('add-dialog').open === true`, 5*time.Second),
)
if err != nil {
t.Fatalf("Failed to open dialog: %v", err)
}

// The input has `required`, so browser validation prevents empty submission.
// Remove `required` via JS to test server-side validation.
err = chromedp.Run(ctx,
chromedp.Evaluate(`document.querySelector('dialog#add-dialog input[name="title"]').removeAttribute('required')`, nil),
chromedp.Clear(`dialog#add-dialog input[name="title"]`, chromedp.ByQuery),
chromedp.Click(`dialog#add-dialog button[type="submit"]`, chromedp.ByQuery),
e2etest.WaitFor(`true`, 2*time.Second), // wait for server response
Comment on lines +284 to +288

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

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

e2etest.WaitFor('true', 2*time.Second) does not actually wait (the JS expression is immediately true), so this subtest can proceed before the server/WebSocket-driven DOM update has applied. Replace it with a wait condition that reflects the expected post-submit state (e.g., wait for a validation error element/aria-invalid, or for the dialog content to re-render).

Suggested change
err = chromedp.Run(ctx,
chromedp.Evaluate(`document.querySelector('dialog#add-dialog input[name="title"]').removeAttribute('required')`, nil),
chromedp.Clear(`dialog#add-dialog input[name="title"]`, chromedp.ByQuery),
chromedp.Click(`dialog#add-dialog button[type="submit"]`, chromedp.ByQuery),
e2etest.WaitFor(`true`, 2*time.Second), // wait for server response
// Snapshot the dialog content first, then wait for it to change after submit.
err = chromedp.Run(ctx,
chromedp.Evaluate(`document.querySelector('dialog#add-dialog input[name="title"]').removeAttribute('required')`, nil),
chromedp.Evaluate(`window.__addDialogBeforeSubmitHTML = document.getElementById('add-dialog').innerHTML`, nil),
chromedp.Clear(`dialog#add-dialog input[name="title"]`, chromedp.ByQuery),
chromedp.Click(`dialog#add-dialog button[type="submit"]`, chromedp.ByQuery),
e2etest.WaitFor(`document.getElementById('add-dialog') && document.getElementById('add-dialog').innerHTML !== window.__addDialogBeforeSubmitHTML`, 2*time.Second),

Copilot uses AI. Check for mistakes.
)
if err != nil {
t.Fatalf("Failed to submit empty form: %v", err)
}

// Item count should remain 4 (unchanged from Add_Item_Via_Dialog)
// Item count should remain 3 (unchanged — fresh session has seed items)
var html string
err = chromedp.Run(ctx,
e2etest.WaitFor(`true`, 1*time.Second), // brief wait for any server response
chromedp.OuterHTML(`body`, &html, chromedp.ByQuery),
)
err = chromedp.Run(ctx, chromedp.OuterHTML(`body`, &html, chromedp.ByQuery))
if err != nil {
t.Fatalf("Failed to get HTML: %v", err)
}
if !strings.Contains(html, "4 items") {
t.Error("Item count should still be '4 items' after failed empty submission")
if !strings.Contains(html, "3 items") {
t.Error("Item count should still be '3 items' after failed empty submission")
}

// Close dialog for next test
err = chromedp.Run(ctx,
chromedp.Click(`button[commandfor="add-dialog"][command="close"]`, chromedp.ByQuery),
e2etest.WaitFor(`document.getElementById('add-dialog').open === false`, 5*time.Second),
t.Log("✅ Empty title submission rejected by server, item count unchanged")
})

t.Run("Delete_Item", func(t *testing.T) {
// Navigate fresh to get clean state
err := chromedp.Run(ctx,
chromedp.Navigate(e2etest.GetChromeTestURL(serverPort)),
e2etest.WaitForWebSocketReady(5*time.Second),
chromedp.WaitVisible(`table`, chromedp.ByQuery),
)
if err != nil {
t.Fatalf("Failed to close dialog: %v", err)
t.Fatalf("Failed to reload page: %v", err)
}

t.Log("✅ Empty title submission rejected, item count unchanged")
})

t.Run("Delete_Item", func(t *testing.T) {
// Delete the first seed item (Learn LiveTemplate)
err := chromedp.Run(ctx,
err = chromedp.Run(ctx,
chromedp.Click(`button[name="delete"][value="1"]`, chromedp.ByQuery),
e2etest.WaitFor(`!document.body.innerText.includes('Learn LiveTemplate')`, 5*time.Second),
)
Expand All @@ -320,11 +339,8 @@ func TestDialogPatternsE2E(t *testing.T) {
if !strings.Contains(html, "Write E2E tests") {
t.Error("Remaining item 'Write E2E tests' should be present")
}
if !strings.Contains(html, "New Test Item") {
t.Error("Previously added item 'New Test Item' should be present")
}
if !strings.Contains(html, "3 items") {
t.Error("Item count should be '3 items' after deletion")
if !strings.Contains(html, "2 items") {
t.Error("Item count should be '2 items' after deletion")
}

t.Log("✅ Item deleted, remaining items preserved")
Expand Down
7 changes: 2 additions & 5 deletions flash-messages/flash.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -90,10 +92,5 @@
</details>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
7 changes: 2 additions & 5 deletions live-preview/preview.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand All @@ -32,10 +34,5 @@
</article>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
8 changes: 3 additions & 5 deletions login/templates/auth.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -53,10 +55,6 @@ <h1>Login</h1>
</article>
{{end}}
</main>
{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}

</body>
</html>
7 changes: 2 additions & 5 deletions progressive-enhancement/progressive-enhancement.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
{{if .lvt.DevMode}}
<link rel="stylesheet" href="/livetemplate.css">
<script defer src="/livetemplate-client.js"></script>
{{else}}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/livetemplate.css">
<script defer src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</head>
<body>
Expand Down Expand Up @@ -88,10 +90,5 @@
</article>
</main>

{{if .lvt.DevMode}}
<script src="/livetemplate-client.js"></script>
{{else}}
<script src="https://cdn.jsdelivr.net/npm/@livetemplate/client@latest/dist/livetemplate-client.browser.js"></script>
{{end}}
</body>
</html>
Loading
Loading