1441 lines
38 KiB
Go
1441 lines
38 KiB
Go
package api_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/concourse/concourse/atc"
|
|
"github.com/concourse/concourse/atc/db"
|
|
"github.com/concourse/concourse/atc/db/dbfakes"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Builds API", func() {
|
|
|
|
Describe("POST /api/v1/builds", func() {
|
|
var plan atc.Plan
|
|
var response *http.Response
|
|
|
|
BeforeEach(func() {
|
|
plan = atc.Plan{
|
|
Task: &atc.TaskPlan{
|
|
Config: &atc.TaskConfig{
|
|
Run: atc.TaskRunConfig{
|
|
Path: "ls",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|
|
|
|
JustBeforeEach(func() {
|
|
reqPayload, err := json.Marshal(plan)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
req, err := http.NewRequest("POST", server.URL+"/api/v1/teams/some-team/builds", bytes.NewBuffer(reqPayload))
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
response, err = client.Do(req)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
|
|
It("does not trigger a build", func() {
|
|
Expect(dbTeam.CreateStartedBuildCallCount()).To(BeZero())
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
})
|
|
|
|
Context("when not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
Context("when creating a started build fails", func() {
|
|
BeforeEach(func() {
|
|
dbTeam.CreateStartedBuildReturns(nil, errors.New("oh no!"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when creating a started build succeeds", func() {
|
|
var fakeBuild *dbfakes.FakeBuild
|
|
|
|
BeforeEach(func() {
|
|
fakeBuild = new(dbfakes.FakeBuild)
|
|
fakeBuild.IDReturns(42)
|
|
fakeBuild.NameReturns("1")
|
|
fakeBuild.TeamNameReturns("some-team")
|
|
fakeBuild.StatusReturns("started")
|
|
fakeBuild.StartTimeReturns(time.Unix(1, 0))
|
|
fakeBuild.EndTimeReturns(time.Unix(100, 0))
|
|
fakeBuild.ReapTimeReturns(time.Unix(200, 0))
|
|
|
|
dbTeam.CreateStartedBuildReturns(fakeBuild, nil)
|
|
})
|
|
|
|
It("returns 201 Created", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusCreated))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("creates a started build", func() {
|
|
Expect(dbTeam.CreateStartedBuildCallCount()).To(Equal(1))
|
|
Expect(dbTeam.CreateStartedBuildArgsForCall(0)).To(Equal(plan))
|
|
})
|
|
|
|
It("returns the created build", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`{
|
|
"id": 42,
|
|
"name": "1",
|
|
"team_name": "some-team",
|
|
"status": "started",
|
|
"api_url": "/api/v1/builds/42",
|
|
"start_time": 1,
|
|
"end_time": 100,
|
|
"reap_time": 200
|
|
}`))
|
|
})
|
|
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds", func() {
|
|
var response *http.Response
|
|
var queryParams string
|
|
var returnedBuilds []db.Build
|
|
|
|
BeforeEach(func() {
|
|
queryParams = ""
|
|
build1 := new(dbfakes.FakeBuild)
|
|
build1.IDReturns(4)
|
|
build1.NameReturns("2")
|
|
build1.JobNameReturns("job2")
|
|
build1.PipelineNameReturns("pipeline2")
|
|
build1.TeamNameReturns("some-team")
|
|
build1.StatusReturns(db.BuildStatusStarted)
|
|
build1.StartTimeReturns(time.Unix(1, 0))
|
|
build1.EndTimeReturns(time.Unix(100, 0))
|
|
build1.ReapTimeReturns(time.Unix(300, 0))
|
|
|
|
build2 := new(dbfakes.FakeBuild)
|
|
build2.IDReturns(3)
|
|
build2.NameReturns("1")
|
|
build2.JobNameReturns("job1")
|
|
build2.PipelineNameReturns("pipeline1")
|
|
build2.TeamNameReturns("some-team")
|
|
build2.StatusReturns(db.BuildStatusSucceeded)
|
|
build2.StartTimeReturns(time.Unix(101, 0))
|
|
build2.EndTimeReturns(time.Unix(200, 0))
|
|
build2.ReapTimeReturns(time.Unix(400, 0))
|
|
|
|
returnedBuilds = []db.Build{build1, build2}
|
|
fakeAccess.TeamNamesReturns([]string{"some-team"})
|
|
})
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
response, err = client.Get(server.URL + "/api/v1/builds" + queryParams)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
Context("when no params are passed", func() {
|
|
BeforeEach(func() {
|
|
queryParams = ""
|
|
})
|
|
|
|
It("does not set defaults for since and until", func() {
|
|
Expect(dbBuildFactory.VisibleBuildsCallCount()).To(Equal(1))
|
|
|
|
teamName, page := dbBuildFactory.VisibleBuildsArgsForCall(0)
|
|
Expect(page).To(Equal(db.Page{
|
|
Since: 0,
|
|
Until: 0,
|
|
Limit: 100,
|
|
}))
|
|
Expect(teamName).To(ConsistOf("some-team"))
|
|
})
|
|
})
|
|
|
|
Context("when all the params are passed", func() {
|
|
BeforeEach(func() {
|
|
queryParams = "?since=2&until=3&limit=8"
|
|
})
|
|
|
|
It("passes them through", func() {
|
|
Expect(dbBuildFactory.VisibleBuildsCallCount()).To(Equal(1))
|
|
|
|
_, page := dbBuildFactory.VisibleBuildsArgsForCall(0)
|
|
Expect(page).To(Equal(db.Page{
|
|
Since: 2,
|
|
Until: 3,
|
|
Limit: 8,
|
|
}))
|
|
})
|
|
})
|
|
|
|
Context("when getting the builds succeeds", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(returnedBuilds, db.Pagination{}, nil)
|
|
})
|
|
|
|
It("returns 200 OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns all builds", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`[
|
|
{
|
|
"id": 4,
|
|
"name": "2",
|
|
"job_name": "job2",
|
|
"pipeline_name": "pipeline2",
|
|
"team_name": "some-team",
|
|
"status": "started",
|
|
"api_url": "/api/v1/builds/4",
|
|
"start_time": 1,
|
|
"end_time": 100,
|
|
"reap_time": 300
|
|
},
|
|
{
|
|
"id": 3,
|
|
"name": "1",
|
|
"job_name": "job1",
|
|
"pipeline_name": "pipeline1",
|
|
"team_name": "some-team",
|
|
"status": "succeeded",
|
|
"api_url": "/api/v1/builds/3",
|
|
"start_time": 101,
|
|
"end_time": 200,
|
|
"reap_time": 400
|
|
}
|
|
]`))
|
|
})
|
|
})
|
|
|
|
Context("when next/previous pages are available", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(returnedBuilds, db.Pagination{
|
|
Previous: &db.Page{Until: 4, Limit: 2},
|
|
Next: &db.Page{Since: 3, Limit: 2},
|
|
}, nil)
|
|
})
|
|
|
|
It("returns Link headers per rfc5988", func() {
|
|
Expect(response.Header["Link"]).To(ConsistOf([]string{
|
|
fmt.Sprintf(`<%s/api/v1/builds?until=4&limit=2>; rel="previous"`, externalURL),
|
|
fmt.Sprintf(`<%s/api/v1/builds?since=3&limit=2>; rel="next"`, externalURL),
|
|
}))
|
|
})
|
|
})
|
|
|
|
Context("when getting all builds fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(nil, db.Pagination{}, errors.New("oh no!"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
})
|
|
|
|
Context("when no params are passed", func() {
|
|
BeforeEach(func() {
|
|
queryParams = ""
|
|
})
|
|
|
|
It("does not set defaults for since and until", func() {
|
|
Expect(dbBuildFactory.VisibleBuildsCallCount()).To(Equal(1))
|
|
|
|
_, page := dbBuildFactory.VisibleBuildsArgsForCall(0)
|
|
Expect(page).To(Equal(db.Page{
|
|
Since: 0,
|
|
Until: 0,
|
|
Limit: 100,
|
|
}))
|
|
})
|
|
})
|
|
|
|
Context("when all the params are passed", func() {
|
|
BeforeEach(func() {
|
|
queryParams = "?since=2&until=3&limit=8"
|
|
})
|
|
|
|
It("passes them through", func() {
|
|
Expect(dbBuildFactory.VisibleBuildsCallCount()).To(Equal(1))
|
|
|
|
_, page := dbBuildFactory.VisibleBuildsArgsForCall(0)
|
|
Expect(page).To(Equal(db.Page{
|
|
Since: 2,
|
|
Until: 3,
|
|
Limit: 8,
|
|
}))
|
|
})
|
|
})
|
|
|
|
Context("when getting the builds succeeds", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(returnedBuilds, db.Pagination{}, nil)
|
|
})
|
|
|
|
It("returns 200 OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns all builds", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`[
|
|
{
|
|
"id": 4,
|
|
"name": "2",
|
|
"job_name": "job2",
|
|
"pipeline_name": "pipeline2",
|
|
"team_name": "some-team",
|
|
"status": "started",
|
|
"api_url": "/api/v1/builds/4",
|
|
"start_time": 1,
|
|
"end_time": 100,
|
|
"reap_time": 300
|
|
},
|
|
{
|
|
"id": 3,
|
|
"name": "1",
|
|
"job_name": "job1",
|
|
"pipeline_name": "pipeline1",
|
|
"team_name": "some-team",
|
|
"status": "succeeded",
|
|
"api_url": "/api/v1/builds/3",
|
|
"start_time": 101,
|
|
"end_time": 200,
|
|
"reap_time": 400
|
|
}
|
|
]`))
|
|
})
|
|
|
|
It("returns builds for teams from the token", func() {
|
|
Expect(dbBuildFactory.VisibleBuildsCallCount()).To(Equal(1))
|
|
teamName, _ := dbBuildFactory.VisibleBuildsArgsForCall(0)
|
|
Expect(teamName).To(ConsistOf("some-team"))
|
|
})
|
|
})
|
|
|
|
Context("when next/previous pages are available", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(returnedBuilds, db.Pagination{
|
|
Previous: &db.Page{Until: 4, Limit: 2},
|
|
Next: &db.Page{Since: 3, Limit: 2},
|
|
}, nil)
|
|
})
|
|
|
|
It("returns Link headers per rfc5988", func() {
|
|
Expect(response.Header["Link"]).To(ConsistOf([]string{
|
|
fmt.Sprintf(`<%s/api/v1/builds?until=4&limit=2>; rel="previous"`, externalURL),
|
|
fmt.Sprintf(`<%s/api/v1/builds?since=3&limit=2>; rel="next"`, externalURL),
|
|
}))
|
|
})
|
|
})
|
|
|
|
Context("when getting all builds fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.VisibleBuildsReturns(nil, db.Pagination{}, errors.New("oh no!"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds/:build_id", func() {
|
|
var response *http.Response
|
|
|
|
Context("when parsing the build_id fails", func() {
|
|
BeforeEach(func() {
|
|
fakeAccessor.CreateReturns(fakeAccess)
|
|
var err error
|
|
|
|
response, err = client.Get(server.URL + "/api/v1/builds/nope")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("returns Bad Request", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusBadRequest))
|
|
})
|
|
})
|
|
|
|
Context("when parsing the build_id succeeds", func() {
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
response, err = client.Get(server.URL + "/api/v1/builds/1")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when calling the database fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("disaster"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the build cannot be found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when the build can be found", func() {
|
|
BeforeEach(func() {
|
|
build.IDReturns(1)
|
|
build.NameReturns("1")
|
|
build.JobNameReturns("job1")
|
|
build.PipelineNameReturns("pipeline1")
|
|
build.TeamNameReturns("some-team")
|
|
build.StatusReturns(db.BuildStatusSucceeded)
|
|
build.StartTimeReturns(time.Unix(1, 0))
|
|
build.EndTimeReturns(time.Unix(100, 0))
|
|
build.ReapTimeReturns(time.Unix(200, 0))
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(true)
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
})
|
|
|
|
Context("and build is one off", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is private", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.PublicReturns(false)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is public", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.PublicReturns(true)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
})
|
|
|
|
Context("when user is not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
|
|
})
|
|
It("returns 200 OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
|
|
Context("when user is authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
It("returns 200 OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns the build with the given build_id", func() {
|
|
Expect(dbBuildFactory.BuildCallCount()).To(Equal(1))
|
|
buildID := dbBuildFactory.BuildArgsForCall(0)
|
|
Expect(buildID).To(Equal(1))
|
|
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`{
|
|
"id": 1,
|
|
"name": "1",
|
|
"status": "succeeded",
|
|
"job_name": "job1",
|
|
"pipeline_name": "pipeline1",
|
|
"team_name": "some-team",
|
|
"api_url": "/api/v1/builds/1",
|
|
"start_time": 1,
|
|
"end_time": 100,
|
|
"reap_time": 200
|
|
}`))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds/:build_id/resources", func() {
|
|
var response *http.Response
|
|
|
|
Context("when the build is found", func() {
|
|
BeforeEach(func() {
|
|
build.JobNameReturns("job1")
|
|
build.TeamNameReturns("some-team")
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
build.PipelineIDReturns(42)
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
})
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
response, err = client.Get(server.URL + "/api/v1/builds/3/resources")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
Context("and build is one off", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is private", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.PublicReturns(false)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is public", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.PublicReturns(true)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when authenticated, but not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when authenticated and authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
It("returns 200 OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
Context("when the build inputs/outputs are not empty", func() {
|
|
BeforeEach(func() {
|
|
build.ResourcesReturns([]db.BuildInput{
|
|
{
|
|
Name: "input1",
|
|
Version: atc.Version{"version": "value1"},
|
|
ResourceID: 1,
|
|
FirstOccurrence: true,
|
|
},
|
|
{
|
|
Name: "input2",
|
|
Version: atc.Version{"version": "value2"},
|
|
ResourceID: 2,
|
|
FirstOccurrence: false,
|
|
},
|
|
},
|
|
[]db.BuildOutput{
|
|
{
|
|
Name: "myresource3",
|
|
Version: atc.Version{"version": "value3"},
|
|
},
|
|
{
|
|
Name: "myresource4",
|
|
Version: atc.Version{"version": "value4"},
|
|
},
|
|
}, nil)
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns the build with it's input and output versioned resources", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`{
|
|
"inputs": [
|
|
{
|
|
"name": "input1",
|
|
"version": {"version": "value1"},
|
|
"pipeline_id": 42,
|
|
"first_occurrence": true
|
|
},
|
|
{
|
|
"name": "input2",
|
|
"version": {"version": "value2"},
|
|
"pipeline_id": 42,
|
|
"first_occurrence": false
|
|
}
|
|
],
|
|
"outputs": [
|
|
{
|
|
"name": "myresource3",
|
|
"version": {"version": "value3"}
|
|
},
|
|
{
|
|
"name": "myresource4",
|
|
"version": {"version": "value4"}
|
|
}
|
|
]
|
|
}`))
|
|
})
|
|
})
|
|
|
|
Context("when the build resources error", func() {
|
|
BeforeEach(func() {
|
|
build.ResourcesReturns([]db.BuildInput{}, []db.BuildOutput{}, errors.New("where are my feedback?"))
|
|
})
|
|
|
|
It("returns internal server error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("with an invalid build", func() {
|
|
Context("when the lookup errors", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(build, false, errors.New("Freakin' out man, I'm freakin' out!"))
|
|
})
|
|
|
|
It("returns internal server error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the build does not exist", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns internal server error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("with an invalid build_id", func() {
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
response, err = client.Get(server.URL + "/api/v1/builds/nope/resources")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
It("returns internal server error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusBadRequest))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds/:build_id/events", func() {
|
|
var (
|
|
request *http.Request
|
|
response *http.Response
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
var err error
|
|
|
|
request, err = http.NewRequest("GET", server.URL+"/api/v1/builds/128/events", nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
response, err = client.Do(request)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when the build can be found", func() {
|
|
BeforeEach(func() {
|
|
build.JobNameReturns("some-job")
|
|
build.TeamNameReturns("some-team")
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
})
|
|
|
|
Context("when authenticated, but not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(200))
|
|
})
|
|
|
|
It("serves the request via the event handler", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(string(body)).To(Equal("fake event handler factory was here"))
|
|
|
|
Expect(constructedEventHandler.build).To(Equal(build))
|
|
Expect(dbBuildFactory.BuildCallCount()).To(Equal(1))
|
|
buildID := dbBuildFactory.BuildArgsForCall(0)
|
|
Expect(buildID).To(Equal(128))
|
|
})
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
Context("and the pipeline is private", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is public", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(true)
|
|
})
|
|
|
|
Context("when the job is found", func() {
|
|
var fakeJob *dbfakes.FakeJob
|
|
|
|
BeforeEach(func() {
|
|
fakeJob = new(dbfakes.FakeJob)
|
|
fakePipeline.JobReturns(fakeJob, true, nil)
|
|
})
|
|
|
|
Context("and the job is private", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the job is public", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(true)
|
|
})
|
|
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(200))
|
|
})
|
|
|
|
It("serves the request via the event handler", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(string(body)).To(Equal("fake event handler factory was here"))
|
|
|
|
Expect(constructedEventHandler.build).To(Equal(build))
|
|
Expect(dbBuildFactory.BuildCallCount()).To(Equal(1))
|
|
buildID := dbBuildFactory.BuildArgsForCall(0)
|
|
Expect(buildID).To(Equal(128))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when finding the job fails", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, errors.New("nope"))
|
|
})
|
|
|
|
It("returns Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the job cannot be found", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when the build can not be found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when calling the database fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("nope"))
|
|
})
|
|
|
|
It("returns Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when calling the database fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("nope"))
|
|
})
|
|
|
|
It("returns Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("PUT /api/v1/builds/:build_id/abort", func() {
|
|
var (
|
|
response *http.Response
|
|
)
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
|
|
req, err := http.NewRequest("PUT", server.URL+"/api/v1/builds/128/abort", nil)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
response, err = client.Do(req)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
})
|
|
|
|
Context("when looking up the build fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("nope"))
|
|
})
|
|
|
|
It("returns 500", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the build can not be found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 404", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when the build is found", func() {
|
|
BeforeEach(func() {
|
|
build.TeamNameReturns("some-team")
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
})
|
|
|
|
Context("when not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
Context("when aborting the build fails", func() {
|
|
BeforeEach(func() {
|
|
build.MarkAsAbortedReturns(errors.New("nope"))
|
|
})
|
|
|
|
It("returns 500", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when aborting succeeds", func() {
|
|
BeforeEach(func() {
|
|
build.MarkAsAbortedReturns(nil)
|
|
})
|
|
|
|
It("returns 204", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNoContent))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds/:build_id/preparation", func() {
|
|
var response *http.Response
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
response, err = http.Get(server.URL + "/api/v1/builds/42/preparation")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when the build is found", func() {
|
|
var buildPrep db.BuildPreparation
|
|
|
|
BeforeEach(func() {
|
|
buildPrep = db.BuildPreparation{
|
|
BuildID: 42,
|
|
PausedPipeline: db.BuildPreparationStatusNotBlocking,
|
|
PausedJob: db.BuildPreparationStatusNotBlocking,
|
|
MaxRunningBuilds: db.BuildPreparationStatusBlocking,
|
|
Inputs: map[string]db.BuildPreparationStatus{
|
|
"foo": db.BuildPreparationStatusUnknown,
|
|
"bar": db.BuildPreparationStatusBlocking,
|
|
},
|
|
InputsSatisfied: db.BuildPreparationStatusBlocking,
|
|
MissingInputReasons: db.MissingInputReasons{"some-input": "some-reason"},
|
|
}
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
build.JobNameReturns("job1")
|
|
build.TeamNameReturns("some-team")
|
|
build.PreparationReturns(buildPrep, true, nil)
|
|
})
|
|
|
|
Context("when authenticated, but not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
Context("and build is one off", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is private", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is public", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(true)
|
|
})
|
|
|
|
Context("when the job is found", func() {
|
|
var fakeJob *dbfakes.FakeJob
|
|
BeforeEach(func() {
|
|
fakeJob = new(dbfakes.FakeJob)
|
|
fakePipeline.JobReturns(fakeJob, true, nil)
|
|
})
|
|
|
|
Context("when job is private", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("when job is public", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(true)
|
|
})
|
|
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when finding the job fails", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, errors.New("nope"))
|
|
})
|
|
|
|
It("returns Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the job cannot be found", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
It("fetches data from the db", func() {
|
|
Expect(build.PreparationCallCount()).To(Equal(1))
|
|
})
|
|
|
|
It("returns OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns the build preparation", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`{
|
|
"build_id": 42,
|
|
"paused_pipeline": "not_blocking",
|
|
"paused_job": "not_blocking",
|
|
"max_running_builds": "blocking",
|
|
"inputs": {
|
|
"foo": "unknown",
|
|
"bar": "blocking"
|
|
},
|
|
"inputs_satisfied": "blocking",
|
|
"missing_input_reasons": {
|
|
"some-input": "some-reason"
|
|
}
|
|
}`))
|
|
})
|
|
|
|
Context("when the build preparation is not found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
build.PreparationReturns(db.BuildPreparation{}, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when looking up the build preparation fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
build.PreparationReturns(db.BuildPreparation{}, false, errors.New("ho ho ho merry festivus"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when looking up the build fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("ho ho ho merry festivus"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when build is not found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 404", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("GET /api/v1/builds/:build_id/plan", func() {
|
|
var plan *json.RawMessage
|
|
|
|
var response *http.Response
|
|
|
|
BeforeEach(func() {
|
|
data := []byte(`{"some":"plan"}`)
|
|
plan = (*json.RawMessage)(&data)
|
|
})
|
|
|
|
JustBeforeEach(func() {
|
|
var err error
|
|
response, err = http.Get(server.URL + "/api/v1/builds/42/plan")
|
|
Expect(err).NotTo(HaveOccurred())
|
|
})
|
|
|
|
Context("when the build is found", func() {
|
|
BeforeEach(func() {
|
|
build.JobNameReturns("job1")
|
|
build.TeamNameReturns("some-team")
|
|
dbBuildFactory.BuildReturns(build, true, nil)
|
|
})
|
|
|
|
Context("when authenticated, but not authorized", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(false)
|
|
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
})
|
|
|
|
It("returns 403", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusForbidden))
|
|
})
|
|
})
|
|
|
|
Context("when not authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(false)
|
|
})
|
|
|
|
Context("and build is one off", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is private", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(false)
|
|
})
|
|
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
|
|
Context("and the pipeline is public", func() {
|
|
BeforeEach(func() {
|
|
build.PipelineReturns(fakePipeline, true, nil)
|
|
fakePipeline.PublicReturns(true)
|
|
})
|
|
|
|
Context("when finding the job fails", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, errors.New("nope"))
|
|
})
|
|
It("returns 500", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
|
|
Context("when the job does not exist", func() {
|
|
BeforeEach(func() {
|
|
fakePipeline.JobReturns(nil, false, nil)
|
|
})
|
|
It("returns 404", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when the job exists", func() {
|
|
var fakeJob *dbfakes.FakeJob
|
|
|
|
BeforeEach(func() {
|
|
fakeJob = new(dbfakes.FakeJob)
|
|
fakePipeline.JobReturns(fakeJob, true, nil)
|
|
})
|
|
|
|
Context("and the job is public", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(true)
|
|
})
|
|
Context("and the build has a plan", func() {
|
|
BeforeEach(func() {
|
|
build.HasPlanReturns(true)
|
|
})
|
|
It("returns 200", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
})
|
|
Context("and the build has no plan", func() {
|
|
BeforeEach(func() {
|
|
build.HasPlanReturns(false)
|
|
})
|
|
It("returns 404", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("and the job is private", func() {
|
|
BeforeEach(func() {
|
|
fakeJob.PublicReturns(false)
|
|
})
|
|
It("returns 401", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusUnauthorized))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when authenticated", func() {
|
|
BeforeEach(func() {
|
|
fakeAccess.IsAuthenticatedReturns(true)
|
|
fakeAccess.IsAuthorizedReturns(true)
|
|
})
|
|
|
|
Context("when the build returns a plan", func() {
|
|
BeforeEach(func() {
|
|
build.HasPlanReturns(true)
|
|
build.PublicPlanReturns(plan)
|
|
build.SchemaReturns("some-schema")
|
|
})
|
|
|
|
It("returns OK", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusOK))
|
|
})
|
|
|
|
It("returns Content-Type 'application/json'", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal("application/json"))
|
|
})
|
|
|
|
It("returns the plan", func() {
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
Expect(err).NotTo(HaveOccurred())
|
|
|
|
Expect(body).To(MatchJSON(`{
|
|
"schema": "some-schema",
|
|
"plan": {"some":"plan"}
|
|
}`))
|
|
})
|
|
})
|
|
|
|
Context("when the build has no plan", func() {
|
|
BeforeEach(func() {
|
|
build.HasPlanReturns(false)
|
|
})
|
|
|
|
It("returns no Content-Type header", func() {
|
|
Expect(response.Header.Get("Content-Type")).To(Equal(""))
|
|
})
|
|
|
|
It("returns not found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
Context("when the build is not found", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, nil)
|
|
})
|
|
|
|
It("returns Not Found", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusNotFound))
|
|
})
|
|
})
|
|
|
|
Context("when looking up the build fails", func() {
|
|
BeforeEach(func() {
|
|
dbBuildFactory.BuildReturns(nil, false, errors.New("oh no!"))
|
|
})
|
|
|
|
It("returns 500 Internal Server Error", func() {
|
|
Expect(response.StatusCode).To(Equal(http.StatusInternalServerError))
|
|
})
|
|
})
|
|
})
|
|
})
|