• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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