Skip to content

Commit a312510

Browse files
Romuald Caplierjahow
Romuald Caplier
authored andcommitted
[BP] refactor(datahub): added an error message when record has no link.
backported from geonetwork/geonetwork-ui#874
1 parent 0892e6d commit a312510

21 files changed

+266
-70
lines changed

apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts

+89-3
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,15 @@ describe('dataset pages', () => {
542542
})
543543
})
544544
})
545+
546+
describe('When there is no link', () => {
547+
beforeEach(() => {
548+
cy.visit('/dataset/a3774ef6-809d-4dd1-984f-9254f49cbd0a')
549+
})
550+
it('display the error datasetHasNoLink error block', () => {
551+
cy.get('[data-test="dataset-has-no-link-block"]').should('exist')
552+
})
553+
})
545554
})
546555
})
547556
})
@@ -685,9 +694,86 @@ describe('api form', () => {
685694
.find('gn-ui-copy-text-button')
686695
.find('input')
687696
.invoke('val')
688-
.then((newUrl) => {
689-
expect(newUrl).to.not.eq(url)
690-
})
697+
.should('not.eq', url)
691698
})
692699
})
693700
})
701+
702+
describe('userFeedback', () => {
703+
describe('when not logged in', () => {
704+
beforeEach(() => {
705+
cy.visit('/dataset/accroche_velos')
706+
cy.get('datahub-record-user-feedbacks').as('userFeedback')
707+
})
708+
it('should sort comments', () => {
709+
cy.get('gn-ui-user-feedback-item')
710+
.find('[data-cy="commentText"]')
711+
.as('commentText')
712+
713+
cy.get('@commentText')
714+
.first()
715+
.then((div) => {
716+
const firstCommentBeforeSort = div.text().trim()
717+
cy.get('@userFeedback')
718+
.find('gn-ui-dropdown-selector')
719+
.openDropdown()
720+
.children('button')
721+
.eq(1)
722+
.click()
723+
724+
cy.get('gn-ui-user-feedback-item')
725+
.find('[data-cy="commentText"]')
726+
.first()
727+
.invoke('text')
728+
.invoke('trim')
729+
.should('not.eq', firstCommentBeforeSort)
730+
})
731+
})
732+
it("shouldn't be able to comment", () => {
733+
cy.get('datahub-record-user-feedbacks')
734+
.find('gn-ui-text-area')
735+
.should('not.exist')
736+
})
737+
})
738+
739+
describe('when logged in', () => {
740+
beforeEach(() => {
741+
cy.login()
742+
cy.visit('/dataset/accroche_velos')
743+
})
744+
it('should publish a comment', () => {
745+
cy.get('datahub-record-user-feedbacks')
746+
.find('gn-ui-text-area')
747+
.first()
748+
.should('exist')
749+
.type('Something')
750+
751+
cy.get('datahub-record-user-feedbacks')
752+
.find('gn-ui-button')
753+
.eq(1)
754+
.should('exist')
755+
})
756+
it('should answer to a comment', () => {
757+
cy.get('gn-ui-user-feedback-item')
758+
.find('gn-ui-text-area')
759+
.first()
760+
.should('exist')
761+
.type('Something')
762+
763+
cy.get('gn-ui-user-feedback-item')
764+
.find('gn-ui-button')
765+
.eq(0)
766+
.should('exist')
767+
})
768+
})
769+
})
770+
771+
describe('When the metadata does not exists', () => {
772+
beforeEach(() => {
773+
cy.visit('/dataset/xyz')
774+
})
775+
it('should display an error message', () => {
776+
cy.get('gn-ui-error').should('exist')
777+
cy.screenshot({ capture: 'viewport' })
778+
})
779+
})

apps/datahub/src/app/record/record-metadata/record-metadata.component.html

+10-5
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,12 @@
130130
></datahub-record-apis>
131131
</div>
132132
</div>
133-
133+
<ng-container *ngIf="displayDatasetHasNoLinkBlock$ | async">
134+
<gn-ui-error
135+
data-test="dataset-has-no-link-block"
136+
[type]="errorTypes.DATASET_HAS_NO_LINK"
137+
></gn-ui-error>
138+
</ng-container>
134139
<div id="related-records" *ngIf="displayRelated$ | async">
135140
<div>
136141
<div class="h-48 overflow-visible">
@@ -150,14 +155,14 @@
150155
class="mt-12 p-4 max-w-[600px] m-auto text-[13px]"
151156
*ngIf="facade.error$ | async as error"
152157
>
153-
<gn-ui-search-results-error
158+
<gn-ui-error
154159
*ngIf="error.notFound"
155160
[type]="errorTypes.RECORD_NOT_FOUND"
156161
[recordId]="(facade.metadata$ | async).uniqueIdentifier"
157-
></gn-ui-search-results-error>
158-
<gn-ui-search-results-error
162+
></gn-ui-error>
163+
<gn-ui-error
159164
*ngIf="error.otherError"
160165
[type]="errorTypes.RECEIVED_ERROR"
161166
[error]="error.otherError"
162-
></gn-ui-search-results-error>
167+
></gn-ui-error>
163168
</div>

apps/datahub/src/app/record/record-metadata/record-metadata.component.spec.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@ import { By } from '@angular/platform-browser'
1010
import { SourcesService } from '@geonetwork-ui/feature/catalog'
1111
import { MapManagerService } from '@geonetwork-ui/feature/map'
1212
import { SearchService } from '@geonetwork-ui/feature/search'
13-
import {
14-
ErrorType,
15-
SearchResultsErrorComponent,
16-
} from '@geonetwork-ui/ui/elements'
13+
import { ErrorComponent, ErrorType } from '@geonetwork-ui/ui/elements'
1714
import { TranslateModule } from '@ngx-translate/core'
1815
import { BehaviorSubject, of } from 'rxjs'
1916
import { RecordMetadataComponent } from './record-metadata.component'
@@ -168,7 +165,7 @@ describe('RecordMetadataComponent', () => {
168165
MockDataOtherlinksComponent,
169166
MockDataApisComponent,
170167
MockRelatedComponent,
171-
SearchResultsErrorComponent,
168+
ErrorComponent,
172169
MockMetadataInfoComponent,
173170
MockMetadataContactComponent,
174171
MockRecordApiFormComponent,
@@ -598,9 +595,9 @@ describe('RecordMetadataComponent', () => {
598595
describe('error handling', () => {
599596
describe('normal', () => {
600597
it('does not show errors', () => {
601-
const result = fixture.debugElement.query(
602-
By.directive(SearchResultsErrorComponent)
603-
)
598+
facade.otherLinks$.next([''])
599+
fixture.detectChanges()
600+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
604601
expect(result).toBeFalsy()
605602
})
606603
})
@@ -610,9 +607,7 @@ describe('RecordMetadataComponent', () => {
610607
fixture.detectChanges()
611608
})
612609
it('shows error', () => {
613-
const result = fixture.debugElement.query(
614-
By.directive(SearchResultsErrorComponent)
615-
)
610+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
616611

617612
expect(result).toBeTruthy()
618613
expect(result.componentInstance.type).toBe(ErrorType.RECORD_NOT_FOUND)
@@ -628,14 +623,30 @@ describe('RecordMetadataComponent', () => {
628623
fixture.detectChanges()
629624
})
630625
it('shows error', () => {
631-
const result = fixture.debugElement.query(
632-
By.directive(SearchResultsErrorComponent)
633-
)
626+
const result = fixture.debugElement.query(By.directive(ErrorComponent))
634627

635628
expect(result).toBeTruthy()
636629
expect(result.componentInstance.type).toBe(ErrorType.RECEIVED_ERROR)
637630
expect(result.componentInstance.error).toBe('This is an Error!')
638631
})
639632
})
633+
634+
describe('When there are no link (download, api or other links)', () => {
635+
beforeEach(() => {
636+
facade.apiLinks$.next([])
637+
facade.downloadLinks$.next([])
638+
facade.otherLinks$.next([])
639+
fixture.detectChanges()
640+
})
641+
it('shows the no link error block', () => {
642+
const result = fixture.debugElement.query(
643+
By.css('[data-test="dataset-has-no-link-block"]')
644+
)
645+
expect(result).toBeTruthy()
646+
expect(result.componentInstance.type).toBe(
647+
ErrorType.DATASET_HAS_NO_LINK
648+
)
649+
})
650+
})
640651
})
641652
})

apps/datahub/src/app/record/record-metadata/record-metadata.component.ts

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ export class RecordMetadataComponent {
4949
map((records) => records?.length > 0)
5050
)
5151

52+
displayDatasetHasNoLinkBlock$ = combineLatest([
53+
this.displayDownload$,
54+
this.displayApi$,
55+
this.displayOtherLinks,
56+
]).pipe(
57+
map(
58+
([displayDownload, displayApi, displayOtherLinks]) =>
59+
!displayDownload && !displayApi && !displayOtherLinks
60+
)
61+
)
62+
5263
sourceLabel$ = this.facade.metadata$.pipe(
5364
map((record) => record?.extras?.catalogUuid as string),
5465
filter((uuid) => !!uuid),

libs/feature/search/src/lib/results-list/results-list.container.component.html

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,16 @@
4242
</div>
4343

4444
<div class="p-4 max-w-[600px] m-auto text-[13px]">
45-
<gn-ui-search-results-error
45+
<gn-ui-error
4646
*ngIf="(errorCode$ | async) === 0"
4747
[type]="errorTypes.COULD_NOT_REACH_API"
4848
>
49-
</gn-ui-search-results-error>
50-
<gn-ui-search-results-error
49+
</gn-ui-error>
50+
<gn-ui-error
5151
*ngIf="(error$ | async) !== null && (errorCode$ | async) !== 0"
5252
[type]="errorTypes.RECEIVED_ERROR"
5353
[error]="errorMessage$ | async"
54-
></gn-ui-search-results-error>
54+
></gn-ui-error>
5555
</div>
5656

5757
<ng-template #favoriteToggle let-record>

libs/ui/elements/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export * from './lib/downloads-list/downloads-list.component'
1515
export * from './lib/link-card/link-card.component'
1616
export * from './lib/pagination/pagination.component'
1717
export * from './lib/related-record-card/related-record-card.component'
18-
export * from './lib/search-results-error/search-results-error.component'
18+
export * from './lib/error/error.component'
1919
export * from './lib/user-preview/user-preview.component'
2020
export * from './lib/max-lines/max-lines.component'
2121
export * from './lib/record-api-form/record-api-form.component'

libs/ui/elements/src/lib/search-results-error/search-results-error.component.html libs/ui/elements/src/lib/error/error.component.html

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
<div
22
class="p-[1.7em] bg-red-50 text-red-800 text-[1.5em] text-center rounded-lg"
33
>
4-
<div *ngIf="type === types.COULD_NOT_REACH_API">
4+
<div
5+
*ngIf="type === types.COULD_NOT_REACH_API"
6+
data-test="could-not-reach-api-error"
7+
>
58
<div class="relative opacity-40">
69
<mat-icon class="material-symbols-outlined face">face</mat-icon>
710
<mat-icon class="material-symbols-outlined question-mark1"
@@ -13,14 +16,26 @@
1316
</div>
1417
<div translate>search.error.couldNotReachApi</div>
1518
</div>
16-
<div *ngIf="type === types.RECEIVED_ERROR">
19+
<div
20+
*ngIf="type === types.DATASET_HAS_NO_LINK"
21+
data-test="dataset-has-no-link-error"
22+
>
23+
<div class="relative opacity-40">
24+
<mat-icon class="material-symbols-outlined face">computer</mat-icon>
25+
</div>
26+
<div translate>search.error.recordHasnolink</div>
27+
</div>
28+
<div *ngIf="type === types.RECEIVED_ERROR" data-test="received-error-error">
1729
<div class="relative opacity-40">
1830
<mat-icon class="material-symbols-outlined face">mood_bad</mat-icon>
1931
</div>
2032
<div translate>search.error.receivedError</div>
2133
<div *ngIf="error">{{ error }}</div>
2234
</div>
23-
<div *ngIf="type === types.RECORD_NOT_FOUND">
35+
<div
36+
*ngIf="type === types.RECORD_NOT_FOUND"
37+
data-test="record-not-found-error"
38+
>
2439
<div class="relative opacity-40">
2540
<mat-icon class="material-symbols-outlined computer">computer</mat-icon>
2641
<mat-icon class="material-symbols-outlined computer-question-mark"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing'
2+
3+
import { ErrorComponent, ErrorType } from './error.component'
4+
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'
5+
import { By } from '@angular/platform-browser'
6+
7+
describe('ErrorComponent', () => {
8+
let component: ErrorComponent
9+
let fixture: ComponentFixture<ErrorComponent>
10+
let compiled: DebugElement
11+
12+
beforeEach(async () => {
13+
await TestBed.configureTestingModule({
14+
declarations: [ErrorComponent],
15+
schemas: [NO_ERRORS_SCHEMA],
16+
}).compileComponents()
17+
})
18+
19+
beforeEach(() => {
20+
fixture = TestBed.createComponent(ErrorComponent)
21+
component = fixture.componentInstance
22+
compiled = fixture.debugElement
23+
})
24+
25+
it('should create', () => {
26+
expect(component).toBeTruthy()
27+
})
28+
29+
describe('ErrorType', () => {
30+
describe('ErrorType.COULD_NOT_REACH_API', () => {
31+
beforeEach(() => {
32+
component.type = ErrorType.COULD_NOT_REACH_API
33+
fixture.detectChanges()
34+
})
35+
36+
it('COULD_NOT_REACH_API block is displayed.', () => {
37+
const errorBlock = compiled.query(
38+
By.css('[data-test="could-not-reach-api-error"]')
39+
)
40+
expect(errorBlock).toBeTruthy()
41+
})
42+
})
43+
44+
describe('ErrorType.RECEIVED_ERROR', () => {
45+
beforeEach(() => {
46+
component.type = ErrorType.RECEIVED_ERROR
47+
fixture.detectChanges()
48+
})
49+
50+
it('RECEIVED_ERROR block is displayed.', () => {
51+
const errorBlock = compiled.query(
52+
By.css('[data-test="received-error-error"]')
53+
)
54+
expect(errorBlock).toBeTruthy()
55+
})
56+
})
57+
58+
describe('ErrorType.RECORD_NOT_FOUND', () => {
59+
beforeEach(() => {
60+
component.type = ErrorType.RECORD_NOT_FOUND
61+
fixture.detectChanges()
62+
})
63+
64+
it('RECORD_NOT_FOUND block is displayed.', () => {
65+
const errorBlock = compiled.query(
66+
By.css('[data-test="record-not-found-error"]')
67+
)
68+
expect(errorBlock).toBeTruthy()
69+
})
70+
})
71+
72+
describe('ErrorType.NO_LINK', () => {
73+
beforeEach(() => {
74+
component.type = ErrorType.DATASET_HAS_NO_LINK
75+
fixture.detectChanges()
76+
})
77+
78+
it('NO_LINK block is displayed.', () => {
79+
const errorBlock = compiled.query(
80+
By.css('[data-test="dataset-has-no-link-error"]')
81+
)
82+
expect(errorBlock).toBeTruthy()
83+
})
84+
})
85+
})
86+
})

0 commit comments

Comments
 (0)