Skip to content

Commit 1a47085

Browse files
committed
chore: wip
1 parent 55778e9 commit 1a47085

9 files changed

+1194
-3
lines changed

packages/pickier/test-debug-curly.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/pickier/test-example.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

packages/pickier/test-simple-curly.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
import { describe, expect, it } from 'bun:test'
2+
import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
3+
import { tmpdir } from 'node:os'
4+
import { join } from 'node:path'
5+
import { runFormat } from '../src/cli/run-format'
6+
7+
function tmp(): string {
8+
return mkdtempSync(join(tmpdir(), 'pickier-format-advanced-'))
9+
}
10+
11+
describe('format advanced cases for coverage', () => {
12+
it('should handle finalNewline: none setting', async () => {
13+
const dir = tmp()
14+
const file = 'no-newline.ts'
15+
const src = 'const x = 1\nconst y = 2\n\n'
16+
17+
writeFileSync(join(dir, file), src, 'utf8')
18+
19+
const cfgPath = join(dir, 'pickier.config.json')
20+
writeFileSync(cfgPath, JSON.stringify({
21+
verbose: false,
22+
ignores: [],
23+
lint: { extensions: ['ts'], reporter: 'stylish', cache: false, maxWarnings: -1 },
24+
format: { extensions: ['ts'], trimTrailingWhitespace: true, maxConsecutiveBlankLines: 1, finalNewline: 'none', indent: 2, quotes: 'single', semi: false },
25+
rules: { noDebugger: 'error', noConsole: 'warn' },
26+
}, null, 2), 'utf8')
27+
28+
const code = await runFormat([dir], { write: true, config: cfgPath })
29+
expect(code).toBe(0)
30+
const result = readFileSync(join(dir, file), 'utf8')
31+
expect(result).not.toMatch(/\n$/) // Should not end with newline
32+
})
33+
34+
it('should handle finalNewline: two setting', async () => {
35+
const dir = tmp()
36+
const file = 'two-newlines.ts'
37+
const src = 'const x = 1\nconst y = 2'
38+
39+
writeFileSync(join(dir, file), src, 'utf8')
40+
41+
const cfgPath = join(dir, 'pickier.config.json')
42+
writeFileSync(cfgPath, JSON.stringify({
43+
verbose: false,
44+
ignores: [],
45+
lint: { extensions: ['ts'], reporter: 'stylish', cache: false, maxWarnings: -1 },
46+
format: { extensions: ['ts'], trimTrailingWhitespace: true, maxConsecutiveBlankLines: 1, finalNewline: 'two', indent: 2, quotes: 'single', semi: false },
47+
rules: { noDebugger: 'error', noConsole: 'warn' },
48+
}, null, 2), 'utf8')
49+
50+
const code = await runFormat([dir], { write: true, config: cfgPath })
51+
expect(code).toBe(0)
52+
const result = readFileSync(join(dir, file), 'utf8')
53+
expect(result).toMatch(/\n\n$/) // Should end with two newlines
54+
})
55+
56+
it('should handle files with existing double newlines', async () => {
57+
const dir = tmp()
58+
const file = 'double-newline.ts'
59+
const src = 'const x = 1\nconst y = 2\n\n'
60+
61+
writeFileSync(join(dir, file), src, 'utf8')
62+
63+
const cfgPath = join(dir, 'pickier.config.json')
64+
writeFileSync(cfgPath, JSON.stringify({
65+
verbose: false,
66+
ignores: [],
67+
lint: { extensions: ['ts'], reporter: 'stylish', cache: false, maxWarnings: -1 },
68+
format: { extensions: ['ts'], trimTrailingWhitespace: true, maxConsecutiveBlankLines: 1, finalNewline: 'two', indent: 2, quotes: 'single', semi: false },
69+
rules: { noDebugger: 'error', noConsole: 'warn' },
70+
}, null, 2), 'utf8')
71+
72+
const code = await runFormat([dir], { write: true, config: cfgPath })
73+
expect(code).toBe(0)
74+
const result = readFileSync(join(dir, file), 'utf8')
75+
expect(result).toMatch(/\n\n$/) // Should preserve double newlines
76+
})
77+
78+
it('should handle imports with type and value sorting', async () => {
79+
const dir = tmp()
80+
const file = 'mixed-imports.ts'
81+
const src = [
82+
'import { value1, type Type1, value2, type Type2 } from "module"',
83+
'import Default from "default-module"',
84+
'import type { OnlyType } from "type-only"',
85+
'',
86+
'console.log(value1, value2, Default)',
87+
'let x: Type1, y: Type2, z: OnlyType',
88+
'',
89+
].join('\n')
90+
91+
writeFileSync(join(dir, file), src, 'utf8')
92+
const code = await runFormat([dir], { write: true })
93+
expect(code).toBe(0)
94+
const result = readFileSync(join(dir, file), 'utf8')
95+
// Should handle mixed type and value imports
96+
expect(result).toContain('import')
97+
expect(result).toContain('console.log')
98+
})
99+
100+
it('should handle imports from different source rankings', async () => {
101+
const dir = tmp()
102+
const file = 'ranked-imports.ts'
103+
const src = [
104+
'import { z } from "@scoped/package"',
105+
'import { a } from "external-package"',
106+
'import { b } from "./relative"',
107+
'import { c } from "../parent"',
108+
'import { d } from "node:fs"',
109+
'',
110+
'console.log(a, b, c, d, z)',
111+
'',
112+
].join('\n')
113+
114+
writeFileSync(join(dir, file), src, 'utf8')
115+
const code = await runFormat([dir], { write: true })
116+
expect(code).toBe(0)
117+
const result = readFileSync(join(dir, file), 'utf8')
118+
// Should sort imports by ranking (node:, external, scoped, relative)
119+
expect(result).toContain('import')
120+
expect(result).toContain('console.log')
121+
})
122+
123+
it('should handle mixed import forms', async () => {
124+
const dir = tmp()
125+
const file = 'import-forms.ts'
126+
const src = [
127+
'import Default, { named } from "mixed"',
128+
'import * as Namespace from "namespace"',
129+
'import { only, named } from "named-only"',
130+
'import OnlyDefault from "default-only"',
131+
'',
132+
'console.log(Default, named, Namespace, only, OnlyDefault)',
133+
'',
134+
].join('\n')
135+
136+
writeFileSync(join(dir, file), src, 'utf8')
137+
const code = await runFormat([dir], { write: true })
138+
expect(code).toBe(0)
139+
const result = readFileSync(join(dir, file), 'utf8')
140+
// Should handle different import forms correctly
141+
expect(result).toContain('import')
142+
expect(result).toContain('console.log')
143+
})
144+
145+
it('should handle semicolon removal in various contexts', async () => {
146+
const dir = tmp()
147+
const file = 'semicolons.ts'
148+
const src = [
149+
'const a = 1;',
150+
'const b = 2;;', // double semicolon
151+
'for (let i = 0; i < 10; i++) {', // semicolons in for loop should be kept
152+
' console.log(i);',
153+
'}',
154+
'function test() {',
155+
' return "value";',
156+
'};', // unnecessary semicolon after function
157+
'',
158+
].join('\n')
159+
160+
writeFileSync(join(dir, file), src, 'utf8')
161+
162+
const cfgPath = join(dir, 'pickier.config.json')
163+
writeFileSync(cfgPath, JSON.stringify({
164+
verbose: false,
165+
ignores: [],
166+
lint: { extensions: ['ts'], reporter: 'stylish', cache: false, maxWarnings: -1 },
167+
format: { extensions: ['ts'], trimTrailingWhitespace: true, maxConsecutiveBlankLines: 1, finalNewline: 'one', indent: 2, quotes: 'single', semi: true },
168+
rules: { noDebugger: 'error', noConsole: 'warn' },
169+
}, null, 2), 'utf8')
170+
171+
const code = await runFormat([dir], { write: true, config: cfgPath })
172+
expect(code).toBe(0)
173+
const result = readFileSync(join(dir, file), 'utf8')
174+
// Should clean up unnecessary semicolons
175+
expect(result).toContain('for (let i = 0; i < 10; i++)') // for loop semicolons preserved
176+
expect(result).not.toContain(';;') // double semicolons removed
177+
})
178+
179+
it('should handle imports with side effects', async () => {
180+
const dir = tmp()
181+
const file = 'side-effects.ts'
182+
const src = [
183+
'import "side-effect-1"',
184+
'import "side-effect-2"',
185+
'import { named } from "with-named"',
186+
'import "another-side-effect"',
187+
'',
188+
'console.log(named)',
189+
'',
190+
].join('\n')
191+
192+
writeFileSync(join(dir, file), src, 'utf8')
193+
const code = await runFormat([dir], { write: true })
194+
expect(code).toBe(0)
195+
const result = readFileSync(join(dir, file), 'utf8')
196+
// Side effect imports should be preserved (with quotes converted to single)
197+
expect(result).toContain('import \'side-effect-1\'')
198+
expect(result).toContain('import \'side-effect-2\'')
199+
expect(result).toContain('import \'another-side-effect\'')
200+
})
201+
202+
it('should handle complex nested object structures', async () => {
203+
const dir = tmp()
204+
const file = 'nested-objects.ts'
205+
const src = [
206+
'const config = {',
207+
' nested: {',
208+
' deep: {',
209+
' value: "test"',
210+
' }',
211+
' },',
212+
' array: [',
213+
' { key: "value1" },',
214+
' { key: "value2" }',
215+
' ]',
216+
'}',
217+
'',
218+
].join('\n')
219+
220+
writeFileSync(join(dir, file), src, 'utf8')
221+
const code = await runFormat([dir], { write: true })
222+
expect(code).toBe(0)
223+
const result = readFileSync(join(dir, file), 'utf8')
224+
expect(result).toContain('\'test\'') // Should convert quotes
225+
expect(result).toContain('\'value1\'')
226+
expect(result).toContain('\'value2\'')
227+
})
228+
})

0 commit comments

Comments
 (0)