Commit 811342e3 authored by Enrique Alcantara's avatar Enrique Alcantara Committed by Tiger

Implement error handling in auth form

Handle isAuthenticating state
Handle authentication error state
parent 06c996be
<script> <script>
import { mapState } from 'vuex';
import ServiceCredentialsForm from './service_credentials_form.vue'; import ServiceCredentialsForm from './service_credentials_form.vue';
import EksClusterConfigurationForm from './eks_cluster_configuration_form.vue'; import EksClusterConfigurationForm from './eks_cluster_configuration_form.vue';
import { mapState } from 'vuex';
export default { export default {
components: { components: {
......
<script> <script>
import { GlFormInput, GlButton } from '@gitlab/ui'; import { GlFormInput } from '@gitlab/ui';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__, __ } from '~/locale';
import _ from 'underscore'; import _ from 'underscore';
import { mapState } from 'vuex'; import { mapState, mapActions } from 'vuex';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
export default { export default {
components: { components: {
GlFormInput, GlFormInput,
GlButton, LoadingButton,
ClipboardButton, ClipboardButton,
}, },
props: { props: {
...@@ -27,7 +28,15 @@ export default { ...@@ -27,7 +28,15 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['accountId', 'externalId']), ...mapState(['accountId', 'externalId', 'isCreatingRole', 'createRoleError']),
submitButtonDisabled() {
return this.isCreatingRole || !this.roleArn;
},
submitButtonLabel() {
return this.isCreatingRole
? __('Authenticating')
: s__('ClusterIntegration|Authenticate with AWS');
},
accountAndExternalIdsHelpText() { accountAndExternalIdsHelpText() {
const escapedUrl = _.escape(this.accountAndExternalIdsHelpPath); const escapedUrl = _.escape(this.accountAndExternalIdsHelpPath);
...@@ -61,6 +70,14 @@ export default { ...@@ -61,6 +70,14 @@ export default {
); );
}, },
}, },
methods: {
...mapActions(['createRole']),
handleAuthenticate() {
const { roleArn, externalId } = this;
this.createRole({ roleArn, externalId });
},
},
}; };
</script> </script>
<template> <template>
...@@ -73,11 +90,14 @@ export default { ...@@ -73,11 +90,14 @@ export default {
) )
}} }}
</p> </p>
<div v-if="createRoleError" class="js-invalid-credentials bs-callout bs-callout-danger">
{{ createRoleError }}
</div>
<div class="form-row"> <div class="form-row">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="gitlab-account-id">{{ __('Account ID') }}</label> <label for="gitlab-account-id">{{ __('Account ID') }}</label>
<div class="input-group"> <div class="input-group">
<gl-form-input type="text" readonly :value="accountId" id="gitlab-account-id" /> <gl-form-input id="gitlab-account-id" type="text" readonly :value="accountId" />
<div class="input-group-append"> <div class="input-group-append">
<clipboard-button <clipboard-button
:text="accountId" :text="accountId"
...@@ -90,7 +110,7 @@ export default { ...@@ -90,7 +110,7 @@ export default {
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="eks-external-id">{{ __('External ID') }}</label> <label for="eks-external-id">{{ __('External ID') }}</label>
<div class="input-group"> <div class="input-group">
<gl-form-input type="text" readonly :value="externalId" id="eks-external-id" /> <gl-form-input id="eks-external-id" type="text" readonly :value="externalId" />
<div class="input-group-append"> <div class="input-group-append">
<clipboard-button <clipboard-button
:text="externalId" :text="externalId"
...@@ -109,8 +129,12 @@ export default { ...@@ -109,8 +129,12 @@ export default {
<gl-form-input id="eks-provision-role-arn" v-model="roleArn" /> <gl-form-input id="eks-provision-role-arn" v-model="roleArn" />
<p class="form-text text-muted" v-html="provisionRoleArnHelpText"></p> <p class="form-text text-muted" v-html="provisionRoleArnHelpText"></p>
</div> </div>
<gl-button class="js-submit-service-credentials" :disabled="!roleArn"> <loading-button
{{ s__('ClusterIntegration|Authenticate with AWS') }} class="js-submit-service-credentials"
</gl-button> :disabled="submitButtonDisabled"
:loading="isCreatingRole"
:label="submitButtonLabel"
@click="handleAuthenticate($event)"
/>
</form> </form>
</template> </template>
import { KUBERNETES_VERSIONS } from '../constants'; import { KUBERNETES_VERSIONS } from '../constants';
export default () => ({ export default () => ({
isValidatingCredentials: false, isAuthenticating: false,
hasCredentials: false, hasCredentials: false,
invalidCredentials: false, invalidCredentials: false,
invalidCredentialsError: null, invalidCredentialsError: null,
......
import { shallowMount } from '@vue/test-utils'; import Vuex from 'vuex';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue'; import ServiceCredentialsForm from '~/create_cluster/eks_cluster/components/service_credentials_form.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import eksClusterState from '~/create_cluster/eks_cluster/store/state';
const localVue = createLocalVue();
localVue.use(Vuex);
describe('ServiceCredentialsForm', () => { describe('ServiceCredentialsForm', () => {
let vm; let vm;
let state;
let createRoleAction;
const accountId = 'accountId'; const accountId = 'accountId';
const externalId = 'externalId'; const externalId = 'externalId';
beforeEach(() => { beforeEach(() => {
state = Object.assign(eksClusterState(), {
accountId,
externalId,
});
createRoleAction = jest.fn();
const store = new Vuex.Store({
state,
actions: {
createRole: createRoleAction,
},
});
vm = shallowMount(ServiceCredentialsForm, { vm = shallowMount(ServiceCredentialsForm, {
propsData: { propsData: {
accountId,
externalId,
accountAndExternalIdsHelpPath: '', accountAndExternalIdsHelpPath: '',
createRoleArnHelpPath: '', createRoleArnHelpPath: '',
}, },
localVue,
store,
}); });
}); });
afterEach(() => vm.destroy()); afterEach(() => vm.destroy());
...@@ -23,7 +44,8 @@ describe('ServiceCredentialsForm', () => { ...@@ -23,7 +44,8 @@ describe('ServiceCredentialsForm', () => {
const findCopyAccountIdButton = () => vm.find('.js-copy-account-id-button'); const findCopyAccountIdButton = () => vm.find('.js-copy-account-id-button');
const findExternalIdInput = () => vm.find('#eks-external-id'); const findExternalIdInput = () => vm.find('#eks-external-id');
const findCopyExternalIdButton = () => vm.find('.js-copy-external-id-button'); const findCopyExternalIdButton = () => vm.find('.js-copy-external-id-button');
const findSubmitButton = () => vm.find('.js-submit-service-credentials'); const findInvalidCredentials = () => vm.find('.js-invalid-credentials');
const findSubmitButton = () => vm.find(LoadingButton);
it('displays provided account id', () => { it('displays provided account id', () => {
expect(findAccountIdInput().attributes('value')).toBe(accountId); expect(findAccountIdInput().attributes('value')).toBe(accountId);
...@@ -50,4 +72,44 @@ describe('ServiceCredentialsForm', () => { ...@@ -50,4 +72,44 @@ describe('ServiceCredentialsForm', () => {
expect(findSubmitButton().attributes('disabled')).toBeFalsy(); expect(findSubmitButton().attributes('disabled')).toBeFalsy();
}); });
it('dispatches authenticate action when submit button is clicked', () => {
findSubmitButton().vm.$emit('click');
expect(createRoleAction).toHaveBeenCalled();
});
describe('when is creating role', () => {
beforeEach(() => {
vm.setData({ roleArn: '123' }); // set role ARN to enable button
state.isCreatingRole = true;
});
it('disables submit button', () => {
expect(findSubmitButton().props('disabled')).toBe(true);
});
it('sets submit button as loading', () => {
expect(findSubmitButton().props('loading')).toBe(true);
})
it('displays Authenticating label on submit button', () => {
expect(findSubmitButton().props('label')).toBe('Authenticating');
});
})
describe('when role can’t be created', () => {
beforeEach(() => {
state.createRoleError = 'Invalid credentials';
});
it('displays invalid role warning banner', () => {
expect(findInvalidCredentials().exists()).toBe(true);
});
it('displays invalid role error message', () => {
expect(findInvalidCredentials().text()).toContain(state.createRoleError);
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment