Skip to content

Commit a3972e8

Browse files
committed
100% coverage; lint
1 parent 7391fbb commit a3972e8

13 files changed

+177
-12
lines changed

jest.config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ module.exports = {
44
coverageReporters: [['text', { skipFull: false, skipEmpty: true }], 'lcov'],
55
coverageThreshold: {
66
global: {
7-
branches: 94,
7+
branches: 100,
88
functions: 100,
99
lines: 100,
10-
statements: 98,
10+
statements: 100,
1111
},
1212
},
1313
moduleDirectories: ['node_modules', 'src'],

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,19 @@
3535
"docs": "eslint-docs",
3636
"format": "prettier --write src/**/*.{js,ts} tests/**/*.{js,ts}",
3737
"lint": "eslint --ext .js,.ts src/ tests/",
38+
"lint:fix": "yarn lint --fix",
3839
"prepublishOnly": "MINIFY=1 yarn build",
3940
"purge": "yarn -s rimraf node_modules lib",
4041
"test:autofix": "yarn -s jest ./tests/autofix.spec.ts",
4142
"test:config": "yarn -s jest ./tests/config.spec.ts",
43+
"test:enum": "yarn -s jest ./tests/rules/enum/*.spec.ts",
4244
"test:interface": "yarn -s jest ./tests/rules/interface/*.spec.ts",
4345
"test:rules": "yarn -s jest ./tests/rules/*/*.spec.ts --collectCoverage=true",
44-
"test:enum": "yarn -s jest ./tests/rules/enum/*.spec.ts",
4546
"test:watch:autofix": "yarn jest --watch ./tests/autofix.spec.ts",
4647
"test:watch:config": "yarn jest --watch ./tests/config.spec.ts",
48+
"test:watch:enum": "yarn jest --watch ./tests/rules/enum/*.spec.ts",
4749
"test:watch:interface": "yarn jest --watch ./tests/rules/interface/*.spec.ts",
4850
"test:watch:rules": "yarn jest --watch ./tests/rules/*/*.spec.ts",
49-
"test:watch:enum": "yarn jest --watch ./tests/rules/enum/*.spec.ts",
5051
"test:watch": "yarn -s jest --watch .*.spec.ts",
5152
"test": "yarn -s jest .*.spec.ts --collectCoverage=true",
5253
"typecheck": "tsc --noEmit --skipLibCheck",
@@ -74,7 +75,7 @@
7475
"@types/node": "^18.0.0",
7576
"@types/tmp": "~0.2.4",
7677
"@typescript-eslint/eslint-plugin": "^6.7.4",
77-
"@typescript-eslint/parser": "^6.7.4",
78+
"@typescript-eslint/parser": "~6.13.2",
7879
"babel-jest": "~29.7.0",
7980
"babel-plugin-module-resolver": "~5.0.0",
8081
"chalk": "~5.3.0",

src/config/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const PLUGIN_NAME = 'typescript-sort-keys'
1+
export const PLUGIN_NAME = 'typescript-sort-keys'

src/utils/sourcecode/commentHelpers.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from '@typescript-eslint/utils'
21
import { Node, SourceCode } from 'types'
2+
3+
import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from '@typescript-eslint/utils'
4+
35
import { getLatestNode } from './nodeHelpers'
46
import {
57
getDeclarationPunctuators,

src/utils/sourcecode/nodeHelpers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ export function getNextNonCommentNode(sourceCode: SourceCode, node: Node) {
2323
return nextNode ?? undefined
2424
}
2525
export function getPreviousNonCommentNode(sourceCode: SourceCode, node: Node) {
26-
const nextNode = sourceCode.getTokenBefore(node, { includeComments: false })
27-
return nextNode ?? undefined
26+
const prevNode = sourceCode.getTokenBefore(node, { includeComments: false })
27+
return prevNode ?? undefined
2828
}

src/utils/sourcecode/punctuationHelpers.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'
21
import assert from 'assert'
32
import { Node, SourceCode } from 'types'
3+
4+
import { AST_NODE_TYPES, AST_TOKEN_TYPES } from '@typescript-eslint/utils'
5+
46
import {
57
getEarliestNode,
68
getLatestNode,
@@ -31,6 +33,7 @@ export function getNodePunctuator(
3133
includeComments: false,
3234
})
3335
// Ensure we don't go beyond the parent into the source code
36+
3437
return punctuator && punctuator.range[1] <= (node.parent?.range[1] || Infinity)
3538
? punctuator
3639
: undefined

tests/autofix.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { ESLint } from '@typescript-eslint/utils/ts-eslint'
21
import fs from 'fs'
32
import path from 'path'
43
import tmp from 'tmp'
4+
5+
import { ESLint } from '@typescript-eslint/utils/ts-eslint'
6+
57
import { Config, getESLint } from './helpers/eslint'
68

79
describe('autofix', () => {

tests/helpers/eslint.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
import { Linter } from 'eslint'
2+
13
import { ESLint } from '@typescript-eslint/utils/ts-eslint'
24

35
import plugin from '../../src'
46
import recommended from '../../src/config/recommended.config'
57
import requiredFirst from '../../src/config/requiredFirst.config'
68
import { typescriptConfig } from './configs'
79

10+
// eslint-disable-next-line @typescript-eslint/no-var-requires
11+
const parser = require('@typescript-eslint/parser')
12+
813
export enum Config {
914
Recommended,
1015
RequiredFirst,
@@ -30,3 +35,32 @@ export function getESLint(config: Config, fix = true) {
3035
})
3136
return eslint
3237
}
38+
39+
// For unit testing
40+
export function getSourceCode(code: string) {
41+
const linter = new Linter()
42+
linter.defineParser('@typescript-eslint/parser', parser)
43+
44+
const config = {
45+
parser: '@typescript-eslint/parser',
46+
parserOptions: {
47+
ecmaVersion: 'latest',
48+
sourceType: 'module',
49+
},
50+
rules: {},
51+
settings: {
52+
'import/parsers': {
53+
'@typescript-eslint/parser': ['.ts', '.tsx'],
54+
},
55+
'import/resolver': {
56+
typescript: {
57+
alwaysTryTypes: true,
58+
},
59+
},
60+
},
61+
} as Linter.Config
62+
63+
const messages = linter.verify(code, config)
64+
65+
return messages[0]?.fatal ? null : linter.getSourceCode()
66+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { AST_TOKEN_TYPES, TSESTree } from '@typescript-eslint/utils'
2+
3+
import { getCommentsBefore } from '../../../../src/utils/sourcecode'
4+
import { getSourceCode } from '../../../helpers/eslint'
5+
6+
describe('commentHelpers.spec.ts coverage', () => {
7+
it('returns empty array with no prevNode', () => {
8+
const code = 'enum U {A = "a", B = "b", C = "c"}'
9+
const sourceCode = getSourceCode(code)
10+
const result = getCommentsBefore(sourceCode, sourceCode.getNodeByRangeIndex(0))
11+
expect(result).toEqual([])
12+
})
13+
14+
it('returns comment of specified type', () => {
15+
const code = 'enum U {A = "a", /* b */ B = "b", C = "c"}'
16+
const sourceCode = getSourceCode(code)
17+
const result: TSESTree.Comment[] = getCommentsBefore(
18+
sourceCode,
19+
sourceCode.getTokenByRangeStart(code.indexOf('B')),
20+
AST_TOKEN_TYPES.Block,
21+
)
22+
expect(result[0].value).toBe(' b ')
23+
})
24+
})
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import {
2+
getEarliestNode,
3+
getNextNonCommentNode,
4+
getPreviousNonCommentNode,
5+
} from '../../../../src/utils/sourcecode'
6+
import { getSourceCode } from '../../../helpers/eslint'
7+
8+
describe('nodeHelpers.spec.ts coverage', () => {
9+
const code = 'enum U /**/{/**/A = "a", /**/B = "b", /**/C = "c"}/**/'
10+
const sourceCode = getSourceCode(code)
11+
const nodes = ['A', 'B', 'C'].map(_ => sourceCode.getNodeByRangeIndex(code.indexOf(_)))
12+
13+
describe('getEarliestNode', () => {
14+
it('returns correct value from out of order array', () => {
15+
const nodesReversed = Array.from(nodes).reverse()
16+
const result = getEarliestNode(nodesReversed)
17+
expect(result).toEqual(nodes[0])
18+
})
19+
})
20+
21+
describe('getNextNonCommentNode', () => {
22+
it('returns nullish when given final node', () => {
23+
const result = getNextNonCommentNode(
24+
sourceCode,
25+
sourceCode.getNodeByRangeIndex(code.indexOf('}')),
26+
)
27+
expect(result).toBeFalsy()
28+
})
29+
it('returns truthy when given middle node', () => {
30+
const result = getNextNonCommentNode(sourceCode, nodes[1])
31+
expect(result).toBeTruthy()
32+
})
33+
})
34+
35+
describe('getPreviousNonCommentNode', () => {
36+
it('returns nullish when given first node', () => {
37+
const result = getPreviousNonCommentNode(
38+
sourceCode,
39+
sourceCode.getNodeByRangeIndex(code.indexOf('{')),
40+
)
41+
expect(result).toBeFalsy()
42+
})
43+
it('returns truthy when given middle node', () => {
44+
const result = getPreviousNonCommentNode(sourceCode, nodes[1])
45+
expect(result).toBeTruthy()
46+
})
47+
})
48+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { getNodePunctuator } from '../../../../src/utils/sourcecode'
2+
import { getSourceCode } from '../../../helpers/eslint'
3+
4+
describe('punctuationHelpers.spec.ts coverage', () => {
5+
describe('getNodePunctuator', () => {
6+
it('returns nullish', () => {
7+
const code = 'enum U {A = "a"}'
8+
const sourceCode = getSourceCode(code)
9+
const result = getNodePunctuator(
10+
sourceCode,
11+
sourceCode.getNodeByRangeIndex(code.indexOf('A')),
12+
)
13+
expect(result).toBeFalsy()
14+
})
15+
16+
it('returns punctuator when node parent is nullish', () => {
17+
const code = 'interface U {A: string; b: string;}'
18+
const sourceCode = getSourceCode(code)
19+
const node = sourceCode.getNodeByRangeIndex(code.indexOf('A'))
20+
node['parent'] = undefined
21+
22+
const result = getNodePunctuator(sourceCode, node)
23+
expect(result).toBeTruthy()
24+
})
25+
})
26+
})
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import {
2+
getTextBetweenNodeAndNext,
3+
getTextBetweenNodeAndPrevious,
4+
} from '../../../../src/utils/sourcecode'
5+
import { getSourceCode } from '../../../helpers/eslint'
6+
7+
describe('textHelpers.spec.ts coverage', () => {
8+
const code = 'enum U {A = "a", B = "b"}'
9+
const sourceCode = getSourceCode(code)
10+
const nodes = ['{', '}'].map(_ => sourceCode.getNodeByRangeIndex(code.indexOf(_)))
11+
12+
describe('getTextBetweenNodeAndPrevious', () => {
13+
it('returns empty string given first node', () => {
14+
const result = getTextBetweenNodeAndPrevious(sourceCode, nodes[0])
15+
expect(result).toBe('')
16+
})
17+
})
18+
19+
describe('getTextBetweenNodeAndNext', () => {
20+
it('returns empty string given last node', () => {
21+
const result = getTextBetweenNodeAndNext(sourceCode, nodes.at(-1))
22+
expect(result).toBe('')
23+
})
24+
})
25+
})

yarn.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@
16781678
semver "^7.5.4"
16791679
ts-api-utils "^1.0.1"
16801680

1681-
"@typescript-eslint/parser@^6.7.4":
1681+
"@typescript-eslint/parser@~6.13.2":
16821682
version "6.13.2"
16831683
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.13.2.tgz#390b79cc9a57a5f904d197a201cc4b6bc4f9afb9"
16841684
integrity sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==

0 commit comments

Comments
 (0)