diff --git a/app/assets/javascripts/lib/utils/axios_startup_calls.js b/app/assets/javascripts/lib/utils/axios_startup_calls.js index cb2e8a76c08c84a86db6be96baa5c17579ad9841..a047cebc8abf1c7975c2c0369496e88bffe0db61 100644 --- a/app/assets/javascripts/lib/utils/axios_startup_calls.js +++ b/app/assets/javascripts/lib/utils/axios_startup_calls.js @@ -34,14 +34,17 @@ const setupAxiosStartupCalls = axios => { }); // eslint-disable-next-line promise/no-nesting - return res.json().then(data => ({ - data, - status: res.status, - statusText: res.statusText, - headers: fetchHeaders, - config: req, - request: req, - })); + return res + .clone() + .json() + .then(data => ({ + data, + status: res.status, + statusText: res.statusText, + headers: fetchHeaders, + config: req, + request: req, + })); }); } diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue index 721cc6787dcc83b22dc5ae765715c3c176d962c9..702df42d655c7c91d05483c0cf5f813888575e4e 100644 --- a/app/assets/javascripts/repository/components/tree_content.vue +++ b/app/assets/javascripts/repository/components/tree_content.vue @@ -1,4 +1,5 @@ @@ -124,6 +143,19 @@ export default { :is-loading="isLoadingFiles" :loading-path="loadingPath" /> +
+ + {{ s__('ProjectFileTree|Show more') }} + +
diff --git a/changelogs/unreleased/222685-improve-rendering-in-file-browser.yml b/changelogs/unreleased/222685-improve-rendering-in-file-browser.yml new file mode 100644 index 0000000000000000000000000000000000000000..c806c42c1cec83b6b1ae81973c31736b9b38ba27 --- /dev/null +++ b/changelogs/unreleased/222685-improve-rendering-in-file-browser.yml @@ -0,0 +1,5 @@ +--- +title: Improve rendering of very large files in the Repo File Browser +merge_request: 38733 +author: +type: fixed diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 4114d77773f861cda0f45448a9cd2e396774b102..d23f22206c648e7b81a8d154c841d88c4d4ddda8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -18730,6 +18730,9 @@ msgstr "" msgid "ProjectFileTree|Name" msgstr "" +msgid "ProjectFileTree|Show more" +msgstr "" + msgid "ProjectLastActivity|Never" msgstr "" diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js index da892ce51d8e9bda05739a049e76cc803d02e04a..ea85cd347436d21e6e7f5a9d704fc5ed8acaae5e 100644 --- a/spec/frontend/repository/components/tree_content_spec.js +++ b/spec/frontend/repository/components/tree_content_spec.js @@ -1,5 +1,6 @@ import { shallowMount } from '@vue/test-utils'; -import TreeContent from '~/repository/components/tree_content.vue'; +import { GlButton } from '@gitlab/ui'; +import TreeContent, { INITIAL_FETCH_COUNT } from '~/repository/components/tree_content.vue'; import FilePreview from '~/repository/components/preview/index.vue'; let vm; @@ -25,14 +26,24 @@ describe('Repository table component', () => { vm.destroy(); }); - it('renders file preview', () => { + it('renders file preview', async () => { factory('/'); vm.setData({ entries: { blobs: [{ name: 'README.md' }] } }); - return vm.vm.$nextTick().then(() => { - expect(vm.find(FilePreview).exists()).toBe(true); - }); + await vm.vm.$nextTick(); + + expect(vm.find(FilePreview).exists()).toBe(true); + }); + + it('trigger fetchFiles when mounted', async () => { + factory('/'); + + jest.spyOn(vm.vm, 'fetchFiles').mockImplementation(() => {}); + + await vm.vm.$nextTick(); + + expect(vm.vm.fetchFiles).toHaveBeenCalled(); }); describe('normalizeData', () => { @@ -70,4 +81,59 @@ describe('Repository table component', () => { expect(output).toEqual({ hasNextPage: true, nextCursor: 'test' }); }); }); + + describe('Show more button', () => { + const showMoreButton = () => vm.find(GlButton); + + describe('when is present', () => { + beforeEach(async () => { + factory('/'); + + vm.setData({ fetchCounter: 10, clickedShowMore: false }); + + await vm.vm.$nextTick(); + }); + + it('is not rendered once it is clicked', async () => { + showMoreButton().vm.$emit('click'); + await vm.vm.$nextTick(); + + expect(showMoreButton().exists()).toBe(false); + }); + + it('is rendered', async () => { + expect(showMoreButton().exists()).toBe(true); + }); + + it('changes clickedShowMore when show more button is clicked', async () => { + showMoreButton().vm.$emit('click'); + + expect(vm.vm.clickedShowMore).toBe(true); + }); + + it('triggers fetchFiles when show more button is clicked', async () => { + jest.spyOn(vm.vm, 'fetchFiles'); + + showMoreButton().vm.$emit('click'); + + expect(vm.vm.fetchFiles).toBeCalled(); + }); + }); + + it('is not rendered if less than 1000 files', async () => { + factory('/'); + + vm.setData({ fetchCounter: 5, clickedShowMore: false }); + + await vm.vm.$nextTick(); + + expect(showMoreButton().exists()).toBe(false); + }); + + it('has limit of 1000 files on initial load', () => { + factory('/'); + + expect(INITIAL_FETCH_COUNT * vm.vm.pageSize).toBe(1000); + }); + }); });