mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
Merge pull request #1096 from prymitive/back-button
fix(ui): correctly handle browser back/forward buttons
This commit is contained in:
@@ -21,6 +21,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
localStorage.setItem("savedFilters", "");
|
||||
jest.restoreAllMocks();
|
||||
window.history.pushState({}, "App", "/");
|
||||
});
|
||||
@@ -119,4 +120,38 @@ describe("<App />", () => {
|
||||
NewUnappliedFilter("use=query")
|
||||
);
|
||||
});
|
||||
|
||||
it("popstate event updates alertStore filters", () => {
|
||||
const tree = shallow(
|
||||
<App defaultFilters={["foo"]} uiDefaults={uiDefaults} />
|
||||
);
|
||||
expect(tree.instance().alertStore.filters.values).toHaveLength(1);
|
||||
expect(tree.instance().alertStore.filters.values[0]).toMatchObject(
|
||||
NewUnappliedFilter("foo")
|
||||
);
|
||||
|
||||
delete global.window.location;
|
||||
global.window.location = {
|
||||
href: "http://localhost/?q=bar",
|
||||
search: "?q=bar"
|
||||
};
|
||||
|
||||
let event = new PopStateEvent("popstate");
|
||||
window.onpopstate(event);
|
||||
|
||||
expect(tree.instance().alertStore.filters.values).toHaveLength(1);
|
||||
expect(tree.instance().alertStore.filters.values[0]).toMatchObject(
|
||||
NewUnappliedFilter("bar")
|
||||
);
|
||||
});
|
||||
|
||||
it("unmounts without crashing", () => {
|
||||
const tree = shallow(
|
||||
<App defaultFilters={["foo=bar"]} uiDefaults={uiDefaults} />
|
||||
);
|
||||
tree.instance().componentWillUnmount();
|
||||
|
||||
let event = new PopStateEvent("popstate");
|
||||
window.onpopstate(event);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -62,6 +62,20 @@ class App extends Component<AppProps, {}> {
|
||||
this.alertStore = new AlertStore(filters);
|
||||
}
|
||||
|
||||
onPopState = (event: PopStateEvent) => {
|
||||
event.preventDefault();
|
||||
const p = DecodeLocationSearch(window.location.search);
|
||||
this.alertStore.filters.setWithoutLocation(p.params.q);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
window.onpopstate = this.onPopState;
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.onpopstate = () => {};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { observable, action } from "mobx";
|
||||
import { observable, action, toJS } from "mobx";
|
||||
|
||||
import { throttle } from "lodash";
|
||||
|
||||
@@ -128,6 +128,15 @@ class AlertStore {
|
||||
setFilters(raws) {
|
||||
this.values = raws.map(raw => NewUnappliedFilter(raw));
|
||||
UpdateLocationSearch({ q: this.values.map(f => f.raw) });
|
||||
},
|
||||
setWithoutLocation(raws) {
|
||||
const filtersByRaw = this.values.reduce(function(map, obj) {
|
||||
map[toJS(obj.raw)] = toJS(obj);
|
||||
return map;
|
||||
}, {});
|
||||
this.values = raws.map(raw =>
|
||||
filtersByRaw[raw] ? filtersByRaw[raw] : NewUnappliedFilter(raw)
|
||||
);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -132,6 +132,81 @@ describe("AlertStore.filters", () => {
|
||||
expect(store.filters.values).toHaveLength(1);
|
||||
expect(store.filters.values[0]).toMatchObject(NewUnappliedFilter("bar"));
|
||||
});
|
||||
|
||||
it("addFilter() updates window.history", () => {
|
||||
const store = new AlertStore([]);
|
||||
const historyMock = jest.spyOn(global.window.history, "pushState");
|
||||
store.filters.addFilter("foo");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"http://localhost/?q=foo"
|
||||
);
|
||||
});
|
||||
|
||||
it("replaceFilter() updates window.history", () => {
|
||||
const store = new AlertStore(["foo"]);
|
||||
const historyMock = jest.spyOn(global.window.history, "pushState");
|
||||
store.filters.replaceFilter("foo", "bar");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"http://localhost/?q=bar"
|
||||
);
|
||||
});
|
||||
|
||||
it("addFilter() updates window.history", () => {
|
||||
const store = new AlertStore([]);
|
||||
const historyMock = jest.spyOn(global.window.history, "pushState");
|
||||
store.filters.addFilter("foo");
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"http://localhost/?q=foo"
|
||||
);
|
||||
});
|
||||
|
||||
it("setFilters() updates window.history", () => {
|
||||
const store = new AlertStore([]);
|
||||
store.filters.addFilter("foo");
|
||||
store.filters.addFilter("bar");
|
||||
|
||||
const historyMock = jest.spyOn(global.window.history, "pushState");
|
||||
store.filters.setFilters(["baz", "far"]);
|
||||
expect(store.filters.values).toHaveLength(2);
|
||||
expect(store.filters.values[0]).toMatchObject(NewUnappliedFilter("baz"));
|
||||
expect(store.filters.values[1]).toMatchObject(NewUnappliedFilter("far"));
|
||||
expect(historyMock).toHaveBeenLastCalledWith(
|
||||
null,
|
||||
null,
|
||||
"http://localhost/?q=baz&q=far"
|
||||
);
|
||||
});
|
||||
|
||||
it("setWithoutLocation() doesn't update window.history", () => {
|
||||
const store = new AlertStore(["far", "foo"]);
|
||||
|
||||
const historyMock = jest.spyOn(global.window.history, "pushState");
|
||||
store.filters.setWithoutLocation(["baz", "far"]);
|
||||
expect(store.filters.values).toHaveLength(2);
|
||||
expect(store.filters.values[0]).toMatchObject(NewUnappliedFilter("baz"));
|
||||
expect(store.filters.values[1]).toMatchObject(NewUnappliedFilter("far"));
|
||||
expect(historyMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("setWithoutLocation() adds missing filters", () => {
|
||||
const store = new AlertStore([]);
|
||||
store.filters.setWithoutLocation(["foo", "bar"]);
|
||||
expect(store.filters.values).toHaveLength(2);
|
||||
expect(store.filters.values[0]).toMatchObject(NewUnappliedFilter("foo"));
|
||||
expect(store.filters.values[1]).toMatchObject(NewUnappliedFilter("bar"));
|
||||
});
|
||||
|
||||
it("setWithoutLocation() removes orphaned filters", () => {
|
||||
const store = new AlertStore(["far"]);
|
||||
store.filters.setWithoutLocation([]);
|
||||
expect(store.filters.values).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("FormatBackendURI", () => {
|
||||
|
||||
Reference in New Issue
Block a user