Skip to content

Commit de32416

Browse files
committed
Fix the state restore from url + localStorage
When using both the aggregator in the url would erase the selected & aggregator list stored in localStorage
1 parent 5e5a7c8 commit de32416

File tree

5 files changed

+129
-28
lines changed

5 files changed

+129
-28
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { render, screen } from '@testing-library/react'
2+
import '@testing-library/jest-dom'
3+
import AggregatorSetter from "../components/AggregatorSetter";
4+
import {initStore} from "./helpers";
5+
import {Provider} from "react-redux";
6+
import default_available_aggregators from "../aggregators-list";
7+
import {settingsSlice} from "../store/settingsSlice";
8+
9+
function renderAggregatorSetter(default_state = undefined) {
10+
const store = initStore(default_state);
11+
return [
12+
render(
13+
<Provider store={store}>
14+
<AggregatorSetter/>
15+
</Provider>
16+
),
17+
store
18+
];
19+
}
20+
21+
describe('AggregatorSetter', () => {
22+
it ('Load with data from the store', () => {
23+
const [_, store] = renderAggregatorSetter();
24+
const settingsState = store.getState().settings;
25+
26+
expect(screen.getByRole('option', { name: settingsState.selectedAggregator }).selected).toBe(true);
27+
expect(screen.getAllByRole('option').map(o => o.value)).toEqual(settingsState.availableAggregators);
28+
});
29+
30+
it ('Load custom aggregators', () => {
31+
const customAggregator = "http://aggregator.test";
32+
renderAggregatorSetter({
33+
settings: {
34+
...settingsSlice.getInitialState(),
35+
selectedAggregator: customAggregator,
36+
availableAggregators: [...default_available_aggregators, customAggregator],
37+
}
38+
});
39+
40+
expect(screen.getByRole('option', { name: customAggregator }).selected).toBe(true);
41+
expect(screen.getAllByRole('option').map(o => o.value)).toContain(customAggregator);
42+
});
43+
});
Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,53 @@
11
import {saveToLocalStorage, storeBuilder} from "../store/store";
22

3+
const baseLocation = 'http://localhost';
4+
35
function initStore(default_state = undefined) {
46
if (default_state) {
57
saveToLocalStorage(default_state);
68
}
79
return storeBuilder();
810
}
911

12+
/**
13+
* Reset the windows location api to `http://localhost`
14+
*/
15+
function resetLocation() {
16+
setLocation(new URL(baseLocation));
17+
}
18+
19+
/**
20+
* Set the window.location to the given url
21+
*
22+
* If you use it define a beforeEach with resetLocation else the new location will persist between tests.
23+
* @param url The new location
24+
*/
25+
function setLocation(url) {
26+
Object.defineProperty(window, 'location', {
27+
set(v) {
28+
this._href = v;
29+
},
30+
get() {
31+
return this._href;
32+
}
33+
})
34+
35+
window.location = url;
36+
}
37+
38+
/**
39+
* Set the window.location search/query aggregator param to the given aggregator
40+
*
41+
* If you use it define a beforeEach with resetLocation else the new location will persist between tests.
42+
* @param aggregatorUrl The target aggregator
43+
*/
44+
function setLocationToAggregator(aggregatorUrl) {
45+
setLocation(new URL(`?aggregator=${aggregatorUrl}`, baseLocation));
46+
}
47+
1048
module.exports = {
11-
initStore
49+
initStore,
50+
setLocation,
51+
setLocationToAggregator,
52+
resetLocation,
1253
}

mithril-explorer/__tests__/store.test.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
import {saveToLocalStorage, storeBuilder} from "../store/store";
22
import {
3-
removeCustomAggregator,
3+
removeSelectedAggregator,
44
selectAggregator,
55
settingsSlice,
66
setUpdateInterval,
77
toggleAutoUpdate
88
} from "../store/settingsSlice";
99
import default_available_aggregators from "../aggregators-list";
10-
import {initStore} from "./helpers";
10+
import {initStore, resetLocation, setLocationToAggregator} from "./helpers";
1111

1212
describe('Store Initialization', () => {
13+
beforeEach(() => {
14+
resetLocation();
15+
});
16+
1317
it('init with settings initialState without local storage', () => {
1418
const store = initStore();
1519

@@ -32,6 +36,25 @@ describe('Store Initialization', () => {
3236
expect(store.getState()).toEqual(expected);
3337
});
3438

39+
it('init with local storage and default aggregator in url', () => {
40+
const aggregatorInUrl = default_available_aggregators.at(1);
41+
setLocationToAggregator(aggregatorInUrl);
42+
let aggregators = [...default_available_aggregators, "https://aggregator.test"];
43+
let expected = {
44+
settings: {
45+
...settingsSlice.getInitialState(),
46+
selectedAggregator: aggregators.at(aggregators.length - 1),
47+
availableAggregators: aggregators,
48+
updateInterval: 12345,
49+
}
50+
};
51+
saveToLocalStorage(expected);
52+
expected.settings.selectedAggregator = aggregatorInUrl;
53+
const store = storeBuilder();
54+
55+
expect(store.getState()).toEqual(expected);
56+
});
57+
3558
it('Can toggle autoUpdate', () => {
3659
const store = initStore();
3760

@@ -70,7 +93,7 @@ describe('Store Initialization', () => {
7093
it('Can\'t remove a default aggregator', () => {
7194
const store = initStore();
7295

73-
store.dispatch(removeCustomAggregator(default_available_aggregators[0]));
96+
store.dispatch(removeSelectedAggregator());
7497
expect(store.getState().settings.availableAggregators).toContain(default_available_aggregators[0]);
7598
});
7699

@@ -84,7 +107,7 @@ describe('Store Initialization', () => {
84107
}
85108
});
86109

87-
store.dispatch(removeCustomAggregator(customAggregator));
110+
store.dispatch(removeSelectedAggregator());
88111
expect(store.getState().settings.availableAggregators).not.toContain(customAggregator);
89112
});
90113
});

mithril-explorer/store/settingsSlice.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ export const settingsSlice = createSlice({
3838
}
3939
},
4040
removeSelectedAggregator: (state) => {
41-
console.log("removing", state.selectedAggregator);
4241
if (default_available_aggregators.includes(state.selectedAggregator)) {
4342
return state;
4443
}

mithril-explorer/store/store.js

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,32 @@ function loadFromLocalStorage() {
2020
return undefined;
2121
}
2222

23-
function initStore() {
23+
export function initStore() {
2424
let state = loadFromLocalStorage();
2525

2626
if (location?.search) {
2727
const params = new URLSearchParams(location.search);
2828
const aggregator = params.get('aggregator');
2929

3030
if (aggregator && checkUrl(aggregator)) {
31-
const settings = {
32-
selectedAggregator: aggregator,
33-
availableAggregators:
34-
!default_available_aggregators.includes(aggregator)
35-
? [...default_available_aggregators, aggregator]
36-
: default_available_aggregators,
37-
canRemoveSelected: !default_available_aggregators.includes(aggregator),
38-
};
39-
40-
state = (state)
41-
? {
42-
...state,
43-
settings: {
44-
...state.settings,
45-
...settings
46-
}
47-
}
31+
const baseState = (state)
32+
? state
4833
: {
49-
settings: {
50-
...settingsInitialState,
51-
...settings,
52-
},
34+
settings: settingsInitialState
5335
};
36+
37+
state = {
38+
...baseState,
39+
settings: {
40+
...baseState.settings,
41+
selectedAggregator: aggregator,
42+
availableAggregators:
43+
!baseState.settings.availableAggregators.includes(aggregator)
44+
? [...baseState.settings.availableAggregators, aggregator]
45+
: baseState.settings.availableAggregators,
46+
canRemoveSelected: !default_available_aggregators.includes(aggregator),
47+
}
48+
};
5449
}
5550
}
5651

0 commit comments

Comments
 (0)