浏览代码

Add more tests and make sure transforms fail if they change the ID.

Afshin Darian 6 年之前
父节点
当前提交
fd49db7f70
共有 2 个文件被更改,包括 96 次插入17 次删除
  1. 28 10
      packages/coreutils/src/settingregistry.ts
  2. 68 7
      tests/test-coreutils/src/settingregistry.spec.ts

+ 28 - 10
packages/coreutils/src/settingregistry.ts

@@ -442,11 +442,12 @@ export class DefaultSchemaValidator implements ISchemaValidator {
     // If the schemas do not exist, add them to the validator and continue.
     if (!validate || !compose) {
       if (plugin.schema.type !== 'object') {
+        const keyword = 'schema';
         const message =
           `Setting registry schemas' root-level type must be ` +
           `'object', rejecting type: ${plugin.schema.type}`;
 
-        return [{ dataPath: 'type', keyword: '', schemaPath: '', message }];
+        return [{ dataPath: 'type', keyword, schemaPath: '', message }];
       }
 
       const errors = this._addSchema(plugin.id, plugin.schema);
@@ -755,7 +756,7 @@ export class SettingRegistry {
   transform(
     plugin: string,
     transforms: {
-      [phase in ISettingRegistry.IPlugin.Phase]: ISettingRegistry.IPlugin.Transform
+      [phase in ISettingRegistry.IPlugin.Phase]?: ISettingRegistry.IPlugin.Transform
     }
   ): IDisposable {
     const transformers = this._transformers;
@@ -814,8 +815,10 @@ export class SettingRegistry {
       (errors as ISchemaValidator.IError[]).forEach((error, index) => {
         const { dataPath, schemaPath, keyword, message } = error;
 
-        output.push(`${index} - schema @ ${schemaPath}, data @ ${dataPath}`);
-        output.push(`\t${keyword} ${message}`);
+        if (dataPath || schemaPath) {
+          output.push(`${index} - schema @ ${schemaPath}, data @ ${dataPath}`);
+        }
+        output.push(`{${keyword}} ${message}`);
       });
       console.warn(output.join('\n'));
 
@@ -869,6 +872,7 @@ export class SettingRegistry {
     started = new Date().getTime()
   ): Promise<ISettingRegistry.IPlugin> {
     const elapsed = new Date().getTime() - started;
+    const id = plugin.id;
     const transformers = this._transformers;
     const timeout = this._timeout;
 
@@ -876,11 +880,18 @@ export class SettingRegistry {
       return plugin;
     }
 
-    if (plugin.id in transformers) {
-      const transformed = transformers[plugin.id][phase].call(null, plugin);
+    if (id in transformers) {
+      const transformed = transformers[id][phase].call(null, plugin);
 
-      if (transformed.id !== plugin.id) {
-        throw new Error('Plugin transformations cannot change plugin IDs.');
+      if (transformed.id !== id) {
+        throw [
+          {
+            dataPath: '',
+            keyword: 'id',
+            message: 'Plugin transformations cannot change plugin IDs.',
+            schemaPath: ''
+          } as ISchemaValidator.IError
+        ];
       }
 
       return transformed;
@@ -896,7 +907,14 @@ export class SettingRegistry {
       return this._transform(phase, plugin, started);
     }
 
-    throw new Error(`Transforming ${plugin.id} timed out.`);
+    throw [
+      {
+        dataPath: '',
+        keyword: 'timeout',
+        message: `Transforming ${plugin.id} timed out.`,
+        schemaPath: ''
+      } as ISchemaValidator.IError
+    ];
   }
 
   /**
@@ -915,7 +933,7 @@ export class SettingRegistry {
   }
 
   private _pluginChanged = new Signal<this, string>(this);
-  private _ready: Promise<void>;
+  private _ready = Promise.resolve();
   private _timeout: number;
   private _transformers: {
     [plugin: string]: {

+ 68 - 7
tests/test-coreutils/src/settingregistry.spec.ts

@@ -255,8 +255,8 @@ describe('@jupyterlab/coreutils', () => {
         connector.schemas[id] = { type: 'object' };
 
         const saved = await registry.get(id, key);
-        expect(saved.composite).to.equal(void 0);
-        expect(saved.user).to.equal(void 0);
+        expect(saved.composite).to.equal(undefined);
+        expect(saved.user).to.equal(undefined);
       });
     });
 
@@ -317,7 +317,7 @@ describe('@jupyterlab/coreutils', () => {
         connector.schemas[id] = { type: 'object', title: first };
         let settings = await registry.reload(id);
         expect(settings.schema.title).to.equal(first);
-        await Promise.resolve(void 0);
+        await Promise.resolve(undefined);
         connector.schemas[id].title = second;
         settings = await registry.reload(id);
         expect(settings.schema.title).to.equal(second);
@@ -333,6 +333,67 @@ describe('@jupyterlab/coreutils', () => {
         expect(failed).to.equal(true);
       });
     });
+
+    describe('#transform()', () => {
+      it(`should transform a plugin during the fetch phase`, async () => {
+        const id = 'foo';
+        const version = 'transform-test';
+
+        expect(Object.keys(registry.plugins)).to.be.empty;
+        connector.schemas[id] = {
+          'jupyter.lab.transform': true,
+          type: 'object'
+        };
+        registry.transform(id, {
+          fetch: plugin => {
+            plugin.version = version;
+            return plugin;
+          }
+        });
+        expect((await registry.load(id)).version).to.equal(version);
+      });
+
+      it(`should transform a plugin during the compose phase`, async () => {
+        const id = 'foo';
+        const composite = { a: 1 };
+
+        expect(Object.keys(registry.plugins)).to.be.empty;
+        connector.schemas[id] = {
+          'jupyter.lab.transform': true,
+          type: 'object'
+        };
+        registry.transform(id, {
+          compose: plugin => {
+            plugin.data = { user: plugin.data.user, composite };
+            return plugin;
+          }
+        });
+        expect((await registry.load(id)).composite).to.eql(composite);
+      });
+
+      it(`should disallow a transform that changes the plugin ID`, async () => {
+        const id = 'foo';
+        let failed = false;
+
+        expect(Object.keys(registry.plugins)).to.be.empty;
+        connector.schemas[id] = {
+          'jupyter.lab.transform': true,
+          type: 'object'
+        };
+        registry.transform(id, {
+          compose: plugin => {
+            plugin.id = 'bar';
+            return plugin;
+          }
+        });
+        try {
+          await registry.load(id);
+        } catch (e) {
+          failed = true;
+        }
+        expect(failed).to.equal(true);
+      });
+    });
   });
 
   describe('Settings', () => {
@@ -635,8 +696,8 @@ describe('@jupyterlab/coreutils', () => {
 
         settings = (await registry.load(id)) as Settings;
         const saved = settings.get(key);
-        expect(saved.composite).to.equal(void 0);
-        expect(saved.user).to.equal(void 0);
+        expect(saved.composite).to.equal(undefined);
+        expect(saved.user).to.equal(undefined);
       });
     });
 
@@ -653,8 +714,8 @@ describe('@jupyterlab/coreutils', () => {
         expect(saved.user).to.equal(value);
         await settings.remove(key);
         saved = settings.get(key);
-        expect(saved.composite).to.equal(void 0);
-        expect(saved.user).to.equal(void 0);
+        expect(saved.composite).to.equal(undefined);
+        expect(saved.user).to.equal(undefined);
       });
     });