Skip to content

Commit 4cef39b

Browse files
Merge branch 'highlighting-assertion-fixtures' into multiple-lines-stage-add
2 parents 5b97afd + b085935 commit 4cef39b

File tree

4 files changed

+49
-51
lines changed

4 files changed

+49
-51
lines changed

internal/assertions/highlighting_assertion.go

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package assertions
22

33
import (
4+
"bytes"
45
"errors"
56
"fmt"
67
"strings"
@@ -19,8 +20,9 @@ type HighlightingAssertion struct {
1920
ExpectedOutput string
2021

2122
// These are temporary values calculated and reset in each run
22-
actualResult executable.ExecutableResult
23-
logger *logger.Logger
23+
actualResult executable.ExecutableResult
24+
matchesShouldbeHighlighted bool
25+
logger *logger.Logger
2426
}
2527

2628
func (a *HighlightingAssertion) getExpectedOutputOnRowIdx(lineIdx int) string {
@@ -40,8 +42,10 @@ func (a *HighlightingAssertion) Run(result executable.ExecutableResult, logger *
4042
a.logger = nil
4143
}()
4244

43-
a.actualResult = result
45+
// Presence of ANSI coloring sequence implies that matches should be highlighted
46+
a.matchesShouldbeHighlighted = bytes.Contains(result.Stdout, []byte("\033[01;31m"))
4447
a.logger = logger.Clone()
48+
a.actualResult = result
4549

4650
expectedLines := utils.ProgramOutputToLines(a.ExpectedOutput)
4751
actualLines := utils.ProgramOutputToLines(string(result.Stdout))
@@ -119,7 +123,7 @@ func (a *HighlightingAssertion) assertHighlighting(expectedScreenState, actualSc
119123
// Log success messages for each row
120124
actualLines := actualScreenState.GetLinesOfTextUptoCursor()
121125
for rowIdx := 0; rowIdx <= lastSuccessFulRowIndex; rowIdx++ {
122-
if screenStateComparator.highlightingIsTurnedOn {
126+
if a.matchesShouldbeHighlighted {
123127
a.logger.Successf("✓ All matches in the line %q are highlighted", actualLines[rowIdx])
124128
} else {
125129
a.logger.Successf("✓ Line %q is not highlighted", actualLines[rowIdx])
@@ -134,33 +138,33 @@ func (a *HighlightingAssertion) assertHighlighting(expectedScreenState, actualSc
134138
return nil
135139
}
136140

137-
func (a *HighlightingAssertion) buildError(compErr *ComparisonError) error {
141+
func (a *HighlightingAssertion) buildError(comparisonError *ComparisonError) error {
138142
var b strings.Builder
139143

140144
// Comparison error message first
141145
b.WriteString(
142146
buildComparisonErrorMessageWithCursor(
143-
a.getExpectedOutputOnRowIdx(compErr.RowIdx),
144-
a.getActualOutputOnLineIdx(compErr.RowIdx),
145-
compErr.ColumnIdx,
147+
a.getExpectedOutputOnRowIdx(comparisonError.RowIdx),
148+
a.getActualOutputOnLineIdx(comparisonError.RowIdx),
149+
comparisonError.ColumnIdx,
146150
),
147151
)
148152
b.WriteString("\n")
149153

150154
// Print success messages
151-
for _, successLog := range compErr.SuccessLogs {
155+
for _, successLog := range comparisonError.PartialSuccessLogs {
152156
b.WriteString(colorizeString(color.FgHiGreen, successLog))
153157
b.WriteString("\n")
154158
}
155159

156160
// Print error message
157-
b.WriteString(colorizeString(color.FgHiRed, fmt.Sprintf("⨯ %s\n", compErr.ErrorString)))
161+
b.WriteString(colorizeString(color.FgHiRed, fmt.Sprintf("⨯ %s\n", comparisonError.ErrorString)))
158162

159-
// Print ANSI sequence comparison
163+
// Print ANSI code comparison
160164
b.WriteString(
161165
buildAnsiCodeMismatchComplaint(
162-
compErr.ExpectedCell.Style.String(),
163-
compErr.ActualCell.Style.String(),
166+
comparisonError.ExpectedANSICode,
167+
comparisonError.ACtualANSICode,
164168
),
165169
)
166170

internal/assertions/highlighting_assertion_panic_if_flawed.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ func (a HighlightingAssertion) panicIfExpectedScreenStateisFlawed(expectedScreen
1919

2020
expectedLinesCount := len(utils.ProgramOutputToLines(a.ExpectedOutput))
2121

22-
// Assert that expected screen state only has one line in the output
23-
if len(linesUptoCursor) > expectedLinesCount {
22+
// Assert that expected screen state has exact expected number of line in the output
23+
if len(linesUptoCursor) != expectedLinesCount {
2424

2525
outputLines := strings.Join(linesUptoCursor, "\n")
2626

2727
panic(fmt.Sprintf(
28-
"Codecrafters Internal Error - Expected one line in output, grep returned %d:\n%s",
28+
"Codecrafters Internal Error - Expected %d line in output, grep returned %d:\n%s",
29+
expectedLinesCount,
2930
len(linesUptoCursor),
3031
outputLines,
3132
))

internal/assertions/highlighting_assertion_screen_state_comparator.go

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"strings"
66

77
uv "github.com/charmbracelet/ultraviolet"
8-
"github.com/charmbracelet/x/ansi"
98
"github.com/codecrafters-io/grep-tester/virtual_terminal"
109
"github.com/dustin/go-humanize/english"
1110
)
@@ -18,30 +17,29 @@ import (
1817
// This one is involved only with error detection and propagation
1918
// Highlighting assertion is responsible for using this and building proper error
2019
type screenStateComparator struct {
21-
successLogs []string
22-
highlightingIsTurnedOn bool
20+
partialSuccessLogs []string
2321
}
2422

2523
// ComparisonError represents an error found during screen state comparison
2624
type ComparisonError struct {
27-
RowIdx int
28-
ColumnIdx int
29-
ExpectedCell *uv.Cell
30-
ActualCell *uv.Cell
31-
ErrorString error
32-
SuccessLogs []string
25+
RowIdx int
26+
ColumnIdx int
27+
ExpectedANSICode string
28+
ACtualANSICode string
29+
ErrorString error
30+
PartialSuccessLogs []string
3331
}
3432

3533
func newScreenStateComparator() *screenStateComparator {
3634
return &screenStateComparator{}
3735
}
3836

39-
func (c *screenStateComparator) resetSuccessLogs() {
40-
c.successLogs = []string{}
37+
func (c *screenStateComparator) resetPartialSuccessLogs() {
38+
c.partialSuccessLogs = []string{}
4139
}
4240

43-
func (c *screenStateComparator) addSuccessLog(successLog string) {
44-
c.successLogs = append(c.successLogs, successLog)
41+
func (c *screenStateComparator) addPartialSuccessLog(successLog string) {
42+
c.partialSuccessLogs = append(c.partialSuccessLogs, successLog)
4543
}
4644

4745
func (c *screenStateComparator) CompareHighlighting(expected, actual *virtual_terminal.ScreenState) *ComparisonError {
@@ -51,25 +49,25 @@ func (c *screenStateComparator) CompareHighlighting(expected, actual *virtual_te
5149
for rowIdx := range cursorPosition.RowIndex + 1 {
5250

5351
// Compare upto the column before in which the cursor is present
54-
columnsCount := expected.GetColumnsCount()
52+
maxColumnsCount := expected.GetColumnsCount()
5553
if cursorPosition.RowIndex == rowIdx {
56-
columnsCount = cursorPosition.ColumnIndex
54+
maxColumnsCount = cursorPosition.ColumnIndex
5755
}
5856

5957
// Compare cells
60-
for columnIdx := range columnsCount {
58+
for columnIdx := range maxColumnsCount {
6159

6260
expectedCell := expected.MustGetCellAtPosition(rowIdx, columnIdx)
6361
actualCell := actual.MustGetCellAtPosition(rowIdx, columnIdx)
6462

6563
if err := c.compareCells(expectedCell, actualCell); err != nil {
6664
return &ComparisonError{
67-
RowIdx: rowIdx,
68-
ColumnIdx: columnIdx,
69-
ExpectedCell: expectedCell,
70-
ActualCell: actualCell,
71-
ErrorString: err,
72-
SuccessLogs: c.successLogs,
65+
RowIdx: rowIdx,
66+
ColumnIdx: columnIdx,
67+
ErrorString: err,
68+
PartialSuccessLogs: c.partialSuccessLogs,
69+
ExpectedANSICode: expectedCell.Style.String(),
70+
ACtualANSICode: actualCell.Style.String(),
7371
}
7472
}
7573
}
@@ -79,13 +77,8 @@ func (c *screenStateComparator) CompareHighlighting(expected, actual *virtual_te
7977
}
8078

8179
func (c *screenStateComparator) compareCells(expected, actual *uv.Cell) error {
82-
// Reset for each comparison
83-
c.resetSuccessLogs()
84-
85-
// If a single cell is found which should be highlighted, which means highlighting is turned on for this run
86-
if expected.Style.Fg == ansi.Red && expected.Style.Attrs == uv.AttrBold {
87-
c.highlightingIsTurnedOn = true
88-
}
80+
// Reset for each cell
81+
c.resetPartialSuccessLogs()
8982

9083
var firstError error
9184

@@ -112,7 +105,7 @@ func (c *screenStateComparator) checkFgColor(expectedCell, actualCell *uv.Cell)
112105
return fmt.Errorf("Expected %s, got %s", getFgColorName(expectedCell.Style.Fg), getFgColorName(actualCell.Style.Fg))
113106
}
114107

115-
c.addSuccessLog(fmt.Sprintf("✓ Color is %s", getFgColorName(expectedCell.Style.Fg)))
108+
c.addPartialSuccessLog(fmt.Sprintf("✓ Color is %s", getFgColorName(expectedCell.Style.Fg)))
116109
return nil
117110
}
118111

@@ -124,14 +117,14 @@ func (c *screenStateComparator) checkBoldAttr(expectedCell, actualCell *uv.Cell)
124117
if expectedBold {
125118
return fmt.Errorf("Expected character to be bold (ANSI code 01), was not bold")
126119
} else {
127-
return fmt.Errorf("Expected character to not be bold, was bold")
120+
return fmt.Errorf("Expected character to not be bold, was bold (ANSI code 01)")
128121
}
129122
}
130123

131124
if expectedBold {
132-
c.addSuccessLog("✓ Bold attribute is present")
125+
c.addPartialSuccessLog("✓ Bold attribute is present")
133126
} else {
134-
c.addSuccessLog("✓ Bold attribute is not present")
127+
c.addPartialSuccessLog("✓ Bold attribute is not present")
135128
}
136129

137130
return nil

internal/assertions/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func getBgColorName(c color.Color) string {
107107
return colorCodeTocolorName(colorCodeString)
108108
}
109109

110-
var attrMap = []struct {
110+
var attributesMap = []struct {
111111
flag uint8
112112
name string
113113
}{
@@ -129,7 +129,7 @@ func attributesToNames(attributes uint8) []string {
129129

130130
var names []string
131131

132-
for _, attr := range attrMap {
132+
for _, attr := range attributesMap {
133133
if attributes&attr.flag != 0 {
134134
names = append(names, attr.name)
135135
}

0 commit comments

Comments
 (0)