const path = require('path') const UIWatcher = require('../lib/ui-watcher') const {it, fit, ffit, afterEach, beforeEach, conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars describe('UIWatcher', () => { let uiWatcher = null beforeEach(() => atom.packages.packageDirPaths.push(path.join(__dirname, 'fixtures'))) afterEach(() => uiWatcher && uiWatcher.destroy()) describe("when a base theme's file changes", () => { beforeEach(() => { spyOn(atom.themes, 'resolveStylesheet').andReturn(path.join(__dirname, 'fixtures', 'static', 'atom.less')) uiWatcher = new UIWatcher() }) it('reloads all the base styles', () => { spyOn(atom.themes, 'reloadBaseStylesheets') expect(uiWatcher.baseTheme.entities[0].getPath()).toContain(`${path.sep}static${path.sep}`) uiWatcher.baseTheme.entities[0].emitter.emit('did-change') expect(atom.themes.reloadBaseStylesheets).toHaveBeenCalled() }) }) it("watches all the style sheets in the theme's styles folder", async () => { const packagePath = path.join(__dirname, 'fixtures', 'package-with-styles-folder') await atom.packages.activatePackage(packagePath) uiWatcher = new UIWatcher() const lastWatcher = uiWatcher.watchers[uiWatcher.watchers.length - 1] expect(lastWatcher.entities.length).toBe(4) expect(lastWatcher.entities[0].getPath()).toBe(path.join(packagePath, 'styles')) expect(lastWatcher.entities[1].getPath()).toBe(path.join(packagePath, 'styles', '3.css')) expect(lastWatcher.entities[2].getPath()).toBe(path.join(packagePath, 'styles', 'sub', '1.css')) expect(lastWatcher.entities[3].getPath()).toBe(path.join(packagePath, 'styles', 'sub', '2.less')) }) describe('when a package stylesheet file changes', async () => { beforeEach(async () => { await atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-styles-manifest')) uiWatcher = new UIWatcher() }) it('reloads all package styles', () => { const pack = atom.packages.getActivePackages()[0] spyOn(pack, 'reloadStylesheets') uiWatcher.watchers[uiWatcher.watchers.length - 1].entities[1].emitter.emit('did-change') expect(pack.reloadStylesheets).toHaveBeenCalled() }) }) describe('when a package does not have a stylesheet', () => { beforeEach(async () => { await atom.packages.activatePackage('package-with-index') uiWatcher = new UIWatcher() }) it('does not create a PackageWatcher', () => { expect(uiWatcher.watchedPackages['package-with-index']).toBeUndefined() }) }) describe('when a package global file changes', () => { beforeEach(async () => { atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-multiple-imported-files']) await atom.themes.activateThemes() uiWatcher = new UIWatcher() }) afterEach(() => atom.themes.deactivateThemes()) it('reloads every package when the variables file changes', () => { let varEntity for (const theme of atom.themes.getActiveThemes()) { spyOn(theme, 'reloadStylesheets') } for (const entity of uiWatcher.watchedThemes.get('theme-with-multiple-imported-files').entities) { if (entity.getPath().indexOf('variables') > -1) varEntity = entity } varEntity.emitter.emit('did-change') for (const theme of atom.themes.getActiveThemes()) { expect(theme.reloadStylesheets).toHaveBeenCalled() } }) }) describe('watcher lifecycle', () => { it('starts watching a package if it is activated after initial startup', async () => { uiWatcher = new UIWatcher() expect(uiWatcher.watchedPackages.size).toBe(0) await atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-styles-folder')) expect(uiWatcher.watchedPackages.get('package-with-styles-folder')).not.toBeUndefined() }) it('unwatches a package after it is deactivated', async () => { await atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-styles-folder')) uiWatcher = new UIWatcher() const watcher = uiWatcher.watchedPackages.get('package-with-styles-folder') expect(watcher).not.toBeUndefined() const watcherDestructionSpy = jasmine.createSpy('watcher-on-did-destroy') watcher.onDidDestroy(watcherDestructionSpy) await atom.packages.deactivatePackage('package-with-styles-folder') expect(uiWatcher.watchedPackages.get('package-with-styles-folder')).toBeUndefined() expect(uiWatcher.watchedPackages.size).toBe(0) expect(watcherDestructionSpy).toHaveBeenCalled() }) it('does not watch activated packages after the UI watcher has been destroyed', async () => { uiWatcher = new UIWatcher() uiWatcher.destroy() await atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-styles-folder')) expect(uiWatcher.watchedPackages.size).toBe(0) }) }) describe('minimal theme packages', () => { let pack = null beforeEach(async () => { atom.config.set('core.themes', ['theme-with-syntax-variables', 'theme-with-index-less']) await atom.themes.activateThemes() uiWatcher = new UIWatcher() pack = atom.themes.getActiveThemes()[0] }) afterEach(() => atom.themes.deactivateThemes()) it('watches themes without a styles directory', () => { spyOn(pack, 'reloadStylesheets') spyOn(atom.themes, 'reloadBaseStylesheets') const watcher = uiWatcher.watchedThemes.get('theme-with-index-less') expect(watcher.entities.length).toBe(1) watcher.entities[0].emitter.emit('did-change') expect(pack.reloadStylesheets).toHaveBeenCalled() expect(atom.themes.reloadBaseStylesheets).not.toHaveBeenCalled() }) }) describe('theme packages', () => { let pack = null beforeEach(async () => { atom.config.set('core.themes', ['theme-with-syntax-variables', 'theme-with-multiple-imported-files']) await atom.themes.activateThemes() uiWatcher = new UIWatcher() pack = atom.themes.getActiveThemes()[0] }) afterEach(() => atom.themes.deactivateThemes()) it('reloads the theme when anything within the theme changes', () => { spyOn(pack, 'reloadStylesheets') spyOn(atom.themes, 'reloadBaseStylesheets') const watcher = uiWatcher.watchedThemes.get('theme-with-multiple-imported-files') expect(watcher.entities.length).toBe(6) watcher.entities[2].emitter.emit('did-change') expect(pack.reloadStylesheets).toHaveBeenCalled() expect(atom.themes.reloadBaseStylesheets).not.toHaveBeenCalled() watcher.entities[watcher.entities.length - 1].emitter.emit('did-change') expect(atom.themes.reloadBaseStylesheets).toHaveBeenCalled() }) it('unwatches when a theme is deactivated', async () => { jasmine.useRealClock() atom.config.set('core.themes', []) await conditionPromise(() => !uiWatcher.watchedThemes['theme-with-multiple-imported-files']) }) it('watches a new theme when it is deactivated', async () => { jasmine.useRealClock() atom.config.set('core.themes', ['theme-with-syntax-variables', 'theme-with-package-file']) await conditionPromise(() => uiWatcher.watchedThemes.get('theme-with-package-file')) pack = atom.themes.getActiveThemes()[0] spyOn(pack, 'reloadStylesheets') expect(pack.name).toBe('theme-with-package-file') const watcher = uiWatcher.watchedThemes.get('theme-with-package-file') watcher.entities[2].emitter.emit('did-change') expect(pack.reloadStylesheets).toHaveBeenCalled() }) }) })