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);
+ });
+ });
});