Path: blob/main/tests/src/rules/order.js
1194 views
import { test, getTSParsers, getNonDefaultParsers } from '../utils';12import { RuleTester } from 'eslint';3import eslintPkg from 'eslint/package.json';4import semver from 'semver';5import flatMap from 'array.prototype.flatmap';67const ruleTester = new RuleTester();8const rule = require('rules/order');910function withoutAutofixOutput(test) {11return Object.assign({}, test, { output: test.code });12}1314ruleTester.run('order', rule, {15valid: [16// Default order using require17test({18code: `19var fs = require('fs');20var async = require('async');21var relParent1 = require('../foo');22var relParent2 = require('../foo/bar');23var relParent3 = require('../');24var relParent4 = require('..');25var sibling = require('./foo');26var index = require('./');`,27}),28// Default order using import29test({30code: `31import fs from 'fs';32import async, {foo1} from 'async';33import relParent1 from '../foo';34import relParent2, {foo2} from '../foo/bar';35import relParent3 from '../';36import sibling, {foo3} from './foo';37import index from './';`,38}),39// Multiple module of the same rank next to each other40test({41code: `42var fs = require('fs');43var fs = require('fs');44var path = require('path');45var _ = require('lodash');46var async = require('async');`,47}),48// Overriding order to be the reverse of the default order49test({50code: `51var index = require('./');52var sibling = require('./foo');53var relParent3 = require('../');54var relParent2 = require('../foo/bar');55var relParent1 = require('../foo');56var async = require('async');57var fs = require('fs');58`,59options: [{ groups: ['index', 'sibling', 'parent', 'external', 'builtin'] }],60}),61// Ignore dynamic requires62test({63code: `64var path = require('path');65var _ = require('lodash');66var async = require('async');67var fs = require('f' + 's');`,68}),69// Ignore non-require call expressions70test({71code: `72var path = require('path');73var result = add(1, 2);74var _ = require('lodash');`,75}),76// Ignore requires that are not at the top-level #177test({78code: `79var index = require('./');80function foo() {81var fs = require('fs');82}83() => require('fs');84if (a) {85require('fs');86}`,87}),88// Ignore requires that are not at the top-level #289test({90code: `91const foo = [92require('./foo'),93require('fs'),94]`,95}),96// Ignore requires in template literal (#1936)97test({98code: "const foo = `${require('./a')} ${require('fs')}`",99}),100// Ignore unknown/invalid cases101test({102code: `103var unknown1 = require('/unknown1');104var fs = require('fs');105var unknown2 = require('/unknown2');106var async = require('async');107var unknown3 = require('/unknown3');108var foo = require('../foo');109var unknown4 = require('/unknown4');110var bar = require('../foo/bar');111var unknown5 = require('/unknown5');112var parent = require('../');113var unknown6 = require('/unknown6');114var foo = require('./foo');115var unknown7 = require('/unknown7');116var index = require('./');117var unknown8 = require('/unknown8');118` }),119// Ignoring unassigned values by default (require)120test({121code: `122require('./foo');123require('fs');124var path = require('path');125` }),126// Ignoring unassigned values by default (import)127test({128code: `129import './foo';130import 'fs';131import path from 'path';132` }),133// No imports134test({135code: `136function add(a, b) {137return a + b;138}139var foo;140` }),141// Grouping import types142test({143code: `144var fs = require('fs');145var index = require('./');146var path = require('path');147148var sibling = require('./foo');149var relParent3 = require('../');150var async = require('async');151var relParent1 = require('../foo');152`,153options: [{ groups: [154['builtin', 'index'],155['sibling', 'parent', 'external'],156] }],157}),158// Omitted types should implicitly be considered as the last type159test({160code: `161var index = require('./');162var path = require('path');163`,164options: [{ groups: [165'index',166['sibling', 'parent', 'external'],167// missing 'builtin'168] }],169}),170// Mixing require and import should have import up top171test({172code: `173import async, {foo1} from 'async';174import relParent2, {foo2} from '../foo/bar';175import sibling, {foo3} from './foo';176var fs = require('fs');177var relParent1 = require('../foo');178var relParent3 = require('../');179var index = require('./');180`,181}),182...flatMap(getTSParsers(), parser => [183// Export equals expressions should be on top alongside with ordinary import-statements.184test({185code: `186import async, {foo1} from 'async';187import relParent2, {foo2} from '../foo/bar';188import sibling, {foo3} from './foo';189var fs = require('fs');190var util = require("util");191var relParent1 = require('../foo');192var relParent3 = require('../');193var index = require('./');194`,195parser,196}),197198test({199code: `200export import CreateSomething = _CreateSomething;201`,202parser,203}),204]),205// Adding unknown import types (e.g. using a resolver alias via babel) to the groups.206test({207code: `208import fs from 'fs';209import { Input } from '-/components/Input';210import { Button } from '-/components/Button';211import { add } from './helper';`,212options: [{213groups: ['builtin', 'external', 'unknown', 'parent', 'sibling', 'index'],214}],215}),216// Using unknown import types (e.g. using a resolver alias via babel) with217// an alternative custom group list.218test({219code: `220import { Input } from '-/components/Input';221import { Button } from '-/components/Button';222import fs from 'fs';223import { add } from './helper';`,224options: [{225groups: [ 'unknown', 'builtin', 'external', 'parent', 'sibling', 'index' ],226}],227}),228// Using unknown import types (e.g. using a resolver alias via babel)229// Option: newlines-between: 'always'230test({231code: `232import fs from 'fs';233234import { Input } from '-/components/Input';235import { Button } from '-/components/Button';236237import p from '..';238import q from '../';239240import { add } from './helper';241242import i from '.';243import j from './';`,244options: [245{246'newlines-between': 'always',247groups: ['builtin', 'external', 'unknown', 'parent', 'sibling', 'index'],248},249],250}),251252// Using pathGroups to customize ordering, position 'after'253test({254code: `255import fs from 'fs';256import _ from 'lodash';257import { Input } from '~/components/Input';258import { Button } from '#/components/Button';259import { add } from './helper';`,260options: [{261pathGroups: [262{ pattern: '~/**', group: 'external', position: 'after' },263{ pattern: '#/**', group: 'external', position: 'after' },264],265}],266}),267// pathGroup without position means "equal" with group268test({269code: `270import fs from 'fs';271import { Input } from '~/components/Input';272import async from 'async';273import { Button } from '#/components/Button';274import _ from 'lodash';275import { add } from './helper';`,276options: [{277pathGroups: [278{ pattern: '~/**', group: 'external' },279{ pattern: '#/**', group: 'external' },280],281}],282}),283// Using pathGroups to customize ordering, position 'before'284test({285code: `286import fs from 'fs';287288import { Input } from '~/components/Input';289290import { Button } from '#/components/Button';291292import _ from 'lodash';293294import { add } from './helper';`,295options: [{296'newlines-between': 'always',297pathGroups: [298{ pattern: '~/**', group: 'external', position: 'before' },299{ pattern: '#/**', group: 'external', position: 'before' },300],301}],302}),303// Using pathGroups to customize ordering, with patternOptions304test({305code: `306import fs from 'fs';307308import _ from 'lodash';309310import { Input } from '~/components/Input';311312import { Button } from '!/components/Button';313314import { add } from './helper';`,315options: [{316'newlines-between': 'always',317pathGroups: [318{ pattern: '~/**', group: 'external', position: 'after' },319{ pattern: '!/**', patternOptions: { nonegate: true }, group: 'external', position: 'after' },320],321}],322}),323// Using pathGroups to customize ordering for imports that are recognized as 'external'324// by setting pathGroupsExcludedImportTypes without 'external'325test({326code: `327import fs from 'fs';328329import { Input } from '@app/components/Input';330331import { Button } from '@app2/components/Button';332333import _ from 'lodash';334335import { add } from './helper';`,336options: [{337'newlines-between': 'always',338pathGroupsExcludedImportTypes: ['builtin'],339pathGroups: [340{ pattern: '@app/**', group: 'external', position: 'before' },341{ pattern: '@app2/**', group: 'external', position: 'before' },342],343}],344}),345// Using pathGroups (a test case for https://github.com/import-js/eslint-plugin-import/pull/1724)346test({347code: `348import fs from 'fs';349import external from 'external';350import externalTooPlease from './make-me-external';351352import sibling from './sibling';`,353options: [{354'newlines-between': 'always',355pathGroupsExcludedImportTypes: [],356pathGroups: [357{ pattern: './make-me-external', group: 'external' },358],359groups: [['builtin', 'external'], 'internal', 'parent', 'sibling', 'index'],360}],361}),362// Monorepo setup, using Webpack resolver, workspace folder name in external-module-folders363test({364code: `365import _ from 'lodash';366import m from '@test-scope/some-module';367368import bar from './bar';369`,370options: [{371'newlines-between': 'always',372}],373settings: {374'import/resolver': 'webpack',375'import/external-module-folders': ['node_modules', 'symlinked-module'],376},377}),378// Monorepo setup, using Node resolver (doesn't resolve symlinks)379test({380code: `381import _ from 'lodash';382import m from '@test-scope/some-module';383384import bar from './bar';385`,386options: [{387'newlines-between': 'always',388}],389settings: {390'import/resolver': 'node',391'import/external-module-folders': ['node_modules', 'symlinked-module'],392},393}),394// Option: newlines-between: 'always'395test({396code: `397var fs = require('fs');398var index = require('./');399var path = require('path');400401402403var sibling = require('./foo');404405406var relParent1 = require('../foo');407var relParent3 = require('../');408var async = require('async');409`,410options: [411{412groups: [413['builtin', 'index'],414['sibling'],415['parent', 'external'],416],417'newlines-between': 'always',418},419],420}),421// Option: newlines-between: 'never'422test({423code: `424var fs = require('fs');425var index = require('./');426var path = require('path');427var sibling = require('./foo');428var relParent1 = require('../foo');429var relParent3 = require('../');430var async = require('async');431`,432options: [433{434groups: [435['builtin', 'index'],436['sibling'],437['parent', 'external'],438],439'newlines-between': 'never',440},441],442}),443// Option: newlines-between: 'ignore'444test({445code: `446var fs = require('fs');447448var index = require('./');449var path = require('path');450var sibling = require('./foo');451452453var relParent1 = require('../foo');454455var relParent3 = require('../');456var async = require('async');457`,458options: [459{460groups: [461['builtin', 'index'],462['sibling'],463['parent', 'external'],464],465'newlines-between': 'ignore',466},467],468}),469// 'ignore' should be the default value for `newlines-between`470test({471code: `472var fs = require('fs');473474var index = require('./');475var path = require('path');476var sibling = require('./foo');477478479var relParent1 = require('../foo');480481var relParent3 = require('../');482483var async = require('async');484`,485options: [486{487groups: [488['builtin', 'index'],489['sibling'],490['parent', 'external'],491],492},493],494}),495// Option newlines-between: 'always' with multiline imports #1496test({497code: `498import path from 'path';499500import {501I,502Want,503Couple,504Imports,505Here506} from 'bar';507import external from 'external'508`,509options: [{ 'newlines-between': 'always' }],510}),511// Option newlines-between: 'always' with multiline imports #2512test({513code: `514import path from 'path';515import net516from 'net';517518import external from 'external'519`,520options: [{ 'newlines-between': 'always' }],521}),522// Option newlines-between: 'always' with multiline imports #3523test({524code: `525import foo526from '../../../../this/will/be/very/long/path/and/therefore/this/import/has/to/be/in/two/lines';527528import bar529from './sibling';530`,531options: [{ 'newlines-between': 'always' }],532}),533// Option newlines-between: 'always' with not assigned import #1534test({535code: `536import path from 'path';537538import 'loud-rejection';539import 'something-else';540541import _ from 'lodash';542`,543options: [{ 'newlines-between': 'always' }],544}),545// Option newlines-between: 'never' with not assigned import #2546test({547code: `548import path from 'path';549import 'loud-rejection';550import 'something-else';551import _ from 'lodash';552`,553options: [{ 'newlines-between': 'never' }],554}),555// Option newlines-between: 'always' with not assigned require #1556test({557code: `558var path = require('path');559560require('loud-rejection');561require('something-else');562563var _ = require('lodash');564`,565options: [{ 'newlines-between': 'always' }],566}),567// Option newlines-between: 'never' with not assigned require #2568test({569code: `570var path = require('path');571require('loud-rejection');572require('something-else');573var _ = require('lodash');574`,575options: [{ 'newlines-between': 'never' }],576}),577// Option newlines-between: 'never' should ignore nested require statement's #1578test({579code: `580var some = require('asdas');581var config = {582port: 4444,583runner: {584server_path: require('runner-binary').path,585586cli_args: {587'webdriver.chrome.driver': require('browser-binary').path588}589}590}591`,592options: [{ 'newlines-between': 'never' }],593}),594// Option newlines-between: 'always' should ignore nested require statement's #2595test({596code: `597var some = require('asdas');598var config = {599port: 4444,600runner: {601server_path: require('runner-binary').path,602cli_args: {603'webdriver.chrome.driver': require('browser-binary').path604}605}606}607`,608options: [{ 'newlines-between': 'always' }],609}),610// Option: newlines-between: 'always-and-inside-groups'611test({612code: `613var fs = require('fs');614var path = require('path');615616var util = require('util');617618var async = require('async');619620var relParent1 = require('../foo');621var relParent2 = require('../');622623var relParent3 = require('../bar');624625var sibling = require('./foo');626var sibling2 = require('./bar');627628var sibling3 = require('./foobar');629`,630options: [631{632'newlines-between': 'always-and-inside-groups',633},634],635}),636// Option alphabetize: {order: 'ignore'}637test({638code: `639import a from 'foo';640import b from 'bar';641642import index from './';643`,644options: [{645groups: ['external', 'index'],646alphabetize: { order: 'ignore' },647}],648}),649// Option alphabetize: {order: 'asc'}650test({651code: `652import c from 'Bar';653import b from 'bar';654import a from 'foo';655656import index from './';657`,658options: [{659groups: ['external', 'index'],660alphabetize: { order: 'asc' },661}],662}),663// Option alphabetize: {order: 'desc'}664test({665code: `666import a from 'foo';667import b from 'bar';668import c from 'Bar';669670import index from './';671`,672options: [{673groups: ['external', 'index'],674alphabetize: { order: 'desc' },675}],676}),677// Option alphabetize with newlines-between: {order: 'asc', newlines-between: 'always'}678test({679code: `680import b from 'Bar';681import c from 'bar';682import a from 'foo';683684import index from './';685`,686options: [{687groups: ['external', 'index'],688alphabetize: { order: 'asc' },689'newlines-between': 'always',690}],691}),692// Alphabetize with require693test({694code: `695import { hello } from './hello';696import { int } from './int';697const blah = require('./blah');698const { cello } = require('./cello');699`,700options: [701{702alphabetize: {703order: 'asc',704},705},706],707}),708// Order of imports with similar names709test({710code: `711import React from 'react';712import { BrowserRouter } from 'react-router-dom';713`,714options: [715{716alphabetize: {717order: 'asc',718},719},720],721}),722test({723code: `724import { UserInputError } from 'apollo-server-express';725726import { new as assertNewEmail } from '~/Assertions/Email';727`,728options: [{729alphabetize: {730caseInsensitive: true,731order: 'asc',732},733pathGroups: [734{ pattern: '~/*', group: 'internal' },735],736groups: [737'builtin',738'external',739'internal',740'parent',741'sibling',742'index',743],744'newlines-between': 'always',745}],746}),747test({748code: `749import { ReactElement, ReactNode } from 'react';750751import { util } from 'Internal/lib';752753import { parent } from '../parent';754755import { sibling } from './sibling';756`,757options: [{758alphabetize: {759caseInsensitive: true,760order: 'asc',761},762pathGroups: [763{ pattern: 'Internal/**/*', group: 'internal' },764],765groups: [766'builtin',767'external',768'internal',769'parent',770'sibling',771'index',772],773'newlines-between': 'always',774pathGroupsExcludedImportTypes: [],775}],776}),777...flatMap(getTSParsers, parser => [778// Order of the `import ... = require(...)` syntax779test({780code: `781import blah = require('./blah');782import { hello } from './hello';`,783parser,784options: [785{786alphabetize: {787order: 'asc',788},789},790],791}),792// Order of object-imports793test({794code: `795import blah = require('./blah');796import log = console.log;`,797parser,798options: [799{800alphabetize: {801order: 'asc',802},803},804],805}),806// Object-imports should not be forced to be alphabetized807test({808code: `809import debug = console.debug;810import log = console.log;`,811parser,812options: [813{814alphabetize: {815order: 'asc',816},817},818],819}),820test({821code: `822import log = console.log;823import debug = console.debug;`,824parser,825options: [826{827alphabetize: {828order: 'asc',829},830},831],832}),833test({834code: `835import { a } from "./a";836export namespace SomeNamespace {837export import a2 = a;838}839`,840parser,841options: [842{843groups: ['external', 'index'],844alphabetize: { order: 'asc' },845},846],847}),848]),849],850invalid: [851// builtin before external module (require)852test({853code: `854var async = require('async');855var fs = require('fs');856`,857output: `858var fs = require('fs');859var async = require('async');860`,861errors: [{862message: '`fs` import should occur before import of `async`',863}],864}),865// fix order with spaces on the end of line866test({867code: `868var async = require('async');869var fs = require('fs');${' '}870`,871output: `872var fs = require('fs');${' '}873var async = require('async');874`,875errors: [{876message: '`fs` import should occur before import of `async`',877}],878}),879// fix order with comment on the end of line880test({881code: `882var async = require('async');883var fs = require('fs'); /* comment */884`,885output: `886var fs = require('fs'); /* comment */887var async = require('async');888`,889errors: [{890message: '`fs` import should occur before import of `async`',891}],892}),893// fix order with comments at the end and start of line894test({895code: `896/* comment1 */ var async = require('async'); /* comment2 */897/* comment3 */ var fs = require('fs'); /* comment4 */898`,899output: `900/* comment3 */ var fs = require('fs'); /* comment4 */901/* comment1 */ var async = require('async'); /* comment2 */902`,903errors: [{904message: '`fs` import should occur before import of `async`',905}],906}),907// fix order with few comments at the end and start of line908test({909code: `910/* comment0 */ /* comment1 */ var async = require('async'); /* comment2 */911/* comment3 */ var fs = require('fs'); /* comment4 */912`,913output: `914/* comment3 */ var fs = require('fs'); /* comment4 */915/* comment0 */ /* comment1 */ var async = require('async'); /* comment2 */916`,917errors: [{918message: '`fs` import should occur before import of `async`',919}],920}),921// fix order with windows end of lines922test({923code:924`/* comment0 */ /* comment1 */ var async = require('async'); /* comment2 */` + `\r\n` +925`/* comment3 */ var fs = require('fs'); /* comment4 */` + `\r\n`,926output:927`/* comment3 */ var fs = require('fs'); /* comment4 */` + `\r\n` +928`/* comment0 */ /* comment1 */ var async = require('async'); /* comment2 */` + `\r\n`,929errors: [{930message: '`fs` import should occur before import of `async`',931}],932}),933// fix order with multilines comments at the end and start of line934test({935code: `936/* multiline1937comment1 */ var async = require('async'); /* multiline2938comment2 */ var fs = require('fs'); /* multiline3939comment3 */940`,941output: `942/* multiline1943comment1 */ var fs = require('fs');` + ' ' + `944var async = require('async'); /* multiline2945comment2 *//* multiline3946comment3 */947`,948errors: [{949message: '`fs` import should occur before import of `async`',950}],951}),952// fix destructured commonjs import953test({954code: `955var {b} = require('async');956var {a} = require('fs');957`,958output: `959var {a} = require('fs');960var {b} = require('async');961`,962errors: [{963message: '`fs` import should occur before import of `async`',964}],965}),966// fix order of multiline import967test({968code: `969var async = require('async');970var fs =971require('fs');972`,973output: `974var fs =975require('fs');976var async = require('async');977`,978errors: [{979message: '`fs` import should occur before import of `async`',980}],981}),982// fix order at the end of file983test({984code: `985var async = require('async');986var fs = require('fs');`,987output: `988var fs = require('fs');989var async = require('async');` + '\n',990errors: [{991message: '`fs` import should occur before import of `async`',992}],993}),994// builtin before external module (import)995test({996code: `997import async from 'async';998import fs from 'fs';999`,1000output: `1001import fs from 'fs';1002import async from 'async';1003`,1004errors: [{1005message: '`fs` import should occur before import of `async`',1006}],1007}),1008// builtin before external module (mixed import and require)1009test({1010code: `1011var async = require('async');1012import fs from 'fs';1013`,1014output: `1015import fs from 'fs';1016var async = require('async');1017`,1018errors: [{1019message: '`fs` import should occur before import of `async`',1020}],1021}),1022// external before parent1023test({1024code: `1025var parent = require('../parent');1026var async = require('async');1027`,1028output: `1029var async = require('async');1030var parent = require('../parent');1031`,1032errors: [{1033message: '`async` import should occur before import of `../parent`',1034}],1035}),1036// parent before sibling1037test({1038code: `1039var sibling = require('./sibling');1040var parent = require('../parent');1041`,1042output: `1043var parent = require('../parent');1044var sibling = require('./sibling');1045`,1046errors: [{1047message: '`../parent` import should occur before import of `./sibling`',1048}],1049}),1050// sibling before index1051test({1052code: `1053var index = require('./');1054var sibling = require('./sibling');1055`,1056output: `1057var sibling = require('./sibling');1058var index = require('./');1059`,1060errors: [{1061message: '`./sibling` import should occur before import of `./`',1062}],1063}),1064// Multiple errors1065...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [1066test({1067code: `1068var sibling = require('./sibling');1069var async = require('async');1070var fs = require('fs');1071`,1072output: `1073var async = require('async');1074var sibling = require('./sibling');1075var fs = require('fs');1076`,1077errors: [{1078message: '`async` import should occur before import of `./sibling`',1079}, {1080message: '`fs` import should occur before import of `./sibling`',1081}],1082}),1083],1084// Uses 'after' wording if it creates less errors1085test({1086code: `1087var index = require('./');1088var fs = require('fs');1089var path = require('path');1090var _ = require('lodash');1091var foo = require('foo');1092var bar = require('bar');1093`,1094output: `1095var fs = require('fs');1096var path = require('path');1097var _ = require('lodash');1098var foo = require('foo');1099var bar = require('bar');1100var index = require('./');1101`,1102errors: [{1103message: '`./` import should occur after import of `bar`',1104}],1105}),1106// Overriding order to be the reverse of the default order1107test({1108code: `1109var fs = require('fs');1110var index = require('./');1111`,1112output: `1113var index = require('./');1114var fs = require('fs');1115`,1116options: [{ groups: ['index', 'sibling', 'parent', 'external', 'builtin'] }],1117errors: [{1118message: '`./` import should occur before import of `fs`',1119}],1120}),1121// member expression of require1122test(withoutAutofixOutput({1123code: `1124var foo = require('./foo').bar;1125var fs = require('fs');1126`,1127errors: [{1128message: '`fs` import should occur before import of `./foo`',1129}],1130})),1131// nested member expression of require1132test(withoutAutofixOutput({1133code: `1134var foo = require('./foo').bar.bar.bar;1135var fs = require('fs');1136`,1137errors: [{1138message: '`fs` import should occur before import of `./foo`',1139}],1140})),1141// fix near nested member expression of require with newlines1142test(withoutAutofixOutput({1143code: `1144var foo = require('./foo').bar1145.bar1146.bar;1147var fs = require('fs');1148`,1149errors: [{1150message: '`fs` import should occur before import of `./foo`',1151}],1152})),1153// fix nested member expression of require with newlines1154test(withoutAutofixOutput({1155code: `1156var foo = require('./foo');1157var fs = require('fs').bar1158.bar1159.bar;1160`,1161errors: [{1162message: '`fs` import should occur before import of `./foo`',1163}],1164})),1165// Grouping import types1166test({1167code: `1168var fs = require('fs');1169var index = require('./');1170var sibling = require('./foo');1171var path = require('path');1172`,1173output: `1174var fs = require('fs');1175var index = require('./');1176var path = require('path');1177var sibling = require('./foo');1178`,1179options: [{ groups: [1180['builtin', 'index'],1181['sibling', 'parent', 'external'],1182] }],1183errors: [{1184message: '`path` import should occur before import of `./foo`',1185}],1186}),1187// Omitted types should implicitly be considered as the last type1188test({1189code: `1190var path = require('path');1191var async = require('async');1192`,1193output: `1194var async = require('async');1195var path = require('path');1196`,1197options: [{ groups: [1198'index',1199['sibling', 'parent', 'external', 'internal'],1200// missing 'builtin'1201] }],1202errors: [{1203message: '`async` import should occur before import of `path`',1204}],1205}),1206// Setting the order for an unknown type1207// should make the rule trigger an error and do nothing else1208test({1209code: `1210var async = require('async');1211var index = require('./');1212`,1213options: [{ groups: [1214'index',1215['sibling', 'parent', 'UNKNOWN', 'internal'],1216] }],1217errors: [{1218message: 'Incorrect configuration of the rule: Unknown type `"UNKNOWN"`',1219}],1220}),1221// Type in an array can't be another array, too much nesting1222test({1223code: `1224var async = require('async');1225var index = require('./');1226`,1227options: [{ groups: [1228'index',1229['sibling', 'parent', ['builtin'], 'internal'],1230] }],1231errors: [{1232message: 'Incorrect configuration of the rule: Unknown type `["builtin"]`',1233}],1234}),1235// No numbers1236test({1237code: `1238var async = require('async');1239var index = require('./');1240`,1241options: [{ groups: [1242'index',1243['sibling', 'parent', 2, 'internal'],1244] }],1245errors: [{1246message: 'Incorrect configuration of the rule: Unknown type `2`',1247}],1248}),1249// Duplicate1250test({1251code: `1252var async = require('async');1253var index = require('./');1254`,1255options: [{ groups: [1256'index',1257['sibling', 'parent', 'parent', 'internal'],1258] }],1259errors: [{1260message: 'Incorrect configuration of the rule: `parent` is duplicated',1261}],1262}),1263// Mixing require and import should have import up top1264test({1265code: `1266import async, {foo1} from 'async';1267import relParent2, {foo2} from '../foo/bar';1268var fs = require('fs');1269var relParent1 = require('../foo');1270var relParent3 = require('../');1271import sibling, {foo3} from './foo';1272var index = require('./');1273`,1274output: `1275import async, {foo1} from 'async';1276import relParent2, {foo2} from '../foo/bar';1277import sibling, {foo3} from './foo';1278var fs = require('fs');1279var relParent1 = require('../foo');1280var relParent3 = require('../');1281var index = require('./');1282`,1283errors: [{1284message: '`./foo` import should occur before import of `fs`',1285}],1286}),1287test({1288code: `1289var fs = require('fs');1290import async, {foo1} from 'async';1291import relParent2, {foo2} from '../foo/bar';1292`,1293output: `1294import async, {foo1} from 'async';1295import relParent2, {foo2} from '../foo/bar';1296var fs = require('fs');1297`,1298errors: [{1299message: '`fs` import should occur after import of `../foo/bar`',1300}],1301}),1302...flatMap(getTSParsers(), parser => [1303// Order of the `import ... = require(...)` syntax1304test({1305code: `1306var fs = require('fs');1307import async, {foo1} from 'async';1308import bar = require("../foo/bar");1309`,1310output: `1311import async, {foo1} from 'async';1312import bar = require("../foo/bar");1313var fs = require('fs');1314`,1315parser,1316errors: [{1317message: '`fs` import should occur after import of `../foo/bar`',1318}],1319}),1320test({1321code: `1322var async = require('async');1323var fs = require('fs');1324`,1325output: `1326var fs = require('fs');1327var async = require('async');1328`,1329parser,1330errors: [{1331message: '`fs` import should occur before import of `async`',1332}],1333}),1334test({1335code: `1336import sync = require('sync');1337import async, {foo1} from 'async';13381339import index from './';1340`,1341output: `1342import async, {foo1} from 'async';1343import sync = require('sync');13441345import index from './';1346`,1347options: [{1348groups: ['external', 'index'],1349alphabetize: { order: 'asc' },1350}],1351parser,1352errors: [{1353message: '`async` import should occur before import of `sync`',1354}],1355}),1356// Order of object-imports1357test({1358code: `1359import log = console.log;1360import blah = require('./blah');`,1361parser,1362errors: [{1363message: '`./blah` import should occur before import of `console.log`',1364}],1365}),1366]),1367// Default order using import with custom import alias1368test({1369code: `1370import { Button } from '-/components/Button';1371import { add } from './helper';1372import fs from 'fs';1373`,1374output: `1375import fs from 'fs';1376import { Button } from '-/components/Button';1377import { add } from './helper';1378`,1379options: [1380{1381groups: ['builtin', 'external', 'unknown', 'parent', 'sibling', 'index'],1382},1383],1384errors: [1385{1386line: 4,1387message: '`fs` import should occur before import of `-/components/Button`',1388},1389],1390}),1391// Default order using import with custom import alias1392test({1393code: `1394import fs from 'fs';1395import { Button } from '-/components/Button';1396import { LinkButton } from '-/components/Link';1397import { add } from './helper';1398`,1399output: `1400import fs from 'fs';14011402import { Button } from '-/components/Button';1403import { LinkButton } from '-/components/Link';14041405import { add } from './helper';1406`,1407options: [1408{1409groups: ['builtin', 'external', 'unknown', 'parent', 'sibling', 'index'],1410'newlines-between': 'always',1411},1412],1413errors: [1414{1415line: 2,1416message: 'There should be at least one empty line between import groups',1417},1418{1419line: 4,1420message: 'There should be at least one empty line between import groups',1421},1422],1423}),1424// Option newlines-between: 'never' - should report unnecessary line between groups1425test({1426code: `1427var fs = require('fs');1428var index = require('./');1429var path = require('path');14301431var sibling = require('./foo');14321433var relParent1 = require('../foo');1434var relParent3 = require('../');1435var async = require('async');1436`,1437output: `1438var fs = require('fs');1439var index = require('./');1440var path = require('path');1441var sibling = require('./foo');1442var relParent1 = require('../foo');1443var relParent3 = require('../');1444var async = require('async');1445`,1446options: [1447{1448groups: [1449['builtin', 'index'],1450['sibling'],1451['parent', 'external'],1452],1453'newlines-between': 'never',1454},1455],1456errors: [1457{1458line: 4,1459message: 'There should be no empty line between import groups',1460},1461{1462line: 6,1463message: 'There should be no empty line between import groups',1464},1465],1466}),1467// Fix newlines-between with comments after1468test({1469code: `1470var fs = require('fs'); /* comment */14711472var index = require('./');1473`,1474output: `1475var fs = require('fs'); /* comment */1476var index = require('./');1477`,1478options: [1479{1480groups: [['builtin'], ['index']],1481'newlines-between': 'never',1482},1483],1484errors: [1485{1486line: 2,1487message: 'There should be no empty line between import groups',1488},1489],1490}),1491// Cannot fix newlines-between with multiline comment after1492test({1493code: `1494var fs = require('fs'); /* multiline1495comment */14961497var index = require('./');1498`,1499output: `1500var fs = require('fs'); /* multiline1501comment */15021503var index = require('./');1504`,1505options: [1506{1507groups: [['builtin'], ['index']],1508'newlines-between': 'never',1509},1510],1511errors: [1512{1513line: 2,1514message: 'There should be no empty line between import groups',1515},1516],1517}),1518// Option newlines-between: 'always' - should report lack of newline between groups1519test({1520code: `1521var fs = require('fs');1522var index = require('./');1523var path = require('path');1524var sibling = require('./foo');1525var relParent1 = require('../foo');1526var relParent3 = require('../');1527var async = require('async');1528`,1529output: `1530var fs = require('fs');1531var index = require('./');1532var path = require('path');15331534var sibling = require('./foo');15351536var relParent1 = require('../foo');1537var relParent3 = require('../');1538var async = require('async');1539`,1540options: [1541{1542groups: [1543['builtin', 'index'],1544['sibling'],1545['parent', 'external'],1546],1547'newlines-between': 'always',1548},1549],1550errors: [1551{1552line: 4,1553message: 'There should be at least one empty line between import groups',1554},1555{1556line: 5,1557message: 'There should be at least one empty line between import groups',1558},1559],1560}),1561// Option newlines-between: 'always' should report unnecessary empty lines space between import groups1562test({1563code: `1564var fs = require('fs');15651566var path = require('path');1567var index = require('./');15681569var sibling = require('./foo');15701571var async = require('async');1572`,1573output: `1574var fs = require('fs');1575var path = require('path');1576var index = require('./');15771578var sibling = require('./foo');1579var async = require('async');1580`,1581options: [1582{1583groups: [1584['builtin', 'index'],1585['sibling', 'parent', 'external'],1586],1587'newlines-between': 'always',1588},1589],1590errors: [1591{1592line: 2,1593message: 'There should be no empty line within import group',1594},1595{1596line: 7,1597message: 'There should be no empty line within import group',1598},1599],1600}),1601// Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports disabled1602// newline is preserved to match existing behavior1603test({1604code: `1605import path from 'path';1606import 'loud-rejection';16071608import 'something-else';1609import _ from 'lodash';1610`,1611output: `1612import path from 'path';1613import 'loud-rejection';16141615import 'something-else';1616import _ from 'lodash';1617`,1618options: [{ 'newlines-between': 'never', warnOnUnassignedImports: false }],1619errors: [1620{1621line: 2,1622message: 'There should be no empty line between import groups',1623},1624],1625}),1626// Option newlines-between: 'never' with unassigned imports and warnOnUnassignedImports enabled1627test({1628code: `1629import path from 'path';1630import 'loud-rejection';16311632import 'something-else';1633import _ from 'lodash';1634`,1635output: `1636import path from 'path';1637import 'loud-rejection';1638import 'something-else';1639import _ from 'lodash';1640`,1641options: [{ 'newlines-between': 'never', warnOnUnassignedImports: true }],1642errors: [1643{1644line: 3,1645message: 'There should be no empty line between import groups',1646},1647],1648}),1649// Option newlines-between: 'never' cannot fix if there are other statements between imports1650test({1651code: `1652import path from 'path';1653export const abc = 123;16541655import 'something-else';1656import _ from 'lodash';1657`,1658output: `1659import path from 'path';1660export const abc = 123;16611662import 'something-else';1663import _ from 'lodash';1664`,1665options: [{ 'newlines-between': 'never' }],1666errors: [1667{1668line: 2,1669message: 'There should be no empty line between import groups',1670},1671],1672}),1673// Option newlines-between: 'always' should report missing empty lines when using not assigned imports1674test({1675code: `1676import path from 'path';1677import 'loud-rejection';1678import 'something-else';1679import _ from 'lodash';1680`,1681output: `1682import path from 'path';16831684import 'loud-rejection';1685import 'something-else';1686import _ from 'lodash';1687`,1688options: [{ 'newlines-between': 'always' }],1689errors: [1690{1691line: 2,1692message: 'There should be at least one empty line between import groups',1693},1694],1695}),1696// fix missing empty lines with single line comment after1697test({1698code: `1699import path from 'path'; // comment1700import _ from 'lodash';1701`,1702output: `1703import path from 'path'; // comment17041705import _ from 'lodash';1706`,1707options: [{ 'newlines-between': 'always' }],1708errors: [1709{1710line: 2,1711message: 'There should be at least one empty line between import groups',1712},1713],1714}),1715// fix missing empty lines with few line block comment after1716test({1717code: `1718import path from 'path'; /* comment */ /* comment */1719import _ from 'lodash';1720`,1721output: `1722import path from 'path'; /* comment */ /* comment */17231724import _ from 'lodash';1725`,1726options: [{ 'newlines-between': 'always' }],1727errors: [1728{1729line: 2,1730message: 'There should be at least one empty line between import groups',1731},1732],1733}),1734// fix missing empty lines with single line block comment after1735test({1736code: `1737import path from 'path'; /* 117382 */1739import _ from 'lodash';1740`,1741output: `1742import path from 'path';1743/* 117442 */1745import _ from 'lodash';1746`,1747options: [{ 'newlines-between': 'always' }],1748errors: [1749{1750line: 2,1751message: 'There should be at least one empty line between import groups',1752},1753],1754}),1755// reorder fix cannot cross function call on moving below #11756test({1757code: `1758const local = require('./local');17591760fn_call();17611762const global1 = require('global1');1763const global2 = require('global2');17641765fn_call();1766`,1767output: `1768const local = require('./local');17691770fn_call();17711772const global1 = require('global1');1773const global2 = require('global2');17741775fn_call();1776`,1777errors: [{1778message: '`./local` import should occur after import of `global2`',1779}],1780}),1781// reorder fix cannot cross function call on moving below #21782test({1783code: `1784const local = require('./local');1785fn_call();1786const global1 = require('global1');1787const global2 = require('global2');17881789fn_call();1790`,1791output: `1792const local = require('./local');1793fn_call();1794const global1 = require('global1');1795const global2 = require('global2');17961797fn_call();1798`,1799errors: [{1800message: '`./local` import should occur after import of `global2`',1801}],1802}),1803// reorder fix cannot cross function call on moving below #31804test({1805code: `1806const local1 = require('./local1');1807const local2 = require('./local2');1808const local3 = require('./local3');1809const local4 = require('./local4');1810fn_call();1811const global1 = require('global1');1812const global2 = require('global2');1813const global3 = require('global3');1814const global4 = require('global4');1815const global5 = require('global5');1816fn_call();1817`,1818output: `1819const local1 = require('./local1');1820const local2 = require('./local2');1821const local3 = require('./local3');1822const local4 = require('./local4');1823fn_call();1824const global1 = require('global1');1825const global2 = require('global2');1826const global3 = require('global3');1827const global4 = require('global4');1828const global5 = require('global5');1829fn_call();1830`,1831errors: [1832'`./local1` import should occur after import of `global5`',1833'`./local2` import should occur after import of `global5`',1834'`./local3` import should occur after import of `global5`',1835'`./local4` import should occur after import of `global5`',1836],1837}),1838// reorder fix cannot cross function call on moving below1839test(withoutAutofixOutput({1840code: `1841const local = require('./local');1842const global1 = require('global1');1843const global2 = require('global2');1844fn_call();1845const global3 = require('global3');18461847fn_call();1848`,1849errors: [{1850message: '`./local` import should occur after import of `global3`',1851}],1852})),1853// reorder fix cannot cross function call on moving below1854// fix imports that not crosses function call only1855test({1856code: `1857const local1 = require('./local1');1858const global1 = require('global1');1859const global2 = require('global2');1860fn_call();1861const local2 = require('./local2');1862const global3 = require('global3');1863const global4 = require('global4');18641865fn_call();1866`,1867output: `1868const local1 = require('./local1');1869const global1 = require('global1');1870const global2 = require('global2');1871fn_call();1872const global3 = require('global3');1873const global4 = require('global4');1874const local2 = require('./local2');18751876fn_call();1877`,1878errors: [1879'`./local1` import should occur after import of `global4`',1880'`./local2` import should occur after import of `global4`',1881],1882}),1883// pathGroup with position 'after'1884test({1885code: `1886import fs from 'fs';1887import _ from 'lodash';1888import { add } from './helper';1889import { Input } from '~/components/Input';1890`,1891output: `1892import fs from 'fs';1893import _ from 'lodash';1894import { Input } from '~/components/Input';1895import { add } from './helper';1896`,1897options: [{1898pathGroups: [1899{ pattern: '~/**', group: 'external', position: 'after' },1900],1901}],1902errors: [{1903message: '`~/components/Input` import should occur before import of `./helper`',1904}],1905}),1906// pathGroup without position1907test({1908code: `1909import fs from 'fs';1910import _ from 'lodash';1911import { add } from './helper';1912import { Input } from '~/components/Input';1913import async from 'async';1914`,1915output: `1916import fs from 'fs';1917import _ from 'lodash';1918import { Input } from '~/components/Input';1919import async from 'async';1920import { add } from './helper';1921`,1922options: [{1923pathGroups: [1924{ pattern: '~/**', group: 'external' },1925],1926}],1927errors: [{1928message: '`./helper` import should occur after import of `async`',1929}],1930}),1931// pathGroup with position 'before'1932test({1933code: `1934import fs from 'fs';1935import _ from 'lodash';1936import { add } from './helper';1937import { Input } from '~/components/Input';1938`,1939output: `1940import fs from 'fs';1941import { Input } from '~/components/Input';1942import _ from 'lodash';1943import { add } from './helper';1944`,1945options: [{1946pathGroups: [1947{ pattern: '~/**', group: 'external', position: 'before' },1948],1949}],1950errors: [{1951message: '`~/components/Input` import should occur before import of `lodash`',1952}],1953}),1954// multiple pathGroup with different positions for same group, fix for 'after'1955test({1956code: `1957import fs from 'fs';1958import { Import } from '$/components/Import';1959import _ from 'lodash';1960import { Output } from '~/components/Output';1961import { Input } from '#/components/Input';1962import { add } from './helper';1963import { Export } from '-/components/Export';1964`,1965output: `1966import fs from 'fs';1967import { Export } from '-/components/Export';1968import { Import } from '$/components/Import';1969import _ from 'lodash';1970import { Output } from '~/components/Output';1971import { Input } from '#/components/Input';1972import { add } from './helper';1973`,1974options: [{1975pathGroups: [1976{ pattern: '~/**', group: 'external', position: 'after' },1977{ pattern: '#/**', group: 'external', position: 'after' },1978{ pattern: '-/**', group: 'external', position: 'before' },1979{ pattern: '$/**', group: 'external', position: 'before' },1980],1981}],1982errors: [1983{1984message: '`-/components/Export` import should occur before import of `$/components/Import`',1985},1986],1987}),19881989// multiple pathGroup with different positions for same group, fix for 'before'1990test({1991code: `1992import fs from 'fs';1993import { Export } from '-/components/Export';1994import { Import } from '$/components/Import';1995import _ from 'lodash';1996import { Input } from '#/components/Input';1997import { add } from './helper';1998import { Output } from '~/components/Output';1999`,2000output: `2001import fs from 'fs';2002import { Export } from '-/components/Export';2003import { Import } from '$/components/Import';2004import _ from 'lodash';2005import { Output } from '~/components/Output';2006import { Input } from '#/components/Input';2007import { add } from './helper';2008`,2009options: [{2010pathGroups: [2011{ pattern: '~/**', group: 'external', position: 'after' },2012{ pattern: '#/**', group: 'external', position: 'after' },2013{ pattern: '-/**', group: 'external', position: 'before' },2014{ pattern: '$/**', group: 'external', position: 'before' },2015],2016}],2017errors: [2018{2019message: '`~/components/Output` import should occur before import of `#/components/Input`',2020},2021],2022}),20232024// reorder fix cannot cross non import or require2025test(withoutAutofixOutput({2026code: `2027var async = require('async');2028fn_call();2029var fs = require('fs');2030`,2031errors: [{2032message: '`fs` import should occur before import of `async`',2033}],2034})),2035// reorder fix cannot cross function call on moving below (from #1252)2036test({2037code: `2038const env = require('./config');20392040Object.keys(env);20412042const http = require('http');2043const express = require('express');20442045http.createServer(express());2046`,2047output: `2048const env = require('./config');20492050Object.keys(env);20512052const http = require('http');2053const express = require('express');20542055http.createServer(express());2056`,2057errors: [{2058message: '`./config` import should occur after import of `express`',2059}],2060}),2061// reorder cannot cross non plain requires2062test(withoutAutofixOutput({2063code: `2064var async = require('async');2065var a = require('./value.js')(a);2066var fs = require('fs');2067`,2068errors: [{2069message: '`fs` import should occur before import of `async`',2070}],2071})),2072// reorder fixes cannot be applied to non plain requires #12073test(withoutAutofixOutput({2074code: `2075var async = require('async');2076var fs = require('fs')(a);2077`,2078errors: [{2079message: '`fs` import should occur before import of `async`',2080}],2081})),2082// reorder fixes cannot be applied to non plain requires #22083test(withoutAutofixOutput({2084code: `2085var async = require('async')(a);2086var fs = require('fs');2087`,2088errors: [{2089message: '`fs` import should occur before import of `async`',2090}],2091})),2092// cannot require in case of not assignment require2093test(withoutAutofixOutput({2094code: `2095var async = require('async');2096require('./aa');2097var fs = require('fs');2098`,2099errors: [{2100message: '`fs` import should occur before import of `async`',2101}],2102})),2103// reorder cannot cross function call (import statement)2104test(withoutAutofixOutput({2105code: `2106import async from 'async';2107fn_call();2108import fs from 'fs';2109`,2110errors: [{2111message: '`fs` import should occur before import of `async`',2112}],2113})),2114// reorder cannot cross variable assignment (import statement)2115test(withoutAutofixOutput({2116code: `2117import async from 'async';2118var a = 1;2119import fs from 'fs';2120`,2121errors: [{2122message: '`fs` import should occur before import of `async`',2123}],2124})),2125// reorder cannot cross non plain requires (import statement)2126test(withoutAutofixOutput({2127code: `2128import async from 'async';2129var a = require('./value.js')(a);2130import fs from 'fs';2131`,2132errors: [{2133message: '`fs` import should occur before import of `async`',2134}],2135})),2136// cannot reorder in case of not assignment import2137test(withoutAutofixOutput({2138code: `2139import async from 'async';2140import './aa';2141import fs from 'fs';2142`,2143errors: [{2144message: '`fs` import should occur before import of `async`',2145}],2146})),2147// Option alphabetize: {order: 'asc'}2148test({2149code: `2150import b from 'bar';2151import c from 'Bar';2152import a from 'foo';21532154import index from './';2155`,2156output: `2157import c from 'Bar';2158import b from 'bar';2159import a from 'foo';21602161import index from './';2162`,2163options: [{2164groups: ['external', 'index'],2165alphabetize: { order: 'asc' },2166}],2167errors: [{2168message: '`Bar` import should occur before import of `bar`',2169}],2170}),2171// Option alphabetize: {order: 'desc'}2172test({2173code: `2174import a from 'foo';2175import c from 'Bar';2176import b from 'bar';21772178import index from './';2179`,2180output: `2181import a from 'foo';2182import b from 'bar';2183import c from 'Bar';21842185import index from './';2186`,2187options: [{2188groups: ['external', 'index'],2189alphabetize: { order: 'desc' },2190}],2191errors: [{2192message: '`bar` import should occur before import of `Bar`',2193}],2194}),2195// Option alphabetize {order: 'asc': caseInsensitive: true}2196test({2197code: `2198import b from 'foo';2199import a from 'Bar';22002201import index from './';2202`,2203output: `2204import a from 'Bar';2205import b from 'foo';22062207import index from './';2208`,2209options: [{2210groups: ['external', 'index'],2211alphabetize: { order: 'asc', caseInsensitive: true },2212}],2213errors: [{2214message: '`Bar` import should occur before import of `foo`',2215}],2216}),2217// Option alphabetize {order: 'desc': caseInsensitive: true}2218test({2219code: `2220import a from 'Bar';2221import b from 'foo';22222223import index from './';2224`,2225output: `2226import b from 'foo';2227import a from 'Bar';22282229import index from './';2230`,2231options: [{2232groups: ['external', 'index'],2233alphabetize: { order: 'desc', caseInsensitive: true },2234}],2235errors: [{2236message: '`foo` import should occur before import of `Bar`',2237}],2238}),2239// Alphabetize with parent paths2240test({2241code: `2242import a from '../a';2243import p from '..';2244`,2245output: `2246import p from '..';2247import a from '../a';2248`,2249options: [{2250groups: ['external', 'index'],2251alphabetize: { order: 'asc' },2252}],2253errors: [{2254message: '`..` import should occur before import of `../a`',2255}],2256}),2257// Alphabetize with require2258...semver.satisfies(eslintPkg.version, '< 3.0.0') ? [] : [2259test({2260code: `2261const { cello } = require('./cello');2262import { int } from './int';2263const blah = require('./blah');2264import { hello } from './hello';2265`,2266output: `2267import { int } from './int';2268const { cello } = require('./cello');2269const blah = require('./blah');2270import { hello } from './hello';2271`,2272errors: [{2273message: '`./int` import should occur before import of `./cello`',2274}, {2275message: '`./hello` import should occur before import of `./cello`',2276}],2277}),2278],2279].filter((t) => !!t),2280});228122822283context('TypeScript', function () {2284getNonDefaultParsers()2285// Type-only imports were added in TypeScript ESTree 2.23.02286.filter((parser) => parser !== require.resolve('typescript-eslint-parser'))2287.forEach((parser) => {2288const parserConfig = {2289parser,2290settings: {2291'import/parsers': { [parser]: ['.ts'] },2292'import/resolver': { 'eslint-import-resolver-typescript': true },2293},2294};22952296ruleTester.run('order', rule, {2297valid: [2298// #1667: typescript type import support22992300// Option alphabetize: {order: 'asc'}2301test({2302code: `2303import c from 'Bar';2304import type { C } from 'Bar';2305import b from 'bar';2306import a from 'foo';2307import type { A } from 'foo';23082309import index from './';2310`,2311...parserConfig,2312options: [2313{2314groups: ['external', 'index'],2315alphabetize: { order: 'asc' },2316},2317],2318}),2319// Option alphabetize: {order: 'desc'}2320test({2321code: `2322import a from 'foo';2323import type { A } from 'foo';2324import b from 'bar';2325import c from 'Bar';2326import type { C } from 'Bar';23272328import index from './';2329`,2330...parserConfig,2331options: [2332{2333groups: ['external', 'index'],2334alphabetize: { order: 'desc' },2335},2336],2337}),2338// Option alphabetize: {order: 'asc'} with type group2339test({2340code: `2341import c from 'Bar';2342import b from 'bar';2343import a from 'foo';23442345import index from './';23462347import type { C } from 'Bar';2348import type { A } from 'foo';2349`,2350...parserConfig,2351options: [2352{2353groups: ['external', 'index', 'type'],2354alphabetize: { order: 'asc' },2355},2356],2357}),2358// Option alphabetize: {order: 'asc'} with type group & path group2359test({2360// only: true,2361code: `2362import c from 'Bar';2363import a from 'foo';23642365import b from 'dirA/bar';23662367import index from './';23682369import type { C } from 'dirA/Bar';2370import type { A } from 'foo';2371`,2372...parserConfig,2373options: [2374{2375alphabetize: { order: 'asc' },2376groups: ['external', 'internal', 'index', 'type'],2377pathGroups: [2378{2379pattern: 'dirA/**',2380group: 'internal',2381},2382],2383'newlines-between': 'always',2384pathGroupsExcludedImportTypes: ['type'],2385},2386],2387}),2388// Option alphabetize: {order: 'asc'} with path group2389test({2390// only: true,2391code: `2392import c from 'Bar';2393import type { A } from 'foo';2394import a from 'foo';23952396import type { C } from 'dirA/Bar';2397import b from 'dirA/bar';23982399import index from './';2400`,2401...parserConfig,2402options: [2403{2404alphabetize: { order: 'asc' },2405groups: ['external', 'internal', 'index'],2406pathGroups: [2407{2408pattern: 'dirA/**',2409group: 'internal',2410},2411],2412'newlines-between': 'always',2413pathGroupsExcludedImportTypes: [],2414},2415],2416}),2417// Option alphabetize: {order: 'desc'} with type group2418test({2419code: `2420import a from 'foo';2421import b from 'bar';2422import c from 'Bar';24232424import index from './';24252426import type { A } from 'foo';2427import type { C } from 'Bar';2428`,2429...parserConfig,2430options: [2431{2432groups: ['external', 'index', 'type'],2433alphabetize: { order: 'desc' },2434},2435],2436}),2437test({2438code: `2439import { Partner } from '@models/partner/partner';2440import { PartnerId } from '@models/partner/partner-id';2441`,2442...parserConfig,2443options: [2444{2445alphabetize: { order: 'asc' },2446},2447],2448}),2449test({2450code: `2451import { serialize, parse, mapFieldErrors } from '@vtaits/form-schema';2452import type { GetFieldSchema } from '@vtaits/form-schema';2453import { useMemo, useCallback } from 'react';2454import type { ReactElement, ReactNode } from 'react';2455import { Form } from 'react-final-form';2456import type { FormProps as FinalFormProps } from 'react-final-form';2457`,2458...parserConfig,2459options: [2460{2461alphabetize: { order: 'asc' },2462},2463],2464}),2465// Imports inside module declaration2466test({2467code: `2468import type { CopyOptions } from 'fs';2469import type { ParsedPath } from 'path';24702471declare module 'my-module' {2472import type { CopyOptions } from 'fs';2473import type { ParsedPath } from 'path';2474}2475`,2476...parserConfig,2477options: [2478{2479alphabetize: { order: 'asc' },2480},2481],2482}),2483],2484invalid: [2485// Option alphabetize: {order: 'asc'}2486test({2487code: `2488import b from 'bar';2489import c from 'Bar';2490import type { C } from 'Bar';2491import a from 'foo';2492import type { A } from 'foo';24932494import index from './';2495`,2496output: `2497import c from 'Bar';2498import type { C } from 'Bar';2499import b from 'bar';2500import a from 'foo';2501import type { A } from 'foo';25022503import index from './';2504`,2505...parserConfig,2506options: [2507{2508groups: ['external', 'index'],2509alphabetize: { order: 'asc' },2510},2511],2512errors: [2513{2514message: semver.satisfies(eslintPkg.version, '< 3')2515? '`bar` import should occur after import of `Bar`'2516: /(`bar` import should occur after import of `Bar`)|(`Bar` import should occur before import of `bar`)/,2517},2518],2519}),2520// Option alphabetize: {order: 'desc'}2521test({2522code: `2523import a from 'foo';2524import type { A } from 'foo';2525import c from 'Bar';2526import type { C } from 'Bar';2527import b from 'bar';25282529import index from './';2530`,2531output: `2532import a from 'foo';2533import type { A } from 'foo';2534import b from 'bar';2535import c from 'Bar';2536import type { C } from 'Bar';25372538import index from './';2539`,2540...parserConfig,2541options: [2542{2543groups: ['external', 'index'],2544alphabetize: { order: 'desc' },2545},2546],2547errors: [2548{2549message: semver.satisfies(eslintPkg.version, '< 3')2550? '`bar` import should occur before import of `Bar`'2551: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/,2552},2553],2554}),2555// Option alphabetize: {order: 'asc'} with type group2556test({2557code: `2558import b from 'bar';2559import c from 'Bar';2560import a from 'foo';25612562import index from './';25632564import type { A } from 'foo';2565import type { C } from 'Bar';2566`,2567output: `2568import c from 'Bar';2569import b from 'bar';2570import a from 'foo';25712572import index from './';25732574import type { C } from 'Bar';2575import type { A } from 'foo';2576`,2577...parserConfig,2578options: [2579{2580groups: ['external', 'index', 'type'],2581alphabetize: { order: 'asc' },2582},2583],2584errors: semver.satisfies(eslintPkg.version, '< 3') ? [2585{ message: '`Bar` import should occur before import of `bar`' },2586{ message: '`Bar` import should occur before import of `foo`' },2587] : [2588{ message: /(`Bar` import should occur before import of `bar`)|(`bar` import should occur after import of `Bar`)/ },2589{ message: /(`Bar` import should occur before import of `foo`)|(`foo` import should occur after import of `Bar`)/ },2590],2591}),2592// Option alphabetize: {order: 'desc'} with type group2593test({2594code: `2595import a from 'foo';2596import c from 'Bar';2597import b from 'bar';25982599import index from './';26002601import type { C } from 'Bar';2602import type { A } from 'foo';2603`,2604output: `2605import a from 'foo';2606import b from 'bar';2607import c from 'Bar';26082609import index from './';26102611import type { A } from 'foo';2612import type { C } from 'Bar';2613`,2614...parserConfig,2615options: [2616{2617groups: ['external', 'index', 'type'],2618alphabetize: { order: 'desc' },2619},2620],2621errors: semver.satisfies(eslintPkg.version, '< 3') ? [2622{ message: '`bar` import should occur before import of `Bar`' },2623{ message: '`foo` import should occur before import of `Bar`' },2624] : [2625{ message: /(`bar` import should occur before import of `Bar`)|(`Bar` import should occur after import of `bar`)/ },2626{ message: /(`foo` import should occur before import of `Bar`)|(`Bar` import should occur after import of `foo`)/ },2627],2628}),2629// warns for out of order unassigned imports (warnOnUnassignedImports enabled)2630test({2631code: `2632import './local1';2633import global from 'global1';2634import local from './local2';2635import 'global2';2636`,2637output: `2638import './local1';2639import global from 'global1';2640import local from './local2';2641import 'global2';2642`,2643errors: [2644{2645message: '`global1` import should occur before import of `./local1`',2646},2647{2648message: '`global2` import should occur before import of `./local1`',2649},2650],2651options: [{ warnOnUnassignedImports: true }],2652}),2653// fix cannot move below unassigned import (warnOnUnassignedImports enabled)2654test({2655code: `2656import local from './local';26572658import 'global1';26592660import global2 from 'global2';2661import global3 from 'global3';2662`,2663output: `2664import local from './local';26652666import 'global1';26672668import global2 from 'global2';2669import global3 from 'global3';2670`,2671errors: [{2672message: '`./local` import should occur after import of `global3`',2673}],2674options: [{ warnOnUnassignedImports: true }],2675}),2676// Imports inside module declaration2677test({2678code: `2679import type { ParsedPath } from 'path';2680import type { CopyOptions } from 'fs';26812682declare module 'my-module' {2683import type { ParsedPath } from 'path';2684import type { CopyOptions } from 'fs';2685}2686`,2687output: `2688import type { CopyOptions } from 'fs';2689import type { ParsedPath } from 'path';26902691declare module 'my-module' {2692import type { CopyOptions } from 'fs';2693import type { ParsedPath } from 'path';2694}2695`,2696errors: [{2697message: '`fs` import should occur before import of `path`',2698},{2699message: '`fs` import should occur before import of `path`',2700}],2701...parserConfig,2702options: [2703{2704alphabetize: { order: 'asc' },2705},2706],2707}),2708],2709});2710});2711});271227132714