'use static';
/*
* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
import { ConfigService } from './module/config/configService';
import DataDriver from './module/config/DataDriver';
import { SuiteService } from './module/service/SuiteService';
import { SpecService } from './module/service/SpecService';
import { ExpectService, AssertMatcher } from './module/service/ExpectService';
import { ReportService } from './module/service/ReportService';
import { OhReport } from './module/report/OhReport';
import { ExpectExtend } from './module/assert/ExpectExtend';
import { SpecEvent, TaskEvent, SuiteEvent } from './module/service/event';
import { ApiIF } from './interface';
import { AnyType, HookFuncType, ItfnType } from './module/types/common';
/**
* core service for execute testcase.
*/
type ServiceType = SuiteService
| SpecService
| ConfigService
| ExpectService
| ReportService
| ExpectExtend
| OhReport
| DataDriver;
type EventType = SuiteEvent | SpecEvent | TaskEvent;
class Core {
public static instance: WorkerLocal<Core> | null = null;
public static getInstance(): Core {
if (!Core.instance) {
let core = new Core();
Core.instance = new WorkerLocal<Core>(() => core);
}
return Core.instance!.get() as Core;
}
public services: Map<string, Map<string, ServiceType>>;
public events: Map<string, Map<string, EventType>>;
public describe: (desc: string, func: () => void) => void;
public xdescribe: (desc: string, func: () => void, reason: string) => void;
public beforeItSpecified: (itDescs: string | string[], func: HookFuncType) => void;
public afterItSpecified: (itDescs: string | string[], func: HookFuncType) => void;
public beforeAll: (func: HookFuncType) => void;
public beforeEach: (func: HookFuncType) => void;
public beforeEachIt: (func: HookFuncType) => void;
public afterAll: (func: HookFuncType) => void;
public afterEach: (func: HookFuncType) => void;
public afterEachIt: (func: HookFuncType) => void;
public it: (desc: string, filter: int, func: ItfnType, timeout?: number, tag?: string) => void;
public xit: (desc: string, filter: int, func: ItfnType, reason: string) => void;
public expect: ((actualValue?: AnyType) => AssertMatcher) | null;
public specEvent: SpecEvent;
public suiteEvent: SuiteEvent;
public taskEvent: TaskEvent;
public sService: SuiteService | null;
public msgHandle: concurrency.MessageHandler |null = null;
constructor() {
this.services = new Map<string, Map<string, ServiceType>>();
this.events = new Map<string, Map<string, EventType>>();
this.describe = (desc: string, func: () => void): void => {};
this.xdescribe = (desc: string, func: () => void, reason: string) => {};
this.beforeItSpecified = (itDescs: string | string[], func: HookFuncType) => { };
this.afterItSpecified = (itDescs: string | string[], func: HookFuncType) => { };
this.beforeAll = (func: HookFuncType) => { };
this.beforeEach = (func: HookFuncType) => { };
this.beforeEachIt = (func: HookFuncType) => { };
this.afterAll = (func: HookFuncType) => { };
this.afterEach = (func: HookFuncType) => { };
this.afterEachIt = (func: HookFuncType) => { };
this.it = (desc: string, filter: int, func: ItfnType, timeout?: number, tag?: string) => { };
this.xit = (desc: string, filter: int, func: ItfnType, reason: string) => { };
this.expect = null;
this.specEvent = new SpecEvent({ id: '' });
this.suiteEvent = new SuiteEvent({ id: '' });
this.taskEvent = new TaskEvent({ id: '' });
this.sService = null;
}
addService(name: string, service: ServiceType): void {
let serviceMap = this.services.get(name);
if (!serviceMap) {
serviceMap = new Map<string, ServiceType>();
this.services.set(name, serviceMap);
}
serviceMap.set(service.id, service);
}
getDefaultService(name: string): ServiceType | null {
const serviceMap = this.services.get(name);
if (serviceMap) {
return (serviceMap as Map<string, ServiceType>).get('default') as ServiceType;
} else {
return null;
}
}
getServices(name: string): Map<string, ServiceType> | undefined {
return this.services.get(name);
}
registerEvent(serviceName: string, event: EventType): void {
let eventMap = this.events.get(serviceName);
if (!eventMap) {
eventMap = new Map<string, EventType>();
this.events.set(serviceName, eventMap);
}
eventMap.set(event.id, event);
}
unRegisterEvent(serviceName: string, eventID: string): void {
const eventObj = this.events.get(serviceName);
if (eventObj) {
eventObj.delete(eventID);
}
}
subscribeEvent(serviceName: string, serviceObj: ReportService): void {
const eventMap = this.events.get(serviceName);
if (eventMap) {
eventMap.forEach((value: EventType) => {
if (value instanceof SuiteEvent) {
(value as SuiteEvent).subscribeEvent(serviceObj);
} else if (value instanceof SpecEvent) {
(value as SpecEvent).subscribeEvent(serviceObj);
} else if (value instanceof TaskEvent) {
(value as TaskEvent).subscribeEvent(serviceObj);
}
});
}
}
subscribeEvent(serviceName: string, serviceObj: OhReport): void {
const eventMap = this.events.get(serviceName);
if (eventMap) {
eventMap.forEach((value: EventType) => {
if (value instanceof SuiteEvent) {
(value as SuiteEvent).subscribeEvent(serviceObj);
} else if (value instanceof SpecEvent) {
(value as SpecEvent).subscribeEvent(serviceObj);
} else if (value instanceof TaskEvent) {
(value as TaskEvent).subscribeEvent(serviceObj);
}
});
}
}
async fireEvents(serviceName: string, eventName: string): Promise<void> {
const eventMap = this.events.get(serviceName);
if (eventMap) {
for (const event of eventMap.values()) {
switch (eventName) {
case 'specStart':
this.specEvent = event as SpecEvent;
await this.specEvent.specStart();
break;
case 'specDone':
this.specEvent = event as SpecEvent;
await this.specEvent.specDone();
break;
case 'suiteStart':
this.suiteEvent = event as SuiteEvent;
await this.suiteEvent.suiteStart();
break;
case 'suiteDone':
this.suiteEvent = event as SuiteEvent;
await this.suiteEvent.suiteDone();
break;
case 'taskStart':
this.taskEvent = event as TaskEvent;
await this.taskEvent.taskStart();
break;
case 'taskDone':
this.taskEvent = event as TaskEvent;
await this.taskEvent.taskDone();
break;
case 'incorrectFormat':
(event as TaskEvent).incorrectFormat();
break;
case 'incorrectTestSuiteFormat':
(event as TaskEvent).incorrectTestSuiteFormat();
break;
}
}
}
}
addToGlobal(apis: ApiIF): void {
const describe = apis.describe;
if (describe) {
this.describe = describe;
}
const xdescribe = apis.xdescribe;
if (xdescribe) {
this.xdescribe = xdescribe;
}
const beforeItSpecified = apis.beforeItSpecified;
if (beforeItSpecified) {
this.beforeItSpecified = beforeItSpecified;
}
const afterItSpecified = apis.afterItSpecified;
if (afterItSpecified) {
this.afterItSpecified = afterItSpecified;
}
const beforeAll = apis.beforeAll;
if (beforeAll) {
this.beforeAll = beforeAll;
}
const beforeEach = apis.beforeEach;
if (beforeEach) {
this.beforeEach = beforeEach;
}
const beforeEachIt = apis.beforeEachIt;
if (beforeEachIt) {
this.beforeEachIt = beforeEachIt;
}
const afterAll = apis.afterAll;
if (afterAll) {
this.afterAll = afterAll;
}
const afterEach = apis.afterEach;
if (afterEach) {
this.afterEach = afterEach;
}
const afterEachIt = apis.afterEachIt;
if (afterEachIt) {
this.afterEachIt = afterEachIt;
}
const it = apis.it;
if (it) {
this.it = it;
}
const xit = apis.xit;
if (xit) {
this.xit = xit;
}
const expect = apis.expect;
if (expect) {
this.expect = expect as (actualValue?: AnyType) => AssertMatcher;
}
}
init(): void {
let suiteService = new SuiteService({ id: 'default' })
suiteService.msgHandle = this.msgHandle;
this.addService('suite', suiteService);
this.addService('spec', new SpecService({ id: 'default' }));
this.addService('expect', new ExpectService({ id: 'default' }));
this.addService('report', new ReportService({ id: 'default' }));
this.addService('config', new ConfigService({ id: 'default' }));
this.registerEvent('task', new TaskEvent({ id: 'default' }));
this.registerEvent('suite', new SuiteEvent({ id: 'default' }));
this.registerEvent('spec', new SpecEvent({ id: 'default' }));
const report = this.getDefaultService('report');
if (report !== null) {
this.subscribeEvent('spec', report as ReportService);
this.subscribeEvent('suite', report as ReportService);
this.subscribeEvent('task', report as ReportService);
}
const context = this;
for (const serviceMap of this.services.values()) {
for (const service of serviceMap.values()) {
let apis: ApiIF = { name: '' };
if (service instanceof SuiteService) {
const typeService = service as SuiteService;
typeService.init(context);
apis = typeService.apis();
} else if (service instanceof SpecService) {
const typeService = service as SpecService;
typeService.init(context);
apis = typeService.apis();
} else if (service instanceof ConfigService) {
const typeService = service as ConfigService;
typeService.init(context);
} else if (service instanceof ExpectService) {
const typeService = service as ExpectService;
typeService.init(context);
apis = typeService.apis();
} else if (service instanceof ReportService) {
const typeService = service as ReportService;
typeService.init(context);
} else if (service instanceof ExpectExtend) {
const typeService = service as ExpectExtend;
typeService.init(context);
apis = typeService.apis();
} else if (service instanceof OhReport) {
const typeService = service as OhReport;
typeService.init(context);
} else if (service instanceof DataDriver) {
const typeService = service as DataDriver;
typeService.init(context);
}
this.addToGlobal(apis);
}
}
}
async execute(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator): Promise<void> {
const suiteService = this.getDefaultService('suite');
const configService = this.getDefaultService('config');
if (suiteService !== null && configService !== null) {
this.sService = suiteService as SuiteService;
const cService = configService as ConfigService;
const service = this.sService;
if (service !== null) {
if (cService.dryRun === 'true') {
await service.dryRun(abilityDelegator);
} else {
setTimeout(() => {
if (service !== null) {
service.execute();
}
}, 0);
}
}
}
}
}
export { Core };