1/* 2 * Copyright (c) 2025 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; 17import { ConfigService } from './module/config/configService'; 18import DataDriver from './module/config/DataDriver'; 19import { SuiteService } from './module/service/SuiteService'; 20import { SpecService } from './module/service/SpecService'; 21import { ExpectService, AssertMatcher } from './module/service/ExpectService'; 22import { ReportService } from './module/service/ReportService'; 23import { OhReport } from './module/report/OhReport'; 24import { ExpectExtend } from './module/assert/ExpectExtend'; 25import { SpecEvent, TaskEvent, SuiteEvent } from './module/service/event'; 26import { ApiIF } from './interface'; 27import { AnyType, HookFuncType, ItfnType } from './module/types/common'; 28/** 29 * core service for execute testcase. 30 */ 31type ServiceType = SuiteService 32 | SpecService 33 | ConfigService 34 | ExpectService 35 | ReportService 36 | ExpectExtend 37 | OhReport 38 | DataDriver; 39type EventType = SuiteEvent | SpecEvent | TaskEvent; 40class Core { 41 public static instance: Core | null = null; 42 public static getInstance() { 43 if (!Core.instance) { 44 Core.instance = new Core(); 45 } 46 return Core.instance; 47 } 48 49 public services: Map<string, Map<string, ServiceType>>; 50 public events: Map<string, Map<string, EventType>>; 51 public describe: (desc: string, func: () => void) => Promise<undefined>; 52 public xdescribe: (desc: string, func: () => void, reason: string) => Promise<void>; 53 public beforeItSpecified: (itDescs: string | string[], func: HookFuncType) => void; 54 public afterItSpecified: (itDescs: string | string[], func: HookFuncType) => void; 55 public beforeAll: (func: HookFuncType) => void; 56 public beforeEach: (func: HookFuncType) => void; 57 public afterAll: (func: HookFuncType) => void; 58 public afterEach: (func: HookFuncType) => void; 59 public it: (desc: string, filter: int, func: ItfnType) => void; 60 public xit: (desc: string, filter: int, func: ItfnType, reason: string) => void; 61 public expect: ((actualValue?: AnyType) => AssertMatcher) | null; 62 public specEvent: SpecEvent; 63 public suiteEvent: SuiteEvent; 64 public taskEvent: TaskEvent; 65 public sService: SuiteService | null; 66 constructor() { 67 this.services = new Map<string, Map<string, ServiceType>>(); 68 this.events = new Map<string, Map<string, EventType>>(); 69 this.describe = (desc: string, func: () => void): Promise<undefined> => { 70 return Promise.resolve(undefined); 71 }; 72 this.xdescribe = (desc: string, func: () => void, reason: string) => { 73 return Promise.resolve(); 74 }; 75 this.beforeItSpecified = (itDescs: string | string[], func: HookFuncType) => { }; 76 this.afterItSpecified = (itDescs: string | string[], func: HookFuncType) => { }; 77 this.beforeAll = (func: HookFuncType) => { }; 78 this.beforeEach = (func: HookFuncType) => { }; 79 this.afterAll = (func: HookFuncType) => { }; 80 this.afterEach = (func: HookFuncType) => { }; 81 this.it = (desc: string, filter: int, func: ItfnType) => { }; 82 this.xit = (desc: string, filter: int, func: ItfnType, reason: string) => { }; 83 this.expect = null; 84 this.specEvent = new SpecEvent({ id: '' }); 85 this.suiteEvent = new SuiteEvent({ id: '' }); 86 this.taskEvent = new TaskEvent({ id: '' }); 87 this.sService = null; 88 } 89 90 addService(name: string, service: ServiceType) { 91 let serviceMap = this.services.get(name); 92 if (!serviceMap) { 93 serviceMap = new Map<string, ServiceType>(); 94 this.services.set(name, serviceMap); 95 } 96 serviceMap.set(service.id, service); 97 } 98 99 getDefaultService(name: string): ServiceType | null { 100 const serviceMap = this.services.get(name); 101 if (serviceMap) { 102 return (serviceMap as Map<string, ServiceType>).get('default') as ServiceType; 103 } else { 104 return null; 105 } 106 } 107 108 getServices(name: string) { 109 return this.services.get(name); 110 } 111 112 registerEvent(serviceName: string, event: EventType) { 113 let eventMap = this.events.get(serviceName); 114 if (!eventMap) { 115 eventMap = new Map<string, EventType>(); 116 this.events.set(serviceName, eventMap); 117 } 118 eventMap.set(event.id, event); 119 } 120 121 unRegisterEvent(serviceName: string, eventID: string) { 122 const eventObj = this.events.get(serviceName); 123 if (eventObj) { 124 eventObj.delete(eventID); 125 } 126 } 127 128 subscribeEvent(serviceName: string, serviceObj: ReportService) { 129 const eventMap = this.events.get(serviceName); 130 if (eventMap) { 131 eventMap.forEach((value: EventType) => { 132 if (value instanceof SuiteEvent) { 133 (value as SuiteEvent).subscribeEvent(serviceObj); 134 } else if (value instanceof SpecEvent) { 135 (value as SpecEvent).subscribeEvent(serviceObj); 136 } else if (value instanceof TaskEvent) { 137 (value as TaskEvent).subscribeEvent(serviceObj); 138 } 139 }); 140 } 141 } 142 143 subscribeEvent(serviceName: string, serviceObj: OhReport) { 144 const eventMap = this.events.get(serviceName); 145 if (eventMap) { 146 eventMap.forEach((value: EventType) => { 147 if (value instanceof SuiteEvent) { 148 (value as SuiteEvent).subscribeEvent(serviceObj); 149 } else if (value instanceof SpecEvent) { 150 (value as SpecEvent).subscribeEvent(serviceObj); 151 } else if (value instanceof TaskEvent) { 152 (value as TaskEvent).subscribeEvent(serviceObj); 153 } 154 }); 155 } 156 } 157 158 async fireEvents(serviceName: string, eventName: string) { 159 const eventMap = this.events.get(serviceName); 160 if (eventMap) { 161 for (const event of eventMap.values()) { 162 switch (eventName) { 163 case 'specStart': 164 this.specEvent = event as SpecEvent; 165 await this.specEvent.specStart(); 166 break; 167 case 'specDone': 168 this.specEvent = event as SpecEvent; 169 await this.specEvent.specDone(); 170 break; 171 case 'suiteStart': 172 this.suiteEvent = event as SuiteEvent; 173 await this.suiteEvent.suiteStart(); 174 break; 175 case 'suiteDone': 176 this.suiteEvent = event as SuiteEvent; 177 await this.suiteEvent.suiteDone(); 178 break; 179 case 'taskStart': 180 this.taskEvent = event as TaskEvent; 181 await this.taskEvent.taskStart(); 182 break; 183 case 'taskDone': 184 this.taskEvent = event as TaskEvent; 185 await this.taskEvent.taskDone(); 186 break; 187 case 'incorrectFormat': 188 (event as TaskEvent).incorrectFormat(); 189 break; 190 case 'incorrectTestSuiteFormat': 191 (event as TaskEvent).incorrectTestSuiteFormat(); 192 break; 193 } 194 } 195 } 196 } 197 198 addToGlobal(apis: ApiIF) { 199 const describe = apis.describe; 200 if (describe) { 201 this.describe = describe; 202 } 203 const xdescribe = apis.xdescribe; 204 if (xdescribe) { 205 this.xdescribe = xdescribe; 206 } 207 const beforeItSpecified = apis.beforeItSpecified; 208 if (beforeItSpecified) { 209 this.beforeItSpecified = beforeItSpecified; 210 } 211 const afterItSpecified = apis.afterItSpecified; 212 if (afterItSpecified) { 213 this.afterItSpecified = afterItSpecified; 214 } 215 const beforeAll = apis.beforeAll; 216 if (beforeAll) { 217 this.beforeAll = beforeAll; 218 } 219 const beforeEach = apis.beforeEach; 220 if (beforeEach) { 221 this.beforeEach = beforeEach; 222 } 223 const afterAll = apis.afterAll; 224 if (afterAll) { 225 this.afterAll = afterAll; 226 } 227 const afterEach = apis.afterEach; 228 if (afterEach) { 229 this.afterEach = afterEach; 230 } 231 const it = apis.it; 232 if (it) { 233 this.it = it; 234 } 235 const xit = apis.xit; 236 if (xit) { 237 this.xit = xit; 238 } 239 const expect = apis.expect; 240 if (expect) { 241 this.expect = expect as (actualValue?: AnyType) => AssertMatcher; 242 } 243 } 244 245 init() { 246 this.addService('suite', new SuiteService({ id: 'default' })); 247 this.addService('spec', new SpecService({ id: 'default' })); 248 this.addService('expect', new ExpectService({ id: 'default' })); 249 this.addService('report', new ReportService({ id: 'default' })); 250 this.addService('config', new ConfigService({ id: 'default' })); 251 this.registerEvent('task', new TaskEvent({ id: 'default', coreContext: this })); 252 this.registerEvent('suite', new SuiteEvent({ id: 'default', coreContext: this })); 253 this.registerEvent('spec', new SpecEvent({ id: 'default', coreContext: this })); 254 const report = this.getDefaultService('report'); 255 if (report !== null) { 256 this.subscribeEvent('spec', report as ReportService); 257 this.subscribeEvent('suite', report as ReportService); 258 this.subscribeEvent('task', report as ReportService); 259 } 260 261 const context = this; 262 for (const serviceMap of this.services.values()) { 263 for (const service of serviceMap.values()) { 264 let apis: ApiIF = {}; 265 if (service instanceof SuiteService) { 266 const typeService = service as SuiteService; 267 typeService.init(context); 268 apis = typeService.apis(); 269 } else if (service instanceof SpecService) { 270 const typeService = service as SpecService; 271 typeService.init(context); 272 apis = typeService.apis(); 273 } else if (service instanceof ConfigService) { 274 const typeService = service as ConfigService; 275 typeService.init(context); 276 } else if (service instanceof ExpectService) { 277 const typeService = service as ExpectService; 278 typeService.init(context); 279 apis = typeService.apis(); 280 } else if (service instanceof ReportService) { 281 const typeService = service as ReportService; 282 typeService.init(context); 283 } else if (service instanceof ExpectExtend) { 284 const typeService = service as ExpectExtend; 285 typeService.init(context); 286 apis = typeService.apis(); 287 } else if (service instanceof OhReport) { 288 const typeService = service as OhReport; 289 typeService.init(context); 290 } 291 this.addToGlobal(apis); 292 } 293 } 294 } 295 296 async execute(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator) { 297 const suiteService = this.getDefaultService('suite'); 298 const configService = this.getDefaultService('config'); 299 if (suiteService !== null && configService !== null) { 300 this.sService = suiteService as SuiteService; 301 const cService = configService as ConfigService; 302 const service = this.sService; 303 if (service !== null) { 304 if (cService.dryRun === 'true') { 305 await service.dryRun(abilityDelegator); 306 } else { 307 setTimeout(() => { 308 if (service !== null) { 309 service.execute(); 310 } 311 }, 0); 312 } 313 } 314 } 315 } 316} 317export { Core }; 318