Skip to content

Commit

Permalink
feat: add timeline statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciej Łukasik committed Oct 14, 2020
1 parent 822ae45 commit b52ca1a
Show file tree
Hide file tree
Showing 111 changed files with 2,718 additions and 237 deletions.
172 changes: 172 additions & 0 deletions angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -2224,6 +2224,178 @@
}
}
},
"pmp-web-repository-repository-pr-timeline-data-access": {
"projectType": "library",
"root": "libs/pmp-web/repository/repository-pr-timeline/data-access",
"sourceRoot": "libs/pmp-web/repository/repository-pr-timeline/data-access/src",
"prefix": "pimp-my-pr",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/pmp-web/repository/repository-pr-timeline/data-access/tsconfig.lib.json",
"libs/pmp-web/repository/repository-pr-timeline/data-access/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/pmp-web/repository/repository-pr-timeline/data-access/**"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/pmp-web/repository/repository-pr-timeline/data-access/jest.config.js",
"tsConfig": "libs/pmp-web/repository/repository-pr-timeline/data-access/tsconfig.spec.json",
"passWithNoTests": true,
"setupFile": "libs/pmp-web/repository/repository-pr-timeline/data-access/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
}
},
"pmp-web-repository-repository-pr-timeline-feature": {
"projectType": "library",
"root": "libs/pmp-web/repository/repository-pr-timeline/feature",
"sourceRoot": "libs/pmp-web/repository/repository-pr-timeline/feature/src",
"prefix": "pimp-my-pr",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/pmp-web/repository/repository-pr-timeline/feature/tsconfig.lib.json",
"libs/pmp-web/repository/repository-pr-timeline/feature/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/pmp-web/repository/repository-pr-timeline/feature/**"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/pmp-web/repository/repository-pr-timeline/feature/jest.config.js",
"tsConfig": "libs/pmp-web/repository/repository-pr-timeline/feature/tsconfig.spec.json",
"passWithNoTests": true,
"setupFile": "libs/pmp-web/repository/repository-pr-timeline/feature/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
}
},
"pmp-web-repository-repository-pr-timeline-ui-charts": {
"projectType": "library",
"root": "libs/pmp-web/repository/repository-pr-timeline/ui-charts",
"sourceRoot": "libs/pmp-web/repository/repository-pr-timeline/ui-charts/src",
"prefix": "pimp-my-pr",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/pmp-web/repository/repository-pr-timeline/ui-charts/tsconfig.lib.json",
"libs/pmp-web/repository/repository-pr-timeline/ui-charts/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/pmp-web/repository/repository-pr-timeline/ui-charts/**"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/pmp-web/repository/repository-pr-timeline/ui-charts/jest.config.js",
"tsConfig": "libs/pmp-web/repository/repository-pr-timeline/ui-charts/tsconfig.spec.json",
"passWithNoTests": true,
"setupFile": "libs/pmp-web/repository/repository-pr-timeline/ui-charts/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
}
},
"pmp-web-shared-ui-error-box": {
"projectType": "library",
"root": "libs/pmp-web/shared/ui-error-box",
"sourceRoot": "libs/pmp-web/shared/ui-error-box/src",
"prefix": "pimp-my-pr",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/pmp-web/shared/ui-error-box/tsconfig.lib.json",
"libs/pmp-web/shared/ui-error-box/tsconfig.spec.json"
],
"exclude": ["**/node_modules/**", "!libs/pmp-web/shared/ui-error-box/**"]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/pmp-web/shared/ui-error-box/jest.config.js",
"tsConfig": "libs/pmp-web/shared/ui-error-box/tsconfig.spec.json",
"passWithNoTests": true,
"setupFile": "libs/pmp-web/shared/ui-error-box/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
}
},
"pmp-web-repository-repository-pr-timeline-util-cross-date-validators": {
"projectType": "library",
"root": "libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators",
"sourceRoot": "libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/src",
"prefix": "pimp-my-pr",
"architect": {
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/tsconfig.lib.json",
"libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**",
"!libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/**"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"options": {
"jestConfig": "libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/jest.config.js",
"tsConfig": "libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/tsconfig.spec.json",
"passWithNoTests": true,
"setupFile": "libs/pmp-web/repository/repository-pr-timeline/util-cross-date-validators/src/test-setup.ts"
}
}
},
"schematics": {
"@nrwl/angular:component": {
"style": "scss"
}
}
},
"pmp-web-repository-repository-settings-data-access": {
"projectType": "library",
"root": "libs/pmp-web/repository/repository-settings/data-access",
Expand Down
7 changes: 7 additions & 0 deletions libs/pmp-web/repository/domain/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
export * from './lib/interfaces/repository.model';
export * from './lib/interfaces/add-edit-repository-dialog-data.interface';
export * from './lib/interfaces/timeline.interface';
export * from './lib/interfaces/timeline-properties.interface';
export * from './lib/interfaces/timeline-record.interface';
export * from './lib/interfaces/timeline-settings.interface';
export * from './lib/interfaces/timeline-chart-range.interface';
export * from './lib/interfaces/timeline-total-stats.interface';
export * from './lib/interfaces/setting.model';
export * from './lib/interfaces/setting-patch.interface';
export * from './lib/payloads/add-repository.payload';
Expand All @@ -9,4 +15,5 @@ export * from './lib/payloads/edit-repository.payload';
export * from './lib/payloads/get-repository-collection.payload';
export * from './lib/payloads/get-repository-statistics.payload';
export * from './lib/payloads/get-reviewers-statistics-collection.payload';
export * from './lib/payloads/get-pr-timeline.payload';
export * from './lib/payloads/update-setting-model.payload';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface TimelineChartRange {
toDate: Date | null;
fromDate: Date | null;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { TimelineStep } from '@pimp-my-pr/shared/domain';

export interface TimelineProperties {
step: TimelineStep;
dateFrom: Date;
trackedFrom: Date;
totalPrs: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface TimelineRecord {
dataFrom: Date;
sumCount: number;
avgCount: number;
avgWaitingTime: number;
/**
* This field is required to calculate total prs count in the selected time period on the timeline
*/
closedBefore: number;
/**
* This field is required to calculate total prs count in the selected time period on the timeline
*/
openedAfter: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { TimelineStep } from '@pimp-my-pr/shared/domain';

export interface TimelineSettings {
step: TimelineStep;
timelineFrom: Date;
timelineTo: Date;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface TimelineTotalStats {
totalPrs: number;
avgPrsCount: number;
avgWaitingTime: number;
opened: number;
closed: number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { TimelineProperties } from './timeline-properties.interface';
import { TimelineRecord } from './timeline-record.interface';

export interface Timeline extends TimelineProperties {
data: TimelineRecord[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { TimelineSettings } from '../..';

export interface GetPrTimelinePayload extends TimelineSettings {
repositoryId: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# pmp-web-repository-repository-timeline-data-access

This library was generated with [Nx](https://nx.dev).

## Running unit tests

Run `nx test pmp-web-repository-repository-timeline-data-access` to execute the unit tests.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
name: 'pmp-web-repository-repository-pr-timeline-data-access',
preset: '../../../../../jest.config.js',
coverageDirectory:
'../../../../../coverage/libs/pmp-web/repository/repository-pr-timeline/data-access',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js'
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './lib/+state/timeline.facade';
export * from './lib/+state/timeline.reducer';
export * from './lib/+state/timeline.selectors';
export * from './lib/pmp-web-repository-repository-pr-timeline-data-access.module';
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Action } from '@ngrx/store';
import { HttpErrorResponse } from '@angular/common/http';
import { Timeline } from '@pimp-my-pr/pmp-web/repository/domain';
import { GetPrTimelinePayload } from '@pimp-my-pr/pmp-web/repository/domain';

export namespace fromTimelineActions {
export enum Types {
GetTimeline = '[Repository pr timeline] Get Timeline',
GetTimelineFail = '[Repository pr timeline] Get Timeline Fail',
GetTimelineSuccess = '[Repository pr timeline] Get Timeline Success'
}

export class GetTimeline implements Action {
readonly type = Types.GetTimeline;

constructor(public payload: GetPrTimelinePayload) {}
}

export class GetTimelineFail implements Action {
readonly type = Types.GetTimelineFail;

constructor(public payload: HttpErrorResponse) {}
}

export class GetTimelineSuccess implements Action {
readonly type = Types.GetTimelineSuccess;

constructor(public payload: Timeline) {}
}

export type CollectiveType = GetTimeline | GetTimelineSuccess | GetTimelineFail;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { TestBed } from '@angular/core/testing';
import { Observable } from 'rxjs';
import { provideMockActions } from '@ngrx/effects/testing';
import { provideMockStore } from '@ngrx/store/testing';
import { NxModule, DataPersistence } from '@nrwl/angular';
import { cold, hot } from 'jest-marbles';
import { TimelineEffects } from './timeline.effects';
import { fromTimelineActions } from './timeline.actions';
import { TimelineDataService } from '../services/timeline-data.service';
import { createSpyObj } from 'jest-createspyobj';

describe('TimelineEffects', () => {
let timelineDataService: jest.Mocked<TimelineDataService>;
let actions: Observable<any>;
let effects: TimelineEffects;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [NxModule.forRoot()],
providers: [
TimelineEffects,
DataPersistence,
provideMockActions(() => actions),
provideMockStore({ initialState: {} }),
{
provide: TimelineDataService,
useValue: createSpyObj(TimelineDataService)
}
]
});

effects = TestBed.get(TimelineEffects);
timelineDataService = TestBed.get(TimelineDataService);
});

describe('getTimelineRecord$', () => {
test('returns GetTimelineSuccess action on success', () => {
const payload = {} as any;
const action = new fromTimelineActions.GetTimeline({} as any);
const completion = new fromTimelineActions.GetTimelineSuccess(payload);

actions = hot('-a', { a: action });
const response = cold('--b|', { b: payload });
const expected = cold('---c', { c: completion });
timelineDataService.getTimeline.mockReturnValue(response);

expect(effects.getTimeline$).toSatisfyOnFlush(() => {
expect(timelineDataService.getTimeline).toHaveBeenCalled();
});
expect(effects.getTimeline$).toBeObservable(expected);
});

test('returns GetTimelineFail action on fail', () => {
const payload = {} as any;
const action = new fromTimelineActions.GetTimeline({} as any);
const completion = new fromTimelineActions.GetTimelineFail(payload);

actions = hot('-a', { a: action });
const response = cold('-#', {}, payload);
const expected = cold('--c', { c: completion });
timelineDataService.getTimeline.mockReturnValue(response);

expect(effects.getTimeline$).toSatisfyOnFlush(() => {
expect(timelineDataService.getTimeline).toHaveBeenCalled();
});
expect(effects.getTimeline$).toBeObservable(expected);
});
});
});
Loading

0 comments on commit b52ca1a

Please sign in to comment.