Skip to content

Commit

Permalink
fix alias import linting
Browse files Browse the repository at this point in the history
  • Loading branch information
FrederickEngelhardt committed May 1, 2021
1 parent e7e8c05 commit aa81589
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,42 +30,43 @@ const missingPropError = {

describe('verifyReactNativeImage', () => {
it('returns true when importing a named export of Image from react-native', () => {
expect(
rule.functions
.verifyReactNativeImage(`import { Text, Image, View } from 'react-native';
const output = rule.functions
.verifyReactNativeImage(`import { Text, Image, View } from 'react-native';
const Component = () => (
<View>
<Image />
</View>
);`);

expect(output.enableLinting).toBe(true);
});

it('returns false when importing a named export of a Image from any other library', () => {
const output = rule.functions
.verifyReactNativeImage(`import { Text, Image, View } from './custom-image-component/Image';
const Component = () => (
<View>
<Image />
</View>
);`)
).toBe(true);
});

it('returns false when importing a named export of a Image from any other library', () => {
expect(
rule.functions
.verifyReactNativeImage(`import { Text, Image, View } from './custom-image-component/Image';
const Component = () => (
<View>
<Image />
</View>
);`)
).toBe(false);
);`);
expect(output.enableLinting).toBe(false);
});

/**
* Super edge case if someone wants to alias ReactNative.Image as another component like RNImage and imports an Image from './any-library'
*/
it('returns true when provided a named export of Image that is aliased as something from react-native', () => {
expect(
rule.functions
.verifyReactNativeImage(`import { Text, Image as RNImage, View } from 'react-native';
const Component = () => (
<View>
<RNImage />
</View>
);`)
).toBe(true);
const output = rule.functions
.verifyReactNativeImage(`import React from 'react'
import {Image as RNImage} from 'react-native'
const CustomImage = () => {
return <RNImage />
}
export default CustomImage`);

expect(output.enableLinting).toBe(true);
});
});

Expand Down Expand Up @@ -232,20 +233,6 @@ const invalidCustomImport = [
sourceType: 'module',
},
},
{
title: 'supports linting module imports',
code: `import * as RN from 'react-native';
const { Image } = RN;
const Component = (props) => (
<Image source={props.source} />
);
`,
errors: [missingPropError],
parserOptions: {
sourceType: 'module',
},
},
{
title:
'supports linting on Custom Invertable ImageComponents without react-native imported',
Expand Down
45 changes: 26 additions & 19 deletions src/rules/has-valid-accessibility-ignores-invert-colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,39 @@ const checkParent = ({ openingElement, parent }) => {
* @description varifies that the Image asset is imported from 'react-native' otherwise exits linting
*/
const verifyReactNativeImage = (text: string): boolean => {
const res = {
enableLinting: true,
elementsToCheck: defaultInvertableComponents,
};

// Escape hatch for tests
if (!text.match(new RegExp(/import/, 'g'))) {
return res;
}

// Flow has issues with String.raw
// $FlowFixMe
const namedSelector = String.raw`(import\s{)(.*)(\bImage\b)(.*)(}\sfrom\s'react-native')`;
// $FlowFixMe
const moduleSelector = String.raw`(import\s\*\sas\s)([a-zA-Z0-9_]\w)(\sfrom\s)('react-native')`;
const es6moduleSelector = String.raw`(?<=Image as )(.*?)(?=} from 'react-native')`;

const imageSourceReactNativeRegExp = new RegExp(
`${moduleSelector}|${namedSelector}`,
const imageSourceReactNativeRegExp = new RegExp(`${namedSelector}`, 'gs');
const imageSourceReactNativeAliasRegExp = new RegExp(
`${es6moduleSelector}`,
'gs'
);

const hasReactNativeImage = text.match(imageSourceReactNativeRegExp);
const matchedImage = text.match(imageSourceReactNativeRegExp) || [];
const matchedAliasImage = text.match(imageSourceReactNativeAliasRegExp) || [];

res.enableLinting =
matchedImage.length === 1 || matchedAliasImage.length === 1;

if (matchedAliasImage.length === 1) {
res.elementsToCheck = [matchedAliasImage[0].trim()];
}

return hasReactNativeImage ? true : false;
return res;
};

module.exports = {
Expand All @@ -66,18 +85,7 @@ module.exports = {
* Checks to see if there are valid imports and if so verifies that those imports related to 'react-native' or if a custom module exists
* */
const { text } = getSourceCode();
let hasImageImportAlias = false;
if (text.match(new RegExp(/import/, 'g'))) {
const hasReactNativeImage = verifyReactNativeImage(text);
if (!hasReactNativeImage) {
hasImageImportAlias = true;
}
}

// avoid directly mutating a constant as it ends up stacking up duplicate strings
const elementsToCheck = !hasImageImportAlias
? [...defaultInvertableComponents]
: [];
const { enableLinting, elementsToCheck } = verifyReactNativeImage(text);

// Add in any other invertible components to check for
if (options.length > 0) {
Expand All @@ -88,7 +96,7 @@ module.exports = {
}

// Exit process if there is nothing to check
if (hasImageImportAlias && options.length === 0) {
if (!enableLinting && options.length === 0) {
return {};
}

Expand All @@ -107,7 +115,6 @@ module.exports = {
'accessibilityIgnoresInvertColors prop is not a boolean value',
});
} else {
const elementsToCheck = defaultInvertableComponents;
if (options.length > 0) {
const { invertableComponents } = options[0];
if (invertableComponents) {
Expand Down

0 comments on commit aa81589

Please sign in to comment.