diff --git a/resources/js/components/GroupsTable.test.js b/resources/js/components/GroupsTable.test.js index 8f8a29305..b21cc4bf3 100644 --- a/resources/js/components/GroupsTable.test.js +++ b/resources/js/components/GroupsTable.test.js @@ -204,8 +204,52 @@ describe('GroupsTable paging', () => { expect(wrapper.vm.show).toBe(before + wrapper.vm.pageSize) }) + + // "Your groups" fetches each group separately, so the scroller can run out + // of rows and give up before most of them have arrived. The groups that + // turn up afterwards must still be reachable by scrolling (#928). + test('keeps scrolling through groups that arrive after it ran out', async () => { + const store = new Vuex.Store({ + modules: { + groups: { + namespaced: true, + state: { list: {} }, + getters: { list: state => Object.values(state.list), get: state => id => state.list[id] }, + mutations: { add: (state, g) => Vue.set(state.list, g.id, g) }, + actions: { fetch: () => Promise.resolve(), hydrate: () => Promise.resolve() }, + }, + }, + }) + const wrapper = mount(GroupsTable, { + localVue, + store, + propsData: { groupids: many.map(g => g.id) }, + stubs: { GroupsTableFilters: true, GroupArchivedBadge: true, InfiniteLoading: true, 'b-img-lazy': true }, + }) + + // Only the first few have loaded when the scroller first checks. + many.slice(0, 5).forEach(g => store.commit('groups/add', g)) + await wrapper.vm.$nextTick() + let completed = false + wrapper.vm.loadMore({ loaded: () => {}, complete: () => { completed = true } }) + expect(completed).toBe(true) + + const before = wrapper.findComponent(InfiniteLoadingStub()).attributes('identifier') + many.forEach(g => store.commit('groups/add', g)) + await wrapper.vm.$nextTick() + await wrapper.vm.$nextTick() + + // The scroller is restarted, and the next scroll brings in more rows. + expect(wrapper.findComponent(InfiniteLoadingStub()).attributes('identifier')).not.toBe(before) + wrapper.vm.loadMore({ loaded: () => {}, complete: () => {} }) + expect(wrapper.vm.itemsToShow.length).toBe(50) + }) }) +function InfiniteLoadingStub() { + return { name: 'infinite-loading' } +} + describe('GroupsTable distance sort', () => { // Someone looking at a map wants the groups they can see, nearest first. // Alphabetical order tells them nothing about where anything is. diff --git a/resources/js/components/GroupsTable.vue b/resources/js/components/GroupsTable.vue index a5e80ca2e..7b8e1ea94 100644 --- a/resources/js/components/GroupsTable.vue +++ b/resources/js/components/GroupsTable.vue @@ -90,7 +90,7 @@ - + @@ -180,7 +180,8 @@ export default { searchName: null, searchTags: null, searchShow: false, - show: PAGE_SIZE + show: PAGE_SIZE, + infiniteId: 0 } }, computed: { @@ -281,6 +282,15 @@ export default { if (!same) { this.show = PAGE_SIZE + this.infiniteId++ + } + }, + 'items.length'(newVal, oldVal) { + // Groups can arrive after the scroller has decided there are no more - + // "Your groups" fetches each one separately - and once it has finished + // it never asks again. Restart it so the late arrivals can be scrolled to. + if (newVal > oldVal) { + this.infiniteId++ } }, activeFilters: {