github.com/saucelabs/saucectl@v0.175.1/internal/saucereport/saucereport.go (about)

     1  package saucereport
     2  
     3  import (
     4  	"encoding/json"
     5  	"time"
     6  )
     7  
     8  // SauceReportFileName is the name for Sauce Labs report.
     9  const SauceReportFileName = "sauce-test-report.json"
    10  
    11  // The different states that a job can be in.
    12  const (
    13  	StatusPassed  = "passed"
    14  	StatusSkipped = "skipped"
    15  	StatusFailed  = "failed"
    16  )
    17  
    18  // SauceReport represents a report generated by Sauce Labs.
    19  type SauceReport struct {
    20  	Status      string       `json:"status,omitempty"`
    21  	Attachments []Attachment `json:"attachments,omitempty"`
    22  	Suites      []Suite      `json:"suites,omitempty"`
    23  }
    24  
    25  // Suite represents a suite in a report.
    26  type Suite struct {
    27  	Name        string       `json:"name,omitempty"`
    28  	Status      string       `json:"status,omitempty"`
    29  	Metadata    Metadata     `json:"metadata,omitempty"`
    30  	Suites      []Suite      `json:"suites,omitempty"`
    31  	Attachments []Attachment `json:"attachments,omitempty"`
    32  	Tests       []Test       `json:"tests,omitempty"`
    33  }
    34  
    35  // Test represents a test in a report.
    36  type Test struct {
    37  	Name           string       `json:"name,omitempty"`
    38  	Status         string       `json:"status,omitempty"`
    39  	StartTime      time.Time    `json:"startTime,omitempty"`
    40  	Duration       int          `json:"duration,omitempty"`
    41  	Attachments    []Attachment `json:"attachments,omitempty"`
    42  	Metadata       Metadata     `json:"metadata,omitempty"`
    43  	Output         string       `json:"output,omitempty"`
    44  	Code           Code         `json:"code,omitempty"`
    45  	VideoTimestamp float64      `json:"VideoTimestamp,omitempty"`
    46  }
    47  
    48  // Code represents the code of a test.
    49  type Code struct {
    50  	Lines []string `json:"lines,omitempty"`
    51  }
    52  
    53  // Attachment represents an attachment.
    54  type Attachment struct {
    55  	Name        string `json:"name,omitempty"`
    56  	Path        string `json:"path,omitempty"`
    57  	ContentType string `json:"contentType,omitempty"`
    58  }
    59  
    60  // Metadata represents metadata.
    61  type Metadata map[string]interface{}
    62  
    63  // Parse parses an json-encoded byte string and returns a `SauceReport` struct
    64  func Parse(fileContent []byte) (SauceReport, error) {
    65  	var report SauceReport
    66  	err := json.Unmarshal(fileContent, &report)
    67  	if err != nil {
    68  		return SauceReport{}, err
    69  	}
    70  	return report, nil
    71  }
    72  
    73  // GetFailedTests get names from failed tests.
    74  func GetFailedTests(report SauceReport) []string {
    75  	var failedTests []string
    76  	if report.Status == StatusPassed || report.Status == StatusSkipped {
    77  		return failedTests
    78  	}
    79  	for _, s := range report.Suites {
    80  		failedTests = append(failedTests, collectFailedTests(s)...)
    81  	}
    82  
    83  	return failedTests
    84  }
    85  
    86  func collectFailedTests(suite Suite) []string {
    87  	if len(suite.Suites) == 0 && len(suite.Tests) == 0 {
    88  		return []string{}
    89  	}
    90  	if suite.Status == StatusPassed || suite.Status == StatusSkipped {
    91  		return []string{}
    92  	}
    93  
    94  	var failedTests []string
    95  	for _, s := range suite.Suites {
    96  		if s.Status == StatusFailed {
    97  			failedTests = append(failedTests, collectFailedTests(s)...)
    98  		}
    99  	}
   100  	for _, t := range suite.Tests {
   101  		if t.Status == StatusFailed {
   102  			failedTests = append(failedTests, t.Name)
   103  		}
   104  	}
   105  
   106  	return failedTests
   107  }