vscode-icons/vscode-icons

View on GitHub
test/app/eventListeners.test.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
/* eslint-disable prefer-arrow-callback */
/* eslint-disable no-unused-expressions */
import { expect } from 'chai';
import { cloneDeep } from 'lodash';
import * as sinon from 'sinon';
import { ExtensionManager } from '../../src/app/extensionManager';
import { ErrorHandler } from '../../src/common/errorHandler';
import { ConfigManager } from '../../src/configuration/configManager';
import { constants } from '../../src/constants';
import { IconsGenerator } from '../../src/iconsManifest';
import { IntegrityManager } from '../../src/integrity/integrityManager';
import * as models from '../../src/models';
import { NotificationManager } from '../../src/notification/notificationManager';
import { ProjectAutoDetectionManager } from '../../src/pad/projectAutoDetectionManager';
import { SettingsManager } from '../../src/settings/settingsManager';
import { VSCodeManager } from '../../src/vscode/vscodeManager';
import { vsicons } from '../fixtures/vsicons';

describe('ExtensionManager: event listeners tests', function () {
  context('ensures that', function () {
    let sandbox: sinon.SinonSandbox;
    let vscodeManagerStub: sinon.SinonStubbedInstance<models.IVSCodeManager>;
    let configManagerStub: sinon.SinonStubbedInstance<models.IConfigManager>;
    let settingsManagerStub: sinon.SinonStubbedInstance<models.ISettingsManager>;
    let notifyManagerStub: sinon.SinonStubbedInstance<models.INotificationManager>;
    let iconsGeneratorStub: sinon.SinonStubbedInstance<models.IIconsGenerator>;
    let padMngStub: sinon.SinonStubbedInstance<models.IProjectAutoDetectionManager>;
    let integrityManagerStub: sinon.SinonStubbedInstance<models.IIntegrityManager>;

    let onDidChangeConfigurationStub: sinon.SinonStub;
    let logErrorStub: sinon.SinonStub;

    let extensionManager: models.IExtensionManager;
    let vsiconsClone: models.IVSIcons;
    let state: models.IState;

    beforeEach(function () {
      sandbox = sinon.createSandbox();

      vscodeManagerStub =
        sandbox.createStubInstance<models.IVSCodeManager>(VSCodeManager);
      sandbox.stub(vscodeManagerStub, 'context').get(() => ({
        subscriptions: [],
      }));
      onDidChangeConfigurationStub = sandbox.stub();
      sandbox.stub(vscodeManagerStub, 'workspace').get(() => ({
        onDidChangeConfiguration: onDidChangeConfigurationStub,
      }));

      configManagerStub =
        sandbox.createStubInstance<models.IConfigManager>(ConfigManager);
      vsiconsClone = cloneDeep(vsicons);
      sandbox.stub(configManagerStub, 'vsicons').get(() => vsiconsClone);

      settingsManagerStub =
        sandbox.createStubInstance<models.ISettingsManager>(SettingsManager);
      notifyManagerStub =
        sandbox.createStubInstance<models.INotificationManager>(
          NotificationManager,
        );

      iconsGeneratorStub =
        sandbox.createStubInstance<models.IIconsGenerator>(IconsGenerator);

      padMngStub =
        sandbox.createStubInstance<models.IProjectAutoDetectionManager>(
          ProjectAutoDetectionManager,
        );

      integrityManagerStub =
        sandbox.createStubInstance<models.IIntegrityManager>(IntegrityManager);

      extensionManager = new ExtensionManager(
        vscodeManagerStub,
        configManagerStub,
        settingsManagerStub,
        notifyManagerStub,
        iconsGeneratorStub,
        padMngStub,
        integrityManagerStub,
      );

      logErrorStub = sandbox.stub(ErrorHandler, 'logError');

      state = SettingsManager.defaultState;
    });

    afterEach(function () {
      sandbox.restore();
    });

    context(`the listener on configuration changes`, function () {
      let affectsConfigurationStub: sinon.SinonStub;

      beforeEach(function () {
        affectsConfigurationStub = sandbox.stub();
      });

      context(`when the affected configuration is the icon theme`, function () {
        beforeEach(function () {
          affectsConfigurationStub.returns(true);
        });

        context(`and is set to this extension's name`, function () {
          beforeEach(function () {
            configManagerStub.getIconTheme.returns(constants.extension.name);
          });

          it(`logs an Error, when 'updateStatus' fails`, function () {
            settingsManagerStub.getState.returns(state);
            settingsManagerStub.updateStatus.throws();

            onDidChangeConfigurationStub.callArgOnWith(0, extensionManager, {
              affectsConfiguration: affectsConfigurationStub,
            });

            expect(logErrorStub.called).to.be.true;
          });

          context(`and the 'status' is NOT 'activated'`, function () {
            context(`the 'status' gets set to`, function () {
              it(`'activated' and gets updated`, function () {
                state.status = models.ExtensionStatus.deactivated;
                settingsManagerStub.getState.returns(state);
                settingsManagerStub.updateStatus.resolves();

                onDidChangeConfigurationStub.callArgOnWith(
                  0,
                  extensionManager,
                  {
                    affectsConfiguration: affectsConfigurationStub,
                  },
                );

                expect(
                  settingsManagerStub.updateStatus.calledOnceWithExactly(
                    models.ExtensionStatus.activated,
                  ),
                ).to.be.true;
                expect(
                  affectsConfigurationStub.calledOnceWithExactly(
                    constants.vscode.iconThemeSetting,
                  ),
                ).to.be.true;
              });
            });
          });

          context(`and the 'status' is 'activated'`, function () {
            context(`the 'status' gets`, function () {
              it(`NOT updated`, function () {
                state.status = models.ExtensionStatus.activated;
                settingsManagerStub.getState.returns(state);

                onDidChangeConfigurationStub.callArgOnWith(
                  0,
                  extensionManager,
                  {
                    affectsConfiguration: affectsConfigurationStub,
                  },
                );

                expect(settingsManagerStub.updateStatus.called).to.be.false;
                expect(
                  affectsConfigurationStub.calledOnceWithExactly(
                    constants.vscode.iconThemeSetting,
                  ),
                ).to.be.true;
              });
            });
          });
        });

        context(`and is NOT set to this extension's name`, function () {
          beforeEach(function () {
            configManagerStub.getIconTheme.returns(undefined);
          });

          context(`and the 'status' is 'activated'`, function () {
            context(`the extension 'status' gets set to`, function () {
              it(`'deactivated' and gets updated`, function () {
                state.status = models.ExtensionStatus.activated;
                settingsManagerStub.getState.returns(state);
                settingsManagerStub.updateStatus.resolves();

                onDidChangeConfigurationStub.callArgOnWith(
                  0,
                  extensionManager,
                  {
                    affectsConfiguration: affectsConfigurationStub,
                  },
                );

                expect(
                  settingsManagerStub.updateStatus.calledOnceWithExactly(
                    models.ExtensionStatus.deactivated,
                  ),
                ).to.be.true;
                expect(
                  affectsConfigurationStub.calledOnceWithExactly(
                    constants.vscode.iconThemeSetting,
                  ),
                ).to.be.true;
              });
            });
          });

          context(`and the 'status' is 'deactivated'`, function () {
            context(`the 'status' gets`, function () {
              it(`NOT updated`, function () {
                state.status = models.ExtensionStatus.deactivated;
                settingsManagerStub.getState.returns(state);

                onDidChangeConfigurationStub.callArgOnWith(
                  0,
                  extensionManager,
                  {
                    affectsConfiguration: affectsConfigurationStub,
                  },
                );

                expect(settingsManagerStub.updateStatus.called).to.be.false;
                expect(
                  affectsConfigurationStub.calledOnceWithExactly(
                    constants.vscode.iconThemeSetting,
                  ),
                ).to.be.true;
              });
            });
          });
        });
      });

      context(`when the affected configuration`, function () {
        let executeAndReloadStub: sinon.SinonStub;
        let applyCustomizationCommandStub: sinon.SinonStub;

        beforeEach(function () {
          executeAndReloadStub = sandbox.stub(
            extensionManager,
            // @ts-ignore
            'executeAndReload',
          );
          applyCustomizationCommandStub = sandbox.stub(
            extensionManager,
            // @ts-ignore
            'applyCustomizationCommand',
          );
          affectsConfigurationStub.onFirstCall().returns(false).returns(true);
        });

        context(`is the 'presets' or the 'associations'`, function () {
          context(`and is set to 'reload' the editor`, function () {
            it(`calls the 'executeAndReload' function`, function () {
              const timer = sandbox.useFakeTimers();

              // @ts-ignore
              extensionManager.doReload = true;

              onDidChangeConfigurationStub.callArgOnWith(0, extensionManager, {
                affectsConfiguration: affectsConfigurationStub,
              });

              expect(affectsConfigurationStub.calledTwice).to.be.true;
              // @ts-ignore
              expect(extensionManager.doReload).to.be.false;

              timer.tick(500);

              expect(executeAndReloadStub.calledOnceWithExactly(undefined)).to
                .be.true;

              timer.restore();
            });
          });

          context(`and is NOT set to 'reload' the editor`, function () {
            context(`and is showing the custom message`, function () {
              beforeEach(function () {
                // @ts-ignore
                extensionManager.customMsgShown = true;
              });

              it(`does nothing`, function () {
                onDidChangeConfigurationStub.callArgOnWith(
                  0,
                  extensionManager,
                  {
                    affectsConfiguration: affectsConfigurationStub,
                  },
                );

                expect(applyCustomizationCommandStub.called).to.be.false;
              });
            });

            context(`and is NOT showing the custom message`, function () {
              beforeEach(function () {
                // @ts-ignore
                extensionManager.customMsgShown = false;
              });

              context(`does call 'applyCustomizationCommand'`, function () {
                it(`when the configuration has changed`, function () {
                  configManagerStub.hasConfigChanged.returns(true);

                  onDidChangeConfigurationStub.callArgOnWith(
                    0,
                    extensionManager,
                    {
                      affectsConfiguration: affectsConfigurationStub,
                    },
                  );

                  expect(
                    configManagerStub.hasConfigChanged.calledOnceWithExactly(
                      vsiconsClone,
                      [
                        constants.vsicons.presets.name,
                        constants.vsicons.associations.name,
                      ],
                    ),
                  ).to.be.true;
                  expect(
                    applyCustomizationCommandStub.calledOnceWithExactly([
                      models.LangResourceKeys.dontShowThis,
                    ]),
                  ).to.be.true;
                });
              });

              context(`does NOT call 'applyCustomizationCommand'`, function () {
                it(`when the configuration has NOT changed`, function () {
                  configManagerStub.hasConfigChanged.returns(false);

                  onDidChangeConfigurationStub.callArgOnWith(
                    0,
                    extensionManager,
                    {
                      affectsConfiguration: affectsConfigurationStub,
                    },
                  );

                  expect(
                    configManagerStub.hasConfigChanged.calledOnceWithExactly(
                      vsiconsClone,
                      [
                        constants.vsicons.presets.name,
                        constants.vsicons.associations.name,
                      ],
                    ),
                  ).to.be.true;
                  expect(applyCustomizationCommandStub.called).to.be.false;
                });

                it(`when set NOT to show the custom message`, function () {
                  configManagerStub.vsicons.dontShowConfigManuallyChangedMessage =
                    true;

                  onDidChangeConfigurationStub.callArgOnWith(
                    0,
                    extensionManager,
                    {
                      affectsConfiguration: affectsConfigurationStub,
                    },
                  );

                  expect(configManagerStub.hasConfigChanged.called).to.be.false;
                  expect(applyCustomizationCommandStub.called).to.be.false;
                });
              });
            });
          });
        });

        context(`is NOT the 'presets' or the 'associations'`, function () {
          it(`does nothing`, function () {
            affectsConfigurationStub.returns(false);

            onDidChangeConfigurationStub.callArgOnWith(0, extensionManager, {
              affectsConfiguration: affectsConfigurationStub,
            });

            expect(affectsConfigurationStub.calledThrice).to.be.true;
            expect(applyCustomizationCommandStub.called).to.be.false;
            expect(executeAndReloadStub.called).to.be.false;
          });
        });
      });
    });
  });
});