Skip to content

Commit

Permalink
Merge pull request #2197 from IDEMSInternational/test/task-service
Browse files Browse the repository at this point in the history
Test: task service tests; minimal test infrastructure for other services
  • Loading branch information
chrismclarke authored Feb 7, 2024
2 parents 07d9ea4 + 742cbac commit 07e9102
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 75 deletions.
2 changes: 1 addition & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
"builder": "@angular-devkit/build-angular:karma",
"options": {
"karmaConfig": "karma.conf.js",
"polyfills": ["zone.js", "zone.js/testing"],
"polyfills": ["zone.js", "zone.js/testing", "src/test/polyfills.ts"],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": ["src/favicon.ico", "src/assets"],
Expand Down
8 changes: 8 additions & 0 deletions src/app/feature/campaign/campaign.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { CampaignService } from "./campaign.service";

export class MockCampaignService implements Partial<CampaignService> {
public async ready(timeoutValue?: number): Promise<boolean> {
return true;
}
// TODO - implement further methods
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@ export class TmplCarouselComponent extends TemplateBaseComponent implements OnIn
config: SwiperOptions = {};
swiper: Swiper;
initialSlide: number;
taskGroupsListName: string;

constructor(private taskService: TaskService) {
super();
}

async ngOnInit() {
await this.getParams();
await this.hackSetHighlightedTask();
// When using carousel within task group context, set initial slide based on highlighted task
if (this.taskGroupsListName) {
this.hackSetInitialSlide();
}
}

async getParams() {
Expand All @@ -39,6 +43,7 @@ export class TmplCarouselComponent extends TemplateBaseComponent implements OnIn
}
this.config.centeredSlides = getBooleanParamFromTemplateRow(this._row, "centred_slides", true);
this.initialSlide = getNumberParamFromTemplateRow(this._row, "initial_slide_index", 0);
this.taskGroupsListName = getStringParamFromTemplateRow(this._row, "task_group_data", null);
}

/** Event emitter called when swiper initialised */
Expand All @@ -47,17 +52,16 @@ export class TmplCarouselComponent extends TemplateBaseComponent implements OnIn
this.swiper.slideTo(this.initialSlide, 0, false);
}

/** When using carousel within task_group context set additional highlighted slide from task data */
private async hackSetHighlightedTask() {
const taskGroupsList = getStringParamFromTemplateRow(this._row, "task_group_data", null);
if (taskGroupsList) {
const highlightedTaskGroup = this.taskService.getHighlightedTaskGroup();
if (highlightedTaskGroup) {
this.initialSlide = await this.taskService.getHighlightedTaskGroupIndex(
highlightedTaskGroup,
taskGroupsList
);
}
/** Set initial slide based on highlighted task */
private async hackSetInitialSlide() {
const indexOfHighlightedTask = await this.taskService.getHighlightedTaskGroupIndex(
this.taskGroupsListName
);
// if highlightes task is not in list, default to 0 for initial slide
if (indexOfHighlightedTask === -1) {
this.initialSlide = 0;
} else {
this.initialSlide = indexOfHighlightedTask;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,6 @@ export class TemplateActionService extends SyncServiceBase {
return processor.processTemplateWithoutRender(templateToProcess);
case "google_auth":
return await this.authService.signInWithGoogle();
case "task_group_set_highlighted":
const { previousHighlightedTaskGroup, newHighlightedTaskGroup } =
this.taskService.setHighlightedTaskGroup(args[0]);
// HACK - reschedule campaign notifications when the highlighted task group has changed,
// in order to handle any that are conditional on the highlighted task group
if (previousHighlightedTaskGroup !== newHighlightedTaskGroup) {
this.campaignService.scheduleCampaignNotifications();
}
return;
case "emit":
const [emit_value, emit_data] = args;
const container: TemplateContainerComponent = this.container;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { TestBed } from "@angular/core/testing";
import { TemplateFieldService } from "./template-field.service";
import type { PromiseExtended } from "dexie";
import { booleanStringToBoolean } from "src/app/shared/utils";

/** Mock calls for field values from the template field service to return test data */
export class MockTemplateFieldService implements Partial<TemplateFieldService> {
mockFields: any;

// allow additional specs implementing service to provide their own fields
constructor(mockFields: any = {}) {
this.mockFields = mockFields;
}
public getField(key: string) {
return booleanStringToBoolean(this.mockFields[key]);
}
public setField(key: string, value: string) {
this.mockFields[key] = value;
return Promise.resolve("_") as PromiseExtended;
}
public async ready(timeoutValue?: number): Promise<boolean> {
return true;
}
}

describe("TemplateFieldService", () => {
let service: TemplateFieldService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
});
service = TestBed.inject(TemplateFieldService);
});

it("should be created", () => {
expect(service).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { TestBed } from "@angular/core/testing";
import { TemplateTranslateService } from "./template-translate.service";

/** Mock calls for field values from the template field service to return test data */
export class MockTemplateTranslateService implements Partial<TemplateTranslateService> {
public translateValue(value: string) {
return value;
}

public async ready(timeoutValue?: number): Promise<boolean> {
return true;
}
}

describe("TaskService", () => {
let service: TemplateTranslateService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(TemplateTranslateService);
});

it("should be created", () => {
expect(service).toBeTruthy();
});
});
16 changes: 16 additions & 0 deletions src/app/shared/services/app-config/app-config.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import { TestBed } from "@angular/core/testing";

import { AppConfigService } from "./app-config.service";
import { BehaviorSubject } from "rxjs/internal/BehaviorSubject";
import { IAppConfig } from "../../model";

/** Mock calls for field values from the template field service to return test data */
export class MockAppConfigService implements Partial<AppConfigService> {
appConfig$ = new BehaviorSubject<IAppConfig>(undefined as any);

// allow additional specs implementing service to provide their own partial appConfig
constructor(mockAppConfig: Partial<IAppConfig> = {}) {
this.appConfig$.next(mockAppConfig as any);
}

public ready(timeoutValue?: number) {
return true;
}
}

describe("AppConfigService", () => {
let service: AppConfigService;
Expand Down
8 changes: 8 additions & 0 deletions src/app/shared/services/data/app-data.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,21 @@ export class MockAppDataService implements Partial<AppDataService> {
constructor(mockData: Partial<IAppDataCache> = {}) {
this.appDataCache = { ...DATA_CACHE_CLEAN, ...mockData };
}

public ready() {
return true;
}

public async getSheet<T extends FlowTypes.FlowTypeWithData>(
flow_type: FlowTypes.FlowType,
flow_name: string
): Promise<T> {
await _wait(50);
return this.appDataCache[flow_type]?.[flow_name] as T;
}
public async getTranslationStrings(language_code: string) {
return {};
}
}

/** Use an extended service for testing to allow override of protected variables */
Expand Down
Loading

0 comments on commit 07e9102

Please sign in to comment.