@Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/post_id.json");
            BackdatingPostUpdate backdatingPostUpdate = new BackdatingPostUpdate("backdating post test.")
                                                            .backdatedTime(1362249213)
                                                            .backdatedTimeGranularity(BackdatedTimeGranularity.month);
            String actual = facebook.postBackdatingFeed("137246726435626", backdatingPostUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626/feed")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("backdated_time", "1362249213"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("backdated_time_granularity", "month"));

            assertThat(actual, is("137246726435626_185932178233747"));
        }
    }

    public static class postPagePhoto extends MockFacebookTestBase {
        @Test
        public void me() throws Exception {
            facebook.setMockJSON("mock_json/post_id.json");
            Media source = new Media(new File("src/test/resources/test_image.png"));
            PagePhotoUpdate pagePhotoUpdate = new PagePhotoUpdate(source).message("upload photo to the page test.");
            Set<String> countries = new HashSet<String>();
            countries.add("US");
            countries.add("GB");
            TargetingParameter targeting = new TargetingParameter().countries(countries);
            pagePhotoUpdate.setTargeting(targeting);
            FeedTargetingParameter feedTargeting = new FeedTargetingParameter().genders(FeedTargetingParameter.Gender.Male);
            feedTargeting.setAgeMin(20);
            feedTargeting.setAgeMax(40);
            pagePhotoUpdate.setFeedTargeting(feedTargeting);
            String actual = facebook.postPagePhoto(pagePhotoUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/me/photos")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("message", "upload photo to the page test."));
            assertThat(facebook.getHttpParameters(), hasTargetingParameterWithCountries("US", "GB"));
            assertThat(facebook.getHttpParameters(), hasPostJsonParameter("feed_targeting", "{\"age_min\":20,\"genders\":{\"value\":1},\"age_max\":40}"));

            assertThat(actual, is("137246726435626_185932178233747"));
        }

        @Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/post_id.json");
            Media source = new Media(new File("src/test/resources/test_image.png"));
            PagePhotoUpdate pagePhotoUpdate = new PagePhotoUpdate(source).message("upload photo to the page test.");
            Set<String> countries = new HashSet<String>();
            countries.add("US");
            countries.add("GB");
            TargetingParameter targeting = new TargetingParameter().countries(countries);
            pagePhotoUpdate.setTargeting(targeting);
            FeedTargetingParameter feedTargeting = new FeedTargetingParameter().genders(FeedTargetingParameter.Gender.Male);
            feedTargeting.setAgeMin(20);
            feedTargeting.setAgeMax(40);
            pagePhotoUpdate.setFeedTargeting(feedTargeting);
            String actual = facebook.postPagePhoto("137246726435626", pagePhotoUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626/photos")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("message", "upload photo to the page test."));
            assertThat(facebook.getHttpParameters(), hasTargetingParameterWithCountries("US", "GB"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("feed_targeting", "{\"age_min\":20,\"genders\":{\"value\":1},\"age_max\":40}"));

            assertThat(actual, is("137246726435626_185932178233747"));
        }

        protected Matcher<HttpParameter[]> hasTargetingParameterWithCountries(String... expectedCountryCodes) {
            final Set<String> expectedCountriesSet = new HashSet<String>(Arrays.asList(expectedCountryCodes));
            return new TypeSafeMatcher<HttpParameter[]>(HttpParameter[].class) {

                private final List<String> actualParams = new ArrayList<String>();

                @Override
                public boolean matchesSafely(HttpParameter[] actual) {
                    for (HttpParameter param : actual) {
                        if (param.getName().equals("targeting")) {
                            actualParams.add(param.getName() + "=" + param.getValue());
                            if (matches(param.getValue())) {
                                return true;
                            }
                        }
                    }
                    return false;
                }

                protected boolean matches(String targetingParamValue) {
                    try {
                        JSONObject targetingParamValueObject = new JSONObject(targetingParamValue);
                        JSONArray actualCountriesArray = targetingParamValueObject.getJSONArray("countries");
                        Set<String> actualCountriesSet = new HashSet<String>();
                        for (int i = 0; i < actualCountriesArray.length(); i++) {
                            String country = actualCountriesArray.getString(i);
                            actualCountriesSet.add(country);
                        }
                        return expectedCountriesSet.equals(actualCountriesSet);
                    } catch (JSONException ignore) {
                        return false;
                    }
                }

                public void describeTo(Description desc) {
                    desc.appendValue("targeting=" + expectedCountriesSet);
                    if (actualParams.size() > 0) {
                        desc.appendText(" but actual is ");
                        desc.appendValue(actualParams.get(0));
                        for (int i = 1; i < actualParams.size(); i++) {
                            desc.appendText(", ");
                            desc.appendValue(actualParams.get(i));
                        }
                    } else {
                        desc.appendText(" but actual has no '" + name + "' parameter");
                    }
                }
            };
        }
    }

    public static class updatePageSetting extends MockFacebookTestBase {
        @Test
        public void me() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            PageSettingUpdate pageSettingUpdate = new PageSettingUpdate("USERS_CAN_POST", false);
            boolean actual = facebook.updatePageSetting(pageSettingUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/me/settings")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("setting", "USERS_CAN_POST"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("value", "false"));

            assertThat(actual, is(true));
        }

        @Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            PageSettingUpdate pageSettingUpdate = new PageSettingUpdate("USERS_CAN_POST", false);
            boolean actual = facebook.updatePageSetting("137246726435626", pageSettingUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626/settings")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("setting", "USERS_CAN_POST"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("value", "false"));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void id_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            PageSettingUpdate pageSettingUpdate = new PageSettingUpdate("USERS_CAN_POST", false);
            boolean actual = facebook.updatePageSetting("137246726435626", pageSettingUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626/settings")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("setting", "USERS_CAN_POST"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("value", "false"));

            assertThat(actual, is(true));
        }
    }

    public static class updatePageCoverPhoto extends MockFacebookTestBase {
        @Test
        public void me() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            PageCoverUpdate pageCoverUpdate = new PageCoverUpdate("193816910778607").offsetY(20).noFeedStory(true);
            boolean actual = facebook.updatePageCoverPhoto(pageCoverUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/me")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("cover", "193816910778607"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("offset_y", "20"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("no_feed_story", "true"));

            assertThat(actual, is(true));
        }

        @Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            PageCoverUpdate pageCoverUpdate = new PageCoverUpdate("193816910778607").offsetY(20).noFeedStory(true);
            boolean actual = facebook.updatePageCoverPhoto("137246726435626", pageCoverUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("cover", "193816910778607"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("offset_y", "20"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("no_feed_story", "true"));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void id_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            PageCoverUpdate pageCoverUpdate = new PageCoverUpdate("193816910778607").offsetY(20).noFeedStory(true);
            boolean actual = facebook.updatePageCoverPhoto("137246726435626", pageCoverUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("cover", "193816910778607"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("offset_y", "20"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("no_feed_story", "true"));

            assertThat(actual, is(true));
        }
    }

    public static class displayPagePost extends MockFacebookTestBase {
        @Test
        public void hide() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            boolean actual = facebook.displayPagePost("137246726435626_210759175751047", true);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626_210759175751047")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_hidden", "true"));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void hide_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            boolean actual = facebook.displayPagePost("137246726435626_210759175751047", true);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626_210759175751047")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_hidden", "true"));

            assertThat(actual, is(true));
        }

        @Test
        public void show() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            boolean actual = facebook.displayPagePost("137246726435626_210759175751047", false);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626_210759175751047")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_hidden", "false"));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void show_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            boolean actual = facebook.displayPagePost("137246726435626_210759175751047", false);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626_210759175751047")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_hidden", "false"));

            assertThat(actual, is(true));
        }
    }

    public static class updateTab extends MockFacebookTestBase {
        @Test
        public void me() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            TabUpdate tabUpdate = new TabUpdate()
                                    .position(4)
                                    .nonConnectionLandingTab(true);
            boolean actual = facebook.updateTab("notes", tabUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/me/tabs/notes")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("position", "4"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_non_connection_landing_tab", "true"));

            assertThat(actual, is(true));
        }

        @Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            TabUpdate tabUpdate = new TabUpdate()
                                    .position(4)
                                    .nonConnectionLandingTab(true);
            boolean actual = facebook.updateTab("137246726435626", "notes", tabUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626/tabs/notes")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("position", "4"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_non_connection_landing_tab", "true"));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void id_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            TabUpdate tabUpdate = new TabUpdate()
                                    .position(4)
                                    .nonConnectionLandingTab(true);
            boolean actual = facebook.updateTab("137246726435626", "notes", tabUpdate);
            assertThat(facebook.getHttpMethod(), is(RequestMethod.POST));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626/tabs/notes")));
            assertThat(facebook.getHttpParameters(), hasPostParameter("position", "4"));
            assertThat(facebook.getHttpParameters(), hasPostParameter("is_non_connection_landing_tab", "true"));

            assertThat(actual, is(true));
        }
    }

    public static class deleteTab extends MockFacebookTestBase {
        @Test
        public void me() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            boolean actual = facebook.deleteTab("notes");
            assertThat(facebook.getHttpMethod(), is(RequestMethod.DELETE));
            assertThat(facebook.getEndpointURL(), is(pathOf("/me/tabs/notes")));

            assertThat(actual, is(true));
        }

        @Test
        public void id() throws Exception {
            facebook.setMockJSON("mock_json/true.json");
            boolean actual = facebook.deleteTab("137246726435626", "notes");
            assertThat(facebook.getHttpMethod(), is(RequestMethod.DELETE));
            assertThat(facebook.getEndpointURL(), is(pathOf("/137246726435626/tabs/notes")));

            assertThat(actual, is(true));
        }

        @Test
        @FacebookAPIVersion("v2.3")
        public void id_v23() throws Exception {
            facebook.setMockJSON("mock_json/success.json");
            boolean actual = facebook.deleteTab("137246726435626", "notes");
            assertThat(facebook.getHttpMethod(), is(RequestMethod.DELETE));
            assertThat(facebook.getEndpointURL(), is(pathOf("/v2.3/137246726435626/tabs/notes")));

            assertThat(actual, is(true));
        }