1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
15
"github.com/juju/testing"
16
jc "github.com/juju/testing/checkers"
17
gc "gopkg.in/check.v1"
19
"github.com/juju/terms-client/api"
20
"github.com/juju/terms-client/api/wireformat"
23
type apiSuite struct {
25
httpClient *mockHttpClient
28
func Test(t *stdtesting.T) {
32
var _ = gc.Suite(&apiSuite{})
34
func (s *apiSuite) SetUpTest(c *gc.C) {
38
func (s *apiSuite) newClient(c *gc.C) {
39
s.httpClient = &mockHttpClient{}
41
s.client, err = api.NewClient(api.HTTPClient(s.httpClient))
42
c.Assert(err, jc.ErrorIsNil)
45
func (s *apiSuite) TestPublish(c *gc.C) {
47
TermID string `json:"term-id"`
49
TermID: "test-owner/test-term/17",
51
s.httpClient.status = http.StatusOK
52
s.httpClient.SetBody(c, termID)
54
id, err := s.client.Publish("test-owner", "test-term", 17)
55
c.Assert(err, jc.ErrorIsNil)
56
c.Assert(id, gc.Equals, termID.TermID)
57
s.httpClient.CheckCall(c, 0, "DoWithBody", "https://api.jujucharms.com/terms/v1/terms/test-owner/test-term/17/publish")
60
func (s *apiSuite) TestSaveOwnedTerm(c *gc.C) {
61
term := wireformat.TermIDResponse{
62
TermID: "test-term/1",
64
s.httpClient.status = http.StatusOK
65
s.httpClient.SetBody(c, term)
66
savedTerm, err := s.client.SaveTerm("owner", "test-term", "You hereby agree to run this test.")
67
c.Assert(err, jc.ErrorIsNil)
68
c.Assert(savedTerm, jc.DeepEquals, term.TermID)
69
s.httpClient.CheckCall(c, 0, "DoWithBody", "https://api.jujucharms.com/terms/v1/terms/owner/test-term")
72
func (s *apiSuite) TestSaveOwnerlessTerm(c *gc.C) {
73
term := wireformat.TermIDResponse{
74
TermID: "test-term/1",
76
s.httpClient.status = http.StatusOK
77
s.httpClient.SetBody(c, term)
78
savedTerm, err := s.client.SaveTerm("", "test-term", "You hereby agree to run this test.")
79
c.Assert(err, jc.ErrorIsNil)
80
c.Assert(savedTerm, jc.DeepEquals, term.TermID)
81
s.httpClient.CheckCall(c, 0, "DoWithBody", "https://api.jujucharms.com/terms/v1/terms/test-term")
84
func (s *apiSuite) TestSaveTermError(c *gc.C) {
85
s.httpClient.status = http.StatusInternalServerError
86
s.httpClient.SetBody(c, struct {
87
Error string `json:"error"`
88
}{"silly internal error"})
89
_, err := s.client.SaveTerm("", "test-term", "You hereby agree to run this test.")
90
c.Assert(err, gc.ErrorMatches, "silly internal error")
93
func (s *apiSuite) TestGetOwnedTermWithRevision(c *gc.C) {
94
t := time.Now().Round(time.Second).UTC()
95
term := []wireformat.Term{{
99
CreatedOn: wireformat.TimeRFC3339(t),
100
Content: "You hereby agree to run this test.",
102
s.httpClient.status = http.StatusOK
103
s.httpClient.SetBody(c, term)
104
savedTerm, err := s.client.GetTerm("owner", "test-term", 17)
105
c.Assert(err, jc.ErrorIsNil)
106
c.Assert(savedTerm, jc.DeepEquals, &term[0])
107
s.httpClient.CheckCall(c, 0, "Do", "https://api.jujucharms.com/terms/v1/terms/owner/test-term?revision=17")
110
func (s *apiSuite) TestGetOwnedTermWithoutRevision(c *gc.C) {
111
t := time.Now().Round(time.Second).UTC()
112
term := []wireformat.Term{{
116
CreatedOn: wireformat.TimeRFC3339(t),
117
Content: "You hereby agree to run this test.",
119
s.httpClient.status = http.StatusOK
120
s.httpClient.SetBody(c, term)
121
savedTerm, err := s.client.GetTerm("owner", "test-term", 0)
122
c.Assert(err, jc.ErrorIsNil)
123
c.Assert(savedTerm, jc.DeepEquals, &term[0])
124
s.httpClient.CheckCall(c, 0, "Do", "https://api.jujucharms.com/terms/v1/terms/owner/test-term")
127
func (s *apiSuite) TestGetOwnerlessTermWithRevision(c *gc.C) {
128
t := time.Now().Round(time.Second).UTC()
129
term := []wireformat.Term{{
132
CreatedOn: wireformat.TimeRFC3339(t),
133
Content: "You hereby agree to run this test.",
135
s.httpClient.status = http.StatusOK
136
s.httpClient.SetBody(c, term)
137
savedTerm, err := s.client.GetTerm("", "test-term", 17)
138
c.Assert(err, jc.ErrorIsNil)
139
c.Assert(savedTerm, jc.DeepEquals, &term[0])
140
s.httpClient.CheckCall(c, 0, "Do", "https://api.jujucharms.com/terms/v1/terms/test-term?revision=17")
143
func (s *apiSuite) TestGetOwnerlessTermWithoutRevision(c *gc.C) {
144
t := time.Now().Round(time.Second).UTC()
145
term := []wireformat.Term{{
148
CreatedOn: wireformat.TimeRFC3339(t),
149
Content: "You hereby agree to run this test.",
151
s.httpClient.status = http.StatusOK
152
s.httpClient.SetBody(c, term)
153
savedTerm, err := s.client.GetTerm("", "test-term", 0)
154
c.Assert(err, jc.ErrorIsNil)
155
c.Assert(savedTerm, jc.DeepEquals, &term[0])
156
s.httpClient.CheckCall(c, 0, "Do", "https://api.jujucharms.com/terms/v1/terms/test-term")
159
func (s *apiSuite) TestGetTermError(c *gc.C) {
160
s.httpClient.status = http.StatusInternalServerError
161
s.httpClient.SetBody(c, struct {
162
Error string `json:"error"`
163
}{"silly internal error"})
164
_, err := s.client.GetTerm("", "test-term", 17)
165
c.Assert(err, gc.ErrorMatches, "silly internal error")
168
func (s *apiSuite) TestSignedAgreements(c *gc.C) {
169
t := time.Now().Round(time.Second).UTC()
170
s.httpClient.status = http.StatusOK
171
s.httpClient.SetBody(c, []wireformat.Agreement{{
173
Term: "hello-world-terms",
175
CreatedOn: wireformat.TimeRFC3339(t),
178
Term: "hello-universe-terms",
180
CreatedOn: wireformat.TimeRFC3339(t),
183
signedAgreements, err := s.client.GetUsersAgreements()
184
c.Assert(err, jc.ErrorIsNil)
185
c.Assert(signedAgreements, gc.HasLen, 2)
186
c.Assert(signedAgreements[0].User, gc.Equals, "test-user")
187
c.Assert(signedAgreements[0].Term, gc.Equals, "hello-world-terms")
188
c.Assert(signedAgreements[0].Revision, gc.Equals, 1)
189
c.Assert(signedAgreements[0].CreatedOn, gc.DeepEquals, t)
190
c.Assert(signedAgreements[1].User, gc.Equals, "test-user")
191
c.Assert(signedAgreements[1].Term, gc.Equals, "hello-universe-terms")
192
c.Assert(signedAgreements[1].Revision, gc.Equals, 42)
193
c.Assert(signedAgreements[1].CreatedOn, gc.DeepEquals, t)
196
func (s *apiSuite) TestUnsignedTerms(c *gc.C) {
197
s.httpClient.status = http.StatusOK
198
s.httpClient.SetBody(c, []wireformat.Term{{
199
Name: "hello-world-terms",
201
Content: "terms doc content",
203
Name: "hello-universe-terms",
205
Content: "universal terms doc content",
208
missingAgreements, err := s.client.GetUnsignedTerms(&wireformat.CheckAgreementsRequest{
210
"hello-world-terms/1",
211
"hello-universe-terms/1",
214
c.Assert(err, jc.ErrorIsNil)
215
c.Assert(missingAgreements, gc.HasLen, 2)
216
c.Assert(missingAgreements[0].Name, gc.Equals, "hello-world-terms")
217
c.Assert(missingAgreements[0].Revision, gc.Equals, 1)
218
c.Assert(missingAgreements[0].Content, gc.Equals, "terms doc content")
219
c.Assert(missingAgreements[1].Name, gc.Equals, "hello-universe-terms")
220
c.Assert(missingAgreements[1].Revision, gc.Equals, 1)
221
c.Assert(missingAgreements[1].Content, gc.Equals, "universal terms doc content")
222
s.httpClient.SetBody(c, wireformat.SaveAgreementResponses{
223
Agreements: []wireformat.AgreementResponse{{
225
Term: "hello-world-terms",
230
p1 := wireformat.SaveAgreements{
231
Agreements: []wireformat.SaveAgreement{{
232
TermName: "hello-world-terms",
236
response, err := s.client.SaveAgreement(&p1)
237
c.Assert(err, jc.ErrorIsNil)
238
c.Assert(response.Agreements, gc.HasLen, 1)
239
c.Assert(response.Agreements[0].User, gc.Equals, "test-user")
240
c.Assert(response.Agreements[0].Term, gc.Equals, "hello-world-terms")
241
c.Assert(response.Agreements[0].Revision, gc.Equals, 1)
244
func (s *apiSuite) TestNotFoundError(c *gc.C) {
245
s.httpClient.status = http.StatusNotFound
246
s.httpClient.body = []byte("something failed")
247
_, err := s.client.GetUnsignedTerms(&wireformat.CheckAgreementsRequest{
249
"hello-world-terms/1",
250
"hello-universe-terms/1",
253
c.Assert(err, gc.ErrorMatches, "failed to get unsigned terms: Not Found: something failed")
256
func (s *apiSuite) TestSignedAgreementsEnvTermsURL(c *gc.C) {
257
cleanup := testing.PatchEnvironment("JUJU_TERMS", "http://example.com")
261
t := time.Now().UTC()
262
s.httpClient.status = http.StatusOK
263
s.httpClient.SetBody(c, []wireformat.AgreementResponse{
266
Term: "hello-world-terms",
272
Term: "hello-universe-terms",
277
_, err := s.client.GetUsersAgreements()
278
c.Assert(err, jc.ErrorIsNil)
279
c.Assert(s.httpClient.Calls(), gc.HasLen, 1)
280
s.httpClient.CheckCall(c, 0, "Do", "http://example.com/v1/agreements")
283
func (s *apiSuite) TestUnsignedTermsEnvTermsURL(c *gc.C) {
284
cleanup := testing.PatchEnvironment("JUJU_TERMS", "http://example.com")
288
s.httpClient.status = http.StatusOK
289
s.httpClient.SetBody(c, []wireformat.GetTermsResponse{
291
Name: "hello-world-terms",
293
Content: "terms doc content",
296
Name: "hello-universe-terms",
298
Content: "universal terms doc content",
301
_, err := s.client.GetUnsignedTerms(&wireformat.CheckAgreementsRequest{
303
"hello-world-terms/1",
304
"hello-universe-terms/1",
307
c.Assert(err, jc.ErrorIsNil)
308
c.Assert(s.httpClient.Calls(), gc.HasLen, 1)
309
s.httpClient.CheckCall(c, 0, "Do", "http://example.com/v1/agreement?Terms=hello-world-terms%2F1&Terms=hello-universe-terms%2F1")
310
s.httpClient.ResetCalls()
313
func (s *apiSuite) TestSaveAgreementEnvTermsURL(c *gc.C) {
314
cleanup := testing.PatchEnvironment("JUJU_TERMS", "http://example.com")
318
s.httpClient.status = http.StatusOK
319
s.httpClient.SetBody(c, wireformat.SaveAgreementResponses{})
320
p1 := wireformat.SaveAgreements{
321
Agreements: []wireformat.SaveAgreement{{
322
TermName: "hello-world-terms",
326
_, err := s.client.SaveAgreement(&p1)
327
c.Assert(err, jc.ErrorIsNil)
328
c.Assert(s.httpClient.Calls(), gc.HasLen, 1)
329
s.httpClient.CheckCall(c, 0, "DoWithBody", "http://example.com/v1/agreement")
332
type mockHttpClient struct {
338
func (m *mockHttpClient) Do(req *http.Request) (*http.Response, error) {
339
m.AddCall("Do", req.URL.String())
340
return &http.Response{
341
Status: http.StatusText(m.status),
342
StatusCode: m.status,
346
Body: ioutil.NopCloser(bytes.NewReader(m.body)),
350
func (m *mockHttpClient) DoWithBody(req *http.Request, body io.ReadSeeker) (*http.Response, error) {
351
m.AddCall("DoWithBody", req.URL.String())
352
return &http.Response{
353
Status: http.StatusText(m.status),
354
StatusCode: m.status,
358
Body: ioutil.NopCloser(bytes.NewReader(m.body)),
362
func (m *mockHttpClient) SetBody(c *gc.C, v interface{}) {
363
b, err := json.Marshal(&v)
364
c.Assert(err, jc.ErrorIsNil)