import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import * as Config from '../src/config.js'; import * as Options from '../src/options.js'; const [testFile] = GLib.filename_from_uri(import.meta.url); const testDir = GLib.path_get_dirname(testFile); describe('Ensure array', function () { it('does not change an array', function () { expect(Config.ensureArray(['a', 'b'])).toEqual(['a', 'b']); }); it('puts a single value into an array', function () { expect(Config.ensureArray('a')).toEqual(['a']); }); }); describe('Loading configuration', function () { beforeEach(function () { // suppress messages spyOn(globalThis, 'print'); spyOn(globalThis, 'printerr'); }); it('loads from a file', function () { const config = Config.loadConfig({config: `${testDir}/fixtures/jasmine.json`}); expect(config.a).toEqual('b'); expect(config.c).toEqual('d'); }); it("doesn't load the file if no-config specified", function () { const config = Config.loadConfig({ 'no-config': true, config: `${testDir}/fixtures/jasmine.json`, }); const keys = Object.keys(config); expect(keys).not.toContain('a'); expect(keys).not.toContain('c'); }); it('loads the default file if none given', function () { const config = Config.loadConfig({}, `${testDir}/fixtures/jasmine.json`); expect(config.a).toEqual('b'); expect(config.c).toEqual('d'); }); it("errors out if the file doesn't exist", function () { expect(() => Config.loadConfig({config: 'nonexist.json'})).toThrow(); }); it("doesn't error out if the default file doesn't exist", function () { expect(() => Config.loadConfig({}, 'nonexist.json')).not.toThrow(); }); it('errors out if the file is invalid', function () { expect(() => Config.loadConfig({ config: `${testDir}/fixtures/invalid.json`, })).toThrow(); }); it("resolves paths relative to the config file's location", function () { const config = Config.loadConfig({config: `${testDir}/fixtures/path.json`}); const location = Gio.File.new_for_path(`${testDir}/fixtures`); expect(config.include_paths).toContain(location.get_path()); expect(config.spec_files).toContain(location.get_child('someSpec.js').get_path()); }); it('warns about unrecognized config options', function () { Config.loadConfig({config: `${testDir}/fixtures/jasmine.json`}); expect(globalThis.printerr).toHaveBeenCalledWith(jasmine.stringMatching(/^warning: /)); }); }); describe('Configuration options to arguments', function () { it('lets command line arguments override config options', function () { const args = Config.configToArgs({options: '--color'}, ...Options.parseOptions(['--no-color'])); expect(args.indexOf('--no-color')).toBeGreaterThan(args.indexOf('--color')); }); it('adds one exclusion path', function () { const args = Config.configToArgs({exclude: 'a'}); expect(args.join(' ')).toMatch('--exclude a'); }); it('adds more than one exclusion path', function () { const args = Config.configToArgs({exclude: ['a', 'b']}); expect(args.join(' ')).toMatch('--exclude a'); expect(args.join(' ')).toMatch('--exclude b'); }); it('adds exclusions from the command line', function () { const args = Config.configToArgs({}, ...Options.parseOptions(['--exclude', 'a.js'])); expect(args.join(' ')).toMatch('--exclude a.js'); }); it('combines exclusions from the command line and the config file', function () { const args = Config.configToArgs({exclude: 'b.js'}, ...Options.parseOptions(['--exclude', 'a.js'])); expect(args.join(' ')).toMatch('--exclude a.js'); expect(args.join(' ')).toMatch('--exclude b.js'); }); it('adds one extra option', function () { const args = Config.configToArgs({options: '--foo'}); expect(args).toContain('--foo'); }); it('adds more than one extra option', function () { const args = Config.configToArgs({options: ['--foo', '--bar']}); expect(args.join(' ')).toMatch('--foo --bar'); // order should be preserved here }); it('adds one spec file', function () { const args = Config.configToArgs({spec_files: 'a'}); expect(args).toContain('a'); }); it('adds more than one spec file', function () { const args = Config.configToArgs({spec_files: ['a', 'b']}); expect(args).toContain('a'); expect(args).toContain('b'); }); it('does not add spec files from config if there were some on the command line', function () { const args = Config.configToArgs({spec_files: ['a', 'b']}, ['c']); expect(args).not.toContain('a'); expect(args).not.toContain('b'); }); it('passes the arguments on to the subprocess', function () { const args = Config.configToArgs({}, ...Options.parseOptions(['--color', 'spec.js'])); expect(args).toContain('--color', 'spec.js'); }); it('passes the config file on to the subprocess as arguments', function () { const args = Config.configToArgs({ environment: {}, options: ['--color'], exclude: ['nonspec*.js'], spec_files: ['a.js', 'b.js'], }, [], {}); expect(args.join(' ')).toMatch(/--exclude nonspec\*\.js/); expect(args).toContain('--color', 'a.js', 'b.js'); }); it('does not pass the config file specs if specs were on the command line', function () { const args = Config.configToArgs({ environment: {}, spec_files: ['spec2.js'], }, ['spec1.js']); expect(args).toContain('spec1.js'); expect(args).not.toContain('spec2.js'); }); it('does not pass include paths as -I arguments', function () { const args = Config.configToArgs({ environment: {}, include_paths: ['/path1', '/path2'], }, [], {}); expect(args.join(' ')).not.toMatch(/-I/); }); }); describe('Manipulating the environment', function () { it('sets environment variables in the launcher', function () { const launcher = Config.prepareLauncher({ environment: { 'MY_VARIABLE': 'my_value', }, }); expect(launcher.getenv('MY_VARIABLE')).toEqual('my_value'); }); it('unsets environment variables with null values', function () { const launcher = Config.prepareLauncher({ environment: { 'MY_VARIABLE': null, }, }); expect(launcher.getenv('MY_VARIABLE')).toBeNull(); }); it('adds one search path', function () { const launcher = Config.prepareLauncher({include_paths: '/a'}); expect(launcher.getenv('GJS_PATH')).toEqual('/a'); }); it('adds multiple search paths in the right order', function () { const launcher = Config.prepareLauncher({include_paths: ['/a', '/b']}); expect(launcher.getenv('GJS_PATH')).toEqual('/a:/b'); }); it('adds search paths with a lower priority than existing search paths', function () { const oldPath = GLib.getenv('GJS_PATH'); GLib.setenv('GJS_PATH', '/a:/b', /* overwrite = */ true); const launcher = Config.prepareLauncher({include_paths: ['/c', '/d']}); expect(launcher.getenv('GJS_PATH')).toEqual('/a:/b:/c:/d'); if (oldPath) GLib.setenv('GJS_PATH', oldPath, /* overwrite = */ true); else GLib.unsetenv('GJS_PATH'); }); }); describe('Manipulating the launcher command line', function () { let args; beforeEach(function () { args = ['jasmine-runner', '--verbose', 'foo.js']; }); it('executes jasmine-runner with a different interpreter binary', function () { args = Config.wrapArgs(args, { interpreter: '/path/to/custom/gjs', }); expect(args).toEqual(['/path/to/custom/gjs', 'jasmine-runner', '--verbose', 'foo.js']); }); it('allows adding arguments to the interpreter', function () { args = Config.wrapArgs(args, { interpreter: 'gjs -d', }); expect(args).toEqual(['gjs', '-d', 'jasmine-runner', '--verbose', 'foo.js']); }); it('executes jasmine-runner with a different interpreter binary from the command line', function () { args = Config.wrapArgs(args, {}, { interpreter: '/path/to/custom/gjs', }); expect(args).toEqual(['/path/to/custom/gjs', 'jasmine-runner', '--verbose', 'foo.js']); }); it('gives the interpreter specified on the command line priority', function () { args = Config.wrapArgs(args, { interpreter: '/path/to/other/gjs', }, { interpreter: '/path/to/custom/gjs', }); expect(args).toEqual(['/path/to/custom/gjs', 'jasmine-runner', '--verbose', 'foo.js']); }); it('executes jasmine-runner with a debugger', function () { args = Config.wrapArgs(args, {}, { debug: 'gdb --args', }); expect(args).toEqual(['gdb', '--args', 'gjs', '-m', 'jasmine-runner', '--verbose', 'foo.js']); }); it('does not pass the gjs interpreter to the debugger if a custom one is configured', function () { args = Config.wrapArgs(args, { interpreter: '/path/to/custom/gjs', }, { debug: 'lldb --', }); expect(args).toEqual(['lldb', '--', '/path/to/custom/gjs', 'jasmine-runner', '--verbose', 'foo.js']); }); it('does not pass the gjs interpreter to the debugger if a custom one is given on the command line', function () { args = Config.wrapArgs(args, {}, { debug: 'lldb --', interpreter: '/path/to/custom/gjs', }); expect(args).toEqual(['lldb', '--', '/path/to/custom/gjs', 'jasmine-runner', '--verbose', 'foo.js']); }); });