Permalink
Browse files

feat(resources): register resources by class (#354)

BREAKING CHANGE - default resources are no longer reexported, need to be explicitly included when bundling
  • Loading branch information...
StrahilKazlachev committed Aug 11, 2018
1 parent ceefb50 commit ff55c80ffaf2c9b27bb704dfe07fcc8af899ba08
@@ -32,10 +32,10 @@
"build:commonjs": "cross-env tsc --project tsconfig.build.json --outDir dist/commonjs --module commonjs",
"postbuild:commonjs": "cross-env copyfiles --up 1 src/**/*.html src/**/*.css dist/commonjs",
"prebuild:es2015": "cross-env rimraf dist/es2015",
"build:es2015": "cross-env tsc --project tsconfig.build.json --outDir dist/es2015 --module es2015 --target es2015",
"build:es2015": "cross-env tsc --project tsconfig.build.json --outDir dist/es2015 --module esnext --target es2015",
"postbuild:es2015": "cross-env copyfiles --up 1 src/**/*.html src/**/*.css dist/es2015",
"prebuild:native-modules": "cross-env rimraf dist/native-modules",
"build:native-modules": "cross-env tsc --project tsconfig.build.json --outDir dist/native-modules --module es2015",
"build:native-modules": "cross-env tsc --project tsconfig.build.json --outDir dist/native-modules --module esnext",
"postbuild:native-modules": "cross-env copyfiles --up 1 src/**/*.html src/**/*.css dist/native-modules",
"prebuild:system": "cross-env rimraf dist/system",
"build:system": "cross-env tsc --project tsconfig.build.json --outDir dist/system --module system",
@@ -110,24 +110,5 @@
"tslint": "5.7.0",
"typedoc": "0.8.0",
"typescript": "^2.5.3"
},
"aurelia": {
"documentation": {
"articles": [
{
"title": "Dialog: Basics",
"href": "doc/article/en-US/dialog-basics.md"
}
]
},
"build": {
"resources": [
"aurelia-dialog/ux-dialog",
"aurelia-dialog/ux-dialog-header",
"aurelia-dialog/ux-dialog-body",
"aurelia-dialog/ux-dialog-footer",
"aurelia-dialog/attach-focus"
]
}
}
}
@@ -3,22 +3,17 @@ import { DialogConfiguration } from './dialog-configuration';
export function configure(
frameworkConfig: FrameworkConfiguration,
callback?: (config: DialogConfiguration) => void): void {
let applyConfig: () => void = null as any;
callback?: (config: DialogConfiguration) => void): void | Promise<void> {
let applyConfig: () => void | Promise<void> = null as any;
const config = new DialogConfiguration(frameworkConfig, (apply: () => void) => { applyConfig = apply; });
if (typeof callback === 'function') {
callback(config);
} else {
config.useDefaults();
}
applyConfig();
return applyConfig();
}
export * from './ux-dialog';
export * from './ux-dialog-header';
export * from './ux-dialog-body';
export * from './ux-dialog-footer';
export * from './attach-focus';
export * from './interfaces';
export * from './dialog-settings';
export * from './dialog-configuration';
@@ -2,16 +2,16 @@ import { FrameworkConfiguration } from 'aurelia-framework';
import { Renderer, RendererStatic } from './renderer';
import { DialogSettings, DefaultDialogSettings } from './dialog-settings';
import { DialogRenderer } from './dialog-renderer';
import { DOM, PLATFORM } from 'aurelia-pal';
import { DOM } from 'aurelia-pal';
const defaultRenderer: RendererStatic = DialogRenderer;
const resources: { [key: string]: string } = {
'ux-dialog': PLATFORM.moduleName('./ux-dialog'),
'ux-dialog-header': PLATFORM.moduleName('./ux-dialog-header'),
'ux-dialog-body': PLATFORM.moduleName('./ux-dialog-body'),
'ux-dialog-footer': PLATFORM.moduleName('./ux-dialog-footer'),
'attach-focus': PLATFORM.moduleName('./attach-focus')
const resources: { [key: string]: () => Promise<any> } = {
'ux-dialog': () => import('./resources/ux-dialog'),
'ux-dialog-header': () => import('./resources/ux-dialog-header'),
'ux-dialog-body': () => import('./resources/ux-dialog-body'),
'ux-dialog-footer': () => import('./resources/ux-dialog-footer'),
'attach-focus': () => import('./resources/attach-focus')
};
// tslint:disable-next-line:max-line-length
@@ -34,19 +34,28 @@ export class DialogConfiguration {
*/
public settings: DialogSettings;
constructor(frameworkConfiguration: FrameworkConfiguration, applySetter: (apply: () => void) => void) {
constructor(
frameworkConfiguration: FrameworkConfiguration,
applySetter: (apply: () => void | Promise<void>) => void
) {
this.fwConfig = frameworkConfiguration;
this.settings = this.fwConfig.container.get(DefaultDialogSettings);
applySetter(() => this._apply());
}
private _apply(): void {
private _apply(): void | Promise<void> {
this.fwConfig.transient(Renderer, this.renderer);
this.resources.forEach(resourceName => this.fwConfig.globalResources(resources[resourceName]));
if (this.cssText) {
DOM.injectStyles(this.cssText);
}
if (this.resources.length) {
return Promise.all(this.resources.map(name => resources[name]()))
.then(modules => {
this.fwConfig.globalResources(modules.map(m => m.default as () => void));
});
}
}
/**
@@ -2,7 +2,7 @@ import { customAttribute, ComponentAttached } from 'aurelia-templating';
import { DOM } from 'aurelia-pal';
@customAttribute('attach-focus')
export class AttachFocus implements ComponentAttached {
export default class AttachFocus implements ComponentAttached {
public value: boolean | string;
/**
@@ -6,6 +6,6 @@ import { customElement, inlineView } from 'aurelia-templating';
<slot></slot>
</template>
`)
export class UxDialogBody {
export default class UxDialogBody {
}
@@ -1,5 +1,5 @@
import { customElement, bindable, inlineView } from 'aurelia-templating';
import { DialogController } from './dialog-controller';
import { DialogController } from '../dialog-controller';
/**
* View-model for footer of Dialog.
@@ -19,7 +19,7 @@ import { DialogController } from './dialog-controller';
</template>
`)
export class UxDialogFooter {
export default class UxDialogFooter {
public static isCancelButton(value: string) {
return value === 'Cancel';
}
@@ -1,5 +1,5 @@
import { customElement, bindable, inlineView, ComponentBind } from 'aurelia-templating';
import { DialogController } from './dialog-controller';
import { DialogController } from '../dialog-controller';
@customElement('ux-dialog-header')
@inlineView(`
@@ -19,7 +19,7 @@ import { DialogController } from './dialog-controller';
</template>
`)
export class UxDialogHeader implements ComponentBind {
export default class UxDialogHeader implements ComponentBind {
@bindable() public showCloseButton: boolean | undefined;
/**
@@ -6,6 +6,6 @@ import { customElement, inlineView } from 'aurelia-templating';
<slot></slot>
</template>
`)
export class UxDialog {
export default class UxDialog {
}
@@ -4,18 +4,27 @@ import { DOM } from 'aurelia-pal';
import { DialogConfiguration, Renderer } from '../../src/aurelia-dialog';
import { DefaultDialogSettings } from '../../src/dialog-settings';
import { DialogRenderer } from '../../src/dialog-renderer';
import UxDialog from '../../src/resources/ux-dialog';
describe('DialogConfiguration', () => {
fdescribe('DialogConfiguration', () => {
const frameworkConfig: FrameworkConfiguration = {
container: new Container(),
globalResources: () => { return; },
transient: () => { return; }
} as any;
let configuration: DialogConfiguration;
let applyConfig: () => void;
let applyConfig: () => Promise<void>;
const applySetterSpy = jasmine.createSpy('applySetter')
.and
.callFake((apply: () => void) => { applyConfig = apply; });
.callFake((apply: () => Promise<void>) => { applyConfig = apply; });
async function whenConfigured(configuration: () => (void | Promise<void>), done: DoneFn): Promise<void> {
try {
await configuration();
} catch (e) {
done.fail(e);
}
}
beforeEach(() => {
frameworkConfig.container.unregister(DefaultDialogSettings);
@@ -32,101 +41,106 @@ describe('DialogConfiguration', () => {
});
describe('even when ".useDefaults" is not called', () => {
it('a default Renderer should be registered', () => {
let applyConfig: () => void = null as any;
it('a default Renderer should be registered', async done => {
let applyConfig: () => void | Promise<void> = null as any;
// tslint:disable-next-line:no-unused-expression
new DialogConfiguration(frameworkConfig, apply => { applyConfig = apply; });
spyOn(frameworkConfig, 'transient');
applyConfig();
await whenConfigured(applyConfig, done);
expect(frameworkConfig.transient).toHaveBeenCalledWith(Renderer, DialogRenderer);
done();
});
it('the default css styles should be applied', () => {
let applyConfig: () => void = null as any;
it('the default css styles should be applied', async done => {
let applyConfig: () => void | Promise<void> = null as any;
// tslint:disable-next-line:no-unused-expression
new DialogConfiguration(frameworkConfig, apply => { applyConfig = apply; });
spyOn(DOM, 'injectStyles');
applyConfig();
await whenConfigured(applyConfig, done);
expect(DOM.injectStyles).toHaveBeenCalledWith(jasmine.any(String));
done();
});
});
describe('useRenderer', () => {
it('should register a renderer as a transient', () => {
it('should register a renderer as a transient', async done => {
const renderer = {} as any;
spyOn(frameworkConfig, 'transient');
configuration.useRenderer(renderer);
applyConfig();
await whenConfigured(applyConfig, done);
expect(frameworkConfig.transient).toHaveBeenCalledWith(Renderer, renderer);
done();
});
it('should export settings', () => {
it('should export settings', async done => {
const first = 'first';
const second = 'second';
configuration.useRenderer({} as any, { first, second });
applyConfig();
await whenConfigured(applyConfig, done);
expect(configuration.settings[first]).toBe(first);
expect(configuration.settings[second]).toBe(second);
done();
});
});
describe('useResource', () => {
it('should call globalResources', () => {
it('should call globalResources', async done => {
spyOn(frameworkConfig, 'globalResources');
configuration.useResource('ux-dialog');
applyConfig();
expect(frameworkConfig.globalResources).toHaveBeenCalled();
await whenConfigured(applyConfig, done);
expect(frameworkConfig.globalResources).toHaveBeenCalledWith(jasmine.arrayContaining([UxDialog]));
done();
});
});
describe('useDefaults', () => {
it('should call useRenderer with the default renderer', () => {
it('should call useRenderer with the default renderer', async done => {
spyOn(configuration, 'useRenderer').and.callThrough();
spyOn(configuration, 'useResource').and.callThrough();
configuration.useDefaults();
applyConfig();
await whenConfigured(applyConfig, done);
expect(configuration.useRenderer).toHaveBeenCalledWith(DialogRenderer);
expect(configuration.useResource).toHaveBeenCalledWith('ux-dialog');
expect(configuration.useResource).toHaveBeenCalledWith('ux-dialog-header');
expect(configuration.useResource).toHaveBeenCalledWith('ux-dialog-footer');
expect(configuration.useResource).toHaveBeenCalledWith('ux-dialog-body');
expect(configuration.useResource).toHaveBeenCalledWith('attach-focus');
done();
});
it('should inject default style', () => {
it('should inject default style', async done => {
spyOn(DOM, 'injectStyles').and.callThrough();
configuration.useDefaults();
applyConfig();
await whenConfigured(applyConfig, done);
expect((DOM.injectStyles as jasmine.Spy).calls.any()).toEqual(true);
done();
});
});
describe('useCSS', () => {
describe('should skip injecting', () => {
it('undefined css', () => {
it('undefined css', async done => {
spyOn(DOM, 'injectStyles').and.callThrough();
configuration.useCSS(undefined as any);
applyConfig();
await whenConfigured(applyConfig, done);
expect((DOM.injectStyles as jasmine.Spy).calls.any()).toEqual(false);
done();
});
it('null css', () => {
it('null css', async done => {
spyOn(DOM, 'injectStyles').and.callThrough();
configuration.useCSS(null as any);
applyConfig();
await whenConfigured(applyConfig, done);
expect((DOM.injectStyles as jasmine.Spy).calls.any()).toEqual(false);
done();
});
it('empty string', () => {
it('empty string', async done => {
spyOn(DOM, 'injectStyles').and.callThrough();
configuration.useCSS('');
applyConfig();
await whenConfigured(applyConfig, done);
expect((DOM.injectStyles as jasmine.Spy).calls.any()).toEqual(false);
done();
});
});
});

0 comments on commit ff55c80

Please sign in to comment.