[eslint/imports/no-boundary-crossing] don't allow package tests to import outside of packages (#142166)

This commit is contained in:
Spencer 2022-09-29 11:48:49 -05:00 committed by GitHub
parent 3ca18d9fe6
commit b41a07f85a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 96 additions and 14 deletions

View file

@ -19,15 +19,17 @@ import { getSourcePath } from '../helpers/source';
import { getRepoSourceClassifier } from '../helpers/repo_source_classifier';
import { getImportResolver } from '../get_import_resolver';
const IMPORTABLE_FROM: Record<ModuleType, ModuleType[] | '*'> = {
const ANY_FILE_IN_BAZEL = Symbol();
const IMPORTABLE_FROM: Record<ModuleType, ModuleType[] | typeof ANY_FILE_IN_BAZEL> = {
'non-package': ['non-package', 'server package', 'browser package', 'common package', 'static'],
'server package': ['common package', 'server package', 'static'],
'browser package': ['common package', 'browser package', 'static'],
'common package': ['common package', 'static'],
static: [],
'tests or mocks': '*',
tooling: '*',
'tests or mocks': ANY_FILE_IN_BAZEL,
tooling: ANY_FILE_IN_BAZEL,
};
const toList = (strings: string[]) => {
@ -87,6 +89,7 @@ export const NoBoundaryCrossingRule: Rule.RuleModule = {
},
messages: {
TYPE_MISMATCH: `"{{importedType}}" code can not be imported from "{{ownType}}" code.{{suggestion}}`,
FILE_OUTSIDE_OF_PACKAGE: `"{{ownType}}" code can import any code already within packages, but not files outside of packages.`,
},
},
create(context) {
@ -98,12 +101,7 @@ export const NoBoundaryCrossingRule: Rule.RuleModule = {
const self = classifier.classify(sourcePath);
const importable = IMPORTABLE_FROM[self.type];
if (importable === '*') {
// don't check imports in files which can import anything
return {};
}
return visitAllImportStatements((req, { node, importer }) => {
return visitAllImportStatements((req, { node, importer, type }) => {
if (
req === null ||
// we can ignore imports using the raw-loader, they will need to be resolved but can be managed on a case by case basis
@ -121,6 +119,27 @@ export const NoBoundaryCrossingRule: Rule.RuleModule = {
const imported = classifier.classify(result.absolute);
if (importable === ANY_FILE_IN_BAZEL) {
if (type === 'jest' && imported.repoRel === 'package.json') {
// we allow jest.mock() calls to mock out the `package.json` file... it's a very
// specific exception for a very specific implementation
return;
}
if (self.pkgInfo?.isBazelPackage ? imported.pkgInfo?.isBazelPackage : true) {
return;
}
context.report({
node: node as ESTree.Node,
messageId: 'FILE_OUTSIDE_OF_PACKAGE',
data: {
ownType: self.type,
},
});
return;
}
if (!importable.includes(imported.type)) {
context.report({
node: node as ESTree.Node,

View file

@ -13,4 +13,6 @@ export interface PkgInfo {
rel: string;
/** Absolute path to the package directory */
pkgDir: string;
/** Is the package a bazel package? If false, then the package is a "synthetic" plugin package */
isBazelPackage: boolean;
}

View file

@ -93,6 +93,7 @@ export class RepoPath {
pkgDir,
pkgId,
rel,
isBazelPackage: this.resolver.isBazelPackage(pkgId),
};
}
}

View file

@ -7,8 +7,8 @@
*/
import React from 'react';
import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock';
import { getExceptionListItemSchemaMock } from '../../test_helpers/exception_list_item_schema.mock';
import * as i18n from '../translations';
import { ExceptionItemCardHeader } from './header';
import { fireEvent, render } from '@testing-library/react';

View file

@ -10,8 +10,8 @@ import React from 'react';
import { fireEvent, render } from '@testing-library/react';
import { ExceptionItemCard } from '.';
import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock';
import { getCommentsArrayMock } from '@kbn/lists-plugin/common/schemas/types/comment.mock';
import { getExceptionListItemSchemaMock } from '../test_helpers/exception_list_item_schema.mock';
import { getCommentsArrayMock } from '../test_helpers/comments.mock';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
const ruleReferences: unknown[] = [

View file

@ -8,7 +8,7 @@
import React from 'react';
import { render } from '@testing-library/react';
import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock';
import { getExceptionListItemSchemaMock } from '../../test_helpers/exception_list_item_schema.mock';
import { ExceptionItemCardMetaInfo } from './meta';
import { RuleReference } from '../../types';

View file

@ -8,7 +8,7 @@
import React from 'react';
import { getExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/response/exception_list_item_schema.mock';
import { getExceptionListItemSchemaMock } from '../test_helpers/exception_list_item_schema.mock';
import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
import { ExceptionItems } from './exception_items';

View file

@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { Comment, CommentsArray } from '@kbn/securitysolution-io-ts-list-types';
export const getCommentsMock = (): Comment => ({
comment: 'some old comment',
created_at: '2020-04-20T15:25:31.830Z',
created_by: 'some user',
id: 'uuid_here',
});
export const getCommentsArrayMock = (): CommentsArray => [getCommentsMock(), getCommentsMock()];

View file

@ -0,0 +1,42 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
export const getExceptionListItemSchemaMock = (
overrides?: Partial<ExceptionListItemSchema>
): ExceptionListItemSchema => ({
_version: undefined,
comments: [],
created_at: '2020-04-20T15:25:31.830Z',
created_by: 'some user',
description: 'some description',
entries: [
{
entries: [
{ field: 'nested.field', operator: 'included', type: 'match', value: 'some value' },
],
field: 'some.parentField',
type: 'nested',
},
{ field: 'some.not.nested.field', operator: 'included', type: 'match', value: 'some value' },
],
id: '1',
item_id: 'endpoint_list_item',
list_id: 'endpoint_list_id',
meta: {},
name: 'some name',
namespace_type: 'single',
os_types: [],
tags: ['user added string for a tag', 'malware'],
tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e',
type: 'simple',
updated_at: '2020-04-20T15:25:31.830Z',
updated_by: 'some user',
...(overrides || {}),
});