summaryrefslogtreecommitdiff
path: root/spec/frontend/environments
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/environments')
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js27
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js11
-rw-r--r--spec/frontend/environments/commit_spec.js71
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js75
-rw-r--r--spec/frontend/environments/deploy_board_wrapper_spec.js124
-rw-r--r--spec/frontend/environments/deployment_spec.js243
-rw-r--r--spec/frontend/environments/environment_actions_spec.js4
-rw-r--r--spec/frontend/environments/environment_pin_spec.js74
-rw-r--r--spec/frontend/environments/environment_table_spec.js3
-rw-r--r--spec/frontend/environments/environments_app_spec.js8
-rw-r--r--spec/frontend/environments/graphql/mock_data.js66
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js4
-rw-r--r--spec/frontend/environments/new_environment_folder_spec.js1
-rw-r--r--spec/frontend/environments/new_environment_item_spec.js185
-rw-r--r--spec/frontend/environments/new_environments_app_spec.js31
15 files changed, 857 insertions, 70 deletions
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
index 6c7a786e652..d58f9f9b8a2 100644
--- a/spec/frontend/environments/canary_ingress_spec.js
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import { CANARY_UPDATE_MODAL } from '~/environments/constants';
+import { rolloutStatus } from './graphql/mock_data';
describe('/environments/components/canary_ingress.vue', () => {
let wrapper;
@@ -13,16 +14,18 @@ describe('/environments/components/canary_ingress.vue', () => {
.at(x / 5)
.vm.$emit('click');
- const createComponent = () => {
+ const createComponent = (props = {}, options = {}) => {
wrapper = mount(CanaryIngress, {
propsData: {
canaryIngress: {
canary_weight: 60,
},
+ ...props,
},
directives: {
GlModal: createMockDirective(),
},
+ ...options,
});
};
@@ -94,9 +97,25 @@ describe('/environments/components/canary_ingress.vue', () => {
});
it('is set to open the change modal', () => {
- const options = canaryWeightDropdown.findAll(GlDropdownItem);
- expect(options).toHaveLength(21);
- options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ canaryWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w) =>
+ expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
+ );
+ });
+ });
+
+ describe('graphql', () => {
+ beforeEach(() => {
+ createComponent({
+ graphql: true,
+ canaryIngress: rolloutStatus.canaryIngress,
+ });
+ });
+
+ it('shows the correct weight', () => {
+ const canaryWeightDropdown = wrapper.find('[data-testid="canary-weight"]');
+ expect(canaryWeightDropdown.props('text')).toBe('50');
});
});
});
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
index c7129ee1320..22d13558a84 100644
--- a/spec/frontend/environments/canary_update_modal_spec.js
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -1,5 +1,6 @@
import { GlAlert, GlModal } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import waitForPromises from 'helpers/wait_for_promises';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import updateCanaryIngress from '~/environments/graphql/mutations/update_canary_ingress.mutation.graphql';
@@ -86,7 +87,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().exists()).toBe(false);
});
@@ -95,7 +96,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().text()).toBe('error');
});
@@ -105,7 +106,7 @@ describe('/environments/components/canary_update_modal.vue', () => {
modal.vm.$emit('primary');
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findAlert().text()).toBe('Something went wrong. Please try again later');
});
@@ -114,12 +115,12 @@ describe('/environments/components/canary_update_modal.vue', () => {
mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
modal.vm.$emit('primary');
- await wrapper.vm.$nextTick();
+ await nextTick();
const alert = findAlert();
alert.vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(alert.exists()).toBe(false);
});
diff --git a/spec/frontend/environments/commit_spec.js b/spec/frontend/environments/commit_spec.js
new file mode 100644
index 00000000000..32eb4b77528
--- /dev/null
+++ b/spec/frontend/environments/commit_spec.js
@@ -0,0 +1,71 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import Commit from '~/environments/components/commit.vue';
+import { resolvedEnvironment } from './graphql/mock_data';
+
+describe('~/environments/components/commit.vue', () => {
+ let commit;
+ let wrapper;
+
+ beforeEach(() => {
+ commit = resolvedEnvironment.lastDeployment.commit;
+ });
+
+ const createWrapper = ({ propsData = {} } = {}) =>
+ mountExtended(Commit, {
+ propsData: {
+ commit,
+ ...propsData,
+ },
+ });
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ describe('with gitlab user', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('links to the user profile', () => {
+ const link = wrapper.findByRole('link', { name: commit.author.name });
+ expect(link.attributes('href')).toBe(commit.author.path);
+ });
+
+ it('displays the user avatar', () => {
+ const avatar = wrapper.findByRole('img', { name: 'avatar' });
+ expect(avatar.attributes('src')).toBe(commit.author.avatarUrl);
+ });
+
+ it('links the commit message to the commit', () => {
+ const message = wrapper.findByRole('link', { name: commit.message });
+
+ expect(message.attributes('href')).toBe(commit.commitPath);
+ });
+ });
+ describe('without gitlab user', () => {
+ beforeEach(() => {
+ commit = {
+ ...commit,
+ author: null,
+ };
+ wrapper = createWrapper();
+ });
+
+ it('links to the user profile', () => {
+ const link = wrapper.findByRole('link', { name: commit.authorName });
+ expect(link.attributes('href')).toBe(`mailto:${commit.authorEmail}`);
+ });
+
+ it('displays the user avatar', () => {
+ const avatar = wrapper.findByRole('img', { name: 'avatar' });
+ expect(avatar.attributes('src')).toBe(commit.authorGravatarUrl);
+ });
+
+ it('displays the commit message', () => {
+ const message = wrapper.findByRole('link', { name: commit.message });
+
+ expect(message.attributes('href')).toBe(commit.commitPath);
+ });
+ });
+});
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
index 24e94867afd..f0fb4d1027c 100644
--- a/spec/frontend/environments/deploy_board_component_spec.js
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -1,9 +1,10 @@
import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import { deployBoardMockData, environment } from './mock_data';
+import { rolloutStatus } from './graphql/mock_data';
const logsPath = `gitlab-org/gitlab-test/-/logs?environment_name=${environment.name}`;
@@ -24,11 +25,11 @@ describe('Deploy Board', () => {
describe('with valid data', () => {
beforeEach((done) => {
wrapper = createComponent();
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render percentage with completion value provided', () => {
- expect(wrapper.vm.$refs.percentage.innerText).toEqual(`${deployBoardMockData.completion}%`);
+ expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${deployBoardMockData.completion}%`);
});
it('should render total instance count', () => {
@@ -57,20 +58,74 @@ describe('Deploy Board', () => {
it('sets up a tooltip for the legend', () => {
const iconSpan = wrapper.find('[data-testid="legend-tooltip-target"]');
- const tooltip = wrapper.find(GlTooltip);
- const icon = iconSpan.find(GlIcon);
+ const tooltip = wrapper.findComponent(GlTooltip);
+ const icon = iconSpan.findComponent(GlIcon);
expect(tooltip.props('target')()).toBe(iconSpan.element);
expect(icon.props('name')).toBe('question');
});
it('renders the canary weight selector', () => {
- const canary = wrapper.find(CanaryIngress);
+ const canary = wrapper.findComponent(CanaryIngress);
expect(canary.exists()).toBe(true);
expect(canary.props('canaryIngress')).toEqual({ canary_weight: 50 });
});
});
+ describe('with new valid data', () => {
+ beforeEach(async () => {
+ wrapper = createComponent({
+ graphql: true,
+ deployBoardData: rolloutStatus,
+ });
+ await nextTick();
+ });
+
+ it('should render percentage with completion value provided', () => {
+ expect(wrapper.find({ ref: 'percentage' }).text()).toBe(`${rolloutStatus.completion}%`);
+ });
+
+ it('should render total instance count', () => {
+ const renderedTotal = wrapper.find('.deploy-board-instances-text');
+ const actualTotal = rolloutStatus.instances.length;
+ const output = `${actualTotal > 1 ? 'Instances' : 'Instance'} (${actualTotal})`;
+
+ expect(renderedTotal.text()).toEqual(output);
+ });
+
+ it('should render all instances', () => {
+ const instances = wrapper.findAll('.deploy-board-instances-container a');
+
+ expect(instances).toHaveLength(rolloutStatus.instances.length);
+ expect(
+ instances.at(1).classes(`deployment-instance-${rolloutStatus.instances[2].status}`),
+ ).toBe(true);
+ });
+
+ it('should render an abort and a rollback button with the provided url', () => {
+ const buttons = wrapper.findAll('.deploy-board-actions a');
+
+ expect(buttons.at(0).attributes('href')).toEqual(rolloutStatus.rollbackUrl);
+ expect(buttons.at(1).attributes('href')).toEqual(rolloutStatus.abortUrl);
+ });
+
+ it('sets up a tooltip for the legend', () => {
+ const iconSpan = wrapper.find('[data-testid="legend-tooltip-target"]');
+ const tooltip = wrapper.findComponent(GlTooltip);
+ const icon = iconSpan.findComponent(GlIcon);
+
+ expect(tooltip.props('target')()).toBe(iconSpan.element);
+ expect(icon.props('name')).toBe('question');
+ });
+
+ it('renders the canary weight selector', () => {
+ const canary = wrapper.findComponent(CanaryIngress);
+ expect(canary.exists()).toBe(true);
+ expect(canary.props('canaryIngress')).toEqual({ canaryWeight: 50 });
+ expect(canary.props('graphql')).toBe(true);
+ });
+ });
+
describe('with empty state', () => {
beforeEach((done) => {
wrapper = createComponent({
@@ -79,7 +134,7 @@ describe('Deploy Board', () => {
isEmpty: true,
logsPath,
});
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render the empty state', () => {
@@ -98,11 +153,11 @@ describe('Deploy Board', () => {
isEmpty: false,
logsPath,
});
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('should render loading spinner', () => {
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
});
});
@@ -116,7 +171,7 @@ describe('Deploy Board', () => {
deployBoardData: deployBoardMockData,
});
({ statuses } = wrapper.vm);
- wrapper.vm.$nextTick(done);
+ nextTick(done);
});
it('with all the possible statuses', () => {
diff --git a/spec/frontend/environments/deploy_board_wrapper_spec.js b/spec/frontend/environments/deploy_board_wrapper_spec.js
new file mode 100644
index 00000000000..c8e6df4d324
--- /dev/null
+++ b/spec/frontend/environments/deploy_board_wrapper_spec.js
@@ -0,0 +1,124 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlCollapse, GlIcon } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { stubTransition } from 'helpers/stub_transition';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { __, s__ } from '~/locale';
+import DeployBoardWrapper from '~/environments/components/deploy_board_wrapper.vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
+import setEnvironmentToChangeCanaryMutation from '~/environments/graphql/mutations/set_environment_to_change_canary.mutation.graphql';
+import { resolvedEnvironment, rolloutStatus } from './graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('~/environments/components/deploy_board_wrapper.vue', () => {
+ let wrapper;
+ let mockApollo;
+
+ const findDeployBoard = () => wrapper.findComponent(DeployBoard);
+
+ const createWrapper = ({ propsData = {} } = {}) => {
+ mockApollo = createMockApollo();
+ return mountExtended(DeployBoardWrapper, {
+ propsData: { environment: resolvedEnvironment, rolloutStatus, ...propsData },
+ provide: { helpPagePath: '/help' },
+ stubs: { transition: stubTransition() },
+ apolloProvider: mockApollo,
+ });
+ };
+
+ const expandCollapsedSection = async () => {
+ const button = wrapper.findByRole('button', { name: __('Expand') });
+ await button.trigger('click');
+
+ return button;
+ };
+
+ afterEach(() => {
+ wrapper?.destroy();
+ });
+
+ it('is labeled Kubernetes Pods', () => {
+ wrapper = createWrapper();
+
+ expect(wrapper.findByText(s__('DeployBoard|Kubernetes Pods')).exists()).toBe(true);
+ });
+
+ describe('collapse', () => {
+ let icon;
+ let collapse;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ collapse = wrapper.findComponent(GlCollapse);
+ icon = wrapper.findComponent(GlIcon);
+ });
+
+ it('is collapsed by default', () => {
+ expect(collapse.attributes('visible')).toBeUndefined();
+ expect(icon.props('name')).toBe('angle-right');
+ });
+
+ it('opens on click', async () => {
+ const button = await expandCollapsedSection();
+
+ expect(button.attributes('aria-label')).toBe(__('Collapse'));
+ expect(collapse.attributes('visible')).toBe('visible');
+ expect(icon.props('name')).toBe('angle-down');
+
+ const deployBoard = findDeployBoard();
+ expect(deployBoard.exists()).toBe(true);
+ });
+ });
+
+ describe('deploy board', () => {
+ it('passes the rollout status on and sets graphql to true', async () => {
+ wrapper = createWrapper();
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+ expect(deployBoard.props('deployBoardData')).toEqual(rolloutStatus);
+ expect(deployBoard.props('graphql')).toBe(true);
+ });
+
+ it('sets the update to the canary via graphql', () => {
+ wrapper = createWrapper();
+ jest.spyOn(mockApollo.defaultClient, 'mutate');
+ const deployBoard = findDeployBoard();
+ deployBoard.vm.$emit('changeCanaryWeight', 15);
+ expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: setEnvironmentToChangeCanaryMutation,
+ variables: { environment: resolvedEnvironment, weight: 15 },
+ });
+ });
+
+ describe('is loading', () => {
+ it('should set the loading prop', async () => {
+ wrapper = createWrapper({
+ propsData: { rolloutStatus: { ...rolloutStatus, status: 'loading' } },
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+
+ expect(deployBoard.props('isLoading')).toBe(true);
+ });
+ });
+
+ describe('is empty', () => {
+ it('should set the empty prop', async () => {
+ wrapper = createWrapper({
+ propsData: { rolloutStatus: { ...rolloutStatus, status: 'not_found' } },
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = findDeployBoard();
+
+ expect(deployBoard.props('isEmpty')).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/deployment_spec.js b/spec/frontend/environments/deployment_spec.js
index 37209bdc86c..6cc363e000b 100644
--- a/spec/frontend/environments/deployment_spec.js
+++ b/spec/frontend/environments/deployment_spec.js
@@ -1,17 +1,32 @@
+import { GlCollapse } from '@gitlab/ui';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { useFakeDate } from 'helpers/fake_date';
+import { stubTransition } from 'helpers/stub_transition';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import { __, s__ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Deployment from '~/environments/components/deployment.vue';
+import Commit from '~/environments/components/commit.vue';
import DeploymentStatusBadge from '~/environments/components/deployment_status_badge.vue';
import { resolvedEnvironment } from './graphql/mock_data';
describe('~/environments/components/deployment.vue', () => {
+ useFakeDate(2022, 0, 8, 16);
+
+ let deployment;
let wrapper;
+ beforeEach(() => {
+ deployment = resolvedEnvironment.lastDeployment;
+ });
+
const createWrapper = ({ propsData = {} } = {}) =>
mountExtended(Deployment, {
propsData: {
- deployment: resolvedEnvironment.lastDeployment,
+ deployment,
...propsData,
},
+ stubs: { transition: stubTransition() },
});
afterEach(() => {
@@ -21,9 +36,229 @@ describe('~/environments/components/deployment.vue', () => {
describe('status', () => {
it('should pass the deployable status to the badge', () => {
wrapper = createWrapper();
- expect(wrapper.findComponent(DeploymentStatusBadge).props('status')).toBe(
- resolvedEnvironment.lastDeployment.status,
- );
+ expect(wrapper.findComponent(DeploymentStatusBadge).props('status')).toBe(deployment.status);
+ });
+ });
+
+ describe('latest', () => {
+ it('should show a badge if the deployment is latest', () => {
+ wrapper = createWrapper({ propsData: { latest: true } });
+
+ const badge = wrapper.findByText(s__('Deployment|Latest Deployed'));
+
+ expect(badge.exists()).toBe(true);
+ });
+
+ it('should not show a badge if the deployment is not latest', () => {
+ wrapper = createWrapper();
+
+ const badge = wrapper.findByText(s__('Deployment|Latest Deployed'));
+
+ expect(badge.exists()).toBe(false);
+ });
+ });
+
+ describe('iid', () => {
+ const findIid = () => wrapper.findByTitle(s__('Deployment|Deployment ID'));
+ const findDeploymentIcon = () => wrapper.findComponent({ ref: 'deployment-iid-icon' });
+
+ describe('is present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('should show the iid', () => {
+ const iid = findIid();
+ expect(iid.exists()).toBe(true);
+ });
+
+ it('should show an icon for the iid', () => {
+ const deploymentIcon = findDeploymentIcon();
+ expect(deploymentIcon.props('name')).toBe('deployments');
+ });
+ });
+
+ describe('is not present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, iid: '' } } });
+ });
+
+ it('should not show the iid', () => {
+ const iid = findIid();
+ expect(iid.exists()).toBe(false);
+ });
+
+ it('should not show an icon for the iid', () => {
+ const deploymentIcon = findDeploymentIcon();
+ expect(deploymentIcon.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('shortSha', () => {
+ describe('is present', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('shows the short SHA for the commit of the deployment', () => {
+ const sha = wrapper.findByTitle(__('Commit SHA'));
+
+ expect(sha.exists()).toBe(true);
+ expect(sha.text()).toBe(deployment.commit.shortId);
+ });
+
+ it('shows the commit icon', () => {
+ const icon = wrapper.findComponent({ ref: 'deployment-commit-icon' });
+ expect(icon.props('name')).toBe('commit');
+ });
+
+ it('shows a copy button for the sha', () => {
+ const button = wrapper.findComponent(ClipboardButton);
+ expect(button.props()).toMatchObject({
+ text: deployment.commit.shortId,
+ title: __('Copy commit SHA'),
+ });
+ });
+ });
+
+ describe('is not present', () => {
+ it('does not show the short SHA for the commit of the deployment', () => {
+ wrapper = createWrapper({
+ propsData: {
+ deployment: {
+ ...deployment,
+ commit: null,
+ },
+ },
+ });
+ const sha = wrapper.findByTestId('deployment-commit-sha');
+ expect(sha.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('created at time', () => {
+ describe('is present', () => {
+ it('shows the timestamp the deployment was deployed at', () => {
+ wrapper = createWrapper();
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.text()).toBe('1 day ago');
+ });
+ });
+ describe('is not present', () => {
+ it('does not show the timestamp', () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, createdAt: null } } });
+ const date = wrapper.findByTitle(formatDate(deployment.createdAt));
+
+ expect(date.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('commit message', () => {
+ describe('with commit', () => {
+ beforeEach(() => {
+ wrapper = createWrapper();
+ });
+
+ it('shows the commit component', () => {
+ const commit = wrapper.findComponent(Commit);
+ expect(commit.props('commit')).toBe(deployment.commit);
+ });
+ });
+
+ describe('without a commit', () => {
+ it('displays nothing', () => {
+ const noCommit = {
+ ...deployment,
+ commit: null,
+ };
+ wrapper = createWrapper({ propsData: { deployment: noCommit } });
+
+ const commit = wrapper.findComponent(Commit);
+ expect(commit.exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('collapse', () => {
+ let collapse;
+ let button;
+
+ beforeEach(() => {
+ wrapper = createWrapper();
+ collapse = wrapper.findComponent(GlCollapse);
+ button = wrapper.findComponent({ ref: 'details-toggle' });
+ });
+
+ it('is collapsed by default', () => {
+ expect(collapse.attributes('visible')).toBeUndefined();
+ expect(button.props('icon')).toBe('expand-down');
+ expect(button.text()).toBe(__('Show details'));
+ });
+
+ it('opens on click', async () => {
+ await button.trigger('click');
+
+ expect(button.text()).toBe(__('Hide details'));
+ expect(button.props('icon')).toBe('expand-up');
+ expect(collapse.attributes('visible')).toBe('visible');
+
+ const username = wrapper.findByRole('link', { name: `@${deployment.user.username}` });
+
+ expect(username.attributes('href')).toBe(deployment.user.path);
+ const job = wrapper.findByRole('link', { name: deployment.deployable.name });
+ expect(job.attributes('href')).toBe(deployment.deployable.buildPath);
+ const apiBadge = wrapper.findByText(__('API'));
+ expect(apiBadge.exists()).toBe(false);
+
+ const branchLabel = wrapper.findByText(__('Branch'));
+ expect(branchLabel.exists()).toBe(true);
+ const tagLabel = wrapper.findByText(__('Tag'));
+ expect(tagLabel.exists()).toBe(false);
+ const ref = wrapper.findByRole('link', { name: deployment.ref.name });
+ expect(ref.attributes('href')).toBe(deployment.ref.refPath);
+ });
+ });
+
+ describe('with tagged deployment', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, tag: true } } });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows tag instead of branch', () => {
+ const refLabel = wrapper.findByText(__('Tag'));
+ expect(refLabel.exists()).toBe(true);
+ });
+ });
+
+ describe('with API deployment', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({ propsData: { deployment: { ...deployment, deployable: null } } });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows API instead of a job name', () => {
+ const apiBadge = wrapper.findByText(__('API'));
+ expect(apiBadge.exists()).toBe(true);
+ });
+ });
+ describe('without a job path', () => {
+ beforeEach(async () => {
+ wrapper = createWrapper({
+ propsData: {
+ deployment: { ...deployment, deployable: { name: deployment.deployable.name } },
+ },
+ });
+ await wrapper.findComponent({ ref: 'details-toggle' }).trigger('click');
+ });
+
+ it('shows a span instead of a link', () => {
+ const job = wrapper.findByTitle(deployment.deployable.name);
+ expect(job.attributes('href')).toBeUndefined();
});
});
});
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index 1b68a692db8..336c207428e 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -1,6 +1,6 @@
import { GlDropdown, GlDropdownItem, GlLoadingIcon, GlIcon } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { TEST_HOST } from 'helpers/test_constants';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
@@ -108,7 +108,7 @@ describe('EnvironmentActions Component', () => {
jest.spyOn(window, 'confirm').mockImplementation(() => confirm);
findDropdownItem(scheduledJobAction).vm.$emit('click');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
beforeEach(() => {
diff --git a/spec/frontend/environments/environment_pin_spec.js b/spec/frontend/environments/environment_pin_spec.js
index a9a58071e12..669c974ea4f 100644
--- a/spec/frontend/environments/environment_pin_spec.js
+++ b/spec/frontend/environments/environment_pin_spec.js
@@ -1,5 +1,9 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import cancelAutoStopMutation from '~/environments/graphql/mutations/cancel_auto_stop.mutation.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
import PinComponent from '~/environments/components/environment_pin.vue';
import eventHub from '~/environments/event_hub';
@@ -18,28 +22,66 @@ describe('Pin Component', () => {
const autoStopUrl = '/root/auto-stop-env-test/-/environments/38/cancel_auto_stop';
- beforeEach(() => {
- factory({
- propsData: {
- autoStopUrl,
- },
+ describe('without graphql', () => {
+ beforeEach(() => {
+ factory({
+ propsData: {
+ autoStopUrl,
+ },
+ });
});
- });
- afterEach(() => {
- wrapper.destroy();
- });
+ afterEach(() => {
+ wrapper.destroy();
+ });
- it('should render the component with descriptive text', () => {
- expect(wrapper.text()).toBe('Prevent auto-stopping');
+ it('should render the component with descriptive text', () => {
+ expect(wrapper.text()).toBe('Prevent auto-stopping');
+ });
+
+ it('should emit onPinClick when clicked', () => {
+ const eventHubSpy = jest.spyOn(eventHub, '$emit');
+ const item = wrapper.find(GlDropdownItem);
+
+ item.vm.$emit('click');
+
+ expect(eventHubSpy).toHaveBeenCalledWith('cancelAutoStop', autoStopUrl);
+ });
});
- it('should emit onPinClick when clicked', () => {
- const eventHubSpy = jest.spyOn(eventHub, '$emit');
- const item = wrapper.find(GlDropdownItem);
+ describe('with graphql', () => {
+ Vue.use(VueApollo);
+ let mockApollo;
- item.vm.$emit('click');
+ beforeEach(() => {
+ mockApollo = createMockApollo();
+ factory({
+ propsData: {
+ autoStopUrl,
+ graphql: true,
+ },
+ apolloProvider: mockApollo,
+ });
+ });
- expect(eventHubSpy).toHaveBeenCalledWith('cancelAutoStop', autoStopUrl);
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should render the component with descriptive text', () => {
+ expect(wrapper.text()).toBe('Prevent auto-stopping');
+ });
+
+ it('should emit onPinClick when clicked', () => {
+ jest.spyOn(mockApollo.defaultClient, 'mutate');
+ const item = wrapper.find(GlDropdownItem);
+
+ item.vm.$emit('click');
+
+ expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: cancelAutoStopMutation,
+ variables: { autoStopUrl },
+ });
+ });
});
});
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index 1851163ac68..c7582e4b06d 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import EnvironmentTable from '~/environments/components/environments_table.vue';
@@ -181,7 +182,7 @@ describe('Environment table', () => {
});
wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
weight: 40,
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index cd05ecbfb53..92d1820681c 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -1,6 +1,7 @@
import { GlTabs } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import Container from '~/environments/components/container.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
@@ -186,14 +187,13 @@ describe('Environment', () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(false);
});
- it('should close an opened folder', () => {
+ it('should close an opened folder', async () => {
expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(true);
// close folder
wrapper.find('.folder-name').trigger('click');
- wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
- });
+ await nextTick();
+ expect(wrapper.find('.folder-icon[data-testid="chevron-down-icon"]').exists()).toBe(false);
});
it('should show children environments', () => {
diff --git a/spec/frontend/environments/graphql/mock_data.js b/spec/frontend/environments/graphql/mock_data.js
index fce30973547..1b7b35702de 100644
--- a/spec/frontend/environments/graphql/mock_data.js
+++ b/spec/frontend/environments/graphql/mock_data.js
@@ -1,3 +1,69 @@
+export const rolloutStatus = {
+ instances: [
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2334 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2335 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2336 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2337 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2338 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ {
+ status: 'succeeded',
+ tooltip: 'tanuki-2339 Finished',
+ podName: 'production-tanuki-1',
+ stable: false,
+ },
+ { status: 'succeeded', tooltip: 'tanuki-2340 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2334 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2335 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2336 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2337 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2338 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2339 Finished', podName: 'production-tanuki-1' },
+ { status: 'succeeded', tooltip: 'tanuki-2340 Finished', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2341 Deploying', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2342 Deploying', podName: 'production-tanuki-1' },
+ { status: 'running', tooltip: 'tanuki-2343 Deploying', podName: 'production-tanuki-1' },
+ { status: 'failed', tooltip: 'tanuki-2344 Failed', podName: 'production-tanuki-1' },
+ { status: 'unknown', tooltip: 'tanuki-2345 Ready', podName: 'production-tanuki-1' },
+ { status: 'unknown', tooltip: 'tanuki-2346 Ready', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2348 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2349 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2350 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2353 Preparing', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2354 waiting', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2355 waiting', podName: 'production-tanuki-1' },
+ { status: 'pending', tooltip: 'tanuki-2356 waiting', podName: 'production-tanuki-1' },
+ ],
+ abortUrl: 'url',
+ rollbackUrl: 'url',
+ completion: 100,
+ status: 'found',
+ canaryIngress: { canaryWeight: 50 },
+};
export const environmentsApp = {
environments: [
{
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
index 6b53dc24f0f..21d7e09bad5 100644
--- a/spec/frontend/environments/graphql/resolvers_spec.js
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -173,9 +173,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should post to the auto stop path', async () => {
mock.onPost(ENDPOINT).reply(200);
- await mockResolvers.Mutation.cancelAutoStop(null, {
- environment: { autoStopPath: ENDPOINT },
- });
+ await mockResolvers.Mutation.cancelAutoStop(null, { autoStopUrl: ENDPOINT });
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
diff --git a/spec/frontend/environments/new_environment_folder_spec.js b/spec/frontend/environments/new_environment_folder_spec.js
index 6823c88a5a1..460263587be 100644
--- a/spec/frontend/environments/new_environment_folder_spec.js
+++ b/spec/frontend/environments/new_environment_folder_spec.js
@@ -32,6 +32,7 @@ describe('~/environments/components/new_environments_folder.vue', () => {
apolloProvider,
propsData,
stubs: { transition: stubTransition() },
+ provide: { helpPagePath: '/help' },
});
beforeEach(async () => {
diff --git a/spec/frontend/environments/new_environment_item_spec.js b/spec/frontend/environments/new_environment_item_spec.js
index 244aef5c43b..db596688dad 100644
--- a/spec/frontend/environments/new_environment_item_spec.js
+++ b/spec/frontend/environments/new_environment_item_spec.js
@@ -2,12 +2,14 @@ import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { GlCollapse, GlIcon } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import { stubTransition } from 'helpers/stub_transition';
-import { __, s__ } from '~/locale';
+import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
+import { __, s__, sprintf } from '~/locale';
import EnvironmentItem from '~/environments/components/new_environment_item.vue';
import Deployment from '~/environments/components/deployment.vue';
-import { resolvedEnvironment } from './graphql/mock_data';
+import DeployBoardWrapper from '~/environments/components/deploy_board_wrapper.vue';
+import { resolvedEnvironment, rolloutStatus } from './graphql/mock_data';
Vue.use(VueApollo);
@@ -22,11 +24,19 @@ describe('~/environments/components/new_environment_item.vue', () => {
mountExtended(EnvironmentItem, {
apolloProvider,
propsData: { environment: resolvedEnvironment, ...propsData },
+ provide: { helpPagePath: '/help' },
stubs: { transition: stubTransition() },
});
const findDeployment = () => wrapper.findComponent(Deployment);
+ const expandCollapsedSection = async () => {
+ const button = wrapper.findByRole('button', { name: __('Expand') });
+ await button.trigger('click');
+
+ return button;
+ };
+
afterEach(() => {
wrapper?.destroy();
});
@@ -165,25 +175,92 @@ describe('~/environments/components/new_environment_item.vue', () => {
});
describe('pin', () => {
- it('shows the option to pin the environment if there is an autostop date', () => {
- wrapper = createWrapper({
- propsData: {
- environment: { ...resolvedEnvironment, autoStopAt: new Date(Date.now() + 100000) },
- },
- apolloProvider: createApolloProvider(),
+ describe('with autostop', () => {
+ let environment;
+
+ beforeEach(() => {
+ environment = {
+ ...resolvedEnvironment,
+ autoStopAt: new Date(Date.now() + 100000).toString(),
+ };
+ wrapper = createWrapper({
+ propsData: {
+ environment,
+ },
+ apolloProvider: createApolloProvider(),
+ });
});
- const rollback = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+ it('shows the option to pin the environment if there is an autostop date', () => {
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
- expect(rollback.exists()).toBe(true);
+ expect(pin.exists()).toBe(true);
+ });
+
+ it('shows when the environment auto stops', () => {
+ const autoStop = wrapper.findByTitle(formatDate(environment.autoStopAt));
+
+ expect(autoStop.text()).toBe('in 1 minute');
+ });
});
- it('does not show the option to pin the environment if there is no autostop date', () => {
- wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+ describe('without autostop', () => {
+ beforeEach(() => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+ });
- const rollback = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+ it('does not show the option to pin the environment if there is no autostop date', () => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
- expect(rollback.exists()).toBe(false);
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+
+ expect(pin.exists()).toBe(false);
+ });
+
+ it('does not show when the environment auto stops', () => {
+ const autoStop = wrapper.findByText(
+ sprintf(s__('Environment|Auto stop %{time}'), {
+ time: getTimeago().format(resolvedEnvironment.autoStopAt),
+ }),
+ );
+
+ expect(autoStop.exists()).toBe(false);
+ });
+ });
+
+ describe('with past autostop', () => {
+ let environment;
+
+ beforeEach(() => {
+ environment = {
+ ...resolvedEnvironment,
+ autoStopAt: new Date(Date.now() - 100000).toString(),
+ };
+ wrapper = createWrapper({
+ propsData: {
+ environment,
+ },
+ apolloProvider: createApolloProvider(),
+ });
+ });
+
+ it('does not show the option to pin the environment if there is no autostop date', () => {
+ wrapper = createWrapper({ apolloProvider: createApolloProvider() });
+
+ const pin = wrapper.findByRole('menuitem', { name: __('Prevent auto-stopping') });
+
+ expect(pin.exists()).toBe(false);
+ });
+
+ it('does not show when the environment auto stops', () => {
+ const autoStop = wrapper.findByText(
+ sprintf(s__('Environment|Auto stop %{time}'), {
+ time: getTimeago().format(environment.autoStopAt),
+ }),
+ );
+
+ expect(autoStop.exists()).toBe(false);
+ });
});
});
@@ -258,14 +335,12 @@ describe('~/environments/components/new_environment_item.vue', () => {
describe('collapse', () => {
let icon;
let collapse;
- let button;
let environmentName;
beforeEach(() => {
wrapper = createWrapper({ apolloProvider: createApolloProvider() });
collapse = wrapper.findComponent(GlCollapse);
icon = wrapper.findComponent(GlIcon);
- button = wrapper.findByRole('button', { name: __('Expand') });
environmentName = wrapper.findByText(resolvedEnvironment.name);
});
@@ -278,7 +353,7 @@ describe('~/environments/components/new_environment_item.vue', () => {
it('opens on click', async () => {
expect(findDeployment().isVisible()).toBe(false);
- await button.trigger('click');
+ const button = await expandCollapsedSection();
expect(button.attributes('aria-label')).toBe(__('Collapse'));
expect(collapse.attributes('visible')).toBe('visible');
@@ -338,4 +413,78 @@ describe('~/environments/components/new_environment_item.vue', () => {
expect(deployment.exists()).toBe(false);
});
});
+
+ describe('empty state', () => {
+ it('should link to documentation', async () => {
+ const environment = {
+ ...resolvedEnvironment,
+ lastDeployment: null,
+ upcomingDeployment: null,
+ };
+
+ wrapper = createWrapper({
+ propsData: { environment },
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const text = s__(
+ 'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
+ );
+
+ const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
+
+ const link = extendedWrapper(emptyState).findByRole('link');
+
+ expect(link.attributes('href')).toBe('/help');
+ });
+
+ it('should not link to the documentation when there are deployments', async () => {
+ wrapper = createWrapper({
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const text = s__(
+ 'Environments|There are no deployments for this environment yet. Learn more about setting up deployments.',
+ );
+
+ const emptyState = wrapper.findByText((_content, element) => element.textContent === text);
+
+ expect(emptyState.exists()).toBe(false);
+ });
+ });
+
+ describe('deploy boards', () => {
+ it('should show a deploy board if the environment has a rollout status', async () => {
+ const environment = {
+ ...resolvedEnvironment,
+ rolloutStatus,
+ };
+
+ wrapper = createWrapper({
+ propsData: { environment },
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = wrapper.findComponent(DeployBoardWrapper);
+ expect(deployBoard.exists()).toBe(true);
+ expect(deployBoard.props('rolloutStatus')).toBe(rolloutStatus);
+ });
+
+ it('should not show a deploy board if the environment has no rollout status', async () => {
+ wrapper = createWrapper({
+ apolloProvider: createApolloProvider(),
+ });
+
+ await expandCollapsedSection();
+
+ const deployBoard = wrapper.findComponent(DeployBoardWrapper);
+ expect(deployBoard.exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/environments/new_environments_app_spec.js b/spec/frontend/environments/new_environments_app_spec.js
index c9eccc26694..42e3608109b 100644
--- a/spec/frontend/environments/new_environments_app_spec.js
+++ b/spec/frontend/environments/new_environments_app_spec.js
@@ -10,6 +10,7 @@ import EnvironmentsApp from '~/environments/components/new_environments_app.vue'
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
import EnvironmentsItem from '~/environments/components/new_environment_item.vue';
import StopEnvironmentModal from '~/environments/components/stop_environment_modal.vue';
+import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
import { resolvedEnvironmentsApp, resolvedFolder, resolvedEnvironment } from './graphql/mock_data';
Vue.use(VueApollo);
@@ -20,6 +21,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
let environmentFolderMock;
let paginationMock;
let environmentToStopMock;
+ let environmentToChangeCanaryMock;
+ let weightMock;
const createApolloProvider = () => {
const mockResolvers = {
@@ -28,6 +31,10 @@ describe('~/environments/components/new_environments_app.vue', () => {
folder: environmentFolderMock,
pageInfo: paginationMock,
environmentToStop: environmentToStopMock,
+ environmentToDelete: jest.fn().mockResolvedValue(resolvedEnvironment),
+ environmentToRollback: jest.fn().mockResolvedValue(resolvedEnvironment),
+ environmentToChangeCanary: environmentToChangeCanaryMock,
+ weight: weightMock,
},
};
@@ -40,6 +47,7 @@ describe('~/environments/components/new_environments_app.vue', () => {
newEnvironmentPath: '/environments/new',
canCreateEnvironment: true,
defaultBranchName: 'main',
+ helpPagePath: '/help',
...provide,
},
apolloProvider,
@@ -50,6 +58,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentsApp,
folder,
environmentToStop = {},
+ environmentToChangeCanary = {},
+ weight = 0,
pageInfo = {
total: 20,
perPage: 5,
@@ -64,6 +74,8 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentFolderMock.mockReturnValue(folder);
paginationMock.mockReturnValue(pageInfo);
environmentToStopMock.mockReturnValue(environmentToStop);
+ environmentToChangeCanaryMock.mockReturnValue(environmentToChangeCanary);
+ weightMock.mockReturnValue(weight);
const apolloProvider = createApolloProvider();
wrapper = createWrapper({ apolloProvider, provide });
@@ -75,11 +87,13 @@ describe('~/environments/components/new_environments_app.vue', () => {
environmentAppMock = jest.fn();
environmentFolderMock = jest.fn();
environmentToStopMock = jest.fn();
+ environmentToChangeCanaryMock = jest.fn();
+ weightMock = jest.fn();
paginationMock = jest.fn();
});
afterEach(() => {
- wrapper?.destroy();
+ wrapper.destroy();
});
it('should show all the folders that are fetched', async () => {
@@ -149,8 +163,6 @@ describe('~/environments/components/new_environments_app.vue', () => {
},
folder: resolvedFolder,
});
- await waitForPromises();
- await nextTick();
const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
expect(button.exists()).toBe(false);
@@ -206,6 +218,19 @@ describe('~/environments/components/new_environments_app.vue', () => {
expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
});
+
+ it('should pass the environment to change canary to the canary update modal', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ environmentToChangeCanary: resolvedEnvironment,
+ weight: 10,
+ });
+
+ const modal = wrapper.findComponent(CanaryUpdateModal);
+
+ expect(modal.props('environment')).toMatchObject(resolvedEnvironment);
+ });
});
describe('pagination', () => {