mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into 1145-refactor-admin-resolver-from-master
This commit is contained in:
commit
d7aec06a2c
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -399,7 +399,7 @@ jobs:
|
|||||||
report_name: Coverage Frontend
|
report_name: Coverage Frontend
|
||||||
type: lcov
|
type: lcov
|
||||||
result_path: ./coverage/lcov.info
|
result_path: ./coverage/lcov.info
|
||||||
min_coverage: 86
|
min_coverage: 90
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
@ -441,7 +441,7 @@ jobs:
|
|||||||
report_name: Coverage Admin Interface
|
report_name: Coverage Admin Interface
|
||||||
type: lcov
|
type: lcov
|
||||||
result_path: ./coverage/lcov.info
|
result_path: ./coverage/lcov.info
|
||||||
min_coverage: 60
|
min_coverage: 69
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|||||||
@ -11,11 +11,8 @@ import addNavigationGuards from './router/guards'
|
|||||||
|
|
||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
|
|
||||||
import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
|
|
||||||
import VueApollo from 'vue-apollo'
|
import VueApollo from 'vue-apollo'
|
||||||
|
|
||||||
import CONFIG from './config'
|
|
||||||
|
|
||||||
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
||||||
import 'bootstrap/dist/css/bootstrap.css'
|
import 'bootstrap/dist/css/bootstrap.css'
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||||
@ -23,37 +20,7 @@ import 'bootstrap-vue/dist/bootstrap-vue.css'
|
|||||||
import moment from 'vue-moment'
|
import moment from 'vue-moment'
|
||||||
import Toasted from 'vue-toasted'
|
import Toasted from 'vue-toasted'
|
||||||
|
|
||||||
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
import { apolloProvider } from './plugins/apolloProvider'
|
||||||
|
|
||||||
const authLink = new ApolloLink((operation, forward) => {
|
|
||||||
const token = store.state.token
|
|
||||||
|
|
||||||
operation.setContext({
|
|
||||||
headers: {
|
|
||||||
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return forward(operation).map((response) => {
|
|
||||||
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
|
||||||
response.errors[0].message = i18n.t('error.session-expired')
|
|
||||||
store.dispatch('logout', null)
|
|
||||||
if (router.currentRoute.path !== '/logout') router.push('/logout')
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
const newToken = operation.getContext().response.headers.get('token')
|
|
||||||
if (newToken) store.commit('token', newToken)
|
|
||||||
return response
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const apolloClient = new ApolloClient({
|
|
||||||
link: authLink.concat(httpLink),
|
|
||||||
cache: new InMemoryCache(),
|
|
||||||
})
|
|
||||||
|
|
||||||
const apolloProvider = new VueApollo({
|
|
||||||
defaultClient: apolloClient,
|
|
||||||
})
|
|
||||||
|
|
||||||
Vue.use(BootstrapVue)
|
Vue.use(BootstrapVue)
|
||||||
|
|
||||||
|
|||||||
@ -101,77 +101,4 @@ describe('main', () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('ApolloLink', () => {
|
|
||||||
// mock store
|
|
||||||
const storeDispatchMock = jest.fn()
|
|
||||||
store.state = {
|
|
||||||
token: 'some-token',
|
|
||||||
}
|
|
||||||
store.dispatch = storeDispatchMock
|
|
||||||
|
|
||||||
// mock i18n.t
|
|
||||||
i18n.t = jest.fn((t) => t)
|
|
||||||
|
|
||||||
// mock apllo response
|
|
||||||
const responseMock = {
|
|
||||||
errors: [{ message: '403.13 - Client certificate revoked' }],
|
|
||||||
}
|
|
||||||
|
|
||||||
// mock router
|
|
||||||
const routerPushMock = jest.fn()
|
|
||||||
router.push = routerPushMock
|
|
||||||
router.currentRoute = {
|
|
||||||
path: '/overview',
|
|
||||||
}
|
|
||||||
|
|
||||||
// mock context
|
|
||||||
const setContextMock = jest.fn()
|
|
||||||
const getContextMock = jest.fn(() => {
|
|
||||||
return {
|
|
||||||
response: {
|
|
||||||
headers: {
|
|
||||||
get: jest.fn(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// mock apollo link function params
|
|
||||||
const operationMock = {
|
|
||||||
setContext: setContextMock,
|
|
||||||
getContext: getContextMock,
|
|
||||||
}
|
|
||||||
|
|
||||||
const forwardMock = jest.fn(() => {
|
|
||||||
return [responseMock]
|
|
||||||
})
|
|
||||||
|
|
||||||
// get apollo link callback
|
|
||||||
const middleware = ApolloLink.mock.calls[0][0]
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
// run the callback with mocked params
|
|
||||||
middleware(operationMock, forwardMock)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets authorization header', () => {
|
|
||||||
expect(setContextMock).toBeCalledWith({
|
|
||||||
headers: {
|
|
||||||
Authorization: 'Bearer some-token',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('apollo response is 403.13', () => {
|
|
||||||
it.skip('dispatches logout', () => {
|
|
||||||
expect(storeDispatchMock).toBeCalledWith('logout', null)
|
|
||||||
})
|
|
||||||
|
|
||||||
it.skip('redirects to logout', () => {
|
|
||||||
expect(routerPushMock).toBeCalledWith('/logout')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
37
admin/src/plugins/apolloProvider.js
Normal file
37
admin/src/plugins/apolloProvider.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
import store from '../store/store'
|
||||||
|
import router from '../router/router'
|
||||||
|
import i18n from '../i18n'
|
||||||
|
|
||||||
|
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
||||||
|
|
||||||
|
const authLink = new ApolloLink((operation, forward) => {
|
||||||
|
const token = store.state.token
|
||||||
|
operation.setContext({
|
||||||
|
headers: {
|
||||||
|
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return forward(operation).map((response) => {
|
||||||
|
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
||||||
|
response.errors[0].message = i18n.t('error.session-expired')
|
||||||
|
store.dispatch('logout', null)
|
||||||
|
if (router.currentRoute.path !== '/logout') router.push('/logout')
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
const newToken = operation.getContext().response.headers.get('token')
|
||||||
|
if (newToken) store.commit('token', newToken)
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const apolloClient = new ApolloClient({
|
||||||
|
link: authLink.concat(httpLink),
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const apolloProvider = new VueApollo({
|
||||||
|
defaultClient: apolloClient,
|
||||||
|
})
|
||||||
178
admin/src/plugins/apolloProvider.test.js
Normal file
178
admin/src/plugins/apolloProvider.test.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import { ApolloClient, ApolloLink, HttpLink } from 'apollo-boost'
|
||||||
|
import './apolloProvider'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
|
import store from '../store/store'
|
||||||
|
import router from '../router/router'
|
||||||
|
import i18n from '../i18n'
|
||||||
|
|
||||||
|
jest.mock('vue-apollo')
|
||||||
|
jest.mock('../store/store')
|
||||||
|
jest.mock('../router/router')
|
||||||
|
jest.mock('../i18n')
|
||||||
|
|
||||||
|
jest.mock('apollo-boost', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
ApolloClient: jest.fn(),
|
||||||
|
ApolloLink: jest.fn(() => {
|
||||||
|
return { concat: jest.fn() }
|
||||||
|
}),
|
||||||
|
InMemoryCache: jest.fn(),
|
||||||
|
HttpLink: jest.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apolloProvider', () => {
|
||||||
|
it('calls the HttpLink', () => {
|
||||||
|
expect(HttpLink).toBeCalledWith({ uri: CONFIG.GRAPHQL_URI })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the ApolloLink', () => {
|
||||||
|
expect(ApolloLink).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the ApolloClient', () => {
|
||||||
|
expect(ApolloClient).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the VueApollo', () => {
|
||||||
|
expect(VueApollo).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('ApolloLink', () => {
|
||||||
|
// mock store
|
||||||
|
const storeDispatchMock = jest.fn()
|
||||||
|
const storeCommitMock = jest.fn()
|
||||||
|
store.state = {
|
||||||
|
token: 'some-token',
|
||||||
|
}
|
||||||
|
store.dispatch = storeDispatchMock
|
||||||
|
store.commit = storeCommitMock
|
||||||
|
|
||||||
|
// mock i18n.t
|
||||||
|
i18n.t = jest.fn((t) => t)
|
||||||
|
|
||||||
|
// mock apllo response
|
||||||
|
const responseMock = {
|
||||||
|
errors: [{ message: '403.13 - Client certificate revoked' }],
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock router
|
||||||
|
const routerPushMock = jest.fn()
|
||||||
|
router.push = routerPushMock
|
||||||
|
router.currentRoute = {
|
||||||
|
path: '/overview',
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock context
|
||||||
|
const setContextMock = jest.fn()
|
||||||
|
const getContextMock = jest.fn(() => {
|
||||||
|
return {
|
||||||
|
response: {
|
||||||
|
headers: {
|
||||||
|
get: jest.fn(() => 'another-token'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// mock apollo link function params
|
||||||
|
const operationMock = {
|
||||||
|
setContext: setContextMock,
|
||||||
|
getContext: getContextMock,
|
||||||
|
}
|
||||||
|
|
||||||
|
const forwardMock = jest.fn(() => {
|
||||||
|
return [responseMock]
|
||||||
|
})
|
||||||
|
|
||||||
|
// get apollo link callback
|
||||||
|
const middleware = ApolloLink.mock.calls[0][0]
|
||||||
|
|
||||||
|
describe('with token in store', () => {
|
||||||
|
it('sets authorization header with token', () => {
|
||||||
|
// run the apollo link callback with mocked params
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
expect(setContextMock).toBeCalledWith({
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer some-token',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('without token in store', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store.state.token = null
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets authorization header empty', () => {
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
expect(setContextMock).toBeCalledWith({
|
||||||
|
headers: {
|
||||||
|
Authorization: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is 403.13', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
// run the apollo link callback with mocked params
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dispatches logout', () => {
|
||||||
|
expect(storeDispatchMock).toBeCalledWith('logout', null)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('current route is not logout', () => {
|
||||||
|
it('redirects to logout', () => {
|
||||||
|
expect(routerPushMock).toBeCalledWith('/logout')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('current route is logout', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
router.currentRoute.path = '/logout'
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not redirect to logout', () => {
|
||||||
|
expect(routerPushMock).not.toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is with new token', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
delete responseMock.errors
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits new token to store', () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('token', 'another-token')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is without new token', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
getContextMock.mockReturnValue({
|
||||||
|
response: {
|
||||||
|
headers: {
|
||||||
|
get: jest.fn(() => null),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not commit token to store', () => {
|
||||||
|
expect(storeCommitMock).not.toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -1,6 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ['@babel/preset-env'],
|
presets: ['@babel/preset-env'],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
'transform-require-context',
|
||||||
[
|
[
|
||||||
'component',
|
'component',
|
||||||
{
|
{
|
||||||
|
|||||||
@ -22,4 +22,5 @@ module.exports = {
|
|||||||
testMatch: ['**/?(*.)+(spec|test).js?(x)'],
|
testMatch: ['**/?(*.)+(spec|test).js?(x)'],
|
||||||
// snapshotSerializers: ['jest-serializer-vue'],
|
// snapshotSerializers: ['jest-serializer-vue'],
|
||||||
transformIgnorePatterns: ['<rootDir>/node_modules/(?!vee-validate/dist/rules)'],
|
transformIgnorePatterns: ['<rootDir>/node_modules/(?!vee-validate/dist/rules)'],
|
||||||
|
testEnvironment: 'jest-environment-jsdom-sixteen',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,8 +22,9 @@
|
|||||||
"apollo-boost": "^0.4.9",
|
"apollo-boost": "^0.4.9",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^27.3.1",
|
||||||
"babel-plugin-require-context-hook": "^1.0.0",
|
"babel-plugin-require-context-hook": "^1.0.0",
|
||||||
|
"babel-plugin-transform-require-context": "^0.1.1",
|
||||||
"babel-preset-vue": "^2.0.2",
|
"babel-preset-vue": "^2.0.2",
|
||||||
"bootstrap": "4.3.1",
|
"bootstrap": "4.3.1",
|
||||||
"bootstrap-vue": "^2.5.0",
|
"bootstrap-vue": "^2.5.0",
|
||||||
@ -51,6 +52,7 @@
|
|||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-canvas-mock": "^2.3.1",
|
"jest-canvas-mock": "^2.3.1",
|
||||||
|
"jest-environment-jsdom-sixteen": "^2.0.0",
|
||||||
"nouislider": "^12.1.0",
|
"nouislider": "^12.1.0",
|
||||||
"particles-bg-vue": "1.2.3",
|
"particles-bg-vue": "1.2.3",
|
||||||
"perfect-scrollbar": "^1.3.0",
|
"perfect-scrollbar": "^1.3.0",
|
||||||
|
|||||||
@ -167,7 +167,10 @@ describe('SideBar', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mocks.$store.state.isAdmin = true
|
mocks.$store.state.isAdmin = true
|
||||||
mocks.$store.state.token = 'valid-token'
|
mocks.$store.state.token = 'valid-token'
|
||||||
window.location.assign = assignLocationSpy
|
delete window.location
|
||||||
|
window.location = {
|
||||||
|
assign: assignLocationSpy,
|
||||||
|
}
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
"error": "Fehler",
|
"error": "Fehler",
|
||||||
"no-account": "Leider konnten wir keinen Account finden mit diesen Daten!",
|
"no-account": "Leider konnten wir keinen Account finden mit diesen Daten!",
|
||||||
"no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!",
|
"no-email-verify": "Die Email wurde noch nicht bestätigt, bitte überprüfe deine Emails und klicke auf den Aktivierungslink!",
|
||||||
"session-expired": "Sitzung abgelaufen!"
|
"session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet."
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"amount": "Betrag",
|
"amount": "Betrag",
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
"error": "Error",
|
"error": "Error",
|
||||||
"no-account": "Unfortunately we could not find an account to the given data!",
|
"no-account": "Unfortunately we could not find an account to the given data!",
|
||||||
"no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!",
|
"no-email-verify": "Your email is not activated yet, please check your emails and click the activation link!",
|
||||||
"session-expired": "The session expired"
|
"session-expired": "The session was closed for security reasons."
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
|
|||||||
@ -3,9 +3,6 @@ import DashboardPlugin from './plugins/dashboard-plugin'
|
|||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import i18n from './i18n.js'
|
import i18n from './i18n.js'
|
||||||
import { loadAllRules } from './validation-rules'
|
import { loadAllRules } from './validation-rules'
|
||||||
import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
|
|
||||||
import VueApollo from 'vue-apollo'
|
|
||||||
import CONFIG from './config'
|
|
||||||
|
|
||||||
import addNavigationGuards from './routes/guards'
|
import addNavigationGuards from './routes/guards'
|
||||||
|
|
||||||
@ -13,42 +10,22 @@ import { store } from './store/store'
|
|||||||
|
|
||||||
import router from './routes/router'
|
import router from './routes/router'
|
||||||
|
|
||||||
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
import { apolloProvider } from './plugins/apolloProvider'
|
||||||
|
|
||||||
const authLink = new ApolloLink((operation, forward) => {
|
|
||||||
const token = store.state.token
|
|
||||||
operation.setContext({
|
|
||||||
headers: {
|
|
||||||
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return forward(operation).map((response) => {
|
|
||||||
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
|
||||||
response.errors[0].message = i18n.t('error.session-expired')
|
|
||||||
store.dispatch('logout', null)
|
|
||||||
if (router.currentRoute.path !== '/login') router.push('/login')
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
const newToken = operation.getContext().response.headers.get('token')
|
|
||||||
if (newToken) store.commit('token', newToken)
|
|
||||||
return response
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const apolloClient = new ApolloClient({
|
|
||||||
link: authLink.concat(httpLink),
|
|
||||||
cache: new InMemoryCache(),
|
|
||||||
uri: CONFIG.GRAPHQL_URI,
|
|
||||||
})
|
|
||||||
|
|
||||||
const apolloProvider = new VueApollo({
|
|
||||||
defaultClient: apolloClient,
|
|
||||||
})
|
|
||||||
|
|
||||||
// plugin setup
|
// plugin setup
|
||||||
Vue.use(DashboardPlugin)
|
Vue.use(DashboardPlugin)
|
||||||
Vue.config.productionTip = false
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
|
Vue.toasted.register(
|
||||||
|
'error',
|
||||||
|
(payload) => {
|
||||||
|
return payload.replace(/^GraphQL error: /, '')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'error',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
loadAllRules(i18n)
|
loadAllRules(i18n)
|
||||||
|
|
||||||
addNavigationGuards(router, store, apolloProvider.defaultClient)
|
addNavigationGuards(router, store, apolloProvider.defaultClient)
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export const getCommunityInfoMixin = {
|
|||||||
return result.data.getCommunityInfo
|
return result.data.getCommunityInfo
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
37
frontend/src/plugins/apolloProvider.js
Normal file
37
frontend/src/plugins/apolloProvider.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ApolloClient, ApolloLink, InMemoryCache, HttpLink } from 'apollo-boost'
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
import { store } from '../store/store'
|
||||||
|
import router from '../routes/router'
|
||||||
|
import i18n from '../i18n'
|
||||||
|
|
||||||
|
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
||||||
|
|
||||||
|
const authLink = new ApolloLink((operation, forward) => {
|
||||||
|
const token = store.state.token
|
||||||
|
operation.setContext({
|
||||||
|
headers: {
|
||||||
|
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return forward(operation).map((response) => {
|
||||||
|
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
||||||
|
response.errors[0].message = i18n.t('error.session-expired')
|
||||||
|
store.dispatch('logout', null)
|
||||||
|
if (router.currentRoute.path !== '/login') router.push('/login')
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
const newToken = operation.getContext().response.headers.get('token')
|
||||||
|
if (newToken) store.commit('token', newToken)
|
||||||
|
return response
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const apolloClient = new ApolloClient({
|
||||||
|
link: authLink.concat(httpLink),
|
||||||
|
cache: new InMemoryCache(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const apolloProvider = new VueApollo({
|
||||||
|
defaultClient: apolloClient,
|
||||||
|
})
|
||||||
178
frontend/src/plugins/apolloProvider.test.js
Normal file
178
frontend/src/plugins/apolloProvider.test.js
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
import { ApolloClient, ApolloLink, HttpLink } from 'apollo-boost'
|
||||||
|
import './apolloProvider'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
|
import { store } from '../store/store.js'
|
||||||
|
import router from '../routes/router'
|
||||||
|
import i18n from '../i18n'
|
||||||
|
|
||||||
|
jest.mock('vue-apollo')
|
||||||
|
jest.mock('../store/store')
|
||||||
|
jest.mock('../routes/router')
|
||||||
|
jest.mock('../i18n')
|
||||||
|
|
||||||
|
jest.mock('apollo-boost', () => {
|
||||||
|
return {
|
||||||
|
__esModule: true,
|
||||||
|
ApolloClient: jest.fn(),
|
||||||
|
ApolloLink: jest.fn(() => {
|
||||||
|
return { concat: jest.fn() }
|
||||||
|
}),
|
||||||
|
InMemoryCache: jest.fn(),
|
||||||
|
HttpLink: jest.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apolloProvider', () => {
|
||||||
|
it('calls the HttpLink', () => {
|
||||||
|
expect(HttpLink).toBeCalledWith({ uri: CONFIG.GRAPHQL_URI })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the ApolloLink', () => {
|
||||||
|
expect(ApolloLink).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the ApolloClient', () => {
|
||||||
|
expect(ApolloClient).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls the VueApollo', () => {
|
||||||
|
expect(VueApollo).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('ApolloLink', () => {
|
||||||
|
// mock store
|
||||||
|
const storeDispatchMock = jest.fn()
|
||||||
|
const storeCommitMock = jest.fn()
|
||||||
|
store.state = {
|
||||||
|
token: 'some-token',
|
||||||
|
}
|
||||||
|
store.dispatch = storeDispatchMock
|
||||||
|
store.commit = storeCommitMock
|
||||||
|
|
||||||
|
// mock i18n.t
|
||||||
|
i18n.t = jest.fn((t) => t)
|
||||||
|
|
||||||
|
// mock apllo response
|
||||||
|
const responseMock = {
|
||||||
|
errors: [{ message: '403.13 - Client certificate revoked' }],
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock router
|
||||||
|
const routerPushMock = jest.fn()
|
||||||
|
router.push = routerPushMock
|
||||||
|
router.currentRoute = {
|
||||||
|
path: '/overview',
|
||||||
|
}
|
||||||
|
|
||||||
|
// mock context
|
||||||
|
const setContextMock = jest.fn()
|
||||||
|
const getContextMock = jest.fn(() => {
|
||||||
|
return {
|
||||||
|
response: {
|
||||||
|
headers: {
|
||||||
|
get: jest.fn(() => 'another-token'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// mock apollo link function params
|
||||||
|
const operationMock = {
|
||||||
|
setContext: setContextMock,
|
||||||
|
getContext: getContextMock,
|
||||||
|
}
|
||||||
|
|
||||||
|
const forwardMock = jest.fn(() => {
|
||||||
|
return [responseMock]
|
||||||
|
})
|
||||||
|
|
||||||
|
// get apollo link callback
|
||||||
|
const middleware = ApolloLink.mock.calls[0][0]
|
||||||
|
|
||||||
|
describe('with token in store', () => {
|
||||||
|
it('sets authorization header with token', () => {
|
||||||
|
// run the apollo link callback with mocked params
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
expect(setContextMock).toBeCalledWith({
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer some-token',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('without token in store', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store.state.token = null
|
||||||
|
})
|
||||||
|
|
||||||
|
it('sets authorization header empty', () => {
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
expect(setContextMock).toBeCalledWith({
|
||||||
|
headers: {
|
||||||
|
Authorization: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is 403.13', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
// run the apollo link callback with mocked params
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dispatches logout', () => {
|
||||||
|
expect(storeDispatchMock).toBeCalledWith('logout', null)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('current route is not login', () => {
|
||||||
|
it('redirects to logout', () => {
|
||||||
|
expect(routerPushMock).toBeCalledWith('/login')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('current route is login', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
router.currentRoute.path = '/login'
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not redirect to login', () => {
|
||||||
|
expect(routerPushMock).not.toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is with new token', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
delete responseMock.errors
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits new token to store', () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('token', 'another-token')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('apollo response is without new token', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
getContextMock.mockReturnValue({
|
||||||
|
response: {
|
||||||
|
headers: {
|
||||||
|
get: jest.fn(() => null),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
middleware(operationMock, forwardMock)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not commit token to store', () => {
|
||||||
|
expect(storeCommitMock).not.toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@ -4,8 +4,11 @@ import Vue from 'vue'
|
|||||||
import GlobalComponents from './globalComponents'
|
import GlobalComponents from './globalComponents'
|
||||||
import GlobalDirectives from './globalDirectives'
|
import GlobalDirectives from './globalDirectives'
|
||||||
|
|
||||||
|
import Toasted from 'vue-toasted'
|
||||||
|
|
||||||
jest.mock('./globalComponents')
|
jest.mock('./globalComponents')
|
||||||
jest.mock('./globalDirectives')
|
jest.mock('./globalDirectives')
|
||||||
|
jest.mock('vue-toasted')
|
||||||
|
|
||||||
jest.mock('vue')
|
jest.mock('vue')
|
||||||
|
|
||||||
@ -22,4 +25,21 @@ describe('dashboard plugin', () => {
|
|||||||
it('installs the global directives', () => {
|
it('installs the global directives', () => {
|
||||||
expect(vueUseMock).toBeCalledWith(GlobalDirectives)
|
expect(vueUseMock).toBeCalledWith(GlobalDirectives)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('vue toasted', () => {
|
||||||
|
const toastedAction = vueUseMock.mock.calls[11][1].action.onClick
|
||||||
|
const goAwayMock = jest.fn()
|
||||||
|
const toastObject = {
|
||||||
|
goAway: goAwayMock,
|
||||||
|
}
|
||||||
|
|
||||||
|
it('installs vue toasted', () => {
|
||||||
|
expect(vueUseMock).toBeCalledWith(Toasted, expect.anything())
|
||||||
|
})
|
||||||
|
|
||||||
|
it('onClick calls goAway(0)', () => {
|
||||||
|
toastedAction({}, toastObject)
|
||||||
|
expect(goAwayMock).toBeCalledWith(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -143,6 +143,13 @@ describe('router', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('password with param comingFrom', () => {
|
||||||
|
it('loads the "Password" component', async () => {
|
||||||
|
const component = await routes.find((r) => r.path === '/password/:comingFrom').component()
|
||||||
|
expect(component.default.name).toBe('password')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('register-community', () => {
|
describe('register-community', () => {
|
||||||
it('loads the "registerCommunity" component', async () => {
|
it('loads the "registerCommunity" component', async () => {
|
||||||
const component = await routes.find((r) => r.path === '/register-community').component()
|
const component = await routes.find((r) => r.path === '/register-community').component()
|
||||||
|
|||||||
@ -39,8 +39,10 @@ describe('DashboardLayoutGdd', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toasterMock,
|
error: toasterMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloMock,
|
query: apolloMock,
|
||||||
},
|
},
|
||||||
@ -266,7 +268,7 @@ describe('DashboardLayoutGdd', () => {
|
|||||||
expect(wrapper.vm.pending).toBeTruthy()
|
expect(wrapper.vm.pending).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('calls $toasted.error method', () => {
|
it('calls $toasted.global.error method', () => {
|
||||||
expect(toasterMock).toBeCalledWith('Ouch!')
|
expect(toasterMock).toBeCalledWith('Ouch!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -133,7 +133,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.pending = true
|
this.pending = true
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
// what to do when loading balance fails?
|
// what to do when loading balance fails?
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -37,8 +37,10 @@ describe('GdtTransactionList ', () => {
|
|||||||
$n: jest.fn((n) => n),
|
$n: jest.fn((n) => n),
|
||||||
$d: jest.fn((d) => d),
|
$d: jest.fn((d) => d),
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloMock,
|
query: apolloMock,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export default {
|
|||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -52,8 +52,10 @@ describe('Login', () => {
|
|||||||
push: mockRouterPush,
|
push: mockRouterPush,
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloQueryMock,
|
query: apolloQueryMock,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.message.includes('No user with this credentials')) {
|
if (error.message.includes('No user with this credentials')) {
|
||||||
this.$toasted.error(this.$t('error.no-account'))
|
this.$toasted.global.error(this.$t('error.no-account'))
|
||||||
} else {
|
} else {
|
||||||
// : this.$t('error.no-email-verify')
|
// : this.$t('error.no-email-verify')
|
||||||
this.$router.push('/reset/login')
|
this.$router.push('/reset/login')
|
||||||
|
|||||||
@ -49,8 +49,10 @@ describe('Register', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const stubs = {
|
const stubs = {
|
||||||
|
|||||||
@ -37,8 +37,10 @@ describe('RegisterCommunity', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const stubs = {
|
const stubs = {
|
||||||
|
|||||||
@ -79,8 +79,10 @@ describe('RegisterSelectCommunity', () => {
|
|||||||
show: spinnerMock,
|
show: spinnerMock,
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toasterMock,
|
error: toasterMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const stubs = {
|
const stubs = {
|
||||||
|
|||||||
@ -76,7 +76,7 @@ export default {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
loader.hide()
|
loader.hide()
|
||||||
this.pending = false
|
this.pending = false
|
||||||
|
|||||||
@ -30,8 +30,10 @@ const createMockObject = (comingFrom) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
|
global: {
|
||||||
error: toasterMock,
|
error: toasterMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$router: {
|
$router: {
|
||||||
push: routerPushMock,
|
push: routerPushMock,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -96,10 +96,10 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.message.includes('Code is older than 10 minutes')) {
|
if (error.message.includes('Code is older than 10 minutes')) {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
this.$router.push('/password/reset')
|
this.$router.push('/password/reset')
|
||||||
} else {
|
} else {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@ -24,8 +24,10 @@ describe('UserCard_CoinAnimation', () => {
|
|||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: mockAPIcall,
|
mutate: mockAPIcall,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -58,7 +58,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.CoinAnimationStatus = this.$store.state.coinanimation
|
this.CoinAnimationStatus = this.$store.state.coinanimation
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -25,8 +25,10 @@ describe('UserCard_FormUserData', () => {
|
|||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: mockAPIcall,
|
mutate: mockAPIcall,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -124,7 +124,7 @@ export default {
|
|||||||
this.$toasted.success(this.$t('settings.name.change-success'))
|
this.$toasted.success(this.$t('settings.name.change-success'))
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -17,8 +17,10 @@ describe('UserCard_FormUserPasswort', () => {
|
|||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: changePasswordProfileMock,
|
mutate: changePasswordProfileMock,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export default {
|
|||||||
this.cancelEdit()
|
this.cancelEdit()
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -31,8 +31,10 @@ describe('UserCard_FormUsername', () => {
|
|||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: mockAPIcall,
|
mutate: mockAPIcall,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export default {
|
|||||||
this.$toasted.success(this.$t('settings.name.change-success'))
|
this.$toasted.success(this.$t('settings.name.change-success'))
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
this.showUsername = true
|
this.showUsername = true
|
||||||
this.username = this.$store.state.username
|
this.username = this.$store.state.username
|
||||||
this.form.username = this.$store.state.username
|
this.form.username = this.$store.state.username
|
||||||
|
|||||||
@ -28,8 +28,10 @@ describe('UserCard_Language', () => {
|
|||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: mockAPIcall,
|
mutate: mockAPIcall,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -101,7 +101,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.language = this.$store.state.language
|
this.language = this.$store.state.language
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
buildTagFromLanguageString() {
|
buildTagFromLanguageString() {
|
||||||
|
|||||||
@ -25,8 +25,10 @@ describe('UserCard_Newsletter', () => {
|
|||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
success: toastSuccessMock,
|
success: toastSuccessMock,
|
||||||
|
global: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: mockAPIcall,
|
mutate: mockAPIcall,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.newsletterState = this.$store.state.newsletterState
|
this.newsletterState = this.$store.state.newsletterState
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.global.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user