Skip to content

Commit

Permalink
Merge pull request #1179 from aneoconsulting/fix/v0.12.x-linear-count…
Browse files Browse the repository at this point in the history
…-by-status-bug

fix: v0.12.x linear count by status bug
  • Loading branch information
ngruelaneo authored Jul 26, 2024
2 parents 127af78 + 2727dd4 commit 9e7d1c1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 76 deletions.
49 changes: 13 additions & 36 deletions src/app/components/count-tasks-by-status.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { TasksStatusesGroup } from '@app/dashboard/types';
import { TasksFiltersService } from '@app/tasks/services/tasks-filters.service';
import { TasksGrpcService } from '@app/tasks/services/tasks-grpc.service';
import { StatusCount, TaskSummaryFilters } from '@app/tasks/types';
import { CacheService } from '@services/cache.service';
import { CountTasksByStatusComponent } from './count-tasks-by-status.component';

describe('CountTasksByStatusComponent', () => {
Expand Down Expand Up @@ -44,42 +43,37 @@ describe('CountTasksByStatusComponent', () => {
const refresh$ = new Subject<void>();
const refreshSpy = jest.spyOn(refresh$, 'next');

const cachedData: StatusCount[] = [{ status: TaskStatus.TASK_STATUS_CREATING, count: 3 }];
const mockCacheService = {
getStatuses: jest.fn((): StatusCount[] | undefined => cachedData),
saveStatuses: jest.fn()
};

beforeEach(() => {
component = TestBed.configureTestingModule({
providers: [
CountTasksByStatusComponent,
{ provide: TasksGrpcService, useValue: mockTasksGrpcService },
TasksFiltersService,
{ provide: CacheService, useValue: mockCacheService }
TasksFiltersService
]
}).inject(CountTasksByStatusComponent);

component.refresh = refresh$;
component.filters = filters;
component.statusesGroups = statusesGroups;
component.ngOnInit();
});

it('Should run', () => {
expect(component).toBeTruthy();
});

describe('initCount', () => {
it('should set id', () => {
expect(component.id).toEqual(filters[0][0].value);
describe('initialisation', () => {
it('should subscribe to refresh', () => {
expect(refresh$.observed).toBeTruthy();
});

it('should load data', () => {
expect(mockCacheService.getStatuses).toHaveBeenCalled();
it('should set id', () => {
expect(component.id).toEqual(filters[0][0].value);
});

it('should not set id if there is no filter value', () => {
component.initCount([]);
component.filters = [];
component.initId();
expect(component.id).toEqual(undefined);
});
});
Expand All @@ -95,37 +89,20 @@ describe('CountTasksByStatusComponent', () => {
});

describe('setting filters', () => {
it('should subscribe to refresh', () => {
expect(refresh$.observed).toBeTruthy();
});

it('should refresh counts', () => {
expect(refreshSpy).toHaveBeenCalled();
it('should set filters', () => {
expect(component.filters).toEqual(filters);
});
});

describe('Refreshing', () => {
it('should update statusesCounts', () => {
component.refresh.next();
refresh$.next();
expect(component.statusesCount()).toEqual(finalStatusesCount);
});

it('should set null if there is no response status', () => {
mockTasksGrpcService.countByStatus$.mockReturnValue(of({ status: undefined }));
component.refresh.next();
expect(component.statusesCount()).toEqual([]);
});
});

describe('loadFromCache', () => {
it('should load cached data', () => {
component.loadFromCache();
expect(component.statusesCount()).toEqual(cachedData);
});

it('should load a null value if there is no cache', () => {
mockCacheService.getStatuses.mockReturnValueOnce(undefined);
component.loadFromCache();
refresh$.next();
expect(component.statusesCount()).toEqual([]);
});
});
Expand Down
73 changes: 34 additions & 39 deletions src/app/components/count-tasks-by-status.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Component, Input, WritableSignal, inject, signal } from '@angular/core';
import { Subject, Subscription, switchMap } from 'rxjs';
import { Component, Input, OnInit, WritableSignal, inject, signal } from '@angular/core';
import { Subject, switchMap } from 'rxjs';
import { TasksStatusesGroup } from '@app/dashboard/types';
import { TasksFiltersService } from '@app/tasks/services/tasks-filters.service';
import { TasksGrpcService } from '@app/tasks/services/tasks-grpc.service';
import { StatusCount, TaskSummaryFilters } from '@app/tasks/types';
import { ViewTasksByStatusComponent } from '@components/view-tasks-by-status.component';
import { CacheService } from '@services/cache.service';

@Component({
selector: 'app-count-tasks-by-status',
Expand All @@ -29,60 +28,56 @@ import { CacheService } from '@services/cache.service';
ViewTasksByStatusComponent,
]
})
export class CountTasksByStatusComponent {
export class CountTasksByStatusComponent implements OnInit {
private readonly tasksGrpcService = inject(TasksGrpcService);

id: string | undefined;
statusesCount: WritableSignal<StatusCount[]> = signal([]);
loading = true;

private _statusesGroups: TasksStatusesGroup[] = [];
private _filters: TaskSummaryFilters;
private _refresh$: Subject<void>;

@Input({ required: true }) queryParams: Record<string, string> = {};
@Input({ required: true }) refresh: Subject<void>;

@Input({ required: true }) set refresh(subject: Subject<void>) {
this._refresh$ = subject;
this.initRefresh();
}

@Input({ required: true }) set statusesGroups(entries: TasksStatusesGroup[]) {
this._statusesGroups = entries;
if (this.refresh) {
this.refresh.next();
}
this._refresh$.next();
}

id: string | undefined;
private _statusesGroups: TasksStatusesGroup[] = [];

get statusesGroups(): TasksStatusesGroup[] {
return this._statusesGroups;
}

statusesCount: WritableSignal<StatusCount[]> = signal([]);

loading = true;

#tasksGrpcService = inject(TasksGrpcService);
readonly cacheService = inject(CacheService);

subscription = new Subscription();
get filters(): TaskSummaryFilters {
return this._filters;
}

@Input({ required: true }) set filters(entries: TaskSummaryFilters) {
this.initCount(entries);
this.refresh.pipe(
switchMap(() => this.#tasksGrpcService.countByStatus$(entries)),
).subscribe(response => {
this.loading = false;
this.statusesCount.set(response.status ?? []);
this.saveData(response.status);
});
this.refresh.next();
this._filters = entries;
}

initCount(filters: TaskSummaryFilters) {
this.#setId(filters);
this.loadFromCache();
ngOnInit(): void {
this.initId();
}

loadFromCache() {
if (this.id) {
this.statusesCount.set(this.cacheService.getStatuses(this.id) ?? []);
}
initId() {
this.#setId(this.filters);
}

saveData(data: StatusCount[] | undefined) {
if (this.id && data) {
this.cacheService.saveStatuses(this.id, data);
}
initRefresh() {
this._refresh$.pipe(
switchMap(() => this.tasksGrpcService.countByStatus$(this.filters)),
).subscribe(response => {
this.loading = false;
this.statusesCount.set(response.status ?? []);
});
}

#setId(filter: TaskSummaryFilters) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/table/table-cell.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
@case ('count') {
<app-count-tasks-by-status
[refresh]="refreshStatuses"
[filters]="countFilters"
[statusesGroups]="statusesGroups"
[queryParams]="queryTasksParams"
[filters]="countFilters"
/>
}
@case ('select') {
Expand Down

1 comment on commit 9e7d1c1

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lines Statements Branches Functions
Coverage: 100%
99.92% (4203/4206) 100% (824/824) 99.73% (1137/1140)

JUnit

Tests Skipped Failures Errors Time
1570 0 💤 0 ❌ 0 🔥 1m 11s ⏱️
Files coverage (100%)
File% Stmts% Branch% Funcs% LinesUncovered Line #s
All files99.9210099.73100 
applications100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
applications/components100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
applications/services100100100100 
   applications-filters.service.ts100100100100 
   applications-grpc.service.ts100100100100 
   applications-index.service.ts100100100100 
components99.6310098.77100 
   actions-toolbar-group.component.ts100100100100 
   actions-toolbar.component.ts100100100100 
   auto-complete.component.html100100100100 
   auto-complete.component.ts100100100100 
   auto-refresh-button.component.html100100100100 
   auto-refresh-button.component.ts100100100100 
   auto-refresh-dialog.component.html100100100100 
   auto-refresh-dialog.component.ts100100100100 
   columns-button.component.ts100100100100 
   columns-modify-dialog.component.html100100100100 
   columns-modify-dialog.component.ts95.2310090.47100 
   count-tasks-by-status.component.ts100100100100 
   icon-picker-dialog.component.html100100100100 
   icon-picker-dialog.component.ts100100100100 
   manage-custom-dialog.component.html100100100100 
   manage-custom-dialog.component.ts100100100100 
   page-header.component.html100100100100 
   page-header.component.ts100100100100 
   page-section-header.component.ts100100100100 
   page-section.component.ts100100100100 
   refresh-button.component.ts100100100100 
   share-url.component.ts100100100100 
   show-action-area.component.html100100100100 
   show-action-area.component.ts100100100100 
   show-actions.component.html100100100100 
   show-actions.component.ts100100100100 
   show-card-content.component.html100100100100 
   show-card-content.component.ts100100100100 
   show-card.component.html100100100100 
   show-card.component.ts100100100100 
   show-page.component.html100100100100 
   show-page.component.ts100100100100 
   spinner.component.ts100100100100 
   table-actions-toolbar.component.html100100100100 
   table-actions-toolbar.component.ts100100100100 
   table-container.component.ts100100100100 
   table-dashboard-actions-toolbar.component.html100100100100 
   table-dashboard-actions-toolbar.component.ts100100100100 
   table-index-actions-toolbar.component.html100100100100 
   table-index-actions-toolbar.component.ts100100100100 
   view-tasks-by-status.component.ts100100100100 
components/filters100100100100 
   filters-chips.component.html100100100100 
   filters-chips.component.ts100100100100 
   filters-dialog-and.component.html100100100100 
   filters-dialog-and.component.ts100100100100 
   filters-dialog-filter-field.component.html100100100100 
   filters-dialog-filter-field.component.ts100100100100 
   filters-dialog-input.component.html100100100100 
   filters-dialog-input.component.ts100100100100 
   filters-dialog-or.component.html100100100100 
   filters-dialog-or.component.ts100100100100 
   filters-dialog.component.html100100100100 
   filters-dialog.component.ts100100100100 
   filters-toolbar.component.html100100100100 
   filters-toolbar.component.ts100100100100 
components/navigation100100100100 
   add-external-service-dialog.component.html100100100100 
   add-external-service-dialog.component.ts100100100100 
   change-language-button.component.html100100100100 
   change-language-button.component.ts100100100100 
   edit-external-service-dialog.component.html100100100100 
   edit-external-service-dialog.component.ts100100100100 
   form-external-service.component.html100100100100 
   form-external-service.component.ts100100100100 
   manage-external-services-dialog.component.html100100100100 
   manage-external-services-dialog.component.ts100100100100 
   navigation.component.html100100100100 
   navigation.component.ts100100100100 
   theme-selector.component.html100100100100 
   theme-selector.component.ts100100100100 
components/statuses100100100100 
   add-statuses-group-dialog.component.ts100100100100 
   edit-status-group-dialog.component.ts100100100100 
   form-statuses-group.component.html100100100100 
   form-statuses-group.component.ts100100100100 
   manage-groups-dialog.component.html100100100100 
   manage-groups-dialog.component.ts100100100100 
components/table100100100100 
   table-actions.component.html100100100100 
   table-actions.component.ts100100100100 
   table-cell.component.html100100100100 
   table-cell.component.ts100100100100 
   table-column-header.component.html100100100100 
   table-column-header.component.ts100100100100 
   table-empty-data.component.ts100100100100 
   table-inspect-object-dialog.component.html100100100100 
   table-inspect-object-dialog.component.ts100100100100 
   table-inspect-object.component.html100100100100 
   table-inspect-object.component.ts100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
dashboard100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
dashboard/components100100100100 
   add-line-dialog.component.html100100100100 
   add-line-dialog.component.ts100100100100 
   edit-name-line-dialog.component.html100100100100 
   edit-name-line-dialog.component.ts100100100100 
   reorganize-lines-dialog.component.html100100100100 
   reorganize-lines-dialog.component.ts100100100100 
   split-lines-dialog.component.ts100100100100 
   statuses-group-card.component.html100100100100 
   statuses-group-card.component.ts100100100100 
dashboard/components/lines100100100100 
   applications-line.component.html100100100100 
   applications-line.component.ts100100100100 
   partitions-line.component.html100100100100 
   partitions-line.component.ts100100100100 
   results-line.component.html100100100100 
   results-line.component.ts100100100100 
   sessions-line.component.html100100100100 
   sessions-line.component.ts100100100100 
   task-by-status-line.component.html100100100100 
   task-by-status-line.component.ts100100100100 
   tasks-line.component.html100100100100 
   tasks-line.component.ts100100100100 
dashboard/services100100100100 
   dashboard-index.service.ts100100100100 
   dashboard-storage.service.ts100100100100 
healthcheck100100100100 
   healthcheck.component.html100100100100 
   healthcheck.component.ts100100100100 
healthcheck/services100100100100 
   healthcheck-grpc.service.ts100100100100 
partitions100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
   show.component.ts100100100100 
partitions/components100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
partitions/services100100100100 
   partitions-filters.service.ts100100100100 
   partitions-grpc.service.ts100100100100 
   partitions-index.service.ts100100100100 
pipes100100100100 
   duration.pipe.ts100100100100 
   empty-cell.pipe.ts100100100100 
profile100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
   types.ts100100100100 
results100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
   show.component.ts100100100100 
results/components100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
results/services100100100100 
   results-filters.service.ts100100100100 
   results-grpc.service.ts100100100100 
   results-index.service.ts100100100100 
   results-statuses.service.ts100100100100 
services100100100100 
   auto-refresh.service.ts100100100100 
   cache.service.ts100100100100 
   default-config.service.ts100100100100 
   environment.service.ts100100100100 
   filters.service.ts100100100100 
   grpc-build-request.service.ts100100100100 
   grpc-sort-field.service.ts100100100100 
   icons.service.ts100100100100 
   navigation.service.ts100100100100 
   notification.service.ts100100100100 
   query-params.service.ts100100100100 
   share-url.service.ts100100100100 
   storage.service.ts100100100100 
   table-storage.service.ts100100100100 
   table-url.service.ts100100100100 
   table.service.ts100100100100 
   tasks-by-status.service.ts100100100100 
   user-grpc.service.ts100100100100 
   user.service.ts100100100100 
   utils.service.ts100100100100 
   versions-grpc.service.ts100100100100 
   versions.service.ts100100100100 
sessions100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
   show.component.ts100100100100 
sessions/components100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
sessions/services100100100100 
   sessions-filters.service.ts100100100100 
   sessions-grpc.service.ts100100100100 
   sessions-index.service.ts100100100100 
   sessions-statuses.service.ts100100100100 
tasks100100100100 
   index.component.html100100100100 
   index.component.ts100100100100 
   show.component.ts100100100100 
tasks/components100100100100 
   manage-view-in-logs-dialog.component.html100100100100 
   manage-view-in-logs-dialog.component.ts100100100100 
   table.component.html100100100100 
   table.component.ts100100100100 
tasks/services100100100100 
   tasks-filters.service.ts100100100100 
   tasks-grpc.service.ts100100100100 
   tasks-index.service.ts100100100100 
   tasks-statuses.service.ts100100100100 
tokens100100100100 
   filters.token.ts100100100100 
types100100100100 
   navigation.ts100100100100 
types/components99.710099.11100 
   dashboard-line-table.ts100100100100 
   index.ts99.1310097.22100 
   show.ts100100100100 
   table.ts100100100100 
types/services100100100100 
   grpcService.ts100100100100 

Please sign in to comment.