Skip to content

Commit 6a6fa68

Browse files
authored
fix(entities-list): show response error message in entity list (#920)
The current implementation just display general error message when error happens, and `<EntityBaseTable />` doesn't support set error message for the list (only error title allowed). To display the message returned from server, prop `errorMessage` in `<EntityBaseTable />` now supports both string form (title only) and object form (title and message). All kinds of entity lists are modified to set the error message when available.
1 parent 7ca1591 commit 6a6fa68

File tree

32 files changed

+1070
-692
lines changed

32 files changed

+1070
-692
lines changed

packages/entities/entities-certificates/src/components/CACertificateList.cy.ts

+62-46
Original file line numberDiff line numberDiff line change
@@ -244,31 +244,39 @@ describe('<CACertificateList />', () => {
244244
})
245245

246246
it('should handle error state', () => {
247-
cy.intercept(
248-
{
249-
method: 'GET',
250-
url: `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/ca_certificates*`,
251-
},
252-
{
253-
statusCode: 500,
254-
body: {},
255-
},
256-
).as('getCaCertificate')
247+
const testHandleErrorRequest = (message?: string) => {
248+
cy.intercept(
249+
{
250+
method: 'GET',
251+
url: `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/ca_certificates*`,
252+
},
253+
{
254+
statusCode: 500,
255+
body: message ? { message } : {},
256+
},
257+
).as('getCaCertificate')
258+
259+
cy.mount(CACertificateList, {
260+
props: {
261+
cacheIdentifier: `ca-certificate-list-${uuidv4()}`,
262+
config: baseConfigKM,
263+
canCreate: () => {},
264+
canEdit: () => {},
265+
canDelete: () => {},
266+
canRetrieve: () => {},
267+
},
268+
})
257269

258-
cy.mount(CACertificateList, {
259-
props: {
260-
cacheIdentifier: `ca-certificate-list-${uuidv4()}`,
261-
config: baseConfigKM,
262-
canCreate: () => {},
263-
canEdit: () => {},
264-
canDelete: () => {},
265-
canRetrieve: () => {},
266-
},
267-
})
270+
cy.wait('@getCaCertificate')
271+
cy.get('.kong-ui-entities-ca-certificates-list').should('be.visible')
272+
cy.get('.k-table-error-state').should('be.visible')
273+
if (message) {
274+
cy.get('.k-table-error-state .k-empty-state-message').should('contain.text', message)
275+
}
276+
}
268277

269-
cy.wait('@getCaCertificate')
270-
cy.get('.kong-ui-entities-ca-certificates-list').should('be.visible')
271-
cy.get('.k-table-error-state').should('be.visible')
278+
testHandleErrorRequest()
279+
testHandleErrorRequest('Custom error message')
272280
})
273281

274282
it('should allow switching between pages', () => {
@@ -546,31 +554,39 @@ describe('<CACertificateList />', () => {
546554
})
547555

548556
it('should handle error state', () => {
549-
cy.intercept(
550-
{
551-
method: 'GET',
552-
url: `${baseConfigKonnect.apiBaseUrl}/api/runtime_groups/${baseConfigKonnect.controlPlaneId}/ca_certificates*`,
553-
},
554-
{
555-
statusCode: 500,
556-
body: {},
557-
},
558-
).as('getCaCertificate')
557+
const testHandleErrorRequest = (message?: string) => {
558+
cy.intercept(
559+
{
560+
method: 'GET',
561+
url: `${baseConfigKonnect.apiBaseUrl}/api/runtime_groups/${baseConfigKonnect.controlPlaneId}/ca_certificates*`,
562+
},
563+
{
564+
statusCode: 500,
565+
body: message ? { message } : {},
566+
},
567+
).as('getCaCertificate')
568+
569+
cy.mount(CACertificateList, {
570+
props: {
571+
cacheIdentifier: `ca-certificate-list-${uuidv4()}`,
572+
config: baseConfigKonnect,
573+
canCreate: () => {},
574+
canEdit: () => {},
575+
canDelete: () => {},
576+
canRetrieve: () => {},
577+
},
578+
})
559579

560-
cy.mount(CACertificateList, {
561-
props: {
562-
cacheIdentifier: `ca-certificate-list-${uuidv4()}`,
563-
config: baseConfigKonnect,
564-
canCreate: () => {},
565-
canEdit: () => {},
566-
canDelete: () => {},
567-
canRetrieve: () => {},
568-
},
569-
})
580+
cy.wait('@getCaCertificate')
581+
cy.get('.kong-ui-entities-ca-certificates-list').should('be.visible')
582+
cy.get('.k-table-error-state').should('be.visible')
583+
if (message) {
584+
cy.get('.k-table-error-state .k-empty-state-message').should('contain.text', message)
585+
}
586+
}
570587

571-
cy.wait('@getCaCertificate')
572-
cy.get('.kong-ui-entities-ca-certificates-list').should('be.visible')
573-
cy.get('.k-table-error-state').should('be.visible')
588+
testHandleErrorRequest()
589+
testHandleErrorRequest('Custom error message')
574590
})
575591

576592
it('should allow switching between pages', () => {

packages/entities/entities-certificates/src/components/CACertificateList.vue

+9-3
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ import type {
162162
EmptyStateOptions,
163163
ExactMatchFilterConfig,
164164
FuzzyMatchFilterConfig,
165+
TableErrorMessage,
165166
} from '@kong-ui-public/entities-shared'
166167
import '@kong-ui-public/entities-shared/dist/style.css'
167168
@@ -283,7 +284,7 @@ const resetPagination = (): void => {
283284
/**
284285
* loading, Error, Empty state
285286
*/
286-
const errorMessage = ref<string>('')
287+
const errorMessage = ref<TableErrorMessage>(null)
287288
288289
/**
289290
* Copy ID action
@@ -419,15 +420,20 @@ const confirmDelete = async (): Promise<void> => {
419420
*/
420421
watch(fetcherState, (state) => {
421422
if (state.status === FetcherStatus.Error) {
422-
errorMessage.value = t('ca-certificates.errors.general')
423+
errorMessage.value = {
424+
title: t('ca-certificates.errors.general'),
425+
}
426+
if (state.error?.response?.data?.message) {
427+
errorMessage.value.message = state.error.response.data.message
428+
}
423429
// Emit the error for the host app
424430
emit('error', state.error)
425431
426432
return
427433
}
428434
429435
certificateDataCache.value = {}
430-
errorMessage.value = ''
436+
errorMessage.value = null
431437
})
432438
433439
// Initialize the empty state options assuming a user does not have create permissions

packages/entities/entities-certificates/src/components/CertificateList.cy.ts

+62-46
Original file line numberDiff line numberDiff line change
@@ -284,31 +284,39 @@ describe('<CertificateList />', () => {
284284
})
285285

286286
it('should handle error state', () => {
287-
cy.intercept(
288-
{
289-
method: 'GET',
290-
url: `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/certificates*`,
291-
},
292-
{
293-
statusCode: 500,
294-
body: {},
295-
},
296-
).as('getCertificate')
287+
const testHandleErrorRequest = (message?: string) => {
288+
cy.intercept(
289+
{
290+
method: 'GET',
291+
url: `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/certificates*`,
292+
},
293+
{
294+
statusCode: 500,
295+
body: message ? { message } : {},
296+
},
297+
).as('getCertificate')
298+
299+
cy.mount(CertificateList, {
300+
props: {
301+
cacheIdentifier: `certificate-list-${uuidv4()}`,
302+
config: baseConfigKM,
303+
canCreate: () => {},
304+
canEdit: () => {},
305+
canDelete: () => {},
306+
canRetrieve: () => {},
307+
},
308+
})
297309

298-
cy.mount(CertificateList, {
299-
props: {
300-
cacheIdentifier: `certificate-list-${uuidv4()}`,
301-
config: baseConfigKM,
302-
canCreate: () => {},
303-
canEdit: () => {},
304-
canDelete: () => {},
305-
canRetrieve: () => {},
306-
},
307-
})
310+
cy.wait('@getCertificate')
311+
cy.get('.kong-ui-entities-certificates-list').should('be.visible')
312+
cy.get('.k-table-error-state').should('be.visible')
313+
if (message) {
314+
cy.get('.k-table-error-state .k-empty-state-message').should('contain.text', message)
315+
}
316+
}
308317

309-
cy.wait('@getCertificate')
310-
cy.get('.kong-ui-entities-certificates-list').should('be.visible')
311-
cy.get('.k-table-error-state').should('be.visible')
318+
testHandleErrorRequest()
319+
testHandleErrorRequest('Custom error message')
312320
})
313321

314322
it('should allow switching between pages', () => {
@@ -593,31 +601,39 @@ describe('<CertificateList />', () => {
593601
})
594602

595603
it('should handle error state', () => {
596-
cy.intercept(
597-
{
598-
method: 'GET',
599-
url: `${baseConfigKonnect.apiBaseUrl}/api/runtime_groups/${baseConfigKonnect.controlPlaneId}/certificates*`,
600-
},
601-
{
602-
statusCode: 500,
603-
body: {},
604-
},
605-
).as('getCertificate')
604+
const testHandleErrorRequest = (message?: string) => {
605+
cy.intercept(
606+
{
607+
method: 'GET',
608+
url: `${baseConfigKonnect.apiBaseUrl}/api/runtime_groups/${baseConfigKonnect.controlPlaneId}/certificates*`,
609+
},
610+
{
611+
statusCode: 500,
612+
body: message ? { message } : {},
613+
},
614+
).as('getCertificate')
615+
616+
cy.mount(CertificateList, {
617+
props: {
618+
cacheIdentifier: `certificate-list-${uuidv4()}`,
619+
config: baseConfigKonnect,
620+
canCreate: () => {},
621+
canEdit: () => {},
622+
canDelete: () => {},
623+
canRetrieve: () => {},
624+
},
625+
})
606626

607-
cy.mount(CertificateList, {
608-
props: {
609-
cacheIdentifier: `certificate-list-${uuidv4()}`,
610-
config: baseConfigKonnect,
611-
canCreate: () => {},
612-
canEdit: () => {},
613-
canDelete: () => {},
614-
canRetrieve: () => {},
615-
},
616-
})
627+
cy.wait('@getCertificate')
628+
cy.get('.kong-ui-entities-certificates-list').should('be.visible')
629+
cy.get('.k-table-error-state').should('be.visible')
630+
if (message) {
631+
cy.get('.k-table-error-state .k-empty-state-message').should('contain.text', message)
632+
}
633+
}
617634

618-
cy.wait('@getCertificate')
619-
cy.get('.kong-ui-entities-certificates-list').should('be.visible')
620-
cy.get('.k-table-error-state').should('be.visible')
635+
testHandleErrorRequest()
636+
testHandleErrorRequest('Custom error message')
621637
})
622638

623639
it('should allow switching between pages', () => {

packages/entities/entities-certificates/src/components/CertificateList.vue

+9-3
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ import type {
189189
EmptyStateOptions,
190190
ExactMatchFilterConfig,
191191
FuzzyMatchFilterConfig,
192+
TableErrorMessage,
192193
} from '@kong-ui-public/entities-shared'
193194
import '@kong-ui-public/entities-shared/dist/style.css'
194195
import '@kong-ui-public/copy-uuid/dist/style.css'
@@ -319,7 +320,7 @@ const resetPagination = (): void => {
319320
/**
320321
* loading, Error, Empty state
321322
*/
322-
const errorMessage = ref<string>('')
323+
const errorMessage = ref<TableErrorMessage>(null)
323324
324325
/**
325326
* Copy ID action
@@ -486,15 +487,20 @@ const confirmDelete = async (): Promise<void> => {
486487
*/
487488
watch(fetcherState, (state) => {
488489
if (state.status === FetcherStatus.Error) {
489-
errorMessage.value = t('certificates.errors.general')
490+
errorMessage.value = {
491+
title: t('certificates.errors.general'),
492+
}
493+
if (state.error?.response?.data?.message) {
494+
errorMessage.value.message = state.error.response.data.message
495+
}
490496
// Emit the error for the host app
491497
emit('error', state.error)
492498
493499
return
494500
}
495501
496502
certificateDataCache.value = {}
497-
errorMessage.value = ''
503+
errorMessage.value = null
498504
})
499505
500506
// Initialize the empty state options assuming a user does not have create permissions

0 commit comments

Comments
 (0)