Merge pull request #450 from gradido/save-locale

feat: Save Locale in Database
This commit is contained in:
Moriz Wahl 2021-05-19 15:03:29 +02:00 committed by GitHub
commit 527ef91fd3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 210 additions and 33 deletions

View File

@ -212,7 +212,7 @@ jobs:
report_name: Coverage Frontend
type: lcov
result_path: ./coverage/lcov.info
min_coverage: 18
min_coverage: 19
token: ${{ github.token }}
#test:

View File

@ -1,5 +1,7 @@
import axios from 'axios'
import CONFIG from '../config'
// eslint-disable-next-line no-unused-vars
import regeneratorRuntime from 'regenerator-runtime'
// control email-text sended with email verification code
const EMAIL_TYPE = {
@ -86,6 +88,16 @@ const loginAPI = {
}
return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
},
updateLanguage: async (sessionId, email, language) => {
const payload = {
session_id: sessionId,
email,
update: {
'User.language': language,
},
}
return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
},
}
export default loginAPI

View File

@ -0,0 +1,95 @@
import { mount } from '@vue/test-utils'
import LanguageSwitch from './LanguageSwitch'
const localVue = global.localVue
describe('LanguageSwitch', () => {
let wrapper
const state = {
sessionId: 1234,
email: 'he@ho.he',
language: null,
}
const mocks = {
$store: {
state,
commit: jest.fn(),
},
$i18n: {
locale: 'en',
},
}
const Wrapper = () => {
return mount(LanguageSwitch, { localVue, mocks })
}
describe('mount', () => {
beforeEach(() => {
wrapper = Wrapper()
})
it('renders the component', () => {
expect(wrapper.find('div.language-switch').exists()).toBeTruthy()
})
describe('with locales en and de', () => {
describe('empty store', () => {
it('shows English as default navigator langauge', () => {
expect(wrapper.find('button.dropdown-toggle').text()).toBe('English - en')
})
describe('navigator language is "de-DE"', () => {
const mockNavigator = jest.fn(() => {
return 'de'
})
it('shows Deutsch as language ', async () => {
wrapper.vm.getNavigatorLanguage = mockNavigator
wrapper.vm.setCurrentLanguage()
await wrapper.vm.$nextTick()
expect(wrapper.find('button.dropdown-toggle').text()).toBe('Deutsch - de')
})
})
describe('navigator language is "es-ES" (not supported)', () => {
const mockNavigator = jest.fn(() => {
return 'es'
})
it('shows English as language ', async () => {
wrapper.vm.getNavigatorLanguage = mockNavigator
wrapper.vm.setCurrentLanguage()
await wrapper.vm.$nextTick()
expect(wrapper.find('button.dropdown-toggle').text()).toBe('English - en')
})
})
})
describe('language "de" in store', () => {
it('shows Deutsch as language', async () => {
wrapper.vm.$store.state.language = 'de'
wrapper.vm.setCurrentLanguage()
await wrapper.vm.$nextTick()
expect(wrapper.find('button.dropdown-toggle').text()).toBe('Deutsch - de')
})
})
describe('dropdown menu', () => {
it('has English and German as languages to choose', () => {
expect(wrapper.findAll('li')).toHaveLength(2)
})
it('has English as first language to choose', () => {
expect(wrapper.findAll('li').at(0).text()).toBe('English')
})
it('has German as second language to choose', () => {
expect(wrapper.findAll('li').at(1).text()).toBe('Deutsch')
})
})
})
})
})

View File

@ -1,22 +1,72 @@
<template>
<div class="language-switch">
<b-dropdown size="sm" :text="$t('language') + ' - ' + $i18n.locale">
<b-dropdown-item @click.prevent="setLocale('de')">Deutsch</b-dropdown-item>
<b-dropdown-item @click.prevent="setLocale('en')">English</b-dropdown-item>
<b-dropdown size="sm" :text="currentLanguage.name + ' - ' + currentLanguage.code">
<b-dropdown-item
v-for="lang in locales"
@click.prevent="saveLocale(lang.code)"
:key="lang.code"
>
{{ lang.name }}
</b-dropdown-item>
</b-dropdown>
</div>
</template>
<script>
import { localeChanged } from 'vee-validate'
import locales from '../locales/'
import loginAPI from '../apis/loginAPI'
export default {
name: 'language-switch',
name: 'LanguageSwitch',
data() {
return {
locales: locales,
currentLanguage: {},
}
},
methods: {
setLocale(locale) {
this.$i18n.locale = locale
this.$store.commit('language', this.$i18n.locale)
this.currentLanguage = this.getLocaleObject(locale)
localeChanged(locale)
},
async saveLocale(locale) {
this.setLocale(locale)
if (this.$store.state.sessionId && this.$store.state.email) {
const result = await loginAPI.updateLanguage(
this.$store.state.sessionId,
this.$store.state.email,
locale,
)
if (result.success) {
// toast success message
} else {
// toast error message
}
}
},
getLocaleObject(code) {
return this.locales.find((l) => l.code === code)
},
getNavigatorLanguage() {
const lang = navigator.language
if (lang) return lang.split('-')[0]
return lang
},
setCurrentLanguage() {
let locale = this.$store.state.language || this.getNavigatorLanguage() || 'en'
let object = this.getLocaleObject(locale)
if (!object) {
locale = 'en'
object = this.getLocaleObject(locale)
}
this.setLocale(locale)
this.currentLanguage = object
},
},
created() {
this.setCurrentLanguage()
},
}
</script>

View File

@ -19,6 +19,7 @@ describe('SideBar', () => {
state: {
email: 'test@example.org',
},
commit: jest.fn(),
},
$i18n: {
locale: 'en',

View File

@ -0,0 +1,16 @@
const locales = [
{
name: 'English',
code: 'en',
iso: 'en-US',
enabled: true,
},
{
name: 'Deutsch',
code: 'de',
iso: 'de-DE',
enabled: true,
},
]
export default locales

View File

@ -18,7 +18,8 @@ export const mutations = {
export const actions = {
login: ({ dispatch, commit }, data) => {
commit('sessionId', data.sessionId)
commit('email', data.email)
commit('email', data.user.email)
commit('language', data.user.language)
},
logout: ({ commit, state }) => {
commit('sessionId', null)
@ -36,7 +37,7 @@ export const store = new Vuex.Store({
state: {
sessionId: null,
email: '',
language: 'en',
language: null,
modals: false,
},
getters: {},

View File

@ -35,20 +35,37 @@ describe('Vuex store', () => {
const commit = jest.fn()
const state = {}
it('calls two commits', () => {
login({ commit, state }, { sessionId: 1234, email: 'someone@there.is' })
expect(commit).toHaveBeenCalledTimes(2)
it('calls three commits', () => {
login(
{ commit, state },
{ sessionId: 1234, user: { email: 'someone@there.is', language: 'en' } },
)
expect(commit).toHaveBeenCalledTimes(3)
})
it('commits sessionId', () => {
login({ commit, state }, { sessionId: 1234, email: 'someone@there.is' })
login(
{ commit, state },
{ sessionId: 1234, user: { email: 'someone@there.is', language: 'en' } },
)
expect(commit).toHaveBeenNthCalledWith(1, 'sessionId', 1234)
})
it('commits email', () => {
login({ commit, state }, { sessionId: 1234, email: 'someone@there.is' })
login(
{ commit, state },
{ sessionId: 1234, user: { email: 'someone@there.is', language: 'en' } },
)
expect(commit).toHaveBeenNthCalledWith(2, 'email', 'someone@there.is')
})
it('commits language', () => {
login(
{ commit, state },
{ sessionId: 1234, user: { email: 'someone@there.is', language: 'en' } },
)
expect(commit).toHaveBeenNthCalledWith(3, 'language', 'en')
})
})
describe('logout', () => {

View File

@ -44,6 +44,9 @@ describe('DashboardLayoutGdd', () => {
const store = new Vuex.Store({
state,
mutations: {
language: jest.fn(),
},
})
const Wrapper = () => {

View File

@ -1,5 +1,4 @@
import { mount, RouterLinkStub } from '@vue/test-utils'
import Vuex from 'vuex'
import flushPromises from 'flush-promises'
import Login from './Login'
@ -16,20 +15,12 @@ describe('Login', () => {
$t: jest.fn((t) => t),
}
const state = {
loginfail: false,
}
const store = new Vuex.Store({
state,
})
const stubs = {
RouterLink: RouterLinkStub,
}
const Wrapper = () => {
return mount(Login, { localVue, mocks, store, stubs })
return mount(Login, { localVue, mocks, stubs })
}
describe('mount', () => {

View File

@ -122,7 +122,7 @@ export default {
if (result.success) {
this.$store.dispatch('login', {
sessionId: result.result.data.session_id,
email: this.model.email,
user: result.result.data.user,
})
this.$router.push('/overview')
loader.hide()

View File

@ -1,5 +1,4 @@
import { mount, RouterLinkStub } from '@vue/test-utils'
import Vuex from 'vuex'
import flushPromises from 'flush-promises'
import Register from './Register'
@ -16,20 +15,12 @@ describe('Register', () => {
$t: jest.fn((t) => t),
}
const state = {
// loginfail: false,
}
const store = new Vuex.Store({
state,
})
const stubs = {
RouterLink: RouterLinkStub,
}
const Wrapper = () => {
return mount(Register, { localVue, mocks, store, stubs })
return mount(Register, { localVue, mocks, stubs })
}
describe('mount', () => {