github.com/getgauge/gauge@v1.6.9/cmd/list.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 cmd
     8  
     9  import (
    10  	"fmt"
    11  	supersort "sort"
    12  
    13  	gm "github.com/getgauge/gauge-proto/go/gauge_messages"
    14  	"github.com/getgauge/gauge/config"
    15  	"github.com/getgauge/gauge/manifest"
    16  	"github.com/getgauge/gauge/runner"
    17  	"github.com/getgauge/gauge/util"
    18  
    19  	"github.com/getgauge/gauge/filter"
    20  	"github.com/getgauge/gauge/gauge"
    21  	"github.com/getgauge/gauge/logger"
    22  	"github.com/getgauge/gauge/parser"
    23  	"github.com/spf13/cobra"
    24  )
    25  
    26  var (
    27  	listCmd = &cobra.Command{
    28  		Use:     "list [flags] [args]",
    29  		Short:   "List specifications, scenarios, steps or tags for a gauge project",
    30  		Long:    `List specifications, scenarios, steps or tags for a gauge project`,
    31  		Example: `  gauge list --tags specs`,
    32  		Run: func(cmd *cobra.Command, args []string) {
    33  			if err := config.SetProjectRoot(args); err != nil {
    34  				exit(err, cmd.UsageString())
    35  			}
    36  			loadEnvAndReinitLogger(cmd)
    37  			specs, failed := parser.ParseSpecs(getSpecsDir(args), gauge.NewConceptDictionary(), gauge.NewBuildErrors())
    38  			if failed {
    39  				return
    40  			}
    41  			if specsFlag {
    42  				logger.Info(true, "[Specifications]")
    43  				listSpecifications(specs, print)
    44  			}
    45  			if scenariosFlag {
    46  				logger.Info(true, "[Scenarios]")
    47  				listScenarios(specs, print)
    48  			}
    49  			if tagsFlag {
    50  				logger.Info(true, "[Tags]")
    51  				listTags(specs, print)
    52  			}
    53  			if stepsFlag {
    54  				logger.Info(true, "[Steps]")
    55  				listSteps(specs, print)
    56  			}
    57  			if !specsFlag && !scenariosFlag && !tagsFlag && !stepsFlag {
    58  				exit(fmt.Errorf("Missing flag, nothing to list"), cmd.UsageString())
    59  			}
    60  		},
    61  		DisableAutoGenTag: true,
    62  	}
    63  	tagsFlag      bool
    64  	specsFlag     bool
    65  	scenariosFlag bool
    66  	stepsFlag     bool
    67  )
    68  
    69  func init() {
    70  	GaugeCmd.AddCommand(listCmd)
    71  	listCmd.Flags().BoolVarP(&tagsFlag, "tags", "", false, "List the tags in projects")
    72  	listCmd.Flags().BoolVarP(&specsFlag, "specs", "", false, "List the specifications in projects")
    73  	listCmd.Flags().BoolVarP(&scenariosFlag, "scenarios", "", false, "List the scenarios in projects")
    74  	listCmd.Flags().BoolVarP(&stepsFlag, "steps", "", false, "List all the steps in projects (including concept steps). Does not include unused steps.")
    75  }
    76  
    77  type handleResult func([]string)
    78  
    79  func print(res []string) {
    80  	for _, element := range res {
    81  		logger.Info(true, element)
    82  	}
    83  }
    84  
    85  func listTags(s []*gauge.Specification, f handleResult) {
    86  	allTags := []string{}
    87  	for _, spec := range s {
    88  		allTags = appendTags(allTags, spec.Tags)
    89  		for _, scenario := range spec.Scenarios {
    90  			allTags = appendTags(allTags, scenario.Tags)
    91  		}
    92  	}
    93  	f(sortedDistinctElements(allTags))
    94  }
    95  
    96  func listScenarios(s []*gauge.Specification, f handleResult) {
    97  	allScenarios := filter.GetAllScenarios(s)
    98  	f(sortedDistinctElements(allScenarios))
    99  }
   100  
   101  func listSpecifications(s []*gauge.Specification, f handleResult) {
   102  	allSpecs := []string{}
   103  	for _, spec := range s {
   104  		allSpecs = append(allSpecs, spec.Heading.Value)
   105  	}
   106  	f(sortedDistinctElements(allSpecs))
   107  }
   108  
   109  func listSteps(s []*gauge.Specification, f handleResult) {
   110  	f(sortedDistinctElements(getImplementedStepsWithAliases()))
   111  }
   112  
   113  func sortedDistinctElements(s []string) []string {
   114  	unique := uniqueNonEmptyElementsOf(s)
   115  	supersort.Strings(unique)
   116  	return unique
   117  }
   118  
   119  func appendTags(s []string, tags *gauge.Tags) []string {
   120  	if tags != nil {
   121  		s = append(s, tags.Values()...)
   122  	}
   123  	return s
   124  }
   125  
   126  func uniqueNonEmptyElementsOf(input []string) []string {
   127  	unique := make(map[string]bool, len(input))
   128  	us := make([]string, len(unique))
   129  	for _, elem := range input {
   130  		if len(elem) != 0 && !unique[elem] {
   131  			us = append(us, elem)
   132  			unique[elem] = true
   133  		}
   134  	}
   135  
   136  	return us
   137  }
   138  
   139  func getImplementedStepsWithAliases() []string {
   140  	r, err := connectToRunner()
   141  	defer func() { _ = r.Kill() }()
   142  	if err != nil {
   143  		panic(err)
   144  	}
   145  	getAllStepsRequest := &gm.Message{MessageType: gm.Message_StepNamesRequest, StepNamesRequest: &gm.StepNamesRequest{}}
   146  	response, err := r.ExecuteMessageWithTimeout(getAllStepsRequest)
   147  	if err != nil {
   148  		exit(fmt.Errorf("error while connecting to runner : %s", err.Error()), "unable to get steps from runner")
   149  	}
   150  	return response.GetStepNamesResponse().GetSteps()
   151  }
   152  
   153  var connectToRunner = func() (runner.Runner, error) {
   154  	outFile, err := util.OpenFile(logger.ActiveLogFile)
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	manifest, err := manifest.ProjectManifest()
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	return runner.StartGrpcRunner(manifest, outFile, outFile, config.IdeRequestTimeout(), false)
   164  }