private getAxes() {
        const axisOptions = this.getAxesOptions();
        return [
            {
                ...deepMerge(axisOptions[this.xAxisType], axisOptions[this.xAxisType].bottom),
                type: this.xAxisType,
                position: ChartAxisPosition.Bottom,
            },
            {
                ...deepMerge(axisOptions[this.yAxisType], axisOptions[this.yAxisType].left),
                type: this.yAxisType,
                position: ChartAxisPosition.Left,
            },
        ];
    }


() => import("@/views/login/index.vue")


() => import("@/views/404/index.vue")


() => import("@/views/dashboard/index.vue")


() => import("@/views/form/index.vue")


() => import("@/views/nested/menu2/index.vue")


() => import("@/views/nested/menu2/menu2-1/index.vue")


() => import("@/views/nested/menu2/menu2-2/index.vue")


() => import("@/views/setting/index.vue")


({ openDrawer, session, tab }) => (
  <Main
    className="fill no-select"


function abort(error: string) {
  console.error(error);
  process.exit(1);
}


// Replace machine-readable times with human-readable versions
// and simplify the route by removing zero-second steps.
function formatRoute(route: Route): any {
  const fix = (o: any) => {
    if ('departTimeSecs' in o) {
      o['departTime'] = utils.formatTime(o.departTimeSecs);
      delete o['departTimeSecs'];
    }
    if ('departureSecs' in o) {
      o['departureTime'] = utils.formatTime(o.departureSecs);
      delete o['departureSecs'];
    }
    if ('arriveTimeSecs' in o) {
      o['arriveTime'] = utils.formatTime(o.arriveTimeSecs);
      delete o['arriveTimeSecs'];
    }
    if ('travelTimeSecs' in o) {
      o['travelTimeSecs'] = Math.round(o['travelTimeSecs']);
    }
    if ('distanceKm' in o) {
      o['distanceKm'] = Math.round(o['distanceKm'] * 100) / 100;
    }
    if ('walkingDistanceKm' in o) {
      o['walkingDistanceKm'] = Math.round(o['walkingDistanceKm'] * 100) / 100;
    }
  };

  const out = _.clone(route);
  if (out) {
    fix(out);
    if (out.steps) {
      out.steps = out.steps.filter(step => step.travelTimeSecs > 0);
      for (const step of out.steps) {
        fix(step);
      }
    }
  }
  return out;
}


// Print a formatted Route object to stdout.
function outputRoute(route: Route, origin: any, destination: any, router: OnlineRouter) {
  const outputGeojson = FLAGS.get('geojson');

  if (route && route.arriveTimeSecs < Infinity) {
    if (outputGeojson) {
      console.log(JSON.stringify(router.routeToGeojson(formatRoute(route)), null, '  '));
    } else {
      console.log(JSON.stringify(formatRoute(route), null, '  '));
    }
  } else if (outputGeojson) {
    // Not exactly clear what we should output in this case, but at least {} is valid GeoJSON.
    console.log('{}');
  } else {
    console.log(JSON.stringify({
      origin,
      destination,
      error: 'No route found.',
    }, null, '  '));
  }
}


function handleOneToOne(router: OnlineRouter, args: string[]) {
  if (args.length !== 5) {
    abort('Usage: one-to-one lat1 lng1 departureTime lat2 lng2');
  }

  const originLat = utils.parseNumber(args[0]);
  const originLng = utils.parseNumber(args[1]);
  const departureSecs = utils.parseTime(args[2]);
  const destinationLat = utils.parseNumber(args[3]);
  const destinationLng = utils.parseNumber(args[4]);

  const origin = { id: 'origin', latitude: originLat, longitude: originLng };
  const destination = { id: 'destination', latitude: destinationLat, longitude: destinationLng };

  const route = router.oneToOne(origin, departureSecs, destination);
  outputRoute(route, origin, destination, router);
}


function handleStopToStop(router: OnlineRouter, args: string[]) {
  if (args.length !== 3) {
    abort('Usage: stop-to-stop originStopId departureTime destinationStopId');
  }

  const originStopId = args[0];
  const departureSecs = utils.parseTime(args[1]);
  const destinationStopId = args[2];
  const route = router.stopToStop(originStopId, departureSecs, destinationStopId);
  outputRoute(route, originStopId, destinationStopId, router);
}


function handleOneToMany(router: OnlineRouter, args: string[]) {
  if (args.length !== 4) {
    abort('Usage: one-to-many originLat originLng departureTime path/to/destination/locations.csv');
  }

  const originLat = utils.parseNumber(args[0]);
  const originLng = utils.parseNumber(args[1]);
  const departureSecs = utils.parseTime(args[2]);
  const destinationFile = args[3];

  return loadLocationsCSV(destinationFile).then(destinations => {
    const origin = { id: 'origin', latitude: originLat, longitude: originLng };
    const startTimeMs = new Date().getTime();
    const times = router.oneToMany(origin, departureSecs, destinations);
    const endTimeMs = new Date().getTime();
    console.warn(`Completed one-to-many query in ${endTimeMs - startTimeMs} ms.`);
    console.log(JSON.stringify(times, null, '  '));
  });
}


function handleAllPairs(router: OnlineRouter, args: string[]) {
  if (args.length !== 2) {
    abort('Usage: all-pairs path/to/locations.csv departureTime');
  }

  const locationsFile = args[0];
  const departureSecs = utils.parseTime(args[1]);

  return loadLocationsCSV(locationsFile).then(locations => {
    const times = router.manyToMany(locations, departureSecs, locations);

    // This outputs CSV to match the behavior of the old all-pairs script.
    console.log('origin,destination,seconds');  // header
    _.forEach(times, (originTimes, originId) => {
      _.forEach(originTimes, (time, destId) => {
        if (originId === destId) return;
        if (time === Infinity) return;
        console.log([originId, destId, Math.round(time)].join(','));
      });
    });
  });
}


function handleOneToOneLocation(router: OnlineRouter, args: string[]) {
  if (args.length !== 4) {
    abort('Usage: one-to-one-location locations.txt originId departureTime destinationId');
  }

  const locationsFile = args[0];
  const originId = args[1];
  const departureSecs = utils.parseTime(args[2]);
  const destId = args[3];

  return loadLocationsCSV(locationsFile).then(locations => {
    const origin = _.find(locations, { id: originId });
    const destination = _.find(locations, { id: destId });
    if (!origin) abort(`Unable to find origin ID ${originId}`);
    if (!destination) abort(`Unable to find destination ID ${destId}`);

    const route = router.oneToOne(origin, departureSecs, destination);
    outputRoute(route, origin, destination, router);
  });
}


function main() {
  FLAGS.parse(process.argv);
  const optionsJson = FLAGS.args[0];
  const subcommand = FLAGS.args[1];

  if (SUBCOMMANDS.indexOf(subcommand) === -1) {
    abort(`Invalid subcommand: ${subcommand}, expected one of ${SUBCOMMANDS}`);
  }
  const subArgs = FLAGS.args.slice(2);

  const options = JSON.parse(fs.readFileSync(optionsJson, 'utf8')) as Options;
  const startMs = new Date().getTime();
  OnlineRouter.fromOptions(options).then(router => {
    const loadMs = new Date().getTime();
    console.warn(`Loaded and indexed GTFS files in ${(loadMs - startMs) / 1000} s`);

    switch (subcommand) {
      case 'one-to-one':
        return handleOneToOne(router, subArgs);
      case 'one-to-one-location':
        return handleOneToOneLocation(router, subArgs);
      case 'one-to-many':
        return handleOneToMany(router, subArgs);
      case 'stop-to-stop':
        return handleStopToStop(router, subArgs);
      case 'all-pairs':
        return handleAllPairs(router, subArgs);
      default:
        throw new Error(`Invalid subcommand: ${subcommand}`);
    }
  }).catch(e => {
    console.error(e.stack);
    process.exit(1);
  });
}


(o: any) => {
    if ('departTimeSecs' in o) {
      o['departTime'] = utils.formatTime(o.departTimeSecs);
      delete o['departTimeSecs'];
    }
    if ('departureSecs' in o) {
      o['departureTime'] = utils.formatTime(o.departureSecs);
      delete o['departureSecs'];
    }
    if ('arriveTimeSecs' in o) {
      o['arriveTime'] = utils.formatTime(o.arriveTimeSecs);
      delete o['arriveTimeSecs'];
    }
    if ('travelTimeSecs' in o) {
      o['travelTimeSecs'] = Math.round(o['travelTimeSecs']);
    }
    if ('distanceKm' in o) {
      o['distanceKm'] = Math.round(o['distanceKm'] * 100) / 100;
    }
    if ('walkingDistanceKm' in o) {
      o['walkingDistanceKm'] = Math.round(o['walkingDistanceKm'] * 100) / 100;
    }
  }


step => step.travelTimeSecs > 0


destinations => {
    const origin = { id: 'origin', latitude: originLat, longitude: originLng };
    const startTimeMs = new Date().getTime();
    const times = router.oneToMany(origin, departureSecs, destinations);
    const endTimeMs = new Date().getTime();
    console.warn(`Completed one-to-many query in ${endTimeMs - startTimeMs} ms.`);
    console.log(JSON.stringify(times, null, '  '));
  }


locations => {
    const times = router.manyToMany(locations, departureSecs, locations);

    // This outputs CSV to match the behavior of the old all-pairs script.
    console.log('origin,destination,seconds');  // header
    _.forEach(times, (originTimes, originId) => {
      _.forEach(originTimes, (time, destId) => {
        if (originId === destId) return;
        if (time === Infinity) return;
        console.log([originId, destId, Math.round(time)].join(','));
      });
    });
  }


(originTimes, originId) => {
      _.forEach(originTimes, (time, destId) => {
        if (originId === destId) return;
        if (time === Infinity) return;
        console.log([originId, destId, Math.round(time)].join(','));
      });
    }


(time, destId) => {
        if (originId === destId) return;
        if (time === Infinity) return;
        console.log([originId, destId, Math.round(time)].join(','));
      }


locations => {
    const origin = _.find(locations, { id: originId });
    const destination = _.find(locations, { id: destId });
    if (!origin) abort(`Unable to find origin ID ${originId}`);
    if (!destination) abort(`Unable to find destination ID ${destId}`);

    const route = router.oneToOne(origin, departureSecs, destination);
    outputRoute(route, origin, destination, router);
  }


router => {
    const loadMs = new Date().getTime();
    console.warn(`Loaded and indexed GTFS files in ${(loadMs - startMs) / 1000} s`);

    switch (subcommand) {
      case 'one-to-one':
        return handleOneToOne(router, subArgs);
      case 'one-to-one-location':
        return handleOneToOneLocation(router, subArgs);
      case 'one-to-many':
        return handleOneToMany(router, subArgs);
      case 'stop-to-stop':
        return handleStopToStop(router, subArgs);
      case 'all-pairs':
        return handleAllPairs(router, subArgs);
      default:
        throw new Error(`Invalid subcommand: ${subcommand}`);
    }
  }


e => {
    console.error(e.stack);
    process.exit(1);
  }


() => {
  it('works correctly', async () => {
    await render(<Title>Text</Title>);

    const screenshot = await page.screenshot();
    expect(screenshot).toMatchImageSnapshot();
  });
}


async () => {
    await render(<Title>Text</Title>);

    const screenshot = await page.screenshot();
    expect(screenshot).toMatchImageSnapshot();
  }


j => j.getOriginalName() === routeParams.job_name!


(data: string) => {
      this.resources(JSON.parse(data));
    }


(elasticProfilesResponse) => {
      elasticProfilesResponse.do((successResponse) => {
        this.elasticAgentIds(successResponse.body.all()().map(p => p.id()) as string[]);
      });
    }


(successResponse) => {
        this.elasticAgentIds(successResponse.body.all()().map(p => p.id()) as string[]);
      }


p => p.id()


(jobTimeoutResponse) => {
      jobTimeoutResponse.do((successResponse) => {
        this.defaultJobTimeout(successResponse.body.defaultJobTimeout());
      });
    }


(successResponse) => {
        this.defaultJobTimeout(successResponse.body.defaultJobTimeout());
      }


(resolve) => {
      resolve(this.allResources());
    }


r => r.trim()


(r) => suggestion.value !== r


(resolve) => {
      resolve(this.allElasticAgentIds());
    }


export class JobSettingsTabContentWidget extends MithrilViewComponent<Attrs> {
  view(vnode: m.Vnode<Attrs, this>) {
    const entity = vnode.attrs.entity;

    const numberFieldForTimeout =

      <NumberField property={entity.jobTimeoutType() !== "number" ? Stream() : (entity.timeout as any)}
                   errorText={entity.errors().errorsForDisplay("timeout")}
                   readonly={entity.jobTimeoutType() !== "number"}/>

;

    const jobTimeoutInNumber: m.Child =

      Cancel after {numberFieldForTimeout} minutes of inactivity

;

    const numberFieldForRunInstance =

      <NumberField property={entity.runType() !== "number" ? Stream() : (entity.runInstanceCount as any)}
                   errorText={entity.errors().errorsForDisplay("runInstanceCount")}
                   readonly={entity.runType() !== "number"}/>

;

    const runInstanceInNumber: m.Child =

      Run {numberFieldForRunInstance} instances

;

    const timeout = vnode.attrs.defaultJobTimeout() === 0 ? "Never" : `${vnode.attrs.defaultJobTimeout()} minute(s)`;

    return

Basic Settings

      <TextField required={true}
                 errorText={entity.errors().errorsForDisplay("name")}
                 label="Job Name"
                 property={entity.name}/>
      <AutocompleteField label="Resources"
                         provider={vnode.attrs.resourcesSuggestions}
                         autoEvaluate={false}
                         errorText={entity.errors().errorsForDisplay("resources")}
                         replace={vnode.attrs.resourcesSuggestions.replace.bind(vnode.attrs.resourcesSuggestions)}
                         filter={vnode.attrs.resourcesSuggestions.filter.bind(vnode.attrs.resourcesSuggestions)}
                         onchange={vnode.attrs.resourcesSuggestions.update.bind(vnode.attrs.resourcesSuggestions)}
                         helpText="The agent resources that the current job requires to run. Specify multiple resources as a comma separated list"
                         readonly={!!entity.elasticProfileId()}
                         property={entity.resources}/>
      <AutocompleteField label="Elastic Agent Profile Id"
                         autoEvaluate={false}
                         errorText={entity.errors().errorsForDisplay("elasticProfileId")}
                         provider={vnode.attrs.elasticAgentsSuggestions}
                         readonly={!!entity.resources()}


export class JobSettingsTabContent extends TabContent<Job> {
  private readonly resources: Stream<string[]>       = Stream([] as string[]);
  private readonly elasticAgentIds: Stream<string[]> = Stream([] as string[]);
  private readonly defaultJobTimeout: Stream<number> = Stream();

  constructor() {
    super();
    this.fetchResources();
    this.fetchElasticAgents();
    this.fetchDefaultJobTimeout();
  }

  static tabName(): string {
    return "Job Settings";
  }

  protected renderer(entity: Job, templateConfig: TemplateConfig): m.Children {
    const resourcesSuggestionsProvider     = new ResourcesSuggestionsProvider(entity.resources, this.resources);
    const elasticAgentsSuggestionsProvider = new ElasticAgenrSuggestionsProvider(this.elasticAgentIds);

    return <JobSettingsTabContentWidget entity={entity}
                                        resourcesSuggestions={resourcesSuggestionsProvider}
                                        elasticAgentsSuggestions={elasticAgentsSuggestionsProvider}
                                        defaultJobTimeout={this.defaultJobTimeout}
                                        resources={this.resources}
                                        templateConfig={templateConfig}/>;
  }

  protected selectedEntity(pipelineConfig: PipelineConfig, routeParams: PipelineConfigRouteParams): Job {
    const jobs = pipelineConfig.stages().findByName(routeParams.stage_name!)!.jobs();
    return Array.from(jobs).find(j => j.getOriginalName() === routeParams.job_name!)!;
  }

  private fetchResources() {
    new ResourcesService().all((data: string) => {
      this.resources(JSON.parse(data));
    });
  }

  private fetchElasticAgents() {
    ElasticAgentProfilesCRUD.all().then((elasticProfilesResponse) => {
      elasticProfilesResponse.do((successResponse) => {
        this.elasticAgentIds(successResponse.body.all()().map(p => p.id()) as string[]);
      });
    });
  }

  private fetchDefaultJobTimeout() {
    JobTimeoutManagementCRUD.get().then((jobTimeoutResponse) => {
      jobTimeoutResponse.do((successResponse) => {
        this.defaultJobTimeout(successResponse.body.defaultJobTimeout());
      });
    });
  }
}


export class ResourcesSuggestionsProvider extends SuggestionProvider {
  private allResources: Stream<string[]>;
  private property: Stream<string>;

  constructor(property: Stream<string>, allResources: Stream<string[]>) {
    super();
    this.property     = property;
    this.allResources = allResources;
  }

  getData(): Promise<Awesomplete.Suggestion[]> {
    return new Promise<Awesomplete.Suggestion[]>((resolve) => {
      resolve(this.allResources());
    });
  }

  replace(suggestion: any) {
    let optionalComma = "";
    if (this.property().trim().length > 0) {
      optionalComma = this.property().trim()[this.property().trim().length - 1] === "," ? "" : ",";
    }

    this.property(this.property() + optionalComma + suggestion.value);
    m.redraw.sync();
  }

  filter(suggestion: any, input: string) {
    const definedResources = input.split(",").map(r => r.trim());
    return definedResources.every((r) => suggestion.value !== r);
  }
}


export class ElasticAgenrSuggestionsProvider extends SuggestionProvider {
  private allElasticAgentIds: Stream<string[]>;

  constructor(allElasticAgentIds: Stream<string[]>) {
    super();
    this.allElasticAgentIds = allElasticAgentIds;
  }

  getData(): Promise<Awesomplete.Suggestion[]> {
    return new Promise<Awesomplete.Suggestion[]>((resolve) => {
      resolve(this.allElasticAgentIds());
    });
  }
}


export interface Attrs {
  entity: Job;
  resources: Stream<string[]>;
  defaultJobTimeout: Stream<number>;
  templateConfig: TemplateConfig;
  resourcesSuggestions: ResourcesSuggestionsProvider;
  elasticAgentsSuggestions: ElasticAgenrSuggestionsProvider;
}


view(vnode: m.Vnode<Attrs, this>) {
    const entity = vnode.attrs.entity;

    const numberFieldForTimeout =

      <NumberField property={entity.jobTimeoutType() !== "number" ? Stream() : (entity.timeout as any)}
                   errorText={entity.errors().errorsForDisplay("timeout")}
                   readonly={entity.jobTimeoutType() !== "number"}/>

;

    const jobTimeoutInNumber: m.Child =

      Cancel after {numberFieldForTimeout} minutes of inactivity

;

    const numberFieldForRunInstance =

      <NumberField property={entity.runType() !== "number" ? Stream() : (entity.runInstanceCount as any)}
                   errorText={entity.errors().errorsForDisplay("runInstanceCount")}
                   readonly={entity.runType() !== "number"}/>

;

    const runInstanceInNumber: m.Child =

      Run {numberFieldForRunInstance} instances

;

    const timeout = vnode.attrs.defaultJobTimeout() === 0 ? "Never" : `${vnode.attrs.defaultJobTimeout()} minute(s)`;

    return

Basic Settings

      <TextField required={true}
                 errorText={entity.errors().errorsForDisplay("name")}
                 label="Job Name"
                 property={entity.name}/>
      <AutocompleteField label="Resources"
                         provider={vnode.attrs.resourcesSuggestions}
                         autoEvaluate={false}
                         errorText={entity.errors().errorsForDisplay("resources")}
                         replace={vnode.attrs.resourcesSuggestions.replace.bind(vnode.attrs.resourcesSuggestions)}
                         filter={vnode.attrs.resourcesSuggestions.filter.bind(vnode.attrs.resourcesSuggestions)}
                         onchange={vnode.attrs.resourcesSuggestions.update.bind(vnode.attrs.resourcesSuggestions)}
                         helpText="The agent resources that the current job requires to run. Specify multiple resources as a comma separated list"
                         readonly={!!entity.elasticProfileId()}


resources()


static tabName(): string {
    return "Job Settings";
  }


protected renderer(entity: Job, templateConfig: TemplateConfig): m.Children {
    const resourcesSuggestionsProvider     = new ResourcesSuggestionsProvider(entity.resources, this.resources);
    const elasticAgentsSuggestionsProvider = new ElasticAgenrSuggestionsProvider(this.elasticAgentIds);

    return <JobSettingsTabContentWidget entity={entity}
                                        resourcesSuggestions={resourcesSuggestionsProvider}
                                        elasticAgentsSuggestions={elasticAgentsSuggestionsProvider}
                                        defaultJobTimeout={this.defaultJobTimeout}
                                        resources={this.resources}
                                        templateConfig={templateConfig}/>;
  }


protected selectedEntity(pipelineConfig: PipelineConfig, routeParams: PipelineConfigRouteParams): Job {
    const jobs = pipelineConfig.stages().findByName(routeParams.stage_name!)!.jobs();
    return Array.from(jobs).find(j => j.getOriginalName() === routeParams.job_name!)!;
  }


private fetchResources() {
    new ResourcesService().all((data: string) => {
      this.resources(JSON.parse(data));
    });
  }


private fetchElasticAgents() {
    ElasticAgentProfilesCRUD.all().then((elasticProfilesResponse) => {
      elasticProfilesResponse.do((successResponse) => {
        this.elasticAgentIds(successResponse.body.all()().map(p => p.id()) as string[]);
      });
    });
  }


private fetchDefaultJobTimeout() {
    JobTimeoutManagementCRUD.get().then((jobTimeoutResponse) => {
      jobTimeoutResponse.do((successResponse) => {
        this.defaultJobTimeout(successResponse.body.defaultJobTimeout());
      });
    });
  }


getData(): Promise<Awesomplete.Suggestion[]> {
    return new Promise<Awesomplete.Suggestion[]>((resolve) => {
      resolve(this.allResources());
    });
  }


replace(suggestion: any) {
    let optionalComma = "";
    if (this.property().trim().length > 0) {
      optionalComma = this.property().trim()[this.property().trim().length - 1] === "," ? "" : ",";
    }

    this.property(this.property() + optionalComma + suggestion.value);
    m.redraw.sync();
  }


filter(suggestion: any, input: string) {
    const definedResources = input.split(",").map(r => r.trim());
    return definedResources.every((r) => suggestion.value !== r);
  }


getData(): Promise<Awesomplete.Suggestion[]> {
    return new Promise<Awesomplete.Suggestion[]>((resolve) => {
      resolve(this.allElasticAgentIds());
    });
  }


(basket, products, validationResults, basketInfo): BasketView => {
    if (!basket) {
      return;
    }

    return {
      ...basket,
      lineItems: basket.lineItems
        ? basket.lineItems.map(li => ({
            ...li,
            product: products[li.productSKU],
            name: products && products[li.productSKU] ? products[li.productSKU].name : undefined,
            inStock: products && products[li.productSKU] ? products[li.productSKU].inStock : undefined,
            availability: products && products[li.productSKU] ? products[li.productSKU].availability : undefined,
            validationError:
              validationResults && !validationResults.valid && validationResults.errors
                ? validationResults.errors.find(error => error.parameters && error.parameters.lineItemId === li.id)
                : undefined,
            info:
              basketInfo && basketInfo.length && basketInfo[0].causes
                ? basketInfo[0].causes.find(cause => cause.parameters && cause.parameters.lineItemId === li.id)
                : undefined,
          }))
        : [],
    };
  }


li => ({
            ...li,
            product: products[li.productSKU],
            name: products && products[li.productSKU] ? products[li.productSKU].name : undefined,
            inStock: products && products[li.productSKU] ? products[li.productSKU].inStock : undefined,
            availability: products && products[li.productSKU] ? products[li.productSKU].availability : undefined,
            validationError:
              validationResults && !validationResults.valid && validationResults.errors
                ? validationResults.errors.find(error => error.parameters && error.parameters.lineItemId === li.id)
                : undefined,
            info:
              basketInfo && basketInfo.length && basketInfo[0].causes
                ? basketInfo[0].causes.find(cause => cause.parameters && cause.parameters.lineItemId === li.id)
                : undefined,
          })


error => error.parameters && error.parameters.lineItemId === li.id


cause => cause.parameters && cause.parameters.lineItemId === li.id


// fire when basket line items or validation results changed
(
    basket: Basket,
    products: Dictionary<Product | VariationProduct | VariationProductMaster>,
    validationResults: BasketValidationResultType,
    basketInfo: BasketInfo[]
  ): string =>
    basket &&
    JSON.stringify([basket, validationResults, basketInfo, ...basket.lineItems.map(li => products[li.productSKU])])


li => products[li.productSKU]


interface AbstractBasket<T> {
  id: string;
  purchaseCurrency?: string;
  dynamicMessages?: string[];
  invoiceToAddress?: Address;
  commonShipToAddress?: Address;
  commonShippingMethod?: ShippingMethod;
  lineItems?: T[];
  payment?: Payment;
  promotionCodes?: string[];
  totals: BasketTotal;
  totalProductQuantity?: number;
  bucketId?: string;
  infos?: BasketInfo[];
}


export interface Basket extends AbstractBasket<LineItem> {}


export interface BasketView extends AbstractBasket<LineItemView> {}


(queryString = '') =>
  queryString
    .replace(/^\?/, '') // Remove leading question mark
    .replace(/\+/g, '%20') // Replace plus signs with URL-encoded spaces
    .split(/&/) // Split on delimiter '&'
    .map(query => query.split(/=/))
    .map(([key, value]) => ({ [key]: decodeURIComponent(value) })) // URL-decode value
    .reduce((a, b) => ({ ...a, ...b }), {})


query => query.split(/=/)


([key, value]) => ({ [key]: decodeURIComponent(value) })


(a, b) => ({ ...a, ...b })


(queryParams = {}) =>
  `?${
    // Add leading question mark
    Object.entries(queryParams)
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
      .filter(([key, value]) => value !== undefined && value !== null && value !== '') // Filter out empty/null/undef values
      .map(([key, value]) => [key, encodeURIComponent(value as string)]) // URL-encode value
      .map(([key, encodedValue]) => `${key}=${encodedValue}`)
      .join('&') // Join with delimiter '&'
      .replace('%20', '+') // Replace URL-encoded spaces with plus
  }`


([key, value]) => value !== undefined && value !== null && value !== ''


([key, value]) => [key, encodeURIComponent(value as string)]


([key, encodedValue]) => `${key}=${encodedValue}`


params => segment => {
  if (!paramSegmentPattern.test(segment)) {
    return segment;
  }
  const [paramName, paramPattern, optional] = paramSegmentPattern.exec(segment).slice(1, 4);
  const paramMatch = new RegExp(paramPattern || '(.+)').exec(params[paramName]);
  const paramValue = paramMatch ? paramMatch[1].replace(/^undefined$/, '') : '';
  return paramValue || (optional ? '' : segment);
}


segment => {
  if (!paramSegmentPattern.test(segment)) {
    return segment;
  }
  const [paramName, paramPattern, optional] = paramSegmentPattern.exec(segment).slice(1, 4);
  const paramMatch = new RegExp(paramPattern || '(.+)').exec(params[paramName]);
  const paramValue = paramMatch ? paramMatch[1].replace(/^undefined$/, '') : '';
  return paramValue || (optional ? '' : segment);
}


(path, params = {}) =>
  path
    .replace(/^\//, ' /') // Add whitespace before leading slash to keep it from being consumed by split
    .replace(/\/$/, '/ ') // Add whitespace after trailing slash to keep it from being consumed by split
    .split('/') // Split on delimiter '/'
    .map(resolveParam(params))
    .filter(segment => segment !== '')
    .join('/')
    .trim()


segment => segment !== ''


array => array.join(',')


formattedArray => formattedArray.split(',')


export enum Mode{ Open }


export default function PopoverPage() {
  return (
    <>
      <SEO title="Popover" keywords={['OAH', 'application', 'react']} />
      <Row>
        <Col breakPoint={{ xs: 12, md: 6 }}>
          <Card size="Tiny">
            <header>Popover Position</header>
            <CardBody id="popoverScroll">
              <Popover
                className="with-margin inline-block"
                trigger="hover"
                placement="left"
                overlay="Hello, how are you today?"
                eventListener="#popoverScroll"
              >
                <Button fullWidth>Left</Button>
              </Popover>
              <Popover
                className="with-margin inline-block"
                trigger="hover"
                placement="right"
                overlay="Hello, how are you today?"
                eventListener="#popoverScroll"
              >
                <Button fullWidth>Right</Button>
              </Popover>
              <Popover
                className="with-margin inline-block"
                trigger="hover"
                placement="top"
                overlay="Hello, how are you today?"
                eventListener="#popoverScroll"
              >
                <Button fullWidth>Top</Button>
              </Popover>
              <Popover
                className="with-margin inline-block"
                trigger="hover"
                placement="bottom"
                overlay="Hello, how are you today?"
                eventListener="#popoverScroll"
              >
                <Button fullWidth>Bottom</Button>
              </Popover>
            </CardBody>
          </Card>
        </Col>
        <Col breakPoint={{ xs: 12, md: 6 }}


class PackerError extends Error {
}


(predefinita: lingua di sistema)


() => {
    firebaseNamespace = new FirebaseNamespace();
  }


() => {
    it('should return the SDK version', () => {
      expect(firebaseNamespace.SDK_VERSION).to.equal('<XXX_SDK_VERSION_XXX>');
    });
  }


() => {
      expect(firebaseNamespace.SDK_VERSION).to.equal('<XXX_SDK_VERSION_XXX>');
    }


() => {
    it('should return an empty array if there are no apps within this namespace', () => {
      expect(firebaseNamespace.apps).to.deep.equal([]);
    });

    it('should return an array of apps within this namespace', () => {
      const appNames = ['one', 'two', 'three'];
      const apps = appNames.map((appName) => {
        return firebaseNamespace.initializeApp(mocks.appOptions, appName);
      });

      expect(firebaseNamespace.apps).to.have.length(apps.length);
      expect(firebaseNamespace.apps).to.deep.equal(apps);
    });

    it('should not include apps which have been deleted', () => {
      const appNames = ['one', 'two', 'three'];
      const apps = appNames.map((appName) => {
        return firebaseNamespace.initializeApp(mocks.appOptions, appName);
      });

      return apps[0].delete().then(() => {
        apps.shift();
        expect(firebaseNamespace.apps).to.have.length(apps.length);
        expect(firebaseNamespace.apps).to.deep.equal(apps);
      });
    });

    it('should be read-only', () => {
      expect(() => {
        (firebaseNamespace as any).apps = 'foo';
      }).to.throw(`Cannot set property apps of #<FirebaseNamespace> which has only a getter`);
    });
  }


() => {
      expect(firebaseNamespace.apps).to.deep.equal([]);
    }


() => {
      const appNames = ['one', 'two', 'three'];
      const apps = appNames.map((appName) => {
        return firebaseNamespace.initializeApp(mocks.appOptions, appName);
      });

      expect(firebaseNamespace.apps).to.have.length(apps.length);
      expect(firebaseNamespace.apps).to.deep.equal(apps);
    }


(appName) => {
        return firebaseNamespace.initializeApp(mocks.appOptions, appName);
      }


() => {
      const appNames = ['one', 'two', 'three'];
      const apps = appNames.map((appName) => {
        return firebaseNamespace.initializeApp(mocks.appOptions, appName);
      });

      return apps[0].delete().then(() => {
        apps.shift();
        expect(firebaseNamespace.apps).to.have.length(apps.length);
        expect(firebaseNamespace.apps).to.deep.equal(apps);
      });
    }


() => {
        apps.shift();
        expect(firebaseNamespace.apps).to.have.length(apps.length);
        expect(firebaseNamespace.apps).to.deep.equal(apps);
      }


() => {
      expect(() => {
        (firebaseNamespace as any).apps = 'foo';
      }).to.throw(`Cannot set property apps of #<FirebaseNamespace> which has only a getter`);
    }


() => {
        (firebaseNamespace as any).apps = 'foo';
      }


() => {
    const invalidAppNames = [null, NaN, 0, 1, true, false, [], ['a'], {}, { a: 1 }, _.noop];
    invalidAppNames.forEach((invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          return firebaseNamespace.app(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    });

    it('should throw given empty string app name', () => {
      expect(() => {
        return firebaseNamespace.app('');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    });

    it('should throw given an app name which does not correspond to an existing app', () => {
      expect(() => {
        return firebaseNamespace.app(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    });

    it('should throw given a deleted app', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      return app.delete().then(() => {
        expect(() => {
          return firebaseNamespace.app(mocks.appName);
        }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
      });
    });

    it('should throw given no app name if the default app does not exist', () => {
      expect(() => {
        return firebaseNamespace.app();
      }).to.throw('The default Firebase app does not exist.');
    });

    it('should return the app associated with the provided app name', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
    });

    it('should return the default app if no app name is provided', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(firebaseNamespace.app()).to.deep.equal(app);
    });

    it('should return the default app if the default app name is provided', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(firebaseNamespace.app(DEFAULT_APP_NAME)).to.deep.equal(app);
    });
  }


(invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          return firebaseNamespace.app(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    }


() => {
        expect(() => {
          return firebaseNamespace.app(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      }


() => {
          return firebaseNamespace.app(invalidAppName as any);
        }


() => {
      expect(() => {
        return firebaseNamespace.app('');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    }


() => {
        return firebaseNamespace.app('');
      }


() => {
      expect(() => {
        return firebaseNamespace.app(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    }


() => {
        return firebaseNamespace.app(mocks.appName);
      }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      return app.delete().then(() => {
        expect(() => {
          return firebaseNamespace.app(mocks.appName);
        }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
      });
    }


() => {
        expect(() => {
          return firebaseNamespace.app(mocks.appName);
        }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
      }


() => {
          return firebaseNamespace.app(mocks.appName);
        }


() => {
      expect(() => {
        return firebaseNamespace.app();
      }).to.throw('The default Firebase app does not exist.');
    }


() => {
        return firebaseNamespace.app();
      }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
    }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(firebaseNamespace.app()).to.deep.equal(app);
    }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(firebaseNamespace.app(DEFAULT_APP_NAME)).to.deep.equal(app);
    }


() => {
    const invalidAppNames = [null, NaN, 0, 1, true, false, [], ['a'], {}, { a: 1 }, _.noop];
    invalidAppNames.forEach((invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          firebaseNamespace.initializeApp(mocks.appOptions, invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    });

    it('should throw given empty string app name', () => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, '');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    });

    it('should throw given a name corresponding to an existing app', () => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" already exists.`);
    });

    it('should throw given no app name if the default app already exists', () => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }).to.throw('The default Firebase app already exists.');
    });

    it('should return a new app with the provided options and app name', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      expect(app.name).to.equal(mocks.appName);
      expect(app.options).to.deep.equal(mocks.appOptions);
    });

    it('should return an app with the default app name if no app name is provided', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(app.name).to.deep.equal(DEFAULT_APP_NAME);
    });

    it('should allow re-use of a deleted app name', () => {
      let app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      return app.delete().then(() => {
        app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
      });
    });

    it('should add the new app to the namespace\'s app list', () => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
    });

    it('should call the "create" app hook for the new app', () => {
      const appHook = sinon.spy();
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory, undefined, appHook);

      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);

      expect(appHook).to.have.been.calledOnce.and.calledWith('create', app);
    });
  }


(invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          firebaseNamespace.initializeApp(mocks.appOptions, invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    }


() => {
        expect(() => {
          firebaseNamespace.initializeApp(mocks.appOptions, invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      }


() => {
          firebaseNamespace.initializeApp(mocks.appOptions, invalidAppName as any);
        }


() => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, '');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions, '');
      }


() => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" already exists.`);
    }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      }


() => {
      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }).to.throw('The default Firebase app already exists.');

      expect(() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }).to.throw('The default Firebase app already exists.');
    }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions);
      }


() => {
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
        firebaseNamespace.initializeApp(mocks.appOptions, DEFAULT_APP_NAME);
      }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      expect(app.name).to.equal(mocks.appName);
      expect(app.options).to.deep.equal(mocks.appOptions);
    }


() => {
      const app = firebaseNamespace.initializeApp(mocks.appOptions);
      expect(app.name).to.deep.equal(DEFAULT_APP_NAME);
    }


() => {
      let app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      return app.delete().then(() => {
        app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
      });
    }


() => {
        app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
        expect(firebaseNamespace.app(mocks.appName)).to.deep.equal(app);
      }


() => {
      const appHook = sinon.spy();
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory, undefined, appHook);

      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);

      expect(appHook).to.have.been.calledOnce.and.calledWith('create', app);
    }


() => {
    const invalidAppNames = [null, NaN, 0, 1, true, false, [], ['a'], {}, { a: 1 }, _.noop];
    invalidAppNames.forEach((invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          firebaseNamespace.INTERNAL.removeApp(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    });

    it('should throw given empty string app name', () => {
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp('');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    });

    it('should throw given an app name which does not correspond to an existing app', () => {
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    });

    it('should throw given no app name if the default app does not exist', () => {
      expect(() => {
        (firebaseNamespace as any).INTERNAL.removeApp();
      }).to.throw(`No Firebase app name provided. App name must be a non-empty string.`);
    });

    it('should throw given no app name even if the default app exists', () => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      expect(() => {
        (firebaseNamespace as any).INTERNAL.removeApp();
      }).to.throw(`No Firebase app name provided. App name must be a non-empty string.`);
    });

    it('should remove the app corresponding to the provided app name from the namespace\'s app list', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      expect(() => {
        return firebaseNamespace.app(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    });

    it('should remove the default app from the namespace\'s app list if the default app name is provided', () => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      firebaseNamespace.INTERNAL.removeApp(DEFAULT_APP_NAME);
      expect(() => {
        return firebaseNamespace.app();
      }).to.throw('The default Firebase app does not exist.');
    });

    it('should not be idempotent', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    });

    it('should call the "delete" app hook for the deleted app', () => {
      const appHook = sinon.spy();
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory, undefined, appHook);

      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);

      appHook.resetHistory();

      firebaseNamespace.INTERNAL.removeApp(mocks.appName);

      expect(appHook).to.have.been.calledOnce.and.calledWith('delete', app);
    });
  }


(invalidAppName) => {
      it('should throw given non-string app name: ' + JSON.stringify(invalidAppName), () => {
        expect(() => {
          firebaseNamespace.INTERNAL.removeApp(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      });
    }


() => {
        expect(() => {
          firebaseNamespace.INTERNAL.removeApp(invalidAppName as any);
        }).to.throw(`Invalid Firebase app name "${invalidAppName}" provided. App name must be a non-empty string.`);
      }


() => {
          firebaseNamespace.INTERNAL.removeApp(invalidAppName as any);
        }


() => {
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp('');
      }).to.throw(`Invalid Firebase app name "" provided. App name must be a non-empty string.`);
    }


() => {
        firebaseNamespace.INTERNAL.removeApp('');
      }


() => {
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    }


() => {
        firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      }


() => {
      expect(() => {
        (firebaseNamespace as any).INTERNAL.removeApp();
      }).to.throw(`No Firebase app name provided. App name must be a non-empty string.`);
    }


() => {
        (firebaseNamespace as any).INTERNAL.removeApp();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      expect(() => {
        (firebaseNamespace as any).INTERNAL.removeApp();
      }).to.throw(`No Firebase app name provided. App name must be a non-empty string.`);
    }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      expect(() => {
        return firebaseNamespace.app(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      firebaseNamespace.INTERNAL.removeApp(DEFAULT_APP_NAME);
      expect(() => {
        return firebaseNamespace.app();
      }).to.throw('The default Firebase app does not exist.');
    }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);
      firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      expect(() => {
        firebaseNamespace.INTERNAL.removeApp(mocks.appName);
      }).to.throw(`Firebase app named "${mocks.appName}" does not exist.`);
    }


() => {
      const appHook = sinon.spy();
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory, undefined, appHook);

      const app = firebaseNamespace.initializeApp(mocks.appOptions, mocks.appName);

      appHook.resetHistory();

      firebaseNamespace.INTERNAL.removeApp(mocks.appName);

      expect(appHook).to.have.been.calledOnce.and.calledWith('delete', app);
    }


() => {
    // TODO(jwenger): finish writing tests for regsiterService() to get more code coverage

    it('should throw given no service name', () => {
      expect(() => {
        firebaseNamespace.INTERNAL.registerService(undefined as unknown as string, mocks.firebaseServiceFactory);
      }).to.throw(`No service name provided. Service name must be a non-empty string.`);
    });

    const invalidServiceNames = [null, NaN, 0, 1, true, false, [], ['a'], {}, { a: 1 }, _.noop];
    invalidServiceNames.forEach((invalidServiceName) => {
      it('should throw given non-string service name: ' + JSON.stringify(invalidServiceName), () => {
        expect(() => {
          firebaseNamespace.INTERNAL.registerService(invalidServiceName as any, mocks.firebaseServiceFactory);
        }).to.throw(`Invalid service name "${invalidServiceName}" provided. Service name must be a non-empty string.`);
      });
    });

    it('should throw given an empty string service name', () => {
      expect(() => {
        firebaseNamespace.INTERNAL.registerService('', mocks.firebaseServiceFactory);
      }).to.throw(`Invalid service name "" provided. Service name must be a non-empty string.`);
    });

    it('should throw given a service name which has already been registered', () => {
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      expect(() => {
        firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      }).to.throw(`Firebase service named "${mocks.serviceName}" has already been registered.`);
    });

    it('should throw given a service name which has already been registered', () => {
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      expect(() => {
        firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      }).to.throw(`Firebase service named "${mocks.serviceName}" has already been registered.`);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.INTERNAL.registerService(undefined as unknown as string, mocks.firebaseServiceFactory);
      }).to.throw(`No service name provided. Service name must be a non-empty string.`);
    }


() => {
        firebaseNamespace.INTERNAL.registerService(undefined as unknown as string, mocks.firebaseServiceFactory);
      }


(invalidServiceName) => {
      it('should throw given non-string service name: ' + JSON.stringify(invalidServiceName), () => {
        expect(() => {
          firebaseNamespace.INTERNAL.registerService(invalidServiceName as any, mocks.firebaseServiceFactory);
        }).to.throw(`Invalid service name "${invalidServiceName}" provided. Service name must be a non-empty string.`);
      });
    }


() => {
        expect(() => {
          firebaseNamespace.INTERNAL.registerService(invalidServiceName as any, mocks.firebaseServiceFactory);
        }).to.throw(`Invalid service name "${invalidServiceName}" provided. Service name must be a non-empty string.`);
      }


() => {
          firebaseNamespace.INTERNAL.registerService(invalidServiceName as any, mocks.firebaseServiceFactory);
        }


() => {
      expect(() => {
        firebaseNamespace.INTERNAL.registerService('', mocks.firebaseServiceFactory);
      }).to.throw(`Invalid service name "" provided. Service name must be a non-empty string.`);
    }


() => {
        firebaseNamespace.INTERNAL.registerService('', mocks.firebaseServiceFactory);
      }


() => {
      firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      expect(() => {
        firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      }).to.throw(`Firebase service named "${mocks.serviceName}" has already been registered.`);
    }


() => {
        firebaseNamespace.INTERNAL.registerService(mocks.serviceName, mocks.firebaseServiceFactory);
      }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.auth();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.auth();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const auth: Auth = firebaseNamespace.auth();
      expect(auth.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const auth: Auth = firebaseNamespace.auth(app);
      expect(auth.app).to.be.deep.equal(app);
    });

    it('should return a reference to Auth type', () => {
      expect(firebaseNamespace.auth.Auth).to.be.deep.equal(Auth);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.auth();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.auth();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.auth();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const auth: Auth = firebaseNamespace.auth();
      expect(auth.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const auth: Auth = firebaseNamespace.auth(app);
      expect(auth.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.auth.Auth).to.be.deep.equal(Auth);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.database();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.database();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const db: Database = firebaseNamespace.database();
      expect(db.app).to.be.deep.equal(app);
      return app.delete();
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const db: Database = firebaseNamespace.database(app);
      expect(db.app).to.be.deep.equal(app);
      return app.delete();
    });

    it('should return a reference to Database type', () => {
      expect(firebaseNamespace.database.Database).to.be.deep.equal(Database);
    });

    it('should return a reference to DataSnapshot type', () => {
      expect(firebaseNamespace.database.DataSnapshot).to.be.deep.equal(DataSnapshot);
    });

    it('should return a reference to OnDisconnect type', () => {
      expect(firebaseNamespace.database.OnDisconnect).to.be.deep.equal(OnDisconnect);
    });

    it('should return a reference to Query type', () => {
      expect(firebaseNamespace.database.Query).to.be.deep.equal(Query);
    });

    it('should return a reference to Reference type', () => {
      expect(firebaseNamespace.database.Reference).to.be.deep.equal(Reference);
    });

    it('should return a reference to ServerValue type', () => {
      expect(firebaseNamespace.database.ServerValue).to.be.deep.equal(ServerValue);
    });

    it('should return a reference to enableLogging function', () => {
      expect(firebaseNamespace.database.enableLogging).to.be.deep.equal(enableLogging);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.database();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.database();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.database();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const db: Database = firebaseNamespace.database();
      expect(db.app).to.be.deep.equal(app);
      return app.delete();
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const db: Database = firebaseNamespace.database(app);
      expect(db.app).to.be.deep.equal(app);
      return app.delete();
    }


() => {
      expect(firebaseNamespace.database.Database).to.be.deep.equal(Database);
    }


() => {
      expect(firebaseNamespace.database.DataSnapshot).to.be.deep.equal(DataSnapshot);
    }


() => {
      expect(firebaseNamespace.database.OnDisconnect).to.be.deep.equal(OnDisconnect);
    }


() => {
      expect(firebaseNamespace.database.Query).to.be.deep.equal(Query);
    }


() => {
      expect(firebaseNamespace.database.Reference).to.be.deep.equal(Reference);
    }


() => {
      expect(firebaseNamespace.database.ServerValue).to.be.deep.equal(ServerValue);
    }


() => {
      expect(firebaseNamespace.database.enableLogging).to.be.deep.equal(enableLogging);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.messaging();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.messaging();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const fcm: Messaging = firebaseNamespace.messaging();
      expect(fcm.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const fcm: Messaging = firebaseNamespace.messaging(app);
      expect(fcm.app).to.be.deep.equal(app);
    });

    it('should return a reference to Messaging type', () => {
      expect(firebaseNamespace.messaging.Messaging).to.be.deep.equal(Messaging);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.messaging();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.messaging();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.messaging();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const fcm: Messaging = firebaseNamespace.messaging();
      expect(fcm.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const fcm: Messaging = firebaseNamespace.messaging(app);
      expect(fcm.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.messaging.Messaging).to.be.deep.equal(Messaging);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.storage();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.storage();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const gcs: Storage = firebaseNamespace.storage();
      expect(gcs.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const gcs: Storage = firebaseNamespace.storage(app);
      expect(gcs.app).to.be.deep.equal(app);
    });

    it('should return a reference to Storage type', () => {
      expect(firebaseNamespace.storage.Storage).to.be.deep.equal(Storage);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.storage();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.storage();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.storage();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const gcs: Storage = firebaseNamespace.storage();
      expect(gcs.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const gcs: Storage = firebaseNamespace.storage(app);
      expect(gcs.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.storage.Storage).to.be.deep.equal(Storage);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.firestore();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.firestore();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      const fs: Firestore = firebaseNamespace.firestore();
      expect(fs).to.not.be.null;
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const fs: Firestore = firebaseNamespace.firestore(app);
      expect(fs).to.not.be.null;
    });

    it('should return a reference to Firestore type', () => {
      expect(firebaseNamespace.firestore.Firestore).to.be.deep.equal(Firestore);
    });

    it('should return a reference to FieldPath type', () => {
      expect(firebaseNamespace.firestore.FieldPath).to.be.deep.equal(FieldPath);
    });

    it('should return a reference to FieldValue type', () => {
      expect(firebaseNamespace.firestore.FieldValue).to.be.deep.equal(FieldValue);
    });

    it('should return a reference to GeoPoint type', () => {
      expect(firebaseNamespace.firestore.GeoPoint).to.be.deep.equal(GeoPoint);
    });

    it('should return a reference to setLogFunction', () => {
      expect(firebaseNamespace.firestore.setLogFunction).to.be.deep.equal(setLogFunction);
    });

    it('should return a reference to the v1beta1 namespace', () => {
      expect(firebaseNamespace.firestore.v1beta1).to.be.deep.equal(v1beta1);
    });

    it('should return a reference to the v1 namespace', () => {
      expect(firebaseNamespace.firestore.v1).to.be.deep.equal(v1);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.firestore();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.firestore();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.firestore();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions);
      const fs: Firestore = firebaseNamespace.firestore();
      expect(fs).to.not.be.null;
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const fs: Firestore = firebaseNamespace.firestore(app);
      expect(fs).to.not.be.null;
    }


() => {
      expect(firebaseNamespace.firestore.Firestore).to.be.deep.equal(Firestore);
    }


() => {
      expect(firebaseNamespace.firestore.FieldPath).to.be.deep.equal(FieldPath);
    }


() => {
      expect(firebaseNamespace.firestore.FieldValue).to.be.deep.equal(FieldValue);
    }


() => {
      expect(firebaseNamespace.firestore.GeoPoint).to.be.deep.equal(GeoPoint);
    }


() => {
      expect(firebaseNamespace.firestore.setLogFunction).to.be.deep.equal(setLogFunction);
    }


() => {
      expect(firebaseNamespace.firestore.v1beta1).to.be.deep.equal(v1beta1);
    }


() => {
      expect(firebaseNamespace.firestore.v1).to.be.deep.equal(v1);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.instanceId();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.instanceId();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const iid: InstanceId = firebaseNamespace.instanceId();
      expect(iid).to.not.be.null;
      expect(iid.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const iid: InstanceId = firebaseNamespace.instanceId(app);
      expect(iid).to.not.be.null;
      expect(iid.app).to.be.deep.equal(app);
    });

    it('should return a reference to InstanceId type', () => {
      expect(firebaseNamespace.instanceId.InstanceId).to.be.deep.equal(InstanceId);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.instanceId();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.instanceId();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.instanceId();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const iid: InstanceId = firebaseNamespace.instanceId();
      expect(iid).to.not.be.null;
      expect(iid.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const iid: InstanceId = firebaseNamespace.instanceId(app);
      expect(iid).to.not.be.null;
      expect(iid.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.instanceId.InstanceId).to.be.deep.equal(InstanceId);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.projectManagement();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.projectManagement();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const projectManagement: ProjectManagement = firebaseNamespace.projectManagement();
      expect(projectManagement).to.not.be.null;
      expect(projectManagement.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const projectManagement: ProjectManagement = firebaseNamespace.projectManagement(app);
      expect(projectManagement).to.not.be.null;
      expect(projectManagement.app).to.be.deep.equal(app);
    });

    it('should return a reference to ProjectManagement type', () => {
      expect(firebaseNamespace.projectManagement.ProjectManagement)
        .to.be.deep.equal(ProjectManagement);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.projectManagement();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.projectManagement();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.projectManagement();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const projectManagement: ProjectManagement = firebaseNamespace.projectManagement();
      expect(projectManagement).to.not.be.null;
      expect(projectManagement.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const projectManagement: ProjectManagement = firebaseNamespace.projectManagement(app);
      expect(projectManagement).to.not.be.null;
      expect(projectManagement.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.projectManagement.ProjectManagement)
        .to.be.deep.equal(ProjectManagement);
    }


() => {
    it('should throw when called before initializing an app', () => {
      expect(() => {
        firebaseNamespace.securityRules();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should throw when default app is not initialized', () => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.securityRules();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    });

    it('should return a valid namespace when the default app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const securityRules: SecurityRules = firebaseNamespace.securityRules();
      expect(securityRules).to.not.be.null;
      expect(securityRules.app).to.be.deep.equal(app);
    });

    it('should return a valid namespace when the named app is initialized', () => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const securityRules: SecurityRules = firebaseNamespace.securityRules(app);
      expect(securityRules).to.not.be.null;
      expect(securityRules.app).to.be.deep.equal(app);
    });

    it('should return a reference to SecurityRules type', () => {
      expect(firebaseNamespace.securityRules.SecurityRules)
        .to.be.deep.equal(SecurityRules);
    });
  }


() => {
      expect(() => {
        firebaseNamespace.securityRules();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
        firebaseNamespace.securityRules();
      }


() => {
      firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      expect(() => {
        firebaseNamespace.securityRules();
      }).to.throw(DEFAULT_APP_NOT_FOUND);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions);
      const securityRules: SecurityRules = firebaseNamespace.securityRules();
      expect(securityRules).to.not.be.null;
      expect(securityRules.app).to.be.deep.equal(app);
    }


() => {
      const app: FirebaseApp = firebaseNamespace.initializeApp(mocks.appOptions, 'testApp');
      const securityRules: SecurityRules = firebaseNamespace.securityRules(app);
      expect(securityRules).to.not.be.null;
      expect(securityRules.app).to.be.deep.equal(app);
    }


() => {
      expect(firebaseNamespace.securityRules.SecurityRules)
        .to.be.deep.equal(SecurityRules);
    }


export function extractJSBlock(binding: any): string | null {
  if (typeof binding == 'string') {
    if (
      binding.startsWith('{') &&
      binding.endsWith('}') &&
      !binding.startsWith('{"') &&
      !binding.endsWith('"}')
    ) {
      return binding.substring(1, binding.length - 2);
    } else if (binding.startsWith(IIF_START) && binding.endsWith(IIF_END)) {
      return binding.substring(
        IIF_START.length,
        binding.length - IIF_END.length - 1,
      );
    }
  }
  return null;
}


export function renderHandlers(
  file: File,
  componentName: string,
  children: MitosisNode[],
): Map<string, string> {
  let id = 0;
  const map = new Map<string, string>();
  const nodes = [...children];
  while (nodes.length) {
    const node = nodes.shift()!;
    const bindings = node.bindings;
    for (const key in bindings) {
      if (Object.prototype.hasOwnProperty.call(bindings, key)) {
        const binding = bindings[key]!;
        if (binding != null) {
          if (key.startsWith('on')) {
            let block = extractJSBlock(binding) || binding;
            const symbol = `${componentName}_${key}_${id++}`;
            map.set(binding, symbol);
            renderHandler(file, symbol, block);
          }
        }
      }
    }
    nodes.push(...node.children);
  }
  return map;
}


function renderHandler(file: File, symbol: string, code: string) {
  const body = [wrapWithUse(file, code)];
  const shouldRenderStateRestore = code.indexOf('state') !== -1;
  if (shouldRenderStateRestore) {
    body.unshift(renderUseLexicalScope(file));
  }
  file.exportConst(symbol, function (this: SrcBuilder) {
    this.emit([arrowFnBlock([], body)]);
  });
  file.src.emit(NL);
}


function wrapWithUse(
  file: File,
  code: string,
): string | ((this: SrcBuilder) => void) {
  const needsEvent = !!code.match(/\bevent\b/);
  if (needsEvent) {
    return function (this: SrcBuilder) {
      this.emit('{', NL, INDENT);
      needsEvent &&
        this.emit(
          'const event',
          WS,
          '=',
          WS,
          invoke(file.import(file.qwikModule, 'useEvent'), []),
          ';',
          NL,
        );
      const blockContent = stripBlock(code);
      this.emit(blockContent);
      this.emit(UNINDENT, NL, '}');
    };
  } else {
    return code;
  }
}


function stripBlock(block: string) {
  return block.substring(1, block.length - 1).trim();
}


/**
 * Provides a WAF Regex Pattern Set Resource
 *
 * ## Example Usage
 *
 * ```typescript
 * import * as pulumi from "@pulumi/pulumi";
 * import * as aws from "@pulumi/aws";
 *
 * const example = new aws.waf.RegexPatternSet("example", {
 *     regexPatternStrings: [
 *         "one",
 *         "two",
 *     ],
 * });
 * ```
 *
 * ## Import
 *
 * AWS WAF Regex Pattern Set can be imported using their ID, e.g.
 *
 * ```sh
 *  $ pulumi import aws:waf/regexPatternSet:RegexPatternSet example a1b2c3d4-d5f6-7777-8888-9999aaaabbbbcccc
 * ```
 */
export class RegexPatternSet extends pulumi.CustomResource {
    /**
     * Get an existing RegexPatternSet resource's state with the given name, ID, and optional extra
     * properties used to qualify the lookup.
     *
     * @param name The _unique_ name of the resulting resource.
     * @param id The _unique_ provider ID of the resource to lookup.
     * @param state Any extra arguments used during the lookup.
     * @param opts Optional settings to control the behavior of the CustomResource.
     */
    public static get(name: string, id: pulumi.Input<pulumi.ID>, state?: RegexPatternSetState, opts?: pulumi.CustomResourceOptions): RegexPatternSet {
        return new RegexPatternSet(name, <any>state, { ...opts, id: id });
    }

    /** @internal */
    public static readonly __pulumiType = 'aws:waf/regexPatternSet:RegexPatternSet';

    /**
     * Returns true if the given object is an instance of RegexPatternSet.  This is designed to work even
     * when multiple copies of the Pulumi SDK have been loaded into the same process.
     */
    public static isInstance(obj: any): obj is RegexPatternSet {
        if (obj === undefined || obj === null) {
            return false;
        }
        return obj['__pulumiType'] === RegexPatternSet.__pulumiType;
    }

    /**
     * Amazon Resource Name (ARN)
     */
    public /*out*/ readonly arn!: pulumi.Output<string>;
    /**
     * The name or description of the Regex Pattern Set.
     */
    public readonly name!: pulumi.Output<string>;
    /**
     * A list of regular expression (regex) patterns that you want AWS WAF to search for, such as `B[a@]dB[o0]t`.
     */
    public readonly regexPatternStrings!: pulumi.Output<string[] | undefined>;

    /**
     * Create a RegexPatternSet resource with the given unique name, arguments, and options.
     *
     * @param name The _unique_ name of the resource.
     * @param args The arguments to use to populate this resource's properties.
     * @param opts A bag of options that control this resource's behavior.
     */
    constructor(name: string, args?: RegexPatternSetArgs, opts?: pulumi.CustomResourceOptions)
    constructor(name: string, argsOrState?: RegexPatternSetArgs | RegexPatternSetState, opts?: pulumi.CustomResourceOptions) {
        let inputs: pulumi.Inputs = {};
        opts = opts || {};
        if (opts.id) {
            const state = argsOrState as RegexPatternSetState | undefined;
            inputs["arn"] = state ? state.arn : undefined;
            inputs["name"] = state ? state.name : undefined;
            inputs["regexPatternStrings"] = state ? state.regexPatternStrings : undefined;
        } else {
            const args = argsOrState as RegexPatternSetArgs | undefined;
            inputs["name"] = args ? args.name : undefined;
            inputs["regexPatternStrings"] = args ? args.regexPatternStrings : undefined;
            inputs["arn"] = undefined /*out*/;
        }
        if (!opts.version) {
            opts = pulumi.mergeOptions(opts, { version: utilities.getVersion()});
        }
        super(RegexPatternSet.__pulumiType, name, inputs, opts);
    }
}


/**
 * Input properties used for looking up and filtering RegexPatternSet resources.
 */
export interface RegexPatternSetState {
    /**
     * Amazon Resource Name (ARN)
     */
    arn?: pulumi.Input<string>;
    /**
     * The name or description of the Regex Pattern Set.
     */
    name?: pulumi.Input<string>;
    /**
     * A list of regular expression (regex) patterns that you want AWS WAF to search for, such as `B[a@]dB[o0]t`.
     */
    regexPatternStrings?: pulumi.Input<pulumi.Input<string>[]>;
}


/**
 * The set of arguments for constructing a RegexPatternSet resource.
 */
export interface RegexPatternSetArgs {
    /**
     * The name or description of the Regex Pattern Set.
     */
    name?: pulumi.Input<string>;
    /**
     * A list of regular expression (regex) patterns that you want AWS WAF to search for, such as `B[a@]dB[o0]t`.
     */
    regexPatternStrings?: pulumi.Input<pulumi.Input<string>[]>;
}


/**
     * Get an existing RegexPatternSet resource's state with the given name, ID, and optional extra
     * properties used to qualify the lookup.
     *
     * @param name The _unique_ name of the resulting resource.
     * @param id The _unique_ provider ID of the resource to lookup.
     * @param state Any extra arguments used during the lookup.
     * @param opts Optional settings to control the behavior of the CustomResource.
     */
public static get(name: string, id: pulumi.Input<pulumi.ID>, state?: RegexPatternSetState, opts?: pulumi.CustomResourceOptions): RegexPatternSet {
        return new RegexPatternSet(name, <any>state, { ...opts, id: id });
    }


/**
     * Returns true if the given object is an instance of RegexPatternSet.  This is designed to work even
     * when multiple copies of the Pulumi SDK have been loaded into the same process.
     */
public static isInstance(obj: any): obj is RegexPatternSet {
        if (obj === undefined || obj === null) {
            return false;
        }
        return obj['__pulumiType'] === RegexPatternSet.__pulumiType;
    }


@Injectable()
export class FeatureService {
  constructor(private readonly featureClientService: FeatureClientService) {}

  async find(): Promise<Record<string, string>> {
    const result = await this.featureClientService.getSomething();
    return result;
  }

  async one(): Promise<Record<string, string>> {
    const result = await this.featureClientService.getTokenUser();
    return result;
  }
}


async find(): Promise<Record<string, string>> {
    const result = await this.featureClientService.getSomething();
    return result;
  }


async one(): Promise<Record<string, string>> {
    const result = await this.featureClientService.getTokenUser();
    return result;
  }


@Option({
  name: 'help',
  alias: 'h',
})
export class Help {
  constructor(arg: OptionArgsProvider) {
    console.log(arg.value)
  }
}


function actValidationErrors(...expectedErrors: string[]) {
    expect(() => sut.validate(testInjector.options)).throws();
    for (const error of expectedErrors) {
      expect(testInjector.logger.error).calledWith(error);
    }
    expect(testInjector.logger.error).callCount(expectedErrors.length);
  }


function actAssertValid() {
    sut.validate(testInjector.options);
    expect(testInjector.logger.fatal).not.called;
    expect(testInjector.logger.error).not.called;
    expect(testInjector.logger.warn).not.called;
  }


function breakConfig(key: keyof StrykerOptions, value: any): void {
    const original = testInjector.options[key];
    if (typeof original === 'object' && !Array.isArray(original)) {
      testInjector.options[key] = { ...original, ...value };
    } else {
      testInjector.options[key] = value;
    }
  }


() => {
    sut = testInjector.injector.provideValue(coreTokens.validationSchema, strykerCoreSchema).injectClass(OptionsValidator);
  }


() => {
    sut.validate({});
    expect(testInjector.logger.fatal).not.called;
    expect(testInjector.logger.error).not.called;
    expect(testInjector.logger.warn).not.called;
  }


() => {
    actAssertValid();
  }


() => {
    it('should be invalid with thresholds < 0 or > 100', () => {
      testInjector.options.thresholds.high = -1;
      testInjector.options.thresholds.low = 101;
      actValidationErrors('Config option "thresholds.high" should be >= 0, was -1.', 'Config option "thresholds.low" should be <= 100, was 101.');
    });

    it('should be invalid with thresholds.high null', () => {
      (testInjector.options.thresholds.high as any) = null;
      actValidationErrors('Config option "thresholds.high" has the wrong type. It should be a number, but was a null.');
    });

    it('should not allow high < low', () => {
      testInjector.options.thresholds.high = 20;
      testInjector.options.thresholds.low = 21;
      actValidationErrors('Config option "thresholds.high" should be higher than "thresholds.low".');
    });
  }


() => {
      testInjector.options.thresholds.high = -1;
      testInjector.options.thresholds.low = 101;
      actValidationErrors('Config option "thresholds.high" should be >= 0, was -1.', 'Config option "thresholds.low" should be <= 100, was 101.');
    }


() => {
      (testInjector.options.thresholds.high as any) = null;
      actValidationErrors('Config option "thresholds.high" has the wrong type. It should be a number, but was a null.');
    }


() => {
      testInjector.options.thresholds.high = 20;
      testInjector.options.thresholds.low = 21;
      actValidationErrors('Config option "thresholds.high" should be higher than "thresholds.low".');
    }


() => {
    testInjector.options.logLevel = 'thisTestPasses' as any;
    actValidationErrors(
      'Config option "logLevel" should be one of the allowed values ("off", "fatal", "error", "warn", "info", "debug", "trace"), but was "thisTestPasses".'
    );
  }


() => {
    breakConfig('timeoutMS', 'break');
    actValidationErrors('Config option "timeoutMS" has the wrong type. It should be a number, but was a string.');
  }


() => {
    breakConfig('timeoutFactor', 'break');
    actValidationErrors('Config option "timeoutFactor" has the wrong type. It should be a number, but was a string.');
  }


() => {
    it('should be invalid with non-array plugins', () => {
      breakConfig('plugins', '@stryker-mutator/typescript');
      actValidationErrors('Config option "plugins" has the wrong type. It should be a array, but was a string.');
    });

    it('should be invalid with non-string array elements', () => {
      breakConfig('plugins', ['stryker-jest', 0]);
      actValidationErrors('Config option "plugins[1]" has the wrong type. It should be a string, but was a number.');
    });
  }


() => {
      breakConfig('plugins', '@stryker-mutator/typescript');
      actValidationErrors('Config option "plugins" has the wrong type. It should be a array, but was a string.');
    }


() => {
      breakConfig('plugins', ['stryker-jest', 0]);
      actValidationErrors('Config option "plugins[1]" has the wrong type. It should be a string, but was a number.');
    }


() => {
    it('should be invalid with non-array plugins', () => {
      breakConfig('appendPlugins', '@stryker-mutator/typescript');
      actValidationErrors('Config option "appendPlugins" has the wrong type. It should be a array, but was a string.');
    });

    it('should be invalid with non-string array elements', () => {
      breakConfig('appendPlugins', ['stryker-jest', 0]);
      actValidationErrors('Config option "appendPlugins[1]" has the wrong type. It should be a string, but was a number.');
    });
  }


() => {
      breakConfig('appendPlugins', '@stryker-mutator/typescript');
      actValidationErrors('Config option "appendPlugins" has the wrong type. It should be a array, but was a string.');
    }


() => {
      breakConfig('appendPlugins', ['stryker-jest', 0]);
      actValidationErrors('Config option "appendPlugins[1]" has the wrong type. It should be a string, but was a number.');
    }


() => {
    it('should be invalid with non-string mutator', () => {
      (testInjector.options.mutator as any) = 1;
      actValidationErrors('Config option "mutator" has the wrong type. It should be a object, but was a number.');
    });

    it('should report a deprecation warning for "mutator.name"', () => {
      (testInjector.options.mutator as any) = {
        name: 'javascript',
      };
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "mutator.name" is no longer needed. You can remove "mutator.name" from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
      );
    });

    it('should report a deprecation warning for mutator as a string', () => {
      (testInjector.options.mutator as any) = 'javascript';
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "mutator" as string is no longer needed. You can remove it from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
      );
    });
  }


() => {
      (testInjector.options.mutator as any) = 1;
      actValidationErrors('Config option "mutator" has the wrong type. It should be a object, but was a number.');
    }


() => {
      (testInjector.options.mutator as any) = {
        name: 'javascript',
      };
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "mutator.name" is no longer needed. You can remove "mutator.name" from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
      );
    }


() => {
      (testInjector.options.mutator as any) = 'javascript';
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "mutator" as string is no longer needed. You can remove it from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.'
      );
    }


() => {
    it('should report a deprecation warning', () => {
      (testInjector.options as any).testFramework = '';
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration.'
      );
    });
  }


() => {
      (testInjector.options as any).testFramework = '';
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration.'
      );
    }


() => {
    it('should be invalid with non-array reporters', () => {
      breakConfig('reporters', '@stryker-mutator/typescript');
      actValidationErrors('Config option "reporters" has the wrong type. It should be a array, but was a string.');
    });

    it('should be invalid with non-string array elements', () => {
      breakConfig('reporters', ['stryker-jest', 0]);
      actValidationErrors('Config option "reporters[1]" has the wrong type. It should be a string, but was a number.');
    });
  }


() => {
      breakConfig('reporters', '@stryker-mutator/typescript');
      actValidationErrors('Config option "reporters" has the wrong type. It should be a array, but was a string.');
    }


() => {
      breakConfig('reporters', ['stryker-jest', 0]);
      actValidationErrors('Config option "reporters[1]" has the wrong type. It should be a string, but was a number.');
    }


() => {
    it('should be invalid for non-string project', () => {
      breakConfig('dashboard', { project: 23 });
      actValidationErrors('Config option "dashboard.project" has the wrong type. It should be a string, but was a number.');
    });
    it('should be invalid for non-string module', () => {
      breakConfig('dashboard', { module: 23 });
      actValidationErrors('Config option "dashboard.module" has the wrong type. It should be a string, but was a number.');
    });
    it('should be invalid for non-string version', () => {
      breakConfig('dashboard', { version: 23 });
      actValidationErrors('Config option "dashboard.version" has the wrong type. It should be a string, but was a number.');
    });
    it('should be invalid for non-string baseUrl', () => {
      breakConfig('dashboard', { baseUrl: 23 });
      actValidationErrors('Config option "dashboard.baseUrl" has the wrong type. It should be a string, but was a number.');
    });
    it('should be invalid for a wrong reportType', () => {
      breakConfig('dashboard', { reportType: 'empty' });
      actValidationErrors('Config option "dashboard.reportType" should be one of the allowed values ("full", "mutationScore"), but was "empty".');
    });
  }


() => {
      breakConfig('dashboard', { project: 23 });
      actValidationErrors('Config option "dashboard.project" has the wrong type. It should be a string, but was a number.');
    }


() => {
      breakConfig('dashboard', { module: 23 });
      actValidationErrors('Config option "dashboard.module" has the wrong type. It should be a string, but was a number.');
    }


() => {
      breakConfig('dashboard', { version: 23 });
      actValidationErrors('Config option "dashboard.version" has the wrong type. It should be a string, but was a number.');
    }


() => {
      breakConfig('dashboard', { baseUrl: 23 });
      actValidationErrors('Config option "dashboard.baseUrl" has the wrong type. It should be a string, but was a number.');
    }


() => {
      breakConfig('dashboard', { reportType: 'empty' });
      actValidationErrors('Config option "dashboard.reportType" should be one of the allowed values ("full", "mutationScore"), but was "empty".');
    }


() => {
    it('should report a deprecation warning', () => {
      testInjector.options.maxConcurrentTestRunners = 8;
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith('DEPRECATED. Use of "maxConcurrentTestRunners" is deprecated. Please use "concurrency" instead.');
    });

    it('should not configure "concurrency" if "maxConcurrentTestRunners" is >= cpus-1', () => {
      testInjector.options.maxConcurrentTestRunners = 2;
      sinon.stub(os, 'cpus').returns([0, 1, 2]);
      sut.validate(testInjector.options);
      expect(testInjector.options.concurrency).undefined;
    });

    it('should configure "concurrency" if "maxConcurrentTestRunners" is set with a lower value', () => {
      testInjector.options.maxConcurrentTestRunners = 1;
      sinon.stub(os, 'cpus').returns([0, 1, 2]);
      sut.validate(testInjector.options);
      expect(testInjector.options.concurrency).eq(1);
    });
  }


() => {
      testInjector.options.maxConcurrentTestRunners = 8;
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith('DEPRECATED. Use of "maxConcurrentTestRunners" is deprecated. Please use "concurrency" instead.');
    }


() => {
      testInjector.options.maxConcurrentTestRunners = 2;
      sinon.stub(os, 'cpus').returns([0, 1, 2]);
      sut.validate(testInjector.options);
      expect(testInjector.options.concurrency).undefined;
    }


() => {
      testInjector.options.maxConcurrentTestRunners = 1;
      sinon.stub(os, 'cpus').returns([0, 1, 2]);
      sut.validate(testInjector.options);
      expect(testInjector.options.concurrency).eq(1);
    }


() => {
    breakConfig('maxTestRunnerReuse', 'break');
    actValidationErrors('Config option "maxTestRunnerReuse" has the wrong type. It should be a number, but was a string.');
  }


() => {
    it('should report a deprecation warning', () => {
      (testInjector.options.transpilers as any) = ['stryker-jest'];
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Support for "transpilers" is removed. You can now configure your own "buildCommand". For example, npm run build.'
      );
    });
  }


() => {
      (testInjector.options.transpilers as any) = ['stryker-jest'];
      sut.validate(testInjector.options);
      expect(testInjector.logger.warn).calledWith(
        'DEPRECATED. Support for "transpilers" is removed. You can now configure your own "buildCommand". For example, npm run build.'
      );
    }


() => {
    breakConfig('coverageAnalysis', 'invalid');
    actValidationErrors('Config option "coverageAnalysis" should be one of the allowed values ("off", "all", "perTest"), but was "invalid".');
  }


() => sut.validate(testInjector.options)


() => {
  let optionsValidatorMock: sinon.SinonStubbedInstance<OptionsValidator>;

  beforeEach(() => {
    optionsValidatorMock = sinon.createStubInstance(OptionsValidator);
  });

  it('should validate the options using given optionsValidator', () => {
    const options = { foo: 'bar' };
    const output = validateOptions(options, (optionsValidatorMock as unknown) as OptionsValidator);
    expect(options).deep.eq(output);
    expect(optionsValidatorMock.validate).calledWith(options);
  });
}


() => {
    optionsValidatorMock = sinon.createStubInstance(OptionsValidator);
  }


() => {
    const options = { foo: 'bar' };
    const output = validateOptions(options, (optionsValidatorMock as unknown) as OptionsValidator);
    expect(options).deep.eq(output);
    expect(optionsValidatorMock.validate).calledWith(options);
  }