Skip to content

Commit ac0ace0

Browse files
author
francescomauto
committed
[DSC-2761] add: unit tests for InWorkflowStatisticsComponent and fix linting
1 parent 44f3f14 commit ac0ace0

2 files changed

Lines changed: 187 additions & 2 deletions

File tree

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import {
2+
ComponentFixture,
3+
TestBed,
4+
} from '@angular/core/testing';
5+
import { TranslateModule } from '@ngx-translate/core';
6+
7+
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
8+
import { ItemDataService } from '../../../../core/data/item-data.service';
9+
import { Item } from '../../../../core/shared/item.model';
10+
import { InWorkflowStatisticsComponent } from './in-workflow-statistics.component';
11+
12+
describe('InWorkflowStatisticsComponent', () => {
13+
let component: InWorkflowStatisticsComponent;
14+
let fixture: ComponentFixture<InWorkflowStatisticsComponent>;
15+
let authorizationService: jasmine.SpyObj<AuthorizationDataService>;
16+
let itemDataService: jasmine.SpyObj<ItemDataService>;
17+
18+
beforeEach(async () => {
19+
const authorizationServiceSpy = jasmine.createSpyObj('AuthorizationDataService', ['isAuthorized']);
20+
const itemDataServiceSpy = jasmine.createSpyObj('ItemDataService', ['findById']);
21+
22+
await TestBed.configureTestingModule({
23+
imports: [InWorkflowStatisticsComponent, TranslateModule.forRoot()],
24+
providers: [
25+
{ provide: AuthorizationDataService, useValue: authorizationServiceSpy },
26+
{ provide: ItemDataService, useValue: itemDataServiceSpy },
27+
],
28+
}).compileComponents();
29+
30+
authorizationService = TestBed.inject(AuthorizationDataService) as jasmine.SpyObj<AuthorizationDataService>;
31+
itemDataService = TestBed.inject(ItemDataService) as jasmine.SpyObj<ItemDataService>;
32+
fixture = TestBed.createComponent(InWorkflowStatisticsComponent);
33+
component = fixture.componentInstance;
34+
});
35+
36+
describe('initWorkflowDates', () => {
37+
it('should not initialize workflow dates if item is archived', () => {
38+
const mockItem = createMockItem({
39+
isArchived: true,
40+
hasMetadata: true,
41+
});
42+
43+
component.item = mockItem;
44+
component.initWorkflowDates();
45+
46+
expect(component.canViewInWorkflowSinceDate$.getValue()).toBe(false);
47+
expect(component.inWorkflowSince$.getValue()).toBeNull();
48+
});
49+
50+
it('should not initialize workflow dates if item does not have dspace.workflow.startDateTime metadata', () => {
51+
const mockItem = createMockItem({
52+
isArchived: false,
53+
hasMetadata: false,
54+
});
55+
56+
component.item = mockItem;
57+
component.initWorkflowDates();
58+
59+
expect(component.canViewInWorkflowSinceDate$.getValue()).toBe(false);
60+
expect(component.inWorkflowSince$.getValue()).toBeNull();
61+
});
62+
63+
it('should initialize workflow dates if item has workflow start date and is not archived', () => {
64+
const mockItem = createMockItem({
65+
isArchived: false,
66+
hasMetadata: true,
67+
metadataValue: '2026-05-10T10:30:00Z',
68+
});
69+
70+
component.item = mockItem;
71+
component.initWorkflowDates();
72+
73+
expect(component.canViewInWorkflowSinceDate$.getValue()).toBe(true);
74+
expect(component.inWorkflowSince$.getValue()).toBeTruthy();
75+
expect(component.inWorkflowSince$.getValue()).toMatch(/\d+ d \d+ h/);
76+
});
77+
78+
it('should not process if item is null', () => {
79+
component.item = null;
80+
component.initWorkflowDates();
81+
82+
expect(component.canViewInWorkflowSinceDate$.getValue()).toBe(false);
83+
expect(component.inWorkflowSince$.getValue()).toBeNull();
84+
});
85+
86+
it('should not process if item is undefined', () => {
87+
component.item = undefined;
88+
component.initWorkflowDates();
89+
90+
expect(component.canViewInWorkflowSinceDate$.getValue()).toBe(false);
91+
expect(component.inWorkflowSince$.getValue()).toBeNull();
92+
});
93+
94+
it('should format workflow start date correctly using getDateForItem', () => {
95+
const mockItem = createMockItem({
96+
isArchived: false,
97+
hasMetadata: true,
98+
metadataValue: '2026-05-13T00:00:00Z', // Yesterday (assuming today is 2026-05-14)
99+
});
100+
101+
component.item = mockItem;
102+
component.initWorkflowDates();
103+
104+
const formattedDate = component.inWorkflowSince$.getValue();
105+
expect(formattedDate).toContain('d');
106+
expect(formattedDate).toContain('h');
107+
});
108+
});
109+
110+
describe('getDateForItem', () => {
111+
it('should calculate days and hours correctly', () => {
112+
const pastDate = '2026-05-10T10:30:00Z'; // 4 days ago
113+
const result = component.getDateForItem(pastDate);
114+
115+
expect(result).toMatch(/\d+ d \d+ h/);
116+
expect(result).toContain('d');
117+
expect(result).toContain('h');
118+
});
119+
120+
it('should return 0 days and 0 hours for current timestamp', () => {
121+
const now = new Date().toISOString();
122+
const result = component.getDateForItem(now);
123+
124+
expect(result).toMatch(/^0 d 0 h$/);
125+
});
126+
127+
it('should return positive values only', () => {
128+
const futureDate = new Date(Date.now() + 10 * 24 * 60 * 60 * 1000).toISOString(); // 10 days in future
129+
const result = component.getDateForItem(futureDate);
130+
131+
const match = result.match(/(\d+) d (\d+) h/);
132+
expect(match).toBeTruthy();
133+
const days = parseInt(match[1], 10);
134+
const hours = parseInt(match[2], 10);
135+
expect(days).toBeGreaterThanOrEqual(0);
136+
expect(hours).toBeGreaterThanOrEqual(0);
137+
});
138+
});
139+
140+
describe('getDateForArchivedItem', () => {
141+
it('should calculate days and hours between two dates', () => {
142+
const startDate = '2026-05-10T10:30:00Z';
143+
const accessionedDate = '2026-05-14T14:30:00Z'; // 4 days, 4 hours later
144+
const result = component.getDateForArchivedItem(startDate, accessionedDate);
145+
146+
expect(result).toMatch(/\d+ d \d+ h/);
147+
});
148+
149+
it('should return 0 days and 0 hours for same timestamp', () => {
150+
const date = '2026-05-14T10:30:00Z';
151+
const result = component.getDateForArchivedItem(date, date);
152+
153+
expect(result).toMatch(/^0 d 0 h$/);
154+
});
155+
156+
it('should return positive values only', () => {
157+
const startDate = '2026-05-12T08:00:00Z';
158+
const accessionedDate = '2026-05-10T10:30:00Z'; // before start date
159+
const result = component.getDateForArchivedItem(startDate, accessionedDate);
160+
161+
// Since accessionedDate is before startDate, the difference should be negative,
162+
// but the Math.max(0, ...) should ensure 0 as minimum
163+
expect(result).toMatch(/^0 d 0 h$/);
164+
});
165+
});
166+
167+
// Helper function to create mock Item
168+
function createMockItem(options: {
169+
isArchived: boolean;
170+
hasMetadata: boolean;
171+
metadataValue?: string;
172+
}): Item {
173+
const mockItem = {
174+
isArchived: options.isArchived,
175+
hasMetadata: (metadata: string) => options.hasMetadata,
176+
firstMetadataValue: (metadata: string) => options.metadataValue || '2026-05-10T10:30:00Z',
177+
id: 'test-item-id',
178+
self: 'http://test.com/item/test-item-id',
179+
} as unknown as Item;
180+
181+
return mockItem;
182+
}
183+
});

src/app/shared/object-collection/shared/in-workflow-statistics/in-workflow-statistics.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,11 @@ export class InWorkflowStatisticsComponent implements OnInit {
9595

9696
initWorkflowDates(): void {
9797
if (this.item) {
98-
if (this.item.isArchived) {return;}
98+
if (this.item.isArchived){
99+
return;
100+
}
99101

100-
if ( this.item.hasMetadata('dspace.workflow.startDateTime')) {
102+
if (this.item.hasMetadata('dspace.workflow.startDateTime')) {
101103
this.canViewInWorkflowSinceDate$.next(true);
102104
this.inWorkflowSince$.next(
103105
this.getDateForItem(this.item.firstMetadataValue('dspace.workflow.startDateTime')),

0 commit comments

Comments
 (0)