From da28f1f364f96eb4140c3877293799330734ba73 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Wed, 16 Jun 2021 13:40:27 +0200 Subject: [PATCH 1/5] setuo password component --- .../src/components/Inputs/InputPassword.vue | 63 +++++++++++++++++++ frontend/src/locales/de.json | 3 +- frontend/src/locales/en.json | 3 +- frontend/src/views/Pages/Login.vue | 52 ++++----------- 4 files changed, 80 insertions(+), 41 deletions(-) create mode 100644 frontend/src/components/Inputs/InputPassword.vue diff --git a/frontend/src/components/Inputs/InputPassword.vue b/frontend/src/components/Inputs/InputPassword.vue new file mode 100644 index 000000000..638eb6eb3 --- /dev/null +++ b/frontend/src/components/Inputs/InputPassword.vue @@ -0,0 +1,63 @@ + + diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 8554996bb..a1cdf985b 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -64,7 +64,8 @@ "change_username_info": "Einmal gespeichert, kann der Username ncht mehr geƤndert werden!" }, "error": { - "error":"Fehler" + "error":"Fehler", + "no-account": "Leider konnten wir keinen Account finden mit diesen Daten!" }, "transaction":{ "show_all":"Alle {count} Transaktionen ansehen", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 7b97c2240..6e39a04b7 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -64,7 +64,8 @@ "change_username_info": "Once saved, the username cannot be changed again!" }, "error": { - "error":"Error" + "error":"Error", + "no-account": "Unfortunately we could not find an account to the given data!" }, "transaction":{ "show_all":"View all {count} transactions.", diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 4619dddf2..d08171c1f 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -46,52 +46,25 @@ - - - - - - - - - - - - - {{ validationContext.errors[0] }} - - - + - Leider konnten wir keinen Account finden mit diesen Daten! + {{ $t('error.no-account') }} -
+
{{ $t('login') }}
@@ -118,9 +91,13 @@ + diff --git a/frontend/src/views/Pages/Login.vue b/frontend/src/views/Pages/Login.vue index 25c40df5a..2d4ce2345 100755 --- a/frontend/src/views/Pages/Login.vue +++ b/frontend/src/views/Pages/Login.vue @@ -13,7 +13,6 @@
- @@ -22,47 +21,14 @@
{{ $t('login') }}
- - - - - - - - - {{ validationContext.errors[0] }} - - - - + + + - - - - - - - {{ $t('error.no-account') }} - - - - -
{{ $t('login') }}
@@ -91,31 +57,26 @@ import loginAPI from '../../apis/loginAPI' import CONFIG from '../../config' import InputPassword from '../../components/Inputs/InputPassword' +import InputEmail from '../../components/Inputs/InputEmail' export default { name: 'login', components: { InputPassword, + InputEmail, }, data() { return { form: { email: '', password: '', - // rememberMe: false }, - loginfail: false, allowRegister: CONFIG.ALLOW_REGISTER, passwordVisible: false, } }, methods: { - getValidationState({ dirty, validated, valid = null }) { - return dirty || validated ? valid : null - }, async onSubmit() { - // error info ausschalten - this.loginfail = false const loader = this.$loading.show({ container: this.$refs.submitButton, }) @@ -129,7 +90,7 @@ export default { loader.hide() } else { loader.hide() - this.loginfail = true + this.$toast.error(this.$t('error.no-account')) } }, }, From 789808ea408997ab66fd9954fa7dd4ee5fc58049 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 29 Jun 2021 14:02:09 +0200 Subject: [PATCH 4/5] Complete test for login page --- frontend/src/components/Inputs/InputEmail.vue | 2 +- frontend/src/views/Pages/Login.spec.js | 119 ++++++++++++++++-- 2 files changed, 110 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Inputs/InputEmail.vue b/frontend/src/components/Inputs/InputEmail.vue index adcd66345..41338fd8c 100644 --- a/frontend/src/components/Inputs/InputEmail.vue +++ b/frontend/src/components/Inputs/InputEmail.vue @@ -37,7 +37,7 @@ export default { } }, }, - name: { type: String, default: 'email' }, + name: { type: String, default: 'Email' }, label: { type: String, default: 'Email' }, placeholder: { type: String, default: 'Email' }, value: { required: true, type: String }, diff --git a/frontend/src/views/Pages/Login.spec.js b/frontend/src/views/Pages/Login.spec.js index 0d94840b0..a4ff79bed 100644 --- a/frontend/src/views/Pages/Login.spec.js +++ b/frontend/src/views/Pages/Login.spec.js @@ -1,10 +1,37 @@ import { mount, RouterLinkStub } from '@vue/test-utils' import flushPromises from 'flush-promises' - +import loginAPI from '../../apis/loginAPI' import Login from './Login' +jest.mock('../../apis/loginAPI') + const localVue = global.localVue +const mockLoginCall = jest.fn() +mockLoginCall.mockReturnValue({ + success: true, + result: { + data: { + session_id: 1, + user: { + name: 'Peter Lustig', + }, + }, + }, +}) + +loginAPI.login = mockLoginCall + +const toastErrorMock = jest.fn() +const mockStoreDispach = jest.fn() +const mockRouterPush = jest.fn() +const spinnerHideMock = jest.fn() +const spinnerMock = jest.fn(() => { + return { + hide: spinnerHideMock, + } +}) + describe('Login', () => { let wrapper @@ -13,6 +40,18 @@ describe('Login', () => { locale: 'en', }, $t: jest.fn((t) => t), + $store: { + dispatch: mockStoreDispach, + }, + $loading: { + show: spinnerMock, + }, + $router: { + push: mockRouterPush, + }, + $toast: { + error: toastErrorMock, + }, } const stubs = { @@ -76,16 +115,76 @@ describe('Login', () => { it('has a Submit button', () => { expect(wrapper.find('button[type="submit"]').exists()).toBeTruthy() }) - - it('shows a warning when no valid Email is entered', async () => { - wrapper.find('input[placeholder="Email"]').setValue('no_valid@Email') - await flushPromises() - await expect(wrapper.find('.invalid-feedback').text()).toEqual( - 'The Email field must be a valid email', - ) - }) }) - // to do: test submit button + describe('submit', () => { + describe('no data', () => { + it('displays a message that Email is required', async () => { + await wrapper.find('form').trigger('submit') + await flushPromises() + expect(wrapper.findAll('div.invalid-feedback').at(0).text()).toBe( + 'The Email field is required', + ) + }) + + it('displays a message that password is required', async () => { + await wrapper.find('form').trigger('submit') + await flushPromises() + expect(wrapper.findAll('div.invalid-feedback').at(1).text()).toBe( + 'The password field is required', + ) + }) + }) + + describe('valid data', () => { + beforeEach(async () => { + jest.clearAllMocks() + await wrapper.find('input[placeholder="Email"]').setValue('user@example.org') + await wrapper.find('input[placeholder="form.password"]').setValue('1234') + await flushPromises() + await wrapper.find('form').trigger('submit') + await flushPromises() + }) + + it('calls the API with the given data', () => { + expect(mockLoginCall).toBeCalledWith('user@example.org', '1234') + }) + + it('creates a spinner', () => { + expect(spinnerMock).toBeCalled() + }) + + describe('login success', () => { + it('dispatches server response to store', () => { + expect(mockStoreDispach).toBeCalledWith('login', { + sessionId: 1, + user: { name: 'Peter Lustig' }, + }) + }) + + it('redirects to overview page', () => { + expect(mockRouterPush).toBeCalledWith('/overview') + }) + + it('hides the spinner', () => { + expect(spinnerHideMock).toBeCalled() + }) + }) + + describe('login fails', () => { + beforeEach(() => { + mockLoginCall.mockReturnValue({ success: false }) + }) + + it('hides the spinner', () => { + expect(spinnerHideMock).toBeCalled() + }) + + it('toasts an error message', () => { + expect(toastErrorMock).toBeCalledWith('error.no-account') + }) + }) + }) + }) }) }) From d3382620fa551ae2f2587bba404565cfecbead37 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 29 Jun 2021 14:09:34 +0200 Subject: [PATCH 5/5] frontend coverage to 33% --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14b507354..329b1dd60 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -212,7 +212,7 @@ jobs: report_name: Coverage Frontend type: lcov result_path: ./coverage/lcov.info - min_coverage: 31 + min_coverage: 33 token: ${{ github.token }} ##############################################################################