Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(features): add support for unary negation #1562

Merged
merged 6 commits into from
Oct 10, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 117 additions & 48 deletions packages/@lwc/features/src/__tests__/flags.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,69 @@ const nonProdTests = {
code: `
import featureFlags from '@lwc/features';
if (featureFlags.ENABLE_FEATURE_TRUE) {
console.log('ENABLE_FEATURE_TRUE');
console.log('featureFlags.ENABLE_FEATURE_TRUE');
}
if (!featureFlags.ENABLE_FEATURE_TRUE) {
console.log('!featureFlags.ENABLE_FEATURE_TRUE');
}
`,
output: `
import featureFlags, { runtimeFlags } from '@lwc/features';

if (runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('ENABLE_FEATURE_TRUE');
console.log('featureFlags.ENABLE_FEATURE_TRUE');
}

if (!runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('!featureFlags.ENABLE_FEATURE_TRUE');
}
`,
},
'should transform boolean-false feature flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_FALSE) {
console.log('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';

if (runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('features.ENABLE_FEATURE_FALSE');
}

if (!runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('!features.ENABLE_FEATURE_FALSE');
}
`,
},
'should transform null feature flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_NULL) {
console.log('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('ENABLE_FEATURE_NULL');
console.log('features.ENABLE_FEATURE_NULL');
}

if (!runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('!features.ENABLE_FEATURE_NULL');
}
`,
},
'should not transform feature flags unless the if-test is a simple member expression': {
'should not transform tests that are not a member expression or not a negated member expression (compile time)': {
code: `
import FEATURES from '@lwc/features';
if (FEATURES.ENABLE_FEATURE_NULL === null) {
Expand All @@ -62,9 +83,6 @@ const nonProdTests = {
if (isTrue(FEATURES.ENABLE_FEATURE_TRUE)) {
console.log('isTrue(ENABLE_FEATURE_TRUE)');
}
if (!FEATURES.ENABLE_FEATURE_FALSE) {
console.log('!ENABLE_FEATURE_FALSE');
}
`,
output: `
import FEATURES, { runtimeFlags } from '@lwc/features';
Expand All @@ -76,30 +94,29 @@ const nonProdTests = {
if (isTrue(FEATURES.ENABLE_FEATURE_TRUE)) {
console.log('isTrue(ENABLE_FEATURE_TRUE)');
}

if (!FEATURES.ENABLE_FEATURE_FALSE) {
console.log('!ENABLE_FEATURE_FALSE');
}
`,
},
'should not transform tests that are not an actual reference to the imported binding': {
code: `
import featureFlag from '@lwc/features';
if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}
function awesome() {
const featureFlag = { ENABLE_FEATURE_FALSE: false };
if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('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';

if (runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}

function awesome() {
Expand All @@ -108,7 +125,11 @@ const nonProdTests = {
};

if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}

if (!featureFlag.ENABLE_FEATURE_FALSE) {
console.log('!featureFlag.ENABLE_FEATURE_FALSE');
}
}
`,
Expand All @@ -130,6 +151,9 @@ const nonProdTests = {
if (featureFlags.ENABLE_FEATURE_TRUE) {
console.log('this looks like a bad idea');
}
if (!featureFlags.ENABLE_FEATURE_TRUE) {
console.log('this looks like a bad idea');
}
}
`,
output: `
Expand All @@ -139,6 +163,29 @@ const nonProdTests = {
if (runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('this looks like a bad idea');
}

if (!runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('this looks like a bad idea');
}
}
`,
},
'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.',
ekashida marked this conversation as resolved.
Show resolved Hide resolved
code: `
import featureFlags from '@lwc/features';
if (featureFlags.enable_the_beer) {
console.log('featureFlags.enable_the_beer');
}
`,
},
Expand All @@ -148,7 +195,6 @@ const featureFlags = {
ENABLE_FEATURE_TRUE: true,
ENABLE_FEATURE_FALSE: false,
ENABLE_FEATURE_NULL: null,
invalidFeatureFlag: true, // invalid because it's not all uppercase
};

const babelOptions = {
Expand All @@ -163,7 +209,19 @@ pluginTester({
featureFlags,
},
babelOptions,
tests: nonProdTests,
tests: {
...nonProdTests,
'should throw an error if runtime flags are manually introduced': {
error:
'Runtime flags should never be used directly and should only be added by the compiler.',
ekashida marked this conversation as resolved.
Show resolved Hide resolved
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
`,
},
},
});

// These tests override corresponding tests in nonProdTests since the plugin has
Expand All @@ -173,25 +231,34 @@ const nonProdTestOverrides = {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_TRUE) {
console.log('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('ENABLE_FEATURE_TRUE');
console.log('features.ENABLE_FEATURE_TRUE');
}
`,
},
'should transform boolean-false feature flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_FALSE) {
console.log('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 nested feature flags': {
Expand Down Expand Up @@ -233,7 +300,10 @@ const nonProdTestOverrides = {
function awesome() {
const featureFlag = { ENABLE_FEATURE_FALSE: false };
if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}
if (!featureFlag.ENABLE_FEATURE_FALSE) {
console.log('!featureFlag.ENABLE_FEATURE_FALSE');
}
}
`,
Expand All @@ -246,7 +316,11 @@ const nonProdTestOverrides = {
};

if (featureFlag.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('featureFlag.ENABLE_FEATURE_FALSE');
}

if (!featureFlag.ENABLE_FEATURE_FALSE) {
console.log('!featureFlag.ENABLE_FEATURE_FALSE');
}
}
`,
Expand All @@ -261,33 +335,36 @@ pluginTester({
prod: true,
},
babelOptions,
tests: Object.assign({}, nonProdTests, nonProdTestOverrides, {
tests: {
...nonProdTests,
...nonProdTestOverrides,
'should transform both boolean and null feature flags': {
code: `
import features from '@lwc/features';
if (features.ENABLE_FEATURE_TRUE) {
console.log('ENABLE_FEATURE_TRUE');
console.log('features.ENABLE_FEATURE_TRUE');
}
if (features.ENABLE_FEATURE_FALSE) {
console.log('ENABLE_FEATURE_FALSE');
console.log('features.ENABLE_FEATURE_FALSE');
}
if (features.ENABLE_FEATURE_NULL) {
console.log('ENABLE_FEATURE_NULL');
console.log('features.ENABLE_FEATURE_NULL');
}
`,
output: `
import features, { runtimeFlags } from '@lwc/features';
{
console.log('ENABLE_FEATURE_TRUE');
console.log('features.ENABLE_FEATURE_TRUE');
}

if (runtimeFlags.ENABLE_FEATURE_NULL) {
console.log('ENABLE_FEATURE_NULL');
console.log('features.ENABLE_FEATURE_NULL');
}
`,
},
'should transform runtime flag lookups into compile-time flags': {
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_TRUE) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
Expand All @@ -299,6 +376,7 @@ pluginTester({
}
`,
output: `
import { runtimeFlags } from '@lwc/features';
{
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
Expand All @@ -308,51 +386,42 @@ pluginTester({
}
`,
},
'should not transform runtime flag lookups unless the if-test is a member expression': {
'should not transform tests that are not a member expression or not a negated member expression (runtime)': {
code: `
import { runtimeFlags } from '@lwc/features';
if (runtimeFlags.ENABLE_FEATURE_NULL === null) {
console.log('runtimeFlags.ENABLE_FEATURE_NULL === null');
}
if (isTrue(runtimeFlags.ENABLE_FEATURE_TRUE)) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}
if (!runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('!runtimeFlags.ENABLE_FEATURE_FALSE');
}
`,
output: `
import { runtimeFlags } from '@lwc/features';

if (runtimeFlags.ENABLE_FEATURE_NULL === null) {
console.log('runtimeFlags.ENABLE_FEATURE_NULL === null');
}

if (isTrue(runtimeFlags.ENABLE_FEATURE_TRUE)) {
console.log('runtimeFlags.ENABLE_FEATURE_TRUE');
}

if (!runtimeFlags.ENABLE_FEATURE_FALSE) {
console.log('!runtimeFlags.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');
}
`,
},
'should not transform runtime flags when used with a ternary operator': {
code: `
console.log(runtimeFlags.ENABLE_FEATURE_NULL ? 'foo' : 'bar');
`,
output: `
console.log(runtimeFlags.ENABLE_FEATURE_NULL ? 'foo' : 'bar');
`,
},
}),
},
});
Loading