Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380 /spec/frontend/vue_mr_widget
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
Diffstat (limited to 'spec/frontend/vue_mr_widget')
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/utils_spec.js18
-rw-r--r--spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js9
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js42
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/mock_data.js2
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js60
-rw-r--r--spec/frontend/vue_mr_widget/test_extension.js39
-rw-r--r--spec/frontend/vue_mr_widget/test_extensions.js99
11 files changed, 212 insertions, 81 deletions
diff --git a/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js b/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js
new file mode 100644
index 00000000000..64e802c4fa5
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js
@@ -0,0 +1,18 @@
+import { generateText } from '~/vue_merge_request_widget/components/extensions/utils';
+
+describe('generateText', () => {
+ it.each`
+ text | expectedText
+ ${'%{strong_start}Hello world%{strong_end}'} | ${'<span class="gl-font-weight-bold">Hello world</span>'}
+ ${'%{success_start}Hello world%{success_end}'} | ${'<span class="gl-font-weight-bold gl-text-green-500">Hello world</span>'}
+ ${'%{danger_start}Hello world%{danger_end}'} | ${'<span class="gl-font-weight-bold gl-text-red-500">Hello world</span>'}
+ ${'%{critical_start}Hello world%{critical_end}'} | ${'<span class="gl-font-weight-bold gl-text-red-800">Hello world</span>'}
+ ${'%{same_start}Hello world%{same_end}'} | ${'<span class="gl-font-weight-bold gl-text-gray-700">Hello world</span>'}
+ ${'%{small_start}Hello world%{small_end}'} | ${'<span class="gl-font-sm">Hello world</span>'}
+ ${'%{strong_start}%{danger_start}Hello world%{danger_end}%{strong_end}'} | ${'<span class="gl-font-weight-bold"><span class="gl-font-weight-bold gl-text-red-500">Hello world</span></span>'}
+ ${'%{no_exist_start}Hello world%{no_exist_end}'} | ${'Hello world'}
+ ${['array']} | ${null}
+ `('generates $expectedText from $text', ({ text, expectedText }) => {
+ expect(generateText(text)).toBe(expectedText);
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
index f965fc32dc1..c30f6f1dfd1 100644
--- a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
@@ -3,7 +3,6 @@ import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit
const testCommitMessage = 'Test commit message';
const testLabel = 'Test label';
-const testTextMuted = 'Test text muted';
const testInputId = 'test-input-id';
describe('Commits edit component', () => {
@@ -64,7 +63,6 @@ describe('Commits edit component', () => {
beforeEach(() => {
createComponent({
header: `<div class="test-header">${testCommitMessage}</div>`,
- 'text-muted': `<p class="test-text-muted">${testTextMuted}</p>`,
});
});
@@ -74,12 +72,5 @@ describe('Commits edit component', () => {
expect(headerSlotElement.exists()).toBe(true);
expect(headerSlotElement.text()).toBe(testCommitMessage);
});
-
- it('renders text-muted slot correctly', () => {
- const textMutedElement = wrapper.find('.test-text-muted');
-
- expect(textMutedElement.exists()).toBe(true);
- expect(textMutedElement.text()).toBe(testTextMuted);
- });
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
index 4bdc6c95f22..f3061d792d0 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
@@ -25,7 +25,7 @@ describe('MRWidgetArchived', () => {
it('renders information', () => {
expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual(
- 'This project is archived, write access has been disabled',
+ 'Merge unavailable: merge requests are read-only on archived projects.',
);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
index e1bce7f0474..89de160b02f 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js
@@ -12,6 +12,14 @@ describe('MRWidgetConflicts', () => {
const findResolveButton = () => wrapper.findByTestId('resolve-conflicts-button');
const findMergeLocalButton = () => wrapper.findByTestId('merge-locally-button');
+ const mergeConflictsText = 'Merge blocked: merge conflicts must be resolved.';
+ const fastForwardMergeText =
+ 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.';
+ const userCannotMergeText =
+ 'Users who can write to the source or target branches can resolve the conflicts.';
+ const resolveConflictsBtnText = 'Resolve conflicts';
+ const mergeLocallyBtnText = 'Merge locally';
+
function createComponent(propsData = {}) {
wrapper = extendedWrapper(
shallowMount(ConflictsComponent, {
@@ -81,16 +89,16 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).not.toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
});
it('should not allow you to resolve the conflicts', () => {
- expect(wrapper.text()).not.toContain('Resolve conflicts');
+ expect(wrapper.text()).not.toContain(resolveConflictsBtnText);
});
it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain('Merge locally');
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
});
});
@@ -107,17 +115,17 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).toContain(userCannotMergeText);
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(path);
});
it('should not have merge buttons', () => {
- expect(wrapper.text()).not.toContain('Merge locally');
+ expect(wrapper.text()).not.toContain(mergeLocallyBtnText);
});
});
@@ -134,17 +142,17 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).not.toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(path);
});
it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain('Merge locally');
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
});
});
@@ -158,9 +166,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(
- 'ask someone with write access',
- );
+ expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(userCannotMergeText);
});
it('should not have action buttons', async () => {
@@ -198,9 +204,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(removeBreakLine(wrapper.text()).trim()).toContain(
- 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.',
- );
+ expect(removeBreakLine(wrapper.text()).trim()).toContain(fastForwardMergeText);
});
});
@@ -236,7 +240,7 @@ describe('MRWidgetConflicts', () => {
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(TEST_HOST);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 016b6b2220b..7082a19a8e7 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
+import { GlSprintf } from '@gitlab/ui';
import simplePoll from '~/lib/utils/simple_poll';
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
@@ -487,6 +488,7 @@ describe('ReadyToMerge', () => {
const findCommitEditElements = () => wrapper.findAll(CommitEdit);
const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
+ const findTipLink = () => wrapper.find(GlSprintf);
describe('squash checkbox', () => {
it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
@@ -503,10 +505,10 @@ describe('ReadyToMerge', () => {
expect(findCheckboxElement().exists()).toBeFalsy();
});
- it('should not be rendered when there is only 1 commit', () => {
+ it('should be rendered when there is only 1 commit', () => {
createComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
- expect(findCheckboxElement().exists()).toBeFalsy();
+ expect(findCheckboxElement().exists()).toBe(true);
});
describe('squash options', () => {
@@ -751,6 +753,12 @@ describe('ReadyToMerge', () => {
expect(findCommitDropdownElement().exists()).toBeTruthy();
});
});
+
+ it('renders a tip including a link to docs on templates', () => {
+ createComponent();
+
+ expect(findTipLink().exists()).toBe(true);
+ });
});
describe('Merge request project settings', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
index 0fb0d5b0b68..4070ca8d8dc 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -81,7 +81,9 @@ describe('Wip', () => {
it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(el.innerText).toContain('This merge request is still a draft.');
+ expect(el.innerText).toContain(
+ "Merge blocked: merge request must be marked as ready. It's still marked as draft.",
+ );
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge');
expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain(
diff --git a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
index f95a92c2cb1..3c9f6c2e165 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
@@ -32,9 +32,7 @@ describe('TerraformPlan', () => {
});
it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(
- `The report ${validPlanWithName.job_name} was generated in your pipelines.`,
- );
+ expect(wrapper.text()).toContain(`The job ${validPlanWithName.job_name} generated a report.`);
});
it('diplays the reported changes', () => {
@@ -70,7 +68,7 @@ describe('TerraformPlan', () => {
it('diplays the header text with a name', () => {
expect(wrapper.text()).toContain(
- `The report ${invalidPlanWithName.job_name} failed to generate.`,
+ `The job ${invalidPlanWithName.job_name} failed to generate a report.`,
);
});
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_mr_widget/mock_data.js
index f0c1da346a1..4538c1320d0 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_mr_widget/mock_data.js
@@ -271,8 +271,6 @@ export default {
mr_troubleshooting_docs_path: 'help',
ci_troubleshooting_docs_path: 'help2',
merge_request_pipelines_docs_path: '/help/ci/pipelines/merge_request_pipelines.md',
- merge_train_when_pipeline_succeeds_docs_path:
- '/help/ci/pipelines/merge_trains.md#startadd-to-merge-train-when-pipeline-succeeds',
squash: true,
visual_review_app_available: true,
merge_trains_enabled: true,
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 550f156d095..8d41f6620ff 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import * as Sentry from '@sentry/browser';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
@@ -19,10 +20,15 @@ import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/consta
import eventHub from '~/vue_merge_request_widget/event_hub';
import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
+import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql';
import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
import mockData from './mock_data';
-import testExtension from './test_extension';
+import {
+ workingExtension,
+ collapsedDataErrorExtension,
+ fullDataErrorExtension,
+} from './test_extensions';
jest.mock('~/api.js');
@@ -892,7 +898,7 @@ describe('MrWidgetOptions', () => {
describe('mock extension', () => {
beforeEach(() => {
- registerExtension(testExtension);
+ registerExtension(workingExtension);
createComponent();
});
@@ -914,7 +920,7 @@ describe('MrWidgetOptions', () => {
.find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
.trigger('click');
- await Vue.nextTick();
+ await nextTick();
expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_expand_event');
});
@@ -926,7 +932,7 @@ describe('MrWidgetOptions', () => {
.find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
.trigger('click');
- await Vue.nextTick();
+ await nextTick();
expect(
wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
@@ -952,4 +958,50 @@ describe('MrWidgetOptions', () => {
expect(collapsedSection.find(GlButton).text()).toBe('Full report');
});
});
+
+ describe('mock extension errors', () => {
+ let captureException;
+
+ const itHandlesTheException = () => {
+ expect(captureException).toHaveBeenCalledTimes(1);
+ expect(captureException).toHaveBeenCalledWith(new Error('Fetch error'));
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('error');
+ };
+
+ beforeEach(() => {
+ captureException = jest.spyOn(Sentry, 'captureException');
+ });
+
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ captureException = null;
+ });
+
+ it('handles collapsed data fetch errors', async () => {
+ registerExtension(collapsedDataErrorExtension);
+ createComponent();
+ await waitForPromises();
+
+ expect(
+ wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(),
+ ).toBe(false);
+ itHandlesTheException();
+ });
+
+ it('handles full data fetch errors', async () => {
+ registerExtension(fullDataErrorExtension);
+ createComponent();
+ await waitForPromises();
+
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).not.toBe('error');
+ wrapper
+ .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
+ .trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ itHandlesTheException();
+ });
+ });
});
diff --git a/spec/frontend/vue_mr_widget/test_extension.js b/spec/frontend/vue_mr_widget/test_extension.js
deleted file mode 100644
index 65c1bd8473b..00000000000
--- a/spec/frontend/vue_mr_widget/test_extension.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
-
-export default {
- name: 'WidgetTestExtension',
- props: ['targetProjectFullPath'],
- expandEvent: 'test_expand_event',
- computed: {
- summary({ count, targetProjectFullPath }) {
- return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
- },
- statusIcon({ count }) {
- return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
- },
- },
- methods: {
- fetchCollapsedData({ targetProjectFullPath }) {
- return Promise.resolve({ targetProjectFullPath, count: 1 });
- },
- fetchFullData() {
- return Promise.resolve([
- {
- id: 1,
- text: 'Hello world',
- icon: {
- name: EXTENSION_ICONS.failed,
- },
- badge: {
- text: 'Closed',
- },
- link: {
- href: 'https://gitlab.com',
- text: 'GitLab.com',
- },
- actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
- },
- ]);
- },
- },
-};
diff --git a/spec/frontend/vue_mr_widget/test_extensions.js b/spec/frontend/vue_mr_widget/test_extensions.js
new file mode 100644
index 00000000000..c7ff02ab726
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/test_extensions.js
@@ -0,0 +1,99 @@
+import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
+
+export const workingExtension = {
+ name: 'WidgetTestExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return Promise.resolve({ targetProjectFullPath, count: 1 });
+ },
+ fetchFullData() {
+ return Promise.resolve([
+ {
+ id: 1,
+ text: 'Hello world',
+ icon: {
+ name: EXTENSION_ICONS.failed,
+ },
+ badge: {
+ text: 'Closed',
+ },
+ link: {
+ href: 'https://gitlab.com',
+ text: 'GitLab.com',
+ },
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
+ },
+ ]);
+ },
+ },
+};
+
+export const collapsedDataErrorExtension = {
+ name: 'WidgetTestCollapsedErrorExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData() {
+ return Promise.reject(new Error('Fetch error'));
+ },
+ fetchFullData() {
+ return Promise.resolve([
+ {
+ id: 1,
+ text: 'Hello world',
+ icon: {
+ name: EXTENSION_ICONS.failed,
+ },
+ badge: {
+ text: 'Closed',
+ },
+ link: {
+ href: 'https://gitlab.com',
+ text: 'GitLab.com',
+ },
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
+ },
+ ]);
+ },
+ },
+};
+
+export const fullDataErrorExtension = {
+ name: 'WidgetTestCollapsedErrorExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return Promise.resolve({ targetProjectFullPath, count: 1 });
+ },
+ fetchFullData() {
+ return Promise.reject(new Error('Fetch error'));
+ },
+ },
+};