From 366a3be38e79ca1dde5daf045985c2baf90eb66e Mon Sep 17 00:00:00 2001 From: Enrique Alcantara Date: Mon, 26 Aug 2019 10:56:20 -0400 Subject: Move gke_cluster_dropdowns to create_cluster dir This commit creates a create_cluster directory to collect all Vue applications related to creating kubernetes applications using gitlab. It also moves the gke_cluster_dropdowns collection of apps to the create_cluster directory. gke_cluster_dropdowns contains dropdown components used to select configuration options to create a Kubernetes cluster in Google Cloud. --- .../gke_cluster/components/gke_dropdown_mixin.js | 71 ++++++++ .../components/gke_machine_type_dropdown.vue | 129 ++++++++++++++ .../components/gke_project_id_dropdown.vue | 188 +++++++++++++++++++++ .../gke_cluster/components/gke_zone_dropdown.vue | 103 +++++++++++ .../create_cluster/gke_cluster/constants.js | 11 ++ .../create_cluster/gke_cluster/index.js | 88 ++++++++++ .../create_cluster/gke_cluster/store/actions.js | 95 +++++++++++ .../create_cluster/gke_cluster/store/getters.js | 3 + .../create_cluster/gke_cluster/store/index.js | 18 ++ .../gke_cluster/store/mutation_types.js | 8 + .../create_cluster/gke_cluster/store/mutations.js | 28 +++ .../create_cluster/gke_cluster/store/state.js | 13 ++ .../javascripts/pages/admin/clusters/index.js | 2 +- app/assets/javascripts/pages/groups/index.js | 2 +- app/assets/javascripts/pages/projects/index.js | 2 +- .../components/gke_dropdown_mixin.js | 71 -------- .../components/gke_machine_type_dropdown.vue | 129 -------------- .../components/gke_project_id_dropdown.vue | 188 --------------------- .../components/gke_zone_dropdown.vue | 103 ----------- .../projects/gke_cluster_dropdowns/constants.js | 11 -- .../projects/gke_cluster_dropdowns/index.js | 88 ---------- .../gke_cluster_dropdowns/store/actions.js | 95 ----------- .../gke_cluster_dropdowns/store/getters.js | 3 - .../projects/gke_cluster_dropdowns/store/index.js | 18 -- .../gke_cluster_dropdowns/store/mutation_types.js | 8 - .../gke_cluster_dropdowns/store/mutations.js | 28 --- .../projects/gke_cluster_dropdowns/store/state.js | 13 -- .../components/gke_machine_type_dropdown_spec.js | 109 ++++++++++++ .../components/gke_project_id_dropdown_spec.js | 104 ++++++++++++ .../components/gke_zone_dropdown_spec.js | 94 +++++++++++ .../create_cluster/gke_cluster/helpers.js | 49 ++++++ .../create_cluster/gke_cluster/mock_data.js | 75 ++++++++ .../gke_cluster/stores/actions_spec.js | 131 ++++++++++++++ .../gke_cluster/stores/getters_spec.js | 65 +++++++ .../gke_cluster/stores/mutations_spec.js | 87 ++++++++++ .../components/gke_machine_type_dropdown_spec.js | 109 ------------ .../components/gke_project_id_dropdown_spec.js | 104 ------------ .../components/gke_zone_dropdown_spec.js | 94 ----------- .../projects/gke_cluster_dropdowns/helpers.js | 49 ------ .../projects/gke_cluster_dropdowns/mock_data.js | 75 -------- .../gke_cluster_dropdowns/stores/actions_spec.js | 131 -------------- .../gke_cluster_dropdowns/stores/getters_spec.js | 65 ------- .../gke_cluster_dropdowns/stores/mutations_spec.js | 87 ---------- 43 files changed, 1472 insertions(+), 1472 deletions(-) create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/constants.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/index.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/actions.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/getters.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/index.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js create mode 100644 app/assets/javascripts/create_cluster/gke_cluster/store/state.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/index.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js delete mode 100644 app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/helpers.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/mock_data.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/stores/actions_spec.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/stores/getters_spec.js create mode 100644 spec/javascripts/create_cluster/gke_cluster/stores/mutations_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/helpers.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/mock_data.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/stores/actions_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/stores/getters_spec.js delete mode 100644 spec/javascripts/projects/gke_cluster_dropdowns/stores/mutations_spec.js diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js new file mode 100644 index 00000000000..5a3407693e5 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_dropdown_mixin.js @@ -0,0 +1,71 @@ +import _ from 'underscore'; +import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue'; +import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue'; +import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue'; +import { GlLoadingIcon } from '@gitlab/ui'; + +import store from '../store'; + +export default { + store, + components: { + DropdownButton, + DropdownSearchInput, + DropdownHiddenInput, + GlLoadingIcon, + }, + props: { + fieldId: { + type: String, + required: true, + }, + fieldName: { + type: String, + required: true, + }, + defaultValue: { + type: String, + required: false, + default: '', + }, + }, + data() { + return { + isLoading: false, + hasErrors: false, + searchQuery: '', + gapiError: '', + }; + }, + computed: { + results() { + if (!this.items) { + return []; + } + + return this.items.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1); + }, + }, + methods: { + fetchSuccessHandler() { + if (this.defaultValue) { + const itemToSelect = _.find(this.items, item => item.name === this.defaultValue); + + if (itemToSelect) { + this.setItem(itemToSelect.name); + } + } + + this.isLoading = false; + this.hasErrors = false; + }, + fetchFailureHandler(resp) { + this.isLoading = false; + this.hasErrors = true; + + if (resp.result && resp.result.error) { + this.gapiError = resp.result.error.message; + } + }, + }, +}; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue new file mode 100644 index 00000000000..83811ab489a --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue @@ -0,0 +1,129 @@ + + + diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue new file mode 100644 index 00000000000..a2eb79af4f9 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue @@ -0,0 +1,188 @@ + + + diff --git a/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue new file mode 100644 index 00000000000..fd5d5f86401 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown.vue @@ -0,0 +1,103 @@ + + + diff --git a/app/assets/javascripts/create_cluster/gke_cluster/constants.js b/app/assets/javascripts/create_cluster/gke_cluster/constants.js new file mode 100644 index 00000000000..2a1c0819916 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/constants.js @@ -0,0 +1,11 @@ +import { s__ } from '~/locale'; + +export const GCP_API_ERROR = s__( + 'ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later.', +); +export const GCP_API_CLOUD_BILLING_ENDPOINT = + 'https://www.googleapis.com/discovery/v1/apis/cloudbilling/v1/rest'; +export const GCP_API_CLOUD_RESOURCE_MANAGER_ENDPOINT = + 'https://www.googleapis.com/discovery/v1/apis/cloudresourcemanager/v1/rest'; +export const GCP_API_COMPUTE_ENDPOINT = + 'https://www.googleapis.com/discovery/v1/apis/compute/v1/rest'; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/index.js b/app/assets/javascripts/create_cluster/gke_cluster/index.js new file mode 100644 index 00000000000..729b9404b64 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/index.js @@ -0,0 +1,88 @@ +/* global gapi */ +import Vue from 'vue'; +import Flash from '~/flash'; +import GkeProjectIdDropdown from './components/gke_project_id_dropdown.vue'; +import GkeZoneDropdown from './components/gke_zone_dropdown.vue'; +import GkeMachineTypeDropdown from './components/gke_machine_type_dropdown.vue'; +import * as CONSTANTS from './constants'; + +const mountComponent = (entryPoint, component, componentName, extraProps = {}) => { + const el = document.querySelector(entryPoint); + if (!el) return false; + + const hiddenInput = el.querySelector('input'); + + return new Vue({ + el, + components: { + [componentName]: component, + }, + render: createElement => + createElement(componentName, { + props: { + fieldName: hiddenInput.getAttribute('name'), + fieldId: hiddenInput.getAttribute('id'), + defaultValue: hiddenInput.value, + ...extraProps, + }, + }), + }); +}; + +const mountGkeProjectIdDropdown = () => { + const entryPoint = '.js-gcp-project-id-dropdown-entry-point'; + const el = document.querySelector(entryPoint); + + mountComponent(entryPoint, GkeProjectIdDropdown, 'gke-project-id-dropdown', { + docsUrl: el.dataset.docsurl, + }); +}; + +const mountGkeZoneDropdown = () => { + mountComponent('.js-gcp-zone-dropdown-entry-point', GkeZoneDropdown, 'gke-zone-dropdown'); +}; + +const mountGkeMachineTypeDropdown = () => { + mountComponent( + '.js-gcp-machine-type-dropdown-entry-point', + GkeMachineTypeDropdown, + 'gke-machine-type-dropdown', + ); +}; + +const gkeDropdownErrorHandler = () => { + Flash(CONSTANTS.GCP_API_ERROR); +}; + +const initializeGapiClient = () => { + const el = document.querySelector('.js-gke-cluster-creation'); + if (!el) return false; + + return gapi.client + .init({ + discoveryDocs: [ + CONSTANTS.GCP_API_CLOUD_BILLING_ENDPOINT, + CONSTANTS.GCP_API_CLOUD_RESOURCE_MANAGER_ENDPOINT, + CONSTANTS.GCP_API_COMPUTE_ENDPOINT, + ], + }) + .then(() => { + gapi.client.setToken({ access_token: el.dataset.token }); + + mountGkeProjectIdDropdown(); + mountGkeZoneDropdown(); + mountGkeMachineTypeDropdown(); + }) + .catch(gkeDropdownErrorHandler); +}; + +const initGkeDropdowns = () => { + if (!gapi) { + gkeDropdownErrorHandler(); + return false; + } + + return gapi.load('client', initializeGapiClient); +}; + +export default initGkeDropdowns; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js new file mode 100644 index 00000000000..f05ad7773a2 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/actions.js @@ -0,0 +1,95 @@ +/* global gapi */ +import * as types from './mutation_types'; + +const gapiResourceListRequest = ({ resource, params, commit, mutation, payloadKey }) => + new Promise((resolve, reject) => { + const request = resource.list(params); + + return request.then( + resp => { + const { result } = resp; + + commit(mutation, result[payloadKey]); + + resolve(); + }, + resp => { + reject(resp); + }, + ); + }); + +export const setProject = ({ commit }, selectedProject) => { + commit(types.SET_PROJECT, selectedProject); +}; + +export const setZone = ({ commit }, selectedZone) => { + commit(types.SET_ZONE, selectedZone); +}; + +export const setMachineType = ({ commit }, selectedMachineType) => { + commit(types.SET_MACHINE_TYPE, selectedMachineType); +}; + +export const setIsValidatingProjectBilling = ({ commit }, isValidatingProjectBilling) => { + commit(types.SET_IS_VALIDATING_PROJECT_BILLING, isValidatingProjectBilling); +}; + +export const fetchProjects = ({ commit }) => + gapiResourceListRequest({ + resource: gapi.client.cloudresourcemanager.projects, + params: {}, + commit, + mutation: types.SET_PROJECTS, + payloadKey: 'projects', + }); + +export const validateProjectBilling = ({ dispatch, commit, state }) => + new Promise((resolve, reject) => { + const request = gapi.client.cloudbilling.projects.getBillingInfo({ + name: `projects/${state.selectedProject.projectId}`, + }); + + commit(types.SET_ZONE, ''); + commit(types.SET_MACHINE_TYPE, ''); + + return request.then( + resp => { + const { billingEnabled } = resp.result; + + commit(types.SET_PROJECT_BILLING_STATUS, Boolean(billingEnabled)); + dispatch('setIsValidatingProjectBilling', false); + resolve(); + }, + resp => { + dispatch('setIsValidatingProjectBilling', false); + reject(resp); + }, + ); + }); + +export const fetchZones = ({ commit, state }) => + gapiResourceListRequest({ + resource: gapi.client.compute.zones, + params: { + project: state.selectedProject.projectId, + }, + commit, + mutation: types.SET_ZONES, + payloadKey: 'items', + }); + +export const fetchMachineTypes = ({ commit, state }) => + gapiResourceListRequest({ + resource: gapi.client.compute.machineTypes, + params: { + project: state.selectedProject.projectId, + zone: state.selectedZone, + }, + commit, + mutation: types.SET_MACHINE_TYPES, + payloadKey: 'items', + }); + +// prevent babel-plugin-rewire from generating an invalid default during karma tests +export default () => {}; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js new file mode 100644 index 00000000000..f9e2e2f74fb --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/getters.js @@ -0,0 +1,3 @@ +export const hasProject = state => Boolean(state.selectedProject.projectId); +export const hasZone = state => Boolean(state.selectedZone); +export const hasMachineType = state => Boolean(state.selectedMachineType); diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/index.js b/app/assets/javascripts/create_cluster/gke_cluster/store/index.js new file mode 100644 index 00000000000..5f72060633e --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/index.js @@ -0,0 +1,18 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; +import * as actions from './actions'; +import * as getters from './getters'; +import mutations from './mutations'; +import createState from './state'; + +Vue.use(Vuex); + +export const createStore = () => + new Vuex.Store({ + actions, + getters, + mutations, + state: createState(), + }); + +export default createStore(); diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js b/app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js new file mode 100644 index 00000000000..45a91efc2d9 --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/mutation_types.js @@ -0,0 +1,8 @@ +export const SET_PROJECT = 'SET_PROJECT'; +export const SET_PROJECT_BILLING_STATUS = 'SET_PROJECT_BILLING_STATUS'; +export const SET_IS_VALIDATING_PROJECT_BILLING = 'SET_IS_VALIDATING_PROJECT_BILLING'; +export const SET_ZONE = 'SET_ZONE'; +export const SET_MACHINE_TYPE = 'SET_MACHINE_TYPE'; +export const SET_PROJECTS = 'SET_PROJECTS'; +export const SET_ZONES = 'SET_ZONES'; +export const SET_MACHINE_TYPES = 'SET_MACHINE_TYPES'; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js b/app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js new file mode 100644 index 00000000000..88a2c1b630d --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/mutations.js @@ -0,0 +1,28 @@ +import * as types from './mutation_types'; + +export default { + [types.SET_PROJECT](state, selectedProject) { + Object.assign(state, { selectedProject }); + }, + [types.SET_IS_VALIDATING_PROJECT_BILLING](state, isValidatingProjectBilling) { + Object.assign(state, { isValidatingProjectBilling }); + }, + [types.SET_PROJECT_BILLING_STATUS](state, projectHasBillingEnabled) { + Object.assign(state, { projectHasBillingEnabled }); + }, + [types.SET_ZONE](state, selectedZone) { + Object.assign(state, { selectedZone }); + }, + [types.SET_MACHINE_TYPE](state, selectedMachineType) { + Object.assign(state, { selectedMachineType }); + }, + [types.SET_PROJECTS](state, projects) { + Object.assign(state, { projects }); + }, + [types.SET_ZONES](state, zones) { + Object.assign(state, { zones }); + }, + [types.SET_MACHINE_TYPES](state, machineTypes) { + Object.assign(state, { machineTypes }); + }, +}; diff --git a/app/assets/javascripts/create_cluster/gke_cluster/store/state.js b/app/assets/javascripts/create_cluster/gke_cluster/store/state.js new file mode 100644 index 00000000000..9f3c473d4bc --- /dev/null +++ b/app/assets/javascripts/create_cluster/gke_cluster/store/state.js @@ -0,0 +1,13 @@ +export default () => ({ + selectedProject: { + projectId: '', + name: '', + }, + selectedZone: '', + selectedMachineType: '', + isValidatingProjectBilling: null, + projectHasBillingEnabled: null, + projects: [], + zones: [], + machineTypes: [], +}); diff --git a/app/assets/javascripts/pages/admin/clusters/index.js b/app/assets/javascripts/pages/admin/clusters/index.js index d0c9ae66c6a..43992938d07 100644 --- a/app/assets/javascripts/pages/admin/clusters/index.js +++ b/app/assets/javascripts/pages/admin/clusters/index.js @@ -1,5 +1,5 @@ import PersistentUserCallout from '~/persistent_user_callout'; -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; function initGcpSignupCallout() { const callout = document.querySelector('.gcp-signup-offer'); diff --git a/app/assets/javascripts/pages/groups/index.js b/app/assets/javascripts/pages/groups/index.js index 451be6497de..a33d242908b 100644 --- a/app/assets/javascripts/pages/groups/index.js +++ b/app/assets/javascripts/pages/groups/index.js @@ -1,5 +1,5 @@ import PersistentUserCallout from '~/persistent_user_callout'; -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; function initGcpSignupCallout() { const callout = document.querySelector('.gcp-signup-offer'); diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js index 55c377ebec0..196798a9076 100644 --- a/app/assets/javascripts/pages/projects/index.js +++ b/app/assets/javascripts/pages/projects/index.js @@ -1,4 +1,4 @@ -import initGkeDropdowns from '~/projects/gke_cluster_dropdowns'; +import initGkeDropdowns from '~/create_cluster/gke_cluster'; import initGkeNamespace from '~/projects/gke_cluster_namespace'; import PersistentUserCallout from '../../persistent_user_callout'; import Project from './project'; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js deleted file mode 100644 index 5a3407693e5..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_dropdown_mixin.js +++ /dev/null @@ -1,71 +0,0 @@ -import _ from 'underscore'; -import DropdownSearchInput from '~/vue_shared/components/dropdown/dropdown_search_input.vue'; -import DropdownHiddenInput from '~/vue_shared/components/dropdown/dropdown_hidden_input.vue'; -import DropdownButton from '~/vue_shared/components/dropdown/dropdown_button.vue'; -import { GlLoadingIcon } from '@gitlab/ui'; - -import store from '../store'; - -export default { - store, - components: { - DropdownButton, - DropdownSearchInput, - DropdownHiddenInput, - GlLoadingIcon, - }, - props: { - fieldId: { - type: String, - required: true, - }, - fieldName: { - type: String, - required: true, - }, - defaultValue: { - type: String, - required: false, - default: '', - }, - }, - data() { - return { - isLoading: false, - hasErrors: false, - searchQuery: '', - gapiError: '', - }; - }, - computed: { - results() { - if (!this.items) { - return []; - } - - return this.items.filter(item => item.name.toLowerCase().indexOf(this.searchQuery) > -1); - }, - }, - methods: { - fetchSuccessHandler() { - if (this.defaultValue) { - const itemToSelect = _.find(this.items, item => item.name === this.defaultValue); - - if (itemToSelect) { - this.setItem(itemToSelect.name); - } - } - - this.isLoading = false; - this.hasErrors = false; - }, - fetchFailureHandler(resp) { - this.isLoading = false; - this.hasErrors = true; - - if (resp.result && resp.result.error) { - this.gapiError = resp.result.error.message; - } - }, - }, -}; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue deleted file mode 100644 index 83811ab489a..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue +++ /dev/null @@ -1,129 +0,0 @@ - - - diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue deleted file mode 100644 index a2eb79af4f9..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue +++ /dev/null @@ -1,188 +0,0 @@ - - - diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue b/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue deleted file mode 100644 index fd5d5f86401..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue +++ /dev/null @@ -1,103 +0,0 @@ - - - diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js deleted file mode 100644 index 2a1c0819916..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/constants.js +++ /dev/null @@ -1,11 +0,0 @@ -import { s__ } from '~/locale'; - -export const GCP_API_ERROR = s__( - 'ClusterIntegration|An error occurred when trying to contact the Google Cloud API. Please try again later.', -); -export const GCP_API_CLOUD_BILLING_ENDPOINT = - 'https://www.googleapis.com/discovery/v1/apis/cloudbilling/v1/rest'; -export const GCP_API_CLOUD_RESOURCE_MANAGER_ENDPOINT = - 'https://www.googleapis.com/discovery/v1/apis/cloudresourcemanager/v1/rest'; -export const GCP_API_COMPUTE_ENDPOINT = - 'https://www.googleapis.com/discovery/v1/apis/compute/v1/rest'; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/index.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/index.js deleted file mode 100644 index 729b9404b64..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/index.js +++ /dev/null @@ -1,88 +0,0 @@ -/* global gapi */ -import Vue from 'vue'; -import Flash from '~/flash'; -import GkeProjectIdDropdown from './components/gke_project_id_dropdown.vue'; -import GkeZoneDropdown from './components/gke_zone_dropdown.vue'; -import GkeMachineTypeDropdown from './components/gke_machine_type_dropdown.vue'; -import * as CONSTANTS from './constants'; - -const mountComponent = (entryPoint, component, componentName, extraProps = {}) => { - const el = document.querySelector(entryPoint); - if (!el) return false; - - const hiddenInput = el.querySelector('input'); - - return new Vue({ - el, - components: { - [componentName]: component, - }, - render: createElement => - createElement(componentName, { - props: { - fieldName: hiddenInput.getAttribute('name'), - fieldId: hiddenInput.getAttribute('id'), - defaultValue: hiddenInput.value, - ...extraProps, - }, - }), - }); -}; - -const mountGkeProjectIdDropdown = () => { - const entryPoint = '.js-gcp-project-id-dropdown-entry-point'; - const el = document.querySelector(entryPoint); - - mountComponent(entryPoint, GkeProjectIdDropdown, 'gke-project-id-dropdown', { - docsUrl: el.dataset.docsurl, - }); -}; - -const mountGkeZoneDropdown = () => { - mountComponent('.js-gcp-zone-dropdown-entry-point', GkeZoneDropdown, 'gke-zone-dropdown'); -}; - -const mountGkeMachineTypeDropdown = () => { - mountComponent( - '.js-gcp-machine-type-dropdown-entry-point', - GkeMachineTypeDropdown, - 'gke-machine-type-dropdown', - ); -}; - -const gkeDropdownErrorHandler = () => { - Flash(CONSTANTS.GCP_API_ERROR); -}; - -const initializeGapiClient = () => { - const el = document.querySelector('.js-gke-cluster-creation'); - if (!el) return false; - - return gapi.client - .init({ - discoveryDocs: [ - CONSTANTS.GCP_API_CLOUD_BILLING_ENDPOINT, - CONSTANTS.GCP_API_CLOUD_RESOURCE_MANAGER_ENDPOINT, - CONSTANTS.GCP_API_COMPUTE_ENDPOINT, - ], - }) - .then(() => { - gapi.client.setToken({ access_token: el.dataset.token }); - - mountGkeProjectIdDropdown(); - mountGkeZoneDropdown(); - mountGkeMachineTypeDropdown(); - }) - .catch(gkeDropdownErrorHandler); -}; - -const initGkeDropdowns = () => { - if (!gapi) { - gkeDropdownErrorHandler(); - return false; - } - - return gapi.load('client', initializeGapiClient); -}; - -export default initGkeDropdowns; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js deleted file mode 100644 index f05ad7773a2..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/actions.js +++ /dev/null @@ -1,95 +0,0 @@ -/* global gapi */ -import * as types from './mutation_types'; - -const gapiResourceListRequest = ({ resource, params, commit, mutation, payloadKey }) => - new Promise((resolve, reject) => { - const request = resource.list(params); - - return request.then( - resp => { - const { result } = resp; - - commit(mutation, result[payloadKey]); - - resolve(); - }, - resp => { - reject(resp); - }, - ); - }); - -export const setProject = ({ commit }, selectedProject) => { - commit(types.SET_PROJECT, selectedProject); -}; - -export const setZone = ({ commit }, selectedZone) => { - commit(types.SET_ZONE, selectedZone); -}; - -export const setMachineType = ({ commit }, selectedMachineType) => { - commit(types.SET_MACHINE_TYPE, selectedMachineType); -}; - -export const setIsValidatingProjectBilling = ({ commit }, isValidatingProjectBilling) => { - commit(types.SET_IS_VALIDATING_PROJECT_BILLING, isValidatingProjectBilling); -}; - -export const fetchProjects = ({ commit }) => - gapiResourceListRequest({ - resource: gapi.client.cloudresourcemanager.projects, - params: {}, - commit, - mutation: types.SET_PROJECTS, - payloadKey: 'projects', - }); - -export const validateProjectBilling = ({ dispatch, commit, state }) => - new Promise((resolve, reject) => { - const request = gapi.client.cloudbilling.projects.getBillingInfo({ - name: `projects/${state.selectedProject.projectId}`, - }); - - commit(types.SET_ZONE, ''); - commit(types.SET_MACHINE_TYPE, ''); - - return request.then( - resp => { - const { billingEnabled } = resp.result; - - commit(types.SET_PROJECT_BILLING_STATUS, Boolean(billingEnabled)); - dispatch('setIsValidatingProjectBilling', false); - resolve(); - }, - resp => { - dispatch('setIsValidatingProjectBilling', false); - reject(resp); - }, - ); - }); - -export const fetchZones = ({ commit, state }) => - gapiResourceListRequest({ - resource: gapi.client.compute.zones, - params: { - project: state.selectedProject.projectId, - }, - commit, - mutation: types.SET_ZONES, - payloadKey: 'items', - }); - -export const fetchMachineTypes = ({ commit, state }) => - gapiResourceListRequest({ - resource: gapi.client.compute.machineTypes, - params: { - project: state.selectedProject.projectId, - zone: state.selectedZone, - }, - commit, - mutation: types.SET_MACHINE_TYPES, - payloadKey: 'items', - }); - -// prevent babel-plugin-rewire from generating an invalid default during karma tests -export default () => {}; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js deleted file mode 100644 index f9e2e2f74fb..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/getters.js +++ /dev/null @@ -1,3 +0,0 @@ -export const hasProject = state => Boolean(state.selectedProject.projectId); -export const hasZone = state => Boolean(state.selectedZone); -export const hasMachineType = state => Boolean(state.selectedMachineType); diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js deleted file mode 100644 index 5f72060633e..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/index.js +++ /dev/null @@ -1,18 +0,0 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; -import * as actions from './actions'; -import * as getters from './getters'; -import mutations from './mutations'; -import createState from './state'; - -Vue.use(Vuex); - -export const createStore = () => - new Vuex.Store({ - actions, - getters, - mutations, - state: createState(), - }); - -export default createStore(); diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js deleted file mode 100644 index 45a91efc2d9..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutation_types.js +++ /dev/null @@ -1,8 +0,0 @@ -export const SET_PROJECT = 'SET_PROJECT'; -export const SET_PROJECT_BILLING_STATUS = 'SET_PROJECT_BILLING_STATUS'; -export const SET_IS_VALIDATING_PROJECT_BILLING = 'SET_IS_VALIDATING_PROJECT_BILLING'; -export const SET_ZONE = 'SET_ZONE'; -export const SET_MACHINE_TYPE = 'SET_MACHINE_TYPE'; -export const SET_PROJECTS = 'SET_PROJECTS'; -export const SET_ZONES = 'SET_ZONES'; -export const SET_MACHINE_TYPES = 'SET_MACHINE_TYPES'; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js deleted file mode 100644 index 88a2c1b630d..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/mutations.js +++ /dev/null @@ -1,28 +0,0 @@ -import * as types from './mutation_types'; - -export default { - [types.SET_PROJECT](state, selectedProject) { - Object.assign(state, { selectedProject }); - }, - [types.SET_IS_VALIDATING_PROJECT_BILLING](state, isValidatingProjectBilling) { - Object.assign(state, { isValidatingProjectBilling }); - }, - [types.SET_PROJECT_BILLING_STATUS](state, projectHasBillingEnabled) { - Object.assign(state, { projectHasBillingEnabled }); - }, - [types.SET_ZONE](state, selectedZone) { - Object.assign(state, { selectedZone }); - }, - [types.SET_MACHINE_TYPE](state, selectedMachineType) { - Object.assign(state, { selectedMachineType }); - }, - [types.SET_PROJECTS](state, projects) { - Object.assign(state, { projects }); - }, - [types.SET_ZONES](state, zones) { - Object.assign(state, { zones }); - }, - [types.SET_MACHINE_TYPES](state, machineTypes) { - Object.assign(state, { machineTypes }); - }, -}; diff --git a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js b/app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js deleted file mode 100644 index 9f3c473d4bc..00000000000 --- a/app/assets/javascripts/projects/gke_cluster_dropdowns/store/state.js +++ /dev/null @@ -1,13 +0,0 @@ -export default () => ({ - selectedProject: { - projectId: '', - name: '', - }, - selectedZone: '', - selectedMachineType: '', - isValidatingProjectBilling: null, - projectHasBillingEnabled: null, - projects: [], - zones: [], - machineTypes: [], -}); diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js new file mode 100644 index 00000000000..7aa7aa9a112 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_machine_type_dropdown_spec.js @@ -0,0 +1,109 @@ +import Vue from 'vue'; +import GkeMachineTypeDropdown from '~/create_cluster/gke_cluster/components/gke_machine_type_dropdown.vue'; +import { createStore } from '~/create_cluster/gke_cluster/store'; +import { + SET_PROJECT, + SET_PROJECT_BILLING_STATUS, + SET_ZONE, + SET_MACHINE_TYPES, +} from '~/create_cluster/gke_cluster/store/mutation_types'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; +import { + selectedZoneMock, + selectedProjectMock, + selectedMachineTypeMock, + gapiMachineTypesResponseMock, +} from '../mock_data'; + +const componentConfig = { + fieldId: 'cluster_provider_gcp_attributes_gcp_machine_type', + fieldName: 'cluster[provider_gcp_attributes][gcp_machine_type]', +}; + +const LABELS = { + LOADING: 'Fetching machine types', + DISABLED_NO_PROJECT: 'Select project and zone to choose machine type', + DISABLED_NO_ZONE: 'Select zone to choose machine type', + DEFAULT: 'Select machine type', +}; + +const createComponent = (store, props = componentConfig) => { + const Component = Vue.extend(GkeMachineTypeDropdown); + + return mountComponentWithStore(Component, { + el: null, + props, + store, + }); +}; + +describe('GkeMachineTypeDropdown', () => { + let vm; + let store; + + beforeEach(() => { + store = createStore(); + vm = createComponent(store); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('shows various toggle text depending on state', () => { + it('returns disabled state toggle text when no project and zone are selected', () => { + expect(vm.toggleText).toBe(LABELS.DISABLED_NO_PROJECT); + }); + + it('returns disabled state toggle text when no zone is selected', () => { + vm.$store.commit(SET_PROJECT, selectedProjectMock); + vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); + + expect(vm.toggleText).toBe(LABELS.DISABLED_NO_ZONE); + }); + + it('returns loading toggle text', () => { + vm.isLoading = true; + + expect(vm.toggleText).toBe(LABELS.LOADING); + }); + + it('returns default toggle text', () => { + expect(vm.toggleText).toBe(LABELS.DISABLED_NO_PROJECT); + + vm.$store.commit(SET_PROJECT, selectedProjectMock); + vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); + vm.$store.commit(SET_ZONE, selectedZoneMock); + + expect(vm.toggleText).toBe(LABELS.DEFAULT); + }); + + it('returns machine type name if machine type selected', () => { + vm.setItem(selectedMachineTypeMock); + + expect(vm.toggleText).toBe(selectedMachineTypeMock); + }); + }); + + describe('form input', () => { + it('reflects new value when dropdown item is clicked', done => { + expect(vm.$el.querySelector('input').value).toBe(''); + vm.$store.commit(SET_MACHINE_TYPES, gapiMachineTypesResponseMock.items); + + return vm + .$nextTick() + .then(() => { + vm.$el.querySelector('.dropdown-content button').click(); + + return vm + .$nextTick() + .then(() => { + expect(vm.$el.querySelector('input').value).toBe(selectedMachineTypeMock); + done(); + }) + .catch(done.fail); + }) + .catch(done.fail); + }); + }); +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js new file mode 100644 index 00000000000..809da3f9088 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_project_id_dropdown_spec.js @@ -0,0 +1,104 @@ +import Vue from 'vue'; +import GkeProjectIdDropdown from '~/create_cluster/gke_cluster/components/gke_project_id_dropdown.vue'; +import { createStore } from '~/create_cluster/gke_cluster/store'; +import { SET_PROJECTS } from '~/create_cluster/gke_cluster/store/mutation_types'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; +import { emptyProjectMock, selectedProjectMock } from '../mock_data'; + +const componentConfig = { + docsUrl: 'https://console.cloud.google.com/home/dashboard', + fieldId: 'cluster_provider_gcp_attributes_gcp_project_id', + fieldName: 'cluster[provider_gcp_attributes][gcp_project_id]', +}; + +const LABELS = { + LOADING: 'Fetching projects', + VALIDATING_PROJECT_BILLING: 'Validating project billing status', + DEFAULT: 'Select project', + EMPTY: 'No projects found', +}; + +const createComponent = (store, props = componentConfig) => { + const Component = Vue.extend(GkeProjectIdDropdown); + + return mountComponentWithStore(Component, { + el: null, + props, + store, + }); +}; + +describe('GkeProjectIdDropdown', () => { + let vm; + let store; + + beforeEach(() => { + store = createStore(); + vm = createComponent(store); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('toggleText', () => { + it('returns loading toggle text', () => { + expect(vm.toggleText).toBe(LABELS.LOADING); + }); + + it('returns project billing validation text', () => { + vm.setIsValidatingProjectBilling(true); + + expect(vm.toggleText).toBe(LABELS.VALIDATING_PROJECT_BILLING); + }); + + it('returns default toggle text', done => + setTimeout(() => { + vm.setItem(emptyProjectMock); + + expect(vm.toggleText).toBe(LABELS.DEFAULT); + + done(); + })); + + it('returns project name if project selected', done => + setTimeout(() => { + vm.isLoading = false; + + expect(vm.toggleText).toBe(selectedProjectMock.name); + + done(); + })); + + it('returns empty toggle text', done => + setTimeout(() => { + vm.$store.commit(SET_PROJECTS, null); + vm.setItem(emptyProjectMock); + + expect(vm.toggleText).toBe(LABELS.EMPTY); + + done(); + })); + }); + + describe('selectItem', () => { + it('reflects new value when dropdown item is clicked', done => { + expect(vm.$el.querySelector('input').value).toBe(''); + + return vm + .$nextTick() + .then(() => { + vm.$el.querySelector('.dropdown-content button').click(); + + return vm + .$nextTick() + .then(() => { + expect(vm.$el.querySelector('input').value).toBe(selectedProjectMock.projectId); + done(); + }) + .catch(done.fail); + }) + .catch(done.fail); + }); + }); +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js b/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js new file mode 100644 index 00000000000..9cb9419e433 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/components/gke_zone_dropdown_spec.js @@ -0,0 +1,94 @@ +import Vue from 'vue'; +import GkeZoneDropdown from '~/create_cluster/gke_cluster/components/gke_zone_dropdown.vue'; +import { createStore } from '~/create_cluster/gke_cluster/store'; +import { + SET_PROJECT, + SET_ZONES, + SET_PROJECT_BILLING_STATUS, +} from '~/create_cluster/gke_cluster/store/mutation_types'; +import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; +import { selectedZoneMock, selectedProjectMock, gapiZonesResponseMock } from '../mock_data'; + +const componentConfig = { + fieldId: 'cluster_provider_gcp_attributes_gcp_zone', + fieldName: 'cluster[provider_gcp_attributes][gcp_zone]', +}; + +const LABELS = { + LOADING: 'Fetching zones', + DISABLED: 'Select project to choose zone', + DEFAULT: 'Select zone', +}; + +const createComponent = (store, props = componentConfig) => { + const Component = Vue.extend(GkeZoneDropdown); + + return mountComponentWithStore(Component, { + el: null, + props, + store, + }); +}; + +describe('GkeZoneDropdown', () => { + let vm; + let store; + + beforeEach(() => { + store = createStore(); + vm = createComponent(store); + }); + + afterEach(() => { + vm.$destroy(); + }); + + describe('toggleText', () => { + it('returns disabled state toggle text', () => { + expect(vm.toggleText).toBe(LABELS.DISABLED); + }); + + it('returns loading toggle text', () => { + vm.isLoading = true; + + expect(vm.toggleText).toBe(LABELS.LOADING); + }); + + it('returns default toggle text', () => { + expect(vm.toggleText).toBe(LABELS.DISABLED); + + vm.$store.commit(SET_PROJECT, selectedProjectMock); + vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); + + expect(vm.toggleText).toBe(LABELS.DEFAULT); + }); + + it('returns project name if project selected', () => { + vm.setItem(selectedZoneMock); + + expect(vm.toggleText).toBe(selectedZoneMock); + }); + }); + + describe('selectItem', () => { + it('reflects new value when dropdown item is clicked', done => { + expect(vm.$el.querySelector('input').value).toBe(''); + vm.$store.commit(SET_ZONES, gapiZonesResponseMock.items); + + return vm + .$nextTick() + .then(() => { + vm.$el.querySelector('.dropdown-content button').click(); + + return vm + .$nextTick() + .then(() => { + expect(vm.$el.querySelector('input').value).toBe(selectedZoneMock); + done(); + }) + .catch(done.fail); + }) + .catch(done.fail); + }); + }); +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/helpers.js b/spec/javascripts/create_cluster/gke_cluster/helpers.js new file mode 100644 index 00000000000..6df511e9157 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/helpers.js @@ -0,0 +1,49 @@ +import { + gapiProjectsResponseMock, + gapiZonesResponseMock, + gapiMachineTypesResponseMock, +} from './mock_data'; + +// eslint-disable-next-line import/prefer-default-export +export const gapi = () => ({ + client: { + cloudbilling: { + projects: { + getBillingInfo: () => + new Promise(resolve => { + resolve({ + result: { billingEnabled: true }, + }); + }), + }, + }, + cloudresourcemanager: { + projects: { + list: () => + new Promise(resolve => { + resolve({ + result: { ...gapiProjectsResponseMock }, + }); + }), + }, + }, + compute: { + zones: { + list: () => + new Promise(resolve => { + resolve({ + result: { ...gapiZonesResponseMock }, + }); + }), + }, + machineTypes: { + list: () => + new Promise(resolve => { + resolve({ + result: { ...gapiMachineTypesResponseMock }, + }); + }), + }, + }, + }, +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/mock_data.js b/spec/javascripts/create_cluster/gke_cluster/mock_data.js new file mode 100644 index 00000000000..d9f5dbc636f --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/mock_data.js @@ -0,0 +1,75 @@ +export const emptyProjectMock = { + projectId: '', + name: '', +}; + +export const selectedProjectMock = { + projectId: 'gcp-project-123', + name: 'gcp-project', +}; + +export const selectedZoneMock = 'us-central1-a'; + +export const selectedMachineTypeMock = 'n1-standard-2'; + +export const gapiProjectsResponseMock = { + projects: [ + { + projectNumber: '1234', + projectId: 'gcp-project-123', + lifecycleState: 'ACTIVE', + name: 'gcp-project', + createTime: '2017-12-16T01:48:29.129Z', + parent: { + type: 'organization', + id: '12345', + }, + }, + ], +}; + +export const gapiZonesResponseMock = { + kind: 'compute#zoneList', + id: 'projects/gitlab-internal-153318/zones', + items: [ + { + kind: 'compute#zone', + id: '2000', + creationTimestamp: '1969-12-31T16:00:00.000-08:00', + name: 'us-central1-a', + description: 'us-central1-a', + status: 'UP', + region: + 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/regions/us-central1', + selfLink: + 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a', + availableCpuPlatforms: ['Intel Skylake', 'Intel Broadwell', 'Intel Sandy Bridge'], + }, + ], + selfLink: 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones', +}; + +export const gapiMachineTypesResponseMock = { + kind: 'compute#machineTypeList', + id: 'projects/gitlab-internal-153318/zones/us-central1-a/machineTypes', + items: [ + { + kind: 'compute#machineType', + id: '3002', + creationTimestamp: '1969-12-31T16:00:00.000-08:00', + name: 'n1-standard-2', + description: '2 vCPUs, 7.5 GB RAM', + guestCpus: 2, + memoryMb: 7680, + imageSpaceGb: 10, + maximumPersistentDisks: 64, + maximumPersistentDisksSizeGb: '65536', + zone: 'us-central1-a', + selfLink: + 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a/machineTypes/n1-standard-2', + isSharedCpu: false, + }, + ], + selfLink: + 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a/machineTypes', +}; diff --git a/spec/javascripts/create_cluster/gke_cluster/stores/actions_spec.js b/spec/javascripts/create_cluster/gke_cluster/stores/actions_spec.js new file mode 100644 index 00000000000..a7591cc38c7 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/stores/actions_spec.js @@ -0,0 +1,131 @@ +import testAction from 'spec/helpers/vuex_action_helper'; +import * as actions from '~/create_cluster/gke_cluster/store/actions'; +import { createStore } from '~/create_cluster/gke_cluster/store'; +import { gapi } from '../helpers'; +import { selectedProjectMock, selectedZoneMock, selectedMachineTypeMock } from '../mock_data'; + +describe('GCP Cluster Dropdown Store Actions', () => { + let store; + + beforeEach(() => { + store = createStore(); + }); + + describe('setProject', () => { + it('should set project', done => { + testAction( + actions.setProject, + selectedProjectMock, + { selectedProject: {} }, + [{ type: 'SET_PROJECT', payload: selectedProjectMock }], + [], + done, + ); + }); + }); + + describe('setZone', () => { + it('should set zone', done => { + testAction( + actions.setZone, + selectedZoneMock, + { selectedZone: '' }, + [{ type: 'SET_ZONE', payload: selectedZoneMock }], + [], + done, + ); + }); + }); + + describe('setMachineType', () => { + it('should set machine type', done => { + testAction( + actions.setMachineType, + selectedMachineTypeMock, + { selectedMachineType: '' }, + [{ type: 'SET_MACHINE_TYPE', payload: selectedMachineTypeMock }], + [], + done, + ); + }); + }); + + describe('setIsValidatingProjectBilling', () => { + it('should set machine type', done => { + testAction( + actions.setIsValidatingProjectBilling, + true, + { isValidatingProjectBilling: null }, + [{ type: 'SET_IS_VALIDATING_PROJECT_BILLING', payload: true }], + [], + done, + ); + }); + }); + + describe('async fetch methods', () => { + window.gapi = gapi(); + + describe('fetchProjects', () => { + it('fetches projects from Google API', done => { + store + .dispatch('fetchProjects') + .then(() => { + expect(store.state.projects[0].projectId).toEqual(selectedProjectMock.projectId); + expect(store.state.projects[0].name).toEqual(selectedProjectMock.name); + + done(); + }) + .catch(done.fail); + }); + }); + + describe('validateProjectBilling', () => { + it('checks project billing status from Google API', done => { + testAction( + actions.validateProjectBilling, + true, + { + selectedProject: selectedProjectMock, + selectedZone: '', + selectedMachineType: '', + projectHasBillingEnabled: null, + }, + [ + { type: 'SET_ZONE', payload: '' }, + { type: 'SET_MACHINE_TYPE', payload: '' }, + { type: 'SET_PROJECT_BILLING_STATUS', payload: true }, + ], + [{ type: 'setIsValidatingProjectBilling', payload: false }], + done, + ); + }); + }); + + describe('fetchZones', () => { + it('fetches zones from Google API', done => { + store + .dispatch('fetchZones') + .then(() => { + expect(store.state.zones[0].name).toEqual(selectedZoneMock); + + done(); + }) + .catch(done.fail); + }); + }); + + describe('fetchMachineTypes', () => { + it('fetches machine types from Google API', done => { + store + .dispatch('fetchMachineTypes') + .then(() => { + expect(store.state.machineTypes[0].name).toEqual(selectedMachineTypeMock); + + done(); + }) + .catch(done.fail); + }); + }); + }); +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/stores/getters_spec.js b/spec/javascripts/create_cluster/gke_cluster/stores/getters_spec.js new file mode 100644 index 00000000000..ac92716b0ab --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/stores/getters_spec.js @@ -0,0 +1,65 @@ +import * as getters from '~/create_cluster/gke_cluster/store/getters'; +import { selectedProjectMock, selectedZoneMock, selectedMachineTypeMock } from '../mock_data'; + +describe('GCP Cluster Dropdown Store Getters', () => { + let state; + + describe('valid states', () => { + beforeEach(() => { + state = { + selectedProject: selectedProjectMock, + selectedZone: selectedZoneMock, + selectedMachineType: selectedMachineTypeMock, + }; + }); + + describe('hasProject', () => { + it('should return true when project is selected', () => { + expect(getters.hasProject(state)).toEqual(true); + }); + }); + + describe('hasZone', () => { + it('should return true when zone is selected', () => { + expect(getters.hasZone(state)).toEqual(true); + }); + }); + + describe('hasMachineType', () => { + it('should return true when machine type is selected', () => { + expect(getters.hasMachineType(state)).toEqual(true); + }); + }); + }); + + describe('invalid states', () => { + beforeEach(() => { + state = { + selectedProject: { + projectId: '', + name: '', + }, + selectedZone: '', + selectedMachineType: '', + }; + }); + + describe('hasProject', () => { + it('should return false when project is not selected', () => { + expect(getters.hasProject(state)).toEqual(false); + }); + }); + + describe('hasZone', () => { + it('should return false when zone is not selected', () => { + expect(getters.hasZone(state)).toEqual(false); + }); + }); + + describe('hasMachineType', () => { + it('should return false when machine type is not selected', () => { + expect(getters.hasMachineType(state)).toEqual(false); + }); + }); + }); +}); diff --git a/spec/javascripts/create_cluster/gke_cluster/stores/mutations_spec.js b/spec/javascripts/create_cluster/gke_cluster/stores/mutations_spec.js new file mode 100644 index 00000000000..7ee6ff436e2 --- /dev/null +++ b/spec/javascripts/create_cluster/gke_cluster/stores/mutations_spec.js @@ -0,0 +1,87 @@ +import { createStore } from '~/create_cluster/gke_cluster/store'; +import * as types from '~/create_cluster/gke_cluster/store/mutation_types'; +import { + selectedProjectMock, + selectedZoneMock, + selectedMachineTypeMock, + gapiProjectsResponseMock, + gapiZonesResponseMock, + gapiMachineTypesResponseMock, +} from '../mock_data'; + +describe('GCP Cluster Dropdown Store Mutations', () => { + let store; + + beforeEach(() => { + store = createStore(); + }); + + describe('SET_PROJECT', () => { + it('should set GCP project as selectedProject', () => { + const projectToSelect = gapiProjectsResponseMock.projects[0]; + + store.commit(types.SET_PROJECT, projectToSelect); + + expect(store.state.selectedProject.projectId).toEqual(selectedProjectMock.projectId); + expect(store.state.selectedProject.name).toEqual(selectedProjectMock.name); + }); + }); + + describe('SET_PROJECT_BILLING_STATUS', () => { + it('should set project billing status', () => { + store.commit(types.SET_PROJECT_BILLING_STATUS, true); + + expect(store.state.projectHasBillingEnabled).toBeTruthy(); + }); + }); + + describe('SET_ZONE', () => { + it('should set GCP zone as selectedZone', () => { + const zoneToSelect = gapiZonesResponseMock.items[0].name; + + store.commit(types.SET_ZONE, zoneToSelect); + + expect(store.state.selectedZone).toEqual(selectedZoneMock); + }); + }); + + describe('SET_MACHINE_TYPE', () => { + it('should set GCP machine type as selectedMachineType', () => { + const machineTypeToSelect = gapiMachineTypesResponseMock.items[0].name; + + store.commit(types.SET_MACHINE_TYPE, machineTypeToSelect); + + expect(store.state.selectedMachineType).toEqual(selectedMachineTypeMock); + }); + }); + + describe('SET_PROJECTS', () => { + it('should set Google API Projects response as projects', () => { + expect(store.state.projects.length).toEqual(0); + + store.commit(types.SET_PROJECTS, gapiProjectsResponseMock.projects); + + expect(store.state.projects.length).toEqual(gapiProjectsResponseMock.projects.length); + }); + }); + + describe('SET_ZONES', () => { + it('should set Google API Zones response as zones', () => { + expect(store.state.zones.length).toEqual(0); + + store.commit(types.SET_ZONES, gapiZonesResponseMock.items); + + expect(store.state.zones.length).toEqual(gapiZonesResponseMock.items.length); + }); + }); + + describe('SET_MACHINE_TYPES', () => { + it('should set Google API Machine Types response as machineTypes', () => { + expect(store.state.machineTypes.length).toEqual(0); + + store.commit(types.SET_MACHINE_TYPES, gapiMachineTypesResponseMock.items); + + expect(store.state.machineTypes.length).toEqual(gapiMachineTypesResponseMock.items.length); + }); + }); +}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js deleted file mode 100644 index fdecb823cd2..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown_spec.js +++ /dev/null @@ -1,109 +0,0 @@ -import Vue from 'vue'; -import GkeMachineTypeDropdown from '~/projects/gke_cluster_dropdowns/components/gke_machine_type_dropdown.vue'; -import { createStore } from '~/projects/gke_cluster_dropdowns/store'; -import { - SET_PROJECT, - SET_PROJECT_BILLING_STATUS, - SET_ZONE, - SET_MACHINE_TYPES, -} from '~/projects/gke_cluster_dropdowns/store/mutation_types'; -import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; -import { - selectedZoneMock, - selectedProjectMock, - selectedMachineTypeMock, - gapiMachineTypesResponseMock, -} from '../mock_data'; - -const componentConfig = { - fieldId: 'cluster_provider_gcp_attributes_gcp_machine_type', - fieldName: 'cluster[provider_gcp_attributes][gcp_machine_type]', -}; - -const LABELS = { - LOADING: 'Fetching machine types', - DISABLED_NO_PROJECT: 'Select project and zone to choose machine type', - DISABLED_NO_ZONE: 'Select zone to choose machine type', - DEFAULT: 'Select machine type', -}; - -const createComponent = (store, props = componentConfig) => { - const Component = Vue.extend(GkeMachineTypeDropdown); - - return mountComponentWithStore(Component, { - el: null, - props, - store, - }); -}; - -describe('GkeMachineTypeDropdown', () => { - let vm; - let store; - - beforeEach(() => { - store = createStore(); - vm = createComponent(store); - }); - - afterEach(() => { - vm.$destroy(); - }); - - describe('shows various toggle text depending on state', () => { - it('returns disabled state toggle text when no project and zone are selected', () => { - expect(vm.toggleText).toBe(LABELS.DISABLED_NO_PROJECT); - }); - - it('returns disabled state toggle text when no zone is selected', () => { - vm.$store.commit(SET_PROJECT, selectedProjectMock); - vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); - - expect(vm.toggleText).toBe(LABELS.DISABLED_NO_ZONE); - }); - - it('returns loading toggle text', () => { - vm.isLoading = true; - - expect(vm.toggleText).toBe(LABELS.LOADING); - }); - - it('returns default toggle text', () => { - expect(vm.toggleText).toBe(LABELS.DISABLED_NO_PROJECT); - - vm.$store.commit(SET_PROJECT, selectedProjectMock); - vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); - vm.$store.commit(SET_ZONE, selectedZoneMock); - - expect(vm.toggleText).toBe(LABELS.DEFAULT); - }); - - it('returns machine type name if machine type selected', () => { - vm.setItem(selectedMachineTypeMock); - - expect(vm.toggleText).toBe(selectedMachineTypeMock); - }); - }); - - describe('form input', () => { - it('reflects new value when dropdown item is clicked', done => { - expect(vm.$el.querySelector('input').value).toBe(''); - vm.$store.commit(SET_MACHINE_TYPES, gapiMachineTypesResponseMock.items); - - return vm - .$nextTick() - .then(() => { - vm.$el.querySelector('.dropdown-content button').click(); - - return vm - .$nextTick() - .then(() => { - expect(vm.$el.querySelector('input').value).toBe(selectedMachineTypeMock); - done(); - }) - .catch(done.fail); - }) - .catch(done.fail); - }); - }); -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js deleted file mode 100644 index 1eb7cb4bd5b..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown_spec.js +++ /dev/null @@ -1,104 +0,0 @@ -import Vue from 'vue'; -import GkeProjectIdDropdown from '~/projects/gke_cluster_dropdowns/components/gke_project_id_dropdown.vue'; -import { createStore } from '~/projects/gke_cluster_dropdowns/store'; -import { SET_PROJECTS } from '~/projects/gke_cluster_dropdowns/store/mutation_types'; -import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; -import { emptyProjectMock, selectedProjectMock } from '../mock_data'; - -const componentConfig = { - docsUrl: 'https://console.cloud.google.com/home/dashboard', - fieldId: 'cluster_provider_gcp_attributes_gcp_project_id', - fieldName: 'cluster[provider_gcp_attributes][gcp_project_id]', -}; - -const LABELS = { - LOADING: 'Fetching projects', - VALIDATING_PROJECT_BILLING: 'Validating project billing status', - DEFAULT: 'Select project', - EMPTY: 'No projects found', -}; - -const createComponent = (store, props = componentConfig) => { - const Component = Vue.extend(GkeProjectIdDropdown); - - return mountComponentWithStore(Component, { - el: null, - props, - store, - }); -}; - -describe('GkeProjectIdDropdown', () => { - let vm; - let store; - - beforeEach(() => { - store = createStore(); - vm = createComponent(store); - }); - - afterEach(() => { - vm.$destroy(); - }); - - describe('toggleText', () => { - it('returns loading toggle text', () => { - expect(vm.toggleText).toBe(LABELS.LOADING); - }); - - it('returns project billing validation text', () => { - vm.setIsValidatingProjectBilling(true); - - expect(vm.toggleText).toBe(LABELS.VALIDATING_PROJECT_BILLING); - }); - - it('returns default toggle text', done => - setTimeout(() => { - vm.setItem(emptyProjectMock); - - expect(vm.toggleText).toBe(LABELS.DEFAULT); - - done(); - })); - - it('returns project name if project selected', done => - setTimeout(() => { - vm.isLoading = false; - - expect(vm.toggleText).toBe(selectedProjectMock.name); - - done(); - })); - - it('returns empty toggle text', done => - setTimeout(() => { - vm.$store.commit(SET_PROJECTS, null); - vm.setItem(emptyProjectMock); - - expect(vm.toggleText).toBe(LABELS.EMPTY); - - done(); - })); - }); - - describe('selectItem', () => { - it('reflects new value when dropdown item is clicked', done => { - expect(vm.$el.querySelector('input').value).toBe(''); - - return vm - .$nextTick() - .then(() => { - vm.$el.querySelector('.dropdown-content button').click(); - - return vm - .$nextTick() - .then(() => { - expect(vm.$el.querySelector('input').value).toBe(selectedProjectMock.projectId); - done(); - }) - .catch(done.fail); - }) - .catch(done.fail); - }); - }); -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js deleted file mode 100644 index 95186e19ca1..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/components/gke_zone_dropdown_spec.js +++ /dev/null @@ -1,94 +0,0 @@ -import Vue from 'vue'; -import GkeZoneDropdown from '~/projects/gke_cluster_dropdowns/components/gke_zone_dropdown.vue'; -import { createStore } from '~/projects/gke_cluster_dropdowns/store'; -import { - SET_PROJECT, - SET_ZONES, - SET_PROJECT_BILLING_STATUS, -} from '~/projects/gke_cluster_dropdowns/store/mutation_types'; -import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; -import { selectedZoneMock, selectedProjectMock, gapiZonesResponseMock } from '../mock_data'; - -const componentConfig = { - fieldId: 'cluster_provider_gcp_attributes_gcp_zone', - fieldName: 'cluster[provider_gcp_attributes][gcp_zone]', -}; - -const LABELS = { - LOADING: 'Fetching zones', - DISABLED: 'Select project to choose zone', - DEFAULT: 'Select zone', -}; - -const createComponent = (store, props = componentConfig) => { - const Component = Vue.extend(GkeZoneDropdown); - - return mountComponentWithStore(Component, { - el: null, - props, - store, - }); -}; - -describe('GkeZoneDropdown', () => { - let vm; - let store; - - beforeEach(() => { - store = createStore(); - vm = createComponent(store); - }); - - afterEach(() => { - vm.$destroy(); - }); - - describe('toggleText', () => { - it('returns disabled state toggle text', () => { - expect(vm.toggleText).toBe(LABELS.DISABLED); - }); - - it('returns loading toggle text', () => { - vm.isLoading = true; - - expect(vm.toggleText).toBe(LABELS.LOADING); - }); - - it('returns default toggle text', () => { - expect(vm.toggleText).toBe(LABELS.DISABLED); - - vm.$store.commit(SET_PROJECT, selectedProjectMock); - vm.$store.commit(SET_PROJECT_BILLING_STATUS, true); - - expect(vm.toggleText).toBe(LABELS.DEFAULT); - }); - - it('returns project name if project selected', () => { - vm.setItem(selectedZoneMock); - - expect(vm.toggleText).toBe(selectedZoneMock); - }); - }); - - describe('selectItem', () => { - it('reflects new value when dropdown item is clicked', done => { - expect(vm.$el.querySelector('input').value).toBe(''); - vm.$store.commit(SET_ZONES, gapiZonesResponseMock.items); - - return vm - .$nextTick() - .then(() => { - vm.$el.querySelector('.dropdown-content button').click(); - - return vm - .$nextTick() - .then(() => { - expect(vm.$el.querySelector('input').value).toBe(selectedZoneMock); - done(); - }) - .catch(done.fail); - }) - .catch(done.fail); - }); - }); -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/helpers.js b/spec/javascripts/projects/gke_cluster_dropdowns/helpers.js deleted file mode 100644 index 6df511e9157..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/helpers.js +++ /dev/null @@ -1,49 +0,0 @@ -import { - gapiProjectsResponseMock, - gapiZonesResponseMock, - gapiMachineTypesResponseMock, -} from './mock_data'; - -// eslint-disable-next-line import/prefer-default-export -export const gapi = () => ({ - client: { - cloudbilling: { - projects: { - getBillingInfo: () => - new Promise(resolve => { - resolve({ - result: { billingEnabled: true }, - }); - }), - }, - }, - cloudresourcemanager: { - projects: { - list: () => - new Promise(resolve => { - resolve({ - result: { ...gapiProjectsResponseMock }, - }); - }), - }, - }, - compute: { - zones: { - list: () => - new Promise(resolve => { - resolve({ - result: { ...gapiZonesResponseMock }, - }); - }), - }, - machineTypes: { - list: () => - new Promise(resolve => { - resolve({ - result: { ...gapiMachineTypesResponseMock }, - }); - }), - }, - }, - }, -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/mock_data.js b/spec/javascripts/projects/gke_cluster_dropdowns/mock_data.js deleted file mode 100644 index d9f5dbc636f..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/mock_data.js +++ /dev/null @@ -1,75 +0,0 @@ -export const emptyProjectMock = { - projectId: '', - name: '', -}; - -export const selectedProjectMock = { - projectId: 'gcp-project-123', - name: 'gcp-project', -}; - -export const selectedZoneMock = 'us-central1-a'; - -export const selectedMachineTypeMock = 'n1-standard-2'; - -export const gapiProjectsResponseMock = { - projects: [ - { - projectNumber: '1234', - projectId: 'gcp-project-123', - lifecycleState: 'ACTIVE', - name: 'gcp-project', - createTime: '2017-12-16T01:48:29.129Z', - parent: { - type: 'organization', - id: '12345', - }, - }, - ], -}; - -export const gapiZonesResponseMock = { - kind: 'compute#zoneList', - id: 'projects/gitlab-internal-153318/zones', - items: [ - { - kind: 'compute#zone', - id: '2000', - creationTimestamp: '1969-12-31T16:00:00.000-08:00', - name: 'us-central1-a', - description: 'us-central1-a', - status: 'UP', - region: - 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/regions/us-central1', - selfLink: - 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a', - availableCpuPlatforms: ['Intel Skylake', 'Intel Broadwell', 'Intel Sandy Bridge'], - }, - ], - selfLink: 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones', -}; - -export const gapiMachineTypesResponseMock = { - kind: 'compute#machineTypeList', - id: 'projects/gitlab-internal-153318/zones/us-central1-a/machineTypes', - items: [ - { - kind: 'compute#machineType', - id: '3002', - creationTimestamp: '1969-12-31T16:00:00.000-08:00', - name: 'n1-standard-2', - description: '2 vCPUs, 7.5 GB RAM', - guestCpus: 2, - memoryMb: 7680, - imageSpaceGb: 10, - maximumPersistentDisks: 64, - maximumPersistentDisksSizeGb: '65536', - zone: 'us-central1-a', - selfLink: - 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a/machineTypes/n1-standard-2', - isSharedCpu: false, - }, - ], - selfLink: - 'https://www.googleapis.com/compute/v1/projects/gitlab-internal-153318/zones/us-central1-a/machineTypes', -}; diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/stores/actions_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/stores/actions_spec.js deleted file mode 100644 index 9d892b8185b..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/stores/actions_spec.js +++ /dev/null @@ -1,131 +0,0 @@ -import testAction from 'spec/helpers/vuex_action_helper'; -import * as actions from '~/projects/gke_cluster_dropdowns/store/actions'; -import { createStore } from '~/projects/gke_cluster_dropdowns/store'; -import { gapi } from '../helpers'; -import { selectedProjectMock, selectedZoneMock, selectedMachineTypeMock } from '../mock_data'; - -describe('GCP Cluster Dropdown Store Actions', () => { - let store; - - beforeEach(() => { - store = createStore(); - }); - - describe('setProject', () => { - it('should set project', done => { - testAction( - actions.setProject, - selectedProjectMock, - { selectedProject: {} }, - [{ type: 'SET_PROJECT', payload: selectedProjectMock }], - [], - done, - ); - }); - }); - - describe('setZone', () => { - it('should set zone', done => { - testAction( - actions.setZone, - selectedZoneMock, - { selectedZone: '' }, - [{ type: 'SET_ZONE', payload: selectedZoneMock }], - [], - done, - ); - }); - }); - - describe('setMachineType', () => { - it('should set machine type', done => { - testAction( - actions.setMachineType, - selectedMachineTypeMock, - { selectedMachineType: '' }, - [{ type: 'SET_MACHINE_TYPE', payload: selectedMachineTypeMock }], - [], - done, - ); - }); - }); - - describe('setIsValidatingProjectBilling', () => { - it('should set machine type', done => { - testAction( - actions.setIsValidatingProjectBilling, - true, - { isValidatingProjectBilling: null }, - [{ type: 'SET_IS_VALIDATING_PROJECT_BILLING', payload: true }], - [], - done, - ); - }); - }); - - describe('async fetch methods', () => { - window.gapi = gapi(); - - describe('fetchProjects', () => { - it('fetches projects from Google API', done => { - store - .dispatch('fetchProjects') - .then(() => { - expect(store.state.projects[0].projectId).toEqual(selectedProjectMock.projectId); - expect(store.state.projects[0].name).toEqual(selectedProjectMock.name); - - done(); - }) - .catch(done.fail); - }); - }); - - describe('validateProjectBilling', () => { - it('checks project billing status from Google API', done => { - testAction( - actions.validateProjectBilling, - true, - { - selectedProject: selectedProjectMock, - selectedZone: '', - selectedMachineType: '', - projectHasBillingEnabled: null, - }, - [ - { type: 'SET_ZONE', payload: '' }, - { type: 'SET_MACHINE_TYPE', payload: '' }, - { type: 'SET_PROJECT_BILLING_STATUS', payload: true }, - ], - [{ type: 'setIsValidatingProjectBilling', payload: false }], - done, - ); - }); - }); - - describe('fetchZones', () => { - it('fetches zones from Google API', done => { - store - .dispatch('fetchZones') - .then(() => { - expect(store.state.zones[0].name).toEqual(selectedZoneMock); - - done(); - }) - .catch(done.fail); - }); - }); - - describe('fetchMachineTypes', () => { - it('fetches machine types from Google API', done => { - store - .dispatch('fetchMachineTypes') - .then(() => { - expect(store.state.machineTypes[0].name).toEqual(selectedMachineTypeMock); - - done(); - }) - .catch(done.fail); - }); - }); - }); -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/stores/getters_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/stores/getters_spec.js deleted file mode 100644 index 6f89158f807..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/stores/getters_spec.js +++ /dev/null @@ -1,65 +0,0 @@ -import * as getters from '~/projects/gke_cluster_dropdowns/store/getters'; -import { selectedProjectMock, selectedZoneMock, selectedMachineTypeMock } from '../mock_data'; - -describe('GCP Cluster Dropdown Store Getters', () => { - let state; - - describe('valid states', () => { - beforeEach(() => { - state = { - selectedProject: selectedProjectMock, - selectedZone: selectedZoneMock, - selectedMachineType: selectedMachineTypeMock, - }; - }); - - describe('hasProject', () => { - it('should return true when project is selected', () => { - expect(getters.hasProject(state)).toEqual(true); - }); - }); - - describe('hasZone', () => { - it('should return true when zone is selected', () => { - expect(getters.hasZone(state)).toEqual(true); - }); - }); - - describe('hasMachineType', () => { - it('should return true when machine type is selected', () => { - expect(getters.hasMachineType(state)).toEqual(true); - }); - }); - }); - - describe('invalid states', () => { - beforeEach(() => { - state = { - selectedProject: { - projectId: '', - name: '', - }, - selectedZone: '', - selectedMachineType: '', - }; - }); - - describe('hasProject', () => { - it('should return false when project is not selected', () => { - expect(getters.hasProject(state)).toEqual(false); - }); - }); - - describe('hasZone', () => { - it('should return false when zone is not selected', () => { - expect(getters.hasZone(state)).toEqual(false); - }); - }); - - describe('hasMachineType', () => { - it('should return false when machine type is not selected', () => { - expect(getters.hasMachineType(state)).toEqual(false); - }); - }); - }); -}); diff --git a/spec/javascripts/projects/gke_cluster_dropdowns/stores/mutations_spec.js b/spec/javascripts/projects/gke_cluster_dropdowns/stores/mutations_spec.js deleted file mode 100644 index 7f8c4f314e4..00000000000 --- a/spec/javascripts/projects/gke_cluster_dropdowns/stores/mutations_spec.js +++ /dev/null @@ -1,87 +0,0 @@ -import { createStore } from '~/projects/gke_cluster_dropdowns/store'; -import * as types from '~/projects/gke_cluster_dropdowns/store/mutation_types'; -import { - selectedProjectMock, - selectedZoneMock, - selectedMachineTypeMock, - gapiProjectsResponseMock, - gapiZonesResponseMock, - gapiMachineTypesResponseMock, -} from '../mock_data'; - -describe('GCP Cluster Dropdown Store Mutations', () => { - let store; - - beforeEach(() => { - store = createStore(); - }); - - describe('SET_PROJECT', () => { - it('should set GCP project as selectedProject', () => { - const projectToSelect = gapiProjectsResponseMock.projects[0]; - - store.commit(types.SET_PROJECT, projectToSelect); - - expect(store.state.selectedProject.projectId).toEqual(selectedProjectMock.projectId); - expect(store.state.selectedProject.name).toEqual(selectedProjectMock.name); - }); - }); - - describe('SET_PROJECT_BILLING_STATUS', () => { - it('should set project billing status', () => { - store.commit(types.SET_PROJECT_BILLING_STATUS, true); - - expect(store.state.projectHasBillingEnabled).toBeTruthy(); - }); - }); - - describe('SET_ZONE', () => { - it('should set GCP zone as selectedZone', () => { - const zoneToSelect = gapiZonesResponseMock.items[0].name; - - store.commit(types.SET_ZONE, zoneToSelect); - - expect(store.state.selectedZone).toEqual(selectedZoneMock); - }); - }); - - describe('SET_MACHINE_TYPE', () => { - it('should set GCP machine type as selectedMachineType', () => { - const machineTypeToSelect = gapiMachineTypesResponseMock.items[0].name; - - store.commit(types.SET_MACHINE_TYPE, machineTypeToSelect); - - expect(store.state.selectedMachineType).toEqual(selectedMachineTypeMock); - }); - }); - - describe('SET_PROJECTS', () => { - it('should set Google API Projects response as projects', () => { - expect(store.state.projects.length).toEqual(0); - - store.commit(types.SET_PROJECTS, gapiProjectsResponseMock.projects); - - expect(store.state.projects.length).toEqual(gapiProjectsResponseMock.projects.length); - }); - }); - - describe('SET_ZONES', () => { - it('should set Google API Zones response as zones', () => { - expect(store.state.zones.length).toEqual(0); - - store.commit(types.SET_ZONES, gapiZonesResponseMock.items); - - expect(store.state.zones.length).toEqual(gapiZonesResponseMock.items.length); - }); - }); - - describe('SET_MACHINE_TYPES', () => { - it('should set Google API Machine Types response as machineTypes', () => { - expect(store.state.machineTypes.length).toEqual(0); - - store.commit(types.SET_MACHINE_TYPES, gapiMachineTypesResponseMock.items); - - expect(store.state.machineTypes.length).toEqual(gapiMachineTypesResponseMock.items.length); - }); - }); -}); -- cgit v1.2.1