You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
529 lines
14 KiB
529 lines
14 KiB
/* eslint-env mocha */ |
|
/* eslint no-template-curly-in-string: 0 */ |
|
import assert from 'assert'; |
|
import { |
|
extractProp, |
|
describeIfNotBabylon, |
|
changePlugins, |
|
setParserName, |
|
} from '../helper'; |
|
import { getLiteralPropValue } from '../../src/getPropValue'; |
|
|
|
describe('getLiteralPropValue', () => { |
|
beforeEach(() => { |
|
setParserName('babel'); |
|
}); |
|
it('should export a function', () => { |
|
const expected = 'function'; |
|
const actual = typeof getLiteralPropValue; |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return undefined when not provided with a JSXAttribute', () => { |
|
const expected = undefined; |
|
const actual = getLiteralPropValue(1); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should not throw error when trying to get value from unknown node type', () => { |
|
const prop = { |
|
type: 'JSXAttribute', |
|
value: { |
|
type: 'JSXExpressionContainer', |
|
}, |
|
}; |
|
let counter = 0; |
|
// eslint-disable-next-line no-console |
|
const errorOrig = console.error; |
|
// eslint-disable-next-line no-console |
|
console.error = () => { |
|
counter += 1; |
|
}; |
|
let value; |
|
assert.doesNotThrow(() => { |
|
value = getLiteralPropValue(prop); |
|
}, Error); |
|
|
|
assert.equal(null, value); |
|
assert.equal(counter, 1); |
|
// eslint-disable-next-line no-console |
|
console.error = errorOrig; |
|
}); |
|
|
|
describe('Null', () => { |
|
it('should return true when no value is given', () => { |
|
const prop = extractProp('<div foo />'); |
|
|
|
const expected = true; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Literal', () => { |
|
it('should return correct string if value is a string', () => { |
|
const prop = extractProp('<div foo="bar" />'); |
|
|
|
const expected = 'bar'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return correct string if value is a string expression', () => { |
|
const prop = extractProp('<div foo={"bar"} />'); |
|
|
|
const expected = 'bar'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return correct integer if value is a integer expression', () => { |
|
const prop = extractProp('<div foo={1} />'); |
|
|
|
const expected = 1; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should convert "true" to boolean type', () => { |
|
const prop = extractProp('<div foo="true" />'); |
|
|
|
const expected = true; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should convert "TrUE" to boolean type', () => { |
|
const prop = extractProp('<div foo="TrUE" />'); |
|
|
|
const expected = true; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should convert "false" to boolean type', () => { |
|
const prop = extractProp('<div foo="false" />'); |
|
|
|
const expected = false; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should convert "FaLsE" to boolean type', () => { |
|
const prop = extractProp('<div foo="FaLsE" />'); |
|
|
|
const expected = false; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return String null when value is null', () => { |
|
const prop = extractProp('<div foo={null} />'); |
|
|
|
const expected = 'null'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('JSXElement', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={<bar />} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Identifier', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={bar} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return undefined when identifier is literally `undefined`', () => { |
|
const prop = extractProp('<div foo={undefined} />'); |
|
|
|
const expected = undefined; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Template literal', () => { |
|
it('should return template literal with vars wrapped in curly braces', () => { |
|
const prop = extractProp('<div foo={`bar ${baz}`} />'); |
|
|
|
const expected = 'bar {baz}'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return string "undefined" for expressions that evaluate to undefined', () => { |
|
const prop = extractProp('<div foo={`bar ${undefined}`} />'); |
|
|
|
const expected = 'bar undefined'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Tagged Template literal', () => { |
|
it('should return template literal with vars wrapped in curly braces', () => { |
|
const prop = extractProp('<div foo={noop`bar ${baz}`} />'); |
|
|
|
const expected = 'bar {baz}'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return string "undefined" for expressions that evaluate to undefined', () => { |
|
const prop = extractProp('<div foo={noop`bar ${undefined}`} />'); |
|
|
|
const expected = 'bar undefined'; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Arrow function expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={ () => { return "bar"; }} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Function expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={ function() { return "bar"; } } />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Logical expression', () => { |
|
it('should return null for && operator', () => { |
|
const prop = extractProp('<div foo={bar && baz} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return null for || operator', () => { |
|
const prop = extractProp('<div foo={bar || baz} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Member expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={bar.baz} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Call expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={bar()} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Unary expression', () => { |
|
it('should correctly evaluate an expression that prefixes with -', () => { |
|
const prop = extractProp('<div foo={-bar} />'); |
|
|
|
// -"bar" => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with -', () => { |
|
const prop = extractProp('<div foo={-42} />'); |
|
|
|
const expected = -42; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with +', () => { |
|
const prop = extractProp('<div foo={+bar} />'); |
|
|
|
// +"bar" => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with +', () => { |
|
const prop = extractProp('<div foo={+42} />'); |
|
|
|
const expected = 42; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with !', () => { |
|
const prop = extractProp('<div foo={!bar} />'); |
|
|
|
const expected = false; // !"bar" === false |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with ~', () => { |
|
const prop = extractProp('<div foo={~bar} />'); |
|
|
|
const expected = -1; // ~"bar" === -1 |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return true when evaluating `delete foo`', () => { |
|
const prop = extractProp('<div foo={delete x} />'); |
|
|
|
const expected = true; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return undefined when evaluating `void foo`', () => { |
|
const prop = extractProp('<div foo={void x} />'); |
|
|
|
const expected = undefined; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
// TODO: We should fix this to check to see if we can evaluate it. |
|
it('should return undefined when evaluating `typeof foo`', () => { |
|
const prop = extractProp('<div foo={typeof x} />'); |
|
|
|
const expected = undefined; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Update expression', () => { |
|
it('should correctly evaluate an expression that prefixes with ++', () => { |
|
const prop = extractProp('<div foo={++bar} />'); |
|
|
|
// ++"bar" => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that prefixes with --', () => { |
|
const prop = extractProp('<div foo={--bar} />'); |
|
|
|
// --"bar" => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that suffixes with ++', () => { |
|
const prop = extractProp('<div foo={bar++} />'); |
|
|
|
// "bar"++ => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should correctly evaluate an expression that suffixes with --', () => { |
|
const prop = extractProp('<div foo={bar--} />'); |
|
|
|
// "bar"-- => NaN |
|
const expected = true; |
|
const actual = Number.isNaN(getLiteralPropValue(prop)); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('This expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={this} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Conditional expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={bar ? baz : bam} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Binary expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={1 == "1"} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Object expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={ { bar: "baz" } } />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.deepEqual(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('New expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={new Bar()} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.deepEqual(actual, expected); |
|
}); |
|
}); |
|
|
|
describe('Array expression', () => { |
|
it('should evaluate to correct representation of the the array in props', () => { |
|
const prop = extractProp('<div foo={["bar", 42, null]} />'); |
|
|
|
const expected = ['bar', 42]; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.deepEqual(actual, expected); |
|
}); |
|
}); |
|
|
|
it('should return an empty array provided an empty array in props', () => { |
|
const prop = extractProp('<div foo={[]} />'); |
|
|
|
const expected = []; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.deepEqual(actual, expected); |
|
}); |
|
|
|
describe('Bind expression', () => { |
|
it('should return null', () => { |
|
const prop = extractProp('<div foo={::this.handleClick} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.deepEqual(actual, expected); |
|
}); |
|
}); |
|
|
|
describeIfNotBabylon('Typescript', () => { |
|
beforeEach(() => { |
|
changePlugins((pls) => [...pls, 'typescript']); |
|
}); |
|
|
|
it('should return string representation of variable identifier wrapped in a Typescript non-null assertion', () => { |
|
const prop = extractProp('<div foo={bar!} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return string representation of variable identifier wrapped in a deep Typescript non-null assertion', () => { |
|
const prop = extractProp('<div foo={(bar!)!} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should return string representation of variable identifier wrapped in a Typescript type coercion', () => { |
|
changePlugins((pls) => [...pls, 'typescript']); |
|
const prop = extractProp('<div foo={bar as any} />'); |
|
|
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
|
|
assert.equal(actual, expected); |
|
}); |
|
|
|
it('should work with a this.props value', () => { |
|
const prop = extractProp('<a href={this.props.href!}>Download</a>'); |
|
const expected = null; |
|
const actual = getLiteralPropValue(prop); |
|
assert.equal(actual, expected); |
|
}); |
|
}); |
|
});
|
|
|