-
Notifications
You must be signed in to change notification settings - Fork 1
test(tables): add unit tests for TabEngine.Render #125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -161,11 +161,21 @@ The table system goes beyond simple formatting to provide hardware-aware renderi | |||||||||||||||||
| - **Font A Enforcement**: Consistent 12-dot character width for predictable layouts | ||||||||||||||||||
| - **Paper Support**: 58mm (32 chars) and 80mm (48 chars) at 203 DPI | ||||||||||||||||||
|
|
||||||||||||||||||
| ### 🧪 Quality Assurance & Testing | ||||||||||||||||||
|
|
||||||||||||||||||
| - **Table-Driven Testing**: Implemented comprehensive table-driven unit tests for the `TableEngine` to verify rendering logic, ensuring support for: | ||||||||||||||||||
| - Header visibility toggling (explicit vs. data-driven). | ||||||||||||||||||
| - Column alignment (Left, Center, Right) with precise padding calculations. | ||||||||||||||||||
| - Word wrapping functionality for long text. | ||||||||||||||||||
| - Edge cases like nil data, invalid definitions, and empty rows. | ||||||||||||||||||
|
Comment on lines
+167
to
+170
|
||||||||||||||||||
| - Header visibility toggling (explicit vs. data-driven). | |
| - Column alignment (Left, Center, Right) with precise padding calculations. | |
| - Word wrapping functionality for long text. | |
| - Edge cases like nil data, invalid definitions, and empty rows. | |
| - Header visibility toggling based on configuration. | |
| - Column alignment (Left, Center, Right) with precise padding calculations. | |
| - Word wrapping functionality for long text. | |
| - Edge cases like nil data and invalid definitions. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| package tables | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "strings" | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
|
|
||
| "github.com/adcondev/poster/pkg/constants" | ||
| ) | ||
|
Comment on lines
+1
to
+12
|
||
|
|
||
| // TestRender tests the TabEngine.Render method | ||
| func TestRender(t *testing.T) { | ||
| // Common test data | ||
| def := Definition{ | ||
| Columns: []Column{ | ||
| {Name: "Item", Width: 10, Align: constants.Left}, | ||
| {Name: "Qty", Width: 5, Align: constants.Center}, | ||
| {Name: "Price", Width: 8, Align: constants.Right}, | ||
| }, | ||
| } | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| data *Data | ||
| opts *Options | ||
| expected []string // Expected substrings | ||
| unexpected []string // Unexpected substrings | ||
| expectError bool | ||
| errorMsg string | ||
| }{ | ||
| { | ||
| name: "Render Basic Table with Headers", | ||
| data: &Data{ | ||
| Definition: def, | ||
| ShowHeaders: true, | ||
| Rows: []Row{ | ||
| {"Apple", "10", "1.50"}, | ||
| }, | ||
| }, | ||
| opts: DefaultOptions(), | ||
| expected: []string{ | ||
| "\x1bE\x01", // Enable Bold | ||
| "Item Qty Price", // Header row | ||
| "\x1bE\x00", // Disable Bold | ||
| "Apple 10 1.50", // Data row | ||
| }, | ||
| expectError: false, | ||
| }, | ||
| { | ||
| name: "Render Table without Headers", | ||
| data: &Data{ | ||
| Definition: def, | ||
| ShowHeaders: false, | ||
| Rows: []Row{ | ||
| {"Banana", "5", "0.99"}, | ||
| }, | ||
| }, | ||
| opts: &Options{ | ||
| PaperWidth: 80, | ||
| ShowHeaders: false, | ||
| HeaderStyle: Style{Bold: true}, | ||
| WordWrap: true, | ||
| ColumnSpacing: 1, | ||
| }, | ||
| expected: []string{ | ||
| "Banana 5 0.99", // Data row | ||
| }, | ||
| unexpected: []string{ | ||
| "Item", "Qty", "Price", // Headers should not be present | ||
| "\x1bE\x01", // No bold command | ||
| }, | ||
| expectError: false, | ||
| }, | ||
| { | ||
| name: "Render Table with Alignment", | ||
| data: &Data{ | ||
| Definition: def, | ||
| Rows: []Row{ | ||
| {"Left", "Cnt", "Right"}, | ||
| }, | ||
| }, | ||
| opts: &Options{ | ||
| PaperWidth: 80, | ||
| ShowHeaders: false, | ||
| HeaderStyle: Style{Bold: true}, | ||
| WordWrap: true, | ||
| ColumnSpacing: 1, | ||
| }, | ||
| expected: []string{ | ||
| "Left Cnt Right", | ||
| }, | ||
| expectError: false, | ||
| }, | ||
| { | ||
| name: "Render Table with Word Wrap", | ||
| data: &Data{ | ||
| Definition: Definition{ | ||
| Columns: []Column{ | ||
| {Name: "Desc", Width: 5, Align: constants.Left}, | ||
| }, | ||
| }, | ||
| Rows: []Row{ | ||
| {"Long Text"}, // Should wrap to "Long " and "Text " | ||
| }, | ||
| }, | ||
| opts: DefaultOptions(), | ||
| expected: []string{ | ||
| "Long ", | ||
| "Text ", | ||
| }, | ||
| expectError: false, | ||
| }, | ||
| { | ||
| name: "Error: Nil Data", | ||
| data: nil, | ||
| opts: DefaultOptions(), | ||
| expectError: true, | ||
| errorMsg: "table data cannot be nil", | ||
| }, | ||
| { | ||
| name: "Error: Invalid Data (Row Length Mismatch)", | ||
| data: &Data{ | ||
| Definition: def, | ||
| Rows: []Row{ | ||
| {"Apple", "10"}, // Missing one column | ||
| }, | ||
| }, | ||
| opts: DefaultOptions(), | ||
| expectError: true, | ||
| errorMsg: "invalid table data", | ||
| }, | ||
| { | ||
| name: "Error: Invalid Data (Empty definition)", | ||
| data: &Data{ | ||
| Definition: Definition{}, | ||
| Rows: []Row{ | ||
| {"Apple"}, | ||
| }, | ||
| }, | ||
| opts: DefaultOptions(), | ||
| expectError: true, | ||
| errorMsg: "table must have at least one column", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| engine := NewEngine(&def, tt.opts) | ||
| var buf bytes.Buffer | ||
|
|
||
| err := engine.Render(&buf, tt.data) | ||
|
|
||
| if tt.expectError { | ||
| require.Error(t, err) | ||
| assert.Contains(t, err.Error(), tt.errorMsg) | ||
| } else { | ||
| require.NoError(t, err) | ||
| output := buf.String() | ||
|
|
||
| for _, exp := range tt.expected { | ||
| assert.Contains(t, output, exp, "Output should contain expected string") | ||
| } | ||
|
|
||
| for _, unexp := range tt.unexpected { | ||
| assert.NotContains(t, output, unexp, "Output should NOT contain unexpected string") | ||
| } | ||
|
|
||
| // Verify Line Feeds are present | ||
| if len(tt.expected) > 0 { | ||
| assert.True(t, strings.HasSuffix(output, "\n"), "Output should end with a newline") | ||
| } | ||
| } | ||
| }) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This section refers to a
TableEngine, but the implementation inpkg/tablesisTabEngine(constructed viatables.NewEngine). Updating the name here would avoid confusion for readers trying to map the docs to the actual code.