Skip to content

Commit

Permalink
fix(features): unary negation of null flag interpreted as boolean fal…
Browse files Browse the repository at this point in the history
…se (#1683)

* test: refactor prod/non-prod tests into separate files

* fix: avoid changing null value to boolean true

* refactor: simplify by untangling prod/non-prod code paths
  • Loading branch information
ekashida authored Jan 21, 2020
1 parent 1653393 commit dc7c1bd
Show file tree
Hide file tree
Showing 3 changed files with 537 additions and 332 deletions.
296 changes: 296 additions & 0 deletions packages/@lwc/features/src/__tests__/flags-prod.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
/*
* Copyright (c) 2018, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
const { default: pluginTester } = require('babel-plugin-tester');
const plugin = require('../babel-plugin');

const babelOptions = {
babelrc: false,
configFile: false,
};

pluginTester({
title: 'prod environments',
plugin,
pluginOptions: {
featureFlags: {
ENABLE_FEATURE_TRUE: true,
ENABLE_FEATURE_FALSE: false,
ENABLE_FEATURE_NULL: null,
},
prod: true,
},
babelOptions,
tests: {
'should transform null compile-time flags into null runtime flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_NULL) {
console.log('features.ENABLE_FEATURE_NULL');
}
if (!features.ENABLE_FEATURE_NULL) {
console.log('!features.ENABLE_FEATURE_NULL');
}
`,
output: `
import features, { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('features.ENABLE_FEATURE_NULL');
}
if (!runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('!features.ENABLE_FEATURE_NULL');
}
`,
},
'should not transform null runtime flags': {
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('runtimeFlags.ENABLE_FEATURE_NULL');
}
if (!runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('!runtimeFlags.ENABLE_FEATURE_NULL');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('runtimeFlags.ENABLE_FEATURE_NULL');
}
if (!runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('!runtimeFlags.ENABLE_FEATURE_NULL');
}
`,
},
'should transform boolean-true compile-time flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_TRUE) {
console.log('features.ENABLE_FEATURE_TRUE');
}
if (!features.ENABLE_FEATURE_TRUE) {
console.log('!features.ENABLE_FEATURE_TRUE');
}
`,
output: `
import features, { runtimeFlags } from '@lwc/features';
{
console.log('features.ENABLE_FEATURE_TRUE');
}
`,
},
'should transform boolean-true runtime flags': {
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
if (!runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('!runtimeFlags.ENABLE_FEATURE_TRUE');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
{
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
`,
},
'should transform boolean-false compile-time flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_FALSE) {
console.log('features.ENABLE_FEATURE_FALSE');
}
if (!features.ENABLE_FEATURE_FALSE) {
console.log('!features.ENABLE_FEATURE_FALSE');
}
`,
output: `
import features, { runtimeFlags } from '@lwc/features';
{
console.log('!features.ENABLE_FEATURE_FALSE');
}
`,
},
'should transform boolean-false runtime flags': {
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('runtimeFlags.ENABLE_FEATURE_FALSE');
}
if (!runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('!runtimeFlags.ENABLE_FEATURE_FALSE');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
{
console.log('!runtimeFlags.ENABLE_FEATURE_FALSE');
}
`,
},
'should not transform if-tests that are not member expressions (compile-time)': {
code: `
import FEATURES from '@lwc/features';
if (isTrue(FEATURES.ENABLE_FEATURE_TRUE)) {
console.log('isTrue(ENABLE_FEATURE_TRUE)');
}
`,
output: `
import FEATURES, { runtimeFlags } from '@lwc/features';
if (isTrue(FEATURES.ENABLE_FEATURE_TRUE)) {
console.log('isTrue(ENABLE_FEATURE_TRUE)');
}
`,
},
'should not transform if-tests that are not member expressions (runtime)': {
code: `
import { runtimeFlags } from '@lwc/features';
if (isTrue(runtimeFlags.ENABLE_FEATURE_TRUE)) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
if (isTrue(runtimeFlags.ENABLE_FEATURE_TRUE)) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
`,
},
'should not transform feature flags when used with a ternary operator': {
code: `
import feats from '@lwc/features';
console.log(feats.ENABLE_FEATURE_NULL ? 'foo' : 'bar');
`,
output: `
import feats, { runtimeFlags } from '@lwc/features';
console.log(feats.ENABLE_FEATURE_NULL ? 'foo' : 'bar');
`,
},
'should throw an error if the flag is undefined': {
error: 'Invalid feature flag "ENABLE_THE_BEER". Flag is undefined.',
code: `
import featureFlags from '@lwc/features';
if (featureFlags.ENABLE_THE_BEER) {
console.log('featureFlags.ENABLE_THE_BEER');
}
`,
},
'should throw an error if the flag name is formatted incorrectly': {
error:
'Invalid feature flag "enable_the_beer". Flag name must only be composed of uppercase letters and underscores.',
code: `
import featureFlags from '@lwc/features';
if (featureFlags.enable_the_beer) {
console.log('featureFlags.enable_the_beer');
}
`,
},
'should transform nested feature flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_NULL) {
if (features.ENABLE_FEATURE_TRUE) {
console.log('nested feature flags sounds like a vary bad idea');
}
}
if (features.ENABLE_FEATURE_TRUE) {
if (features.ENABLE_FEATURE_NULL) {
console.log('nested feature flags sounds like a vary bad idea');
}
}
`,
output: `
import features, { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_NULL) {
{
console.log('nested feature flags sounds like a vary bad idea');
}
}
{
if (runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('nested feature flags sounds like a vary bad idea');
}
}
`,
},
'should not transform tests that are not an actual reference to the imported binding': {
code: `
import featureFlag from '@lwc/features';
function awesome() {
const featureFlag = { ENABLE_FEATURE_FALSE: false };
if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}
if (!featureFlag.ENABLE_FEATURE_FALSE) {
console.log('!featureFlag.ENABLE_FEATURE_FALSE');
}
}
`,
output: `
import featureFlag, { runtimeFlags } from '@lwc/features';
function awesome() {
const featureFlag = {
ENABLE_FEATURE_FALSE: false,
};
if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}
if (!featureFlag.ENABLE_FEATURE_FALSE) {
console.log('!featureFlag.ENABLE_FEATURE_FALSE');
}
}
`,
},
'should not transform member expressions that are not runtime flag lookups': {
code: `
import { runtimeFlags } from '@lwc/features';
if (churroteria.ENABLE_FEATURE_TRUE) {
console.log('churroteria.ENABLE_FEATURE_TRUE');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
if (churroteria.ENABLE_FEATURE_TRUE) {
console.log('churroteria.ENABLE_FEATURE_TRUE');
}
`,
},
},
});
Loading

0 comments on commit dc7c1bd

Please sign in to comment.