-
Notifications
You must be signed in to change notification settings - Fork 3
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 #27 from onecx-apps/fixUnitTest
Improve datepipe and fix unit tests
- Loading branch information
Showing
2 changed files
with
102 additions
and
49 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,84 @@ | ||
// Core imports | ||
import { TestBed } from '@angular/core/testing'; | ||
import { RelativeDatePipe } from './relative-date.pipe'; | ||
import { TranslateService } from '@ngx-translate/core'; | ||
import { TranslateServiceMock } from 'src/app/test/TranslateServiceMock'; | ||
|
||
describe('RelativeDatePipe', () => { | ||
const value = []; | ||
const pipe = new RelativeDatePipe(value as any); | ||
let pipe: RelativeDatePipe; | ||
let translateService: TranslateService; | ||
|
||
beforeEach(async () => { | ||
TestBed.configureTestingModule({ | ||
providers: [ | ||
RelativeDatePipe, | ||
{ provide: TranslateService, useClass: TranslateServiceMock }, | ||
], | ||
}); | ||
|
||
pipe = TestBed.inject(RelativeDatePipe); | ||
translateService = TestBed.inject(TranslateService); | ||
}); | ||
|
||
it('create an instance', () => { | ||
expect(pipe).toBeTruthy(); | ||
}); | ||
it('should transform a string date to relative date', () => { | ||
const result = pipe.transform('2022-07-01'); | ||
expect(result).toBe('1 year ago'); | ||
|
||
it('should transform date strings into relative time format', () => { | ||
const now = new Date(); | ||
const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000); | ||
const result = pipe.transform(fiveMinutesAgo.toISOString()); | ||
expect(result).toBe('5 minutes ago'); | ||
}); | ||
|
||
it('should transform date objects into relative time format', () => { | ||
const now = new Date(); | ||
const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000); | ||
const result = pipe.transform(fiveMinutesAgo); | ||
expect(result).toBe('5 minutes ago'); | ||
}); | ||
|
||
it('should return "just now" for very recent dates', () => { | ||
const now = new Date(); | ||
const justNow = new Date(now.getTime() - 1000); // 1 second ago | ||
const result = pipe.transform(justNow); | ||
expect(result).toBe('just now'); | ||
}); | ||
it('should return "just now" for durations under 60 seconds', () => { | ||
const now = new Date(); | ||
const justNow = new Date(now.getTime() - 1000 * 59); // 59 second ago | ||
const result = pipe.transform(justNow); | ||
expect(result).toBe('just now'); | ||
}); | ||
it('should transform an object date to relative date', () => { | ||
const date = new Date('2022-07-01'); | ||
const result = pipe.transform(date); | ||
expect(result).toBe('1 year ago'); | ||
|
||
it('should handle dates in the past year correctly', () => { | ||
const now = new Date(); | ||
const sixMonthsAgo = new Date(now.getTime() - 6 * 30 * 24 * 60 * 60 * 1000); // Approx 6 months | ||
const result = pipe.transform(sixMonthsAgo); | ||
expect(result).toBe('6 months ago'); | ||
}); | ||
|
||
it('should handle dates in the past years correctly', () => { | ||
const now = new Date(); | ||
const twoYearsAgo = new Date(now.getTime() - 2 * 365 * 24 * 60 * 60 * 1000); // Approx 2 years | ||
const result = pipe.transform(twoYearsAgo); | ||
expect(result).toBe('2 years ago'); | ||
}); | ||
|
||
it('should return "1 hour ago" for exactly one hour ago', () => { | ||
const now = new Date(); | ||
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000); // 1 hour ago | ||
const result = pipe.transform(oneHourAgo); | ||
expect(result).toBe('1 hour ago'); | ||
}); | ||
|
||
it('should handle invalid input gracefully', () => { | ||
const result = pipe.transform('invalid-date'); | ||
expect(result).toBeUndefined(); | ||
}); | ||
|
||
it('should handle invalid input gracefully', () => { | ||
const result = pipe.transform(undefined); | ||
expect(result).toBeUndefined(); | ||
}); | ||
}); |
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 |
---|---|---|
@@ -1,51 +1,39 @@ | ||
// Core imports | ||
import { Pipe, PipeTransform } from '@angular/core'; | ||
|
||
// Third party imports | ||
import { TranslateService } from '@ngx-translate/core'; | ||
@Pipe({ name: 'relativeDate' }) | ||
export class RelativeDatePipe implements PipeTransform { | ||
transform(value: Date | string | number | undefined): string | undefined { | ||
if (value === undefined) { | ||
return undefined; | ||
} | ||
|
||
const DIVISIONS: { amount: number; name: Intl.RelativeTimeFormatUnit }[] = [ | ||
{ amount: 60, name: 'seconds' }, | ||
{ amount: 60, name: 'minutes' }, | ||
{ amount: 24, name: 'hours' }, | ||
{ amount: 7, name: 'days' }, | ||
{ amount: 4.34524, name: 'weeks' }, | ||
{ amount: 12, name: 'months' }, | ||
{ amount: Number.POSITIVE_INFINITY, name: 'years' }, | ||
]; | ||
if (!(value instanceof Date)) { | ||
value = new Date(value); | ||
if (isNaN(value.getTime())) { | ||
return undefined; | ||
} | ||
} | ||
|
||
@Pipe({ | ||
name: 'relativeDate', | ||
}) | ||
export class RelativeDatePipe implements PipeTransform { | ||
rtf: Intl.RelativeTimeFormat; | ||
const seconds = Math.floor((new Date().getTime() - value.getTime()) / 1000); | ||
|
||
constructor(private readonly translateService: TranslateService) { | ||
this.rtf = new Intl.RelativeTimeFormat(this.translateService.currentLang, { | ||
style: 'long', | ||
}); | ||
} | ||
/** convert string format into relative date format */ | ||
transform(value: any, args?: any): any { | ||
let date: Date; | ||
switch (typeof value) { | ||
case 'string': | ||
date = new Date(value); | ||
break; | ||
case 'object': | ||
date = value; | ||
break; | ||
default: | ||
break; | ||
if (seconds < 60) { | ||
return 'just now'; | ||
} | ||
|
||
let duration = (date.getTime() - new Date().getTime()) / 1000; | ||
for (let i = 0; i <= DIVISIONS.length; i++) { | ||
const division = DIVISIONS[i]; | ||
if (Math.abs(duration) < division.amount) { | ||
return this.rtf.format(Math.round(duration), division.name); | ||
const intervals = [ | ||
{ label: 'year', seconds: 31536000 }, | ||
{ label: 'month', seconds: 2592000 }, | ||
{ label: 'day', seconds: 86400 }, | ||
{ label: 'hour', seconds: 3600 }, | ||
{ label: 'minute', seconds: 60 }, | ||
{ label: 'second', seconds: 1 }, | ||
]; | ||
|
||
for (const interval of intervals) { | ||
const count = Math.floor(seconds / interval.seconds); | ||
if (count >= 1) { | ||
return count + ` ${interval.label}${count !== 1 ? 's' : ''} ago`; | ||
} | ||
duration /= division.amount; | ||
} | ||
} | ||
} |