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:
authorRobert Speicher <rspeicher@gmail.com>2021-01-20 22:34:23 +0300
committerRobert Speicher <rspeicher@gmail.com>2021-01-20 22:34:23 +0300
commit6438df3a1e0fb944485cebf07976160184697d72 (patch)
tree00b09bfd170e77ae9391b1a2f5a93ef6839f2597 /spec/frontend/environments
parent42bcd54d971da7ef2854b896a7b34f4ef8601067 (diff)
Add latest changes from gitlab-org/gitlab@13-8-stable-eev13.8.0-rc42
Diffstat (limited to 'spec/frontend/environments')
-rw-r--r--spec/frontend/environments/canary_ingress_spec.js102
-rw-r--r--spec/frontend/environments/canary_update_modal_spec.js126
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js139
-rw-r--r--spec/frontend/environments/environment_actions_spec.js4
-rw-r--r--spec/frontend/environments/environment_monitoring_spec.js3
-rw-r--r--spec/frontend/environments/environment_table_spec.js128
-rw-r--r--spec/frontend/environments/environment_terminal_button_spec.js2
-rw-r--r--spec/frontend/environments/environments_app_spec.js32
-rw-r--r--spec/frontend/environments/environments_folder_view_spec.js59
-rw-r--r--spec/frontend/environments/environments_store_spec.js56
-rw-r--r--spec/frontend/environments/folder/environments_folder_view_spec.js4
-rw-r--r--spec/frontend/environments/mock_data.js41
12 files changed, 680 insertions, 16 deletions
diff --git a/spec/frontend/environments/canary_ingress_spec.js b/spec/frontend/environments/canary_ingress_spec.js
new file mode 100644
index 00000000000..3dd67de1369
--- /dev/null
+++ b/spec/frontend/environments/canary_ingress_spec.js
@@ -0,0 +1,102 @@
+import { mount } from '@vue/test-utils';
+import { GlDropdownItem } from '@gitlab/ui';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { CANARY_UPDATE_MODAL } from '~/environments/constants';
+import CanaryIngress from '~/environments/components/canary_ingress.vue';
+
+describe('/environments/components/canary_ingress.vue', () => {
+ let wrapper;
+
+ const setWeightTo = (weightWrapper, x) =>
+ weightWrapper
+ .findAll(GlDropdownItem)
+ .at(x / 5)
+ .vm.$emit('click');
+
+ const createComponent = () => {
+ wrapper = mount(CanaryIngress, {
+ propsData: {
+ canaryIngress: {
+ canary_weight: 60,
+ },
+ },
+ directives: {
+ GlModal: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+
+ wrapper = null;
+ });
+
+ describe('stable weight', () => {
+ let stableWeightDropdown;
+
+ beforeEach(() => {
+ stableWeightDropdown = wrapper.find('[data-testid="stable-weight"]');
+ });
+
+ it('displays the current stable weight', () => {
+ expect(stableWeightDropdown.props('text')).toBe('40');
+ });
+
+ it('emits a change with the new canary weight', () => {
+ setWeightTo(stableWeightDropdown, 15);
+
+ expect(wrapper.emitted('change')).toContainEqual([85]);
+ });
+
+ it('lists options from 0 to 100 in increments of 5', () => {
+ const options = stableWeightDropdown.findAll(GlDropdownItem);
+ expect(options).toHaveLength(21);
+ options.wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ });
+
+ it('is set to open the change modal', () => {
+ stableWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w) =>
+ expect(getBinding(w.element, 'gl-modal')).toMatchObject({ value: CANARY_UPDATE_MODAL }),
+ );
+ });
+ });
+
+ describe('canary weight', () => {
+ let canaryWeightDropdown;
+
+ beforeEach(() => {
+ canaryWeightDropdown = wrapper.find('[data-testid="canary-weight"]');
+ });
+
+ it('displays the current canary weight', () => {
+ expect(canaryWeightDropdown.props('text')).toBe('60');
+ });
+
+ it('emits a change with the new canary weight', () => {
+ setWeightTo(canaryWeightDropdown, 15);
+
+ expect(wrapper.emitted('change')).toContainEqual([15]);
+ });
+
+ it('lists options from 0 to 100 in increments of 5', () => {
+ canaryWeightDropdown
+ .findAll(GlDropdownItem)
+ .wrappers.forEach((w, i) => expect(w.text()).toBe((i * 5).toString()));
+ });
+
+ 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()));
+ });
+ });
+});
diff --git a/spec/frontend/environments/canary_update_modal_spec.js b/spec/frontend/environments/canary_update_modal_spec.js
new file mode 100644
index 00000000000..d0b97cf2eda
--- /dev/null
+++ b/spec/frontend/environments/canary_update_modal_spec.js
@@ -0,0 +1,126 @@
+import { mount } from '@vue/test-utils';
+import { GlAlert, GlModal } from '@gitlab/ui';
+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';
+
+describe('/environments/components/canary_update_modal.vue', () => {
+ let wrapper;
+ let modal;
+ let mutate;
+
+ const findAlert = () => wrapper.find(GlAlert);
+
+ const createComponent = () => {
+ mutate = jest.fn().mockResolvedValue();
+ wrapper = mount(CanaryUpdateModal, {
+ propsData: {
+ environment: {
+ name: 'staging',
+ global_id: 'gid://environments/staging',
+ },
+ weight: 60,
+ visible: true,
+ },
+ mocks: {
+ $apollo: { mutate },
+ },
+ });
+ modal = wrapper.find(GlModal);
+ };
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+
+ wrapper = null;
+ });
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('should bind the modal props', () => {
+ expect(modal.props()).toMatchObject({
+ modalId: 'confirm-canary-change',
+ actionPrimary: {
+ text: 'Change ratio',
+ attributes: [{ variant: 'info' }],
+ },
+ actionCancel: { text: 'Cancel' },
+ });
+ });
+
+ it('should display the new weights', () => {
+ expect(modal.text()).toContain('Stable: 40');
+ expect(modal.text()).toContain('Canary: 60');
+ });
+
+ it('should display the affected environment', () => {
+ expect(modal.text()).toContain(
+ 'You are changing the ratio of the canary rollout for staging compared to the stable deployment to:',
+ );
+ });
+
+ it('should update the weight on primary action', () => {
+ modal.vm.$emit('primary');
+
+ expect(mutate).toHaveBeenCalledWith({
+ mutation: updateCanaryIngress,
+ variables: {
+ input: {
+ id: 'gid://environments/staging',
+ weight: 60,
+ },
+ },
+ });
+ });
+
+ it('should do nothing on cancel', () => {
+ modal.vm.$emit('secondary');
+ expect(mutate).not.toHaveBeenCalled();
+ });
+
+ it('should not display an error if there was not one', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: [] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('should display an error if there was one', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().text()).toBe('error');
+ });
+
+ it('should display a generic error if there was a top-level one', async () => {
+ mutate.mockRejectedValue();
+ modal.vm.$emit('primary');
+
+ await waitForPromises();
+ await wrapper.vm.$nextTick();
+
+ expect(findAlert().text()).toBe('Something went wrong. Please try again later');
+ });
+
+ it('hides teh alert on dismiss', async () => {
+ mutate.mockResolvedValue({ data: { environmentsCanaryIngressUpdate: { errors: ['error'] } } });
+ modal.vm.$emit('primary');
+
+ await wrapper.vm.$nextTick();
+
+ const alert = findAlert();
+ alert.vm.$emit('dismiss');
+
+ await wrapper.vm.$nextTick();
+
+ expect(alert.exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
new file mode 100644
index 00000000000..dbef03f99d8
--- /dev/null
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -0,0 +1,139 @@
+import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
+import CanaryIngress from '~/environments/components/canary_ingress.vue';
+import { deployBoardMockData, environment } from './mock_data';
+
+const logsPath = `gitlab-org/gitlab-test/-/logs?environment_name=${environment.name}`;
+
+describe('Deploy Board', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) =>
+ mount(Vue.extend(DeployBoard), {
+ provide: { glFeatures: { canaryIngressWeightControl: true } },
+ propsData: {
+ deployBoardData: deployBoardMockData,
+ isLoading: false,
+ isEmpty: false,
+ logsPath,
+ ...props,
+ },
+ });
+
+ describe('with valid data', () => {
+ beforeEach((done) => {
+ wrapper = createComponent();
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render percentage with completion value provided', () => {
+ expect(wrapper.vm.$refs.percentage.innerText).toEqual(`${deployBoardMockData.completion}%`);
+ });
+
+ it('should render total instance count', () => {
+ const renderedTotal = wrapper.find('.deploy-board-instances-text');
+ const actualTotal = deployBoardMockData.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(deployBoardMockData.instances.length);
+ expect(
+ instances.at(1).classes(`deployment-instance-${deployBoardMockData.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(deployBoardMockData.rollback_url);
+ expect(buttons.at(1).attributes('href')).toEqual(deployBoardMockData.abort_url);
+ });
+
+ 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);
+
+ expect(tooltip.props('target')()).toBe(iconSpan.element);
+ expect(icon.props('name')).toBe('question');
+ });
+
+ it('renders the canary weight selector', () => {
+ const canary = wrapper.find(CanaryIngress);
+ expect(canary.exists()).toBe(true);
+ expect(canary.props('canaryIngress')).toEqual({ canary_weight: 50 });
+ });
+ });
+
+ describe('with empty state', () => {
+ beforeEach((done) => {
+ wrapper = createComponent({
+ deployBoardData: {},
+ isLoading: false,
+ isEmpty: true,
+ logsPath,
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render the empty state', () => {
+ expect(wrapper.find('.deploy-board-empty-state-svg svg')).toBeDefined();
+ expect(
+ wrapper.find('.deploy-board-empty-state-text .deploy-board-empty-state-title').text(),
+ ).toContain('Kubernetes deployment not found');
+ });
+ });
+
+ describe('with loading state', () => {
+ beforeEach((done) => {
+ wrapper = createComponent({
+ deployBoardData: {},
+ isLoading: true,
+ isEmpty: false,
+ logsPath,
+ });
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('should render loading spinner', () => {
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ });
+ });
+
+ describe('has legend component', () => {
+ let statuses = [];
+ beforeEach((done) => {
+ wrapper = createComponent({
+ isLoading: false,
+ isEmpty: false,
+ logsPath: environment.log_path,
+ deployBoardData: deployBoardMockData,
+ });
+ ({ statuses } = wrapper.vm);
+ wrapper.vm.$nextTick(done);
+ });
+
+ it('with all the possible statuses', () => {
+ const deployBoardLegend = wrapper.find('.deploy-board-legend');
+
+ expect(deployBoardLegend).toBeDefined();
+ expect(deployBoardLegend.findAll('a')).toHaveLength(Object.keys(statuses).length);
+ });
+
+ Object.keys(statuses).forEach((item) => {
+ it(`with ${item} text next to deployment instance icon`, () => {
+ expect(wrapper.find(`.deployment-instance-${item}`)).toBeDefined();
+ expect(wrapper.find(`.deployment-instance-${item} + .legend-text`).text()).toBe(
+ statuses[item].text,
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/environment_actions_spec.js b/spec/frontend/environments/environment_actions_spec.js
index cc5153d6eba..875a01c07ea 100644
--- a/spec/frontend/environments/environment_actions_spec.js
+++ b/spec/frontend/environments/environment_actions_spec.js
@@ -38,9 +38,9 @@ describe('EnvironmentActions Component', () => {
return createComponent({ actions: [scheduledJobAction, expiredJobAction] }, opts);
}
- const findDropdownItem = action => {
+ const findDropdownItem = (action) => {
const buttons = wrapper.findAll(GlDropdownItem);
- return buttons.filter(button => button.text().startsWith(action.name)).at(0);
+ return buttons.filter((button) => button.text().startsWith(action.name)).at(0);
};
afterEach(() => {
diff --git a/spec/frontend/environments/environment_monitoring_spec.js b/spec/frontend/environments/environment_monitoring_spec.js
index a73f49f1047..bbd49c04fb6 100644
--- a/spec/frontend/environments/environment_monitoring_spec.js
+++ b/spec/frontend/environments/environment_monitoring_spec.js
@@ -16,7 +16,8 @@ describe('Monitoring Component', () => {
};
const findButtons = () => wrapper.findAll(GlButton);
- const findButtonsByIcon = icon => findButtons().filter(button => button.props('icon') === icon);
+ const findButtonsByIcon = (icon) =>
+ findButtons().filter((button) => button.props('icon') === icon);
beforeEach(() => {
createWrapper();
diff --git a/spec/frontend/environments/environment_table_spec.js b/spec/frontend/environments/environment_table_spec.js
index b8ef40e2568..daef35bcf99 100644
--- a/spec/frontend/environments/environment_table_spec.js
+++ b/spec/frontend/environments/environment_table_spec.js
@@ -1,10 +1,11 @@
import { mount } from '@vue/test-utils';
import EnvironmentTable from '~/environments/components/environments_table.vue';
-import { folder } from './mock_data';
+import eventHub from '~/environments/event_hub';
+import DeployBoard from '~/environments/components/deploy_board.vue';
+import CanaryUpdateModal from '~/environments/components/canary_update_modal.vue';
+import { folder, deployBoardMockData } from './mock_data';
const eeOnlyProps = {
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
@@ -37,10 +38,127 @@ describe('Environment table', () => {
wrapper.destroy();
});
- it('Should render a table', () => {
+ it('Should render a table', async () => {
+ const mockItem = {
+ name: 'review',
+ folderName: 'review',
+ size: 3,
+ isFolder: true,
+ environment_path: 'url',
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
expect(wrapper.classes()).toContain('ci-table');
});
+ it('should render deploy board container when data is provided', async () => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ logs_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: deployBoardMockData,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canCreateDeployment: false,
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ expect(wrapper.find('.js-deploy-board-row').exists()).toBe(true);
+ expect(wrapper.find('.deploy-board-icon').exists()).toBe(true);
+ });
+
+ it('should toggle deploy board visibility when arrow is clicked', (done) => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: {
+ instances: [{ status: 'ready', tooltip: 'foo' }],
+ abort_url: 'url',
+ rollback_url: 'url',
+ completion: 100,
+ is_completed: true,
+ canary_ingress: { canary_weight: 60 },
+ },
+ isDeployBoardVisible: false,
+ };
+
+ eventHub.$on('toggleDeployBoard', (env) => {
+ expect(env.id).toEqual(mockItem.id);
+ done();
+ });
+
+ factory({
+ propsData: {
+ environments: [mockItem],
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ wrapper.find('.deploy-board-icon').trigger('click');
+ });
+
+ it('should set the enviornment to change and weight when a change canary weight event is recevied', async () => {
+ const mockItem = {
+ name: 'review',
+ size: 1,
+ environment_path: 'url',
+ logs_path: 'url',
+ id: 1,
+ hasDeployBoard: true,
+ deployBoardData: deployBoardMockData,
+ isDeployBoardVisible: true,
+ isLoadingDeployBoard: false,
+ isEmptyDeployBoard: false,
+ };
+
+ await factory({
+ propsData: {
+ environments: [mockItem],
+ canCreateDeployment: false,
+ canReadEnvironment: true,
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ },
+ });
+
+ wrapper.find(DeployBoard).vm.$emit('changeCanaryWeight', 40);
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(CanaryUpdateModal).props()).toMatchObject({
+ weight: 40,
+ environment: mockItem,
+ });
+ });
+
describe('sortEnvironments', () => {
it('should sort environments by last updated', () => {
const mockItems = [
@@ -266,7 +384,7 @@ describe('Environment table', () => {
},
});
- expect(wrapper.vm.sortedEnvironments.map(env => env.name)).toEqual([
+ expect(wrapper.vm.sortedEnvironments.map((env) => env.name)).toEqual([
review.name,
staging.name,
production.name,
diff --git a/spec/frontend/environments/environment_terminal_button_spec.js b/spec/frontend/environments/environment_terminal_button_spec.js
index 274186fbbd6..2475785a927 100644
--- a/spec/frontend/environments/environment_terminal_button_spec.js
+++ b/spec/frontend/environments/environment_terminal_button_spec.js
@@ -5,7 +5,7 @@ describe('Stop Component', () => {
let wrapper;
const terminalPath = '/path';
- const mountWithProps = props => {
+ const mountWithProps = (props) => {
wrapper = shallowMount(TerminalComponent, {
propsData: props,
});
diff --git a/spec/frontend/environments/environments_app_spec.js b/spec/frontend/environments/environments_app_spec.js
index bb114e31063..d6614e2fd2b 100644
--- a/spec/frontend/environments/environments_app_spec.js
+++ b/spec/frontend/environments/environments_app_spec.js
@@ -5,6 +5,7 @@ import EnableReviewAppModal from '~/environments/components/enable_review_app_mo
import Container from '~/environments/components/container.vue';
import EmptyState from '~/environments/components/empty_state.vue';
import EnvironmentsApp from '~/environments/components/environments_app.vue';
+import DeployBoard from '~/environments/components/deploy_board.vue';
import axios from '~/lib/utils/axios_utils';
import { environment, folder } from './mock_data';
@@ -18,8 +19,6 @@ describe('Environment', () => {
canReadEnvironment: true,
newEnvironmentPath: 'environments/new',
helpPagePath: 'help',
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
@@ -114,6 +113,35 @@ describe('Environment', () => {
expect(wrapper.vm.updateContent).toHaveBeenCalledTimes(0);
});
});
+
+ describe('deploy boards', () => {
+ beforeEach(() => {
+ const deployEnvironment = {
+ ...environment,
+ rollout_status: {
+ status: 'found',
+ },
+ };
+
+ mockRequest(200, {
+ environments: [deployEnvironment],
+ stopped_count: 1,
+ available_count: 0,
+ });
+
+ return createWrapper();
+ });
+
+ it('should render deploy boards', () => {
+ expect(wrapper.find(DeployBoard).exists()).toBe(true);
+ });
+
+ it('should render arrow to open deploy boards', () => {
+ expect(
+ wrapper.find('.deploy-board-icon [data-testid="chevron-down-icon"]').exists(),
+ ).toBe(true);
+ });
+ });
});
});
diff --git a/spec/frontend/environments/environments_folder_view_spec.js b/spec/frontend/environments/environments_folder_view_spec.js
new file mode 100644
index 00000000000..e4661d27872
--- /dev/null
+++ b/spec/frontend/environments/environments_folder_view_spec.js
@@ -0,0 +1,59 @@
+import { mount } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import EnvironmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
+import axios from '~/lib/utils/axios_utils';
+import { environmentsList } from './mock_data';
+
+describe('Environments Folder View', () => {
+ let mock;
+ let wrapper;
+
+ const mockData = {
+ endpoint: 'environments.json',
+ folderName: 'review',
+ canReadEnvironment: true,
+ cssContainerClass: 'container',
+ userCalloutsPath: '/callouts',
+ lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
+ helpCanaryDeploymentsPath: 'help/canary-deployments',
+ };
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ wrapper.destroy();
+ });
+
+ describe('successful request', () => {
+ beforeEach(() => {
+ mock.onGet(mockData.endpoint).reply(
+ 200,
+ {
+ environments: environmentsList,
+ stopped_count: 1,
+ available_count: 0,
+ },
+ {
+ 'X-nExt-pAge': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '20',
+ 'X-Total-Pages': '10',
+ },
+ );
+
+ wrapper = mount(EnvironmentsFolderViewComponent, { propsData: mockData });
+ return axios.waitForAll();
+ });
+
+ describe('deploy boards', () => {
+ it('should render arrow to open deploy boards', () => {
+ expect(wrapper.find('.folder-icon[data-testid="chevron-right-icon"]').exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/environments/environments_store_spec.js b/spec/frontend/environments/environments_store_spec.js
index 8abdbcbbe54..4a07281353f 100644
--- a/spec/frontend/environments/environments_store_spec.js
+++ b/spec/frontend/environments/environments_store_spec.js
@@ -1,5 +1,5 @@
import Store from '~/environments/stores/environments_store';
-import { environmentsList, serverData } from './mock_data';
+import { environmentsList, serverData, deployBoardMockData } from './mock_data';
describe('Store', () => {
let store;
@@ -160,4 +160,58 @@ describe('Store', () => {
expect(store.getOpenFolders()[0]).toEqual(store.state.environments[1]);
});
});
+
+ it('should store a non folder environment with deploy board if rollout_status key is provided', () => {
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ rollout_status: deployBoardMockData,
+ },
+ };
+
+ store.storeEnvironments([environment]);
+
+ expect(store.state.environments[0].hasDeployBoard).toEqual(true);
+ expect(store.state.environments[0].isDeployBoardVisible).toEqual(true);
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+ });
+
+ describe('deploy boards', () => {
+ beforeEach(() => {
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ },
+ rollout_status: deployBoardMockData,
+ };
+
+ store.storeEnvironments([environment]);
+ });
+
+ it('should toggle deploy board property for given environment id', () => {
+ store.toggleDeployBoard(1);
+
+ expect(store.state.environments[0].isDeployBoardVisible).toEqual(false);
+ });
+
+ it('should keep deploy board data when updating environments', () => {
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+
+ const environment = {
+ name: 'foo',
+ size: 1,
+ latest: {
+ id: 1,
+ },
+ rollout_status: deployBoardMockData,
+ };
+ store.storeEnvironments([environment]);
+
+ expect(store.state.environments[0].deployBoardData).toEqual(deployBoardMockData);
+ });
+ });
});
diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js
index f55cb851dde..3943e89c6cf 100644
--- a/spec/frontend/environments/folder/environments_folder_view_spec.js
+++ b/spec/frontend/environments/folder/environments_folder_view_spec.js
@@ -16,14 +16,12 @@ describe('Environments Folder View', () => {
folderName: 'review',
canReadEnvironment: true,
cssContainerClass: 'container',
- canaryDeploymentFeatureId: 'canary_deployment',
- showCanaryDeploymentCallout: true,
userCalloutsPath: '/callouts',
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
helpCanaryDeploymentsPath: 'help/canary-deployments',
};
- const mockEnvironments = environmentList => {
+ const mockEnvironments = (environmentList) => {
mock.onGet(mockData.endpoint).reply(
200,
{
diff --git a/spec/frontend/environments/mock_data.js b/spec/frontend/environments/mock_data.js
index e7b99c8688c..4ad005f55c3 100644
--- a/spec/frontend/environments/mock_data.js
+++ b/spec/frontend/environments/mock_data.js
@@ -26,6 +26,45 @@ const buildProps = {
updated_at: '2017-02-01T19:42:18.400Z',
};
+const deployBoardMockData = {
+ instances: [
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2334 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2335 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2336 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2337 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2338 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2339 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'finished', tooltip: 'tanuki-2340 Finished', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2341 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2342 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'deploying', tooltip: 'tanuki-2343 Deploying', pod_name: 'production-tanuki-1' },
+ { status: 'failed', tooltip: 'tanuki-2344 Failed', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2345 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'ready', tooltip: 'tanuki-2346 Ready', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2348 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2349 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2350 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'preparing', tooltip: 'tanuki-2353 Preparing', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2354 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2355 Waiting', pod_name: 'production-tanuki-1' },
+ { status: 'waiting', tooltip: 'tanuki-2356 Waiting', pod_name: 'production-tanuki-1' },
+ ],
+ abort_url: 'url',
+ rollback_url: 'url',
+ completion: 100,
+ status: 'found',
+ canary_ingress: {
+ canary_weight: 50,
+ },
+};
+
const environment = {
name: 'production',
size: 1,
@@ -262,4 +301,4 @@ const tableData = {
},
};
-export { environment, environmentsList, folder, serverData, tableData };
+export { environment, environmentsList, folder, serverData, tableData, deployBoardMockData };