# HG changeset patch # User cin # Date 2020-09-08 05:56:27 # Node ID 03e32ec7c20bff5e5d5643bd23827167f906dda5 # Parent 511bcc634d65b968f9dd5cea795eda10ab61821f Completely removed IoC annotations Fluent configuration - staging diff --git a/src/main/ts/di/ActivationContext.ts b/src/main/ts/di/ActivationContext.ts --- a/src/main/ts/di/ActivationContext.ts +++ b/src/main/ts/di/ActivationContext.ts @@ -15,6 +15,10 @@ export interface ActivationContextInfo { let nextId = 1; +/** This class is created once per `Container.resolve` method call and used to + * cache dependencies and to track created instances. The activation context + * tracks services with `context` activation type. + */ export class ActivationContext { _cache: MapOf; @@ -30,6 +34,14 @@ export class ActivationContext | undefined; + /** Creates a new activation context with the specified parameters. + * @param container the container which starts the activation process + * @param services the initial service registrations + * @param name the name of the service being activated, this parameter is + * used for the debug purpose. + * @param service the service to activate, this parameter is used for the + * debug purpose. + */ constructor(container: Container, services: ContainerServiceMap, name: string, service: Descriptor) { this._name = name; this._service = service; @@ -39,16 +51,33 @@ export class ActivationContext>(name: K): TypeOfService; + /** Resolves the specified dependency with the specified default value if + * the dependency is missing. + * + * @param name The name of the dependency being resolved + * @param def A default value to return in case of the specified dependency + * is missing. + */ resolve, T>(name: K, def: T): TypeOfService | T; + /** Resolves the specified dependency and returns undefined in case if the + * dependency is missing. + * + * @param name The name of the dependency being resolved + */ resolve>(name: K, def: undefined): TypeOfService | undefined; resolve, T>(name: K, def?: T): TypeOfService | T | undefined { const d = this._services[name]; @@ -92,6 +121,7 @@ export class ActivationContext(d: Descriptor, name: string) { if (trace.isLogEnabled()) trace.log(`enter ${name} ${d}`); diff --git a/src/main/ts/di/Annotations.ts b/src/main/ts/di/Annotations.ts deleted file mode 100644 --- a/src/main/ts/di/Annotations.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { TypeRegistration } from "./Configuration"; -import { ExtractDependency } from "./fluent/interfaces"; - -export class AnnotationBuilder { - wire

(...args: P) { - return ) => T>(constructor: C) => { - - }; - } - - inject

(...args: P) { - return any }, M extends keyof (T | X)>( - target: X, - memberName: M, - descriptor: TypedPropertyDescriptor< T[M] extends ((...args: ExtractDependency) => any) ? any : never > - ) => { - - }; - } - - getDescriptor(): TypeRegistration T, S> { - throw new Error(); - } - -} diff --git a/src/main/ts/di/Container.ts b/src/main/ts/di/Container.ts --- a/src/main/ts/di/Container.ts +++ b/src/main/ts/di/Container.ts @@ -1,7 +1,7 @@ import { ActivationContext } from "./ActivationContext"; import { ValueDescriptor } from "./ValueDescriptor"; import { ActivationError } from "./ActivationError"; -import { ServiceMap, Descriptor, PartialServiceMap, ContainerProvided, ServiceLocator, ContainerServiceMap, ContainerKeys, TypeOfService, ILifetimeManager } from "./interfaces"; +import { ServiceMap, Descriptor, PartialServiceMap, ServiceLocator, ContainerServiceMap, ContainerKeys, TypeOfService } from "./interfaces"; import { TraceSource } from "../log/TraceSource"; import { Configuration, RegistrationMap } from "./Configuration"; import { Cancellation } from "../Cancellation"; @@ -9,13 +9,15 @@ import { MapOf, IDestroyable } from "../ import { isDescriptor } from "./traits"; import { LifetimeManager } from "./LifetimeManager"; import { each } from "../safe"; +import { FluentRegistrations } from "./fluent/interfaces"; +import { FluentConfiguration } from "./fluent/FluentConfiguration"; const trace = TraceSource.get("@implab/core/di/ActivationContext"); export class Container implements ServiceLocator, IDestroyable { readonly _services: ContainerServiceMap; - readonly _lifetimeManager: ILifetimeManager; + readonly _lifetimeManager: LifetimeManager; readonly _cleanup: (() => void)[]; @@ -126,6 +128,11 @@ export class Container(config: FluentRegistrations, ct = Cancellation.none): Promise { + await new FluentConfiguration().register(config).apply(this, ct); + return this; + } + createChildContainer(): Container { return new Container(this as any); } diff --git a/src/main/ts/di/LifetimeManager.ts b/src/main/ts/di/LifetimeManager.ts --- a/src/main/ts/di/LifetimeManager.ts +++ b/src/main/ts/di/LifetimeManager.ts @@ -1,6 +1,6 @@ import { IDestroyable, MapOf } from "../interfaces"; -import { argumentNotNull, isDestroyable } from "../safe"; -import { ILifetimeManager, ILifetime } from "./interfaces"; +import { argumentNotNull, isDestroyable, primitive, isNull, argumentNotEmptyString } from "../safe"; +import { ILifetime } from "./interfaces"; import { ActivationContext } from "./ActivationContext"; import { Container } from "./Container"; @@ -12,7 +12,7 @@ function safeCall(item: () => void) { } } -const emptyLifetime: ILifetime = { +const emptyLifetime: ILifetime = Object.freeze({ has() { return false; }, @@ -29,11 +29,11 @@ const emptyLifetime: ILifetime = { // does nothing } -}; +}); -const unknownLifetime: ILifetime = { +const unknownLifetime: ILifetime = Object.freeze({ has() { - throw new Error("The lifetime is unknown"); + return false; }, initialize() { throw new Error("Can't call initialize on the unknown lifetime object"); @@ -44,11 +44,13 @@ const unknownLifetime: ILifetime = { store() { throw new Error("Can't store a value in the unknown lifetime object"); } -} +}); let nextId = 0; -export class LifetimeManager implements IDestroyable, ILifetimeManager { +const singletons: { [k in keyof any]: any; } = {}; + +export class LifetimeManager implements IDestroyable { private _cleanup: (() => void)[] = []; private _cache: MapOf = {}; private _destroyed = false; @@ -116,7 +118,7 @@ export class LifetimeManager implements if (_lifetime !== unknownLifetime) throw new Error("Cyclic reference activation detected"); - _lifetime = context.getContainer().getLifetimeManager().create(context); + _lifetime = context.getContainer().getLifetimeManager().create(); }, get() { return _lifetime.get(); @@ -151,7 +153,27 @@ export class LifetimeManager implements } static singletonLifetime(typeId: string): ILifetime { - return emptyLifetime; + argumentNotEmptyString(typeId, "typeId"); + let pending = false; + return { + has() { + return typeId in singletons; + }, + get() { + if (!this.has()) + throw new Error(`The instance ${typeId} doesn't exists`); + return singletons[typeId]; + }, + initialize() { + if (pending) + throw new Error("Cyclic reference detected"); + pending = true; + }, + store(item: any) { + singletons[typeId] = item; + pending = false; + } + }; } static containerLifetime(container: Container) { @@ -160,7 +182,7 @@ export class LifetimeManager implements initialize(context: ActivationContext) { if (_lifetime !== unknownLifetime) throw new Error("Cyclic reference detected"); - _lifetime = container.getLifetimeManager().create(context); + _lifetime = container.getLifetimeManager().create(); }, get() { return _lifetime.get(); diff --git a/src/main/ts/di/ServiceDescriptor.ts b/src/main/ts/di/ServiceDescriptor.ts --- a/src/main/ts/di/ServiceDescriptor.ts +++ b/src/main/ts/di/ServiceDescriptor.ts @@ -1,5 +1,5 @@ import { ActivationContext } from "./ActivationContext"; -import { Descriptor, ServiceMap, PartialServiceMap, ILifetimeManager, ILifetime } from "./interfaces"; +import { Descriptor, ServiceMap, PartialServiceMap, ILifetime } from "./interfaces"; import { isPrimitive, keys, isNull } from "../safe"; import { TraceSource } from "../log/TraceSource"; import { isDescriptor } from "./traits"; diff --git a/src/main/ts/di/fluent/Configuration.ts b/src/main/ts/di/fluent/Configuration.ts deleted file mode 100644 --- a/src/main/ts/di/fluent/Configuration.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { Container } from "../Container"; -import { argumentNotNull, each } from "../../safe"; -import { DescriptorBuilder } from "./DescriptorBuilder"; - -enum State { - ready, - - pending -} - -export class Configuration { - - private _state = State.ready; - - _completion: PromiseLike = Promise.resolve(); - - _builders: { [k in keyof S]?: (service: DescriptorBuilder) => void } = {}; - - register(name: K, builder: (service: DescriptorBuilder) => void): Configuration> { - argumentNotNull(builder, "builder"); - - return this; - } - - private _moveStart() { - if (this._state !== State.ready) - throw new Error("Invalid operation"); - - this._state = State.pending; - } - - private _moveDone() { - this._state = State.ready; - } - - apply(target: Container) { - this._moveStart(); - - let pending = 1; - - this._completion = new Promise((resolve, reject) => { - each(this._builders, (v, k) => { - pending++; - const d = new DescriptorBuilder(target, result => { - target.register(k, result); - if (!--pending) - resolve(); - }); - - try { - v(d); - } catch (e) { - reject(e); - } - }); - }).then(() => this._moveDone()); - } - -} diff --git a/src/main/ts/di/fluent/DescriptorBuilder.ts b/src/main/ts/di/fluent/DescriptorBuilder.ts --- a/src/main/ts/di/fluent/DescriptorBuilder.ts +++ b/src/main/ts/di/fluent/DescriptorBuilder.ts @@ -1,46 +1,94 @@ -import { Resolver, LazyDependencyOptions, DependencyOptions } from "./interfaces"; +import { Resolver, RegistrationBuilder } from "./interfaces"; import { Container } from "../Container"; -import { Descriptor, ILifetime, ContainerKeys } from "../interfaces"; -import { ActivationContext } from "../ActivationContext"; +import { Descriptor, ILifetime, ActivationType, PartialServiceMap } from "../interfaces"; +import { DescriptorImpl } from "./DescriptorImpl"; +import { LifetimeManager } from "../LifetimeManager"; +import { isString, each, isPrimitive, isPromise, oid } from "../../safe"; + +export class DescriptorBuilder { + private readonly _container: Container; + private readonly _cb: (d: Descriptor) => void; + + private readonly _eb: (err: any) => void; -export class DescriptorBuilder { - readonly _container: Container; - readonly _cb: (d: Descriptor) => void; + private _lifetime = LifetimeManager.empty(); + + private _overrides?: PartialServiceMap; + + private _cleanup?: (item: T) => void; - constructor(container: Container, cb: (d: Descriptor) => void) { + private _factory?: (resolve: Resolver) => T; + + private _pending = 1; + + private _failed = false; + + constructor(container: Container, cb: (d: Descriptor) => void, eb: (err: any) => void) { this._container = container; this._cb = cb; + this._eb = eb; + } + + build(): DescriptorBuilder { + this._defer(); + return new DescriptorBuilder(this._container, () => this._complete(), err => this._fail(err)); } - factory(f: (resolve: Resolver, activate: (lifetime: ILifetime, factory: () => any, cleanup?: (item: any) => void) => any) => T): void { - this._cb({ - activate(context: ActivationContext) { - const resolve = (name: ContainerKeys, opts?: DependencyOptions | LazyDependencyOptions) => { - if (opts && "lazy" in opts && opts.lazy) { - const c2 = context.clone(); - return () => { - return opts.optional ? c2.resolve(name, opts.default) : c2.resolve(name); - }; - } else { - return opts && opts.optional ? context.resolve(name, opts.default) : context.resolve(name); - } - }; + override(name: K, builder: RegistrationBuilder): this; + override(services: { [name in K]: RegistrationBuilder }): this; + override(nameOrServices: K | { [name in K]: RegistrationBuilder }, builder?: RegistrationBuilder): this { + const overrides: PartialServiceMap = this._overrides ? + this._overrides : + (this._overrides = {}); + + const guard = (v: void | Promise) => { + if (isPromise(v)) + v.catch(err => this._fail(err)); + }; + + if (isPrimitive(nameOrServices)) { + if (builder) { + this._defer(); + const d = new DescriptorBuilder( + this._container, + result => { + overrides[nameOrServices] = result; + this._complete(); + }, + err => this._fail(err) + ); - const activate = (lifetime: ILifetime, factory: () => any, cleanup?: (item: any) => void) => { - if (lifetime.has()) { - return lifetime.get(); - } else { - lifetime.initialize(context); - const instance = factory(); - lifetime.store(instance, cleanup); - return instance; - } + try { + guard(builder(d)); + } catch (err) { + this._fail(err); + } + } + } else { + each(nameOrServices, (v, k) => this.override(k, v)); + } + return this; + } - }; + lifetime(lifetime: "singleton", typeId: string): this; + lifetime(lifetime: ILifetime | Exclude): this; + lifetime(lifetime: ILifetime | ActivationType, typeId?: string): this { + if (isString(lifetime)) { + this._lifetime = this._resolveLifetime(lifetime, typeId); + } else { + this._lifetime = lifetime; + } + return this; + } - return f(resolve, activate); - } - }); + cleanup(cb: (item: T) => void): this { + this._cleanup = cb; + return this; + } + + factory(f: (resolve: Resolver) => T): void { + this._factory = f; + this._complete(); } value(v: T): void { @@ -51,4 +99,49 @@ export class DescriptorBuilder({ + lifetime: this._lifetime, + factory: this._factory, + overrides: this._overrides, + cleanup: this._cleanup + })); + } + } + + _fail(err: any) { + if (!this._failed) { + this._failed = true; + this._eb.call(undefined, err); + } + } + } diff --git a/src/main/ts/di/fluent/DescriptorImpl.ts b/src/main/ts/di/fluent/DescriptorImpl.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/di/fluent/DescriptorImpl.ts @@ -0,0 +1,63 @@ +import { Descriptor, PartialServiceMap, ILifetime, ContainerKeys } from "../interfaces"; +import { ActivationContext } from "../ActivationContext"; +import { each } from "../../safe"; +import { DependencyOptions, LazyDependencyOptions, Resolver } from "./interfaces"; + +export interface DescriptorImplArgs { + lifetime: ILifetime; + + factory: (resolve: Resolver) => T; + + cleanup?: (item: T) => void; + + overrides?: PartialServiceMap; +} + +export class DescriptorImpl implements Descriptor { + + private readonly _overrides?: PartialServiceMap; + + private readonly _lifetime: ILifetime; + + private readonly _factory: (resolve: Resolver) => T; + + private readonly _cleanup?: (item: T) => void; + + constructor(args: DescriptorImplArgs) { + this._lifetime = args.lifetime; + this._factory = args.factory; + if (args.cleanup) + this._cleanup = args.cleanup; + if (args.overrides) + this._overrides = args.overrides; + } + + activate(context: ActivationContext): T { + + if (this._lifetime.has()) + return this._lifetime.get(); + + this._lifetime.initialize(context); + + if (this._overrides) + each(this._overrides, (v, k) => context.register(k, v)); + + const resolve = (name: ContainerKeys, opts?: DependencyOptions | LazyDependencyOptions) => { + if (opts && "lazy" in opts && opts.lazy) { + const c2 = context.clone(); + return () => { + return opts.optional ? c2.resolve(name, opts.default) : c2.resolve(name); + }; + } else { + return opts && opts.optional ? context.resolve(name, opts.default) : context.resolve(name); + } + }; + + const instance = this._factory.call(undefined, resolve); + + this._lifetime.store(instance, this._cleanup); + + return instance; + } + +} diff --git a/src/main/ts/di/fluent/FluentConfiguration.ts b/src/main/ts/di/fluent/FluentConfiguration.ts new file mode 100644 --- /dev/null +++ b/src/main/ts/di/fluent/FluentConfiguration.ts @@ -0,0 +1,58 @@ +import { Container } from "../Container"; +import { argumentNotNull, each, isPrimitive, isPromise } from "../../safe"; +import { DescriptorBuilder } from "./DescriptorBuilder"; +import { RegistrationBuilder, FluentRegistrations } from "./interfaces"; +import { Cancellation } from "../../Cancellation"; + +export class FluentConfiguration { + + _builders: { [k in keyof S]?: RegistrationBuilder } = {}; + + register(name: K, builder: RegistrationBuilder): FluentConfiguration>; + register(config: FluentRegistrations): FluentConfiguration>; + register(nameOrConfig: K | FluentRegistrations, builder?: RegistrationBuilder): FluentConfiguration> { + if (isPrimitive(nameOrConfig)) { + argumentNotNull(builder, "builder"); + this._builders[nameOrConfig] = builder; + } else { + each(nameOrConfig, (v, k) => this.register(k, v)); + } + + return this; + } + + apply(target: Container, ct = Cancellation.none) { + + let pending = 1; + + return new Promise((resolve, reject) => { + function guard(v: void | Promise) { + if (isPromise(v)) + v.catch(reject); + } + + function complete() { + if (!--pending) + resolve(); + } + each(this._builders, (v, k) => { + pending++; + const d = new DescriptorBuilder(target, + result => { + target.register(k, result); + complete(); + }, + reject + ); + + try { + guard(v(d, ct)); + } catch (e) { + reject(e); + } + }); + complete(); + }); + } + +} diff --git a/src/main/ts/di/fluent/interfaces.ts b/src/main/ts/di/fluent/interfaces.ts --- a/src/main/ts/di/fluent/interfaces.ts +++ b/src/main/ts/di/fluent/interfaces.ts @@ -1,6 +1,6 @@ import { primitive } from "../../safe"; -import { AnnotationBuilder } from "../Annotations"; -import { ILifetime, TypeOfService, ContainerKeys } from "../interfaces"; +import { TypeOfService, ContainerKeys, ActivationType, ILifetime } from "../interfaces"; +import { ICancellation } from "../../interfaces"; export interface DependencyOptions { optional?: boolean; @@ -22,10 +22,6 @@ export type ExtractDependency = D export type WalkDependencies = D extends primitive ? D : { [K in keyof D]: ExtractDependency }; -export type ServiceModule = { - [m in M]: AnnotationBuilder; -}; - export type InferReferenceType, O> = O extends { default: infer X } ? (TypeOfService | X) : O extends { optional: true } ? (TypeOfService | undefined) : TypeOfService; @@ -35,14 +31,22 @@ export interface Resolver, O extends DependencyOptions>(this: void, name: K, opts?: O): InferReferenceType; } -export interface DescriptorBuilder { - service(service: AnnotationBuilder | ServiceModule): void; +export interface DescriptorBuilder { + factory(f: (resolve: Resolver) => T): void; + + build(): DescriptorBuilder; - factory(f: (resolve: Resolver, activate: (lifetime: ILifetime, factory: () => T2, cleanup?: (item: T2) => void) => T2) => T): void; + override(name: K, builder: RegistrationBuilder): this; + override(services: { [name in K]: RegistrationBuilder }): this; + + lifetime(lifetime: "singleton", typeId: any): this; + lifetime(lifetime: ILifetime | Exclude): this; + + cleanup(cb: (item: T) => void): this; value(v: T): void; } -export interface Configuration { - register(name: K, builder: (d: DescriptorBuilder) => void): Configuration>; -} +export type RegistrationBuilder = (d: DescriptorBuilder, ct?: ICancellation) => void | Promise; + +export type FluentRegistrations = { [k in K]: RegistrationBuilder }; diff --git a/src/main/ts/di/interfaces.ts b/src/main/ts/di/interfaces.ts --- a/src/main/ts/di/interfaces.ts +++ b/src/main/ts/di/interfaces.ts @@ -37,10 +37,6 @@ export type ContainerRegistered): ILifetime; -} - /** * Интерфейс для управления жизнью экземпляра объекта. Каждая регистрация имеет * свой собственный объект `ILifetime`, который создается при первой активации diff --git a/src/main/ts/di/traits.ts b/src/main/ts/di/traits.ts --- a/src/main/ts/di/traits.ts +++ b/src/main/ts/di/traits.ts @@ -1,12 +1,11 @@ import { isPrimitive } from "../safe"; import { Descriptor } from "./interfaces"; -import { Configuration } from "./fluent/Configuration"; - +import { FluentConfiguration } from "./fluent/FluentConfiguration"; export function isDescriptor(x: any): x is Descriptor { return (!isPrimitive(x)) && (x.activate instanceof Function); } -export function configure() { - return new Configuration(); +export function fluent() { + return new FluentConfiguration(); } diff --git a/src/main/ts/safe.ts b/src/main/ts/safe.ts --- a/src/main/ts/safe.ts +++ b/src/main/ts/safe.ts @@ -1,4 +1,4 @@ -import { ICancellable, Constructor, IDestroyable } from "./interfaces"; +import { ICancellable, Constructor, IDestroyable, PromiseOrValue } from "./interfaces"; import { Cancellation } from "./Cancellation"; let _nextOid = 0; @@ -6,6 +6,8 @@ const _oid = typeof Symbol === "function Symbol("__implab__oid__") : "__implab__oid__"; +export function oid(instance: null | undefined): undefined; +export function oid(instance: NonNullable): string; export function oid(instance: any): string | undefined { if (isNull(instance)) return undefined; diff --git a/src/test/ts/mock/config.ts b/src/test/ts/mock/config.ts --- a/src/test/ts/mock/config.ts +++ b/src/test/ts/mock/config.ts @@ -1,16 +1,19 @@ import { Services } from "./services"; -import { configure } from "../di/traits"; -import { LifetimeManager } from "../di/LifetimeManager"; +import { fluent } from "../di/traits"; + +export default fluent().register({ + host: it => it.value("example.com"), -export const config = configure() - .register("host", s => s.value("example.com")) - .register("bar2", bar2 => Promise.all([import("./Foo"), import("./Bar")]) - .then(([{ Foo }, { Bar }]) => { - const lifetime = LifetimeManager.hierarchyLifetime(); - - bar2.factory((resolve, activate) => { + bar2: it => Promise.all([import("./Foo"), import("./Bar")]) + .then(([{ Foo }, { Bar }]) => it + .lifetime("container") + .override({ + host: it2 => it2.value("simple.org"), + foo: it2 => it2.value(new Foo()) + }) + .factory(resolve => { const bar = new Bar({ - foo: activate(lifetime, () => new Foo()), + foo: new Foo(), nested: { lazy: resolve("foo", { lazy: true }) }, @@ -18,6 +21,6 @@ export const config = configure { const container = new Container<{ diff --git a/src/test/ts/tests/FluentContainerTests.ts b/src/test/ts/tests/FluentContainerTests.ts new file mode 100644 --- /dev/null +++ b/src/test/ts/tests/FluentContainerTests.ts @@ -0,0 +1,54 @@ +import { test } from "./TestTraits"; +import { fluent } from "../di/traits"; +import { Bar } from "../mock/Bar"; +import { Container } from "../di/Container"; +import { Foo } from "../mock/Foo"; +import { Box } from "../mock/Box"; +import { delay } from "../safe"; + +test("Simple fluent config", async t => { + const config = fluent<{ host: string; bar: Bar; foo: Foo }>() + .register({ + host: it => it.value("example.com"), + bar: it => it.factory(resolve => new Bar({ host: resolve("host") }, "s-bar")), + foo: it => import("../mock/Foo").then(m => it.lifetime("container").factory(() => new m.Foo())) + }); + + const container = new Container<{ host: string; bar: Bar; foo: Foo; }>(); + await config.apply(container); + + t.equal(container.resolve("host"), "example.com", "The value should be resolved"); + t.assert(container.resolve("bar"), "The service should de activated"); + t.equal(container.resolve("foo"), container.resolve("foo"), "The service should be activated once"); +}); + +test("Nested async configuration", async t => { + const container = await new Container<{ + foo: Foo; + box: Box + }>().fluent({ + foo: it => delay(0).then(() => it.factory(() => new Foo())), + box: it => it.lifetime("context").factory($dependency => new Box($dependency("foo"))) + }); + + t.assert(container.resolve("box").getValue(), "The dependency should be set"); + t.equals(container.resolve("box").getValue(), container.resolve("box").getValue(), "The service should be activated once") +}); + +test("Bad fluent config", async t => { + try { + await new Container<{ + foo: Foo; + box: Box + }>().fluent({ + foo: it => delay(0).then(() => it.factory(() => new Foo())), + box: it => it.lifetime("context") + .override("foo", () => { throw new Error("bad override"); }) + .factory($dependency => new Box($dependency("foo"))) + }); + t.fail("Should throw"); + } catch (e) { + t.pass("The configuration should fail"); + t.equal(e.message, "bad override", "the error should pass"); + } +}); diff --git a/src/test/tsconfig.json b/src/test/tsconfig.json --- a/src/test/tsconfig.json +++ b/src/test/tsconfig.json @@ -1,8 +1,6 @@ { "extends": "../tsconfig", "compilerOptions": { - //"rootDir": "ts", - "baseUrl": ".", "rootDirs": [ "ts", "../main/ts" diff --git a/src/testAmd/js/tests/plan.js b/src/testAmd/js/tests/plan.js --- a/src/testAmd/js/tests/plan.js +++ b/src/testAmd/js/tests/plan.js @@ -6,5 +6,6 @@ define([ "./ObservableTests", "./ContainerTests", "./SafeTests", - "./TextTests" + "./TextTests", + "./FluentContainerTests" ]); \ No newline at end of file