text: 'use strict';
  
  const path = require('path');
  const FixturifyProject = require('../../helpers/fixturify-project');
  const Project = require('../../../lib/models/project');
  const expect = require('chai').expect;
  const td = require('testdouble');
  const broccoliTestHelper = require('broccoli-test-helper');
  const { WatchedDir, UnwatchedDir } = require('broccoli-source');
  
  const createBuilder = broccoliTestHelper.createBuilder;
  const createTempDir = broccoliTestHelper.createTempDir;
  
  const MockCLI = require('../../helpers/mock-cli');
  const { isExperimentEnabled } = require('../../../lib/experiments');
  const mergeTrees = require('../../../lib/broccoli/merge-trees');
  const BroccoliMergeTrees = require('broccoli-merge-trees').MergeTrees;
  
  let EmberApp = require('../../../lib/broccoli/ember-app');
  const Addon = require('../../../lib/models/addon');
  
  function mockTemplateRegistry(app) {
    let oldLoad = app.registry.load;
    app.registry.load = function (type) {
      if (type === 'template') {
        return [
          {
            toTree: (tree) => tree,
          },
        ];
      }
      return oldLoad.apply(app.registry, arguments);
    };
  }
  
  describe('EmberApp', function () {
    let project, projectPath, app, addon;
  
    function setupProject(rootPath) {
      const packageContents = require(path.join(rootPath, 'package.json'));
      let cli = new MockCLI();
  
      project = new Project(rootPath, packageContents, cli.ui, cli);
      project.require = function () {
        return function () {};
      };
      project.initializeAddons = function () {
        this.addons = [];
      };
  
      return project;
    }
  
    beforeEach(function () {
      projectPath = path.resolve(__dirname, '../../fixtures/addon/simple');
      project = setupProject(projectPath);
    });
  
    if (isExperimentEnabled('PACKAGER')) {
      describe('packager hook', function () {
        let js, input, output;
  
        before(async function () {
          js = await createTempDir();
          js.write({
            fake: {
              javascript: '// javascript.js',
            },
          });
        });
  
        beforeEach(async function () {
          input = await createTempDir();
        });
  
        afterEach(async function () {
          await input.dispose();
          if (output) {
            await output.dispose();
          }
        });
  
        after(async function () {
          await js.dispose();
        });
  
        it('sets `_isPackageHookSupplied` to `false` if `package` hook is not a function', function () {
          let app = new EmberApp({
            project,
            package: false,
          });
  
          expect(app._isPackageHookSupplied).to.equal(false);
        });
  
        it('sets `_isPackageHookSupplied` to `false` if `package` hook is not supplied', function () {
          let app = new EmberApp({
            project,
          });
  
          expect(app._isPackageHookSupplied).to.equal(false);
        });
  
        it('sets `_isPackageHookSupplied` to `true` if `package` hook is supplied', function () {
          let app = new EmberApp({
            project,
            package: () => input.path(),
          });
  
          expect(app._isPackageHookSupplied).to.equal(true);
        });
  
        it('overrides the output of the build', async function () {
          input.write({
            fake: {
              dist: {
                'foo.js': '// foo.js',
              },
            },
          });
  
          let app = new EmberApp({
            project,
            package: () => input.path(),
          });
          mockTemplateRegistry(app);
  
          output = createBuilder(app.toTree());
          await output.build();
  
          let outputFiles = output.read();
  
          expect(outputFiles).to.deep.equal({
            fake: {
              dist: {
                'foo.js': '// foo.js',
              },
            },
          });
        });
  
        it('receives a full tree as an argument', async function () {
          let appStyles = await createTempDir();
          appStyles.write({
            'app.css': '// css styles',
          });
          input.write({
            fake: {
              dist: {
                'foo.js': '// foo.js',
              },
            },
          });
  
          let app = new EmberApp({
            project,
            package: (tree) => mergeTrees([tree, input.path()]),
            trees: {
              styles: appStyles.path(),
            },
          });
          mockTemplateRegistry(app);
  
          app.getAppJavascript = () => js.path();
  
          output = createBuilder(app.toTree());
          await output.build();
  
          let outputFiles = output.read();
  
          expect(outputFiles).to.deep.equal({
            'addon-tree-output': {},
            fake: {
              dist: {
                'foo.js': '// foo.js',
              },
              javascript: '// javascript.js',
            },
            app: {
              styles: {
                'app.css': '// css styles',
              },
            },
            'test-project': {
              templates: {},
            },
            tests: {
              '.gitkeep': '',
              'addon-test-support': {},
              lint: {},
            },
            public: {},
            vendor: {
              '.gitkeep': '',
            },
          });
        });
  
        it('prints a warning if `package` is not a function and falls back to default packaging', async function () {
          let app = new EmberApp({
            project,
            package: {},
          });
  
          app.project.ui.writeWarnLine = td.function();
  
          app.getAppJavascript = td.function();
          app.getAddonTemplates = td.function();
          app.getStyles = td.function();
          app.getTests = td.function();
          app.getExternalTree = td.function();
          app._legacyAddonCompile = td.function();
          app._defaultPackager = {
            packagePublic: td.function(),
            packageJavascript: td.function(),
            packageStyles: td.function(),
            processIndex: td.function(),
            importAdditionalAssets: td.function(),
            packageTests: td.function(),
          };
  
          output = createBuilder(app.toTree());
          await output.build();
  
          td.verify(app.getAppJavascript(false));
          td.verify(app.getStyles());
          td.verify(app.getTests());
          td.verify(app.getExternalTree());
          td.verify(
            app.project.ui.writeWarnLine('`package` hook must be a function, falling back to default packaging.')
          );
        });
  
        it('receives transpiled ES current app tree', async function () {
          let app = new EmberApp({
            project,
            package: (tree) => tree,
          });
          mockTemplateRegistry(app);
  
          input.write({
            fake: {
              dist: {
                'foo.js': '// foo.js',
              },
            },
          });
          app.registry.add('js', {
            name: 'fake-js-preprocessor',
            ext: 'js',
            toTree() {
              return input.path();
            },
          });
  
          output = createBuilder(app.toTree());
          await output.build();
  
          let outputFiles = output.read();
  
          expect(outputFiles.fake).to.deep.equal({
            dist: {
              'foo.js': '// foo.js',
            },
          });
        });
      });
    }
  
    describe('getStyles()', function () {
      it('can handle empty styles folders', async function () {
        let appStyles = await createTempDir();
        appStyles.write({
          'app.css': '// css styles',
        });
  
        let app = new EmberApp({
          project,
          trees: {
            styles: appStyles.path(),
          },
        });
  
        app.addonTreesFor = () => [];
  
        let output = createBuilder(app.getStyles());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles).to.deep.equal({
          app: {
            styles: {
              'app.css': '// css styles',
            },
          },
        });
  
        await output.dispose();
      });
  
      it('can handle empty addon styles folders', async function () {
        let appOptions = { project };
  
        let app = new EmberApp(appOptions);
  
        let AddonFoo = Addon.extend({
          root: 'foo',
          packageRoot: 'foo',
          name: 'foo',
        });
        let addonFoo = new AddonFoo(app, project);
        app.project.addons.push(addonFoo);
  
        let output = createBuilder(app.getStyles());
        await output.build();
        let outputFiles = output.read();
  
        let expectedOutput = {};
        expect(outputFiles).to.deep.equal(expectedOutput);
  
        await output.dispose();
      });
  
      it('add `app/styles` folder from add-ons', async function () {
        let addonFooStyles = await createTempDir();
  
        addonFooStyles.write({
          app: {
            styles: {
              'foo.css': 'foo',
            },
          },
        });
  
        let appOptions = { project };
  
        let app = new EmberApp(appOptions);
  
        let AddonFoo = Addon.extend({
          root: 'foo',
          packageRoot: 'foo',
          name: 'foo',
          treeForStyles() {
            return addonFooStyles.path();
          },
        });
        let addonFoo = new AddonFoo(app, project);
        app.project.addons.push(addonFoo);
  
        let output = createBuilder(app.getStyles());
        await output.build();
        let outputFiles = output.read();
  
        let expectedOutput = {
          app: {
            styles: {
              'foo.css': 'foo',
            },
          },
        };
        expect(outputFiles).to.deep.equal(expectedOutput);
  
        await addonFooStyles.dispose();
        await output.dispose();
      });
  
      it('returns add-ons styles files', async function () {
        let addonFooStyles = await createTempDir();
        let addonBarStyles = await createTempDir();
  
        // `ember-basic-dropdown`
        addonFooStyles.write({
          app: {
            styles: {
              'foo.css': 'foo',
            },
          },
        });
        // `ember-bootstrap`
        addonBarStyles.write({
          baztrap: {
            'baztrap.css': '// baztrap.css',
          },
        });
  
        let app = new EmberApp({
          project,
        });
        app.addonTreesFor = function () {
          return [addonFooStyles.path(), addonBarStyles.path()];
        };
  
        let output = createBuilder(app.getStyles());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles).to.deep.equal({
          app: {
            styles: {
              'foo.css': 'foo',
            },
          },
          baztrap: {
            'baztrap.css': '// baztrap.css',
          },
        });
  
        await addonFooStyles.dispose();
        await addonBarStyles.dispose();
        await output.dispose();
      });
  
      it('does not fail if add-ons do not export styles', async function () {
        let app = new EmberApp({
          project,
        });
        app.addonTreesFor = () => [];
  
        let output = createBuilder(app.getStyles());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles).to.deep.equal({});
  
        await output.dispose();
      });
    });
  
    describe('getPublic()', function () {
      it('returns public files for app and add-ons', async function () {
        let input = await createTempDir();
        let addonFooPublic = await createTempDir();
        let addonBarPublic = await createTempDir();
  
        input.write({
          'crossdomain.xml': '',
          'robots.txt': '',
        });
        addonFooPublic.write({
          foo: 'foo',
        });
        addonBarPublic.write({
          bar: 'bar',
        });
  
        app = new EmberApp({
          project,
        });
  
        app.trees.public = input.path();
        app.addonTreesFor = function () {
          return [addonFooPublic.path(), addonBarPublic.path()];
        };
  
        let output = createBuilder(app.getPublic());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles).to.deep.equal({
          public: {
            'crossdomain.xml': '',
            'robots.txt': '',
            foo: 'foo',
            bar: 'bar',
          },
        });
  
        await input.dispose();
        await addonFooPublic.dispose();
        await addonBarPublic.dispose();
        await output.dispose();
      });
  
      it('does not fail if app or add-ons have the same `public` folder structure', async function () {
        let input = await createTempDir();
        let addonFooPublic = await createTempDir();
        let addonBarPublic = await createTempDir();
  
        input.write({
          'crossdomain.xml': '',
          'robots.txt': '',
        });
        addonFooPublic.write({
          bar: 'bar',
          foo: 'foo',
        });
        addonBarPublic.write({
          bar: 'bar',
        });
  
        app = new EmberApp({
          project,
        });
  
        app.trees.public = input.path();
        app.addonTreesFor = function () {
          return [addonFooPublic.path(), addonBarPublic.path()];
        };
  
        let output = createBuilder(app.getPublic());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles).to.deep.equal({
          public: {
            'crossdomain.xml': '',
            'robots.txt': '',
            foo: 'foo',
            bar: 'bar',
          },
        });
  
        await input.dispose();
        await addonFooPublic.dispose();
        await addonBarPublic.dispose();
        await output.dispose();
      });
    });
  
    describe('getAddonTemplates()', function () {
      it('returns add-ons template files', async function () {
        let input = await createTempDir();
        let addonFooTemplates = await createTempDir();
        let addonBarTemplates = await createTempDir();
  
        addonFooTemplates.write({
          'foo.hbs': 'foo',
        });
        addonBarTemplates.write({
          'bar.hbs': 'bar',
        });
  
        let app = new EmberApp({
          project,
        });
        app.trees.templates = input.path();
        app.addonTreesFor = function () {
          return [addonFooTemplates.path(), addonBarTemplates.path()];
        };
  
        let output = createBuilder(app.getAddonTemplates());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles['test-project'].templates).to.deep.equal({
          'foo.hbs': 'foo',
          'bar.hbs': 'bar',
        });
  
        await input.dispose();
        await addonFooTemplates.dispose();
        await addonBarTemplates.dispose();
        await output.dispose();
      });
    });
  
    describe('getTests()', function () {
      it('returns all test files `hinting` is enabled', async function () {
        let input = await createTempDir();
        let addonLint = await createTempDir();
        let addonFooTestSupport = await createTempDir();
        let addonBarTestSupport = await createTempDir();
  
        input.write({
          acceptance: {
            'login-test.js': '',
            'logout-test.js': '',
          },
        });
        addonFooTestSupport.write({
          'foo-helper.js': 'foo',
        });
        addonBarTestSupport.write({
          'bar-helper.js': 'bar',
        });
        addonLint.write({
          'login-test.lint.js': '',
          'logout-test.lint.js': '',
        });
  
        let app = new EmberApp({
          project,
        });
        app.trees.tests = input.path();
        app.addonLintTree = (type, tree) => {
          if (type === 'tests') {
            return addonLint.path();
          }
  
          return tree;
        };
        app.addonTreesFor = function (type) {
          if (type === 'test-support') {
            return [addonFooTestSupport.path(), addonBarTestSupport.path()];
          }
  
          return [];
        };
  
        let output = createBuilder(app.getTests());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles.tests).to.deep.equal({
          'addon-test-support': {},
          lint: {
            'login-test.lint.js': '',
            'logout-test.lint.js': '',
          },
          acceptance: {
            'login-test.js': '',
            'logout-test.js': '',
          },
          'foo-helper.js': 'foo',
          'bar-helper.js': 'bar',
        });
  
        await input.dispose();
        await addonFooTestSupport.dispose();
        await addonBarTestSupport.dispose();
        await addonLint.dispose();
        await output.dispose();
      });
  
      it('returns test files w/o lint tests if `hinting` is disabled', async function () {
        let input = await createTempDir();
        let addonFooTestSupport = await createTempDir();
        let addonBarTestSupport = await createTempDir();
  
        input.write({
          acceptance: {
            'login-test.js': '',
            'logout-test.js': '',
          },
        });
        addonFooTestSupport.write({
          'foo-helper.js': 'foo',
        });
        addonBarTestSupport.write({
          'bar-helper.js': 'bar',
        });
  
        let app = new EmberApp({
          project,
          hinting: false,
        });
        app.trees.tests = input.path();
        app.addonTreesFor = function (type) {
          if (type === 'test-support') {
            return [addonFooTestSupport.path(), addonBarTestSupport.path()];
          }
  
          return [];
        };
  
        let output = createBuilder(app.getTests());
        await output.build();
        let outputFiles = output.read();
  
        expect(outputFiles.tests).to.deep.equal({
          'addon-test-support': {},
          acceptance: {
            'login-test.js': '',
            'logout-test.js': '',
          },
          'foo-helper.js': 'foo',
          'bar-helper.js': 'bar',
        });
  
        await input.dispose();
        await addonFooTestSupport.dispose();
        await addonBarTestSupport.dispose();
        await output.dispose();
      });
    });
  
    describe('constructor', function () {
      it('should override project.configPath if configPath option is specified', function () {
        project.configPath = function () {
          return 'original value';
        };
  
        let expected = 'custom config path';
  
        new EmberApp({
          project,
          configPath: expected,
        });
  
        expect(project.configPath().slice(-expected.length)).to.equal(expected);
      });
  
      it('should update project.config() if configPath option is specified', function () {
        project.require = function (path) {
          return () => ({ path });
        };
  
        expect(project.config('development')).to.deep.equal({});
  
        new EmberApp({
          project,
          configPath: path.join('..', '..', 'app-import', 'config', 'environment'),
        });
  
        expect(project.configPath()).to.contain(path.join('app-import', 'config', 'environment'));
      });
  
      it('should set bowerDirectory for app', function () {
        let app = new EmberApp({
          project,
        });
  
        expect(app.bowerDirectory).to.equal(project.bowerDirectory);
        expect(app.bowerDirectory).to.equal('bower_components');
      });
  
      it('should merge options with defaults to depth', function () {
        let app = new EmberApp(
          {
            project,
            foo: {
              bar: ['baz'],
            },
            fooz: {
              bam: {
                boo: ['default'],
              },
            },
          },
          {
            foo: {
              bar: ['bizz'],
            },
            fizz: 'fizz',
            fooz: {
              bam: {
                boo: ['custom'],
              },
            },
          }
        );
  
        expect(app.options.foo).to.deep.eql({
          bar: ['bizz'],
        });
        expect(app.options.fizz).to.eql('fizz');
        expect(app.options.fooz).to.eql({
          bam: {
            boo: ['custom'],
          },
        });
      });
  
      it('should do the right thing when merging default object options', function () {
        let app = new EmberApp(
          {
            project,
          },
          {
            minifyJS: {
              enabled: true,
              options: {
                exclusions: ['hey', 'you'],
              },
            },
          }
        );
  
        expect(app.options.minifyJS).to.deep.equal({
          enabled: true,
          options: {
            exclusions: ['hey', 'you'],
            compress: {
              // eslint-disable-next-line camelcase
              negate_iife: false,
              sequences: 30,
            },
            output: {
              semicolons: false,
            },
          },
        });
      });
  
      it('should watch vendor if it exists', function () {
        let app = new EmberApp({
          project,
        });
  
        expect(app.options.trees.vendor.__broccoliGetInfo__()).to.have.property('watched', true);
      });
  
      describe('Addons included hook', function () {
        let includedWasCalled;
        let setupPreprocessorRegistryWasCalled;
        let addonsAppIncluded, addonsApp;
        let addon = {
          name: 'custom-addon',
          included() {
            includedWasCalled++;
            expect(setupPreprocessorRegistryWasCalled).to.eql(1);
            addonsAppIncluded = this.app;
          },
  
          setupPreprocessorRegistry() {
            expect(includedWasCalled).to.eql(0);
            setupPreprocessorRegistryWasCalled++;
            addonsApp = this.app;
          },
        };
  
        beforeEach(function () {
          setupPreprocessorRegistryWasCalled = includedWasCalled = 0;
          addonsApp = null;
          addonsAppIncluded = null;
          project.initializeAddons = function () {};
          project.addons = [addon];
        });
  
        it('should set the app on the addons', function () {
          expect(includedWasCalled).to.eql(0);
          let app = new EmberApp({
            project,
          });
          expect(includedWasCalled).to.eql(1);
          expect(setupPreprocessorRegistryWasCalled).to.eql(1);
          expect(addonsAppIncluded).to.eql(app);
          expect(addonsApp).to.eql(app);
  
          let addon = project.addons[0];
          expect(addon.app).to.deep.equal(app);
        });
      });
  
      describe('ember-resolver npm vs Bower', function () {
        it('does not load ember-resolver.js as bower dep when ember-resolver is present in registry.availablePlugins', function () {
          let app = new EmberApp({ project });
          expect(app.vendorFiles['ember-resolver']).to.equal(undefined);
        });
  
        it('keeps ember-resolver.js in vendorFiles when npm ember-resolver is not installed, but is present in bower.json', function () {
          project._bowerDependencies = function () {
            return { ember: {}, 'ember-resolver': {} };
          };
          let app = new EmberApp({
            project,
            registry: {
              add() {},
              availablePlugins: {},
            },
          });
          expect(app.vendorFiles['ember-resolver.js'][0]).to.equal(
            'bower_components/ember-resolver/dist/modules/ember-resolver.js'
          );
        });
  
        it('removes ember-resolver.js from vendorFiles when not in bower.json and npm ember-resolver not installed', function () {
          project._bowerDependencies = function () {
            return { ember: {} };
          };
          let app = new EmberApp({
            project,
            registry: {
              add() {},
              availablePlugins: {},
            },
          });
  
          expect(app.vendorFiles['ember-resolver']).to.equal(undefined);
        });
      });
  
      describe('options.babel.sourceMaps', function () {
        it('disables babel sourcemaps by default', function () {
          let app = new EmberApp({
            project,
          });
  
          expect(app.options.babel.sourceMaps).to.be.false;
        });
  
        it('can enable babel sourcemaps with the option', function () {
          let app = new EmberApp({
            project,
            babel: {
              sourceMaps: 'inline',
            },
          });
  
          expect(app.options.babel.sourceMaps).to.equal('inline');
        });
      });
  
      describe('options.fingerprint.exclude', function () {
        it('excludeds testem in fingerprint exclude', function () {
          let app = new EmberApp({
            project,
            fingerprint: {
              exclude: [],
            },
          });
  
          expect(app.options.fingerprint.exclude).to.include('testem');
        });
      });
    });
  
    describe('addons', function () {
      describe('included hook', function () {
        it('included hook is called properly on instantiation', function () {
          let called = false;
          let passedApp;
  
          addon = {
            included(app) {
              called = true;
              passedApp = app;
            },
            treeFor() {},
          };
  
          project.initializeAddons = function () {
            this.addons = [addon];
          };
  
          let app = new EmberApp({
            project,
          });
  
          expect(called).to.be.true;
          expect(passedApp).to.equal(app);
        });
  
        it('does not throw an error if the addon does not implement `included`', function () {
          delete addon.included;
  
          project.initializeAddons = function () {
            this.addons = [addon];
          };
  
          expect(() => {
            new EmberApp({
              project,
            });
          }).to.not.throw(/addon must implement the `included`/);
        });
      });
  
      describe('addonTreesFor', function () {
        beforeEach(function () {
          addon = {
            included() {},
            treeFor() {},
          };
  
          project.initializeAddons = function () {
            this.addons = [addon];
          };
  
          app = new EmberApp({
            project,
          });
        });
  
        it('addonTreesFor returns an empty array if no addons return a tree', function () {
          expect(app.addonTreesFor('blah')).to.deep.equal([]);
        });
  
        it('addonTreesFor calls treesFor on the addon', function () {
          let sampleAddon = project.addons[0];
          let actualTreeName;
  
          sampleAddon.treeFor = function (name) {
            actualTreeName = name;
  
            return 'blazorz';
          };
  
          expect(app.addonTreesFor('blah')).to.deep.equal(['blazorz']);
          expect(actualTreeName).to.equal('blah');
        });
  
        it('addonTreesFor does not throw an error if treeFor is not defined', function () {
          delete addon.treeFor;
  
          app = new EmberApp({
            project,
          });
  
          expect(() => {
            app.addonTreesFor('blah');
          }).not.to.throw(/addon must implement the `treeFor`/);
        });
  
        describe('addonTreesFor is called properly', function () {
          beforeEach(function () {
            app = new EmberApp({
              project,
            });
  
            app.addonTreesFor = td.function();
            td.when(app.addonTreesFor(), { ignoreExtraArgs: true }).thenReturn(['batman']);
          });
  
          it('getAppJavascript calls addonTreesFor', function () {
            app.getAppJavascript();
  
            let args = td.explain(app.addonTreesFor).calls.map(function (call) {
              return call.args[0];
            });
  
            expect(args).to.deep.equal(['app']);
          });
        });
      });
  
      describe('toArray', function () {
        it('excludes `tests` tree from resulting array if the tree is not present', function () {
          app = new EmberApp({
            project,
            trees: {
              tests: null,
            },
          });
  
          app._defaultPackager.packageJavascript = td.function();
          app._defaultPackager.packageStyles = td.function();
          app._legacyAddonCompile = td.function();
  
          td.when(app._legacyAddonCompile(), { ignoreExtraArgs: true }).thenReturn('batman');
          td.when(app._defaultPackager.packageJavascript(), { ignoreExtraArgs: true }).thenReturn('batman');
          td.when(app._defaultPackager.packageStyles(), { ignoreExtraArgs: true }).thenReturn('batman');
  
          app.toArray(); // doesn't throw an error
        });
      });
  
      describe('toTree', function () {
        beforeEach(function () {
          addon = {
            included() {},
            treeFor() {},
            postprocessTree: td.function(),
          };
  
          project.initializeAddons = function () {
            this.addons = [addon];
          };
  
          app = new EmberApp({
            project,
            tests: true,
            trees: { tests: {} },
          });
        });
  
        it('calls postProcessTree if defined', function () {
          app.toArray = td.function();
          app._legacyPackage = td.function();
  
          td.when(app.toArray(), { ignoreExtraArgs: true }).thenReturn([]);
          td.when(app._legacyPackage(), { ignoreExtraArgs: true }).thenReturn('bar');
          td.when(
            addon.postprocessTree(
              'all',
              td.matchers.argThat(
                (t) => t.constructor === BroccoliMergeTrees && t._inputNodes.length === 1 && t._inputNodes[0] === 'bar'
              )
            )
          ).thenReturn('derp');
  
          expect(app.toTree()).to.equal('derp');
        });
  
        it('calls addonPostprocessTree', function () {
          app.toArray = td.function();
          app.addonPostprocessTree = td.function();
          app._legacyPackage = td.function();
  
          td.when(app._legacyPackage(), { ignoreExtraArgs: true }).thenReturn('bar');
          td.when(app.toArray(), { ignoreExtraArgs: true }).thenReturn([]);
          td.when(
            app.addonPostprocessTree(
              'all',
              td.matchers.argThat(
                (t) => t.constructor === BroccoliMergeTrees && t._inputNodes.length === 1 && t._inputNodes[0] === 'bar'
              )
            )
          ).thenReturn('blap');
  
          expect(app.toTree()).to.equal('blap');
        });
  
        it('calls each addon postprocessTree hook', function () {
          mockTemplateRegistry(app);
  
          app.index = td.function();
          app.getTests = td.function();
          app._legacyAddonCompile = td.function();
          app._defaultPackager.processTemplates = td.function();
  
          td.when(app._defaultPackager.processTemplates(), { ignoreExtraArgs: true }).thenReturn('x');
          td.when(addon.postprocessTree(), { ignoreExtraArgs: true }).thenReturn('blap');
          td.when(app.index(), { ignoreExtraArgs: true }).thenReturn(null);
          td.when(app.getTests(), { ignoreExtraArgs: true }).thenReturn(null);
          td.when(app._legacyAddonCompile(), { ignoreExtraArgs: true }).thenReturn(null);
  
          expect(app.toTree()).to.equal('blap');
  
          let args = td.explain(addon.postprocessTree).calls.map(function (call) {
            return call.args[0];
          });
  
          expect(args).to.deep.equal(['js', 'css', 'test', 'all']);
        });
      });
  
      describe('addons can be disabled', function () {
        beforeEach(function () {
          projectPath = path.resolve(__dirname, '../../fixtures/addon/env-addons');
          const packageContents = require(path.join(projectPath, 'package.json'));
          let cli = new MockCLI();
          project = new Project(projectPath, packageContents, cli.ui, cli);
        });
  
        afterEach(function () {
          process.env.EMBER_ENV = undefined;
        });
  
        describe('isEnabled is called properly', function () {
          describe('with environment', function () {
            let emberFooEnvAddonFixture;
  
            beforeEach(function () {
              emberFooEnvAddonFixture = require(path.resolve(projectPath, 'node_modules/ember-foo-env-addon/index.js'));
            });
  
            it('development', function () {
              process.env.EMBER_ENV = 'development';
              let app = new EmberApp({ project });
  
              emberFooEnvAddonFixture.app = app;
              expect(app._addonEnabled(emberFooEnvAddonFixture)).to.be.false;
  
              expect(app.project.addons.length).to.equal(8);
            });
  
            it('foo', function () {
              process.env.EMBER_ENV = 'foo';
              let app = new EmberApp({ project });
  
              emberFooEnvAddonFixture.app = app;
              expect(app._addonEnabled(emberFooEnvAddonFixture)).to.be.true;
  
              expect(app.project.addons.length).to.equal(9);
            });
          });
        });
  
        describe('blacklist', function () {
          it('prevents addons to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
  
            let app = new EmberApp({
              project,
              addons: {
                blacklist: ['ember-foo-env-addon'],
              },
            });
  
            expect(app._addonDisabledByExclude({ name: 'ember-foo-env-addon' })).to.be.true;
            expect(app._addonDisabledByExclude({ name: 'Ember Random Addon' })).to.be.false;
            expect(app.project.addons.length).to.equal(8);
          });
  
          it('throws if unavailable addon is specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
  
              new EmberApp({
                project,
                addons: {
                  blacklist: ['ember-cli-self-troll'],
                },
              });
            }
  
            expect(load).to.throw('Addon "ember-cli-self-troll" defined in "blacklist" is not found');
          });
        });
  
        describe('whitelist', function () {
          it('prevents non-whitelisted addons to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
  
            let app = new EmberApp({
              project,
              addons: {
                whitelist: ['ember-foo-env-addon'],
              },
            });
  
            expect(app._addonDisabledByInclude({ name: 'ember-foo-env-addon' })).to.be.false;
            expect(app._addonDisabledByInclude({ name: 'Ember Random Addon' })).to.be.true;
            expect(app.project.addons.length).to.equal(1);
          });
  
          it('throws if unavailable addon is specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
              app = new EmberApp({
                project,
                addons: {
                  whitelist: ['ember-cli-self-troll'],
                },
              });
            }
  
            expect(load).to.throw('Addon "ember-cli-self-troll" defined in "whitelist" is not found');
          });
        });
  
        describe('blacklist wins over whitelist', function () {
          it('prevents addon to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
            app = new EmberApp({
              project,
              addons: {
                whitelist: ['ember-foo-env-addon'],
                blacklist: ['ember-foo-env-addon'],
              },
            });
  
            expect(app.project.addons.length).to.equal(0);
          });
        });
  
        describe('exclude', function () {
          it('prevents addons to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
  
            let app = new EmberApp({
              project,
              addons: {
                exclude: ['ember-foo-env-addon'],
              },
            });
  
            expect(app._addonDisabledByExclude({ name: 'ember-foo-env-addon' })).to.be.true;
            expect(app._addonDisabledByExclude({ name: 'Ember Random Addon' })).to.be.false;
            expect(app.project.addons.length).to.equal(8);
          });
  
          it('throws if unavailable addon is specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
  
              new EmberApp({
                project,
                addons: {
                  exclude: ['ember-cli-self-troll'],
                },
              });
            }
  
            expect(load).to.throw('Addon "ember-cli-self-troll" defined in "exclude" is not found');
          });
        });
  
        describe('include', function () {
          it('prevents non-included addons to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
  
            let app = new EmberApp({
              project,
              addons: {
                include: ['ember-foo-env-addon'],
              },
            });
  
            expect(app._addonDisabledByInclude({ name: 'ember-foo-env-addon' })).to.be.false;
            expect(app._addonDisabledByInclude({ name: 'Ember Random Addon' })).to.be.true;
            expect(app.project.addons.length).to.equal(1);
          });
  
          it('throws if unavailable addon is specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
  
              new EmberApp({
                project,
                addons: {
                  include: ['ember-cli-self-troll'],
                },
              });
            }
  
            expect(load).to.throw('Addon "ember-cli-self-troll" defined in "include" is not found');
          });
        });
  
        describe('exclude wins over include', function () {
          it('prevents addon to be added to the project', function () {
            process.env.EMBER_ENV = 'foo';
  
            let app = new EmberApp({
              project,
              addons: {
                include: ['ember-foo-env-addon'],
                exclude: ['ember-foo-env-addon'],
              },
            });
  
            expect(app.project.addons.length).to.equal(0);
          });
        });
  
        describe('blacklist and exclude', function () {
          it('throws when both are specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
  
              new EmberApp({
                project,
                addons: {
                  blacklist: ['ember-foo-env-addon'],
                  exclude: ['ember-foo-env-addon'],
                },
              });
            }
  
            expect(load).to.throw('Specifying both "blacklist" and "exclude" is not supported. Please use only one.');
          });
        });
  
        describe('whitelist and include', function () {
          it('throws when both are specified', function () {
            function load() {
              process.env.EMBER_ENV = 'foo';
  
              new EmberApp({
                project,
                addons: {
                  whitelist: ['ember-foo-env-addon'],
                  include: ['ember-foo-env-addon'],
                },
              });
            }
  
            expect(load).to.throw('Specifying both "whitelist" and "include" is not supported. Please use only one.');
          });
        });
      });
  
      describe('addon instance bundle caching validation (when used within the project)', function () {
        let fixturifyProject;
  
        beforeEach(function () {
          fixturifyProject = new FixturifyProject('awesome-proj', '1.0.0');
          fixturifyProject.addDevDependency('ember-cli', '*');
        });
  
        afterEach(function () {
          fixturifyProject.dispose();
        });
  
        it('throws an error if an addon `whitelist` is specified', function () {
          fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
          fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
            callback: (inRepoAddon) => {
              inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
            },
          });
  
          fixturifyProject.writeSync();
  
          let projectWithBundleCaching = fixturifyProject.buildProjectModel();
          projectWithBundleCaching.initializeAddons();
  
          expect(() => {
            new EmberApp({
              project: projectWithBundleCaching,
              addons: {
                whitelist: ['foo'],
              },
            });
          }).to.throw(
            [
              '[ember-cli] addon bundle caching is disabled for apps that specify an addon "whitelist"',
              '',
              'All addons using bundle caching:',
              projectWithBundleCaching.addons.find((addon) => addon.name === 'foo').packageRoot,
            ].join('\n')
          );
        });
  
        it('throws an error if an addon `blacklist` is specified', function () {
          fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
          fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
            callback: (inRepoAddon) => {
              inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
            },
          });
  
          fixturifyProject.writeSync();
  
          let projectWithBundleCaching = fixturifyProject.buildProjectModel();
          projectWithBundleCaching.initializeAddons();
  
          expect(() => {
            new EmberApp({
              project: projectWithBundleCaching,
              addons: {
                blacklist: ['foo'],
              },
            });
          }).to.throw(
            [
              '[ember-cli] addon bundle caching is disabled for apps that specify an addon "blacklist"',
              '',
              'All addons using bundle caching:',
              projectWithBundleCaching.addons.find((addon) => addon.name === 'foo').packageRoot,
            ].join('\n')
          );
        });
  
        it('throws an error if an addon `include` is specified', function () {
          fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
          fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
            callback: (inRepoAddon) => {
              inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
            },
          });
  
          fixturifyProject.writeSync();
  
          let projectWithBundleCaching = fixturifyProject.buildProjectModel();
          projectWithBundleCaching.initializeAddons();
  
          expect(() => {
            new EmberApp({
              project: projectWithBundleCaching,
              addons: {
                include: ['foo'],
              },
            });
          }).to.throw(
            [
              '[ember-cli] addon bundle caching is disabled for apps that specify an addon "include"',
              '',
              'All addons using bundle caching:',
              projectWithBundleCaching.addons.find((addon) => addon.name === 'foo').packageRoot,
            ].join('\n')
          );
        });
  
        it('throws an error if an addon `exclude` is specified', function () {
          fixturifyProject.addInRepoAddon('foo', '1.0.0', { allowCachingPerBundle: true });
          fixturifyProject.addInRepoAddon('foo-bar', '1.0.0', {
            callback: (inRepoAddon) => {
              inRepoAddon.pkg['ember-addon'].paths = ['../foo'];
            },
          });
  
          fixturifyProject.writeSync();
  
          let projectWithBundleCaching = fixturifyProject.buildProjectModel();
          projectWithBundleCaching.initializeAddons();
  
          expect(() => {
            new EmberApp({
              project: projectWithBundleCaching,
              addons: {
                exclude: ['foo'],
              },
            });
          }).to.throw(
            [
              '[ember-cli] addon bundle caching is disabled for apps that specify an addon "exclude"',
              '',
              'All addons using bundle caching:',
              projectWithBundleCaching.addons.find((addon) => addon.name === 'foo').packageRoot,
            ].join('\n')
          );
        });
      });
  
      describe('addonLintTree', function () {
        beforeEach(function () {
          addon = {
            lintTree: td.function(),
          };
  
          project.initializeAddons = function () {
            this.addons = [addon];
          };
  
          app = new EmberApp({
            project,
          });
        });
  
        it('does not throw an error if lintTree is not defined', function () {
          app.addonLintTree();
        });
  
        it('calls lintTree on the addon', function () {
          app.addonLintTree('blah', 'blam');
  
          td.verify(addon.lintTree('blah', 'blam'));
        });
      });
    });
  
    describe('import', function () {
      beforeEach(function () {
        app = new EmberApp({
          project,
        });
      });
  
      afterEach(function () {
        process.env.EMBER_ENV = undefined;
      });
  
      it('appends dependencies to vendor by default', function () {
        app.import('vendor/moment.js');
        let outputFile = app._scriptOutputFiles['/assets/vendor.js'];
  
        expect(outputFile).to.be.instanceof(Array);
        expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
      });
      it('appends dependencies', function () {
        app.import('vendor/moment.js', { type: 'vendor' });
  
        let outputFile = app._scriptOutputFiles['/assets/vendor.js'];
  
        expect(outputFile).to.be.instanceof(Array);
        expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
      });
  
      it('prepends dependencies', function () {
        app.import('vendor/es5-shim.js', { type: 'vendor', prepend: true });
  
        let outputFile = app._scriptOutputFiles['/assets/vendor.js'];
  
        expect(outputFile).to.be.instanceof(Array);
        expect(outputFile.indexOf('vendor/es5-shim.js')).to.equal(0);
      });
  
      it('prepends dependencies to outputFile', function () {
        app.import('vendor/moment.js', { outputFile: 'moment.js', prepend: true });
  
        let outputFile = app._scriptOutputFiles['moment.js'];
  
        expect(outputFile).to.be.instanceof(Array);
        expect(outputFile.indexOf('vendor/moment.js')).to.equal(0);
      });
  
      it('appends dependencies to outputFile', function () {
        app.import('vendor/moment.js', { outputFile: 'moment.js' });
  
        let outputFile = app._scriptOutputFiles['moment.js'];
  
        expect(outputFile).to.be.instanceof(Array);
        expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
      });
  
      it('defaults to development if production is not set', function () {
        process.env.EMBER_ENV = 'production';
        app.import({
          development: 'vendor/jquery.js',
        });
  
        let outputFile = app._scriptOutputFiles['/assets/vendor.js'];
        expect(outputFile.indexOf('vendor/jquery.js')).to.equal(outputFile.length - 1);
      });
  
      it('honors explicitly set to null in environment', function () {
        process.env.EMBER_ENV = 'production';
        // set EMBER_ENV before creating the project
  
        app = new EmberApp({
          project,
        });
  
        app.import({
          development: 'vendor/jquery.js',
          production: null,
        });
  
        expect(app._scriptOutputFiles['/assets/vendor.js']).to.not.contain('vendor/jquery.js');
      });
  
      it('normalizes asset path correctly', function () {
        app.import('vendor\\path\\to\\lib.js', { type: 'vendor' });
        app.import('vendor/path/to/lib2.js', { type: 'vendor' });
  
        expect(app._scriptOutputFiles['/assets/vendor.js']).to.contain('vendor/path/to/lib.js');
        expect(app._scriptOutputFiles['/assets/vendor.js']).to.contain('vendor/path/to/lib2.js');
      });
  
      it('option.using throws exception given invalid inputs', function () {
        // `using` is looped over if given, we should ensure this throws an exception with proper error message
        expect(() => {
          app.import('vendor/path/to/lib1.js', { using: 1 });
        }).to.throw(/You must pass an array of transformations for `using` option/);
  
        expect(() => {
          app.import('vendor/path/to/lib2.js', { using: 'foop' });
        }).to.throw(/You must pass an array of transformations for `using` option/);
  
        expect(() => {
          app.import('vendor/path/to/lib3.js', { using: [1] });
        }).to.throw(/list must have a `transformation` name/);
  
        expect(() => {
          app.import('vendor/path/to/lib3.js', { using: [{ foo: 'bar' }] });
        }).to.throw(/list must have a `transformation` name/);
      });
    });
  
    describe('vendorFiles', function () {
      let defaultVendorFiles = ['jquery.js', 'ember.js', 'app-shims.js'];
  
      describe('handlebars.js', function () {
        it('does not app.import handlebars if not present in bower.json', function () {
          let app = new EmberApp({
            project,
          });
  
          expect(app.vendorFiles).not.to.include.keys('handlebars.js');
        });
  
        it('includes handlebars if present in bower.json', function () {
          projectPath = path.resolve(__dirname, '../../fixtures/project-with-handlebars');
          project = setupProject(projectPath);
  
          let app = new EmberApp({
            project,
          });
  
          expect(app.vendorFiles).to.include.keys('handlebars.js');
        });
  
        it('includes handlebars if present in provided `vendorFiles`', function () {
          let app = new EmberApp({
            project,
            vendorFiles: {
              'handlebars.js': 'some/path/whatever.js',
            },
          });
  
          expect(app.vendorFiles).to.include.keys('handlebars.js');
        });
      });
  
      it('defines vendorFiles by default', function () {
        app = new EmberApp({
          project,
        });
        expect(Object.keys(app.vendorFiles)).to.deep.equal(defaultVendorFiles);
      });
  
      it('redefines a location of a vendor asset', function () {
        app = new EmberApp({
          project,
  
          vendorFiles: {
            'ember.js': 'vendor/ember.js',
          },
        });
        expect(app.vendorFiles['ember.js']).to.equal('vendor/ember.js');
      });
  
      it('defines vendorFiles in order even when option for it is passed', function () {
        app = new EmberApp({
          project,
  
          vendorFiles: {
            'ember.js': 'vendor/ember.js',
          },
        });
        expect(Object.keys(app.vendorFiles)).to.deep.equal(defaultVendorFiles);
      });
  
      it('does not include jquery if the app has `@ember/jquery` installed', function () {
        project.initializeAddons = function () {
          this.addons = [{ name: '@ember/jquery' }];
        };
        app = new EmberApp({ project });
        let filesWithoutJQuery = defaultVendorFiles.filter((e) => e !== 'jquery.js');
        expect(Object.keys(app.vendorFiles)).to.deep.equal(filesWithoutJQuery);
      });
  
      it('does not include jquery if the app has `@ember/optional-features` with the `jquery-integration` FF turned off', function () {
        project.initializeAddons = function () {
          this.addons = [
            {
              name: 'ember-source',
              paths: { jquery: 'foo', testing: null },
            },
            {
              name: '@ember/optional-features',
              isFeatureEnabled() {
                return false;
              },
            },
          ];
        };
        app = new EmberApp({ project, vendorFiles: { 'ember-testing.js': null } });
        let filesWithoutJQuery = defaultVendorFiles.filter((e) => e !== 'jquery.js');
        expect(Object.keys(app.vendorFiles)).to.deep.equal(filesWithoutJQuery);
      });
  
      it('removes dependency in vendorFiles', function () {
        app = new EmberApp({
          project,
  
          vendorFiles: {
            'ember.js': null,
            'handlebars.js': null,
          },
        });
        let vendorFiles = Object.keys(app.vendorFiles);
        expect(vendorFiles).to.not.contain('ember.js');
        expect(vendorFiles).to.not.contain('handlebars.js');
      });
  
      it('defaults to ember.debug.js if exists in bower_components', function () {
        let root = path.resolve(__dirname, '../../fixtures/app/with-default-ember-debug');
  
        app = new EmberApp({
          project: setupProject(root),
        });
  
        let files = app.vendorFiles['ember.js'];
        expect(files.development).to.equal('bower_components/ember/ember.debug.js');
      });
  
      it('switches the default ember.debug.js to ember.js if it does not exist', function () {
        let root = path.resolve(__dirname, '../../fixtures/app/without-ember-debug');
  
        app = new EmberApp({
          project: setupProject(root),
        });
  
        let files = app.vendorFiles['ember.js'];
        expect(files.development).to.equal('bower_components/ember/ember.js');
      });
  
      it('does not clobber an explicitly configured ember development file', function () {
        app = new EmberApp({
          project,
  
          vendorFiles: {
            'ember.js': {
              development: 'vendor/ember.debug.js',
            },
          },
        });
        let files = app.vendorFiles['ember.js'];
        expect(files.development).to.equal('vendor/ember.debug.js');
      });
    });
  
    it('fails with invalid type', function () {
      let app = new EmberApp({
        project,
      });
  
      expect(() => {
        app.import('vendor/b/c/foo.js', { type: 'javascript' });
      }).to.throw(
        /You must pass either `vendor` or `test` for options.type in your call to `app.import` for file: foo.js/
      );
    });
  
    describe('_initOptions', function () {
      it('sets the tests directory as watched when tests are enabled', function () {
        let app = new EmberApp({
          project,
        });
  
        app._initOptions({
          tests: true,
        });
  
        expect(app.options.trees.tests).to.be.an.instanceOf(WatchedDir);
      });
      it('sets the tests directory as unwatched when tests are disabled', function () {
        let app = new EmberApp({
          project,
        });
  
        app._initOptions({
          tests: false,
        });
  
        expect(app.options.trees.tests).to.be.an.instanceOf(UnwatchedDir);
      });
    });
  
    describe('_resolveLocal', function () {
      it('resolves a path relative to the project root', function () {
        let app = new EmberApp({
          project,
        });
  
        let result = app._resolveLocal('foo');
        expect(result).to.equal(path.join(project.root, 'foo'));
      });
    });
  
    describe('_concatFiles()', function () {
      beforeEach(function () {
        app = new EmberApp({ project });
      });
  
      describe('concat order', function () {
        beforeEach(function () {
          mockTemplateRegistry(app);
        });
  
        it('correctly orders concats from app.styles()', function () {
          app.import('files/b.css');
          app.import('files/c.css');
          app.import('files/a.css', { prepend: true });
          app.import('files/d.css');
  
          expect(app._styleOutputFiles['/assets/vendor.css']).to.deep.equal([
            'files/a.css',
            'files/b.css',
            'files/c.css',
            'files/d.css',
          ]);
        });
  
        it('correctly orders concats from app.testFiles()', function () {
          app.import('files/b.js', { type: 'test' });
          app.import('files/c.js', { type: 'test' });
          app.import('files/a.js', { type: 'test' });
          app.import('files/a.js', { type: 'test', prepend: true }); // Should end up second.
          app.import('files/d.js', { type: 'test' });
          app.import('files/d.js', { type: 'test', prepend: true }); // Should end up first.
          app.import('files/d.js', { type: 'test' });
  
          app.import('files/b.css', { type: 'test' });
          app.import('files/c.css', { type: 'test' });
          app.import('files/a.css', { type: 'test', prepend: true });
          app.import('files/d.css', { type: 'test' });
          app.import('files/d.css', { type: 'test' });
  
          expect(app.legacyTestFilesToAppend).to.deep.equal(['files/d.js', 'files/a.js', 'files/b.js', 'files/c.js']);
  
          expect(app.vendorTestStaticStyles).to.deep.equal(['files/a.css', 'files/b.css', 'files/c.css', 'files/d.css']);
        });
      });
    });
  
    describe('deprecations', function () {
      it('shows ember-cli-shims deprecation', function () {
        let root = path.resolve(__dirname, '../../fixtures/app/npm');
        let project = setupProject(root);
        project.require = function () {
          return {
            version: '5.0.0',
          };
        };
        project.initializeAddons = function () {
          this.addons = [
            {
              name: 'ember-cli-babel',
              pkg: { version: '5.0.0' },
            },
          ];
        };
  
        app = new EmberApp({
          project,
        });
  
        expect(project.ui.output).to.contain(
          "You have not included `ember-cli-shims` in your project's `bower.json` or `package.json`."
        );
      });
  
      describe('jQuery integration', function () {
        it('shows deprecation', function () {
          project.initializeAddons = function () {
            this.addons = [{ name: 'ember-source', paths: {} }];
          };
          app = new EmberApp({ project });
  
          expect(project.ui.output).to.contain(
            'The integration of jQuery into Ember has been deprecated and will be removed with Ember 4.0'
          );
        });
  
        it('does not show deprecation if the app has `@ember/jquery` installed', function () {
          project.initializeAddons = function () {
            this.addons = [{ name: 'ember-source', paths: {} }, { name: '@ember/jquery' }];
          };
          app = new EmberApp({ project });
          expect(project.ui.output).to.not.contain(
            'The integration of jQuery into Ember has been deprecated and will be removed with Ember 4.0'
          );
        });
  
        it('does not show deprecation if the app has `@ember/optional-features` with the `jquery-integration` FF turned off', function () {
          project.initializeAddons = function () {
            this.addons = [
              { name: 'ember-source', paths: {} },
              {
                name: '@ember/optional-features',
                isFeatureEnabled() {
                  return false;
                },
              },
            ];
          };
          app = new EmberApp({ project, vendorFiles: { 'ember-testing.js': null } });
          expect(project.ui.output).to.not.contain(
            'The integration of jQuery into Ember has been deprecated and will be removed with Ember 4.0'
          );
        });
      });
    });
  });
  