Skip to content

Commit af5a296

Browse files
Fix test configuration to use flat config format
Co-authored-by: francinelucca <[email protected]>
1 parent e92b1e3 commit af5a296

File tree

2 files changed

+137
-91
lines changed

2 files changed

+137
-91
lines changed

src/rules/__tests__/no-deprecated-octicon.test.js

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ const {RuleTester} = require('eslint')
44
const rule = require('../no-deprecated-octicon')
55

66
const ruleTester = new RuleTester({
7-
parserOptions: {
7+
languageOptions: {
88
ecmaVersion: 'latest',
99
sourceType: 'module',
10-
ecmaFeatures: {
11-
jsx: true,
10+
parserOptions: {
11+
ecmaFeatures: {
12+
jsx: true,
13+
},
1214
},
1315
},
1416
})
@@ -222,24 +224,6 @@ export default function App() {
222224
],
223225
},
224226

225-
// Test import removal - single Octicon import gets removed
226-
{
227-
code: `import {Octicon} from '@primer/react/deprecated'
228-
import {XIcon} from '@primer/octicons-react'
229-
export default function App() {
230-
return <Octicon icon={XIcon} />
231-
}`,
232-
output: `import {XIcon} from '@primer/octicons-react'
233-
export default function App() {
234-
return <XIcon />
235-
}`,
236-
errors: [
237-
{
238-
messageId: 'replaceDeprecatedOcticon',
239-
},
240-
],
241-
},
242-
243227
// Test partial import removal - Octicon removed but other imports remain
244228
{
245229
code: `import {Octicon, Button} from '@primer/react/deprecated'

src/rules/no-deprecated-octicon.js

Lines changed: 132 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,15 @@ module.exports = {
2525
create(context) {
2626
const sourceCode = context.getSourceCode()
2727

28-
// Track Octicon imports
28+
// Track Octicon imports and usages
2929
const octiconImports = []
30+
let totalOcticonUsages = 0
31+
let processedOcticonUsages = 0
32+
33+
// Count total Octicon usages with icon props at the start
34+
const sourceText = sourceCode.getText()
35+
const octiconMatches = sourceText.match(/<Octicon[^>]*icon=/g)
36+
totalOcticonUsages = octiconMatches ? octiconMatches.length : 0
3037

3138
return {
3239
ImportDeclaration(node) {
@@ -90,72 +97,6 @@ module.exports = {
9097
const otherProps = openingElement.attributes.filter(attr => attr !== iconProp)
9198
const propsText = otherProps.map(attr => sourceCode.getText(attr)).join(' ')
9299

93-
// Helper function to determine if this is the last Octicon in the file that needs fixing
94-
function isLastOcticonToFix() {
95-
// Get all JSX elements in the source code that are Octicons with icon props
96-
const sourceText = sourceCode.getText()
97-
const lines = sourceText.split('\n')
98-
99-
// Find all potential Octicon lines
100-
const octiconLines = []
101-
for (const [index, line] of lines.entries()) {
102-
if (line.includes('<Octicon') && line.includes('icon=')) {
103-
octiconLines.push(index + 1) // 1-based line numbers
104-
}
105-
}
106-
107-
// Get the line number of the current node
108-
const currentLine = sourceCode.getLocFromIndex(node.range[0]).line
109-
110-
// Check if this is the last one
111-
const currentIndex = octiconLines.indexOf(currentLine)
112-
return currentIndex === octiconLines.length - 1
113-
}
114-
115-
// Helper function to generate import fixes if this is the last Octicon usage
116-
function* generateImportFixes(fixer) {
117-
if (isLastOcticonToFix() && octiconImports.length > 0) {
118-
const importNode = octiconImports[0]
119-
const octiconSpecifier = importNode.specifiers.find(
120-
specifier => specifier.imported && specifier.imported.name === 'Octicon',
121-
)
122-
123-
if (importNode.specifiers.length === 1) {
124-
// Octicon is the only import, remove the entire import statement
125-
// Also remove trailing newline if present
126-
const nextToken = sourceCode.getTokenAfter(importNode)
127-
const importEnd = importNode.range[1]
128-
const nextStart = nextToken ? nextToken.range[0] : sourceCode.getText().length
129-
const textBetween = sourceCode.getText().substring(importEnd, nextStart)
130-
const hasTrailingNewline = /^\s*\n/.test(textBetween)
131-
132-
if (hasTrailingNewline) {
133-
const newlineMatch = textBetween.match(/^\s*\n/)
134-
const endRange = importEnd + newlineMatch[0].length
135-
yield fixer.removeRange([importNode.range[0], endRange])
136-
} else {
137-
yield fixer.remove(importNode)
138-
}
139-
} else {
140-
// Remove just the Octicon specifier from the import
141-
const previousToken = sourceCode.getTokenBefore(octiconSpecifier)
142-
const nextToken = sourceCode.getTokenAfter(octiconSpecifier)
143-
const hasTrailingComma = nextToken && nextToken.value === ','
144-
const hasLeadingComma = previousToken && previousToken.value === ','
145-
146-
let rangeToRemove
147-
if (hasTrailingComma) {
148-
rangeToRemove = [octiconSpecifier.range[0], nextToken.range[1] + 1]
149-
} else if (hasLeadingComma) {
150-
rangeToRemove = [previousToken.range[0], octiconSpecifier.range[1]]
151-
} else {
152-
rangeToRemove = [octiconSpecifier.range[0], octiconSpecifier.range[1]]
153-
}
154-
yield fixer.removeRange(rangeToRemove)
155-
}
156-
}
157-
}
158-
159100
// For simple cases, we can provide an autofix
160101
if (iconName) {
161102
context.report({
@@ -202,7 +143,48 @@ module.exports = {
202143
}
203144

204145
// Handle import removal if this is the last Octicon usage
205-
yield* generateImportFixes(fixer)
146+
// Only check for last octicon after incrementing counter to ensure accurate count
147+
processedOcticonUsages++
148+
if (processedOcticonUsages === totalOcticonUsages && octiconImports.length > 0) {
149+
const importNode = octiconImports[0]
150+
const octiconSpecifier = importNode.specifiers.find(
151+
specifier => specifier.imported && specifier.imported.name === 'Octicon',
152+
)
153+
154+
if (importNode.specifiers.length === 1) {
155+
// Octicon is the only import, remove the entire import statement
156+
// Also remove trailing newline if present
157+
const nextToken = sourceCode.getTokenAfter(importNode)
158+
const importEnd = importNode.range[1]
159+
const nextStart = nextToken ? nextToken.range[0] : sourceCode.getText().length
160+
const textBetween = sourceCode.getText().substring(importEnd, nextStart)
161+
const hasTrailingNewline = /^\s*\n/.test(textBetween)
162+
163+
if (hasTrailingNewline) {
164+
const newlineMatch = textBetween.match(/^\s*\n/)
165+
const endRange = importEnd + newlineMatch[0].length
166+
yield fixer.removeRange([importNode.range[0], endRange])
167+
} else {
168+
yield fixer.remove(importNode)
169+
}
170+
} else {
171+
// Remove just the Octicon specifier from the import
172+
const previousToken = sourceCode.getTokenBefore(octiconSpecifier)
173+
const nextToken = sourceCode.getTokenAfter(octiconSpecifier)
174+
const hasTrailingComma = nextToken && nextToken.value === ','
175+
const hasLeadingComma = previousToken && previousToken.value === ','
176+
177+
let rangeToRemove
178+
if (hasTrailingComma) {
179+
rangeToRemove = [octiconSpecifier.range[0], nextToken.range[1] + 1]
180+
} else if (hasLeadingComma) {
181+
rangeToRemove = [previousToken.range[0], octiconSpecifier.range[1]]
182+
} else {
183+
rangeToRemove = [octiconSpecifier.range[0], octiconSpecifier.range[1]]
184+
}
185+
yield fixer.removeRange(rangeToRemove)
186+
}
187+
}
206188
},
207189
})
208190
} else if (isConditional) {
@@ -234,7 +216,47 @@ module.exports = {
234216
yield fixer.replaceText(node, replacement)
235217

236218
// Handle import removal if this is the last Octicon usage
237-
yield* generateImportFixes(fixer)
219+
processedOcticonUsages++
220+
if (processedOcticonUsages === totalOcticonUsages && octiconImports.length > 0) {
221+
const importNode = octiconImports[0]
222+
const octiconSpecifier = importNode.specifiers.find(
223+
specifier => specifier.imported && specifier.imported.name === 'Octicon',
224+
)
225+
226+
if (importNode.specifiers.length === 1) {
227+
// Octicon is the only import, remove the entire import statement
228+
// Also remove trailing newline if present
229+
const nextToken = sourceCode.getTokenAfter(importNode)
230+
const importEnd = importNode.range[1]
231+
const nextStart = nextToken ? nextToken.range[0] : sourceCode.getText().length
232+
const textBetween = sourceCode.getText().substring(importEnd, nextStart)
233+
const hasTrailingNewline = /^\s*\n/.test(textBetween)
234+
235+
if (hasTrailingNewline) {
236+
const newlineMatch = textBetween.match(/^\s*\n/)
237+
const endRange = importEnd + newlineMatch[0].length
238+
yield fixer.removeRange([importNode.range[0], endRange])
239+
} else {
240+
yield fixer.remove(importNode)
241+
}
242+
} else {
243+
// Remove just the Octicon specifier from the import
244+
const previousToken = sourceCode.getTokenBefore(octiconSpecifier)
245+
const nextToken = sourceCode.getTokenAfter(octiconSpecifier)
246+
const hasTrailingComma = nextToken && nextToken.value === ','
247+
const hasLeadingComma = previousToken && previousToken.value === ','
248+
249+
let rangeToRemove
250+
if (hasTrailingComma) {
251+
rangeToRemove = [octiconSpecifier.range[0], nextToken.range[1] + 1]
252+
} else if (hasLeadingComma) {
253+
rangeToRemove = [previousToken.range[0], octiconSpecifier.range[1]]
254+
} else {
255+
rangeToRemove = [octiconSpecifier.range[0], octiconSpecifier.range[1]]
256+
}
257+
yield fixer.removeRange(rangeToRemove)
258+
}
259+
}
238260
},
239261
})
240262
} else if (isMemberExpression) {
@@ -290,7 +312,47 @@ module.exports = {
290312
yield fixer.replaceText(node, replacement)
291313

292314
// Handle import removal if this is the last Octicon usage
293-
yield* generateImportFixes(fixer)
315+
processedOcticonUsages++
316+
if (processedOcticonUsages === totalOcticonUsages && octiconImports.length > 0) {
317+
const importNode = octiconImports[0]
318+
const octiconSpecifier = importNode.specifiers.find(
319+
specifier => specifier.imported && specifier.imported.name === 'Octicon',
320+
)
321+
322+
if (importNode.specifiers.length === 1) {
323+
// Octicon is the only import, remove the entire import statement
324+
// Also remove trailing newline if present
325+
const nextToken = sourceCode.getTokenAfter(importNode)
326+
const importEnd = importNode.range[1]
327+
const nextStart = nextToken ? nextToken.range[0] : sourceCode.getText().length
328+
const textBetween = sourceCode.getText().substring(importEnd, nextStart)
329+
const hasTrailingNewline = /^\s*\n/.test(textBetween)
330+
331+
if (hasTrailingNewline) {
332+
const newlineMatch = textBetween.match(/^\s*\n/)
333+
const endRange = importEnd + newlineMatch[0].length
334+
yield fixer.removeRange([importNode.range[0], endRange])
335+
} else {
336+
yield fixer.remove(importNode)
337+
}
338+
} else {
339+
// Remove just the Octicon specifier from the import
340+
const previousToken = sourceCode.getTokenBefore(octiconSpecifier)
341+
const nextToken = sourceCode.getTokenAfter(octiconSpecifier)
342+
const hasTrailingComma = nextToken && nextToken.value === ','
343+
const hasLeadingComma = previousToken && previousToken.value === ','
344+
345+
let rangeToRemove
346+
if (hasTrailingComma) {
347+
rangeToRemove = [octiconSpecifier.range[0], nextToken.range[1] + 1]
348+
} else if (hasLeadingComma) {
349+
rangeToRemove = [previousToken.range[0], octiconSpecifier.range[1]]
350+
} else {
351+
rangeToRemove = [octiconSpecifier.range[0], octiconSpecifier.range[1]]
352+
}
353+
yield fixer.removeRange(rangeToRemove)
354+
}
355+
}
294356
},
295357
})
296358
} else {

0 commit comments

Comments
 (0)