// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.collide.clientlibs.navigation;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.json.shared.JsonStringMap.IterationCallback;
import com.google.collide.shared.util.JsonCollections;
import com.google.common.base.Equivalence;
import junit.framework.TestCase;
/**
*/
public class DefaultUrlSerializerTests extends TestCase {
/**
* A class which simplifies building/asserting a url.
*/
private class UrlBuilder {
private final StringBuilder url = new StringBuilder();
public UrlBuilder place(String placeName) {
url.append(UrlSerializer.PATH_SEPARATOR);
url.append(urlEncoder.encode(placeName));
return this;
}
public UrlBuilder value(String key, String value) {
if (value == null) {
return this;
}
String encodedKey = urlEncoder.encode(key);
String encodedValue = urlEncoder.encode(value);
url.append(UrlSerializer.PATH_SEPARATOR);
url.append(encodedKey).append(DefaultUrlSerializer.KEY_VALUE_SEPARATOR).append(encodedValue);
return this;
}
public UrlBuilder token(NavigationToken token) {
place(token.getPlaceName());
token.getBookmarkableState().iterate(new IterationCallback<String>() {
@Override
public void onIteration(String key, String value) {
value(key, value);
}
});
return this;
}
public UrlBuilder tokens(JsonArray<NavigationToken> navTokens) {
for (int i = 0; i < navTokens.size(); i++) {
token(navTokens.get(i));
}
return this;
}
public void assertMatch(String resultUrl) {
TestCase.assertEquals("Url did not match", url.toString(), resultUrl);
}
}
private static final String HOME_PLACE = "HOME";
private static final String LEAF_PLACE = "LEAF";
private static final String DETAIL_PLACE = "DETAIL";
private static final String EMPTY_PLACE = "EMPTY";
/** Identifies the home place, has no properties */
private static final NavigationToken HOME_TOKEN = new NavigationTokenImpl(HOME_PLACE);
/** Identifies a leaf place, has only a single property */
private static final NavigationToken LEAF_TOKEN = new NavigationTokenImpl(LEAF_PLACE);
/** Identifies a detail place, has three properties */
private static final NavigationToken DETAIL_TOKEN = new NavigationTokenImpl(DETAIL_PLACE);
/** Identifies the EMPTY place, has some weird properties null/empty string */
private static final NavigationToken EMPTY_TOKEN = new NavigationTokenImpl(EMPTY_PLACE);
private static final UrlComponentEncoder urlEncoder = new StubUrlEncoder();
private static final Equivalence<NavigationToken> NAVIGATION_EQUIVALENCE =
new Equivalence<NavigationToken>() {
@Override
protected boolean doEquivalent(NavigationToken a, NavigationToken b) {
return a.getPlaceName().equals(b.getPlaceName()) && JsonCollections.equals(
a.getBookmarkableState(), b.getBookmarkableState());
}
@Override
protected int doHash(NavigationToken t) {
return t.getPlaceName().hashCode() ^ t.getBookmarkableState().hashCode();
}
};
static {
LEAF_TOKEN.getBookmarkableState().put("one", "one");
DETAIL_TOKEN.getBookmarkableState().put("one", "one");
DETAIL_TOKEN.getBookmarkableState().put("two", "two");
DETAIL_TOKEN.getBookmarkableState().put("three", "three");
EMPTY_TOKEN.getBookmarkableState().put("one", null);
EMPTY_TOKEN.getBookmarkableState().put("two", "");
// This really tests the encoder more than anything...
EMPTY_TOKEN.getBookmarkableState().put("three", DefaultUrlSerializer.PATH_SEPARATOR);
EMPTY_TOKEN.getBookmarkableState()
.put("four", String.valueOf(DefaultUrlSerializer.KEY_VALUE_SEPARATOR));
}
private UrlSerializer serializer;
@Override
public void setUp() {
serializer = new DefaultUrlSerializer(urlEncoder);
}
public void testHome() {
assertTokens(JsonCollections.createArray(HOME_TOKEN));
assertTokens(JsonCollections.createArray(HOME_TOKEN, HOME_TOKEN, HOME_TOKEN));
}
public void testLeaf() {
assertTokens(JsonCollections.createArray(LEAF_TOKEN));
assertTokens(JsonCollections.createArray(HOME_TOKEN, LEAF_TOKEN, LEAF_TOKEN));
assertTokens(JsonCollections.createArray(HOME_TOKEN, LEAF_TOKEN, HOME_TOKEN));
}
public void testDetail() {
assertTokens(JsonCollections.createArray(DETAIL_TOKEN));
assertTokens(JsonCollections.createArray(HOME_TOKEN, LEAF_TOKEN, DETAIL_TOKEN));
assertTokens(JsonCollections.createArray(DETAIL_TOKEN, HOME_TOKEN, LEAF_TOKEN, DETAIL_TOKEN));
}
public void testWeird() {
NavigationToken modifiedEmptyToken = new NavigationTokenImpl(EMPTY_PLACE);
modifiedEmptyToken.getBookmarkableState().putAll(EMPTY_TOKEN.getBookmarkableState());
modifiedEmptyToken.getBookmarkableState().remove("one");
// We have to be explit here since we are ignoring null
JsonArray<NavigationToken> tokens = JsonCollections.createArray(EMPTY_TOKEN);
String url = serializer.serialize(tokens);
new UrlBuilder().token(modifiedEmptyToken).assertMatch(url);
assertEquals(JsonCollections.createArray(modifiedEmptyToken), serializer.deserialize(url));
tokens = JsonCollections.createArray(DETAIL_TOKEN, EMPTY_TOKEN, LEAF_TOKEN);
url = serializer.serialize(tokens);
new UrlBuilder().token(DETAIL_TOKEN)
.token(modifiedEmptyToken).token(LEAF_TOKEN).assertMatch(url);
assertEquals(JsonCollections.createArray(DETAIL_TOKEN, modifiedEmptyToken, LEAF_TOKEN),
serializer.deserialize(url));
}
private void assertTokens(JsonArray<NavigationToken> tokens) {
String url = serializer.serialize(tokens);
new UrlBuilder().tokens(tokens).assertMatch(url);
assertEquals(tokens, serializer.deserialize(url));
}
private void assertEquals(
JsonArray<NavigationToken> expected, JsonArray<NavigationToken> actual) {
boolean isEqual = JsonCollections.equals(expected, actual, NAVIGATION_EQUIVALENCE);
if (!isEqual) {
failNotEquals("Deserialized URL was not the same", expected, actual);
}
}
}