1 package com.atlassian.marketplace.client.impl;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.InputStream;
5 import java.net.URI;
6
7 import com.atlassian.marketplace.client.MpacException;
8 import com.atlassian.marketplace.client.model.Entity;
9
10 import com.google.common.collect.ImmutableList;
11 import com.google.common.collect.ImmutableMap;
12
13 import org.junit.Before;
14 import org.junit.Test;
15
16 import static com.atlassian.fugue.Option.none;
17 import static com.atlassian.fugue.Option.some;
18 import static com.atlassian.marketplace.client.TestObjects.BASE_URI;
19 import static com.atlassian.marketplace.client.impl.ClientTester.defaultRootResource;
20 import static org.hamcrest.MatcherAssert.assertThat;
21 import static org.hamcrest.Matchers.equalTo;
22 import static org.hamcrest.Matchers.sameInstance;
23 import static org.junit.Assert.fail;
24 import static org.mockito.Matchers.any;
25 import static org.mockito.Matchers.eq;
26 import static org.mockito.Mockito.verify;
27
28 public abstract class ApiImplTestBaseWithCreateAndUpdate<T extends Entity> extends ApiImplTestBase
29 {
30 private static final String FAKE_PATCH = "[patching]";
31
32 protected ClientTester tester;
33
34 @Before
35 public void setUp() throws Exception
36 {
37 tester = new ClientTester(BASE_URI);
38 tester.mockResource(tester.apiBase, defaultRootResource());
39 }
40
41 protected abstract URI getCollectionUri();
42 protected abstract T makeEntityToCreate();
43 protected abstract T makeEntityWithUpdates(T from);
44 protected abstract T makeEntityFromServer();
45 protected abstract T createEntity(T entity) throws Exception;
46 protected abstract T updateEntity(T original, T updated) throws Exception;
47
48 protected URI transformEntityUriAfterCreate(URI uri)
49 {
50 return uri;
51 }
52
53 @Test
54 public void createPostsToCollectionResource() throws Exception
55 {
56 T entity = makeEntityToCreate();
57 tester.mockPostResource(getCollectionUri(), 201,
58 ImmutableMap.<String, Iterable<String>>of("Location", ImmutableList.of("/newuri")));
59 tester.mockResource(transformEntityUriAfterCreate(tester.apiBase.resolve("/newuri")), entity);
60
61 createEntity(entity);
62
63 ByteArrayOutputStream bos = new ByteArrayOutputStream();
64 tester.encoding.encode(bos, entity, false);
65 byte[] data = bos.toByteArray();
66
67 verify(tester.httpTransport).post(any(URI.class),
68 any(InputStream.class),
69 eq((long) data.length),
70 eq("application/json"),
71 eq("application/json"));
72 }
73
74 @Test
75 public void createReturnsNewEntity() throws Exception
76 {
77 T result = makeEntityFromServer();
78
79 tester.mockPostResource(getCollectionUri(), 201,
80 ImmutableMap.<String, Iterable<String>>of("Location", ImmutableList.of("/newuri")));
81 tester.mockResource(transformEntityUriAfterCreate(tester.apiBase.resolve("/newuri")), result);
82
83 assertThat(createEntity(makeEntityToCreate()), sameInstance(result));
84 }
85
86 @Test
87 public void createThrowsExceptionIfServerReturnsError() throws Exception
88 {
89 tester.mockPostResource(getCollectionUri(), 400);
90
91 try
92 {
93 createEntity(makeEntityToCreate());
94 fail("expected error");
95 }
96 catch (MpacException.ServerError e)
97 {
98 assertThat(e.getStatus(), equalTo(400));
99 }
100 }
101
102 @Test
103 public void updateSendsPatchRequest() throws Exception
104 {
105 T original = makeEntityFromServer();
106 T updated = makeEntityWithUpdates(original);
107 URI uri = tester.apiBase.resolve(original.getSelfUri());
108 URI newUri = URI.create("/newuri");
109 tester.mockPatchResource(uri, 204, some(newUri.toASCIIString()));
110 tester.mockResource(tester.apiBase.resolve(newUri), updated);
111 tester.mockPatchDocument(original, updated, FAKE_PATCH);
112
113 updateEntity(original, updated);
114
115 verify(tester.httpTransport).patch(uri, FAKE_PATCH.getBytes());
116 }
117
118 @Test
119 public void updateReturnsNewEntity() throws Exception
120 {
121 T original = makeEntityFromServer();
122 T updated = makeEntityWithUpdates(original);
123 T result = makeEntityFromServer();
124 URI uri = tester.apiBase.resolve(original.getSelfUri());
125 URI newUri = URI.create("/newuri");
126 tester.mockPatchResource(uri, 204, some(newUri.toASCIIString()));
127 tester.mockResource(tester.apiBase.resolve(newUri), result);
128
129 assertThat(updateEntity(original, updated), sameInstance(result));
130 }
131
132 @Test
133 public void updateQueriesNewEntityWithNoCaching() throws Exception
134 {
135 T original = makeEntityFromServer();
136 T updated = makeEntityWithUpdates(original);
137 T result = makeEntityFromServer();
138 URI uri = tester.apiBase.resolve(original.getSelfUri());
139 URI newUri = URI.create("/newuri");
140 tester.mockPatchResource(uri, 204, some(newUri.toASCIIString()));
141 tester.mockResource(tester.apiBase.resolve(newUri), result);
142
143 updateEntity(original, updated);
144
145 assertThat(tester.getReceivedExtraHeaders(tester.apiBase.resolve(newUri), "GET"),
146 equalTo(ImmutableMap.of("Cache-Control", "no-cache")));
147 }
148
149 @Test
150 public void updateThrowsExceptionIfServerReturnsError() throws Exception
151 {
152 T original = makeEntityFromServer();
153 T updated = makeEntityWithUpdates(original);
154 URI uri = tester.apiBase.resolve(original.getSelfUri());
155 tester.mockPatchResource(uri, 400, none(String.class));
156
157 try
158 {
159 updateEntity(original, updated);
160 fail("expected error");
161 }
162 catch (MpacException.ServerError e)
163 {
164 assertThat(e.getStatus(), equalTo(400));
165 }
166 }
167
168 @Test
169 public void updateThrowsExceptionIfFinalQueryOfUpdatedEntityFails() throws Exception
170 {
171 T original = makeEntityFromServer();
172 T updated = makeEntityWithUpdates(original);
173 URI uri = tester.apiBase.resolve(original.getSelfUri());
174 URI newUri = URI.create("/newuri");
175 tester.mockPatchResource(uri, 204, some(newUri.toASCIIString()));
176 tester.mockResourceError(tester.apiBase.resolve(newUri), 404);
177
178 try
179 {
180 updateEntity(original, updated);
181 fail("expected error");
182 }
183 catch (MpacException.ServerError e)
184 {
185 assertThat(e.getStatus(), equalTo(404));
186 }
187 }
188
189 @Test(expected = MpacException.CannotUpdateNonServerSideEntity.class)
190 public void updateThrowsExceptionIfOriginalEntityIsNotFromServer() throws Exception
191 {
192 T original = makeEntityToCreate();
193 T updated = makeEntityWithUpdates(original);
194
195 updateEntity(original, updated);
196 }
197 }