From 11d52ca426e5c594f7c6c10766935a7f30a83225 Mon Sep 17 00:00:00 2001 From: s0ders <39492740+s0ders@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:41:52 +0200 Subject: [PATCH 01/11] fix(table): preventing cursor from being out-of-bounds. The following brings: - Preventing table's cursor from being out-of-bound when the table's rows shrink. ref: #782 --- table/table.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/table/table.go b/table/table.go index ed29d8c53..4dd120360 100644 --- a/table/table.go +++ b/table/table.go @@ -4,12 +4,13 @@ package table import ( "strings" - "github.com/charmbracelet/bubbles/help" - "github.com/charmbracelet/bubbles/key" - "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/mattn/go-runewidth" + + "github.com/charmbracelet/bubbles/help" + "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/bubbles/viewport" ) // Model defines a state for the table widget. @@ -306,6 +307,11 @@ func (m Model) Columns() []Column { // SetRows sets a new rows state. func (m *Model) SetRows(r []Row) { m.rows = r + + if m.cursor > len(m.rows)-1 { + m.cursor = len(m.rows) - 1 + } + m.UpdateViewport() } From d4feefed7d674edbfbc8f09e99c56704706038c5 Mon Sep 17 00:00:00 2001 From: ShalokShalom Date: Wed, 23 Apr 2025 15:10:13 +0200 Subject: [PATCH 02/11] docs: remove Charm Cloud reference (#785) Remove a reference to charm --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index c6a4efdeb..8c3c0b515 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,9 @@ [![Go ReportCard](https://goreportcard.com/badge/charmbracelet/bubbles)](https://goreportcard.com/report/charmbracelet/bubbles) Some components for [Bubble Tea](https://github.com/charmbracelet/bubbletea) -applications. These components are used in production in [Glow][glow], -[Charm][charm] and [many other applications][otherstuff]. +applications. These components are used in production in [Glow][glow], and [many other applications][otherstuff]. [glow]: https://github.com/charmbracelet/glow -[charm]: https://github.com/charmbracelet/charm [otherstuff]: https://github.com/charmbracelet/bubbletea/#bubble-tea-in-the-wild ## Spinner From 8562e9075fb87edf45e99c5d63a6610254d6c6e7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 23 Apr 2025 15:12:25 +0200 Subject: [PATCH 03/11] ci: sync golangci-lint config (#781) Co-authored-by: aymanbagabas <3187948+aymanbagabas@users.noreply.github.com> --- .golangci.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 7c0a115e8..be61d89ba 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -30,10 +30,6 @@ linters: generated: lax presets: - common-false-positives - paths: - - third_party$ - - builtin$ - - examples$ issues: max-issues-per-linter: 0 max-same-issues: 0 @@ -43,7 +39,3 @@ formatters: - goimports exclusions: generated: lax - paths: - - third_party$ - - builtin$ - - examples$ From daab808a4d85e0b616ca9e30c1c5d9acd365aa02 Mon Sep 17 00:00:00 2001 From: Charm <124303983+charmcli@users.noreply.github.com> Date: Mon, 28 Apr 2025 09:10:04 -0300 Subject: [PATCH 04/11] ci: sync dependabot config (#786) --- .github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cbc9aa410..63ed01f2e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -37,5 +37,5 @@ updates: labels: - "dependencies" commit-message: - prefix: "feat" + prefix: "chore" include: "scope" From c376ce3ef18cc26bbf1f6338cc8518ae329a18d6 Mon Sep 17 00:00:00 2001 From: DryHumour Date: Wed, 30 Apr 2025 10:45:41 -0400 Subject: [PATCH 05/11] fix(cursor): fix data race on blinkTag (#784) --- cursor/cursor.go | 4 +++- cursor/cursor_test.go | 50 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 cursor/cursor_test.go diff --git a/cursor/cursor.go b/cursor/cursor.go index d101332b1..155d56c73 100644 --- a/cursor/cursor.go +++ b/cursor/cursor.go @@ -173,11 +173,13 @@ func (m *Model) BlinkCmd() tea.Cmd { m.blinkTag++ + blinkMsg := BlinkMsg{id: m.id, tag: m.blinkTag} + return func() tea.Msg { defer cancel() <-ctx.Done() if ctx.Err() == context.DeadlineExceeded { - return BlinkMsg{id: m.id, tag: m.blinkTag} + return blinkMsg } return blinkCanceled{} } diff --git a/cursor/cursor_test.go b/cursor/cursor_test.go new file mode 100644 index 000000000..c526c4ae1 --- /dev/null +++ b/cursor/cursor_test.go @@ -0,0 +1,50 @@ +package cursor + +import ( + "sync" + "testing" + "time" +) + +// TestBlinkCmdDataRace tests for a race on [Cursor.blinkTag]. +// +// The original [Model.BlinkCmd] implementation returned a closure over the pointer receiver: +// +// return func() tea.Msg { +// defer cancel() +// <-ctx.Done() +// if ctx.Err() == context.DeadlineExceeded { +// return BlinkMsg{id: m.id, tag: m.blinkTag} +// } +// return blinkCanceled{} +// } +// +// A race on “m.blinkTag” will occur if: +// 1. [Model.BlinkCmd] is called e.g. by calling [Model.Focus] from +// ["github.com/charmbracelet/bubbletea".Model.Update]; +// 2. ["github.com/charmbracelet/bubbletea".handleCommands] is kept sufficiently busy that it does not recieve and +// execute the [Model.BlinkCmd] e.g. by other long running command or commands; +// 3. at least [Mode.BlinkSpeed] time elapses; +// 4. [Model.BlinkCmd] is called again; +// 5. ["github.com/charmbracelet/bubbletea".handleCommands] gets around to receiving and executing the original +// closure. +// +// Even if this did not formally race, the value of the tag fetched would be semantically incorrect (likely being the +// current value rather than the value at the time the closure was created). +func TestBlinkCmdDataRace(t *testing.T) { + m := New() + cmd := m.BlinkCmd() + var wg sync.WaitGroup + wg.Add(2) + go func() { + defer wg.Done() + time.Sleep(m.BlinkSpeed * 3) + cmd() + }() + go func() { + defer wg.Done() + time.Sleep(m.BlinkSpeed * 2) + m.BlinkCmd() + }() + wg.Wait() +} From 5348e154652c0770083bcd29cb373e4ed1f865c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 09:35:08 +0000 Subject: [PATCH 06/11] chore(deps): bump github.com/charmbracelet/bubbletea from 1.3.4 to 1.3.5 (#787) Bumps [github.com/charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) from 1.3.4 to 1.3.5. - [Release notes](https://github.com/charmbracelet/bubbletea/releases) - [Changelog](https://github.com/charmbracelet/bubbletea/blob/main/.goreleaser.yml) - [Commits](https://github.com/charmbracelet/bubbletea/compare/v1.3.4...v1.3.5) --- updated-dependencies: - dependency-name: github.com/charmbracelet/bubbletea dependency-version: 1.3.5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 42d6dd94a..1549aedb2 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 github.com/aymanbagabas/go-udiff v0.2.0 - github.com/charmbracelet/bubbletea v1.3.4 + github.com/charmbracelet/bubbletea v1.3.5 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v1.1.0 github.com/charmbracelet/x/ansi v0.8.0 @@ -33,7 +33,7 @@ require ( github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect + golang.org/x/sync v0.13.0 // indirect + golang.org/x/sys v0.32.0 // indirect golang.org/x/text v0.3.8 // indirect ) diff --git a/go.sum b/go.sum index bb1720b3f..2915d278a 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= -github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= -github.com/charmbracelet/bubbletea v1.3.4/go.mod h1:dtcUCyCGEX3g9tosuYiut3MXgY/Jsv9nKVdibKKRRXo= +github.com/charmbracelet/bubbletea v1.3.5 h1:JAMNLTbqMOhSwoELIr0qyP4VidFq72/6E9j7HHmRKQc= +github.com/charmbracelet/bubbletea v1.3.5/go.mod h1:TkCnmH+aBd4LrXhXcqrKiYwRs7qyQx5rBgH5fVY3v54= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= @@ -51,11 +51,11 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= +golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= +golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= From 6157198699c569fd78ccd7bcdbfd5ac3705c12a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 May 2025 09:40:45 +0000 Subject: [PATCH 07/11] chore(deps): bump github.com/charmbracelet/x/ansi from 0.8.0 to 0.9.2 (#788) Bumps [github.com/charmbracelet/x/ansi](https://github.com/charmbracelet/x) from 0.8.0 to 0.9.2. - [Commits](https://github.com/charmbracelet/x/compare/ansi/v0.8.0...ansi/v0.9.2) --- updated-dependencies: - dependency-name: github.com/charmbracelet/x/ansi dependency-version: 0.9.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1549aedb2..b4c92ee09 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/charmbracelet/bubbletea v1.3.5 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v1.1.0 - github.com/charmbracelet/x/ansi v0.8.0 + github.com/charmbracelet/x/ansi v0.9.2 github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 diff --git a/go.sum b/go.sum index 2915d278a..41b06ec7a 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= -github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/ansi v0.9.2 h1:92AGsQmNTRMzuzHEYfCdjQeUzTrgE1vfO5/7fEVoXdY= +github.com/charmbracelet/x/ansi v0.9.2/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= From dff42ddb7cf28f022da475c69dba2e74f75af34d Mon Sep 17 00:00:00 2001 From: Broderick Westrope Date: Mon, 23 Sep 2024 09:47:30 +1000 Subject: [PATCH 08/11] feat: update keybindings in list setSize method --- list/list.go | 1 + 1 file changed, 1 insertion(+) diff --git a/list/list.go b/list/list.go index a96dc77f5..fc7c6b101 100644 --- a/list/list.go +++ b/list/list.go @@ -696,6 +696,7 @@ func (m *Model) setSize(width, height int) { m.Help.Width = width m.FilterInput.Width = width - promptWidth - lipgloss.Width(m.spinnerView()) m.updatePagination() + m.updateKeybindings() } func (m *Model) resetFiltering() { From f54a125f7decd8fefa0db4a0853720200d50a631 Mon Sep 17 00:00:00 2001 From: Broderick Westrope Date: Sat, 17 May 2025 03:13:06 +1000 Subject: [PATCH 09/11] test(table): improve table unit tests (#601) --- table/table_test.go | 638 +++++++++++++++++- .../TestModel_View/Bordered_cells.golden | 21 + .../TestModel_View/Bordered_headers.golden | 23 + table/testdata/TestModel_View/Empty.golden | 20 + .../TestModel_View/Extra_padding.golden | 14 + .../Manual_height_greater_than_rows.golden | 6 + .../Manual_height_less_than_rows.golden | 2 + .../Manual_width_greater_than_columns.golden | 21 + .../Manual_width_less_than_columns.golden | 21 + .../Modified_viewport_height.golden | 3 + .../Multiple_rows_and_columns.golden | 21 + .../testdata/TestModel_View/No_padding.golden | 10 + .../Single_row_and_column.golden | 21 + .../TestModel_View_CenteredInABox.golden | 8 + 14 files changed, 799 insertions(+), 30 deletions(-) create mode 100644 table/testdata/TestModel_View/Bordered_cells.golden create mode 100644 table/testdata/TestModel_View/Bordered_headers.golden create mode 100644 table/testdata/TestModel_View/Empty.golden create mode 100644 table/testdata/TestModel_View/Extra_padding.golden create mode 100644 table/testdata/TestModel_View/Manual_height_greater_than_rows.golden create mode 100644 table/testdata/TestModel_View/Manual_height_less_than_rows.golden create mode 100644 table/testdata/TestModel_View/Manual_width_greater_than_columns.golden create mode 100644 table/testdata/TestModel_View/Manual_width_less_than_columns.golden create mode 100644 table/testdata/TestModel_View/Modified_viewport_height.golden create mode 100644 table/testdata/TestModel_View/Multiple_rows_and_columns.golden create mode 100644 table/testdata/TestModel_View/No_padding.golden create mode 100644 table/testdata/TestModel_View/Single_row_and_column.golden create mode 100644 table/testdata/TestModel_View_CenteredInABox.golden diff --git a/table/table_test.go b/table/table_test.go index cc49f0d3c..6129245ca 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -1,14 +1,183 @@ package table import ( + "reflect" "testing" + "github.com/charmbracelet/bubbles/help" + "github.com/charmbracelet/bubbles/viewport" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/x/ansi" "github.com/charmbracelet/x/exp/golden" ) -func TestFromValues(t *testing.T) { +var testCols = []Column{ + {Title: "col1", Width: 10}, + {Title: "col2", Width: 10}, + {Title: "col3", Width: 10}, +} + +func TestNew(t *testing.T) { + tests := map[string]struct { + opts []Option + want Model + }{ + "Default": { + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + }, + }, + "WithColumns": { + opts: []Option{ + WithColumns([]Column{ + {Title: "Foo", Width: 1}, + {Title: "Bar", Width: 2}, + }), + }, + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + cols: []Column{ + {Title: "Foo", Width: 1}, + {Title: "Bar", Width: 2}, + }, + }, + }, + "WithColumns; WithRows": { + opts: []Option{ + WithColumns([]Column{ + {Title: "Foo", Width: 1}, + {Title: "Bar", Width: 2}, + }), + WithRows([]Row{ + {"1", "Foo"}, + {"2", "Bar"}, + }), + }, + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + cols: []Column{ + {Title: "Foo", Width: 1}, + {Title: "Bar", Width: 2}, + }, + rows: []Row{ + {"1", "Foo"}, + {"2", "Bar"}, + }, + }, + }, + "WithHeight": { + opts: []Option{ + WithHeight(10), + }, + want: Model{ + // Default fields + cursor: 0, + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + // Viewport height is 1 less than the provided height when no header is present since lipgloss.Height adds 1 + viewport: viewport.New(0, 9), + }, + }, + "WithWidth": { + opts: []Option{ + WithWidth(10), + }, + want: Model{ + // Default fields + cursor: 0, + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + // Viewport height is 1 less than the provided height when no header is present since lipgloss.Height adds 1 + viewport: viewport.New(10, 20), + }, + }, + "WithFocused": { + opts: []Option{ + WithFocused(true), + }, + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + KeyMap: DefaultKeyMap(), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + focus: true, + }, + }, + "WithStyles": { + opts: []Option{ + WithStyles(Styles{}), + }, + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + KeyMap: DefaultKeyMap(), + Help: help.New(), + + // Modified fields + styles: Styles{}, + }, + }, + "WithKeyMap": { + opts: []Option{ + WithKeyMap(KeyMap{}), + }, + want: Model{ + // Default fields + cursor: 0, + viewport: viewport.New(0, 20), + Help: help.New(), + styles: DefaultStyles(), + + // Modified fields + KeyMap: KeyMap{}, + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + tc.want.UpdateViewport() + + got := New(tc.opts...) + + if !reflect.DeepEqual(tc.want, got) { + t.Errorf("\n\nwant %v\n\ngot %v", tc.want, got) + } + }) + } +} + +func TestModel_FromValues(t *testing.T) { input := "foo1,bar1\nfoo2,bar2\nfoo3,bar3" table := New(WithColumns([]Column{{Title: "Foo"}, {Title: "Bar"}})) table.FromValues(input, ",") @@ -22,12 +191,12 @@ func TestFromValues(t *testing.T) { {"foo2", "bar2"}, {"foo3", "bar3"}, } - if !deepEqual(table.rows, expect) { - t.Fatal("table rows is not equals to the input") + if !reflect.DeepEqual(table.rows, expect) { + t.Fatalf("\n\nwant %v\n\ngot %v", expect, table.rows) } } -func TestFromValuesWithTabSeparator(t *testing.T) { +func TestModel_FromValues_WithTabSeparator(t *testing.T) { input := "foo1.\tbar1\nfoo,bar,baz\tbar,2" table := New(WithColumns([]Column{{Title: "Foo"}, {Title: "Bar"}})) table.FromValues(input, "\t") @@ -40,32 +209,12 @@ func TestFromValuesWithTabSeparator(t *testing.T) { {"foo1.", "bar1"}, {"foo,bar,baz", "bar,2"}, } - if !deepEqual(table.rows, expect) { - t.Fatal("table rows is not equals to the input") + if !reflect.DeepEqual(table.rows, expect) { + t.Fatalf("\n\nwant %v\n\ngot %v", expect, table.rows) } } -func deepEqual(a, b []Row) bool { - if len(a) != len(b) { - return false - } - for i, r := range a { - for j, f := range r { - if f != b[i][j] { - return false - } - } - } - return true -} - -var cols = []Column{ - {Title: "col1", Width: 10}, - {Title: "col2", Width: 10}, - {Title: "col3", Width: 10}, -} - -func TestRenderRow(t *testing.T) { +func TestModel_RenderRow(t *testing.T) { tests := []struct { name string table *Model @@ -75,7 +224,7 @@ func TestRenderRow(t *testing.T) { name: "simple row", table: &Model{ rows: []Row{{"Foooooo", "Baaaaar", "Baaaaaz"}}, - cols: cols, + cols: testCols, styles: Styles{Cell: lipgloss.NewStyle()}, }, expected: "Foooooo Baaaaar Baaaaaz ", @@ -84,7 +233,7 @@ func TestRenderRow(t *testing.T) { name: "simple row with truncations", table: &Model{ rows: []Row{{"Foooooooooo", "Baaaaaaaaar", "Quuuuuuuuux"}}, - cols: cols, + cols: testCols, styles: Styles{Cell: lipgloss.NewStyle()}, }, expected: "Foooooooo…Baaaaaaaa…Quuuuuuuu…", @@ -93,7 +242,7 @@ func TestRenderRow(t *testing.T) { name: "simple row avoiding truncations", table: &Model{ rows: []Row{{"Fooooooooo", "Baaaaaaaar", "Quuuuuuuux"}}, - cols: cols, + cols: testCols, styles: Styles{Cell: lipgloss.NewStyle()}, }, expected: "FoooooooooBaaaaaaaarQuuuuuuuux", @@ -157,3 +306,432 @@ func TestTableAlignment(t *testing.T) { golden.RequireEqual(t, []byte(got)) }) } + +func TestCursorNavigation(t *testing.T) { + tests := map[string]struct { + rows []Row + action func(*Model) + want int + }{ + "New": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + }, + action: func(_ *Model) {}, + want: 0, + }, + "MoveDown": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.MoveDown(2) + }, + want: 2, + }, + "MoveUp": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.cursor = 3 + t.MoveUp(2) + }, + want: 1, + }, + "GotoBottom": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.GotoBottom() + }, + want: 3, + }, + "GotoTop": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.cursor = 3 + t.GotoTop() + }, + want: 0, + }, + "SetCursor": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.SetCursor(2) + }, + want: 2, + }, + "MoveDown with overflow": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.MoveDown(5) + }, + want: 3, + }, + "MoveUp with overflow": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.cursor = 3 + t.MoveUp(5) + }, + want: 0, + }, + "Blur does not stop movement": { + rows: []Row{ + {"r1"}, + {"r2"}, + {"r3"}, + {"r4"}, + }, + action: func(t *Model) { + t.Blur() + t.MoveDown(2) + }, + want: 2, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + table := New(WithColumns(testCols), WithRows(tc.rows)) + tc.action(&table) + + if table.Cursor() != tc.want { + t.Errorf("want %d, got %d", tc.want, table.Cursor()) + } + }) + } +} + +func TestModel_SetRows(t *testing.T) { + table := New(WithColumns(testCols)) + + if len(table.rows) != 0 { + t.Fatalf("want 0, got %d", len(table.rows)) + } + + table.SetRows([]Row{{"r1"}, {"r2"}}) + + if len(table.rows) != 2 { + t.Fatalf("want 2, got %d", len(table.rows)) + } + + want := []Row{{"r1"}, {"r2"}} + if !reflect.DeepEqual(table.rows, want) { + t.Fatalf("\n\nwant %v\n\ngot %v", want, table.rows) + } +} + +func TestModel_SetColumns(t *testing.T) { + table := New() + + if len(table.cols) != 0 { + t.Fatalf("want 0, got %d", len(table.cols)) + } + + table.SetColumns([]Column{{Title: "Foo"}, {Title: "Bar"}}) + + if len(table.cols) != 2 { + t.Fatalf("want 2, got %d", len(table.cols)) + } + + want := []Column{{Title: "Foo"}, {Title: "Bar"}} + if !reflect.DeepEqual(table.cols, want) { + t.Fatalf("\n\nwant %v\n\ngot %v", want, table.cols) + } +} + +func TestModel_View(t *testing.T) { + tests := map[string]struct { + modelFunc func() Model + skip bool + }{ + // TODO(?): should the view/output of empty tables use the same default height? (this has height 21) + "Empty": { + modelFunc: func() Model { + return New() + }, + }, + "Single row and column": { + modelFunc: func() Model { + return New( + WithColumns([]Column{ + {Title: "Name", Width: 25}, + }), + WithRows([]Row{ + {"Chocolate Digestives"}, + }), + ) + }, + }, + "Multiple rows and columns": { + modelFunc: func() Model { + return New( + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + }, + }, + // TODO(fix): since the table height is tied to the viewport height, adding vertical padding to the headers' height directly increases the table height. + "Extra padding": { + modelFunc: func() Model { + s := DefaultStyles() + s.Header = lipgloss.NewStyle().Padding(2, 2) + s.Cell = lipgloss.NewStyle().Padding(2, 2) + + return New( + WithHeight(10), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + WithStyles(s), + ) + }, + }, + "No padding": { + modelFunc: func() Model { + s := DefaultStyles() + s.Header = lipgloss.NewStyle() + s.Cell = lipgloss.NewStyle() + + return New( + WithHeight(10), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + WithStyles(s), + ) + }, + }, + // TODO(?): the total height is modified with borderd headers, however not with bordered cells. Is this expected/desired? + "Bordered headers": { + modelFunc: func() Model { + return New( + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + WithStyles(Styles{ + Header: lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()), + }), + ) + }, + }, + // TODO(fix): Headers are not horizontally aligned with cells due to the border adding width to the cells. + "Bordered cells": { + modelFunc: func() Model { + return New( + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + WithStyles(Styles{ + Cell: lipgloss.NewStyle().BorderStyle(lipgloss.NormalBorder()), + }), + ) + }, + }, + "Manual height greater than rows": { + modelFunc: func() Model { + return New( + WithHeight(6), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + }, + }, + "Manual height less than rows": { + modelFunc: func() Model { + return New( + WithHeight(2), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + }, + }, + // TODO(fix): spaces are added to the right of the viewport to fill the width, but the headers end as though they are not aware of the width. + "Manual width greater than columns": { + modelFunc: func() Model { + return New( + WithWidth(80), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + }, + }, + // TODO(fix): Setting the table width does not affect the total headers' width. Cells are wrapped. + // Headers are not affected. Truncation/resizing should match lipgloss.table functionality. + "Manual width less than columns": { + modelFunc: func() Model { + return New( + WithWidth(30), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + }, + skip: true, + }, + "Modified viewport height": { + modelFunc: func() Model { + m := New( + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + + m.viewport.Height = 2 + + return m + }, + }, + } + + for name, tc := range tests { + t.Run(name, func(t *testing.T) { + if tc.skip { + t.Skip() + } + + table := tc.modelFunc() + + got := ansi.Strip(table.View()) + + golden.RequireEqual(t, []byte(got)) + }) + } +} + +// TODO: Fix table to make this test will pass. +func TestModel_View_CenteredInABox(t *testing.T) { + t.Skip() + + boxStyle := lipgloss.NewStyle(). + BorderStyle(lipgloss.NormalBorder()). + Align(lipgloss.Center) + + table := New( + WithHeight(6), + WithWidth(80), + WithColumns([]Column{ + {Title: "Name", Width: 25}, + {Title: "Country of Origin", Width: 16}, + {Title: "Dunk-able", Width: 12}, + }), + WithRows([]Row{ + {"Chocolate Digestives", "UK", "Yes"}, + {"Tim Tams", "Australia", "No"}, + {"Hobnobs", "UK", "Yes"}, + }), + ) + + tableView := ansi.Strip(table.View()) + got := boxStyle.Render(tableView) + + golden.RequireEqual(t, []byte(got)) +} diff --git a/table/testdata/TestModel_View/Bordered_cells.golden b/table/testdata/TestModel_View/Bordered_cells.golden new file mode 100644 index 000000000..71e95988b --- /dev/null +++ b/table/testdata/TestModel_View/Bordered_cells.golden @@ -0,0 +1,21 @@ +Name Country of Orig…Dunk-able +┌─────────────────────────┐┌────────────────┐┌────────────┐ +│Chocolate Digestives ││UK ││Yes │ +└─────────────────────────┘└────────────────┘└────────────┘ +┌─────────────────────────┐┌────────────────┐┌────────────┐ +│Tim Tams ││Australia ││No │ +└─────────────────────────┘└────────────────┘└────────────┘ +┌─────────────────────────┐┌────────────────┐┌────────────┐ +│Hobnobs ││UK ││Yes │ +└─────────────────────────┘└────────────────┘└────────────┘ + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Bordered_headers.golden b/table/testdata/TestModel_View/Bordered_headers.golden new file mode 100644 index 000000000..0e260bae2 --- /dev/null +++ b/table/testdata/TestModel_View/Bordered_headers.golden @@ -0,0 +1,23 @@ +┌─────────────────────────┐┌────────────────┐┌────────────┐ +│Name ││Country of Orig…││Dunk-able │ +└─────────────────────────┘└────────────────┘└────────────┘ +Chocolate Digestives UK Yes +Tim Tams Australia No +Hobnobs UK Yes + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Empty.golden b/table/testdata/TestModel_View/Empty.golden new file mode 100644 index 000000000..7b050800f --- /dev/null +++ b/table/testdata/TestModel_View/Empty.golden @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/table/testdata/TestModel_View/Extra_padding.golden b/table/testdata/TestModel_View/Extra_padding.golden new file mode 100644 index 000000000..3028ba66e --- /dev/null +++ b/table/testdata/TestModel_View/Extra_padding.golden @@ -0,0 +1,14 @@ + + + Name Country of Orig… Dunk-able + + + + + Chocolate Digestives UK Yes + + + + + Tim Tams Australia No + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden b/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden new file mode 100644 index 000000000..0888bdeb0 --- /dev/null +++ b/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden @@ -0,0 +1,6 @@ + Name Country of Orig… Dunk-able + Chocolate Digestives UK Yes + Tim Tams Australia No + Hobnobs UK Yes + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_height_less_than_rows.golden b/table/testdata/TestModel_View/Manual_height_less_than_rows.golden new file mode 100644 index 000000000..9c331b390 --- /dev/null +++ b/table/testdata/TestModel_View/Manual_height_less_than_rows.golden @@ -0,0 +1,2 @@ + Name Country of Orig… Dunk-able + Chocolate Digestives UK Yes \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden b/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden new file mode 100644 index 000000000..684450492 --- /dev/null +++ b/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden @@ -0,0 +1,21 @@ + Name Country of Orig… Dunk-able + Chocolate Digestives UK Yes + Tim Tams Australia No + Hobnobs UK Yes + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_width_less_than_columns.golden b/table/testdata/TestModel_View/Manual_width_less_than_columns.golden new file mode 100644 index 000000000..d2bc25b96 --- /dev/null +++ b/table/testdata/TestModel_View/Manual_width_less_than_columns.golden @@ -0,0 +1,21 @@ + Name Country of Origin Dunk-able + Chocolate Digestives UK Yes + Tim Tams Australia No + Hobnobs UK Yes + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Modified_viewport_height.golden b/table/testdata/TestModel_View/Modified_viewport_height.golden new file mode 100644 index 000000000..91445d49a --- /dev/null +++ b/table/testdata/TestModel_View/Modified_viewport_height.golden @@ -0,0 +1,3 @@ + Name Country of Orig… Dunk-able + Chocolate Digestives UK Yes + Tim Tams Australia No \ No newline at end of file diff --git a/table/testdata/TestModel_View/Multiple_rows_and_columns.golden b/table/testdata/TestModel_View/Multiple_rows_and_columns.golden new file mode 100644 index 000000000..6ba436ce5 --- /dev/null +++ b/table/testdata/TestModel_View/Multiple_rows_and_columns.golden @@ -0,0 +1,21 @@ + Name Country of Orig… Dunk-able + Chocolate Digestives UK Yes + Tim Tams Australia No + Hobnobs UK Yes + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/No_padding.golden b/table/testdata/TestModel_View/No_padding.golden new file mode 100644 index 000000000..f74874668 --- /dev/null +++ b/table/testdata/TestModel_View/No_padding.golden @@ -0,0 +1,10 @@ +Name Country of Orig…Dunk-able +Chocolate Digestives UK Yes +Tim Tams Australia No +Hobnobs UK Yes + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View/Single_row_and_column.golden b/table/testdata/TestModel_View/Single_row_and_column.golden new file mode 100644 index 000000000..84950d577 --- /dev/null +++ b/table/testdata/TestModel_View/Single_row_and_column.golden @@ -0,0 +1,21 @@ + Name + Chocolate Digestives + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/table/testdata/TestModel_View_CenteredInABox.golden b/table/testdata/TestModel_View_CenteredInABox.golden new file mode 100644 index 000000000..59d9c7030 --- /dev/null +++ b/table/testdata/TestModel_View_CenteredInABox.golden @@ -0,0 +1,8 @@ +┌────────────────────────────────────────────────────────────────────────────────┐ +│ Name Country of Orig… Dunk-able │ +│ Chocolate Digestives UK Yes │ +│ Tim Tams Australia No │ +│ Hobnobs UK Yes │ +│ │ +│ │ +└────────────────────────────────────────────────────────────────────────────────┘ \ No newline at end of file From 73839850f77c0d25d8f558677acd5cdbc71d468c Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 16 May 2025 14:24:05 -0300 Subject: [PATCH 10/11] test: update golden files with nbsp for v2 --- table/testdata/TestModel_View/Extra_padding.golden | 6 +++--- .../TestModel_View/Manual_height_greater_than_rows.golden | 8 ++++---- .../TestModel_View/Manual_height_less_than_rows.golden | 4 ++-- .../Manual_width_greater_than_columns.golden | 8 ++++---- .../TestModel_View/Modified_viewport_height.golden | 6 +++--- .../TestModel_View/Multiple_rows_and_columns.golden | 8 ++++---- .../testdata/TestModel_View/Single_row_and_column.golden | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/table/testdata/TestModel_View/Extra_padding.golden b/table/testdata/TestModel_View/Extra_padding.golden index 3028ba66e..d6f6b76e8 100644 --- a/table/testdata/TestModel_View/Extra_padding.golden +++ b/table/testdata/TestModel_View/Extra_padding.golden @@ -1,14 +1,14 @@ - Name Country of Orig… Dunk-able +  Name     Country of Orig…    Dunk-able    - Chocolate Digestives UK Yes +  Chocolate Digestives     UK     Yes    - Tim Tams Australia No +  Tim Tams     Australia     No    \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden b/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden index 0888bdeb0..f89de1df9 100644 --- a/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden +++ b/table/testdata/TestModel_View/Manual_height_greater_than_rows.golden @@ -1,6 +1,6 @@ - Name Country of Orig… Dunk-able - Chocolate Digestives UK Yes - Tim Tams Australia No - Hobnobs UK Yes + Name   Country of Orig…  Dunk-able   + Chocolate Digestives   UK   Yes   + Tim Tams   Australia   No   + Hobnobs   UK   Yes   \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_height_less_than_rows.golden b/table/testdata/TestModel_View/Manual_height_less_than_rows.golden index 9c331b390..83bded11d 100644 --- a/table/testdata/TestModel_View/Manual_height_less_than_rows.golden +++ b/table/testdata/TestModel_View/Manual_height_less_than_rows.golden @@ -1,2 +1,2 @@ - Name Country of Orig… Dunk-able - Chocolate Digestives UK Yes \ No newline at end of file + Name   Country of Orig…  Dunk-able   + Chocolate Digestives   UK   Yes   \ No newline at end of file diff --git a/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden b/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden index 684450492..a1c06fee1 100644 --- a/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden +++ b/table/testdata/TestModel_View/Manual_width_greater_than_columns.golden @@ -1,7 +1,7 @@ - Name Country of Orig… Dunk-able - Chocolate Digestives UK Yes - Tim Tams Australia No - Hobnobs UK Yes + Name   Country of Orig…  Dunk-able   + Chocolate Digestives   UK   Yes   + Tim Tams   Australia   No   + Hobnobs   UK   Yes   diff --git a/table/testdata/TestModel_View/Modified_viewport_height.golden b/table/testdata/TestModel_View/Modified_viewport_height.golden index 91445d49a..98a44eeb9 100644 --- a/table/testdata/TestModel_View/Modified_viewport_height.golden +++ b/table/testdata/TestModel_View/Modified_viewport_height.golden @@ -1,3 +1,3 @@ - Name Country of Orig… Dunk-able - Chocolate Digestives UK Yes - Tim Tams Australia No \ No newline at end of file + Name   Country of Orig…  Dunk-able   + Chocolate Digestives   UK   Yes   + Tim Tams   Australia   No   \ No newline at end of file diff --git a/table/testdata/TestModel_View/Multiple_rows_and_columns.golden b/table/testdata/TestModel_View/Multiple_rows_and_columns.golden index 6ba436ce5..d1dffc5ba 100644 --- a/table/testdata/TestModel_View/Multiple_rows_and_columns.golden +++ b/table/testdata/TestModel_View/Multiple_rows_and_columns.golden @@ -1,7 +1,7 @@ - Name Country of Orig… Dunk-able - Chocolate Digestives UK Yes - Tim Tams Australia No - Hobnobs UK Yes + Name   Country of Orig…  Dunk-able   + Chocolate Digestives   UK   Yes   + Tim Tams   Australia   No   + Hobnobs   UK   Yes   diff --git a/table/testdata/TestModel_View/Single_row_and_column.golden b/table/testdata/TestModel_View/Single_row_and_column.golden index 84950d577..36d5110eb 100644 --- a/table/testdata/TestModel_View/Single_row_and_column.golden +++ b/table/testdata/TestModel_View/Single_row_and_column.golden @@ -1,5 +1,5 @@ - Name - Chocolate Digestives + Name   + Chocolate Digestives   From 47b0944fc851b3d0e5947851899513f35e3c3551 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Fri, 16 May 2025 14:38:06 -0300 Subject: [PATCH 11/11] test: fix tests by ignoring func references --- table/table_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/table/table_test.go b/table/table_test.go index 0c04e680b..78db2424b 100644 --- a/table/table_test.go +++ b/table/table_test.go @@ -195,6 +195,11 @@ func TestNew(t *testing.T) { got := New(tc.opts...) + // NOTE(@andreynering): Funcs have different references, so we need + // to clear them out to compare the structs. + tc.want.viewport.LeftGutterFunc = nil + got.viewport.LeftGutterFunc = nil + if !reflect.DeepEqual(tc.want, got) { t.Errorf("\n\nwant %v\n\ngot %v", tc.want, got) }