From f639763cc217454deb1e75ffbce266b01248db2e Mon Sep 17 00:00:00 2001 From: Krist Wongsuphasawat Date: Wed, 14 Nov 2018 10:50:56 -0800 Subject: [PATCH] Add ExtensibleFunction class (#32) --- .../packages/superset-ui-core/src/index.js | 1 + .../src/models/ExtensibleFunction.js | 9 ++++ .../superset-ui-core/test/index.test.js | 2 + .../test/models/ExtensibleFunction.test.js | 52 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/models/ExtensibleFunction.js create mode 100644 superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/models/ExtensibleFunction.test.js diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/index.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/index.js index 20e2bc2d84dd1..39308e8e73c07 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/index.js +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/index.js @@ -1,3 +1,4 @@ +export { default as ExtensibleFunction } from './models/ExtensibleFunction'; export { default as Plugin } from './models/Plugin'; export { default as Preset } from './models/Preset'; export { default as Registry } from './models/Registry'; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/models/ExtensibleFunction.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/models/ExtensibleFunction.js new file mode 100644 index 0000000000000..f987638c0e9fc --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/src/models/ExtensibleFunction.js @@ -0,0 +1,9 @@ +/** + * From https://stackoverflow.com/questions/36871299/how-to-extend-function-with-es6-classes + */ + +export default class ExtensibleFunction extends Function { + constructor(fn) { + return Object.setPrototypeOf(fn, new.target.prototype); + } +} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/index.test.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/index.test.js index 5e382d2981479..4e98e9ad36f95 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/index.test.js +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/index.test.js @@ -1,4 +1,5 @@ import { + ExtensibleFunction, Plugin, Preset, Registry, @@ -12,6 +13,7 @@ import { describe('index', () => { it('exports modules', () => { [ + ExtensibleFunction, Plugin, Preset, Registry, diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/models/ExtensibleFunction.test.js b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/models/ExtensibleFunction.test.js new file mode 100644 index 0000000000000..6bf79fedd2227 --- /dev/null +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-core/test/models/ExtensibleFunction.test.js @@ -0,0 +1,52 @@ +import ExtensibleFunction from '../../src/models/ExtensibleFunction'; + +describe('ExtensibleFunction', () => { + class Func1 extends ExtensibleFunction { + constructor(x) { + super(() => x); // closure + } + } + class Func2 extends ExtensibleFunction { + constructor(x) { + super(() => this.x); // arrow function, refer to its own field + this.x = x; + } + + hi() { + return 'hi'; + } + } + class Func3 extends ExtensibleFunction { + constructor(x) { + super(function customName() { + return customName.x; + }); // named function + this.x = x; + } + } + + it('its subclass is an instance of Function', () => { + expect(Func1).toBeInstanceOf(Function); + expect(Func2).toBeInstanceOf(Function); + expect(Func3).toBeInstanceOf(Function); + }); + + const func1 = new Func1(100); + const func2 = new Func2(100); + const func3 = new Func3(100); + + it('an instance of its subclass is executable like regular function', () => { + expect(func1()).toEqual(100); + expect(func2()).toEqual(100); + expect(func3()).toEqual(100); + }); + + it('its subclass behaves like regular class with its own fields and functions', () => { + expect(func2.x).toEqual(100); + expect(func2.hi()).toEqual('hi'); + }); + + it('its subclass can set name by passing named function to its constructor', () => { + expect(func3.name).toEqual('customName'); + }); +});