Skip to content

Commit 0afd791

Browse files
authored
Merge pull request DSpace#3010 from autavares-dev/item-page-cc-license-field
Item page cc license field
2 parents c18b369 + cec5892 commit 0afd791

14 files changed

Lines changed: 456 additions & 9 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<div *ngIf="uri && name" class="item-page-field">
2+
<ds-metadata-field-wrapper [label]="'item.page.cc.license.title' | translate">
3+
<div [ngClass]="{'row': variant === 'full', 'col': variant === 'small'}">
4+
5+
<!-- 'img' tag is not rendered if any errors occurs when loading it -->
6+
<div *ngIf="showImage" [ngClass]="{'col-auto': variant === 'full', 'row': variant === 'small'}"
7+
style="align-content: center;"
8+
>
9+
<a [href]="uri" target="_blank" class="link-anchor dont-break-out ds-simple-metadata-link">
10+
<img (error)="showImage = false" [src]="imgSrc" [alt]="name" class="cc-image"
11+
[ngStyle]="{
12+
'width': 'var(--ds-thumbnail-max-width)',
13+
'margin-bottom': variant === 'small'? '1ch' : '0',
14+
}"
15+
/>
16+
</a>
17+
</div>
18+
19+
<!-- CC name is always displayed if the image fails to load -->
20+
<div [ngClass]="{ 'row': variant === 'small', 'col': variant === 'full' }">
21+
<span>
22+
{{ variant === 'full' && showDisclaimer ? ('item.page.cc.license.disclaimer' | translate) : '' }}
23+
<a *ngIf="showName || !showImage" [href]="uri" target="_blank" id="cc-name">{{ name }}</a>
24+
</span>
25+
</div>
26+
</div>
27+
</ds-metadata-field-wrapper>
28+
</div>
Lines changed: 298 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
import {
2+
ChangeDetectionStrategy,
3+
NO_ERRORS_SCHEMA,
4+
} from '@angular/core';
5+
import {
6+
ComponentFixture,
7+
TestBed,
8+
waitForAsync,
9+
} from '@angular/core/testing';
10+
import { By } from '@angular/platform-browser';
11+
import {
12+
TranslateLoader,
13+
TranslateModule,
14+
} from '@ngx-translate/core';
15+
import { Item } from 'src/app/core/shared/item.model';
16+
import {
17+
MetadataMap,
18+
MetadataValue,
19+
} from 'src/app/core/shared/metadata.models';
20+
import { createSuccessfulRemoteDataObject$ } from 'src/app/shared/remote-data.utils';
21+
import { createPaginatedList } from 'src/app/shared/testing/utils.test';
22+
23+
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
24+
import { environment } from '../../../../../../environments/environment';
25+
import { TranslateLoaderMock } from '../../../../../shared/testing/translate-loader.mock';
26+
import { ItemPageCcLicenseFieldComponent } from './item-page-cc-license-field.component';
27+
28+
29+
interface TestInstance {
30+
metadata: {
31+
'dc.rights.uri'?: string;
32+
'dc.rights'?: string;
33+
};
34+
componentInputs?: {
35+
variant?: 'small' | 'full';
36+
showName?: boolean;
37+
showDisclaimer?: boolean;
38+
};
39+
}
40+
41+
42+
interface TestCase {
43+
testInstance: TestInstance;
44+
expected: {
45+
render: boolean,
46+
showImage: boolean,
47+
showName: boolean,
48+
showDisclaimer: boolean
49+
};
50+
}
51+
52+
53+
const licenseNameMock = 'CC LICENSE NAME';
54+
55+
56+
const testCases: TestCase[] = [
57+
{
58+
testInstance: {
59+
metadata: { 'dc.rights.uri': undefined, 'dc.rights': undefined },
60+
},
61+
expected: {
62+
render: false,
63+
showName: false,
64+
showImage: false,
65+
showDisclaimer: false,
66+
},
67+
},
68+
{
69+
testInstance: {
70+
metadata: { 'dc.rights.uri': null, 'dc.rights': null },
71+
},
72+
expected: {
73+
render: false,
74+
showName: false,
75+
showImage: false,
76+
showDisclaimer: false,
77+
},
78+
},
79+
{
80+
testInstance: {
81+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/licenses/by/4.0', 'dc.rights': null },
82+
},
83+
expected: {
84+
render: false,
85+
showName: false,
86+
showImage: false,
87+
showDisclaimer: false,
88+
},
89+
},
90+
{
91+
testInstance: {
92+
metadata: { 'dc.rights.uri': null, 'dc.rights': licenseNameMock },
93+
},
94+
expected: {
95+
render: false,
96+
showName: false,
97+
showImage: false,
98+
showDisclaimer: false,
99+
},
100+
},
101+
{
102+
testInstance: {
103+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/licenses/by/4.0', 'dc.rights': licenseNameMock },
104+
},
105+
expected: {
106+
render: true,
107+
showName: true,
108+
showImage: true,
109+
showDisclaimer: false,
110+
},
111+
},
112+
{
113+
testInstance: {
114+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/', 'dc.rights': licenseNameMock },
115+
},
116+
expected: {
117+
render: true,
118+
showName: true,
119+
showImage: false,
120+
showDisclaimer: false,
121+
},
122+
},
123+
{
124+
testInstance: {
125+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/', 'dc.rights': licenseNameMock },
126+
componentInputs: { variant: 'full' },
127+
},
128+
expected: {
129+
render: true,
130+
showName: true,
131+
showImage: false,
132+
showDisclaimer: true,
133+
},
134+
},
135+
{
136+
testInstance: {
137+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/', 'dc.rights': licenseNameMock },
138+
componentInputs: { showName: false },
139+
},
140+
expected: {
141+
render: true,
142+
showName: true,
143+
showImage: false,
144+
showDisclaimer: false,
145+
},
146+
},
147+
{
148+
testInstance: {
149+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/licenses/by/4.0', 'dc.rights': licenseNameMock },
150+
componentInputs: { showName: false },
151+
},
152+
expected: {
153+
render: true,
154+
showName: false,
155+
showImage: true,
156+
showDisclaimer: false,
157+
},
158+
},
159+
{
160+
testInstance: {
161+
metadata: { 'dc.rights.uri': 'https://creativecommons.org/licenses/by/4.0', 'dc.rights': licenseNameMock },
162+
componentInputs: { variant: 'full', showDisclaimer: false },
163+
},
164+
expected: {
165+
render: true,
166+
showName: true,
167+
showImage: true,
168+
showDisclaimer: false,
169+
},
170+
},
171+
];
172+
173+
174+
// Updates the component fixture with parameters from the test instance
175+
function configureFixture(
176+
fixture: ComponentFixture<ItemPageCcLicenseFieldComponent>,
177+
testInstance: TestInstance,
178+
) {
179+
const item = Object.assign(new Item(), {
180+
bundles: createSuccessfulRemoteDataObject$(createPaginatedList([])),
181+
metadata: new MetadataMap(),
182+
});
183+
184+
for (const [key, value] of Object.entries(testInstance.metadata)) {
185+
item.metadata[key] = [
186+
{
187+
language: 'en_US',
188+
value: value,
189+
},
190+
] as MetadataValue[];
191+
}
192+
193+
let component: ItemPageCcLicenseFieldComponent = fixture.componentInstance;
194+
for (const [key, value] of Object.entries(testInstance.componentInputs ?? {})) {
195+
component[key] = value;
196+
}
197+
component.item = item;
198+
199+
fixture.detectChanges();
200+
}
201+
202+
203+
describe('ItemPageCcLicenseFieldComponent', () => {
204+
let fixture: ComponentFixture<ItemPageCcLicenseFieldComponent>;
205+
206+
beforeEach(waitForAsync(() => {
207+
void TestBed.configureTestingModule({
208+
imports: [
209+
TranslateModule.forRoot({
210+
loader: {
211+
provide: TranslateLoader,
212+
useClass: TranslateLoaderMock,
213+
},
214+
}),
215+
ItemPageCcLicenseFieldComponent,
216+
],
217+
providers: [{ provide: APP_CONFIG, useValue: environment }],
218+
schemas: [NO_ERRORS_SCHEMA],
219+
})
220+
.overrideComponent(ItemPageCcLicenseFieldComponent, {
221+
set: { changeDetection: ChangeDetectionStrategy.Default },
222+
})
223+
.compileComponents();
224+
}));
225+
226+
beforeEach(waitForAsync(() => {
227+
fixture = TestBed.createComponent(ItemPageCcLicenseFieldComponent);
228+
}));
229+
230+
testCases.forEach((testCase) => {
231+
describe('', () => {
232+
beforeEach(async () => {
233+
configureFixture(fixture, testCase.testInstance);
234+
235+
// Waits the image to be loaded or to cause an error when loading
236+
let imgEl = fixture.debugElement.query(By.css('img'));
237+
if (imgEl) {
238+
await new Promise<void>((resolve, reject) => {
239+
imgEl.nativeElement.addEventListener('load', () => resolve());
240+
imgEl.nativeElement.addEventListener('error', () => resolve());
241+
});
242+
}
243+
244+
// Executes again because the 'img' element could have been updated due to a loading error
245+
fixture.detectChanges();
246+
});
247+
248+
it('should render or not the component',
249+
() => {
250+
const componentEl = fixture.debugElement.query(By.css('.item-page-field'));
251+
expect(Boolean(componentEl)).toBe(testCase.expected.render);
252+
},
253+
);
254+
255+
it('should show/hide CC license name',
256+
() => {
257+
const nameEl = fixture.debugElement.query(de => de.nativeElement.id === 'cc-name');
258+
expect(Boolean(nameEl)).toBe(testCase.expected.showName);
259+
if (nameEl && testCase.expected.showName) {
260+
expect(nameEl.nativeElement.innerHTML).toContain(licenseNameMock);
261+
}
262+
},
263+
);
264+
265+
it('should show CC license image',
266+
() => {
267+
const imgEl = fixture.debugElement.query(By.css('img'));
268+
expect(Boolean(imgEl)).toBe(testCase.expected.showImage);
269+
},
270+
);
271+
272+
it('should use name fallback when CC image fails loading',
273+
() => {
274+
const nameEl = fixture.debugElement.query(de => de.nativeElement.id === 'cc-name');
275+
expect(Boolean(nameEl)).toBe(testCase.expected.showName);
276+
if (nameEl && testCase.expected.showName) {
277+
expect(nameEl.nativeElement.innerHTML).toContain(licenseNameMock);
278+
}
279+
},
280+
);
281+
282+
it('should show or not CC license disclaimer',
283+
() => {
284+
const disclaimerEl = fixture.debugElement.query(By.css('span'));
285+
if (testCase.expected.showDisclaimer) {
286+
expect(disclaimerEl).toBeTruthy();
287+
expect(disclaimerEl.nativeElement.innerHTML).toContain('item.page.cc.license.disclaimer');
288+
} else if (testCase.expected.render) {
289+
expect(disclaimerEl).toBeTruthy();
290+
expect(disclaimerEl.nativeElement.innerHTML).not.toContain('item.page.cc.license.disclaimer');
291+
} else {
292+
expect(disclaimerEl).toBeFalsy();
293+
}
294+
},
295+
);
296+
});
297+
});
298+
});

0 commit comments

Comments
 (0)