add tag based color writter for printing formatter tests
Этот коммит содержится в:
родитель
6868191a61
коммит
5bb581e3bd
8 изменённых файлов: 273 добавлений и 0 удалений
250
color_tag_test.go
Обычный файл
250
color_tag_test.go
Обычный файл
|
@ -0,0 +1,250 @@
|
|||
package godog
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/godog/colors"
|
||||
)
|
||||
|
||||
type csiState int
|
||||
|
||||
const (
|
||||
outsideCsiCode csiState = iota
|
||||
firstCsiCode
|
||||
secondCsiCode
|
||||
)
|
||||
|
||||
type tagColorWriter struct {
|
||||
w io.Writer
|
||||
state csiState
|
||||
paramStartBuf bytes.Buffer
|
||||
paramBuf bytes.Buffer
|
||||
tag string
|
||||
}
|
||||
|
||||
const (
|
||||
firstCsiChar byte = '\x1b'
|
||||
secondeCsiChar byte = '['
|
||||
separatorChar byte = ';'
|
||||
sgrCode byte = 'm'
|
||||
)
|
||||
|
||||
const (
|
||||
ansiReset = "0"
|
||||
ansiIntensityOn = "1"
|
||||
ansiIntensityOff = "21"
|
||||
ansiUnderlineOn = "4"
|
||||
ansiUnderlineOff = "24"
|
||||
ansiBlinkOn = "5"
|
||||
ansiBlinkOff = "25"
|
||||
|
||||
ansiForegroundBlack = "30"
|
||||
ansiForegroundRed = "31"
|
||||
ansiForegroundGreen = "32"
|
||||
ansiForegroundYellow = "33"
|
||||
ansiForegroundBlue = "34"
|
||||
ansiForegroundMagenta = "35"
|
||||
ansiForegroundCyan = "36"
|
||||
ansiForegroundWhite = "37"
|
||||
ansiForegroundDefault = "39"
|
||||
|
||||
ansiBackgroundBlack = "40"
|
||||
ansiBackgroundRed = "41"
|
||||
ansiBackgroundGreen = "42"
|
||||
ansiBackgroundYellow = "43"
|
||||
ansiBackgroundBlue = "44"
|
||||
ansiBackgroundMagenta = "45"
|
||||
ansiBackgroundCyan = "46"
|
||||
ansiBackgroundWhite = "47"
|
||||
ansiBackgroundDefault = "49"
|
||||
|
||||
ansiLightForegroundGray = "90"
|
||||
ansiLightForegroundRed = "91"
|
||||
ansiLightForegroundGreen = "92"
|
||||
ansiLightForegroundYellow = "93"
|
||||
ansiLightForegroundBlue = "94"
|
||||
ansiLightForegroundMagenta = "95"
|
||||
ansiLightForegroundCyan = "96"
|
||||
ansiLightForegroundWhite = "97"
|
||||
|
||||
ansiLightBackgroundGray = "100"
|
||||
ansiLightBackgroundRed = "101"
|
||||
ansiLightBackgroundGreen = "102"
|
||||
ansiLightBackgroundYellow = "103"
|
||||
ansiLightBackgroundBlue = "104"
|
||||
ansiLightBackgroundMagenta = "105"
|
||||
ansiLightBackgroundCyan = "106"
|
||||
ansiLightBackgroundWhite = "107"
|
||||
)
|
||||
|
||||
var colorMap = map[string]string{
|
||||
ansiForegroundBlack: "black",
|
||||
ansiForegroundRed: "red",
|
||||
ansiForegroundGreen: "green",
|
||||
ansiForegroundYellow: "yellow",
|
||||
ansiForegroundBlue: "blue",
|
||||
ansiForegroundMagenta: "magenta",
|
||||
ansiForegroundCyan: "cyan",
|
||||
ansiForegroundWhite: "white",
|
||||
ansiForegroundDefault: "",
|
||||
}
|
||||
|
||||
func (cw *tagColorWriter) flushBuffer() (int, error) {
|
||||
return cw.flushTo(cw.w)
|
||||
}
|
||||
|
||||
func (cw *tagColorWriter) resetBuffer() (int, error) {
|
||||
return cw.flushTo(nil)
|
||||
}
|
||||
|
||||
func (cw *tagColorWriter) flushTo(w io.Writer) (int, error) {
|
||||
var n1, n2 int
|
||||
var err error
|
||||
|
||||
startBytes := cw.paramStartBuf.Bytes()
|
||||
cw.paramStartBuf.Reset()
|
||||
if w != nil {
|
||||
n1, err = cw.w.Write(startBytes)
|
||||
if err != nil {
|
||||
return n1, err
|
||||
}
|
||||
} else {
|
||||
n1 = len(startBytes)
|
||||
}
|
||||
paramBytes := cw.paramBuf.Bytes()
|
||||
cw.paramBuf.Reset()
|
||||
if w != nil {
|
||||
n2, err = cw.w.Write(paramBytes)
|
||||
if err != nil {
|
||||
return n1 + n2, err
|
||||
}
|
||||
} else {
|
||||
n2 = len(paramBytes)
|
||||
}
|
||||
return n1 + n2, nil
|
||||
}
|
||||
|
||||
func isParameterChar(b byte) bool {
|
||||
return ('0' <= b && b <= '9') || b == separatorChar
|
||||
}
|
||||
|
||||
func (cw *tagColorWriter) Write(p []byte) (int, error) {
|
||||
r, nw, first, last := 0, 0, 0, 0
|
||||
|
||||
var err error
|
||||
for i, ch := range p {
|
||||
switch cw.state {
|
||||
case outsideCsiCode:
|
||||
if ch == firstCsiChar {
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
cw.state = firstCsiCode
|
||||
}
|
||||
case firstCsiCode:
|
||||
switch ch {
|
||||
case firstCsiChar:
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
break
|
||||
case secondeCsiChar:
|
||||
cw.paramStartBuf.WriteByte(ch)
|
||||
cw.state = secondCsiCode
|
||||
last = i - 1
|
||||
default:
|
||||
cw.resetBuffer()
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
case secondCsiCode:
|
||||
if isParameterChar(ch) {
|
||||
cw.paramBuf.WriteByte(ch)
|
||||
} else {
|
||||
nw, err = cw.w.Write(p[first:last])
|
||||
r += nw
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
first = i + 1
|
||||
if ch == sgrCode {
|
||||
cw.changeColor()
|
||||
}
|
||||
n, _ := cw.resetBuffer()
|
||||
// Add one more to the size of the buffer for the last ch
|
||||
r += n + 1
|
||||
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
default:
|
||||
cw.state = outsideCsiCode
|
||||
}
|
||||
}
|
||||
|
||||
if cw.state == outsideCsiCode {
|
||||
nw, err = cw.w.Write(p[first:len(p)])
|
||||
r += nw
|
||||
}
|
||||
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (cw *tagColorWriter) changeColor() {
|
||||
strParam := cw.paramBuf.String()
|
||||
if len(strParam) <= 0 {
|
||||
strParam = "0"
|
||||
}
|
||||
csiParam := strings.Split(strParam, string(separatorChar))
|
||||
for _, p := range csiParam {
|
||||
c, ok := colorMap[p]
|
||||
switch {
|
||||
case !ok:
|
||||
switch p {
|
||||
case ansiReset:
|
||||
fmt.Fprint(cw.w, "</"+cw.tag+">")
|
||||
cw.tag = ""
|
||||
case ansiIntensityOn:
|
||||
cw.tag = "bold-" + cw.tag
|
||||
case ansiIntensityOff:
|
||||
case ansiUnderlineOn:
|
||||
case ansiUnderlineOff:
|
||||
case ansiBlinkOn:
|
||||
case ansiBlinkOff:
|
||||
default:
|
||||
// unknown code
|
||||
}
|
||||
default:
|
||||
cw.tag += c
|
||||
fmt.Fprint(cw.w, "<"+cw.tag+">")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagColorWriter(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
w := &tagColorWriter{w: &buf}
|
||||
|
||||
s := fmt.Sprintf("text %s then %s", colors.Red("in red"), colors.Yellow("yel"))
|
||||
fmt.Fprint(w, s)
|
||||
|
||||
expected := "text <red>in red</red> then <yellow>yel</yellow>"
|
||||
if buf.String() != expected {
|
||||
t.Fatalf("expected `%s` but got `%s`", expected, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestTagBoldColorWriter(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
w := &tagColorWriter{w: &buf}
|
||||
|
||||
s := fmt.Sprintf(
|
||||
"text %s then %s",
|
||||
colors.Bold(colors.Red)("in red"),
|
||||
colors.Bold(colors.Yellow)("yel"),
|
||||
)
|
||||
fmt.Fprint(w, s)
|
||||
|
||||
expected := "text <bold-red>in red</bold-red> then <bold-yellow>yel</bold-yellow>"
|
||||
if buf.String() != expected {
|
||||
t.Fatalf("expected `%s` but got `%s`", expected, buf.String())
|
||||
}
|
||||
}
|
1
formatter-tests/features/empty.feature
Обычный файл
1
formatter-tests/features/empty.feature
Обычный файл
|
@ -0,0 +1 @@
|
|||
Feature: empty feature
|
4
formatter-tests/features/empty_with_description.feature
Обычный файл
4
formatter-tests/features/empty_with_description.feature
Обычный файл
|
@ -0,0 +1,4 @@
|
|||
Feature: empty feature
|
||||
describes
|
||||
an empty
|
||||
feature
|
|
@ -0,0 +1,3 @@
|
|||
Feature: empty feature
|
||||
|
||||
Scenario: without steps
|
|
@ -0,0 +1,6 @@
|
|||
Feature: empty feature
|
||||
describes
|
||||
an empty
|
||||
feature
|
||||
|
||||
Scenario: without steps
|
|
@ -0,0 +1,7 @@
|
|||
Feature: single passing scenario
|
||||
describes
|
||||
a single scenario
|
||||
feature
|
||||
|
||||
Scenario: one step passing
|
||||
Given a passing step
|
1
formatter-tests/pretty/empty
Обычный файл
1
formatter-tests/pretty/empty
Обычный файл
|
@ -0,0 +1 @@
|
|||
Feature: empty feature
|
1
formatters_print_test.go
Обычный файл
1
formatters_print_test.go
Обычный файл
|
@ -0,0 +1 @@
|
|||
package godog
|
Загрузка…
Создание таблицы
Сослаться в новой задаче