go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/luci_notify/mailtmpl/bundle_test.go (about) 1 // Copyright 2019 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package mailtmpl 16 17 import ( 18 "context" 19 "testing" 20 21 buildbucketpb "go.chromium.org/luci/buildbucket/proto" 22 "go.chromium.org/luci/gae/impl/memory" 23 "go.chromium.org/luci/gae/service/datastore" 24 25 "go.chromium.org/luci/luci_notify/api/config" 26 "go.chromium.org/luci/luci_notify/common" 27 28 . "github.com/smartystreets/goconvey/convey" 29 . "go.chromium.org/luci/common/testing/assertions" 30 ) 31 32 func TestBundle(t *testing.T) { 33 t.Parallel() 34 35 Convey(`bundle`, t, func() { 36 c := memory.Use(context.Background()) 37 c = common.SetAppIDForTest(c, "luci-config") 38 39 templates := []*Template{ 40 { 41 Name: "default", 42 SubjectTextTemplate: "Build {{.Build.Id}} completed", 43 BodyHTMLTemplate: `Build {{.Build.Id}} completed with status {{.Build.Status}}`, 44 }, 45 { 46 Name: "markdown", 47 SubjectTextTemplate: "Build {{.Build.Id}}", 48 BodyHTMLTemplate: `{{.Build.SummaryMarkdown | markdown}}`, 49 }, 50 { 51 Name: "using_other_files", 52 SubjectTextTemplate: "", 53 BodyHTMLTemplate: ` 54 Reusing templates from other files. 55 {{template "inlineEntireFile" .}} 56 {{template "steps" .}}`, 57 }, 58 { 59 Name: "inlineEntireFile", 60 SubjectTextTemplate: "this file is shared", 61 BodyHTMLTemplate: `Build {{.Build.Id}}`, 62 }, 63 { 64 Name: "shared", 65 SubjectTextTemplate: "this file is shared", 66 BodyHTMLTemplate: `{{define "steps"}}steps of build {{.Build.Id}} go here{{end}}`, 67 }, 68 { 69 Name: "bad", 70 SubjectTextTemplate: "bad template", 71 BodyHTMLTemplate: `{{.FieldDoesNotExist}}`, 72 }, 73 } 74 So(datastore.Put(c, templates), ShouldBeNil) 75 datastore.GetTestable(c).CatchupIndexes() 76 77 bundle := NewBundle(templates) 78 So(bundle.Err, ShouldBeNil) 79 So(bundle.bodies.Lookup("default"), ShouldNotBeNil) 80 81 Convey(`GenerateEmail`, func() { 82 input := &config.TemplateInput{ 83 BuildbucketHostname: "buildbucket.example.com", 84 Build: &buildbucketpb.Build{ 85 Id: 54, 86 Builder: &buildbucketpb.BuilderID{ 87 Project: "chromium", 88 Bucket: "ci", 89 Builder: "linux-rel", 90 }, 91 Status: buildbucketpb.Status_SUCCESS, 92 SummaryMarkdown: "*ninja* compiled `11` files", 93 }, 94 } 95 96 Convey("simple template", func() { 97 subject, body := bundle.GenerateEmail("default", input) 98 // Assert on body first, since errors would be rendered in body. 99 So(body, ShouldEqual, "Build 54 completed with status SUCCESS") 100 So(subject, ShouldEqual, "Build 54 completed") 101 }) 102 103 Convey("markdown", func() { 104 _, body := bundle.GenerateEmail("markdown", input) 105 So(body, ShouldEqual, "<p><em>ninja</em> compiled <code>11</code> files</p>\n") 106 }) 107 108 Convey("template using other files", func() { 109 _, body := bundle.GenerateEmail("using_other_files", input) 110 So(body, ShouldEqual, ` 111 Reusing templates from other files. 112 Build 54 113 steps of build 54 go here`) 114 }) 115 116 Convey("error", func() { 117 _, body := bundle.GenerateEmail("bad", input) 118 So(body, ShouldContainSubstring, "spartan") 119 So(body, ShouldContainSubstring, "buildbucket.example.com") 120 }) 121 }) 122 123 Convey(`generateDefaultStatusMessage`, func() { 124 input := &config.TemplateInput{ 125 BuildbucketHostname: "buildbucket.example.com", 126 Build: &buildbucketpb.Build{ 127 Id: 123, 128 Builder: &buildbucketpb.BuilderID{ 129 Project: "chromium", 130 Bucket: "ci", 131 Builder: "linux-rel", 132 }, 133 Input: &buildbucketpb.Build_Input{ 134 GitilesCommit: &buildbucketpb.GitilesCommit{ 135 Id: "deadbeefdeadbeef", 136 }, 137 }, 138 }, 139 MatchingFailedSteps: []*buildbucketpb.Step{ 140 {Name: "test1"}, 141 {Name: "test2"}, 142 }, 143 } 144 145 So(generateDefaultStatusMessage(input), ShouldEqual, 146 `"test1", "test2" on https://buildbucket.example.com/build/123 linux-rel from deadbeefdeadbeef`) 147 }) 148 149 // Regression test for https://crbug.com/1084358. 150 Convey(`GenerateStatusMessage, nil commit`, func() { 151 input := &config.TemplateInput{ 152 BuildbucketHostname: "buildbucket.example.com", 153 Build: &buildbucketpb.Build{ 154 Id: 123, 155 Builder: &buildbucketpb.BuilderID{ 156 Project: "chromium", 157 Bucket: "ci", 158 Builder: "linux-rel", 159 }, 160 Input: &buildbucketpb.Build_Input{GitilesCommit: nil}, 161 }, 162 MatchingFailedSteps: []*buildbucketpb.Step{ 163 {Name: "test1"}, 164 {Name: "test2"}, 165 }, 166 } 167 168 So(generateDefaultStatusMessage(input), ShouldEqual, 169 `"test1", "test2" on https://buildbucket.example.com/build/123 linux-rel`) 170 }) 171 }) 172 } 173 174 func TestSplitTemplateFile(t *testing.T) { 175 t.Parallel() 176 Convey(`SplitTemplateFile`, t, func() { 177 Convey(`valid template`, func() { 178 s, b, err := SplitTemplateFile(`subject 179 180 body`) 181 182 So(err, ShouldBeNil) 183 So(s, ShouldEqual, "subject") 184 So(b, ShouldEqual, "body") 185 }) 186 187 Convey(`empty`, func() { 188 _, _, err := SplitTemplateFile(``) 189 So(err, ShouldErrLike, "empty") 190 }) 191 192 Convey(`single line`, func() { 193 s, b, err := SplitTemplateFile("one line") 194 195 So(err, ShouldBeNil) 196 So(s, ShouldEqual, "one line") 197 So(b, ShouldEqual, "") 198 }) 199 200 Convey(`blank second line`, func() { 201 s, b, err := SplitTemplateFile(`subject 202 `) 203 204 So(err, ShouldBeNil) 205 So(s, ShouldEqual, "subject") 206 So(b, ShouldEqual, "") 207 }) 208 209 Convey(`non-blank second line`, func() { 210 _, _, err := SplitTemplateFile(`subject 211 body`) 212 213 So(err, ShouldErrLike, "second line is not blank") 214 }) 215 216 Convey(`no blank line`, func() { 217 _, _, err := SplitTemplateFile(`subject 218 body 219 second line 220 `) 221 So(err, ShouldErrLike, "second line is not blank") 222 }) 223 }) 224 }