Comparing version 1.0.0 to 1.1.0
@@ -5,2 +5,12 @@ # Change Log | ||
<a name="1.1.0"></a> | ||
# [1.1.0](https://github.com/moxystudio/js-class-is/compare/v1.0.0...v1.1.0) (2018-04-04) | ||
### Features | ||
* add `withoutNew` option ([e6b0c18](https://github.com/moxystudio/js-class-is/commit/e6b0c18)) | ||
<a name="1.0.0"></a> | ||
@@ -7,0 +17,0 @@ # [1.0.0](https://github.com/moxystudio/js-class-is/compare/v0.5.1...v1.0.0) (2018-03-30) |
12
index.js
@@ -30,8 +30,12 @@ 'use strict'; | ||
function withIsProto(Class, { className, symbolName }) { | ||
function withIsProto(Class, { className, symbolName, withoutNew }) { | ||
const symbol = Symbol.for(symbolName); | ||
/* eslint-disable object-shorthand */ | ||
const ClassIsWrapper = { | ||
/* eslint-disable object-shorthand */ | ||
[className]: function (...args) { | ||
if (withoutNew && !(this instanceof ClassIsWrapper)) { | ||
return new ClassIsWrapper(...args); | ||
} | ||
const _this = Class.call(this, ...args) || this; | ||
@@ -46,3 +50,7 @@ | ||
}[className]; | ||
/* eslint-enable object-shorthand */ | ||
ClassIsWrapper.prototype = Object.create(Class.prototype); | ||
ClassIsWrapper.prototype.constructor = ClassIsWrapper; | ||
Object.defineProperty(ClassIsWrapper.prototype, Symbol.toStringTag, { | ||
@@ -49,0 +57,0 @@ get() { |
{ | ||
"name": "class-is", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Enhances a JavaScript class by adding an is<Class> property to compare types between realms.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -53,3 +53,6 @@ # class-is | ||
module.exports = withIs(Person, { className: 'Person', symbolName: '@org/package-x/person' }); | ||
module.exports = withIs(Person, { | ||
className: 'Person', | ||
symbolName: '@org/package-x/Person', | ||
}); | ||
``` | ||
@@ -67,3 +70,6 @@ | ||
module.exports = withIs(Animal, { className: 'Animal', symbolName: '@org/package-y/animal' }); | ||
module.exports = withIs(Animal, { | ||
className: 'Animal', | ||
symbolName: '@org/package-y/Animal', | ||
}); | ||
``` | ||
@@ -98,2 +104,4 @@ | ||
} | ||
this.radius = radius; | ||
} | ||
@@ -107,17 +115,29 @@ ``` | ||
const Circle = withIs.proto(function () { | ||
const Circle = withIs.proto(function (radius) { | ||
if (!(this instanceof Circle)) { | ||
return new Circle(); | ||
} | ||
}, { className: 'Circle', symbolName: '@org/package/circle' }); | ||
const circle = Circle(); | ||
console.log(Circle.isCircle(circle)); | ||
this.radius = radius; | ||
}, { | ||
className: 'Circle', | ||
symbolName: '@org/package/Circle', | ||
}); | ||
``` | ||
The example above will print: | ||
...or even better: | ||
```js | ||
const withIs = require('class-is'); | ||
function Circle(radius) { | ||
this.radius = radius; | ||
} | ||
module.exports = withIs.proto(Circle, { | ||
className: 'Circle', | ||
symbolName: '@org/package/Circle', | ||
withoutNew: true, | ||
}); | ||
``` | ||
true | ||
``` | ||
@@ -127,3 +147,3 @@ | ||
### withIs(Class, { className: name, symbolName: symbol }) | ||
### withIs(Class, { className, symbolName }) | ||
@@ -148,9 +168,16 @@ ###### class | ||
Example: `@organization/package/class` | ||
Example: `@organization/package/Class` | ||
### withIs.proto(Class, { className: name, symbolName: symbol }) | ||
### withIs.proto(Class, { className, symbolName, withoutNew }) | ||
Apply the same parameters as above. | ||
The `className` and `symbolName` parameters are the same as above. | ||
###### withoutNew | ||
Type: `Boolean` | ||
Default: `false` | ||
Allow creating an instance without the `new` operator. | ||
## Tests | ||
@@ -157,0 +184,0 @@ |
'use strict'; | ||
const withIs = require('..'); | ||
const { | ||
Animal, | ||
Plant, | ||
Mammal, | ||
Algae, | ||
const Circle = withIs.proto(function () { | ||
if (!(this instanceof Circle)) { // eslint-disable-line no-invalid-this | ||
return new Circle(); | ||
} | ||
}, { className: 'Circle', symbolName: '@org/package/circle' }); | ||
ExplicitWithoutNew, | ||
ImplicitWithoutNew, | ||
ImplicitExplicitWithoutNew, | ||
} = require('./fixtures/es5'); | ||
const Square = withIs.proto(function () { | ||
if (!(this instanceof Square)) { // eslint-disable-line no-invalid-this | ||
return new Square(); | ||
} | ||
}, { className: 'Square', symbolName: '@org/package/square' }); | ||
it('should setup the prototype chain correctly', () => { | ||
const animal = new Animal('mammal'); | ||
const plant = new Plant('algae'); | ||
const circle = new Circle(); | ||
const square = new Square(); | ||
expect(Object.getPrototypeOf(animal)).toBe(Animal.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(animal))).toBe(Animal.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(animal)).not.toBe(Plant.prototype); | ||
expect(Object.getPrototypeOf(plant)).toBe(Plant.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(plant))).toBe(Plant.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(plant)).not.toBe(Animal.prototype); | ||
test('circle is an instance of Circle class', () => { | ||
expect(Circle.isCircle(circle)).toBe(true); | ||
}); | ||
expect(animal instanceof Animal).toBe(true); | ||
expect(animal instanceof Animal.WrappedClass).toBe(true); | ||
expect(animal instanceof Plant).toBe(false); | ||
expect(plant instanceof Plant).toBe(true); | ||
expect(plant instanceof Plant.WrappedClass).toBe(true); | ||
expect(plant instanceof Animal).toBe(false); | ||
test('square is not an instance of Circle class', () => { | ||
expect(Circle.isCircle(square)).toBe(false); | ||
expect(animal.getType()).toBe('mammal'); | ||
expect(plant.getType()).toBe('algae'); | ||
}); | ||
test('square is an instance of Square class', () => { | ||
expect(Square.isSquare(square)).toBe(true); | ||
it('should have a custom toStringTag', () => { | ||
expect(Object.prototype.toString.call(new Animal())).toBe('[object Animal]'); | ||
expect(Object.prototype.toString.call(new Plant())).toBe('[object Plant]'); | ||
}); | ||
test('circle is not an instance of Square class', () => { | ||
expect(Square.isSquare(circle)).toBe(false); | ||
}); | ||
describe('is<className> method', () => { | ||
it('should add a working is<className> static method', () => { | ||
const animal = new Animal('mammal'); | ||
const plant = new Plant('algae'); | ||
test('calling without new', () => { | ||
const circle = Circle(); // eslint-disable-line new-cap | ||
expect(Animal.isAnimal(animal)).toBe(true); | ||
expect(Animal.isAnimal(plant)).toBe(false); | ||
expect(Plant.isPlant(plant)).toBe(true); | ||
expect(Plant.isPlant(animal)).toBe(false); | ||
}); | ||
expect(Circle.isCircle(circle)).toBe(true); | ||
}); | ||
it('should not crash if `null` or `undefined` is passed to is<ClassName>', () => { | ||
expect(Animal.isAnimal(null)).toBe(false); | ||
expect(Animal.isAnimal(undefined)).toBe(false); | ||
}); | ||
test('undefined/null is not an instance of any class', () => { | ||
expect(Circle.isCircle(undefined)).toBe(false); | ||
expect(Circle.isCircle(null)).toBe(false); | ||
it('should work correctly for deep inheritance scenarios', () => { | ||
const mammal = new Mammal(); | ||
const algae = new Algae(); | ||
expect(Mammal.isMammal(mammal)).toBe(true); | ||
expect(Animal.isAnimal(mammal)).toBe(true); | ||
expect(Mammal.isMammal(algae)).toBe(false); | ||
expect(Animal.isAnimal(algae)).toBe(false); | ||
expect(Algae.isAlgae(algae)).toBe(true); | ||
expect(Plant.isPlant(algae)).toBe(true); | ||
expect(Algae.isAlgae(mammal)).toBe(false); | ||
expect(Plant.isPlant(mammal)).toBe(false); | ||
}); | ||
}); | ||
test('check custom tag of Square class', () => { | ||
expect(Object.prototype.toString.call(square)).toBe('[object Square]'); | ||
describe('new operator', () => { | ||
it('should work on explicit without-new handling', () => { | ||
const instance = new ExplicitWithoutNew(); | ||
const instance2 = ExplicitWithoutNew(); // eslint-disable-line new-cap | ||
expect(Object.getPrototypeOf(instance)).toBe(ExplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instance))).toBe(ExplicitWithoutNew.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(instance2)).toBe(ExplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instance2))).toBe(ExplicitWithoutNew.WrappedClass.prototype); | ||
expect(instance instanceof ExplicitWithoutNew).toBe(true); | ||
expect(instance instanceof ExplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instance2 instanceof ExplicitWithoutNew).toBe(true); | ||
expect(instance2 instanceof ExplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instance.getLabel()).toBe('ExplicitWithoutNew'); | ||
expect(instance2.getLabel()).toBe('ExplicitWithoutNew'); | ||
}); | ||
it('should work on implicit without-new handling', () => { | ||
const instance = new ImplicitWithoutNew(); | ||
const instanceNoNew = ImplicitWithoutNew(); // eslint-disable-line new-cap | ||
expect(Object.getPrototypeOf(instance)).toBe(ImplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instance))).toBe(ImplicitWithoutNew.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(instanceNoNew)).toBe(ImplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instanceNoNew))).toBe(ImplicitWithoutNew.WrappedClass.prototype); | ||
expect(instance instanceof ImplicitWithoutNew).toBe(true); | ||
expect(instance instanceof ImplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instanceNoNew instanceof ImplicitWithoutNew).toBe(true); | ||
expect(instanceNoNew instanceof ImplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instance.getLabel()).toBe('ImplicitWithoutNew'); | ||
expect(instanceNoNew.getLabel()).toBe('ImplicitWithoutNew'); | ||
}); | ||
it('should work on explicit & implicit without-new handling', () => { | ||
const instance = new ImplicitExplicitWithoutNew(); | ||
const instanceNoNew = ImplicitExplicitWithoutNew(); // eslint-disable-line new-cap | ||
expect(Object.getPrototypeOf(instance)).toBe(ImplicitExplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instance))).toBe(ImplicitExplicitWithoutNew.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(instanceNoNew)).toBe(ImplicitExplicitWithoutNew.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(instanceNoNew))).toBe(ImplicitExplicitWithoutNew.WrappedClass.prototype); | ||
expect(instance instanceof ImplicitExplicitWithoutNew).toBe(true); | ||
expect(instance instanceof ImplicitExplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instanceNoNew instanceof ImplicitExplicitWithoutNew).toBe(true); | ||
expect(instanceNoNew instanceof ImplicitExplicitWithoutNew.WrappedClass).toBe(true); | ||
expect(instance.getLabel()).toBe('ImplicitExplicitWithoutNew'); | ||
expect(instanceNoNew.getLabel()).toBe('ImplicitExplicitWithoutNew'); | ||
}); | ||
}); |
'use strict'; | ||
const withIs = require('..'); | ||
const { | ||
Animal, | ||
Plant, | ||
Mammal, | ||
Algae, | ||
} = require('./fixtures/es6'); | ||
const Person = withIs(class { | ||
constructor(name, city) { | ||
this.name = name; | ||
this.city = city; | ||
} | ||
}, { className: 'Person', symbolName: '@org/package-x/person' }); | ||
it('should setup the prototype chain correctly', () => { | ||
const animal = new Animal('mammal'); | ||
const plant = new Plant('algae'); | ||
const Animal = withIs(class { | ||
constructor(species) { | ||
this.species = species; | ||
} | ||
}, { className: 'Animal', symbolName: '@org/package-y/person' }); | ||
expect(Object.getPrototypeOf(animal)).toBe(Animal.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(animal))).toBe(Animal.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(animal)).not.toBe(Plant.prototype); | ||
expect(Object.getPrototypeOf(plant)).toBe(Plant.prototype); | ||
expect(Object.getPrototypeOf(Object.getPrototypeOf(plant))).toBe(Plant.WrappedClass.prototype); | ||
expect(Object.getPrototypeOf(plant)).not.toBe(Animal.prototype); | ||
const diogo = new Person('Diogo', 'Porto'); | ||
const wolf = new Animal('Wolf'); | ||
expect(animal instanceof Animal).toBe(true); | ||
expect(animal instanceof Animal.WrappedClass).toBe(true); | ||
expect(animal instanceof Plant).toBe(false); | ||
expect(plant instanceof Plant).toBe(true); | ||
expect(plant instanceof Plant.WrappedClass).toBe(true); | ||
expect(plant instanceof Animal).toBe(false); | ||
test('person is an instance of Person class', () => { | ||
expect(Person.isPerson(diogo)).toBe(true); | ||
expect(animal.getType()).toBe('mammal'); | ||
expect(plant.getType()).toBe('algae'); | ||
}); | ||
test('wolf is not an instance of Person class', () => { | ||
expect(Person.isPerson(wolf)).toBe(false); | ||
it('should have a custom toStringTag', () => { | ||
expect(Object.prototype.toString.call(new Animal())).toBe('[object Animal]'); | ||
expect(Object.prototype.toString.call(new Plant())).toBe('[object Plant]'); | ||
}); | ||
test('wolf is an instance of Animal class', () => { | ||
expect(Animal.isAnimal(wolf)).toBe(true); | ||
}); | ||
describe('is<className> method', () => { | ||
it('should add a working is<className> static method', () => { | ||
const animal = new Animal('mammal'); | ||
const plant = new Plant('algae'); | ||
test('person is not an instance of Animal class', () => { | ||
expect(Animal.isAnimal(diogo)).toBe(false); | ||
}); | ||
expect(Animal.isAnimal(animal)).toBe(true); | ||
expect(Animal.isAnimal(plant)).toBe(false); | ||
expect(Plant.isPlant(plant)).toBe(true); | ||
expect(Plant.isPlant(animal)).toBe(false); | ||
}); | ||
test('undefined/null is not an instance of any class', () => { | ||
expect(Person.isPerson(undefined)).toBe(false); | ||
expect(Person.isPerson(null)).toBe(false); | ||
}); | ||
it('should not crash if `null` or `undefined` is passed to is<ClassName>', () => { | ||
expect(Animal.isAnimal(null)).toBe(false); | ||
expect(Animal.isAnimal(undefined)).toBe(false); | ||
}); | ||
test('check custom tag of class', () => { | ||
expect(Object.prototype.toString.call(diogo)).toBe('[object Person]'); | ||
expect(Object.prototype.toString.call(wolf)).toBe('[object Animal]'); | ||
it('should work correctly for deep inheritance scenarios', () => { | ||
const mammal = new Mammal(); | ||
const algae = new Algae(); | ||
expect(Mammal.isMammal(mammal)).toBe(true); | ||
expect(Animal.isAnimal(mammal)).toBe(true); | ||
expect(Mammal.isMammal(algae)).toBe(false); | ||
expect(Animal.isAnimal(algae)).toBe(false); | ||
expect(Algae.isAlgae(algae)).toBe(true); | ||
expect(Plant.isPlant(algae)).toBe(true); | ||
expect(Algae.isAlgae(mammal)).toBe(false); | ||
expect(Plant.isPlant(mammal)).toBe(false); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25299
247709
24
391
186
1