Implemented FacebookErrorHandler to handle facebook-error-codes
[facebook-utils] / src / test / java / de / juplo / facebook / GraphApiErrorHandlerTest.java
1 package de.juplo.facebook;
2
3 import java.util.Date;
4 import java.util.Map;
5 import java.util.Set;
6 import javax.annotation.Resource;
7 import static org.junit.Assert.*;
8 import org.junit.Before;
9 import org.junit.Test;
10 import org.junit.runner.RunWith;
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13 import org.springframework.http.HttpStatus;
14 import org.springframework.http.converter.HttpMessageNotReadableException;
15 import org.springframework.security.access.AccessDeniedException;
16 import org.springframework.security.oauth2.client.OAuth2RestTemplate;
17 import org.springframework.security.oauth2.client.http.OAuth2ErrorHandler;
18 import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
19 import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
20 import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
21 import org.springframework.security.oauth2.client.token.AccessTokenProvider;
22 import org.springframework.security.oauth2.client.token.AccessTokenRequest;
23 import org.springframework.security.oauth2.common.OAuth2AccessToken;
24 import static org.springframework.security.oauth2.common.OAuth2AccessToken.OAUTH2_TYPE;
25 import org.springframework.security.oauth2.common.OAuth2RefreshToken;
26 import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
27 import org.springframework.test.context.ContextConfiguration;
28 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
29
30
31
32 /**
33  *
34  * @author kai
35  */
36 @RunWith(SpringJUnit4ClassRunner.class)
37 @ContextConfiguration(
38   locations = {
39     "classpath:/spring/test-facebook-error-handler.xml"
40     })
41 public class GraphApiErrorHandlerTest
42 {
43   private static final Logger log =
44       LoggerFactory.getLogger(GraphApiErrorHandlerTest.class);
45
46   @Resource
47   private OAuth2RestTemplate clientTemplate;
48
49   private MockClientHttpRequestFactory requestFactory;
50
51
52   @Test
53   public void testError1()
54   {
55     log.info("testError1");
56
57
58     requestFactory.setBody(
59         "{\n" +
60         "  \"error\":\n" +
61         "  {\n" +
62         "    \"message\": \"An unknown error has occurred.\",\n" +
63         "    \"type\": \"OAuthException\",\n" +
64         "    \"code\": 1\n" +
65         "  }\n" +
66         "}");
67
68     try
69     {
70       clientTemplate.getForObject("ANY", SOME.class);
71       fail("The expected exception was not thrown");
72     }
73     catch(UnknownErrorException e)
74     {
75       log.debug("{}", e.toString());
76       assertEquals("invalid_request", e.getOAuth2ErrorCode());
77       assertEquals(1, e.getCode());
78       assertEquals("An unknown error has occurred.", e.getMessage());
79       assertEquals("OAuthException", e.getType());
80     }
81   }
82
83   @Test
84   public void testError2()
85   {
86     log.info("testError2");
87
88
89     requestFactory.setBody(
90         "{\n" +
91         "  \"error\":\n" +
92         "  {\n" +
93         "    \"message\": \"An unexpected error has occurred. Please retry your request later.\",\n" +
94         "    \"type\": \"OAuthException\",\n" +
95         "    \"code\": 2\n" +
96         "  }\n" +
97         "}");
98
99     try
100     {
101       clientTemplate.getForObject("ANY", SOME.class);
102       fail("The expected exception was not thrown");
103     }
104     catch(UnexpectedErrorException e)
105     {
106       log.debug("{}", e.toString());
107       assertEquals("invalid_request", e.getOAuth2ErrorCode());
108       assertEquals(2, e.getCode());
109       assertEquals("An unexpected error has occurred. Please retry your request later.", e.getMessage());
110       assertEquals("OAuthException", e.getType());
111     }
112   }
113
114   @Test
115   public void testError21()
116   {
117     log.info("testError21");
118
119
120     requestFactory.setBody(
121         "{\n" +
122         "  \"error\":\n" +
123         "  {\n" +
124         "    \"message\": \"(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603.  Please update your API calls to the new ID\",\n" +
125         "    \"type\": \"OAuthException\",\n" +
126         "    \"code\": 21\n" +
127         "  }\n" +
128         "}");
129
130     try
131     {
132       clientTemplate.getForObject("ANY", SOME.class);
133       fail("The expected exception was not thrown");
134     }
135     catch(PageMigratedException e)
136     {
137       log.debug("{}", e.toString());
138       assertEquals("invalid_request", e.getOAuth2ErrorCode());
139       assertEquals(21, e.getCode());
140       assertEquals("(#21) Page ID 590408587650316 was migrated to page ID 1421620791415603.  Please update your API calls to the new ID", e.getMessage());
141       assertEquals("OAuthException", e.getType());
142     }
143   }
144
145   @Test
146   public void testError100()
147   {
148     log.info("testError100");
149
150
151     requestFactory.setBody(
152         "{\n" +
153         "  \"error\":\n" +
154         "  {\n" +
155         "    \"message\": \"Unsupported get request.\",\n" +
156         "    \"type\": \"GraphMethodException\",\n" +
157         "    \"code\": 100\n" +
158         "  }\n" +
159         "}");
160
161     try
162     {
163       clientTemplate.getForObject("ANY", SOME.class);
164       fail("The expected exception was not thrown");
165     }
166     catch(UnsupportedGetRequestException e)
167     {
168       log.debug("{}", e.toString());
169       assertEquals("invalid_request", e.getOAuth2ErrorCode());
170       assertEquals(100, e.getCode());
171       assertEquals("Unsupported get request.", e.getMessage());
172       assertEquals("GraphMethodException", e.getType());
173     }
174   }
175
176   @Test
177   public void testUnmappedError()
178   {
179     log.info("testUnmappedError");
180
181
182     requestFactory.setBody(
183         "{\n" +
184         "  \"error\":\n" +
185         "  {\n" +
186         "    \"message\": \"This error does not exist.\",\n" +
187         "    \"type\": \"NonexistentException\",\n" +
188         "    \"code\": 999999999\n" +
189         "  }\n" +
190         "}");
191
192     try
193     {
194       clientTemplate.getForObject("ANY", SOME.class);
195       fail("The expected exception was not thrown");
196     }
197     catch(GraphApiException e)
198     {
199       log.debug("{}", e.toString());
200       assertEquals("invalid_request", e.getOAuth2ErrorCode());
201       assertEquals(999999999, e.getCode());
202       assertEquals("This error does not exist.", e.getMessage());
203       assertEquals("NonexistentException", e.getType());
204     }
205   }
206
207   @Test
208   public void testInvlalidErrors()
209   {
210     log.info("testInvalidErrors");
211
212
213     requestFactory.setBody(
214         "{\n" +
215         "  \"error\":\n" +
216         "  {\n" +
217         "    \"message\": null,\n" +
218         "    \"type\": \"Whatever\",\n" +
219         "    \"code\": 999999999\n" +
220         "  }\n" +
221         "}");
222
223     try
224     {
225       clientTemplate.getForObject("ANY", SOME.class);
226       fail("The expected exception was not thrown");
227     }
228     catch(OAuth2Exception e)
229     {
230       log.debug("{}", e.toString());
231       assertEquals("invalid_request", e.getOAuth2ErrorCode());
232       assertFalse(e instanceof GraphApiException);
233     }
234
235
236     requestFactory.setBody(
237         "{\n" +
238         "  \"error\":\n" +
239         "  {\n" +
240         "    \"type\": \"Whatever\",\n" +
241         "    \"code\": 999999999\n" +
242         "  }\n" +
243         "}");
244
245     try
246     {
247       clientTemplate.getForObject("ANY", SOME.class);
248       fail("The expected exception was not thrown");
249     }
250     catch(OAuth2Exception e)
251     {
252       log.debug("{}", e.toString());
253       assertEquals("invalid_request", e.getOAuth2ErrorCode());
254       assertFalse(e instanceof GraphApiException);
255     }
256
257
258     requestFactory.setBody(
259         "{\n" +
260         "  \"error\":\n" +
261         "  {\n" +
262         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
263         "    \"type\": null,\n" +
264         "    \"code\": 999999999\n" +
265         "  }\n" +
266         "}");
267
268     try
269     {
270       clientTemplate.getForObject("ANY", SOME.class);
271       fail("The expected exception was not thrown");
272     }
273     catch(OAuth2Exception e)
274     {
275       log.debug("{}", e.toString());
276       assertEquals("invalid_request", e.getOAuth2ErrorCode());
277       assertFalse(e instanceof GraphApiException);
278     }
279
280
281     requestFactory.setBody(
282         "{\n" +
283         "  \"error\":\n" +
284         "  {\n" +
285         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
286         "    \"code\": 999999999\n" +
287         "  }\n" +
288         "}");
289
290     try
291     {
292       clientTemplate.getForObject("ANY", SOME.class);
293       fail("The expected exception was not thrown");
294     }
295     catch(OAuth2Exception e)
296     {
297       log.debug("{}", e.toString());
298       assertEquals("invalid_request", e.getOAuth2ErrorCode());
299       assertFalse(e instanceof GraphApiException);
300     }
301
302
303     requestFactory.setBody(
304         "{\n" +
305         "  \"error\":\n" +
306         "  {\n" +
307         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
308         "    \"type\": \"Whatever\",\n" +
309         "    \"code\": \"some string\"\n" +
310         "  }\n" +
311         "}");
312
313     try
314     {
315       clientTemplate.getForObject("ANY", SOME.class);
316       fail("The expected exception was not thrown");
317     }
318     catch(OAuth2Exception e)
319     {
320       log.debug("{}", e.toString());
321       assertEquals("invalid_request", e.getOAuth2ErrorCode());
322       assertFalse(e instanceof GraphApiException);
323     }
324
325
326     requestFactory.setBody(
327         "{\n" +
328         "  \"error\":\n" +
329         "  {\n" +
330         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
331         "    \"type\": \"Whatever\",\n" +
332         "    \"code\": 9.9\n" +
333         "  }\n" +
334         "}");
335
336     try
337     {
338       clientTemplate.getForObject("ANY", SOME.class);
339       fail("The expected exception was not thrown");
340     }
341     catch(OAuth2Exception e)
342     {
343       log.debug("{}", e.toString());
344       assertEquals("invalid_request", e.getOAuth2ErrorCode());
345       assertFalse(e instanceof GraphApiException);
346     }
347
348
349     requestFactory.setBody(
350         "{\n" +
351         "  \"error\":\n" +
352         "  {\n" +
353         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
354         "    \"type\": \"Whatever\",\n" +
355         "    \"code\": null\n" +
356         "  }\n" +
357         "}");
358
359     try
360     {
361       clientTemplate.getForObject("ANY", SOME.class);
362       fail("The expected exception was not thrown");
363     }
364     catch(OAuth2Exception e)
365     {
366       log.debug("{}", e.toString());
367       assertEquals("invalid_request", e.getOAuth2ErrorCode());
368       assertFalse(e instanceof GraphApiException);
369     }
370
371
372     requestFactory.setBody(
373         "{\n" +
374         "  \"error\":\n" +
375         "  {\n" +
376         "    \"message\": \"Not a Graph-Api-Exception.\",\n" +
377         "    \"type\": \"Whatever\"\n" +
378         "  }\n" +
379         "}");
380
381     try
382     {
383       clientTemplate.getForObject("ANY", SOME.class);
384       fail("The expected exception was not thrown");
385     }
386     catch(OAuth2Exception e)
387     {
388       log.debug("{}", e.toString());
389       assertEquals("invalid_request", e.getOAuth2ErrorCode());
390       assertFalse(e instanceof GraphApiException);
391     }
392
393
394     requestFactory.setBody("{\"error\":{\"message\":null}}");
395
396     try
397     {
398       clientTemplate.getForObject("ANY", SOME.class);
399       fail("The expected exception was not thrown");
400     }
401     catch(OAuth2Exception e)
402     {
403       log.debug("{}", e.toString());
404       assertEquals("invalid_request", e.getOAuth2ErrorCode());
405       assertFalse(e instanceof GraphApiException);
406     }
407
408
409     requestFactory.setBody("{\"error\":{\"type\":null}}");
410
411     try
412     {
413       clientTemplate.getForObject("ANY", SOME.class);
414       fail("The expected exception was not thrown");
415     }
416     catch(OAuth2Exception e)
417     {
418       log.debug("{}", e.toString());
419       assertEquals("invalid_request", e.getOAuth2ErrorCode());
420       assertFalse(e instanceof GraphApiException);
421     }
422
423
424     requestFactory.setBody("{\"error\":{\"code\":null}}");
425
426     try
427     {
428       clientTemplate.getForObject("ANY", SOME.class);
429       fail("The expected exception was not thrown");
430     }
431     catch(OAuth2Exception e)
432     {
433       log.debug("{}", e.toString());
434       assertEquals("invalid_request", e.getOAuth2ErrorCode());
435       assertFalse(e instanceof GraphApiException);
436     }
437
438
439     requestFactory.setBody("{\"error\":{}}");
440
441     try
442     {
443       clientTemplate.getForObject("ANY", SOME.class);
444       fail("The expected exception was not thrown");
445     }
446     catch(OAuth2Exception e)
447     {
448       log.debug("{}", e.toString());
449       assertEquals("invalid_request", e.getOAuth2ErrorCode());
450       assertFalse(e instanceof GraphApiException);
451     }
452
453
454     requestFactory.setBody("{\"error\":\"some message\"}");
455
456     try
457     {
458       clientTemplate.getForObject("ANY", SOME.class);
459       fail("The expected exception was not thrown");
460     }
461     catch(OAuth2Exception e)
462     {
463       log.debug("{}", e.toString());
464       assertEquals("invalid_request", e.getOAuth2ErrorCode());
465       assertFalse(e instanceof GraphApiException);
466     }
467
468
469     requestFactory.setBody("{\"error\":null}");
470
471     try
472     {
473       clientTemplate.getForObject("ANY", SOME.class);
474       fail("The expected exception was not thrown");
475     }
476     catch(OAuth2Exception e)
477     {
478       log.debug("{}", e.toString());
479       assertEquals("invalid_request", e.getOAuth2ErrorCode());
480       assertFalse(e instanceof GraphApiException);
481     }
482
483
484     requestFactory.setBody("{\"some filed\":\"some message\"}");
485
486     try
487     {
488       clientTemplate.getForObject("ANY", SOME.class);
489       fail("The expected exception was not thrown");
490     }
491     catch(OAuth2Exception e)
492     {
493       log.debug("{}", e.toString());
494       assertEquals("invalid_request", e.getOAuth2ErrorCode());
495       assertFalse(e instanceof GraphApiException);
496     }
497
498
499     requestFactory.setBody("{}");
500
501     try
502     {
503       clientTemplate.getForObject("ANY", SOME.class);
504       fail("The expected exception was not thrown");
505     }
506     catch(OAuth2Exception e)
507     {
508       log.debug("{}", e.toString());
509       assertEquals("invalid_request", e.getOAuth2ErrorCode());
510       assertFalse(e instanceof GraphApiException);
511     }
512
513
514     requestFactory.setBody("");
515
516     try
517     {
518       clientTemplate.getForObject("ANY", SOME.class);
519       fail("The expected exception was not thrown");
520     }
521     catch(HttpMessageNotReadableException e)
522     {
523       // TODO: OAuth2ErrorHandler fails, if body contains no valid JSON!
524       log.debug("{}", e.toString());
525     }
526   }
527
528
529   @Before
530   public void setUp()
531   {
532     requestFactory = new MockClientHttpRequestFactory();
533     requestFactory.setStatus(HttpStatus.BAD_REQUEST);
534     requestFactory.addHeader("Content-Type", "application/json");
535     clientTemplate.setRequestFactory(requestFactory);
536
537     clientTemplate.setErrorHandler(
538         new GraphApiErrorHandler(
539             (OAuth2ErrorHandler)clientTemplate.getErrorHandler()
540             )
541         );
542
543     clientTemplate.setAccessTokenProvider(new AccessTokenProvider()
544     {
545       @Override
546       public OAuth2AccessToken obtainAccessToken(
547           OAuth2ProtectedResourceDetails details,
548           AccessTokenRequest parameters
549           )
550           throws
551             UserRedirectRequiredException,
552             UserApprovalRequiredException,
553             AccessDeniedException
554       {
555         return new OAuth2AccessToken() {
556
557           @Override
558           public Map<String, Object> getAdditionalInformation()
559           {
560             throw new UnsupportedOperationException("Not supported yet.");
561           }
562
563           @Override
564           public Set<String> getScope()
565           {
566             throw new UnsupportedOperationException("Not supported yet.");
567           }
568
569           @Override
570           public OAuth2RefreshToken getRefreshToken()
571           {
572             throw new UnsupportedOperationException("Not supported yet.");
573           }
574
575           @Override
576           public String getTokenType()
577           {
578             return OAUTH2_TYPE;
579           }
580
581           @Override
582           public boolean isExpired()
583           {
584             return false;
585           }
586
587           @Override
588           public Date getExpiration()
589           {
590             throw new UnsupportedOperationException("Not supported yet.");
591           }
592
593           @Override
594           public int getExpiresIn()
595           {
596             throw new UnsupportedOperationException("Not supported yet.");
597           }
598
599           @Override
600           public String getValue()
601           {
602             return "ANY";
603           }
604         };
605       }
606
607       @Override
608       public boolean supportsResource(OAuth2ProtectedResourceDetails resource)
609       {
610         return true;
611       }
612
613       @Override
614       public OAuth2AccessToken refreshAccessToken(
615           OAuth2ProtectedResourceDetails resource,
616           OAuth2RefreshToken refreshToken,
617           AccessTokenRequest request
618           )
619           throws
620             UserRedirectRequiredException
621       {
622         throw new UnsupportedOperationException("Not supported yet.");
623       }
624
625       @Override
626       public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource)
627       {
628         return false;
629       }
630     });
631   }
632
633
634   static class SOME
635   {
636   }
637 }