-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16505 from swarajsaaj/vue-error-alert
[vue] Add error handling toast
- Loading branch information
Showing
16 changed files
with
250 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
generators/client/templates/vue/src/main/webapp/app/shared/alert/alert.service.ts.ejs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import Vue from 'vue'; | ||
|
||
export default class AlertService { | ||
public showError(instance: Vue, message: string, params?: any) { | ||
<%_ if (enableTranslation) { _%> | ||
const alertMessage = instance.$t(message, params); | ||
<%_ } else {_%> | ||
const alertMessage = message; | ||
<%_ } _%> | ||
instance.$root.$bvToast.toast(alertMessage.toString(), { | ||
toaster: 'b-toaster-top-center', | ||
title: 'Error', | ||
variant: 'danger', | ||
solid: true, | ||
autoHideDelay: 5000, | ||
}); | ||
} | ||
|
||
public showHttpError(instance: Vue, httpErrorResponse: any) { | ||
switch (httpErrorResponse.status) { | ||
case 0: | ||
this.showError(instance,<% if (enableTranslation) { %> 'error.server.not.reachable'<% } else { %> 'Server not reachable'<% } %>); | ||
break; | ||
|
||
case 400: { | ||
const arr = Object.keys(httpErrorResponse.headers); | ||
let errorHeader: string | null = null; | ||
<%_ if (enableTranslation) { _%> | ||
let entityKey: string | null = null; | ||
<%_ } _%> | ||
for (const entry of arr) { | ||
if (entry.toLowerCase().endsWith('app-error')) { | ||
errorHeader = httpErrorResponse.headers[entry]; | ||
<%_ if (enableTranslation) { _%> | ||
} else if (entry.toLowerCase().endsWith('app-params')) { | ||
entityKey = httpErrorResponse.headers[entry]; | ||
<%_ } _%> | ||
} | ||
} | ||
if (errorHeader) { | ||
<%_ if (enableTranslation) { _%> | ||
const alertData = entityKey ? { entityName: instance.$t(`global.menu.entities.${entityKey}`) } : undefined; | ||
<%_ } _%> | ||
this.showError(instance, errorHeader<% if (enableTranslation) { %>, alertData<% } %>); | ||
} else if (httpErrorResponse.data !== '' && httpErrorResponse.data.fieldErrors) { | ||
this.showError(instance, <% if (enableTranslation) { %>httpErrorResponse.data.message<% } else { %>'Validation error'<% } %>); | ||
} else { | ||
this.showError(instance, httpErrorResponse.data.message); | ||
} | ||
break; | ||
} | ||
|
||
case 404: | ||
this.showError(instance, <% if (enableTranslation) { %>'error.http.404'<% } else { %>'Not found'<% } %>); | ||
break; | ||
|
||
default: | ||
this.showError(instance, httpErrorResponse.data.message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
124 changes: 124 additions & 0 deletions
124
.../client/templates/vue/src/test/javascript/spec/app/shared/alert/alert.service.spec.ts.ejs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import sinon from 'sinon'; | ||
|
||
import AlertService from '@/shared/alert/alert.service'; | ||
import Vue from 'vue'; | ||
import { createLocalVue, mount, shallowMount } from '@vue/test-utils'; | ||
<%_ if (enableTranslation) { _%> | ||
const translationStub = sinon.stub(); | ||
<%_ } _%> | ||
const toastStub = sinon.stub(); | ||
|
||
const vueInstance = { | ||
<% if (enableTranslation) { %>$t: translationStub,<% } %> | ||
$root: { | ||
$bvToast: { | ||
toast: toastStub, | ||
}, | ||
}, | ||
}; | ||
|
||
describe('Alert Service test suite', () => { | ||
let alertService: AlertService; | ||
|
||
beforeEach(() => { | ||
<%_ if (enableTranslation) { _%> | ||
translationStub.reset(); | ||
<%_ } _%> | ||
toastStub.reset(); | ||
alertService = new AlertService(); | ||
}); | ||
|
||
it('should show error toast with translation/message', async () => { | ||
const message = 'translatedMessage'; | ||
<%_ if (enableTranslation) { _%> | ||
const translationKey = 'err.code'; | ||
|
||
// GIVEN | ||
translationStub.withArgs(translationKey).returns(message); | ||
<%_ } _%> | ||
|
||
// WHEN | ||
alertService.showError((<any>vueInstance) as Vue, <% if (enableTranslation) { %>translationKey<%} else {%>message<% } %>); | ||
|
||
//THEN | ||
<%_ if (enableTranslation) { _%> | ||
expect(translationStub.withArgs(translationKey).callCount).toEqual(1); | ||
<%_ } _%> | ||
expect( | ||
toastStub.calledOnceWith(message, { | ||
toaster: 'b-toaster-top-center', | ||
title: 'Error', | ||
variant: 'danger', | ||
solid: true, | ||
autoHideDelay: 5000, | ||
}) | ||
).toBeTruthy(); | ||
}); | ||
|
||
it('should show not reachable toast when http status = 0', async () => { | ||
<%_ if (enableTranslation) { _%> | ||
const translationKey = 'error.server.not.reachable'; | ||
<%_ } _%> | ||
const message = 'Server not reachable'; | ||
const httpErrorResponse = { | ||
status: 0, | ||
}; | ||
<%_ if (enableTranslation) { _%> | ||
// GIVEN | ||
translationStub.withArgs(translationKey).returns(message); | ||
<%_ } _%> | ||
|
||
// WHEN | ||
alertService.showHttpError((<any>vueInstance) as Vue, httpErrorResponse); | ||
|
||
//THEN | ||
<%_ if (enableTranslation) { _%> | ||
expect(translationStub.withArgs(translationKey).callCount).toEqual(1); | ||
<%_ } _%> | ||
expect( | ||
toastStub.calledOnceWith(message, { | ||
toaster: 'b-toaster-top-center', | ||
title: 'Error', | ||
variant: 'danger', | ||
solid: true, | ||
autoHideDelay: 5000, | ||
}) | ||
).toBeTruthy(); | ||
}); | ||
|
||
it('should show parameterized error toast when http status = 400 and entity headers', async () => { | ||
<%_ if (enableTranslation) { _%> | ||
const translationKey = 'error.update'; | ||
<%_ } _%> | ||
const message = 'Updation Error'; | ||
const httpErrorResponse = { | ||
status: 400, | ||
headers: { | ||
'x-jhipsterapp-error': <% if (enableTranslation) { %>translationKey<% } else {%>message<% } %>, | ||
'x-jhipsterapp-params': 'dummyEntity', | ||
}, | ||
}; | ||
<%_ if (enableTranslation) { _%> | ||
// GIVEN | ||
translationStub.withArgs(translationKey).returns(message); | ||
translationStub.withArgs('global.menu.entities.dummyEntity').returns('DummyEntity'); | ||
<%_ } _%> | ||
|
||
// WHEN | ||
alertService.showHttpError((<any>vueInstance) as Vue, httpErrorResponse); | ||
|
||
//THEN | ||
<%_ if (enableTranslation) { _%> | ||
expect(translationStub.withArgs(translationKey, { entityName: 'DummyEntity' }).callCount).toEqual(1); | ||
<%_ } _%> | ||
expect( | ||
toastStub.calledOnceWith(message, { | ||
toaster: 'b-toaster-top-center', | ||
title: 'Error', | ||
variant: 'danger', | ||
solid: true, | ||
autoHideDelay: 5000, | ||
}) | ||
).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.