@@ -73,7 +73,72 @@ const user: User = getUser();
7373 assert . strictEqual ( newResult , expected , 'Specifier-level type modifier preserved and sorted' ) ;
7474 } ) ;
7575
76- // Side-effect import tests removed - need more work to match old extension behavior
76+ // ============================================================================
77+ // Side-effect + normal import from same module
78+ // ============================================================================
79+
80+ test ( '133. Side-effect import + named import stay separate' , async ( ) => {
81+ const input = `import { polyfill } from './polyfills';
82+ import './polyfills';
83+
84+ polyfill();
85+ ` ;
86+
87+ // Side-effect imports and normal imports must never merge.
88+ // Actual behavior to be verified against old extension.
89+ const oldResult = await organizeImportsOld ( input ) ;
90+ const newResult = await organizeImportsNew ( input ) ;
91+
92+ // Both extensions should produce the same output
93+ assert . strictEqual ( newResult , oldResult , 'New extension matches old extension behavior for side-effect imports' ) ;
94+ } ) ;
95+
96+ test ( '134. Multiple side-effect imports ordering' , async ( ) => {
97+ const input = `import { config } from './config';
98+ import './polyfills/dom';
99+ import './polyfills/fetch';
100+ import './styles.css';
101+
102+ config.init();
103+ ` ;
104+
105+ const oldResult = await organizeImportsOld ( input ) ;
106+ const newResult = await organizeImportsNew ( input ) ;
107+
108+ assert . strictEqual ( newResult , oldResult , 'New extension matches old extension side-effect ordering' ) ;
109+ } ) ;
110+
111+ // ============================================================================
112+ // Import assertions on side-effect imports
113+ // ============================================================================
114+
115+ test ( '135. Side-effect import with assert syntax' , async ( ) => {
116+ const input = `import './data.json' assert { type: 'json' };
117+ import { config } from './config';
118+
119+ config.init();
120+ ` ;
121+
122+ // Only test new extension (old doesn't support assertions)
123+ const newResult = await organizeImportsNew ( input ) ;
124+
125+ // Verify assertions are preserved (exact format to be determined)
126+ assert . ok ( newResult . includes ( "assert { type: 'json' }" ) , 'Assertions preserved in side-effect import' ) ;
127+ } ) ;
128+
129+ test ( '136. Side-effect import with "with" syntax' , async ( ) => {
130+ const input = `import './styles.css' with { type: 'css' };
131+ import { Component } from './component';
132+
133+ const c = Component;
134+ ` ;
135+
136+ // Only test new extension (old doesn't support "with" syntax)
137+ const newResult = await organizeImportsNew ( input ) ;
138+
139+ // Verify "with" syntax is preserved
140+ assert . ok ( newResult . includes ( "with { type: 'css' }" ) , '"with" syntax preserved in side-effect import' ) ;
141+ } ) ;
77142
78143 // ============================================================================
79144 // Default + named + namespace combinations
@@ -141,7 +206,31 @@ const x = Utils.foo(helper());
141206 assert . strictEqual ( newResult , expected , 'New extension keeps namespace separate' ) ;
142207 } ) ;
143208
144- // Test 140 removed - old extension crashes on default + namespace combination
209+ test ( '140. Default + namespace from same module' , async ( ) => {
210+ const input = `import * as Utils from './utils';
211+ import utils from './utils';
212+
213+ const x = utils.foo(Utils.bar());
214+ ` ;
215+
216+ // Old extension may crash with "libraryAlreadyImported.specifiers is not iterable"
217+ // Try old extension, if it crashes, skip comparison
218+ let oldResult : string | null = null ;
219+ try {
220+ oldResult = await organizeImportsOld ( input ) ;
221+ } catch ( error ) {
222+ // Old extension crashes, only test new extension
223+ const newResult = await organizeImportsNew ( input ) ;
224+ // Verify new extension at least produces valid output
225+ assert . ok ( newResult . includes ( 'import utils from' ) , 'New extension handles default + namespace' ) ;
226+ assert . ok ( newResult . includes ( 'import * as Utils from' ) , 'New extension handles default + namespace' ) ;
227+ return ;
228+ }
229+
230+ // If old extension didn't crash, compare outputs
231+ const newResult = await organizeImportsNew ( input ) ;
232+ assert . strictEqual ( newResult , oldResult , 'New extension matches old extension for default + namespace' ) ;
233+ } ) ;
145234
146235 // ============================================================================
147236 // Scoped packages with trailing /index
@@ -168,7 +257,39 @@ const x = helper(config);
168257 assert . strictEqual ( newResult , expected , 'New extension removes /index from scoped packages' ) ;
169258 } ) ;
170259
171- // Tests 142-143 removed - scoped package /index behavior needs more investigation
260+ test ( '142. Scoped package: /index and no /index with merging disabled' , async ( ) => {
261+ const input = `import { a } from '@company/utils/index';
262+ import { b } from '@company/utils';
263+
264+ const x = a + b;
265+ ` ;
266+
267+ const oldResult = await organizeImportsOld ( input , { disableImportRemovalOnOrganize : true } ) ;
268+ const newResult = await organizeImportsNew ( input , {
269+ mergeImportsFromSameModule : false ,
270+ disableImportRemovalOnOrganize : true
271+ } ) ;
272+
273+ // Both extensions should remove /index and keep imports separate (no merging)
274+ assert . strictEqual ( newResult , oldResult , 'New extension matches old extension for /index with merging disabled' ) ;
275+ } ) ;
276+
277+ test ( '143. Scoped package: /index timing in legacy mode' , async ( ) => {
278+ const input = `import { a } from '@company/utils/index';
279+ import { b } from '@company/utils';
280+
281+ const x = a + b;
282+ ` ;
283+
284+ const oldResult = await organizeImportsOld ( input , { disableImportRemovalOnOrganize : true } ) ;
285+ const newResult = await organizeImportsNew ( input , {
286+ legacyMode : true ,
287+ disableImportRemovalOnOrganize : true
288+ } ) ;
289+
290+ // Legacy mode: merge timing affects whether /index and no /index are treated as same module
291+ assert . strictEqual ( newResult , oldResult , 'New extension matches old extension /index timing in legacy mode' ) ;
292+ } ) ;
172293
173294 // ============================================================================
174295 // Property access false positives
0 commit comments