Skip to content

Latest commit

 

History

History
303 lines (211 loc) · 6.9 KB

File metadata and controls

303 lines (211 loc) · 6.9 KB

e2ed/no-code-outside-test

📝 Disallow top-level code outside the test call in test files.

💼 This rule is enabled in the following configs: 🌐 all, ✅ recommended.

🔧 This rule is automatically fixable by the --fix CLI option.

Each test file contains exactly one test — a single call of the test function. All code of the test, including its constants, must live inside the test callback: statements at the top level of the module run at import time, outside of the test lifecycle, and split the test logic between two scopes.

The rule applies only to test files — all JS/TS files in the autotests/tests directory (at any depth). At the top level of such files it allows only import declarations and the test(...) call itself, and reports every other statement.

Examples

❌ Incorrect

// autotests/tests/search/searchPage.ts

import {test} from 'autotests';
import {Language} from 'autotests/constants/external';

const language = Language.PT_BR;

test('Search page is working', {meta: {testId: 1209}}, async () => {
  const searchPage = await navigateToPage(SearchPage, {language});
});
Fixed
import {test} from 'autotests';
import {Language} from 'autotests/constants/external';

test('Search page is working', {meta: {testId: 1209}}, async () => {
  const language = Language.PT_BR;
  const searchPage = await navigateToPage(SearchPage, {language});
});
// autotests/tests/search/searchSuggestions.ts

const query = 'phone';
const expectedSuggestion = query + ' case';

test('Search suggestions are shown', {meta: {testId: 1211}}, async () => {});
Fixed
test('Search suggestions are shown', {meta: {testId: 1211}}, async () => {
  const query = 'phone';
  const expectedSuggestion = query + ' case';
});
// autotests/tests/search/searchByQuery.ts

test('Search by query works', {meta: {testId: 1210}}, async () => {});
clearSearchHistory();
Fixed
test('Search by query works', {meta: {testId: 1210}}, async () => {
  clearSearchHistory();
});
// autotests/tests/search/searchPagination.ts

const pageSize = 20;
export const pagesCount = 3;

test('Search pagination works', {meta: {testId: 1214}}, async () => {});
Fixed
export const pagesCount = 3;

test('Search pagination works', {meta: {testId: 1214}}, async () => {
  const pageSize = 20;
});
// autotests/tests/search/searchFilters.ts

// `export` cannot be moved into the test, reported without autofix
test('Search filters work', {meta: {testId: 1212}}, async () => {});
export const filtersCount = 3;
// autotests/tests/search/searchSorting.ts

// The callback has no block body to move the statement into, reported without autofix
const sorting = 'price';

test('Search sorting works', {meta: {testId: 1213}}, async () => checkSorting(sorting));
// autotests/tests/search/constants.ts

// A test file without a `test` call
const defaultSearchQuery = 'phone';
// autotests/tests/search/searchResultsLoading.ts

const timeout = 5000; // ms

test('Search results are loaded', {meta: {testId: 1215}}, async () => {});
Fixed
test('Search results are loaded', {meta: {testId: 1215}}, async () => {
  const timeout = 5000; // ms
});
// autotests/tests/search/searchResultsUpdating.ts

const timeout = 5000; /* default timeout
for search results */

test('Search results are updated', {meta: {testId: 1218}}, async () => {});
Fixed
/* default timeout
for search results */

test('Search results are updated', {meta: {testId: 1218}}, async () => {
  const timeout = 5000;
});
// autotests/tests/search/searchByDefaultQuery.ts

// Default search query
const query = 'phone';

test('Search by default query works', {meta: {testId: 1219}}, async () => {});
Fixed
test('Search by default query works', {meta: {testId: 1219}}, async () => {
  // Default search query
  const query = 'phone';
});
// autotests/tests/search/searchByShortQuery.ts

// Search page tests

const query = 'tv';

test('Search by short query works', {meta: {testId: 1222}}, async () => {});
Fixed
// Search page tests

test('Search by short query works', {meta: {testId: 1222}}, async () => {
  const query = 'tv';
});

✅ Correct

// autotests/tests/search/searchPage.ts

import {test} from 'autotests';
import {Language} from 'autotests/constants/external';

test('Search page is working', {meta: {testId: 1209}}, async () => {
  const language = Language.PT_BR;

  const searchPage = await navigateToPage(SearchPage, {language});
});
// autotests/tests/search/searchResults.ts

// Search page tests
import {test} from 'autotests'; // e2ed test function

/**
 * Checks that the search page is rendered.
 */
test('Search page is working', {meta: {testId: 1209}}, async () => {
  const timeout = 5000; // ms
}); // end of the test
// autotests/pageObjects/SearchPage.ts

// Only test files in the `autotests/tests` directory are checked
const defaultSearchQuery = 'phone';
// autotests/tests-old/search/searchPage.ts

// The directory must be named exactly `tests`
const searchQuery = 'phone';
// my-autotests/tests/search/searchPage.ts

// The parent directory must be named exactly `autotests`
const retriesCount = 3;
// src/utils/search.ts

// Files outside the `autotests` directory are not checked
const defaultSearchQuery = 'phone';

Rule details

The autofix moves the reported statements to the beginning of the test callback body, preserving their order. Each statement is moved together with the comments directly above it (on their own lines, without blank lines between them and the statement — for example, JSDoc or eslint-disable-next-line comments) and with the comments on the line where the statement ends. A block comment that starts on that line but continues on the following lines is left in place. Statements that cannot be placed inside a function (export declarations, import ... = require(...)) are reported without the autofix, as are all statements in files without a test(...) call with a block-bodied callback.

When not to use it

Do not enable this rule only if your test files intentionally contain top-level code besides imports and the test(...) call (for example, constants declared at the module level on purpose).

Further reading