forked from DSpace/dspace-angular
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathdspace-rest-response-parsing.service.spec.ts
More file actions
248 lines (196 loc) · 12.2 KB
/
Copy pathdspace-rest-response-parsing.service.spec.ts
File metadata and controls
248 lines (196 loc) · 12.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import { DspaceRestResponseParsingService } from './dspace-rest-response-parsing.service';
import { RestRequest } from './rest-request.model';
import { GetRequest, PostRequest } from './request.models';
import { RawRestResponse } from '../dspace-rest/raw-rest-response.model';
import { ObjectCacheService } from '../cache/object-cache.service';
/**
* Exposes the protected {@link DspaceRestResponseParsingService#ensureSelfLink} so it can be
* tested in isolation.
*/
class TestParsingService extends DspaceRestResponseParsingService {
public callEnsureSelfLink(request: RestRequest, response: RawRestResponse): RawRestResponse {
return this.ensureSelfLink(request, response);
}
}
describe('DspaceRestResponseParsingService', () => {
let service: TestParsingService;
let objectCache: ObjectCacheService;
const MISMATCH = jasmine.stringMatching(/These don't match/);
const REDUCED_PAGE = jasmine.stringMatching(/asked for a page of 9999 elements, but the REST API served 1000/);
const NO_SELF_LINK = jasmine.stringMatching(/doesn't have a self link/);
const requestFor = (href: string): RestRequest =>
new GetRequest('c4f0b1b7-3ffa-4b1a-9f5f-8bd6b1c4de71', href);
const responseWithSelfLink = (href: string, page?: any): RawRestResponse => ({
payload: {
_links: {
self: { href },
},
...(page ? { page } : {}),
},
statusCode: 200,
statusText: 'OK',
});
beforeEach(() => {
objectCache = jasmine.createSpyObj('objectCache', ['add', 'remove']);
service = new TestParsingService(objectCache);
spyOn(console, 'warn');
});
describe('ensureSelfLink', () => {
describe('differences the REST API is expected to introduce', () => {
it('should not warn when the self link matches the requested url', () => {
const href = 'https://rest.api/core/bundles/9d18168a/bitstreams?page=0&size=5';
const response = service.callEnsureSelfLink(requestFor(href), responseWithSelfLink(href));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href).toBe(href);
});
it('should not warn when the self link only echoes the embed params of the request', () => {
// https://github.com/dataquest-dev/dspace-customers/issues/862
const href = 'https://rest.api/core/bundles/9d18168a/bitstreams?page=0&embed=accessStatus&size=5';
const response = service.callEnsureSelfLink(requestFor(href), responseWithSelfLink(href));
expect(console.warn).not.toHaveBeenCalled();
// the self link is still normalized, because that's the url the response is cached under
expect(response.payload._links.self.href).toBe('https://rest.api/core/bundles/9d18168a/bitstreams?page=0&size=5');
});
it('should not warn when the self link echoes embed params and the request has no other params', () => {
const href = 'https://rest.api/core/items/eba1c085/bundles?embed=primaryBitstream&embed=bitstreams/format&embed.size=bitstreams=5';
const response = service.callEnsureSelfLink(requestFor(href), responseWithSelfLink(href));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles');
});
it('should not warn when the self link only percent decoded a param value', () => {
// https://github.com/dataquest-dev/dspace-customers/issues/862
const request = requestFor('https://rest.api/statistics/usagereports/search/object?page=-1&size=10&uri=https%3A%2F%2Frest.api%2Fcore%2Fsites%2F8f842a80');
const response = service.callEnsureSelfLink(request, responseWithSelfLink(
'https://rest.api/statistics/usagereports/search/object?page=-1&size=10&uri=https://rest.api/core/sites/8f842a80'));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href)
.toBe('https://rest.api/statistics/usagereports/search/object?page=-1&size=10&uri=https%3A%2F%2Frest.api%2Fcore%2Fsites%2F8f842a80');
});
it('should not warn or normalize when params are only in a different order', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&size=5');
const response = service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?size=5&page=0'));
expect(console.warn).not.toHaveBeenCalled();
// the urls hold the same params, so nothing is rewritten here
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles?size=5&page=0');
});
});
describe('differences that point at a problem with the endpoint', () => {
it('should say so when the REST API reduced the requested page size', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?size=9999');
service.callEnsureSelfLink(request, responseWithSelfLink(
'https://rest.api/core/items/eba1c085/bundles?size=1000',
{ number: 0, size: 1000, totalPages: 1, totalElements: 2 }));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(REDUCED_PAGE);
});
it('should report a reduced page size alongside other params without confusing the two', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&size=9999&sort=name,ASC');
service.callEnsureSelfLink(request, responseWithSelfLink(
'https://rest.api/core/items/eba1c085/bundles?page=0&size=1000&sort=name,ASC'));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(REDUCED_PAGE);
});
it('should fall back to the generic warning when more than the page size differs', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&size=9999');
service.callEnsureSelfLink(request, responseWithSelfLink(
'https://rest.api/core/items/eba1c085/bundles?page=3&size=1000'));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(MISMATCH);
});
it('should use the generic warning when the returned page size is larger than requested', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?size=5');
service.callEnsureSelfLink(request, responseWithSelfLink(
'https://rest.api/core/items/eba1c085/bundles?size=50',
{ number: 0, size: 50, totalPages: 1, totalElements: 2 }));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(MISMATCH);
});
it('should still warn when a param value differs beyond its encoding', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?uri=https%3A%2F%2Frest.api%2Fcore%2Fsites%2Faaa');
service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?uri=https://rest.api/core/sites/bbb'));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(MISMATCH);
});
it('should report the normalized request url and the raw self link in the warning', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&embed=primaryBitstream&size=5');
service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?page=3&embed=primaryBitstream&size=5'));
expect(console.warn).toHaveBeenCalledWith(
'The response for \'https://rest.api/core/items/eba1c085/bundles?page=0&size=5\' has the self link ' +
'\'https://rest.api/core/items/eba1c085/bundles?page=3&embed=primaryBitstream&size=5\'. ' +
'These don\'t match. This could mean there\'s an issue with the REST endpoint');
});
it('should warn when a non-embed param differs', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&embed=primaryBitstream&size=5');
service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?page=3&embed=primaryBitstream&size=5'));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(MISMATCH);
});
it('should warn when the self link has a param the request did not have', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?size=5');
service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?size=5&sort=name,ASC'));
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(MISMATCH);
});
it('should warn and fill in the requested url when the response has no self link', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?embed=primaryBitstream&size=5');
const response = service.callEnsureSelfLink(request, {
payload: { _links: {} },
statusCode: 200,
statusText: 'OK',
});
expect(console.warn).toHaveBeenCalledTimes(1);
expect(console.warn).toHaveBeenCalledWith(NO_SELF_LINK);
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles?size=5');
});
});
describe('normalization of the self link', () => {
it('should normalize the self link when it differs, so it matches the cache key', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&embed=primaryBitstream&size=5');
const response = service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?page=3&embed=primaryBitstream&size=5'));
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles?page=0&size=5');
});
it('should keep the other links when it normalizes the self link', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?page=0&size=5');
const response = service.callEnsureSelfLink(request, {
payload: {
_links: {
self: { href: 'https://rest.api/core/items/eba1c085/bundles?page=3&size=5' },
primaryBitstream: { href: 'https://rest.api/core/bitstreams/6a5f' },
},
},
statusCode: 200,
statusText: 'OK',
});
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles?page=0&size=5');
expect(response.payload._links.primaryBitstream.href).toBe('https://rest.api/core/bitstreams/6a5f');
});
it('should not touch a self link on a different host', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?size=5');
const response = service.callEnsureSelfLink(request,
responseWithSelfLink('https://other.api/core/items/eba1c085/bundles?size=5'));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href).toBe('https://other.api/core/items/eba1c085/bundles?size=5');
});
it('should not touch a self link that points at a different path', () => {
const request = requestFor('https://rest.api/core/items/eba1c085/bundles?size=5');
const response = service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085?size=5'));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085?size=5');
});
it('should leave non-GET requests alone', () => {
const request = new PostRequest('c4f0b1b7-3ffa-4b1a-9f5f-8bd6b1c4de71', 'https://rest.api/core/items/eba1c085/bundles?size=5');
const response = service.callEnsureSelfLink(request,
responseWithSelfLink('https://rest.api/core/items/eba1c085/bundles?size=1000'));
expect(console.warn).not.toHaveBeenCalled();
expect(response.payload._links.self.href).toBe('https://rest.api/core/items/eba1c085/bundles?size=1000');
});
});
});
});