1package api_test 2 3import ( 4 "errors" 5 "io/ioutil" 6 "net/http" 7 "time" 8 9 "github.com/concourse/concourse/atc" 10 "github.com/concourse/concourse/atc/db" 11 "github.com/concourse/concourse/atc/db/dbfakes" 12 . "github.com/concourse/concourse/atc/testhelpers" 13 "github.com/tedsuo/rata" 14 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17) 18 19var _ = Describe("cc.xml", func() { 20 var ( 21 requestGenerator *rata.RequestGenerator 22 ) 23 24 BeforeEach(func() { 25 requestGenerator = rata.NewRequestGenerator(server.URL, atc.Routes) 26 }) 27 28 Describe("GET /api/v1/teams/:team_name/cc.xml", func() { 29 var response *http.Response 30 31 JustBeforeEach(func() { 32 req, err := requestGenerator.CreateRequest(atc.GetCC, rata.Params{ 33 "team_name": "a-team", 34 }, nil) 35 Expect(err).NotTo(HaveOccurred()) 36 37 response, err = client.Do(req) 38 Expect(err).NotTo(HaveOccurred()) 39 }) 40 41 Context("when authorized", func() { 42 BeforeEach(func() { 43 fakeAccess.IsAuthenticatedReturns(true) 44 fakeAccess.IsAuthorizedReturns(true) 45 }) 46 47 Context("when the team is found", func() { 48 var fakeTeam *dbfakes.FakeTeam 49 BeforeEach(func() { 50 fakeTeam = new(dbfakes.FakeTeam) 51 fakeTeam.NameReturns("a-team") 52 dbTeamFactory.FindTeamReturns(fakeTeam, true, nil) 53 }) 54 55 Context("when a pipeline is found", func() { 56 var fakePipeline *dbfakes.FakePipeline 57 BeforeEach(func() { 58 fakePipeline = new(dbfakes.FakePipeline) 59 fakeTeam.PipelinesReturns([]db.Pipeline{ 60 fakePipeline, 61 }, nil) 62 }) 63 64 Context("when a job is found", func() { 65 var endTime time.Time 66 BeforeEach(func() { 67 fakePipeline.DashboardReturns(atc.Dashboard{ 68 { 69 Name: "some-job", 70 PipelineName: "something-else", 71 TeamName: "a-team", 72 }, 73 }, nil) 74 75 endTime, _ = time.Parse(time.RFC3339, "2018-11-04T21:26:38Z") 76 }) 77 78 Context("when the last build is successful", func() { 79 BeforeEach(func() { 80 fakePipeline.DashboardReturns(atc.Dashboard{ 81 { 82 Name: "some-job", 83 PipelineName: "something-else", 84 TeamName: "a-team", 85 FinishedBuild: &atc.DashboardBuild{ 86 Name: "42", 87 Status: "succeeded", 88 EndTime: endTime, 89 }, 90 }, 91 }, nil) 92 }) 93 94 It("returns 200", func() { 95 Expect(response.StatusCode).To(Equal(http.StatusOK)) 96 }) 97 98 It("returns Content-Type 'application/xml'", func() { 99 expectedHeaderEntries := map[string]string{ 100 "Content-Type": "application/xml", 101 } 102 Expect(response).Should(IncludeHeaderEntries(expectedHeaderEntries)) 103 }) 104 105 It("returns the CC.xml", func() { 106 body, err := ioutil.ReadAll(response.Body) 107 Expect(err).NotTo(HaveOccurred()) 108 109 Expect(body).To(MatchXML(` 110<Projects> 111 <Project activity="Sleeping" lastBuildLabel="42" lastBuildStatus="Success" lastBuildTime="2018-11-04T21:26:38Z" name="something-else/some-job" webUrl="https://example.com/teams/a-team/pipelines/something-else/jobs/some-job"/> 112</Projects> 113`)) 114 }) 115 }) 116 117 Context("when the last build is aborted", func() { 118 BeforeEach(func() { 119 fakePipeline.DashboardReturns(atc.Dashboard{ 120 { 121 Name: "some-job", 122 PipelineName: "something-else", 123 TeamName: "a-team", 124 FinishedBuild: &atc.DashboardBuild{ 125 Name: "42", 126 Status: "aborted", 127 EndTime: endTime, 128 }, 129 }, 130 }, nil) 131 }) 132 133 It("returns the CC.xml", func() { 134 body, err := ioutil.ReadAll(response.Body) 135 Expect(err).NotTo(HaveOccurred()) 136 137 Expect(body).To(MatchXML(` 138<Projects> 139 <Project activity="Sleeping" lastBuildLabel="42" lastBuildStatus="Exception" lastBuildTime="2018-11-04T21:26:38Z" name="something-else/some-job" webUrl="https://example.com/teams/a-team/pipelines/something-else/jobs/some-job"/> 140</Projects> 141`)) 142 }) 143 }) 144 145 Context("when the last build is errored", func() { 146 BeforeEach(func() { 147 fakePipeline.DashboardReturns(atc.Dashboard{ 148 { 149 Name: "some-job", 150 PipelineName: "something-else", 151 TeamName: "a-team", 152 FinishedBuild: &atc.DashboardBuild{ 153 Name: "42", 154 Status: "errored", 155 EndTime: endTime, 156 }, 157 }, 158 }, nil) 159 }) 160 161 It("returns the CC.xml", func() { 162 body, err := ioutil.ReadAll(response.Body) 163 Expect(err).NotTo(HaveOccurred()) 164 165 Expect(body).To(MatchXML(` 166<Projects> 167 <Project activity="Sleeping" lastBuildLabel="42" lastBuildStatus="Exception" lastBuildTime="2018-11-04T21:26:38Z" name="something-else/some-job" webUrl="https://example.com/teams/a-team/pipelines/something-else/jobs/some-job"/> 168</Projects> 169`)) 170 }) 171 }) 172 173 Context("when the last build is failed", func() { 174 BeforeEach(func() { 175 fakePipeline.DashboardReturns(atc.Dashboard{ 176 { 177 Name: "some-job", 178 PipelineName: "something-else", 179 TeamName: "a-team", 180 FinishedBuild: &atc.DashboardBuild{ 181 Name: "42", 182 Status: "failed", 183 EndTime: endTime, 184 }, 185 }, 186 }, nil) 187 }) 188 189 It("returns the CC.xml", func() { 190 body, err := ioutil.ReadAll(response.Body) 191 Expect(err).NotTo(HaveOccurred()) 192 193 Expect(body).To(MatchXML(` 194<Projects> 195 <Project activity="Sleeping" lastBuildLabel="42" lastBuildStatus="Failure" lastBuildTime="2018-11-04T21:26:38Z" name="something-else/some-job" webUrl="https://example.com/teams/a-team/pipelines/something-else/jobs/some-job"/> 196</Projects> 197`)) 198 }) 199 }) 200 201 Context("when a next build exists", func() { 202 BeforeEach(func() { 203 fakePipeline.DashboardReturns(atc.Dashboard{ 204 { 205 Name: "some-job", 206 PipelineName: "something-else", 207 TeamName: "a-team", 208 FinishedBuild: &atc.DashboardBuild{ 209 Name: "42", 210 Status: "succeeded", 211 EndTime: endTime, 212 }, 213 NextBuild: &atc.DashboardBuild{}, 214 }, 215 }, nil) 216 }) 217 218 It("returns the CC.xml", func() { 219 body, err := ioutil.ReadAll(response.Body) 220 Expect(err).NotTo(HaveOccurred()) 221 222 Expect(body).To(MatchXML(` 223<Projects> 224 <Project activity="Building" lastBuildLabel="42" lastBuildStatus="Success" lastBuildTime="2018-11-04T21:26:38Z" name="something-else/some-job" webUrl="https://example.com/teams/a-team/pipelines/something-else/jobs/some-job"/> 225</Projects> 226`)) 227 }) 228 }) 229 230 Context("when no last build exists", func() { 231 It("returns the CC.xml without the job", func() { 232 body, err := ioutil.ReadAll(response.Body) 233 Expect(err).NotTo(HaveOccurred()) 234 235 Expect(body).To(MatchXML("<Projects></Projects>")) 236 }) 237 }) 238 }) 239 240 Context("when no job is found", func() { 241 BeforeEach(func() { 242 fakePipeline.DashboardReturns(atc.Dashboard{}, nil) 243 }) 244 245 It("returns 200", func() { 246 Expect(response.StatusCode).To(Equal(http.StatusOK)) 247 }) 248 249 It("returns the CC.xml", func() { 250 body, err := ioutil.ReadAll(response.Body) 251 Expect(err).NotTo(HaveOccurred()) 252 253 Expect(body).To(MatchXML("<Projects></Projects>")) 254 }) 255 }) 256 257 Context("when finding the jobs fails", func() { 258 BeforeEach(func() { 259 fakePipeline.DashboardReturns(nil, errors.New("failed")) 260 }) 261 262 It("returns 500", func() { 263 Expect(response.StatusCode).To(Equal(http.StatusInternalServerError)) 264 }) 265 }) 266 }) 267 268 Context("when no pipeline is found", func() { 269 BeforeEach(func() { 270 fakeTeam.PipelinesReturns([]db.Pipeline{}, nil) 271 }) 272 273 It("returns 200", func() { 274 Expect(response.StatusCode).To(Equal(http.StatusOK)) 275 }) 276 277 It("returns the CC.xml", func() { 278 body, err := ioutil.ReadAll(response.Body) 279 Expect(err).NotTo(HaveOccurred()) 280 281 Expect(body).To(MatchXML("<Projects></Projects>")) 282 }) 283 }) 284 285 Context("when getting the pipelines fails", func() { 286 BeforeEach(func() { 287 fakeTeam.PipelinesReturns(nil, errors.New("failed")) 288 }) 289 290 It("returns 500", func() { 291 Expect(response.StatusCode).To(Equal(http.StatusInternalServerError)) 292 }) 293 }) 294 }) 295 296 Context("when the team is not found", func() { 297 BeforeEach(func() { 298 dbTeamFactory.FindTeamReturns(nil, false, nil) 299 }) 300 301 It("returns 404", func() { 302 Expect(response.StatusCode).To(Equal(http.StatusNotFound)) 303 }) 304 }) 305 306 Context("when finding the team fails", func() { 307 BeforeEach(func() { 308 dbTeamFactory.FindTeamReturns(nil, false, errors.New("failed")) 309 }) 310 311 It("returns 500", func() { 312 Expect(response.StatusCode).To(Equal(http.StatusInternalServerError)) 313 }) 314 }) 315 }) 316 317 Context("when not authenticated", func() { 318 BeforeEach(func() { 319 fakeAccess.IsAuthenticatedReturns(false) 320 }) 321 322 It("returns 401", func() { 323 Expect(response.StatusCode).To(Equal(http.StatusUnauthorized)) 324 }) 325 }) 326 }) 327}) 328