@nextcloud/eslint-config 8.2.1 → 8.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v8.3.0-beta.0](https://github.com/nextcloud/eslint-config/tree/v8.3.0-beta.0) (2023-05-12)
4
+
5
+ [Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.2.1...v8.3.0-beta.0)
6
+
7
+ **Merged pull requests:**
8
+ - Typescript 5 support
9
+ - Various dependencies upgrades
10
+
3
11
  ## [v8.2.1](https://github.com/nextcloud/eslint-config/tree/v8.2.1) (2023-01-30)
4
12
 
5
13
  [Full Changelog](https://github.com/nextcloud/eslint-config/compare/v8.2.0...v8.2.1)
package/index.js CHANGED
@@ -121,7 +121,7 @@ module.exports = {
121
121
  },
122
122
  overrides: [
123
123
  {
124
- files: ['**/*.ts'],
124
+ files: ['**/*.ts', '**/*.tsx'],
125
125
  extends: [
126
126
  '@vue/eslint-config-typescript/recommended',
127
127
  'plugin:import/typescript',
@@ -148,7 +148,7 @@ module.exports = {
148
148
  'import/resolver': {
149
149
  node: {
150
150
  paths: ['src'],
151
- extensions: ['.js', '.ts', '.vue'],
151
+ extensions: ['.(m|c)?js', '.ts', '.tsx', '.vue'],
152
152
  },
153
153
  },
154
154
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextcloud/eslint-config",
3
- "version": "8.2.1",
3
+ "version": "8.3.0-beta.0",
4
4
  "description": "Eslint shared config for nextcloud vue.js apps",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "scripts": {
11
11
  "lint": "eslint -c index.js *.js",
12
- "lint:fix": "eslint -c index.js --fix *.js"
12
+ "lint:fix": "eslint -c index.js --fix *.js",
13
+ "test": "jest"
13
14
  },
14
15
  "peerDependencies": {
15
16
  "@babel/core": "^7.13.10",
@@ -20,27 +21,30 @@
20
21
  "eslint-config-standard": "^17.0.0",
21
22
  "eslint-import-resolver-exports": "^1.0.0-beta.4",
22
23
  "eslint-plugin-import": "^2.26.0",
23
- "eslint-plugin-jsdoc": "^39.6.2",
24
+ "eslint-plugin-jsdoc": "^43.0.3",
24
25
  "eslint-plugin-n": "^15.5.1",
25
26
  "eslint-plugin-promise": "^6.1.1",
26
27
  "eslint-plugin-vue": "^9.7.0",
27
- "typescript": "^4.9.4",
28
+ "typescript": "^5.0.2",
28
29
  "webpack": "^5.4.0"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@babel/core": "^7.13.10",
32
33
  "@babel/eslint-parser": "^7.16.5",
33
34
  "@nextcloud/eslint-plugin": "^2.0.0",
35
+ "@types/jest": "^29.4.0",
34
36
  "@vue/eslint-config-typescript": "^11.0.2",
35
37
  "eslint": "^8.27.0",
36
- "eslint-import-resolver-exports": "^1.0.0-beta.4",
37
38
  "eslint-config-standard": "^17.0.0",
39
+ "eslint-import-resolver-exports": "^1.0.0-beta.4",
38
40
  "eslint-plugin-import": "^2.26.0",
39
- "eslint-plugin-jsdoc": "^39.6.2",
41
+ "eslint-plugin-jsdoc": "^43.0.3",
40
42
  "eslint-plugin-n": "^15.5.1",
41
43
  "eslint-plugin-promise": "^6.1.1",
42
44
  "eslint-plugin-vue": "^9.7.0",
43
- "typescript": "^4.9.4",
45
+ "jest": "^29.4.1",
46
+ "ts-jest": "^29.0.5",
47
+ "typescript": "^5.0.2",
44
48
  "webpack": "^5.4.0"
45
49
  },
46
50
  "keywords": [
@@ -59,5 +63,12 @@
59
63
  "engines": {
60
64
  "node": "^16.0.0",
61
65
  "npm": "^7.0.0 || ^8.0.0"
66
+ },
67
+ "jest": {
68
+ "preset": "ts-jest",
69
+ "testEnvironment": "node",
70
+ "setupFilesAfterEnv": [
71
+ "./tests/setup-jest.ts"
72
+ ]
62
73
  }
63
74
  }
@@ -0,0 +1,31 @@
1
+ import { ESLint } from "eslint"
2
+ import type { Linter } from "eslint"
3
+ import * as path from 'path'
4
+ import * as eslintConfig from '../index.js'
5
+
6
+
7
+ const eslint = new ESLint({
8
+ baseConfig: eslintConfig as unknown as Linter.Config<Linter.RulesRecord>
9
+ })
10
+
11
+ const lintFile = async (file) => {
12
+ const real = path.resolve(path.join(__dirname, file))
13
+ return await eslint.lintFiles(real)
14
+ }
15
+
16
+ test('some basic issues should fail', async () => {
17
+ const results = await lintFile('fixtures/example-fail.js')
18
+ expect(results).toHaveIssueCount(3)
19
+ expect(results).toHaveIssue('spaced-comment')
20
+ expect(results).toHaveIssue({ ruleId: 'no-console', line: 3 })
21
+ })
22
+
23
+ test('TSX is linted', async () => {
24
+ const ignored = await eslint.isPathIgnored('./fixtures/some.tsx')
25
+ expect(ignored).toBe(false)
26
+
27
+ const results = await lintFile('fixtures/some.tsx')
28
+ expect(results).toHaveIssue({ruleId: 'jsdoc/check-tag-names', line: 5})
29
+ expect(results).toHaveIssue({ruleId: '@typescript-eslint/no-unused-vars', line: 7})
30
+ expect(results).toHaveIssueCount(2)
31
+ })
@@ -0,0 +1,11 @@
1
+ export { }
2
+
3
+ declare global {
4
+ namespace jest {
5
+ interface Matchers<R> {
6
+ toPass(): R;
7
+ toHaveIssueCount(n: number): R;
8
+ toHaveIssue(issue: string | {ruleId: string, line?: number}): R;
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,3 @@
1
+ //should fail because of missing space on this comment
2
+ // and usage of `console` and using a semicolon
3
+ console.log('some');
@@ -0,0 +1,7 @@
1
+ // TSX
2
+
3
+ /**
4
+ * @notExported <- should work
5
+ * @aaabbbcccddd <- should fail
6
+ */
7
+ const foo = '' // <- should fail, as unused
@@ -0,0 +1,128 @@
1
+ import { ESLint, Linter } from "eslint"
2
+
3
+ /**
4
+ * Add some custom matchers for ESLint to jest
5
+ */
6
+ expect.extend({
7
+ toPass: assertLintingPassed,
8
+ toHaveIssueCount: assertHavingNIssues,
9
+ toHaveIssue: assertHavingIssue
10
+ })
11
+
12
+ /**
13
+ * Check if linting a file did not throw any errors or warnings
14
+ *
15
+ * @param received Lint result
16
+ */
17
+ function hasNoIssues(received: ESLint.LintResult) {
18
+ // dirty type check
19
+ if (received?.errorCount === undefined) throw new Error('Expected ESLintResult')
20
+
21
+ return received.errorCount === 0 && received.warningCount === 0
22
+ }
23
+
24
+ /**
25
+ * Check if linting of multiple fils
26
+ *
27
+ * @param received
28
+ * @returns {}
29
+ */
30
+ function assertLintingPassed(received: ESLint.LintResult | ESLint.LintResult[]) {
31
+ // allow single ESLintResult
32
+ if (!Array.isArray(received)) {
33
+ received = [received]
34
+ }
35
+
36
+ const errors = [] as {file: string, errors: Linter.LintMessage[]}[]
37
+ const pass = received.every((result) => {
38
+ // save issues
39
+ errors.push({file: result.filePath, errors: result.messages})
40
+ return hasNoIssues(result)
41
+ })
42
+
43
+ return {
44
+ pass,
45
+ message: () => {
46
+ if (pass) {
47
+ return 'Expected file to not pass eslint, but got no issues'
48
+ } else {
49
+ const errorMessages = errors.map((m) =>
50
+ `file: ${m.file}\n` + m.errors.map((e) => 'line: ' + e.line + ': ' + (e.ruleId || e.message))
51
+ )
52
+ return 'Expected file to pass eslint, got issues:\n' + errorMessages.join('\n')
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Count the total amount of issues
60
+ *
61
+ * @param received lint result
62
+ * @returns total amount of issues
63
+ */
64
+ function countIssues(received: ESLint.LintResult) {
65
+ return received.errorCount + received.warningCount
66
+ }
67
+
68
+ /**
69
+ * Check if exactly the same number of issues is reported
70
+ *
71
+ * @param received the lint result
72
+ * @param expected number of expected issues
73
+ * @returns jest matcher result
74
+ */
75
+ function assertHavingNIssues(received: ESLint.LintResult | ESLint.LintResult[], expected: number) {
76
+ if (!(typeof expected === 'number')) throw new Error('Expected a number as expected value')
77
+
78
+ if (!Array.isArray(received)) {
79
+ received = [received]
80
+ }
81
+
82
+ const issues = received.map(countIssues).reduce((p, c) => p + c)
83
+ const pass = issues === expected
84
+
85
+ return {
86
+ pass,
87
+ message: () => pass ? `Expected not to find exactly ${expected} issues.` : `Expected ${expected} issues, found ${issues}`
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Check if result contains the expected issue
93
+ *
94
+ * @param received the lint result
95
+ * @param issue the expected issue
96
+ * @returns jest matcher result
97
+ */
98
+ function assertHavingIssue(received: ESLint.LintResult | ESLint.LintResult[], issue: string | {ruleId: string, line?: number}) {
99
+ if (!Array.isArray(received)) {
100
+ received = [received]
101
+ }
102
+
103
+ // Should not pass
104
+ if (assertLintingPassed(received).pass) {
105
+ return {
106
+ pass: false,
107
+ message: () => 'Expected issue, but no linting issues found.'
108
+ }
109
+ }
110
+
111
+ const name = typeof issue === 'string' ? issue : issue.ruleId
112
+ const result = received.some((result) => {
113
+ return result.messages.some((message) => {
114
+ // ensure name matches
115
+ if (message.ruleId !== name) return false
116
+ // if line is requested ignore not matching ones
117
+ if (typeof issue === 'object' && issue.line !== undefined && issue.line !== message.line) return false
118
+ // otherwise matched
119
+ return true
120
+ })
121
+ });
122
+
123
+ const onLine = typeof issue === 'string' ? '' : ` on line ${issue.line}`
124
+ return {
125
+ pass: result,
126
+ message: () => result ? `Unexpected error '${name}'${onLine} found.` : `Expected error '${name}'${onLine} not found.`
127
+ }
128
+ }