// Copyright (c) 2026 The Brave Authors. All rights reserved. // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. import { parse } from './ifdef-loader'; describe('ifdef-loader', () => { describe('basic conditionals', () => { it('should include code when condition is true', () => { const source = `const foo = 1; // const debug = true; console.log('debug'); // const bar = 2;`; const result = parse(source, { DEBUG: true }); expect(result).toBe(`const foo = 1; const debug = true; console.log('debug'); const bar = 2;`); }); it('should exclude code when condition is false', () => { const source = `const foo = 1; // const debug = true; // const bar = 2;`; const result = parse(source, { DEBUG: false }); expect(result).toBe(`const foo = 1; const bar = 2;`); }); it('should handle if/else branches', () => { const source = `// const env = 'production'; // const env = 'development'; // `; expect(parse(source, { PROD: true })).toBe(` const env = 'production'; `); expect(parse(source, { PROD: false })).toBe(` const env = 'development'; `); }); it('should handle if/elif/else chains', () => { const source = `// const config = 'production'; // const config = 'staging'; // const config = 'development'; // `; expect(parse(source, { ENV: 'prod' })).toContain("'production'"); expect(parse(source, { ENV: 'staging' })).toContain("'staging'"); expect(parse(source, { ENV: 'dev' })).toContain("'development'"); }); }); describe('nested conditionals', () => { it('should handle nested if blocks', () => { const source = `const start = 1; // const outer = true; // const inner = true; // const afterInner = true; // const end = 1;`; const withBoth = parse(source, { OUTER: true, INNER: true }); expect(withBoth).toContain('outer = true'); expect(withBoth).toContain('inner = true'); expect(withBoth).toContain('afterInner = true'); const outerOnly = parse(source, { OUTER: true, INNER: false }); expect(outerOnly).toContain('outer = true'); expect(outerOnly).not.toContain('inner = true'); expect(outerOnly).toContain('afterInner = true'); const noneIncluded = parse(source, { OUTER: false, INNER: true }); expect(noneIncluded).not.toContain('outer'); expect(noneIncluded).not.toContain('inner'); }); }); describe('expressions', () => { it('should evaluate boolean operators', () => { const source = `// const log = true; // `; expect(parse(source, { DEBUG: true, VERBOSE: true })).toContain('log = true'); expect(parse(source, { DEBUG: true, VERBOSE: false })).not.toContain('log = true'); expect(parse(source, { DEBUG: false, VERBOSE: true })).not.toContain('log = true'); }); it('should evaluate comparisons', () => { const source = `// const newFeature = true; // // const isIOS = true; // `; const v3 = parse(source, { VERSION: 3, PLATFORM: 'ios' }); expect(v3).toContain('newFeature = true'); expect(v3).toContain('isIOS = true'); const v1 = parse(source, { VERSION: 1, PLATFORM: 'android' }); expect(v1).not.toContain('newFeature = true'); expect(v1).not.toContain('isIOS = true'); }); }); describe('edge cases', () => { it('should return source unchanged when no if expressions present', () => { const source = `const foo = 1; const bar = 2;`; expect(parse(source, { DEBUG: true })).toBe(source); }); it('should throw error for unclosed if block', () => { const source = `// const debug = true;`; expect(() => parse(source, { DEBUG: true })).toThrow('#if without #endif'); }); it('should throw error for invalid expressions', () => { const source = `// const foo = 1; // `; expect(() => parse(source, {})).toThrow('error evaluation'); }); it('should preserve line numbers for source maps', () => { const source = `line1 // line3 line4 // line6`; const result = parse(source, { DEBUG: false }); const lines = result.split('\n'); expect(lines.length).toBe(6); expect(lines[0]).toBe('line1'); expect(lines[1]).toBe(''); expect(lines[2]).toBe(''); expect(lines[3]).toBe(''); expect(lines[4]).toBe(''); expect(lines[5]).toBe('line6'); }); }); describe('real-world usage', () => { it('should handle platform-specific code', () => { const source = `// import { IOSModule } from './ios'; // import { AndroidModule } from './android'; // import { WebModule } from './web'; // export const PlatformModule = // IOSModule; // AndroidModule; // WebModule; // `; const iosResult = parse(source, { is_ios: true, is_android: false }); expect(iosResult).toContain('IOSModule'); expect(iosResult).not.toContain('AndroidModule'); expect(iosResult).not.toContain('WebModule'); const androidResult = parse(source, { is_ios: false, is_android: true }); expect(androidResult).not.toContain('IOSModule'); expect(androidResult).toContain('AndroidModule'); expect(androidResult).not.toContain('WebModule'); const webResult = parse(source, { is_ios: false, is_android: false }); expect(webResult).not.toContain('IOSModule'); expect(webResult).not.toContain('AndroidModule'); expect(webResult).toContain('WebModule'); }); }); });