...

Source file src/github.com/redhat-developer/odo/tests/helper/helper_documentation.go

Documentation: github.com/redhat-developer/odo/tests/helper

     1  package helper
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"regexp"
     9  	"runtime"
    10  	"strings"
    11  	"unicode"
    12  
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  const (
    17  	timePatternInOdo = `(\[[0-9smh]+\])` // e.g. [4s], [1m], [3ms]
    18  	staticTimeValue  = "[1s]"
    19  	// Credit: https://github.com/acarl005/stripansi/blob/master/stripansi.go
    20  	ansiPattern          = "[\u001B\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))"
    21  	unicodeSpinnerFrames = "◓◐◑◒"
    22  )
    23  
    24  var (
    25  	// Matches versions like "vX.Y.Z (6721c668b)" or "vX.Y.Z (6721c668b-dirty)" or "vX.Y.Z-rc (6721c668b-broken)"
    26  	reOdoVersion = regexp.MustCompile(`(v[0-9]+.[0-9]+.[0-9]+(?:-\w+)?)\s*\(\w+(-\w+)?\)`)
    27  )
    28  
    29  // ReplaceAllTimeInString replaces the time taken to download a Devfile or a starter project for an odo command with a custom value;
    30  // this function is helpful because the time value is variable and replacing it with the value in mdx content helps in comparing.
    31  func ReplaceAllTimeInString(docString string, timeString string) string {
    32  	reg := regexp.MustCompile(timePatternInOdo)
    33  	return reg.ReplaceAllString(docString, timeString)
    34  }
    35  
    36  // StripGitCommitFromVersion removes any git commit hash from the full odo version string.
    37  // For example, given a version string like "vX.Y.Z (6721c668b)", it will simply return "vX.Y.Z"
    38  func StripGitCommitFromVersion(docString string) string {
    39  	return reOdoVersion.ReplaceAllString(docString, "$1")
    40  }
    41  
    42  // StripSpinner strips the cmd out string of spaces, spinner statements and spinner frames
    43  func StripSpinner(docString string) (returnString string) {
    44  	sc := bufio.NewScanner(strings.NewReader(docString))
    45  	for sc.Scan() {
    46  		line := sc.Text()
    47  		// trim any special character present in the line
    48  		line = strings.TrimFunc(line, unicode.IsSpace)
    49  
    50  		if len(line) == 0 {
    51  			continue
    52  		}
    53  
    54  		// This check is to avoid spinner statements in the cmd output
    55  		// currently it does so for init and dev
    56  		// e.g. " •  Syncing file changes ..."
    57  		if (strings.HasPrefix(line, "•  Downloading") ||
    58  			strings.HasPrefix(line, "•  Syncing") ||
    59  			strings.HasPrefix(line, "•  Building") ||
    60  			strings.HasPrefix(line, "•  Waiting for the application") ||
    61  			strings.HasPrefix(line, "•  Creating the namespace") ||
    62  			strings.HasPrefix(line, "•  Creating the project")) &&
    63  			strings.HasSuffix(line, "...") {
    64  			continue
    65  		}
    66  		// Remove warnings, except "Pod is Pending"
    67  		if strings.HasPrefix(line, "⚠") && !strings.Contains(line, "Pod is Pending") {
    68  			continue
    69  		}
    70  		if strings.HasPrefix(line, "===") {
    71  			continue
    72  		}
    73  
    74  		// for some reason, splitting the docString by \n does not split the spinner frames,
    75  		// so we perform a side operation to remove the extra spinner frames that are not present in the final output
    76  		// e.g. "◐  Downloading devfile "java-maven" from registry "DefaultDevfileReg... \n ◓  Downloading devfile "java-maven" from registry "DefaultDevfileReg...\n\n ✓  Downloading devfile "java-maven" from registry "DefaultDevfileRegistry" [2s]"
    77  		if strings.ContainsAny(line, unicodeSpinnerFrames) {
    78  			line = "✓" + strings.SplitAfter(line, "✓")[1]
    79  		}
    80  		// this is specific to `odo dev` when it fails to pull images
    81  		if strings.Contains(line, "Failed to pull image") || strings.Contains(line, "Error:") {
    82  			continue
    83  		}
    84  		returnString += line + "\n"
    85  	}
    86  	// replace all instances of time to [1s], this is also done for mdx out
    87  	returnString = ReplaceAllTimeInString(returnString, staticTimeValue)
    88  	return
    89  }
    90  
    91  // GetMDXContent reads the content of MDX files, strips it of extra spaces and returns the string
    92  // it strips the extra space for an easy comparison
    93  func GetMDXContent(filePath string) (mdxContent string) {
    94  	// filename of this file
    95  	_, filename, _, _ := runtime.Caller(0)
    96  	// path to the docs directory
    97  	mdxDir := filepath.Join(filepath.Dir(filename), "..", "..", "docs", "website", "docs")
    98  
    99  	readFile, err := os.Open(filepath.Join(mdxDir, filePath))
   100  	defer func(err error) {
   101  		if err == nil {
   102  			readFile.Close()
   103  		}
   104  	}(err)
   105  	Expect(err).ToNot(HaveOccurred())
   106  
   107  	fileScanner := bufio.NewScanner(readFile)
   108  
   109  	fileScanner.Split(bufio.ScanLines)
   110  
   111  	for fileScanner.Scan() {
   112  		line := fileScanner.Text()
   113  		line = strings.TrimFunc(line, unicode.IsSpace)
   114  		if len(line) == 0 {
   115  			continue
   116  		}
   117  		mdxContent += line + "\n"
   118  	}
   119  
   120  	// replace all instances of time to [1s], this is also done for cmd out
   121  	mdxContent = ReplaceAllTimeInString(mdxContent, staticTimeValue)
   122  	mdxContent = StripGitCommitFromVersion(mdxContent)
   123  	return mdxContent
   124  }
   125  
   126  // StripAnsi strips the cmd out of ansi values used for fomatting(underline, colored line, etc.) the cmd out;
   127  // this function should be called before StripSpinner for better results
   128  // and is essential because mdx content does not support ansi
   129  // The regex used by this function is copied from https://github.com/acarl005/stripansi/
   130  func StripAnsi(docString string) (returnString string) {
   131  	reg, err := regexp.Compile(ansiPattern)
   132  	Expect(err).To(BeNil())
   133  	returnString = reg.ReplaceAllString(docString, "")
   134  	return
   135  }
   136  
   137  // StripInteractiveQuestion strips the extra output from interactive questions, leaving the final output
   138  // e.g. "? Is this correct? (Y/n) No? Is this correct? No"
   139  func StripInteractiveQuestion(docString string) (returnString string) {
   140  	returnString = docString
   141  	for _, question := range []string{"? Select language:", "? Select project type:", "? Select container for which you want to change configuration?", "? Is this correct?", "? Enter component name:", "? Which starter project do you want to use?", "? Select version:"} {
   142  		if strings.Count(returnString, question) > 1 {
   143  			returnString = returnString[:strings.Index(returnString, question)] + returnString[strings.LastIndex(returnString, question):]
   144  		}
   145  	}
   146  	return
   147  }
   148  
   149  // ReplaceAllForwardedPorts replaces the actual endpoints in cmd out with the ones in mdx out
   150  func ReplaceAllForwardedPorts(docString string, cmdEndpointsMap map[string]string, mdxEndpointsMap map[string]string) (returnString string) {
   151  	returnString = docString
   152  	for port, forward := range cmdEndpointsMap {
   153  		returnString = strings.ReplaceAll(returnString, fmt.Sprintf("Forwarding from %s -> %s", forward, port), fmt.Sprintf("Forwarding from %s -> %s", mdxEndpointsMap[port], port))
   154  	}
   155  	return
   156  }
   157  
   158  // ReplaceRegistryUrl replaces the registry URL used for testing by a more static one
   159  func ReplaceRegistryUrl(commonVar CommonVar, docString string) string {
   160  	return strings.ReplaceAll(docString, commonVar.GetDevfileRegistryURL(), "https://registry.stage.devfile.io")
   161  }
   162  

View as plain text