Compare commits
3 Commits
refactor/s
...
fix/temp-d
| Author | SHA1 | Date | |
|---|---|---|---|
| 88bbdd2c5d | |||
| efa2d83cab | |||
| c112797875 |
@@ -355,11 +355,16 @@ func (m Model) RenderCardList() string {
|
|||||||
boxes = append(boxes, box)
|
boxes = append(boxes, box)
|
||||||
}
|
}
|
||||||
|
|
||||||
sshFocused := m.payment.cardCursor == len(m.SavedCards)
|
// SSH inline card-add is dormant until i have a norwegian org
|
||||||
sshBox := m.CreateBox(m.formatListItem("+ add card via ssh", sshFocused), sshFocused)
|
// number wired to stripe, something i dont have since its $300+. Keep the row visible so the option is
|
||||||
|
// discoverable, but render it dimmed and exclude it from cursor space
|
||||||
|
// (handled in PaymentUpdate below) so it can not be picked
|
||||||
|
dim := m.theme.TextDim().Render
|
||||||
|
sshLabel := dim("+ add card via ssh") + " " + dim("(WIP)")
|
||||||
|
sshBox := m.CreateBox(m.formatListItem(sshLabel, false), false)
|
||||||
boxes = append(boxes, sshBox)
|
boxes = append(boxes, sshBox)
|
||||||
|
|
||||||
httpsFocused := m.payment.cardCursor == len(m.SavedCards)+1
|
httpsFocused := m.payment.cardCursor == len(m.SavedCards)
|
||||||
httpsBox := m.CreateBox(m.formatListItem("+ add payment via browser", httpsFocused), httpsFocused)
|
httpsBox := m.CreateBox(m.formatListItem("+ add payment via browser", httpsFocused), httpsFocused)
|
||||||
boxes = append(boxes, httpsBox)
|
boxes = append(boxes, httpsBox)
|
||||||
|
|
||||||
@@ -501,7 +506,7 @@ func (m Model) PaymentUpdate(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
m.payment.cardCursor--
|
m.payment.cardCursor--
|
||||||
}
|
}
|
||||||
case "down", "j":
|
case "down", "j":
|
||||||
if m.payment.cardCursor < len(m.SavedCards)+1 {
|
if m.payment.cardCursor < len(m.SavedCards) {
|
||||||
m.payment.cardCursor++
|
m.payment.cardCursor++
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,17 +516,8 @@ func (m Model) PaymentUpdate(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
m.SelectedCard = &selected
|
m.SelectedCard = &selected
|
||||||
return m.ReviewSwitch()
|
return m.ReviewSwitch()
|
||||||
}
|
}
|
||||||
if m.payment.cardCursor == len(m.SavedCards) {
|
// Browser flow, the only reachable add-card path while the SSH
|
||||||
m.payment.view = 1
|
// inline form is dormant (see RenderCardList)
|
||||||
m.payment.form = m.InitPaymentForm()
|
|
||||||
m.footer = []footerCommand{
|
|
||||||
{key: "tab", value: "next"},
|
|
||||||
{key: "enter", value: "submit"},
|
|
||||||
{key: "esc", value: "back"},
|
|
||||||
}
|
|
||||||
return m, m.payment.form.form.Init()
|
|
||||||
}
|
|
||||||
// Browser payment
|
|
||||||
m.payment.view = 2
|
m.payment.view = 2
|
||||||
m.payment.collectURL = nil
|
m.payment.collectURL = nil
|
||||||
m.payment.collectTimeOut = false
|
m.payment.collectTimeOut = false
|
||||||
@@ -546,16 +542,6 @@ func (m Model) PaymentUpdate(msg tea.Msg) (Model, tea.Cmd) {
|
|||||||
if m.payment.cardCursor >= len(m.SavedCards) && m.payment.cardCursor > 0 {
|
if m.payment.cardCursor >= len(m.SavedCards) && m.payment.cardCursor > 0 {
|
||||||
m.payment.cardCursor--
|
m.payment.cardCursor--
|
||||||
}
|
}
|
||||||
if len(m.SavedCards) == 0 {
|
|
||||||
m.payment.view = 1
|
|
||||||
m.payment.form = m.InitPaymentForm()
|
|
||||||
m.footer = []footerCommand{
|
|
||||||
{key: "tab", value: "next"},
|
|
||||||
{key: "enter", value: "submit"},
|
|
||||||
{key: "esc", value: "back"},
|
|
||||||
}
|
|
||||||
return m, tea.Batch(m.payment.form.form.Init(), m.deleteCardCmd(card.ID))
|
|
||||||
}
|
|
||||||
return m, m.deleteCardCmd(card.ID)
|
return m, m.deleteCardCmd(card.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
91
pkg/tui/payment_form_test.go
Normal file
91
pkg/tui/payment_form_test.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"terminalShop/pkg/models"
|
||||||
|
|
||||||
|
tea "charm.land/bubbletea/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// newPaymentCardListModel parks a Model on the payment page card-list view
|
||||||
|
// with n synthetic saved cards. Baseline for assertint that the dormant
|
||||||
|
// "+ add card via ssh" row is dimmed and unreachable by cursor navigation.
|
||||||
|
func newPaymentCardListModel(t *testing.T, n int) Model {
|
||||||
|
t.Helper()
|
||||||
|
m := NewModel("test")
|
||||||
|
m = m.updateLayout(120, 40)
|
||||||
|
m.currentPage = paymentPage
|
||||||
|
m.payment.view = 0
|
||||||
|
m.payment.form = nil
|
||||||
|
m.payment.cardCursor = 0
|
||||||
|
for i := range n {
|
||||||
|
m.SavedCards = append(m.SavedCards, models.Card{
|
||||||
|
ID: uint(i + 1),
|
||||||
|
Brand: "visa",
|
||||||
|
Last4: "4242",
|
||||||
|
ExpMonth: 12,
|
||||||
|
ExpYear: 2030,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyEnter() tea.KeyMsg { return tea.KeyPressMsg{Code: tea.KeyEnter} }
|
||||||
|
|
||||||
|
func TestRenderCardList_SshOptionComingSoon(t *testing.T) {
|
||||||
|
m := newPaymentCardListModel(t, 1)
|
||||||
|
out := m.RenderCardList()
|
||||||
|
if !strings.Contains(out, "add card via ssh") {
|
||||||
|
t.Fatalf("ssh option missing from card list output:\n%s", out)
|
||||||
|
}
|
||||||
|
if !strings.Contains(out, "WIP") {
|
||||||
|
t.Fatalf("want 'WIP' marked on ssh option:\n%s", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPaymentUpdate_DownNavigationStopsAtBrowserSlot(t *testing.T) {
|
||||||
|
m := newPaymentCardListModel(t, 2)
|
||||||
|
for range 10 {
|
||||||
|
var cmd tea.Cmd
|
||||||
|
m, cmd = m.PaymentUpdate(keyJ())
|
||||||
|
_ = cmd
|
||||||
|
}
|
||||||
|
want := len(m.SavedCards) // browser slot; ssh slot in unreachable
|
||||||
|
if m.payment.cardCursor != want {
|
||||||
|
t.Fatalf("cursor stopped at %d, want %d (browser slot)", m.payment.cardCursor, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPaymentUpdate_EnterOnBrowserSlotLaunchesBrowserFlow(t *testing.T) {
|
||||||
|
m := newPaymentCardListModel(t, 1)
|
||||||
|
m.payment.cardCursor = len(m.SavedCards) // browser slot
|
||||||
|
newM, cmd := m.PaymentUpdate(keyEnter())
|
||||||
|
if newM.payment.view != 2 {
|
||||||
|
t.Fatalf("payment.view = %d, want 2 (browser flow)", newM.payment.view)
|
||||||
|
}
|
||||||
|
if newM.payment.form != nil {
|
||||||
|
t.Fatalf("payment.form must be nil after enter; ssh inline form is dormant")
|
||||||
|
}
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatalf("expected collectCardCmd, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPaymentUpdate_EnterWithZeroCardsLaunchesBrowserFlow(t *testing.T) {
|
||||||
|
m := newPaymentCardListModel(t, 0)
|
||||||
|
if m.payment.cardCursor != 0 {
|
||||||
|
t.Fatalf("default cursor = %d, want 0 ", m.payment.cardCursor)
|
||||||
|
}
|
||||||
|
newM, cmd := m.PaymentUpdate(keyEnter())
|
||||||
|
if newM.payment.view != 2 {
|
||||||
|
t.Fatalf("payment.view = %d, want 2 (browser flow)", newM.payment.view)
|
||||||
|
}
|
||||||
|
if newM.payment.form != nil {
|
||||||
|
t.Fatalf("payment.form must be nil; ssh inline form is dormant")
|
||||||
|
}
|
||||||
|
if cmd == nil {
|
||||||
|
t.Fatalf("expected collectCardCmd, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user