123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554 |
- // Copyright (c) Jupyter Development Team.
- // Distributed under the terms of the Modified BSD License.
- import expect = require('expect.js');
- import {
- uuid
- } from '@jupyterlab/coreutils';
- import {
- toArray
- } from '@phosphor/algorithm';
- import {
- DisposableDelegate, IDisposable
- } from '@phosphor/disposable';
- import {
- Widget
- } from '@phosphor/widgets';
- import {
- ABCWidgetFactory, Base64ModelFactory, DocumentRegistry, DocumentWidget, IDocumentWidget
- } from '@jupyterlab/docregistry';
- class WidgetFactory extends ABCWidgetFactory<IDocumentWidget> {
- protected createNewWidget(context: DocumentRegistry.Context): IDocumentWidget {
- const content = new Widget();
- const widget = new DocumentWidget({ content, context });
- widget.addClass('WidgetFactory');
- return widget;
- }
- }
- class WidgetExtension implements DocumentRegistry.WidgetExtension {
- createNew(widget: Widget, context: DocumentRegistry.Context): IDisposable {
- return new DisposableDelegate(null);
- }
- }
- function createFactory(modelName?: string) {
- return new WidgetFactory({
- name: uuid(),
- modelName: modelName || 'text',
- fileTypes: ['text', 'foobar'],
- defaultFor: ['text', 'foobar']
- });
- }
- describe('docregistry/registry', () => {
- describe('DocumentRegistry', () => {
- let registry: DocumentRegistry;
- beforeEach(() => {
- registry = new DocumentRegistry();
- registry.addFileType({
- name: 'foobar',
- extensions: ['.foo.bar']
- });
- });
- afterEach(() => {
- registry.dispose();
- });
- describe('#isDisposed', () => {
- it('should get whether the registry has been disposed', () => {
- expect(registry.isDisposed).to.be(false);
- registry.dispose();
- expect(registry.isDisposed).to.be(true);
- });
- });
- describe('#dispose()', () => {
- it('should dispose of the resources held by the registry', () => {
- registry.addFileType({ name: 'notebook', extensions: ['.ipynb'] });
- registry.dispose();
- expect(registry.isDisposed).to.be(true);
- });
- it('should be safe to call multiple times', () => {
- registry.dispose();
- registry.dispose();
- expect(registry.isDisposed).to.be(true);
- });
- });
- describe('#addWidgetFactory()', () => {
- it('should add the widget factory to the registry', () => {
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- expect(registry.getWidgetFactory(factory.name)).to.be(factory);
- expect(registry.getWidgetFactory(factory.name.toUpperCase())).to.be(factory);
- });
- it('should become the global default if `*` is given as a defaultFor', () => {
- let factory = new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- });
- registry.addWidgetFactory(factory);
- expect(registry.defaultWidgetFactory('*').name).to.be('global');
- });
- it('should override an existing global default', () => {
- registry.addWidgetFactory(new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- }));
- let factory = new WidgetFactory({
- name: 'bar',
- fileTypes: ['*'],
- defaultFor: ['*']
- });
- registry.addWidgetFactory(factory);
- expect(registry.defaultWidgetFactory('*').name).to.be('bar');
- });
- it('should override an existing extension default', () => {
- registry.addWidgetFactory(createFactory());
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- expect(registry.defaultWidgetFactory('a.foo.bar')).to.be(factory);
- });
- it('should be removed from the registry when disposed', () => {
- let factory = createFactory();
- let disposable = registry.addWidgetFactory(factory);
- disposable.dispose();
- expect(registry.getWidgetFactory('test')).to.be(void 0);
- });
- });
- describe('#addModelFactory()', () => {
- it('should add the model factory to the registry', () => {
- let factory = new Base64ModelFactory();
- registry.addModelFactory(factory);
- });
- it('should be a no-op a factory with the given `name` is already registered', () => {
- let factory = new Base64ModelFactory();
- registry.addModelFactory(factory);
- let disposable = registry.addModelFactory(new Base64ModelFactory());
- disposable.dispose();
- });
- it('should be a no-op if the same factory is already registered', () => {
- let factory = new Base64ModelFactory();
- registry.addModelFactory(factory);
- let disposable = registry.addModelFactory(factory);
- disposable.dispose();
- });
- it('should be removed from the registry when disposed', () => {
- let factory = new Base64ModelFactory();
- let disposable = registry.addModelFactory(factory);
- disposable.dispose();
- });
- });
- describe('#addWidgetExtension()', () => {
- it('should add a widget extension to the registry', () => {
- let extension = new WidgetExtension();
- registry.addWidgetExtension('foo', extension);
- expect(registry.widgetExtensions('foo').next()).to.be(extension);
- });
- it('should be a no-op if the extension is already registered for a given widget factory', () => {
- let extension = new WidgetExtension();
- registry.addWidgetExtension('foo', extension);
- let disposable = registry.addWidgetExtension('foo', extension);
- disposable.dispose();
- expect(registry.widgetExtensions('foo').next()).to.be(extension);
- });
- it('should be removed from the registry when disposed', () => {
- let extension = new WidgetExtension();
- let disposable = registry.addWidgetExtension('foo', extension);
- disposable.dispose();
- expect(toArray(registry.widgetExtensions('foo')).length).to.be(0);
- });
- });
- describe('#addFileType()', () => {
- it('should add a file type to the document registry', () => {
- registry = new DocumentRegistry({ initialFileTypes: [] });
- let fileType = { name: 'notebook', extensions: ['.ipynb'] };
- registry.addFileType(fileType);
- expect(registry.fileTypes().next().name).to.be(fileType.name);
- });
- it('should be removed from the registry when disposed', () => {
- registry = new DocumentRegistry({ initialFileTypes: [] });
- let fileType = { name: 'notebook', extensions: ['.ipynb'] };
- let disposable = registry.addFileType(fileType);
- disposable.dispose();
- expect(toArray(registry.fileTypes()).length).to.be(0);
- });
- it('should be a no-op if a file type of the same name is registered', () => {
- registry = new DocumentRegistry({ initialFileTypes: [] });
- let fileType = { name: 'notebook', extensions: ['.ipynb'] };
- registry.addFileType(fileType);
- let disposable = registry.addFileType(fileType);
- disposable.dispose();
- expect(registry.fileTypes().next().name).to.be(fileType.name);
- });
- });
- describe('#preferredWidgetFactories()', () => {
- beforeEach(() => {
- registry.addFileType({
- name: 'tablejson',
- extensions: ['.table.json']
- });
- });
- it('should give the valid registered widget factories', () => {
- expect(toArray(registry.preferredWidgetFactories('foo.txt'))).to.eql([]);
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let gFactory = new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- });
- registry.addWidgetFactory(gFactory);
- let factories = registry.preferredWidgetFactories('a.foo.bar');
- expect(toArray(factories)).to.eql([factory, gFactory]);
- });
- it('should not list a factory whose model is not registered', () => {
- registry.addWidgetFactory(createFactory('foobar'));
- expect(registry.preferredWidgetFactories('a.foo.bar').length).to.eql(0);
- });
- it('should select the factory for a given extension', () => {
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let mdFactory = new WidgetFactory({
- name: 'markdown',
- fileTypes: ['markdown'],
- });
- registry.addWidgetFactory(mdFactory);
- expect(registry.preferredWidgetFactories('a.txt')[0]).to.be(factory);
- expect(registry.preferredWidgetFactories('a.md')[0]).to.be(mdFactory);
- });
- it('should respect the priority order', () => {
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let gFactory = new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- });
- registry.addWidgetFactory(gFactory);
- let mdFactory = new WidgetFactory({
- name: 'markdown',
- fileTypes: ['markdown'],
- });
- registry.addWidgetFactory(mdFactory);
- let factories = registry.preferredWidgetFactories('a.txt');
- expect(toArray(factories)).to.eql([factory, gFactory]);
- });
- it('should handle multi-part extensions', () => {
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let tFactory = new WidgetFactory({
- name: 'table',
- fileTypes: ['tablejson'],
- });
- registry.addWidgetFactory(tFactory);
- let jFactory = new WidgetFactory({
- name: 'json',
- fileTypes: ['json'],
- });
- registry.addWidgetFactory(jFactory);
- let factories = registry.preferredWidgetFactories('foo.table.json');
- expect(toArray(factories)).to.eql([tFactory, jFactory]);
- factories = registry.preferredWidgetFactories('foo.json');
- expect(toArray(factories)).to.eql([jFactory]);
- });
- it('should handle just a multi-part extension', () => {
- let factory = new WidgetFactory({
- name: 'table',
- fileTypes: ['tablejson'],
- });
- registry.addWidgetFactory(factory);
- let factories = registry.preferredWidgetFactories('foo.table.json');
- expect(toArray(factories)).to.eql([factory]);
- factories = registry.preferredWidgetFactories('foo.json');
- expect(toArray(factories)).to.eql([]);
- });
- });
- describe('#defaultWidgetFactory()', () => {
- it('should get the default widget factory for a given extension', () => {
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let gFactory = new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- });
- registry.addWidgetFactory(gFactory);
- let mdFactory = new WidgetFactory({
- name: 'markdown',
- fileTypes: ['markdown'],
- defaultFor: ['markdown']
- });
- registry.addWidgetFactory(mdFactory);
- expect(registry.defaultWidgetFactory('a.foo.bar')).to.be(factory);
- expect(registry.defaultWidgetFactory('a.md')).to.be(mdFactory);
- expect(registry.defaultWidgetFactory()).to.be(gFactory);
- });
- });
- describe('#fileTypes()', () => {
- it('should get the registered file types', () => {
- registry = new DocumentRegistry({ initialFileTypes: [] });
- expect(toArray(registry.fileTypes()).length).to.be(0);
- let fileTypes = [
- { name: 'notebook', extensions: ['.ipynb'] },
- { name: 'python', extensions: ['.py'] },
- { name: 'table', extensions: ['.table.json'] }
- ];
- registry.addFileType(fileTypes[0]);
- registry.addFileType(fileTypes[1]);
- registry.addFileType(fileTypes[2]);
- let values = registry.fileTypes();
- expect(values.next().name).to.be(fileTypes[0].name);
- expect(values.next().name).to.be(fileTypes[1].name);
- expect(values.next().name).to.be(fileTypes[2].name);
- });
- });
- describe('#getFileType()', () => {
- it('should get a file type by name', () => {
- expect(registry.getFileType('notebook')).to.be.ok();
- expect(registry.getFileType('python')).to.be.ok();
- expect(registry.getFileType('fizzbuzz')).to.be(void 0);
- });
- });
- describe('#getKernelPreference()', () => {
- it('should get a kernel preference', () => {
- registry.addWidgetFactory(createFactory());
- registry.addWidgetFactory(new WidgetFactory({
- name: 'python',
- fileTypes: ['python'],
- preferKernel: true,
- canStartKernel: true
- }));
- registry.addWidgetFactory(new WidgetFactory({
- name: 'global',
- fileTypes: ['*'],
- defaultFor: ['*']
- }));
- let pref = registry.getKernelPreference('.c', 'global');
- expect(pref.language).to.be('clike');
- expect(pref.shouldStart).to.be(false);
- expect(pref.canStart).to.be(false);
- pref = registry.getKernelPreference('.py', 'python');
- expect(pref.language).to.be('python');
- expect(pref.shouldStart).to.be(true);
- expect(pref.canStart).to.be(true);
- pref = registry.getKernelPreference('.py', 'baz');
- expect(pref).to.be(void 0);
- });
- });
- describe('#getModelFactory()', () => {
- it('should get a registered model factory by name', () => {
- let mFactory = new Base64ModelFactory();
- registry.addModelFactory(mFactory);
- expect(registry.getModelFactory('base64')).to.be(mFactory);
- });
- });
- describe('#getWidgetFactory()', () => {
- it('should get a widget factory by name', () => {
- registry.addModelFactory(new Base64ModelFactory());
- let factory = createFactory();
- registry.addWidgetFactory(factory);
- let mdFactory = new WidgetFactory({
- name: 'markdown',
- fileTypes: ['markdown'],
- });
- registry.addWidgetFactory(mdFactory);
- expect(registry.getWidgetFactory(factory.name)).to.be(factory);
- expect(registry.getWidgetFactory('markdown')).to.be(mdFactory);
- expect(registry.getWidgetFactory('baz')).to.be(void 0);
- });
- });
- describe('#widgetExtensions()', () => {
- it('should get the registered extensions for a given widget', () => {
- let foo = new WidgetExtension();
- let bar = new WidgetExtension();
- registry.addWidgetExtension('fizz', foo);
- registry.addWidgetExtension('fizz', bar);
- registry.addWidgetExtension('buzz', foo);
- let fizz = toArray(registry.widgetExtensions('fizz'));
- expect(fizz[0]).to.be(foo);
- expect(fizz[1]).to.be(bar);
- expect(fizz.length).to.be(2);
- let buzz = toArray(registry.widgetExtensions('buzz'));
- expect(buzz[0]).to.be(foo);
- expect(toArray(buzz).length).to.be(1);
- expect(registry.widgetExtensions('baz').next()).to.be(void 0);
- });
- });
- describe('#getFileTypeForModel()', () => {
- beforeEach(() => {
- DocumentRegistry.defaultFileTypes.forEach(ft => {
- registry.addFileType(ft);
- });
- });
- it('should handle a directory', () => {
- let ft = registry.getFileTypeForModel({
- type: 'directory'
- });
- expect(ft.name).to.be('directory');
- });
- it('should handle a notebook', () => {
- let ft = registry.getFileTypeForModel({
- type: 'notebook'
- });
- expect(ft.name).to.be('notebook');
- });
- it('should handle a python file', () => {
- let ft = registry.getFileTypeForModel({
- name: 'foo.py'
- });
- expect(ft.name).to.be('python');
- });
- it('should handle an unknown file', () => {
- let ft = registry.getFileTypeForModel({
- name: 'foo.bar'
- });
- expect(ft.name).to.be('text');
- });
- it('should get the most specific extension', () => {
- [
- { name: 'json', extensions: ['.json'] },
- { name: 'vega', extensions: ['.vg.json'] }
- ].forEach(ft => {registry.addFileType(ft); });
- let ft = registry.getFileTypeForModel({
- name: 'foo.vg.json'
- });
- expect(ft.name).to.be('vega');
- });
- it('should be case insensitive', () => {
- let ft = registry.getFileTypeForModel({
- name: 'foo.PY'
- });
- expect(ft.name).to.be('python');
- });
- });
- describe('#getFileTypesForPath()', () => {
- beforeEach(() => {
- DocumentRegistry.defaultFileTypes.forEach(ft => {
- registry.addFileType(ft);
- });
- });
- it('should handle a notebook', () => {
- let ft = registry.getFileTypesForPath('foo/bar/baz.ipynb');
- expect(ft[0].name).to.be('notebook');
- });
- it('should handle a python file', () => {
- let ft = registry.getFileTypesForPath('foo/bar/baz.py');
- expect(ft[0].name).to.be('python');
- });
- it('should return an empty list for an unknown file', () => {
- let ft = registry.getFileTypesForPath('foo/bar/baz.weird');
- expect(ft.length).to.be(0);
- });
- it('should get the most specific extension first', () => {
- [
- { name: 'json', extensions: ['.json'] },
- { name: 'vega', extensions: ['.vg.json'] }
- ].forEach(ft => {registry.addFileType(ft); });
- let ft = registry.getFileTypesForPath('foo/bar/baz.vg.json');
- expect(ft[0].name).to.be('vega');
- expect(ft[1].name).to.be('json');
- });
- it('should be case insensitive', () => {
- let ft = registry.getFileTypesForPath('foo/bar/baz.PY');
- expect(ft[0].name).to.be('python');
- });
- });
- });
- });
|