All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.gwt.test.internal.patchers.HistoryImplPatcher Maven / Gradle / Ivy

There is a newer version: 0.63
Show newest version
package com.googlecode.gwt.test.internal.patchers;

import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.googlecode.gwt.test.internal.AfterTestCallback;
import com.googlecode.gwt.test.internal.AfterTestCallbackManager;
import com.googlecode.gwt.test.patchers.PatchClass;
import com.googlecode.gwt.test.patchers.PatchMethod;
import com.googlecode.gwt.test.patchers.PatchMethod.ParamType;
import com.googlecode.gwt.test.utils.GwtReflectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@PatchClass(target = HistoryImplPatcher.HISTORY_IMPL)
class HistoryImplPatcher {

    static final String HISTORY_IMPL = "com.google.gwt.user.client.History$HistoryImpl";

    static class GwtBrowserHistory implements AfterTestCallback {

        private int currentIndex;
        private final List stack;

        GwtBrowserHistory() {
            this.stack = new ArrayList();
            this.currentIndex = -1;
            AfterTestCallbackManager.get().registerCallback(this);
        }

        /**
         * Add a new token in the history if it does not equal the current token
         *
         * @param token
         */
        public void addToken(String token) {
            String current = getCurrentToken();
            if (!current.equals(token)) {
                // remove possible token which could be reach with a forward so it
                // won't
                // be possible anymore
                while (stack.size() > currentIndex + 1) {
                    stack.remove(stack.size() - 1);
                }
                stack.add(token);
                currentIndex = stack.size() - 1;
            }
        }

        public void afterTest() throws Throwable {
            stack.clear();
            currentIndex = -1;

            Object historyImpl = GwtReflectionUtils.getStaticFieldValue(History.class, "historyEventSource");
            GwtReflectionUtils.callPrivateMethod(GwtReflectionUtils.getPrivateFieldValue(
                    GwtReflectionUtils.getPrivateFieldValue(
                            GwtReflectionUtils.getPrivateFieldValue(historyImpl, "handlers"),
                            "eventBus"), "map"), "clear");
            GwtReflectionUtils.setStaticField(History.class, "token", "");
        }

        /**
         * Simulate a Browser back button click
         *
         * @return the previous token or an empty String
         */
        public String back() {
            String token = null;
            boolean fireEvent = false;
            switch (currentIndex) {
                case 0:
                    currentIndex--;
                    fireEvent = true;
                case -1:
                    token = "";
                    break;
                default:
                    fireEvent = true;
                    token = stack.get(--currentIndex);
            }

            if (fireEvent) {
                fireHistoryChanged(token);
            }

            return token;
        }

        /**
         * Simulate a Browser forward button click
         *
         * @return the next token or an empty String
         */
        public String forward() {
            if (currentIndex >= stack.size() - 1) {
                return "";
            } else {
                String token = stack.get(++currentIndex);
                fireHistoryChanged(token);
                return token;
            }
        }

        /**
         * Return the current token in history
         *
         * @return the current token in history or an empty String if no token is set in the URL
         */
        public String getCurrentToken() {
            return (currentIndex == -1) ? "" : stack.get(currentIndex);
        }

        private void fireHistoryChanged(String token) {
            Object impl = GwtReflectionUtils.getStaticFieldValue(History.class, "historyEventSource");
            try {
                Method method = GwtReflectionUtils.findMethod(impl.getClass(), "fireValueChangedEvent", String.class);
                method.invoke(impl, token);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

    }

    static GwtBrowserHistory BROWSER_HISTORY = new GwtBrowserHistory();

    @PatchMethod
    static String encodeHistoryToken(@ParamType(HISTORY_IMPL) Object impl, String fragment) {
        return URL.encodeQueryString(fragment).replace("#", "%23");
    }

    @PatchMethod
    static void newToken(@ParamType(HISTORY_IMPL) Object impl, String token) {
        if (token == null) {
            token = "";
        }
        BROWSER_HISTORY.addToken(token);
    }

    @PatchMethod
    static String getToken() {
        return BROWSER_HISTORY.getCurrentToken();
    }

    @PatchMethod
    static boolean init(@ParamType(HISTORY_IMPL) Object historyImpl) {
        String hash = Window.Location.getHash();
        int index = hash.indexOf("#");
        if (index > -1) {
            String token = hash.substring(index + 1);
            GwtReflectionUtils.callPrivateMethod(historyImpl, "setToken", token);
            nativeUpdate(historyImpl, token);
        }
        return true;
    }

    @PatchMethod
    static void nativeUpdate(@ParamType(HISTORY_IMPL) Object historyImpl, String historyToken) {
        if (historyToken == null) {
            historyToken = "";
        }

        BROWSER_HISTORY.addToken(historyToken);
    }


    @PatchMethod
    static void attachListener(@ParamType(HISTORY_IMPL) Object historyImpl) {
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy