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  }