github.com/getgauge/gauge@v1.6.9/reporter/verboseColoredConsole.go (about) 1 /*---------------------------------------------------------------- 2 * Copyright (c) ThoughtWorks, Inc. 3 * Licensed under the Apache License, Version 2.0 4 * See LICENSE in the project root for license information. 5 *----------------------------------------------------------------*/ 6 7 package reporter 8 9 import ( 10 "bytes" 11 "fmt" 12 "io" 13 "strings" 14 15 "github.com/apoorvam/goterminal" 16 ct "github.com/daviddengcn/go-colortext" 17 "github.com/getgauge/gauge-proto/go/gauge_messages" 18 "github.com/getgauge/gauge/execution/result" 19 "github.com/getgauge/gauge/gauge" 20 "github.com/getgauge/gauge/logger" 21 ) 22 23 type verboseColoredConsole struct { 24 writer *goterminal.Writer 25 headingBuffer bytes.Buffer 26 pluginMessagesBuffer bytes.Buffer 27 errorMessagesBuffer bytes.Buffer 28 indentation int 29 } 30 31 func newVerboseColoredConsole(out io.Writer) *verboseColoredConsole { 32 return &verboseColoredConsole{writer: goterminal.New(out)} 33 } 34 35 func (c *verboseColoredConsole) SuiteStart() { 36 } 37 38 func (c *verboseColoredConsole) SpecStart(spec *gauge.Specification, res result.Result) { 39 if res.(*result.SpecResult).Skipped { 40 return 41 } 42 msg := formatSpec(spec.Heading.Value) 43 logger.Info(false, msg) 44 c.displayMessage(msg+newline, ct.Cyan) 45 c.writer.Reset() 46 } 47 48 func (c *verboseColoredConsole) SpecEnd(spec *gauge.Specification, res result.Result) { 49 if res.(*result.SpecResult).Skipped { 50 return 51 } 52 printHookFailureVCC(c, res, res.GetPreHook) 53 printHookFailureVCC(c, res, res.GetPostHook) 54 c.displayMessage(newline, ct.None) 55 c.writer.Reset() 56 } 57 58 func (c *verboseColoredConsole) ScenarioStart(scenario *gauge.Scenario, i *gauge_messages.ExecutionInfo, res result.Result) { 59 if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED { 60 return 61 } 62 c.indentation += scenarioIndentation 63 msg := formatScenario(scenario.Heading.Value) 64 logger.Info(false, msg) 65 66 indentedText := indent(msg+"\t", c.indentation) 67 c.displayMessage(indentedText+newline, ct.Yellow) 68 c.writer.Reset() 69 } 70 71 func (c *verboseColoredConsole) ScenarioEnd(scenario *gauge.Scenario, res result.Result, i *gauge_messages.ExecutionInfo) { 72 if res.(*result.ScenarioResult).ProtoScenario.ExecutionStatus == gauge_messages.ExecutionStatus_SKIPPED { 73 return 74 } 75 printHookFailureVCC(c, res, res.GetPreHook) 76 printHookFailureVCC(c, res, res.GetPostHook) 77 78 c.writer.Reset() 79 c.indentation -= scenarioIndentation 80 } 81 82 func (c *verboseColoredConsole) StepStart(stepText string) { 83 c.resetBuffers() 84 c.writer.Reset() 85 86 c.indentation += stepIndentation 87 logger.Debug(false, stepText) 88 _, err := c.headingBuffer.WriteString(indent(strings.TrimSpace(stepText), c.indentation)) 89 if err != nil { 90 logger.Errorf(false, "Unable to add message to heading Buffer : %s", err.Error()) 91 } 92 } 93 94 func (c *verboseColoredConsole) StepEnd(step gauge.Step, res result.Result, execInfo *gauge_messages.ExecutionInfo) { 95 stepRes := res.(*result.StepResult) 96 c.writer.Clear() 97 if !(hookFailed(res.GetPreHook) || hookFailed(res.GetPostHook)) { 98 if stepRes.GetStepFailed() { 99 c.displayMessage(c.headingBuffer.String()+"\t ...[FAIL]\n", ct.Red) 100 } else { 101 c.displayMessage(c.headingBuffer.String()+"\t ...[PASS]\n", ct.Green) 102 } 103 } else { 104 c.displayMessage(c.headingBuffer.String()+newline, ct.None) 105 } 106 printHookFailureVCC(c, res, res.GetPreHook) 107 c.displayMessage(c.pluginMessagesBuffer.String(), ct.None) 108 c.displayMessage(c.errorMessagesBuffer.String(), ct.Red) 109 if stepRes.GetStepFailed() { 110 stepText := prepStepMsg(step.LineText) 111 logger.Error(false, stepText) 112 errMsg := prepErrorMessage(stepRes.ProtoStepExecResult().GetExecutionResult().GetErrorMessage()) 113 logger.Error(false, errMsg) 114 specInfo := prepSpecInfo(execInfo.GetCurrentSpec().GetFileName(), step.LineNo, step.InConcept()) 115 logger.Error(false, specInfo) 116 stacktrace := prepStacktrace(stepRes.ProtoStepExecResult().GetExecutionResult().GetStackTrace()) 117 logger.Error(false, stacktrace) 118 119 msg := formatErrorFragment(stepText, c.indentation) + formatErrorFragment(specInfo, c.indentation) + formatErrorFragment(errMsg, c.indentation) + formatErrorFragment(stacktrace, c.indentation) 120 121 c.displayMessage(msg, ct.Red) 122 } 123 printHookFailureVCC(c, res, res.GetPostHook) 124 c.indentation -= stepIndentation 125 c.writer.Reset() 126 c.resetBuffers() 127 } 128 129 func (c *verboseColoredConsole) ConceptStart(conceptHeading string) { 130 c.indentation += stepIndentation 131 logger.Debug(false, conceptHeading) 132 c.displayMessage(indent(strings.TrimSpace(conceptHeading), c.indentation)+newline, ct.Magenta) 133 c.writer.Reset() 134 } 135 136 func (c *verboseColoredConsole) ConceptEnd(res result.Result) { 137 c.indentation -= stepIndentation 138 } 139 140 func (c *verboseColoredConsole) SuiteEnd(res result.Result) { 141 suiteRes := res.(*result.SuiteResult) 142 printHookFailureVCC(c, res, res.GetPreHook) 143 printHookFailureVCC(c, res, res.GetPostHook) 144 for _, e := range suiteRes.UnhandledErrors { 145 logger.Error(false, e.Error()) 146 c.displayMessage(indent(e.Error(), c.indentation+errorIndentation)+newline, ct.Red) 147 } 148 } 149 150 func (c *verboseColoredConsole) DataTable(table string) { 151 logger.Debug(false, table) 152 c.displayMessage(table, ct.Yellow) 153 c.writer.Reset() 154 } 155 156 func (c *verboseColoredConsole) Errorf(text string, args ...interface{}) { 157 msg := fmt.Sprintf(text, args...) 158 logger.Error(false, msg) 159 msg = indent(msg, c.indentation+errorIndentation) + newline 160 c.displayMessage(msg, ct.Red) 161 _, err := c.errorMessagesBuffer.WriteString(msg) 162 if err != nil { 163 logger.Errorf(false, "Unable to print error message '%s' : %s", msg, err.Error()) 164 } 165 } 166 167 // Write writes the bytes to console via goterminal's writer. 168 // This is called when any sysouts are to be printed on console. 169 func (c *verboseColoredConsole) Write(b []byte) (int, error) { 170 text := string(b) 171 n, err := c.pluginMessagesBuffer.WriteString(text) 172 if err != nil { 173 return n, err 174 } 175 c.displayMessage(text, ct.None) 176 return n, nil 177 } 178 179 func (c *verboseColoredConsole) displayMessage(msg string, color ct.Color) { 180 ct.Foreground(color, false) 181 defer ct.ResetColor() 182 fmt.Fprint(c.writer, msg) 183 err := c.writer.Print() 184 if err != nil { 185 logger.Error(false, err.Error()) 186 } 187 } 188 189 func (c *verboseColoredConsole) resetBuffers() { 190 c.headingBuffer.Reset() 191 c.pluginMessagesBuffer.Reset() 192 c.errorMessagesBuffer.Reset() 193 } 194 195 func printHookFailureVCC(c *verboseColoredConsole, res result.Result, hookFailure func() []*gauge_messages.ProtoHookFailure) bool { 196 if hookFailed(hookFailure) { 197 errMsg := prepErrorMessage(hookFailure()[0].GetErrorMessage()) 198 logger.Error(false, errMsg) 199 stacktrace := prepStacktrace(hookFailure()[0].GetStackTrace()) 200 logger.Error(false, stacktrace) 201 c.displayMessage(formatErrorFragment(errMsg, c.indentation)+formatErrorFragment(stacktrace, c.indentation), ct.Red) 202 return false 203 } 204 return true 205 } 206 207 func hookFailed(hookFailure func() []*gauge_messages.ProtoHookFailure) bool { 208 return len(hookFailure()) > 0 209 }