Skip to content
Permalink
Browse files

Fix: Validate target prop only if browserlist configuration exists

Fix #3388
Close #3415
  • Loading branch information
sarvaje authored and molant committed Dec 4, 2019
1 parent 68f7878 commit 1b55e3e130f5e5a457460a3d8b37efa3c2e47d5c
@@ -3,9 +3,11 @@
* in the TypeScript configuration file (i.e `tsconfig.json`) not optimized for the defined
* `browserslist` values.
*/
import * as path from 'path';

import { HintContext, IHint } from 'hint';
import { Severity } from '@hint/utils-types';
import { findPackageRoot } from '@hint/utils';
import { TypeScriptConfigEvents, TypeScriptConfigParse } from '@hint/parser-typescript-config';

import meta from './meta/target';
@@ -227,10 +229,44 @@ export default class TypeScriptConfigTarget implements IHint {
return maxVersion;
};

const browserslistConfigExists = (): boolean => {
let browserslistFolder: string | null;

try {
browserslistFolder = findPackageRoot(__dirname, '.browserslistrc');
} catch (e) {
browserslistFolder = null;
}

if (browserslistFolder) {
return true;
}

let packageJsonFolder: string | null;

try {
packageJsonFolder = findPackageRoot(__dirname, 'package.json');
} catch (e) {
packageJsonFolder = null;
}

if (packageJsonFolder) {
const packageJson = require(path.join(packageJsonFolder, 'package.json'));

return !!packageJson.browserslist;
}

return false;
};

const validate = (evt: TypeScriptConfigParse) => {
const { config, getLocation, mergedConfig, originalConfig, resource } = evt;
const { targetedBrowsers } = context;

if (!browserslistConfigExists()) {
return;
}

const target = normalizeScriptTarget(config.compilerOptions.target as any);
const minimumBrowsers = toMiniumBrowser(targetedBrowsers);
const messageName = 'target';
@@ -0,0 +1,6 @@
{
"browserslist": [
"defaults",
"maintained node versions"
]
}
@@ -1,7 +1,9 @@
import * as path from 'path';

import * as mock from 'mock-require';
import { getHintPath, HintLocalTest, testLocalHint } from '@hint/utils-tests-helpers';
import { Severity } from '@hint/utils-types';
import * as utils from '@hint/utils';

const hintPath = getHintPath(__filename, true);

@@ -31,11 +33,25 @@ const paths = [

const tests: TestWithBrowserInfo[] = [
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 8', 'IE 9', 'Edge 15', 'Edge 16', 'Chrome 63', 'Chrome 60', 'android 4.4.3-4.4.4', 'Safari 10.1', 'Safari 10.0'],
name: 'Configuration with "compilerOptions.target = es3" and old browsers should pass',
path: paths.es3
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: 'Configuration with "compilerOptions.target = es3" and modern browsers should fail',
path: paths.es3,
@@ -48,16 +64,37 @@ const tests: TestWithBrowserInfo[] = [
]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 9', 'Edge 15', 'Chrome 63'],
name: 'Configuration with "compilerOptions.target = es5" and minimum browsers should pass',
path: paths.es5
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: 'Configuration with "compilerOptions.target = es2016" and modern browsers should pass',
path: paths.es2016
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 8', 'Edge 15', 'Chrome 63'],
name: 'Configuration with "compilerOptions.target = es2016" and old browsers should fail',
path: paths.es2016,
@@ -70,6 +107,13 @@ const tests: TestWithBrowserInfo[] = [
]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: 'Configuration with "compilerOptions.target = esnext" and not very old browsers should fail',
path: paths.esnext,
@@ -82,11 +126,25 @@ const tests: TestWithBrowserInfo[] = [
]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 8', 'Edge 15', 'Chrome 63'],
name: 'Configuration with no "compilerOptions.target" and old browsers should pass',
path: paths['no-target']
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with no "compilerOptions.target" and modern browsers shouldn't pass`,
path: paths['no-target'],
@@ -98,11 +156,25 @@ const tests: TestWithBrowserInfo[] = [
}]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 8', 'Edge 15', 'Chrome 63'],
name: 'Configuration with no "compilerOptions.target" in extended file and old browsers should pass',
path: paths['no-target-extends']
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with no "compilerOptions.target" in extended file and modern browsers shouldn't pass`,
path: paths['no-target-extends'],
@@ -114,6 +186,13 @@ const tests: TestWithBrowserInfo[] = [
}]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with "compilerOptions.target" in extended file and modern browsers shouldn't pass`,
path: paths['no-target-extends-target'],
@@ -125,11 +204,25 @@ const tests: TestWithBrowserInfo[] = [
}]
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and modern browsers should pass`,
path: paths.extends
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and target es3 should fail`,
path: paths['extends-overrides'],
@@ -142,6 +235,64 @@ const tests: TestWithBrowserInfo[] = [
]
},
{
before() {
(utils as any).findPackageRoot = (dirname: string, fileToFind: string) => {
if (fileToFind === 'package.json') {
return path.join(__dirname, 'fixtures', 'target', 'config-package-json');
}

throw new Error('Package not found');
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and target es3 should fail if browserlist is found in package.json`,
path: paths['extends-overrides'],
reports: [
{
message: `Based on your browser configuration your "compilerOptions.target" should be "ES2016". Current one is "ES3"`,
position: { match: '"es3"' },
severity: Severity.warning
}
]
},
{
before() {
(utils as any).findPackageRoot = (dirname: string, fileToFind: string) => {
if (fileToFind === 'package.json') {
return path.join(__dirname, 'fixtures', 'target', 'no-config-package-json');
}

throw new Error('Package not found');
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and target es3 should pass if browserlist configuration is not found in package.json`,
path: paths['extends-overrides']
},
{
before() {
(utils as any).findPackageRoot = (dirname: string, fileToFind: string) => {
throw new Error('Package not found');
};

mock('@hint/utils', utils);
},
browserslist: ['Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and target es3 should pass if browserlist configuration is not found`,
path: paths['extends-overrides']
},
{
before() {
(utils as any).findPackageRoot = () => {
return 'folder';
};

mock('@hint/utils', utils);
},
browserslist: ['IE 8', 'Edge 15', 'Chrome 63'],
name: `Configuration with extends pointing to ES2016 and old browsers should fail`,
path: paths.extends,
@@ -157,13 +308,15 @@ const tests: TestWithBrowserInfo[] = [

tests.forEach((info: TestWithBrowserInfo) => {
const test: HintLocalTest = {
before: info.before,
name: info.name,
path: info.path,
reports: info.reports
};

testLocalHint(hintPath, [test], {
browserslist: info.browserslist,
parsers: ['typescript-config']
parsers: ['typescript-config'],
serial: true
});
});
@@ -14,7 +14,6 @@
],
"references": [
{ "path": "../hint" },
{ "path": "../utils-debug" },
{ "path": "../utils-fs" },
{ "path": "../utils-json" },
{ "path": "../utils-network" }

0 comments on commit 1b55e3e

Please sign in to comment.
You can’t perform that action at this time.