Skip to content

Commit 6c2c2d6

Browse files
[DURACOM-317] clean up, add tests
1 parent bfc6de5 commit 6c2c2d6

8 files changed

Lines changed: 314 additions & 212 deletions

File tree

src/app/audit-page/audit-table/audit-table.component.html

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -75,56 +75,15 @@
7575
</tr>
7676
@if (audit.hasDetails) {
7777
<tr [(ngbCollapse)]="audit.isCollapsed" [id]="audit.id" [ngClass]="{'border-top-0': !audit.isCollapsed}" class="w-100 nested-row">
78-
<td colspan="4" class="border-top-0">
79-
<div class="w-100">
80-
<div class="d-flex flex-column mw-100 w-100">
81-
@if (audit.metadataField) {
82-
<div class="d-flex mb-1">
83-
<small class="font-weight-bold me-2" >{{"audit.detail.metadata.field" | translate}}</small>
84-
<small>{{ audit.metadataField | dsStringReplace: "_":"." }}</small>
85-
</div>
86-
}
87-
@if (audit.value) {
88-
<div class="d-flex mb-1">
89-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.value" | translate}}</small>
90-
<small class="content dont-break-out preserve-line-breaks">
91-
{{ audit.value }}
92-
</small>
93-
</div>
94-
}
95-
@if (audit.authority) {
96-
<div class="d-flex mb-1">
97-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.authority" | translate}}</small>
98-
<small>{{ audit.authority }}</small>
99-
</div>
100-
}
101-
@if (audit.confidence !== null) {
102-
<div class="d-flex mb-1">
103-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.confidence" | translate}}</small>
104-
<small>{{ audit.confidence }}</small>
105-
</div>
106-
}
107-
@if (audit.place !== null) {
108-
<div class="d-flex mb-1">
109-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.place" | translate}}</small>
110-
<small>{{ audit.place }}</small>
111-
</div>
112-
}
113-
@if (audit.action) {
114-
<div class="d-flex mb-1">
115-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.action" | translate}}</small>
116-
<small>{{ audit.action }}</small>
117-
</div>
118-
}
119-
@if (audit.checksum) {
120-
<div class="d-flex">
121-
<small class="font-weight-bold me-2">{{"audit.detail.metadata.checksum" | translate}}</small>
122-
<small>{{ audit.checksum }}</small>
123-
</div>
124-
}
125-
</div>
126-
</div>
127-
</td>
78+
@if (isOverviewPage) {
79+
<td colspan="7" class="border-top-0">
80+
<ng-container *ngTemplateOutlet="auditInto; context: { audit }"></ng-container>
81+
</td>
82+
} @else {
83+
<td colspan="4" class="border-top-0">
84+
<ng-container *ngTemplateOutlet="auditInto; context: { audit }"></ng-container>
85+
</td>
86+
}
12887
</tr>
12988
}
13089
}
@@ -134,3 +93,53 @@
13493
</ds-pagination>
13594
}
13695

96+
<ng-template #auditInto let-audit=audit>
97+
<div class="w-100">
98+
<div class="d-flex flex-column mw-100 w-100">
99+
@if (audit.metadataField) {
100+
<div class="d-flex mb-1">
101+
<small class="font-weight-bold me-2" >{{"audit.detail.metadata.field" | translate}}</small>
102+
<small>{{ audit.metadataField | dsStringReplace: "_":"." }}</small>
103+
</div>
104+
}
105+
@if (audit.value) {
106+
<div class="d-flex mb-1">
107+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.value" | translate}}</small>
108+
<small class="content dont-break-out preserve-line-breaks">
109+
{{ audit.value }}
110+
</small>
111+
</div>
112+
}
113+
@if (audit.authority) {
114+
<div class="d-flex mb-1">
115+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.authority" | translate}}</small>
116+
<small>{{ audit.authority }}</small>
117+
</div>
118+
}
119+
@if (audit.confidence !== null) {
120+
<div class="d-flex mb-1">
121+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.confidence" | translate}}</small>
122+
<small>{{ audit.confidence }}</small>
123+
</div>
124+
}
125+
@if (audit.place !== null) {
126+
<div class="d-flex mb-1">
127+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.place" | translate}}</small>
128+
<small>{{ audit.place }}</small>
129+
</div>
130+
}
131+
@if (audit.action) {
132+
<div class="d-flex mb-1">
133+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.action" | translate}}</small>
134+
<small>{{ audit.action }}</small>
135+
</div>
136+
}
137+
@if (audit.checksum) {
138+
<div class="d-flex">
139+
<small class="font-weight-bold me-2">{{"audit.detail.metadata.checksum" | translate}}</small>
140+
<small>{{ audit.checksum }}</small>
141+
</div>
142+
}
143+
</div>
144+
</div>
145+
</ng-template>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { NO_ERRORS_SCHEMA } from '@angular/core';
2+
import {
3+
ComponentFixture,
4+
TestBed,
5+
waitForAsync,
6+
} from '@angular/core/testing';
7+
import { By } from '@angular/platform-browser';
8+
import { RouterTestingModule } from '@angular/router/testing';
9+
import { TranslateModule } from '@ngx-translate/core';
10+
import { PaginatedList } from 'src/app/core/data/paginated-list.model';
11+
12+
import { Audit } from '../../core/audit/model/audit.model';
13+
import { DSONameService } from '../../core/breadcrumbs/dso-name.service';
14+
import { DSONameServiceMock } from '../../shared/mocks/dso-name.service.mock';
15+
import { PaginationComponent } from '../../shared/pagination/pagination.component';
16+
import { AuditMock } from '../../shared/testing/audit.mock';
17+
import { AuditTableComponent } from './audit-table.component';
18+
19+
describe('AuditTableComponent', () => {
20+
let component: AuditTableComponent;
21+
let fixture: ComponentFixture<AuditTableComponent>;
22+
23+
let audits = new PaginatedList() as PaginatedList<Audit>;
24+
25+
beforeEach(waitForAsync(() => {
26+
audits.page = [ AuditMock ];
27+
TestBed.configureTestingModule({
28+
imports: [
29+
TranslateModule.forRoot(),
30+
RouterTestingModule.withRoutes([]),
31+
AuditTableComponent,
32+
PaginationComponent,
33+
],
34+
providers: [
35+
{ provide: DSONameService, useValue: new DSONameServiceMock() },
36+
],
37+
schemas: [NO_ERRORS_SCHEMA],
38+
})
39+
.overrideComponent(AuditTableComponent, {
40+
remove: { imports: [PaginationComponent] },
41+
})
42+
.compileComponents();
43+
}));
44+
45+
beforeEach(() => {
46+
fixture = TestBed.createComponent(AuditTableComponent);
47+
component = fixture.componentInstance;
48+
component.audits = audits;
49+
component.isOverviewPage = true;
50+
fixture.detectChanges();
51+
});
52+
53+
describe('table structure', () => {
54+
55+
it('should display the entityType in the first column', () => {
56+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
57+
const el = rowElements[0].query(By.css('td:nth-child(1)')).nativeElement;
58+
expect(el.textContent).toContain(audits.page[0].eventType);
59+
});
60+
61+
it('should display the eperson in the second column', () => {
62+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
63+
const el = rowElements[0].query(By.css('td:nth-child(2)')).nativeElement;
64+
expect(el.textContent).toContain(audits.page[0].epersonName);
65+
});
66+
67+
it('should display the timestamp in the third column', () => {
68+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
69+
const el = rowElements[0].query(By.css('td:nth-child(3)')).nativeElement;
70+
expect(el.textContent).toContain('2020-11-13 11:41:06');
71+
});
72+
73+
it('should display the objectUUID in the fourth column', () => {
74+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
75+
const el = rowElements[0].query(By.css('td:nth-child(4)')).nativeElement;
76+
expect(el.textContent).toContain(audits.page[0].objectUUID);
77+
});
78+
79+
it('should display the objectType in the fifth column', () => {
80+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
81+
const el = rowElements[0].query(By.css('td:nth-child(5)')).nativeElement;
82+
expect(el.textContent).toContain(audits.page[0].objectType);
83+
});
84+
85+
it('should display the subjectUUID in the sixth column', () => {
86+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
87+
const el = rowElements[0].query(By.css('td:nth-child(6)')).nativeElement;
88+
expect(el.textContent).toContain(audits.page[0].subjectUUID);
89+
});
90+
91+
it('should display the subjectType in the seventh column', () => {
92+
const rowElements = fixture.debugElement.queryAll(By.css('tbody tr'));
93+
const el = rowElements[0].query(By.css('td:nth-child(7)')).nativeElement;
94+
expect(el.textContent).toContain(audits.page[0].subjectType);
95+
});
96+
});
97+
});

src/app/audit-page/audit-table/audit-table.component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
AsyncPipe,
33
DatePipe,
44
NgClass,
5+
NgTemplateOutlet,
56
} from '@angular/common';
67
import {
78
ChangeDetectorRef,
@@ -35,6 +36,7 @@ import { VarDirective } from '../../shared/utils/var.directive';
3536
StringReplacePipe,
3637
NgClass,
3738
NgbCollapseModule,
39+
NgTemplateOutlet,
3840
],
3941
standalone: true,
4042
})
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { NO_ERRORS_SCHEMA } from '@angular/core';
2+
import {
3+
ComponentFixture,
4+
fakeAsync,
5+
TestBed,
6+
tick,
7+
waitForAsync,
8+
} from '@angular/core/testing';
9+
import {
10+
ActivatedRoute,
11+
Router,
12+
RouterLink,
13+
} from '@angular/router';
14+
import { RouterTestingModule } from '@angular/router/testing';
15+
import { provideMockStore } from '@ngrx/store/testing';
16+
import { TranslateModule } from '@ngx-translate/core';
17+
import { of as observableOf } from 'rxjs';
18+
import { CollectionDataService } from 'src/app/core/data/collection-data.service';
19+
import { Item } from 'src/app/core/shared/item.model';
20+
import { APP_DATA_SERVICES_MAP } from 'src/config/app-config.interface';
21+
22+
import { AuditDataService } from '../../core/audit/audit-data.service';
23+
import { Audit } from '../../core/audit/model/audit.model';
24+
import { ItemDataService } from '../../core/data/item-data.service';
25+
import { PaginationService } from '../../core/pagination/pagination.service';
26+
import { MockActivatedRoute } from '../../shared/mocks/active-router.mock';
27+
import { RouterMock } from '../../shared/mocks/router.mock';
28+
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
29+
import { AuditMock } from '../../shared/testing/audit.mock';
30+
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
31+
import { createPaginatedList } from '../../shared/testing/utils.test';
32+
import { AuditTableComponent } from '../audit-table/audit-table.component';
33+
import { ObjectAuditOverviewComponent } from './object-audit-overview.component';
34+
35+
describe('ObjectAuditOverviewComponent', () => {
36+
let component: ObjectAuditOverviewComponent;
37+
let fixture: ComponentFixture<ObjectAuditOverviewComponent>;
38+
39+
let auditService: AuditDataService;
40+
let audits: Audit[];
41+
let itemService: ItemDataService;
42+
let collectionService;
43+
let activatedRoute;
44+
45+
46+
function init() {
47+
audits = [ AuditMock ];
48+
auditService = jasmine.createSpyObj('auditService', {
49+
findByObject: createSuccessfulRemoteDataObject$(createPaginatedList(audits)),
50+
getEpersonName: observableOf('Eperson Name'),
51+
auditHasDetails: false,
52+
});
53+
itemService = jasmine.createSpyObj('ItemService', { findById: createSuccessfulRemoteDataObject$(new Item()) });
54+
collectionService = jasmine.createSpyObj('CollectionDataService',
55+
{ findOwningCollectionFor: createSuccessfulRemoteDataObject$(createPaginatedList([{ id : 'collectionId' }])) },
56+
);
57+
activatedRoute = new MockActivatedRoute({ objectId: '1234' });
58+
activatedRoute.paramMap = observableOf({
59+
get: () => '1234',
60+
});
61+
}
62+
63+
beforeEach(waitForAsync(() => {
64+
init();
65+
TestBed.configureTestingModule({
66+
imports: [
67+
TranslateModule.forRoot(),
68+
RouterTestingModule.withRoutes([]),
69+
AuditTableComponent,
70+
ObjectAuditOverviewComponent,
71+
RouterLink,
72+
],
73+
providers: [
74+
{ provide: AuditDataService, useValue: auditService },
75+
{ provide: PaginationService, useValue: new PaginationServiceStub() },
76+
{ provide: ItemDataService, useValue: itemService },
77+
{ provide: ActivatedRoute, useValue: activatedRoute },
78+
{ provide: Router, useValue: new RouterMock() },
79+
{ provide: CollectionDataService, useValue: collectionService },
80+
{ provide: APP_DATA_SERVICES_MAP, useValue: new Map() },
81+
provideMockStore({}),
82+
],
83+
schemas: [NO_ERRORS_SCHEMA],
84+
})
85+
.overrideComponent(ObjectAuditOverviewComponent, {
86+
remove: {
87+
imports: [AuditTableComponent],
88+
},
89+
})
90+
.compileComponents();
91+
}));
92+
93+
beforeEach(() => {
94+
fixture = TestBed.createComponent(ObjectAuditOverviewComponent);
95+
component = fixture.componentInstance;
96+
spyOn(component, 'setAudits').and.callThrough();
97+
fixture.detectChanges();
98+
});
99+
100+
describe('object detail data setting', () => {
101+
it('should set audits on init', fakeAsync(() => {
102+
tick();
103+
fixture.detectChanges();
104+
expect(component.setAudits).toHaveBeenCalled();
105+
}));
106+
107+
it('should set owning collection', () => {
108+
expect(component.owningCollection$).toBeTruthy();
109+
});
110+
});
111+
});

0 commit comments

Comments
 (0)