1 package com.atlassian.marketplace.client.impl;
2
3 import com.atlassian.marketplace.client.MpacException;
4 import com.atlassian.marketplace.client.model.ErrorDetail;
5 import com.atlassian.utt.matchers.NamedFunction;
6
7 import com.google.common.collect.ImmutableList;
8
9 import org.hamcrest.Matcher;
10 import org.hamcrest.Matchers;
11 import org.junit.Assert;
12 import org.junit.Before;
13 import org.junit.Test;
14
15 import static com.atlassian.fugue.Option.some;
16 import static com.atlassian.marketplace.client.TestObjects.BASE_URI;
17 import static com.atlassian.marketplace.client.impl.ClientTester.defaultRootResource;
18 import static com.atlassian.marketplace.client.model.TestModelBuilders.errorDetail;
19 import static com.atlassian.utt.reflect.ReflectionFunctions.accessor;
20 import static com.atlassian.utt.reflect.ReflectionFunctions.iterableAccessor;
21 import static org.hamcrest.MatcherAssert.assertThat;
22 import static org.hamcrest.Matchers.allOf;
23 import static org.hamcrest.Matchers.contains;
24 import static org.hamcrest.Matchers.not;
25 import static org.hamcrest.Matchers.nullValue;
26 import static org.mockito.Mockito.verify;
27
28 public class DefaultMarketplaceClientTest
29 {
30 ClientTester tester;
31
32 @Before
33 public void setUp() throws Exception
34 {
35 tester = new ClientTester(BASE_URI);
36 tester.mockResource(tester.apiBase, defaultRootResource());
37 }
38
39 @Test
40 public void addonsAccessorQueriesRootResource() throws Exception
41 {
42 tester.client.addons();
43
44 verify(tester.httpTransport).get(tester.apiBase);
45 }
46
47 @Test(expected=MpacException.class)
48 public void addonsAccessorThrowsExceptionIfRootResourceNotAvailable() throws Exception
49 {
50 tester.mockResourceError(tester.apiBase, 404);
51 tester.client.addons();
52 }
53
54 @Test
55 public void addonsAccessorReturnsNonNullObject() throws Exception
56 {
57 assertThat(tester.client.addons(), not(nullValue()));
58 }
59
60 @Test
61 public void applicationsAccessorQueriesRootResource() throws Exception
62 {
63 tester.client.applications();
64
65 verify(tester.httpTransport).get(tester.apiBase);
66 }
67
68 @Test(expected=MpacException.class)
69 public void applicationsAccessorThrowsExceptionIfRootResourceNotAvailable() throws Exception
70 {
71 tester.mockResourceError(tester.apiBase, 404);
72 tester.client.applications();
73 }
74
75 @Test
76 public void applicationsAccessorReturnsNonNullObject() throws Exception
77 {
78 assertThat(tester.client.applications(), not(nullValue()));
79 }
80
81 @Test
82 public void productsAccessorQueriesRootResource() throws Exception
83 {
84 tester.client.products();
85
86 verify(tester.httpTransport).get(tester.apiBase);
87 }
88
89 @Test(expected=MpacException.class)
90 public void productsAccessorThrowsExceptionIfRootResourceNotAvailable() throws Exception
91 {
92 tester.mockResourceError(tester.apiBase, 404);
93 tester.client.products();
94 }
95
96 @Test
97 public void productsAccessorReturnsNonNullObject() throws Exception
98 {
99 assertThat(tester.client.products(), not(nullValue()));
100 }
101
102 @Test
103 public void errorResponseWithNoBodyIsThrownWithJustStatusCode() throws Exception
104 {
105 tester.mockResourceError(tester.apiBase, 400);
106 apiShouldFail(allOf(
107 serverErrorStatus.is(400),
108 serverErrorMessage.is("error 400"),
109 serverErrorDetails.is(Matchers.<ErrorDetail>emptyIterable())
110 ));
111 }
112
113 private void apiShouldFail(Matcher<MpacException.ServerError> errorConditions) throws Exception
114 {
115 try
116 {
117 tester.client.addons();
118 Assert.fail("expected exception");
119 }
120 catch (MpacException.ServerError e)
121 {
122 assertThat(e, errorConditions);
123 }
124 }
125
126 @Test
127 public void errorResponseWithJsonBodyIsThrownWithStatusCodeAndDetails() throws Exception
128 {
129 ErrorDetail error1 = errorDetail("sorry");
130 ErrorDetail error2 = errorDetail("unacceptable", some("/your/apology"), some("bad.thing"));
131 ImmutableList<ErrorDetail> details = ImmutableList.of(error1, error2);
132
133 tester.mockResourceErrorBody(tester.apiBase, 400, details, "GET");
134
135 apiShouldFail(allOf(
136 serverErrorStatus.is(400),
137 serverErrorMessage.is("sorry, /your/apology: unacceptable"),
138 serverErrorDetails.is(contains(error1, error2))
139 ));
140 }
141
142 @Test
143 public void errorResponseWithNonJsonBodyIsThrownWithStatusCodeAndString() throws Exception
144 {
145 tester.mockResourceErrorBody(tester.apiBase, 400, "whatever", "GET");
146
147 apiShouldFail(allOf(
148 serverErrorStatus.is(400),
149 serverErrorMessage.is("whatever"),
150 serverErrorDetails.is(Matchers.<ErrorDetail>emptyIterable())
151 ));
152 }
153
154
155 @Test
156 public void errorResponseWithMalformedJsonBodyIsThrownWithStatusCodeAndString() throws Exception
157 {
158 tester.mockResourceErrorBody(tester.apiBase, 400, "{}", "GET");
159
160 apiShouldFail(allOf(
161 serverErrorStatus.is(400),
162 serverErrorMessage.is("{}"),
163 serverErrorDetails.is(Matchers.<ErrorDetail>emptyIterable())
164 ));
165 }
166
167 private static NamedFunction<MpacException.ServerError, Integer> serverErrorStatus =
168 accessor(MpacException.ServerError.class, int.class, "getStatus");
169
170 private static NamedFunction<MpacException.ServerError, String> serverErrorMessage =
171 accessor(MpacException.ServerError.class, String.class, "getMessage");
172
173 private static NamedFunction<MpacException.ServerError, Iterable<ErrorDetail>> serverErrorDetails =
174 iterableAccessor(MpacException.ServerError.class, ErrorDetail.class, "getErrorDetails");
175 }