From c7c569e1ca8fdce3a2e5ac2fb9f4fab58f8ada7b Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 27 Feb 2024 13:47:16 +0100 Subject: [PATCH] add tests, fix bugs --- backend/src/graphql/resolver/UserResolver.ts | 6 +- frontend/src/App.vue | 12 +++ frontend/src/components/CommunitySwitch.vue | 17 ---- .../UserGMSLocationFormat.spec.js | 79 ++++++++++++++++++ .../UserSettings/UserGMSLocationFormat.vue | 20 +---- .../UserSettings/UserGMSNamingFormat.spec.js | 81 +++++++++++++++++++ .../UserSettings/UserGMSNamingFormat.vue | 20 +---- .../components/UserSettings/UserGMSSwitch.vue | 4 +- frontend/src/locales/de.json | 4 +- frontend/src/locales/en.json | 5 +- frontend/src/pages/Settings.vue | 4 +- 11 files changed, 192 insertions(+), 60 deletions(-) create mode 100644 frontend/src/components/UserSettings/UserGMSLocationFormat.spec.js create mode 100644 frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js diff --git a/backend/src/graphql/resolver/UserResolver.ts b/backend/src/graphql/resolver/UserResolver.ts index 8f6b36652..d0bba1e62 100644 --- a/backend/src/graphql/resolver/UserResolver.ts +++ b/backend/src/graphql/resolver/UserResolver.ts @@ -609,16 +609,16 @@ export class UserResolver { user.hideAmountGDT = hideAmountGDT } - if (gmsAllowed) { + if (gmsAllowed !== undefined) { user.gmsAllowed = gmsAllowed } - if (gmsPublishName) { + if (gmsPublishName !== null && gmsPublishName !== undefined) { user.gmsPublishName = gmsPublishName } if (gmsLocation) { user.location = Location2Point(gmsLocation) } - if (gmsPublishLocation) { + if (gmsPublishLocation !== null && gmsPublishLocation !== undefined) { user.gmsPublishLocation = gmsPublishLocation } // } catch (err) { diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 46f7dacb8..663c9e7d4 100755 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -71,4 +71,16 @@ export default { .text-color-gdd-yellow { color: rgb(197 141 56); } + +.dropdown > .dropdown-toggle { + border-radius: 17px; + height: 50px; + text-align: left; +} +.dropdown-toggle::after { + float: right; + top: 50%; + transform: translateY(-50%); + position: relative; +} diff --git a/frontend/src/components/CommunitySwitch.vue b/frontend/src/components/CommunitySwitch.vue index ac9ce3182..4ff3d9781 100644 --- a/frontend/src/components/CommunitySwitch.vue +++ b/frontend/src/components/CommunitySwitch.vue @@ -90,20 +90,3 @@ export default { }, } - diff --git a/frontend/src/components/UserSettings/UserGMSLocationFormat.spec.js b/frontend/src/components/UserSettings/UserGMSLocationFormat.spec.js new file mode 100644 index 000000000..9ec235d95 --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSLocationFormat.spec.js @@ -0,0 +1,79 @@ +import { mount } from '@vue/test-utils' +import UserGMSLocationFormat from './UserGMSLocationFormat.vue' +import { toastErrorSpy } from '@test/testSetup' + +const mockAPIcall = jest.fn() + +const storeCommitMock = jest.fn() + +const localVue = global.localVue + +describe('UserGMSLocationFormat', () => { + let wrapper + beforeEach(() => { + wrapper = mount(UserGMSLocationFormat, { + mocks: { + $t: (key) => key, // Mocking the translation function + $store: { + state: { + gmsPublishLocation: null, + }, + commit: storeCommitMock, + }, + $apollo: { + mutate: mockAPIcall, + }, + }, + localVue, + propsData: { + selectedOption: 'GMS_LOCATION_TYPE_RANDOM', + }, + }) + }) + + afterEach(() => { + wrapper.destroy() + }) + + it('renders the correct dropdown options', () => { + const dropdownItems = wrapper.findAll('.dropdown-item') + expect(dropdownItems.length).toBe(3) + + const labels = dropdownItems.wrappers.map((item) => item.text()) + expect(labels).toEqual([ + 'settings.GMS.publish-location.exact', + 'settings.GMS.publish-location.approximate', + 'settings.GMS.publish-location.random', + ]) + }) + + it('updates selected option on click', async () => { + const dropdownItem = wrapper.findAll('.dropdown-item').at(1) // Click the second item + await dropdownItem.trigger('click') + + expect(wrapper.emitted().gmsPublishLocation).toBeTruthy() + expect(wrapper.emitted().gmsPublishLocation.length).toBe(1) + expect(wrapper.emitted().gmsPublishLocation[0]).toEqual(['GMS_LOCATION_TYPE_APPROXIMATE']) + }) + + it('does not update when clicking on already selected option', async () => { + const dropdownItem = wrapper.findAll('.dropdown-item').at(2) // Click the third item (which is already selected) + await dropdownItem.trigger('click') + + expect(wrapper.emitted().gmsPublishLocation).toBeFalsy() + }) + + describe('update with error', () => { + beforeEach(async () => { + mockAPIcall.mockRejectedValue({ + message: 'Ouch', + }) + const dropdownItem = wrapper.findAll('.dropdown-item').at(1) // Click the second item + await dropdownItem.trigger('click') + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Ouch') + }) + }) +}) diff --git a/frontend/src/components/UserSettings/UserGMSLocationFormat.vue b/frontend/src/components/UserSettings/UserGMSLocationFormat.vue index 169a69cae..d20135d5e 100644 --- a/frontend/src/components/UserSettings/UserGMSLocationFormat.vue +++ b/frontend/src/components/UserSettings/UserGMSLocationFormat.vue @@ -39,13 +39,12 @@ export default { }, computed: { selectedOptionLabel() { - const selected = this.dropdownOptions.find((option) => option.value === this.selectedOption) - return selected ? selected.label : this.selectedOption + return this.dropdownOptions.find((option) => option.value === this.selectedOption).label }, }, methods: { async update(option) { - if (option === this.selectedOption) { + if (option.value === this.selectedOption) { return } try { @@ -67,19 +66,8 @@ export default { } diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js b/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js new file mode 100644 index 000000000..3dbbfdb2c --- /dev/null +++ b/frontend/src/components/UserSettings/UserGMSNamingFormat.spec.js @@ -0,0 +1,81 @@ +import { mount } from '@vue/test-utils' +import UserGMSNamingFormat from './UserGMSNamingFormat.vue' +import { toastErrorSpy } from '@test/testSetup' + +const mockAPIcall = jest.fn() + +const storeCommitMock = jest.fn() + +const localVue = global.localVue + +describe('UserGMSNamingFormat', () => { + let wrapper + beforeEach(() => { + wrapper = mount(UserGMSNamingFormat, { + mocks: { + $t: (key) => key, // Mocking the translation function + $store: { + state: { + gmsPublishName: null, + }, + commit: storeCommitMock, + }, + $apollo: { + mutate: mockAPIcall, + }, + }, + localVue, + propsData: { + selectedOption: 'GMS_PUBLISH_NAME_ALIAS_OR_INITALS', + }, + }) + }) + + afterEach(() => { + wrapper.destroy() + }) + + it('renders the correct dropdown options', () => { + const dropdownItems = wrapper.findAll('.dropdown-item') + expect(dropdownItems.length).toBe(5) + + const labels = dropdownItems.wrappers.map((item) => item.text()) + expect(labels).toEqual([ + 'settings.GMS.publish-name.alias-or-initials', + 'settings.GMS.publish-name.initials', + 'settings.GMS.publish-name.first', + 'settings.GMS.publish-name.first-initial', + 'settings.GMS.publish-name.name-full', + ]) + }) + + it('updates selected option on click', async () => { + const dropdownItem = wrapper.findAll('.dropdown-item').at(3) // Click the fourth item + await dropdownItem.trigger('click') + + expect(wrapper.emitted().gmsPublishName).toBeTruthy() + expect(wrapper.emitted().gmsPublishName.length).toBe(1) + expect(wrapper.emitted().gmsPublishName[0]).toEqual(['GMS_PUBLISH_NAME_FIRST_INITIAL']) + }) + + it('does not update when clicking on already selected option', async () => { + const dropdownItem = wrapper.findAll('.dropdown-item').at(0) // Click the first item (which is already selected) + await dropdownItem.trigger('click') + + expect(wrapper.emitted().gmsPublishName).toBeFalsy() + }) + + describe('update with error', () => { + beforeEach(async () => { + mockAPIcall.mockRejectedValue({ + message: 'Ouch', + }) + const dropdownItem = wrapper.findAll('.dropdown-item').at(2) // Click the third item + await dropdownItem.trigger('click') + }) + + it('toasts an error message', () => { + expect(toastErrorSpy).toBeCalledWith('Ouch') + }) + }) +}) diff --git a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue index 0ef008b43..29b4cd384 100644 --- a/frontend/src/components/UserSettings/UserGMSNamingFormat.vue +++ b/frontend/src/components/UserSettings/UserGMSNamingFormat.vue @@ -53,13 +53,12 @@ export default { }, computed: { selectedOptionLabel() { - const selected = this.dropdownOptions.find((option) => option.value === this.selectedOption) - return selected ? selected.label : this.selectedOption + return this.dropdownOptions.find((option) => option.value === this.selectedOption).label }, }, methods: { async update(option) { - if (option === this.selectedOption) { + if (option.value === this.selectedOption) { return } try { @@ -81,19 +80,8 @@ export default { } diff --git a/frontend/src/components/UserSettings/UserGMSSwitch.vue b/frontend/src/components/UserSettings/UserGMSSwitch.vue index cc9a344a5..979736e39 100644 --- a/frontend/src/components/UserSettings/UserGMSSwitch.vue +++ b/frontend/src/components/UserSettings/UserGMSSwitch.vue @@ -29,8 +29,8 @@ export default { }, }) .then(() => { - this.$store.commit('gmsState', this.gmsAllowed) - this.$emit('gmsStateSwitch', this.gmsAllowed) + this.$store.commit('gmsAllowed', this.gmsAllowed) + this.$emit('gmsAllowed', this.gmsAllowed) this.toastSuccess( this.gmsAllowed ? this.$t('settings.GMS.enabled') : this.$t('settings.GMS.disabled'), ) diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 715a9b7e4..1c37d5e24 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -294,7 +294,7 @@ "emailInfo": "Kann aktuell noch nicht geändert werden.", "GMS": { "disabled": "Daten werden nicht nach GMS exportiert", - "enabled": "Daten werden nach GMS exportiert", + "enabled": "Daten werden nach GMS exportiert", "location": { "label": "Positionsbestimmung", "button": "Klick mich!" @@ -305,7 +305,7 @@ "exact": "Genaue Position", "approximate": "Ungefähre Position", "random": "Zufallsposition", - "updated":"Positionstyp für GMS aktualisiert" + "updated": "Positionstyp für GMS aktualisiert" }, "publish-name": { "alias-or-initials": "Benutzername oder Initialen", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index 81c37733a..7c607ecbb 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -304,7 +304,8 @@ "publish-location": { "exact": "exact position", "approximate": "approximate position", - "random": "random position" + "random": "random position", + "updated": "format of location for GMS updated" }, "publish-name": { "alias-or-initials": "Username or initials", @@ -319,7 +320,7 @@ "name-full-tooltip": "fullname: firstname plus lastname", "updated": "format of name for GMS updated" }, - "switch": "Allow data export to GMS" + "switch": "Allow data export to GMS" }, "hideAmountGDD": "Your GDD amount is hidden.", "hideAmountGDT": "Your GDT amount is hidden.", diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue index b1706906b..cb840e068 100644 --- a/frontend/src/pages/Settings.vue +++ b/frontend/src/pages/Settings.vue @@ -90,7 +90,7 @@ - +
@@ -206,7 +206,7 @@ export default { } catch (error) {} }, gmsStateSwitch(eventData) { - this.gmsState = eventData + this.gmsAllowed = eventData }, }, }