mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
fix(frontend): post migration fixes (#3372)
* fix(frontend): post migration fixes * fix(frontend): align with stylelint * fix(frontend): fix tests and dashboard layout --------- Co-authored-by: einhornimmond <dario.rekowski@gmx.de>
This commit is contained in:
parent
b8df97068f
commit
71f19d366f
@ -48,6 +48,7 @@
|
||||
"portal-vue": "^3.0.0",
|
||||
"qrcanvas-vue": "3",
|
||||
"regenerator-runtime": "^0.13.7",
|
||||
"tua-body-scroll-lock": "^1.5.1",
|
||||
"uuid": "^9.0.0",
|
||||
"vee-validate": "^4.13.2",
|
||||
"vite": "3.2.10",
|
||||
|
||||
@ -1,68 +1,5 @@
|
||||
// import { shallowMount, RouterLinkStub } from '@vue/test-utils'
|
||||
// import App from './App'
|
||||
//
|
||||
// const localVue = global.localVue
|
||||
// const mockStoreCommit = jest.fn()
|
||||
//
|
||||
// const stubs = {
|
||||
// RouterLink: RouterLinkStub,
|
||||
// RouterView: true,
|
||||
// }
|
||||
//
|
||||
// describe('App', () => {
|
||||
// const mocks = {
|
||||
// $i18n: {
|
||||
// locale: 'en',
|
||||
// },
|
||||
// $t: jest.fn((t) => t),
|
||||
// $store: {
|
||||
// commit: mockStoreCommit,
|
||||
// state: {
|
||||
// token: null,
|
||||
// },
|
||||
// },
|
||||
// $route: {
|
||||
// meta: {
|
||||
// requiresAuth: false,
|
||||
// },
|
||||
// params: {},
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// let wrapper
|
||||
//
|
||||
// const Wrapper = () => {
|
||||
// return shallowMount(App, { localVue, mocks, stubs })
|
||||
// }
|
||||
//
|
||||
// describe('mount', () => {
|
||||
// beforeEach(() => {
|
||||
// wrapper = Wrapper()
|
||||
// })
|
||||
//
|
||||
// it('renders the App', () => {
|
||||
// expect(wrapper.find('#app').exists()).toBe(true)
|
||||
// })
|
||||
//
|
||||
// it('has a component AuthLayout', () => {
|
||||
// expect(wrapper.findComponent({ name: 'AuthLayout' }).exists()).toBe(true)
|
||||
// })
|
||||
//
|
||||
// describe('route requires authorization', () => {
|
||||
// beforeEach(async () => {
|
||||
// mocks.$route.meta.requiresAuth = true
|
||||
// wrapper = Wrapper()
|
||||
// })
|
||||
//
|
||||
// it('has a component DashboardLayout', () => {
|
||||
// expect(wrapper.findComponent({ name: 'DashboardLayout' }).exists()).toBe(true)
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
// })
|
||||
|
||||
import { shallowMount } from '@vue/test-utils'
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import { describe, it, expect, beforeEach } from 'vitest'
|
||||
import App from './App'
|
||||
import DashboardLayout from '@/layouts/DashboardLayout'
|
||||
import AuthLayout from '@/layouts/AuthLayout'
|
||||
|
||||
@ -345,3 +345,15 @@ a:hover,
|
||||
.gdd-toaster-body {
|
||||
color: rgb(255 255 255);
|
||||
}
|
||||
|
||||
.gdd-toaster-body-darken {
|
||||
color: #2c2c2c;
|
||||
}
|
||||
|
||||
input.rounded-input {
|
||||
border-radius: 17px;
|
||||
}
|
||||
|
||||
.fs-7 {
|
||||
font-size: 14px !important;
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<div class="mb-3">
|
||||
<BButton
|
||||
v-if="!pending && transactionLinks.length < transactionLinkCount"
|
||||
class="test-button-load-more"
|
||||
class="test-button-load-more w-100 rounded-5"
|
||||
block
|
||||
variant="outline-primary"
|
||||
@click.stop="loadMoreLinks"
|
||||
|
||||
@ -64,11 +64,11 @@ describe('InputEmail', () => {
|
||||
})
|
||||
|
||||
it('has the placeholder "input-field-placeholder"', () => {
|
||||
expect(wrapper.find('input').attributes('placeholder')).toBe('input-field-placeholder')
|
||||
expect(wrapper.find('input').attributes('placeholder')).toBe('form.email')
|
||||
})
|
||||
|
||||
it('has the label "input-field-label"', () => {
|
||||
expect(wrapper.find('label').text()).toBe('input-field-label')
|
||||
expect(wrapper.find('label').text()).toBe('form.email')
|
||||
})
|
||||
|
||||
it('has the label for "input-field-name-input-field"', () => {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
:placeholder="defaultTranslations.placeholder"
|
||||
type="email"
|
||||
trim
|
||||
class="rounded-input"
|
||||
:class="$route.path === '/send' ? 'bg-248' : ''"
|
||||
:disabled="disabled"
|
||||
autocomplete="off"
|
||||
@ -33,14 +34,6 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'email',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Email',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Email',
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@ -54,8 +47,8 @@ const { value, errorMessage, validate, meta } = useField(() => props.name, 'requ
|
||||
const { t } = useI18n()
|
||||
|
||||
const defaultTranslations = computed(() => ({
|
||||
label: props.label ?? t('form.email'),
|
||||
placeholder: props.placeholder ?? t('form.email'),
|
||||
label: t('form.email'),
|
||||
placeholder: t('form.email'),
|
||||
}))
|
||||
|
||||
const normalizeEmail = (emailAddress) => {
|
||||
|
||||
@ -80,7 +80,7 @@ describe('InputPassword', () => {
|
||||
})
|
||||
|
||||
it('has the placeholder "input-field-placeholder"', () => {
|
||||
expect(wrapper.find('input').attributes('placeholder')).toEqual('input-field-placeholder')
|
||||
expect(wrapper.find('input').attributes('placeholder')).toEqual('form.password')
|
||||
})
|
||||
|
||||
it('has the value ""', () => {
|
||||
@ -88,7 +88,7 @@ describe('InputPassword', () => {
|
||||
})
|
||||
|
||||
it('has the label "input-field-label"', () => {
|
||||
expect(wrapper.find('label').text()).toEqual('input-field-label')
|
||||
expect(wrapper.find('label').text()).toEqual('form.password')
|
||||
})
|
||||
|
||||
it('has the label for "input-field-name-input-field"', () => {
|
||||
|
||||
@ -50,14 +50,6 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: 'password',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Password',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'Password',
|
||||
},
|
||||
immediate: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@ -78,18 +70,11 @@ const { value, errorMessage, meta, errors, validate } = useField(name, props.rul
|
||||
validateOnMount: props.immediate,
|
||||
})
|
||||
|
||||
// onMounted(async () => {
|
||||
// await nextTick()
|
||||
// if (props.immediate) {
|
||||
// await validate()
|
||||
// }
|
||||
// })
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const defaultTranslations = computed(() => ({
|
||||
label: props.label ?? t('form.password'),
|
||||
placeholder: props.placeholder ?? t('form.password'),
|
||||
label: t('form.password'),
|
||||
placeholder: t('form.password'),
|
||||
}))
|
||||
|
||||
const showPassword = ref(false)
|
||||
@ -109,3 +94,9 @@ const ariaMsg = computed(() => ({
|
||||
|
||||
const labelFor = computed(() => `${props.name}-input-field`)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
input {
|
||||
border-radius: 17px 0 0 17px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -129,8 +129,9 @@ button.navbar-toggler > span.navbar-toggler-icon {
|
||||
.navbar-element {
|
||||
z-index: 1000;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
background-color: #f5f5f5e6;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.sheet-img {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
no-header-close
|
||||
horizontal
|
||||
skip-animation
|
||||
@update:model-value="isMobileMenuOpen = $event"
|
||||
>
|
||||
<div class="mobile-sidebar-wrapper py-2">
|
||||
<BImg src="img/svg/lines.png" />
|
||||
@ -17,14 +18,30 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { lock, unlock } from 'tua-body-scroll-lock'
|
||||
|
||||
const isMobileMenuOpen = ref(false)
|
||||
|
||||
const emit = defineEmits(['admin', 'logout'])
|
||||
|
||||
watch(
|
||||
() => isMobileMenuOpen.value,
|
||||
(newVal) => {
|
||||
if (newVal) {
|
||||
lock()
|
||||
} else {
|
||||
unlock()
|
||||
}
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.mobile-sidebar-wrapper {
|
||||
width: 220px;
|
||||
background-color: #fff;
|
||||
z-index: 10;
|
||||
z-index: 1001;
|
||||
position: absolute;
|
||||
border-bottom-right-radius: 26px;
|
||||
border-top-right-radius: 26px;
|
||||
@ -38,6 +55,7 @@ const emit = defineEmits(['admin', 'logout'])
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
.simple-overlay {
|
||||
@ -46,7 +64,7 @@ const emit = defineEmits(['admin', 'logout'])
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
background-color: #212529;
|
||||
z-index: 9;
|
||||
z-index: 99;
|
||||
opacity: 0.6;
|
||||
width: calc(100vw - 200px);
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="transaction-link gradido-custom-background">
|
||||
<BRow :class="validLink ? '' : 'bg-muted text-dark'" class="mb-2 pt-2 pb-2">
|
||||
<BRow :class="{ 'light-gray-text': !validLink }" class="mb-2 pt-2 pb-2">
|
||||
<BCol cols="1">
|
||||
<variant-icon icon="link45deg" variant="danger" />
|
||||
</BCol>
|
||||
@ -153,4 +153,8 @@ const toggleQrModal = () => {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
}
|
||||
|
||||
.light-gray-text {
|
||||
color: #adb5bd !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { mount, RouterLinkStub } from '@vue/test-utils'
|
||||
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
||||
import Name from './Name'
|
||||
import { BLink } from 'bootstrap-vue-next'
|
||||
@ -44,7 +44,7 @@ describe('Name', () => {
|
||||
global: {
|
||||
mocks,
|
||||
stubs: {
|
||||
BLink,
|
||||
RouterLink: RouterLinkStub,
|
||||
},
|
||||
},
|
||||
props: propsData,
|
||||
@ -88,31 +88,18 @@ describe('Name', () => {
|
||||
|
||||
it('has a link', () => {
|
||||
expect(
|
||||
wrapper
|
||||
.find('div.gdd-transaction-list-item-name')
|
||||
.findComponent({ name: 'BLink' })
|
||||
.exists(),
|
||||
wrapper.find('div.gdd-transaction-list-item-name').findComponent(RouterLinkStub).exists(),
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
describe('click link', () => {
|
||||
beforeEach(async () => {
|
||||
await wrapper.findComponent({ name: 'BLink' }).trigger('click')
|
||||
})
|
||||
|
||||
it('pushes router to send', () => {
|
||||
expect(routerPushMock).toHaveBeenCalledWith({
|
||||
path: '/send',
|
||||
})
|
||||
})
|
||||
|
||||
it('pushes params for gradidoID and community UUID', () => {
|
||||
expect(routerPushMock).toHaveBeenCalledWith({
|
||||
params: {
|
||||
communityIdentifier: 'community UUID',
|
||||
userIdentifier: 'gradido-ID',
|
||||
},
|
||||
})
|
||||
it('RouterLink has correct to prop', () => {
|
||||
const routerLink = wrapper.findComponent(RouterLinkStub)
|
||||
expect(routerLink.props().to).toEqual({
|
||||
name: 'Send',
|
||||
params: {
|
||||
communityIdentifier: 'community UUID',
|
||||
userIdentifier: 'gradido-ID',
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -2,9 +2,9 @@
|
||||
<div class="name">
|
||||
<div class="gdd-transaction-list-item-name">
|
||||
<div v-if="linkedUser && linkedUser.gradidoID">
|
||||
<BLink :class="fontColor" @click.stop="tunnelEmail">
|
||||
<router-link :class="fontColor" :to="pushTo">
|
||||
{{ itemText }}
|
||||
</BLink>
|
||||
</router-link>
|
||||
</div>
|
||||
<span v-else>{{ itemText }}</span>
|
||||
</div>
|
||||
@ -45,6 +45,15 @@ export default {
|
||||
(this.linkedUser.communityName ? ' / ' + this.linkedUser.communityName : '')
|
||||
: this.text
|
||||
},
|
||||
pushTo() {
|
||||
return {
|
||||
name: 'Send',
|
||||
params: {
|
||||
userIdentifier: this.linkedUser.gradidoID,
|
||||
communityIdentifier: this.linkedUser.communityUuid,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async tunnelEmail() {
|
||||
|
||||
@ -22,6 +22,7 @@ export function useAppToast() {
|
||||
toast(message, {
|
||||
title: t('navigation.info'),
|
||||
variant: 'warning',
|
||||
bodyClass: 'gdd-toaster-body-darken',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest'
|
||||
import { nextTick } from 'vue'
|
||||
import { nextTick, ref } from 'vue'
|
||||
import DashboardLayout from './DashboardLayout'
|
||||
import { createStore } from 'vuex'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
@ -15,11 +15,15 @@ vi.mock('@/composables/useToast', () => ({
|
||||
}))
|
||||
|
||||
const mockQueryFn = vi.fn()
|
||||
const mockRefetchFn = vi.fn()
|
||||
const mockMutateFn = vi.fn()
|
||||
const mockQueryResult = ref(null)
|
||||
|
||||
vi.mock('@vue/apollo-composable', () => ({
|
||||
useLazyQuery: vi.fn(() => ({
|
||||
load: mockQueryFn,
|
||||
refetch: mockRefetchFn,
|
||||
result: mockQueryResult,
|
||||
onResult: vi.fn(),
|
||||
onError: vi.fn(),
|
||||
})),
|
||||
@ -136,25 +140,25 @@ describe('DashboardLayout', () => {
|
||||
|
||||
describe('update transactions', () => {
|
||||
beforeEach(async () => {
|
||||
mockQueryFn.mockResolvedValue({
|
||||
mockQueryResult.value = {
|
||||
transactionList: {
|
||||
balance: {
|
||||
balanceGDT: 100,
|
||||
balanceGDT: '100',
|
||||
count: 4,
|
||||
linkCount: 8,
|
||||
balance: 1450,
|
||||
decay: 1250,
|
||||
balance: '1450',
|
||||
},
|
||||
transactions: ['transaction', 'transaction', 'transaction', 'transaction'],
|
||||
transactions: ['transaction1', 'transaction2', 'transaction3', 'transaction4'],
|
||||
},
|
||||
})
|
||||
await wrapper
|
||||
.findComponent({ ref: 'router-view' })
|
||||
.vm.$emit('update-transactions', { currentPage: 2, pageSize: 5 })
|
||||
await nextTick()
|
||||
}
|
||||
|
||||
mockQueryFn.mockResolvedValue(mockQueryResult.value)
|
||||
|
||||
await wrapper.vm.updateTransactions({ currentPage: 2, pageSize: 5 })
|
||||
await nextTick() // Ensure all promises are resolved
|
||||
})
|
||||
|
||||
it('calls the API', () => {
|
||||
it('load call to the API', () => {
|
||||
expect(mockQueryFn).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@ -164,10 +168,10 @@ describe('DashboardLayout', () => {
|
||||
|
||||
it('updates transactions', () => {
|
||||
expect(wrapper.vm.transactions).toEqual([
|
||||
'transaction',
|
||||
'transaction',
|
||||
'transaction',
|
||||
'transaction',
|
||||
'transaction1',
|
||||
'transaction2',
|
||||
'transaction3',
|
||||
'transaction4',
|
||||
])
|
||||
})
|
||||
|
||||
|
||||
@ -215,7 +215,11 @@ import { useAppToast } from '@/composables/useToast'
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const { load: useCommunityStatsQuery } = useLazyQuery(communityStatistics)
|
||||
const { load: useTransactionsQuery } = useLazyQuery(transactionsQuery)
|
||||
const {
|
||||
load: useTransactionsQuery,
|
||||
refetch: useRefetchTransactionsQuery,
|
||||
result: transactionQueryResult,
|
||||
} = useLazyQuery(transactionsQuery)
|
||||
const { mutate: useLogoutMutation } = useMutation(logout)
|
||||
const { t } = useI18n()
|
||||
const { toastError } = useAppToast()
|
||||
@ -239,7 +243,7 @@ const testModal = () => {
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
updateTransactions({ currentPage: 0, pageSize: 10 })
|
||||
updateTransactions({ currentPage: 1, pageSize: 10 })
|
||||
getCommunityStatistics()
|
||||
setTimeout(() => {
|
||||
skeleton.value = false
|
||||
@ -260,9 +264,9 @@ const logoutUser = async () => {
|
||||
const updateTransactions = async ({ currentPage, pageSize }) => {
|
||||
pending.value = true
|
||||
try {
|
||||
const result = await useTransactionsQuery()
|
||||
if (!result) return // TODO this return mitigate an error when this method is called second time but without actual request
|
||||
const { transactionList } = result
|
||||
await loadOrFetchTransactionQuery({ currentPage, pageSize })
|
||||
if (!transactionQueryResult) return
|
||||
const { transactionList } = transactionQueryResult.value
|
||||
GdtBalance.value =
|
||||
transactionList.balance.balanceGDT === null ? 0 : Number(transactionList.balance.balanceGDT)
|
||||
transactions.value = transactionList.transactions
|
||||
@ -277,6 +281,13 @@ const updateTransactions = async ({ currentPage, pageSize }) => {
|
||||
}
|
||||
}
|
||||
|
||||
const loadOrFetchTransactionQuery = async (queryVariables = { currentPage: 1, pageSize: 25 }) => {
|
||||
return (
|
||||
(await useTransactionsQuery(transactionsQuery, queryVariables)) ||
|
||||
(await useRefetchTransactionsQuery(queryVariables))
|
||||
)
|
||||
}
|
||||
|
||||
const getCommunityStatistics = async () => {
|
||||
try {
|
||||
const result = await useCommunityStatsQuery()
|
||||
|
||||
@ -19,10 +19,11 @@
|
||||
</BCol>
|
||||
</BRow>
|
||||
<BRow>
|
||||
<BCol cols="12" lg="6">
|
||||
<BCol class="col-lg-6 col-12">
|
||||
<BButton
|
||||
ref="submitBtn"
|
||||
type="submit"
|
||||
class="w-100 fs-7"
|
||||
:variant="meta.valid ? 'gradido' : 'gradido-disable'"
|
||||
block
|
||||
:disabled="!meta.valid"
|
||||
|
||||
@ -23,6 +23,8 @@ const routes = [
|
||||
// communityIdentifier can be community name or community UUID
|
||||
path: '/send/:communityIdentifier?/:userIdentifier?',
|
||||
component: () => import('@/pages/Send'),
|
||||
name: 'Send',
|
||||
props: true,
|
||||
meta: {
|
||||
requiresAuth: true,
|
||||
pageTitle: 'send',
|
||||
|
||||
@ -6772,6 +6772,11 @@ tslib@^2.1.0, tslib@^2.3.0, tslib@^2.6.2:
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0"
|
||||
integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==
|
||||
|
||||
tua-body-scroll-lock@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/tua-body-scroll-lock/-/tua-body-scroll-lock-1.5.1.tgz#1b8b7316dff55a821d5bec3fef045f995e7627a5"
|
||||
integrity sha512-AOjusG9EjTGxqqL1xqg6JeMauJ+IQoX9ITW1qP7UugySUdH6lzi2CqJRmU+oYqOv7vCQjOs5CQrjIakGlbOenQ==
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user