Merge branch '1697-refactor-thx-page-#1' of github.com:gradido/gradido into 1697-refactor-thx-page-#2

# Conflicts:
#	frontend/src/components/Message/Message.spec.js
#	frontend/src/components/Message/Message.vue
This commit is contained in:
Wolfgang Huß 2022-05-05 15:14:42 +02:00
commit 0a8bbe7ea6
17 changed files with 149 additions and 117 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ package-lock.json
/deployment/bare_metal/nginx/update-page/updating.html
/deployment/bare_metal/log
/deployment/bare_metal/backup
/.nvmrc

3
admin/.gitignore vendored
View File

@ -9,4 +9,5 @@ dist/
coverage/
# emacs
*~
*~
/.nvmrc

3
backend/.gitignore vendored
View File

@ -5,4 +5,5 @@
package-json.lock
coverage
# emacs
*~
*~
/.nvmrc

3
database/.gitignore vendored
View File

@ -24,4 +24,5 @@ package-lock.json
coverage/
*~
*~
/.nvmrc

View File

@ -2,6 +2,9 @@
# This assums you have root access via ssh to your cleanly setup server
# Furthermore this assumes you have debian (11 64bit) running
# Check your (Sub-)Domain with your Provider.
# In this document gddhost.tld refers to your chosen domain
> ssh root@gddhost.tld
# change root default shell
@ -87,9 +90,10 @@
# Adjust .env
# NOTE ';' can not be part of any value
# The Github Secret is Created on Github in Settimgs -> Webhooks
> cd gradido/deployment/bare_metal
> cp .env.dist .env
> nano .env
>> Adjust values accordingly
# TODO the install.sh is not yet ready to run directly - consider to use it as pattern to do it manually
> ./install.sh
> ./install.sh

3
frontend/.gitignore vendored
View File

@ -23,4 +23,5 @@ package-lock.json
coverage/
*~
*~
/.nvmrc

View File

@ -30,14 +30,34 @@ describe('Message', () => {
expect(wrapper.find('div.header').exists()).toBe(true)
})
it('renders title, subtitle, and button text', () => {
expect(wrapper.find('.test-message-headline').text()).toBe('Headline text')
expect(wrapper.find('.test-message-subtitle').text()).toBe('Subtitle text')
expect(wrapper.find('.test-message-button').text()).toBe('login')
describe('with button', () => {
it('renders title, subtitle, and button text', () => {
expect(wrapper.find('.test-message-headline').text()).toBe('Headline text')
expect(wrapper.find('.test-message-subtitle').text()).toBe('Subtitle text')
expect(wrapper.find('.test-message-button').text()).toBe('login')
})
it('button link redirects to /login', () => {
expect(wrapper.find('a.btn').attributes('href')).toBe('/login')
})
})
it('button link redirects to /login', () => {
expect(wrapper.find('a.btn').attributes('href')).toBe('/login')
describe('without button', () => {
beforeEach(() => {
wrapper.setProps({
buttonText: null,
linkTo: null,
})
})
it('renders title, subtitle, and button text', () => {
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.title')
expect(wrapper.find('.test-message-subtitle').text()).toBe('site.thx.email')
})
it('button is not shown', () => {
expect(wrapper.find('.test-message-button').exists()).toBe(false)
})
})
})
})

View File

@ -6,12 +6,7 @@
<p class="h1 test-message-headline">{{ headline }}</p>
<p class="h4 test-message-subtitle">{{ subtitle }}</p>
<hr />
<b-button
v-if="showButton()"
class="test-message-button"
:to="buttonLinkTo()"
@click="optionalCallback()"
>
<b-button v-if="showButton" class="test-message-button" :to="buttonLinkTo">
{{ buttonText }}
</b-button>
</div>
@ -28,17 +23,11 @@ export default {
subtitle: { type: String, required: true },
buttonText: { type: String, required: false, default: null },
linkTo: { type: String, required: false, default: null },
callback: { type: Function, required: false, default: null },
code: { type: String, required: false, default: null }, // Wolle: to be removed by adding it directly to the "linkTo"
},
methods: {
optionalCallback() {
if (this.callback) {
this.callback()
}
},
computed: {
showButton() {
return this.buttonText && (this.linkTo || this.callback)
return this.buttonText && this.linkTo
},
buttonLinkTo() {
return this.linkTo ? this.linkTo + (this.code ? `/${this.code}` : '') : null

View File

@ -227,6 +227,36 @@ describe('TransactionLinkSummary', () => {
fetchPolicy: 'network-only',
})
})
describe('close transaction link list', () => {
beforeEach(async () => {
wrapper.find('div.transaction-link-details').trigger('click')
})
describe('reopen transaction link list', () => {
beforeEach(async () => {
jest.clearAllMocks()
wrapper.find('div.transaction-link-details').trigger('click')
})
it('calls the API once', () => {
expect(apolloQueryMock).toBeCalledTimes(1)
})
it('calls the API with current page one', () => {
expect(apolloQueryMock).toBeCalledWith({
query: listTransactionLinks,
variables: {
currentPage: 1,
},
fetchPolicy: 'network-only',
})
})
it('has four transactionLinks', () => {
expect(wrapper.vm.transactionLinks).toHaveLength(4)
})
})
})
})
})

View File

@ -84,7 +84,11 @@ export default {
this.visible = false
} else {
this.transactionLinks = []
this.updateListTransactionLinks()
if (this.currentPage === 1) {
this.updateListTransactionLinks()
} else {
this.currentPage = 1
}
this.visible = true
}
},

View File

@ -35,6 +35,7 @@
"error": "Fehler!",
"no-account": "Leider konnten wir keinen (aktivierten) Account mit diesen Daten finden.",
"no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt.",
"no-user": "Kein Benutzer mit diesen Anmeldedaten.",
"session-expired": "Die Sitzung wurde aus Sicherheitsgründen beendet.",
"unknown-error": "Unbekanter Fehler: ",
"user-already-exists": "Ein Benutzer mit diesen Daten existiert bereits."
@ -215,9 +216,6 @@
"new_wallet": "Neues Konto erstellen",
"signin": "Anmelden"
},
"register": {
"message-button-text": "Alles klar"
},
"signup": {
"agree": "Ich stimme der <a href='https://gradido.net/de/datenschutz/' target='_blank' >Datenschutzerklärung</a> zu.",
"dont_match": "Die Passwörter stimmen nicht überein.",

View File

@ -35,6 +35,7 @@
"error": "Error!",
"no-account": "Unfortunately we could not find an (activated) account to the given data.",
"no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.",
"no-user": "No user with this credentials.",
"session-expired": "The session was closed for security reasons.",
"unknown-error": "Unknown error: ",
"user-already-exists": "A user with this data already exists."
@ -215,9 +216,6 @@
"new_wallet": "Create new account",
"signin": "Sign in"
},
"register": {
"message-button-text": "Okay"
},
"signup": {
"agree": "I agree to the <a href='https://gradido.net/en/datenschutz/' target='_blank' > privacy policy</a>.",
"dont_match": "Passwords don't match.",

View File

@ -13,7 +13,7 @@
</div>
</b-container>
</div>
<b-container v-if="!showPageMessage" class="mt--8 p-1">
<b-container v-if="enterData" class="mt--8 p-1">
<b-row class="justify-content-center">
<b-col lg="6" md="8">
<b-card no-body class="border-0 gradido-custom-background">
@ -75,6 +75,11 @@ export default {
success: null,
}
},
created() {
if (this.$route.params.comingFrom) {
this.subtitle = 'settings.password.resend_subtitle'
}
},
methods: {
async onSubmit() {
this.$apollo
@ -95,10 +100,10 @@ export default {
})
},
},
created() {
if (this.$route.params.comingFrom) {
this.subtitle = 'settings.password.resend_subtitle'
}
computed: {
enterData() {
return !this.showPageMessage
},
},
}
</script>

View File

@ -219,7 +219,7 @@ describe('Login', () => {
describe('login fails with "User email not validated"', () => {
beforeEach(async () => {
await createError('GraphQL error: User email not validated')
await createError('GraphQL error: User email not validated.')
})
it('hides the spinner', () => {
@ -251,7 +251,7 @@ describe('Login', () => {
describe('login fails with "User has no password set yet"', () => {
beforeEach(async () => {
await createError('GraphQL error: User has no password set yet')
await createError('GraphQL error: User has no password set yet.')
})
it('shows error title, subtitle, login button', () => {
@ -277,26 +277,35 @@ describe('Login', () => {
})
})
describe('login fails with "No user with this credentials"', () => {
beforeEach(async () => {
await createError('GraphQL error: No user with this credentials.')
})
it('shows no error message on the page', () => {
// don't show any error on the page! against boots
expect(wrapper.vm.showPageMessage).toBe(false)
expect(wrapper.find('.test-message-headline').exists()).toBe(false)
expect(wrapper.find('.test-message-subtitle').exists()).toBe(false)
expect(wrapper.find('.test-message-button').exists()).toBe(false)
})
it('toasts the error message', () => {
expect(toastErrorSpy).toBeCalledWith('error.no-user')
})
})
describe('login fails with an unknow error', () => {
beforeEach(async () => {
await createError(' Unknow error')
})
it('shows error title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe(
'error.unknown-error Unknow error',
)
expect(wrapper.find('.test-message-button').text()).toBe('settings.password.reset')
})
it('button link directs to "/forgot-password"', () => {
expect(wrapper.find('.test-message-button').attributes('href')).toBe('/forgot-password')
})
it.skip('click redirects to "/forgot-password"', () => {
// expect(mockRouterPush).toBeCalledWith('/forgot-password')
it('shows no error message on the page', () => {
// don't show any error on the page! against boots
expect(wrapper.vm.showPageMessage).toBe(false)
expect(wrapper.find('.test-message-headline').exists()).toBe(false)
expect(wrapper.find('.test-message-subtitle').exists()).toBe(false)
expect(wrapper.find('.test-message-button').exists()).toBe(false)
})
it('toasts the error message', () => {

View File

@ -13,7 +13,7 @@
</div>
</b-container>
</div>
<b-container v-if="!showPageMessage" class="mt--8 p-1">
<b-container v-if="enterData" class="mt--8 p-1">
<b-row class="justify-content-center">
<b-col lg="5" md="7">
<b-card no-body class="border-0 mb-0 gradido-custom-background">
@ -134,17 +134,21 @@ export default {
this.errorSubtitle = this.$t('site.thx.unsetPassword')
this.errorLinkTo = '/reset-password/login'
this.toastError(this.$t('error.no-account'))
} else if (error.message.includes('No user with this credentials')) {
// don't show any error on the page! against boots
this.toastError(this.$t('error.no-user'))
} else {
// appeared errors: 'GraphQL error: No user with this credentials'
const errorMessage = this.$t('error.unknown-error') + error.message
this.showPageMessage = true
this.errorSubtitle = errorMessage
this.errorLinkTo = '/forgot-password'
this.toastError(errorMessage)
// don't show any error on the page! against boots
this.toastError(this.$t('error.unknown-error') + error.message)
}
loader.hide()
})
},
},
computed: {
enterData() {
return !this.showPageMessage
},
},
}
</script>

View File

@ -234,24 +234,17 @@ describe('Register', () => {
await createError('GraphQL error: User already exists.')
})
it('shows success title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe('error.user-already-exists')
expect(wrapper.find('.test-message-button').text()).toBe(
'site.register.message-button-text',
)
it('shows no error message on the page', () => {
// don't show any error on the page! against boots
expect(wrapper.vm.showPageMessage).toBe(false)
expect(wrapper.find('.test-message-headline').exists()).toBe(false)
expect(wrapper.find('.test-message-subtitle').exists()).toBe(false)
expect(wrapper.find('.test-message-button').exists()).toBe(false)
})
it('toasts the error message', () => {
expect(toastErrorSpy).toBeCalledWith('error.user-already-exists')
})
it('click calls "solveError"', async () => {
wrapper.find('.test-message-button').trigger('click')
await wrapper.vm.$nextTick()
expect(wrapper.vm.showPageMessage).toBe(false)
})
})
describe('server sends back error "Unknown error"', () => {
@ -259,26 +252,17 @@ describe('Register', () => {
await createError(' Unknown error.')
})
it('shows success title, subtitle, login button', () => {
expect(wrapper.vm.showPageMessage).toBe(true)
expect(wrapper.find('.test-message-headline').text()).toBe('site.thx.errorTitle')
expect(wrapper.find('.test-message-subtitle').text()).toBe(
'error.unknown-error Unknown error.',
)
expect(wrapper.find('.test-message-button').text()).toBe(
'site.register.message-button-text',
)
it('shows no error message on the page', () => {
// don't show any error on the page! against boots
expect(wrapper.vm.showPageMessage).toBe(false)
expect(wrapper.find('.test-message-headline').exists()).toBe(false)
expect(wrapper.find('.test-message-subtitle').exists()).toBe(false)
expect(wrapper.find('.test-message-button').exists()).toBe(false)
})
it('toasts the error message', () => {
expect(toastErrorSpy).toBeCalledWith('error.unknown-error Unknown error.')
})
it('click calls "solveError"', async () => {
wrapper.find('.test-message-button').trigger('click')
await wrapper.vm.$nextTick()
expect(wrapper.vm.showPageMessage).toBe(false)
})
})
})

View File

@ -15,7 +15,7 @@
</div>
<!-- Page content -->
<b-container v-if="!showPageMessage" class="mt--8 p-1">
<b-container v-if="enterData" class="mt--8 p-1">
<!-- Table -->
<b-row class="justify-content-center">
@ -165,18 +165,7 @@
</b-row>
</b-container>
<b-container v-else class="mt--8 p-1">
<message
v-if="success"
:headline="$t('site.thx.title')"
:subtitle="$t('site.thx.register')"
/>
<message
v-else
:headline="$t('site.thx.errorTitle')"
:subtitle="messageError"
:buttonText="$t('site.register.message-button-text')"
:callback="solveError"
/>
<message :headline="$t('site.thx.title')" :subtitle="$t('site.thx.register')" />
</b-container>
<!--
<div class="text-center pt-4">
@ -214,7 +203,6 @@ export default {
language: '',
showPageMessage: false,
submitted: false,
messageError: '',
publisherId: this.$store.state.publisherId,
redeemCode: this.$route.params.code,
CONFIG,
@ -246,30 +234,21 @@ export default {
})
.then(() => {
this.showPageMessage = true
this.success = true
})
.catch((error) => {
this.showPageMessage = true
this.success = false
// don't show any error on the page! against boots
let errorMessage
switch (error.message) {
case 'GraphQL error: User already exists.':
this.messageError = this.$t('error.user-already-exists')
errorMessage = this.$t('error.user-already-exists')
break
default:
this.messageError = this.$t('error.unknown-error') + error.message
errorMessage = this.$t('error.unknown-error') + error.message
break
}
this.toastError(this.messageError)
this.toastError(errorMessage)
})
},
solveError() {
this.showPageMessage = false
this.messageError = ''
this.form.email = ''
this.form.firstname = ''
this.form.lastname = ''
this.form.agree = false
},
},
computed: {
namesFilled() {
@ -286,6 +265,9 @@ export default {
disabled() {
return !(this.namesFilled && this.emailFilled && this.form.agree && !!this.language)
},
enterData() {
return !this.showPageMessage
},
},
}
</script>