github.com/getgauge/gauge@v1.6.9/api/lang/diagnostics_test.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 lang 8 9 import ( 10 "os" 11 "testing" 12 "time" 13 14 "reflect" 15 16 "strings" 17 18 "github.com/getgauge/gauge-proto/go/gauge_messages" 19 "github.com/getgauge/gauge/runner" 20 "github.com/getgauge/gauge/util" 21 "github.com/sourcegraph/go-langserver/pkg/lsp" 22 ) 23 24 var conceptFile = "foo.cpt" 25 var specFile = "foo.spec" 26 27 func TestMain(m *testing.M) { 28 exitCode := m.Run() 29 tearDown() 30 os.Exit(exitCode) 31 } 32 33 func setup() { 34 openFilesCache = &files{cache: make(map[lsp.DocumentURI][]string)} 35 openFilesCache.add(util.ConvertPathToURI(conceptFile), "") 36 openFilesCache.add(util.ConvertPathToURI(specFile), "") 37 responses := map[gauge_messages.Message_MessageType]interface{}{} 38 responses[gauge_messages.Message_StepValidateResponse] = &gauge_messages.StepValidateResponse{IsValid: true} 39 lRunner.runner = &runner.GrpcRunner{LegacyClient: &mockClient{responses: responses}, Timeout: time.Second * 30} 40 41 util.GetConceptFiles = func() []string { 42 return []string{conceptFile} 43 } 44 45 util.GetSpecFiles = func(paths []string) []string { 46 return []string{specFile} 47 } 48 } 49 func tearDown() { 50 lRunner.runner = nil 51 } 52 53 func TestDiagnosticWithParseErrorsInSpec(t *testing.T) { 54 setup() 55 specText := `Specification Heading 56 ===================== 57 58 Scenario Heading 59 ================ 60 61 * Step text` 62 63 uri := util.ConvertPathToURI(specFile) 64 openFilesCache.add(uri, specText) 65 66 want := []lsp.Diagnostic{ 67 { 68 Range: lsp.Range{ 69 Start: lsp.Position{Line: 0, Character: 0}, 70 End: lsp.Position{Line: 1, Character: 21}, 71 }, 72 Message: "Spec should have atleast one scenario", 73 Severity: 1, 74 }, 75 { 76 Range: lsp.Range{ 77 Start: lsp.Position{Line: 3, Character: 0}, 78 End: lsp.Position{Line: 4, Character: 16}, 79 }, 80 Message: "Multiple spec headings found in same file", 81 Severity: 1, 82 }, 83 } 84 85 diagnostics, err := getDiagnostics() 86 if err != nil { 87 t.Errorf("Expected no error, got : %s", err.Error()) 88 } 89 90 got := diagnostics[uri] 91 if !reflect.DeepEqual(got, want) { 92 t.Errorf("want: `%+v`,\n got: `%+v`", want, got) 93 } 94 } 95 96 func TestDiagnosticWithNoErrors(t *testing.T) { 97 setup() 98 specText := `Specification Heading 99 ===================== 100 101 Scenario Heading 102 ---------------- 103 104 * Step text 105 ` 106 uri := util.ConvertPathToURI(specFile) 107 openFilesCache.add(uri, specText) 108 d, err := getDiagnostics() 109 if err != nil { 110 t.Errorf("expected no error.\n Got: %s", err.Error()) 111 } 112 if len(d[uri]) > 0 { 113 t.Errorf("expected no error.\n Got: %+v", d) 114 } 115 } 116 117 func TestParseConcept(t *testing.T) { 118 setup() 119 cptText := `# concept 120 * foo 121 ` 122 uri := util.ConvertPathToURI(conceptFile) 123 openFilesCache.add(uri, cptText) 124 125 diagnostics := make(map[lsp.DocumentURI][]lsp.Diagnostic) 126 127 dictionary, err := validateConcepts(diagnostics) 128 if err != nil { 129 t.Errorf("expected no error.\n Got: %s", err.Error()) 130 } 131 132 if len(dictionary.ConceptsMap) == 0 { 133 t.Errorf("Concept dictionary is empty") 134 } 135 136 if len(diagnostics[uri]) > 0 { 137 t.Errorf("Parsing failed, got : %+v", diagnostics) 138 } 139 } 140 141 func TestDiagnosticsForConceptParseErrors(t *testing.T) { 142 setup() 143 cptText := `# concept` 144 145 uri := util.ConvertPathToURI(conceptFile) 146 147 openFilesCache.add(uri, cptText) 148 149 diagnostics := make(map[lsp.DocumentURI][]lsp.Diagnostic) 150 151 _, err := validateConcepts(diagnostics) 152 153 if err != nil { 154 t.Error(err) 155 } 156 if len(diagnostics[uri]) <= 0 { 157 t.Errorf("expected parse errors") 158 } 159 160 want := []lsp.Diagnostic{ 161 { 162 Range: lsp.Range{ 163 Start: lsp.Position{Line: 0, Character: 0}, 164 End: lsp.Position{Line: 0, Character: 9}, 165 }, 166 Message: "Concept should have atleast one step", 167 Severity: 1, 168 }, 169 } 170 171 if !reflect.DeepEqual(want, diagnostics[uri]) { 172 t.Errorf("want: `%v`,\n got: `%v`", want, diagnostics[uri]) 173 } 174 } 175 176 func TestDiagnosticOfConceptsWithCircularReference(t *testing.T) { 177 setup() 178 cptText := `# concept 179 * concept 180 ` 181 uri := util.ConvertPathToURI(conceptFile) 182 openFilesCache.add(uri, cptText) 183 184 diagnostics, err := getDiagnostics() 185 if err != nil { 186 t.Errorf("expected no error.\n Got: %s", err.Error()) 187 } 188 189 got := diagnostics[uri] 190 containsDiagnostics(got, 1, 0, "Circular reference found in concept.", t) 191 } 192 193 var containsDiagnostics = func(diagnostics []lsp.Diagnostic, line1, line2 int, startMessage string, t *testing.T) { 194 for _, diagnostic := range diagnostics { 195 if !strings.Contains(diagnostic.Message, startMessage) { 196 t.Errorf("Invalid error message, got : %s : ", diagnostic.Message) 197 } 198 if (diagnostic.Range.Start.Line != line1 || diagnostic.Range.Start.Line != line2) && diagnostic.Range.Start.Character != 0 { 199 t.Errorf("Invalid start in range, got : %+v : ", diagnostic.Range.Start) 200 } 201 if (diagnostic.Range.End.Line != line1 || diagnostic.Range.End.Line != line2) && diagnostic.Range.End.Character != 9 { 202 t.Errorf("Invalid end in range, got : %+v : ", diagnostic.Range.End) 203 } 204 if diagnostic.Severity != 1 { 205 t.Errorf("Invalid diagnostic severity, want : 1, got : %d : ", diagnostic.Severity) 206 } 207 } 208 }