diff --git a/listenbrainz/webserver/static/js/src/stats/UserHistory.test.tsx b/listenbrainz/webserver/static/js/src/stats/UserHistory.test.tsx index e2831504eb..17fc52409c 100644 --- a/listenbrainz/webserver/static/js/src/stats/UserHistory.test.tsx +++ b/listenbrainz/webserver/static/js/src/stats/UserHistory.test.tsx @@ -142,6 +142,23 @@ describe("changePage", () => { expect(wrapper.state("data")).toEqual(userArtistsProcessDataOutput); expect(wrapper.state("currPage")).toBe(2); }); + + it("calls changeURL with correct parameters", async () => { + const wrapper = shallow(); + const instance = wrapper.instance(); + + const spy = jest.spyOn(instance.APIService, "getUserEntity"); + spy.mockImplementation((): any => { + return Promise.resolve(userArtistsResponse); + }); + instance.processData = jest.fn().mockImplementationOnce(() => { + return userArtistsProcessDataOutput; + }); + instance.changeURL = jest.fn(); + await instance.changePage(2); + + expect(instance.changeURL).toHaveBeenCalledWith(2, "all_time", "release"); + }); }); describe("changeRange", () => { @@ -202,6 +219,27 @@ describe("changeRange", () => { expect(wrapper.state("maxListens")).toBe(26); expect(wrapper.state("entityCount")).toBe(165); }); + + it("calls changeURL with correct parameters", async () => { + const wrapper = shallow(); + const instance = wrapper.instance(); + + instance.getData = jest.fn().mockImplementationOnce(() => { + return Promise.resolve(userReleasesResponse); + }); + const spy = jest.spyOn(instance.APIService, "getUserEntity"); + spy.mockImplementation((): any => { + return Promise.resolve(userReleasesResponse); + }); + instance.processData = jest.fn().mockImplementationOnce(() => { + return userReleasesProcessDataOutput; + }); + instance.changeURL = jest.fn(); + wrapper.setState({ entity: "release" }); + await instance.changeRange("all_time"); + + expect(instance.changeURL).toHaveBeenCalledWith(1, "all_time", "release"); + }); }); describe("changeEntity", () => { @@ -270,4 +308,47 @@ describe("changeEntity", () => { expect(wrapper.state("maxListens")).toBe(26); expect(wrapper.state("entityCount")).toBe(165); }); + + it("calls changeURL with correct parameters", async () => { + const wrapper = shallow(); + const instance = wrapper.instance(); + + instance.getData = jest.fn().mockImplementationOnce(() => { + return Promise.resolve(userReleasesResponse); + }); + const spy = jest.spyOn(instance.APIService, "getUserEntity"); + spy.mockImplementation((): any => { + return Promise.resolve(userReleasesResponse); + }); + instance.processData = jest.fn().mockImplementationOnce(() => { + return userReleasesProcessDataOutput; + }); + instance.changeURL = jest.fn(); + wrapper.setState({ range: "all_time" }); + await instance.changeEntity("release"); + + expect(instance.changeURL).toHaveBeenCalledWith(1, "all_time", "release"); + }); +}); + +describe("changeURL", () => { + it("changes the URL", () => { + const wrapper = shallow(); + const instance = wrapper.instance(); + + delete window.location; + window.location = { + origin: "https://foobar/", + pathname: "user/bazfoo/history", + } as Window["location"]; + const spy = jest.spyOn(window.history, "pushState"); + spy.mockImplementationOnce(() => {}); + + instance.changeURL(2, "all_time", "release"); + expect(spy).toHaveBeenCalledWith( + null, + "", + "https://foobar/user/bazfoo/history?page=2&range=all_time&entity=release" + ); + }); }); diff --git a/listenbrainz/webserver/static/js/src/stats/UserHistory.tsx b/listenbrainz/webserver/static/js/src/stats/UserHistory.tsx index a21db27495..d2e9a8b4b0 100644 --- a/listenbrainz/webserver/static/js/src/stats/UserHistory.tsx +++ b/listenbrainz/webserver/static/js/src/stats/UserHistory.tsx @@ -88,6 +88,7 @@ export default class UserHistory extends React.Component< try { const data = await this.getData(newPage, range, entity); + this.changeURL(newPage, range, entity); this.setState({ data: this.processData(data, newPage), currPage: newPage, @@ -132,6 +133,7 @@ export default class UserHistory extends React.Component< } data = await this.getData(page, newRange, entity); + this.changeURL(page, newRange, entity); await new Promise((resolve) => this.setState( { @@ -186,6 +188,7 @@ export default class UserHistory extends React.Component< } data = await this.getData(page, range, newEntity); + this.changeURL(page, range, newEntity); this.setState({ data: this.processData(data, page, newEntity), entity: newEntity, @@ -262,6 +265,18 @@ export default class UserHistory extends React.Component< }); }; + changeURL = ( + page: number, + range: UserEntityAPIRange, + entity: Entity + ): void => { + window.history.pushState( + null, + "", + `${window.location.origin}${window.location.pathname}?page=${page}&range=${range}&entity=${entity}` + ); + }; + render() { const { data,