github.com/saucelabs/saucectl@v0.175.1/internal/cypress/code/parser.go (about)

     1  package code
     2  
     3  import (
     4  	"regexp"
     5  	"strings"
     6  )
     7  
     8  // Functions to parse cypress spec files for testcases and their metadata (e.g.
     9  // test titles and tags).
    10  // The general strategy is to parse in multiple passes; the first pass extracts
    11  // testcase definitions (e.g. it('some test title', { tags: '@tag' }, () => ...)
    12  // and subsequent passes extract the titles and tags.
    13  
    14  var (
    15  	reTestCasePattern  = regexp.MustCompile(`(?m)^ *(?:it|test|context|describe)(?:\.\w+)?(\([\s\S]*?,\s*(?:function)?\s*\()`)
    16  	reTitlePattern     = regexp.MustCompile(`\(["'\x60](.*?)["'\x60],\s*?(?:function)?|[{(]`)
    17  	reMultiTagPattern  = regexp.MustCompile(`tags\s*:\s*\[([\s\S]*?)\]`)
    18  	reSingleTagPattern = regexp.MustCompile(`tags\s*:\s*['"](.*?)["']`)
    19  )
    20  
    21  // TestCase describes the metadata for a cypress test case parsed from a cypress spec file.
    22  type TestCase struct {
    23  	// Title is the name of the test case, the first argument to `it|test`.
    24  	Title string
    25  	// Tags is an optional list of tags. This is simply a space delimited
    26  	// concatenation of all tags defined for the testcase.
    27  	Tags string
    28  }
    29  
    30  // Parse takes the contents of a test file and parses testcases
    31  func Parse(input string) []TestCase {
    32  	matches := reTestCasePattern.FindAllStringSubmatch(input, -1)
    33  
    34  	var testCases []TestCase
    35  	for _, m := range matches {
    36  		tc := TestCase{}
    37  		argSubMatch := m[1]
    38  
    39  		tc.Title = parseTitle(argSubMatch)
    40  		tc.Tags = parseTags(argSubMatch)
    41  
    42  		testCases = append(testCases, tc)
    43  	}
    44  
    45  	return testCases
    46  }
    47  
    48  func parseTitle(input string) string {
    49  	titleMatch := reTitlePattern.FindStringSubmatch(input)
    50  	if titleMatch != nil {
    51  		return titleMatch[1]
    52  	}
    53  
    54  	return ""
    55  }
    56  
    57  func parseTags(input string) string {
    58  	var tags []string
    59  	tagMatch := reSingleTagPattern.FindStringSubmatch(input)
    60  	if tagMatch == nil {
    61  		tagMatch = reMultiTagPattern.FindStringSubmatch(input)
    62  	}
    63  	if tagMatch != nil {
    64  		rawTags := strings.Split(tagMatch[1], ",")
    65  		for _, t := range rawTags {
    66  			t = strings.TrimSpace(t)
    67  			if t != "" {
    68  				tags = append(tags, strings.Trim(t, `"'`))
    69  			}
    70  		}
    71  		return strings.Join(tags, " ")
    72  	}
    73  	return ""
    74  }