Finish manual decaf settings-view

This commit is contained in:
confused-Techie 2023-08-30 23:50:21 -07:00
parent 9d30cd2276
commit 57965f8837
31 changed files with 371 additions and 3571 deletions

View File

@ -1,90 +0,0 @@
GeneralPanel = require '../lib/general-panel'
describe "GeneralPanel", ->
panel = null
getValueForId = (id) ->
element = panel.element.querySelector("##{id.replace(/\./g, '\\.')}")
if element.tagName is "INPUT"
element.checked
else if element.tagName is "SELECT"
element.value
else
element.getModel().getText()
setValueForId = (id, value) ->
element = panel.element.querySelector("##{id.replace(/\./g, '\\.')}")
if element.tagName is "INPUT"
element.checked = value
element.dispatchEvent(new Event('change', {bubbles: true}))
else if element.tagName is "SELECT"
element.value = value
element.dispatchEvent(new Event('change', {bubbles: true}))
else
element.getModel().setText(value?.toString())
window.advanceClock(10000) # wait for contents-modified to be triggered
beforeEach ->
atom.config.set('core.enum', 4)
atom.config.set('core.int', 22)
atom.config.set('core.float', 0.1)
atom.config.setSchema('', type: 'object')
atom.config.setSchema('core.enum',
type: 'integer'
default: 2
enum: [2, 4, 6, 8]
)
panel = new GeneralPanel()
it "automatically binds named fields to their corresponding config keys", ->
expect(getValueForId('core.enum')).toBe '4'
expect(getValueForId('core.int')).toBe '22'
expect(getValueForId('core.float')).toBe '0.1'
atom.config.set('core.enum', 6)
atom.config.set('core.int', 222)
atom.config.set('core.float', 0.11)
expect(getValueForId('core.enum')).toBe '6'
expect(getValueForId('core.int')).toBe '222'
expect(getValueForId('core.float')).toBe '0.11'
setValueForId('core.enum', '2')
setValueForId('core.int', 90)
setValueForId('core.float', 89.2)
expect(atom.config.get('core.enum')).toBe 2
expect(atom.config.get('core.int')).toBe 90
expect(atom.config.get('core.float')).toBe 89.2
setValueForId('core.int', '')
setValueForId('core.float', '')
expect(atom.config.get('core.int')).toBeUndefined()
expect(atom.config.get('core.float')).toBeUndefined()
it "does not save the config value until it has been changed to a new value", ->
observeHandler = jasmine.createSpy("observeHandler")
atom.config.observe "core.int", observeHandler
observeHandler.reset()
window.advanceClock(10000) # wait for contents-modified to be triggered
expect(observeHandler).not.toHaveBeenCalled()
setValueForId('core.int', 2)
expect(observeHandler).toHaveBeenCalled()
observeHandler.reset()
setValueForId('core.int', 2)
expect(observeHandler).not.toHaveBeenCalled()
it "does not update the editor text unless the value it parses to changes", ->
setValueForId('core.int', "2.")
expect(atom.config.get('core.int')).toBe 2
expect(getValueForId('core.int')).toBe '2.'
it "shows the package settings notes for core and editor settings", ->
expect(panel.element.querySelector('#core-settings-note')).toExist()
expect(panel.element.querySelector('#core-settings-note').textContent).toContain('their package card in')

View File

@ -1,11 +1,7 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const GeneralPanel = require('../lib/general-panel');
describe("GeneralPanel", function() {
describe("GeneralPanel", () => {
let panel = null;
const getValueForId = function(id) {
@ -33,7 +29,7 @@ describe("GeneralPanel", function() {
}
};
beforeEach(function() {
beforeEach(() => {
atom.config.set('core.enum', 4);
atom.config.set('core.int', 22);
atom.config.set('core.float', 0.1);
@ -46,10 +42,10 @@ describe("GeneralPanel", function() {
}
);
return panel = new GeneralPanel();
panel = new GeneralPanel();
});
it("automatically binds named fields to their corresponding config keys", function() {
it("automatically binds named fields to their corresponding config keys", () => {
expect(getValueForId('core.enum')).toBe('4');
expect(getValueForId('core.int')).toBe('22');
expect(getValueForId('core.float')).toBe('0.1');
@ -74,10 +70,10 @@ describe("GeneralPanel", function() {
setValueForId('core.float', '');
expect(atom.config.get('core.int')).toBeUndefined();
return expect(atom.config.get('core.float')).toBeUndefined();
expect(atom.config.get('core.float')).toBeUndefined();
});
it("does not save the config value until it has been changed to a new value", function() {
it("does not save the config value until it has been changed to a new value", () => {
const observeHandler = jasmine.createSpy("observeHandler");
atom.config.observe("core.int", observeHandler);
observeHandler.reset();
@ -90,17 +86,17 @@ describe("GeneralPanel", function() {
observeHandler.reset();
setValueForId('core.int', 2);
return expect(observeHandler).not.toHaveBeenCalled();
expect(observeHandler).not.toHaveBeenCalled();
});
it("does not update the editor text unless the value it parses to changes", function() {
it("does not update the editor text unless the value it parses to changes", () => {
setValueForId('core.int', "2.");
expect(atom.config.get('core.int')).toBe(2);
return expect(getValueForId('core.int')).toBe('2.');
expect(getValueForId('core.int')).toBe('2.');
});
return it("shows the package settings notes for core and editor settings", function() {
it("shows the package settings notes for core and editor settings", () => {
expect(panel.element.querySelector('#core-settings-note')).toExist();
return expect(panel.element.querySelector('#core-settings-note').textContent).toContain('their package card in');
expect(panel.element.querySelector('#core-settings-note').textContent).toContain('their package card in');
});
});

View File

@ -1,113 +0,0 @@
InstallPanel = require '../lib/install-panel'
PackageManager = require '../lib/package-manager'
SettingsView = require '../lib/settings-view'
describe 'InstallPanel', ->
beforeEach ->
settingsView = new SettingsView()
@packageManager = new PackageManager()
@panel = new InstallPanel(settingsView, @packageManager)
describe "when the packages button is clicked", ->
beforeEach ->
spyOn(@panel, 'search')
@panel.refs.searchEditor.setText('something')
it "performs a search for the contents of the input", ->
@panel.refs.searchPackagesButton.click()
expect(@panel.searchType).toBe 'packages'
expect(@panel.search).toHaveBeenCalledWith 'something'
expect(@panel.search.callCount).toBe 1
@panel.refs.searchPackagesButton.click()
expect(@panel.searchType).toBe 'packages'
expect(@panel.search).toHaveBeenCalledWith 'something'
expect(@panel.search.callCount).toBe 2
describe "when the themes button is clicked", ->
beforeEach ->
spyOn(@panel, 'search')
@panel.refs.searchEditor.setText('something')
it "performs a search for the contents of the input", ->
@panel.refs.searchThemesButton.click()
expect(@panel.searchType).toBe 'themes'
expect(@panel.search.callCount).toBe 1
expect(@panel.search).toHaveBeenCalledWith 'something'
@panel.refs.searchThemesButton.click()
expect(@panel.searchType).toBe 'themes'
expect(@panel.search.callCount).toBe 2
describe "when the buttons are toggled", ->
beforeEach ->
spyOn(@panel, 'search')
@panel.refs.searchEditor.setText('something')
it "performs a search for the contents of the input", ->
@panel.refs.searchThemesButton.click()
expect(@panel.searchType).toBe 'themes'
expect(@panel.search.callCount).toBe 1
expect(@panel.search).toHaveBeenCalledWith 'something'
@panel.refs.searchPackagesButton.click()
expect(@panel.searchType).toBe 'packages'
expect(@panel.search.callCount).toBe 2
@panel.refs.searchThemesButton.click()
expect(@panel.searchType).toBe 'themes'
expect(@panel.search.callCount).toBe 3
describe "searching packages", ->
it "displays the packages in the order returned", ->
spyOn(@panel.client, 'search').andCallFake -> Promise.resolve([{name: 'not-first'}, {name: 'first'}])
spyOn(@panel, 'getPackageCardView').andCallThrough()
waitsForPromise =>
@panel.search('first')
runs ->
expect(@panel.getPackageCardView.argsForCall[0][0].name).toEqual 'not-first'
expect(@panel.getPackageCardView.argsForCall[1][0].name).toEqual 'first'
describe "searching git packages", ->
beforeEach ->
spyOn(@panel, 'showGitInstallPackageCard').andCallThrough()
it "shows a git installation card with git specific info for ssh URLs", ->
query = 'git@github.com:user/repo.git'
@panel.performSearchForQuery(query)
args = @panel.showGitInstallPackageCard.argsForCall[0][0]
expect(args.name).toEqual query
expect(args.gitUrlInfo).toBeTruthy()
it "shows a git installation card with git specific info for https URLs", ->
query = 'https://github.com/user/repo.git'
@panel.performSearchForQuery(query)
args = @panel.showGitInstallPackageCard.argsForCall[0][0]
expect(args.name).toEqual query
expect(args.gitUrlInfo).toBeTruthy()
it "shows a git installation card with git specific info for shortcut URLs", ->
query = 'user/repo'
@panel.performSearchForQuery(query)
args = @panel.showGitInstallPackageCard.argsForCall[0][0]
expect(args.name).toEqual query
expect(args.gitUrlInfo).toBeTruthy()
it "doesn't show a git installation card for normal packages", ->
query = 'this-package-is-so-normal'
@panel.performSearchForQuery(query)
expect(@panel.showGitInstallPackageCard).not.toHaveBeenCalled()
describe "when a package with the same gitUrlInfo property is installed", ->
beforeEach ->
@gitUrlInfo = jasmine.createSpy('gitUrlInfo')
@panel.showGitInstallPackageCard(gitUrlInfo: @gitUrlInfo)
it "replaces the package card with the newly installed pack object", ->
newPack =
gitUrlInfo: @gitUrlInfo
spyOn(@panel, 'updateGitPackageCard')
@packageManager.emitter.emit('package-installed', {pack: newPack})
expect(@panel.updateGitPackageCard).toHaveBeenCalledWith newPack

View File

@ -1,26 +1,22 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const InstallPanel = require('../lib/install-panel');
const PackageManager = require('../lib/package-manager');
const SettingsView = require('../lib/settings-view');
describe('InstallPanel', function() {
beforeEach(function() {
describe('InstallPanel', () => {
beforeEach(() => {
const settingsView = new SettingsView();
this.packageManager = new PackageManager();
return this.panel = new InstallPanel(settingsView, this.packageManager);
this.panel = new InstallPanel(settingsView, this.packageManager);
});
describe("when the packages button is clicked", function() {
beforeEach(function() {
describe("when the packages button is clicked", () => {
beforeEach(() => {
spyOn(this.panel, 'search');
return this.panel.refs.searchEditor.setText('something');
this.panel.refs.searchEditor.setText('something');
});
return it("performs a search for the contents of the input", function() {
it("performs a search for the contents of the input", () => {
this.panel.refs.searchPackagesButton.click();
expect(this.panel.searchType).toBe('packages');
expect(this.panel.search).toHaveBeenCalledWith('something');
@ -29,17 +25,17 @@ describe('InstallPanel', function() {
this.panel.refs.searchPackagesButton.click();
expect(this.panel.searchType).toBe('packages');
expect(this.panel.search).toHaveBeenCalledWith('something');
return expect(this.panel.search.callCount).toBe(2);
expect(this.panel.search.callCount).toBe(2);
});
});
describe("when the themes button is clicked", function() {
beforeEach(function() {
describe("when the themes button is clicked", () => {
beforeEach(() => {
spyOn(this.panel, 'search');
return this.panel.refs.searchEditor.setText('something');
this.panel.refs.searchEditor.setText('something');
});
return it("performs a search for the contents of the input", function() {
it("performs a search for the contents of the input", () => {
this.panel.refs.searchThemesButton.click();
expect(this.panel.searchType).toBe('themes');
expect(this.panel.search.callCount).toBe(1);
@ -47,17 +43,17 @@ describe('InstallPanel', function() {
this.panel.refs.searchThemesButton.click();
expect(this.panel.searchType).toBe('themes');
return expect(this.panel.search.callCount).toBe(2);
expect(this.panel.search.callCount).toBe(2);
});
});
describe("when the buttons are toggled", function() {
beforeEach(function() {
describe("when the buttons are toggled", () => {
beforeEach(() => {
spyOn(this.panel, 'search');
return this.panel.refs.searchEditor.setText('something');
this.panel.refs.searchEditor.setText('something');
});
return it("performs a search for the contents of the input", function() {
it("performs a search for the contents of the input", () => {
this.panel.refs.searchThemesButton.click();
expect(this.panel.searchType).toBe('themes');
expect(this.panel.search.callCount).toBe(1);
@ -69,11 +65,11 @@ describe('InstallPanel', function() {
this.panel.refs.searchThemesButton.click();
expect(this.panel.searchType).toBe('themes');
return expect(this.panel.search.callCount).toBe(3);
expect(this.panel.search.callCount).toBe(3);
});
});
describe("searching packages", () => it("displays the packages in the order returned", function() {
describe("searching packages", () => it("displays the packages in the order returned", () => {
spyOn(this.panel.client, 'search').andCallFake(() => Promise.resolve([{name: 'not-first'}, {name: 'first'}]));
spyOn(this.panel, 'getPackageCardView').andCallThrough();
@ -81,23 +77,23 @@ describe('InstallPanel', function() {
return this.panel.search('first');
});
return runs(function() {
runs(() => {
expect(this.panel.getPackageCardView.argsForCall[0][0].name).toEqual('not-first');
return expect(this.panel.getPackageCardView.argsForCall[1][0].name).toEqual('first');
expect(this.panel.getPackageCardView.argsForCall[1][0].name).toEqual('first');
});
}));
return describe("searching git packages", function() {
beforeEach(function() {
return spyOn(this.panel, 'showGitInstallPackageCard').andCallThrough();
describe("searching git packages", () => {
beforeEach(() => {
spyOn(this.panel, 'showGitInstallPackageCard').andCallThrough();
});
it("shows a git installation card with git specific info for ssh URLs", function() {
it("shows a git installation card with git specific info for ssh URLs", () => {
const query = 'git@github.com:user/repo.git';
this.panel.performSearchForQuery(query);
const args = this.panel.showGitInstallPackageCard.argsForCall[0][0];
expect(args.name).toEqual(query);
return expect(args.gitUrlInfo).toBeTruthy();
expect(args.gitUrlInfo).toBeTruthy();
});
it("shows a git installation card with git specific info for https URLs", function() {
@ -105,7 +101,7 @@ describe('InstallPanel', function() {
this.panel.performSearchForQuery(query);
const args = this.panel.showGitInstallPackageCard.argsForCall[0][0];
expect(args.name).toEqual(query);
return expect(args.gitUrlInfo).toBeTruthy();
expect(args.gitUrlInfo).toBeTruthy();
});
it("shows a git installation card with git specific info for shortcut URLs", function() {
@ -113,27 +109,27 @@ describe('InstallPanel', function() {
this.panel.performSearchForQuery(query);
const args = this.panel.showGitInstallPackageCard.argsForCall[0][0];
expect(args.name).toEqual(query);
return expect(args.gitUrlInfo).toBeTruthy();
expect(args.gitUrlInfo).toBeTruthy();
});
it("doesn't show a git installation card for normal packages", function() {
const query = 'this-package-is-so-normal';
this.panel.performSearchForQuery(query);
return expect(this.panel.showGitInstallPackageCard).not.toHaveBeenCalled();
expect(this.panel.showGitInstallPackageCard).not.toHaveBeenCalled();
});
return describe("when a package with the same gitUrlInfo property is installed", function() {
describe("when a package with the same gitUrlInfo property is installed", function() {
beforeEach(function() {
this.gitUrlInfo = jasmine.createSpy('gitUrlInfo');
return this.panel.showGitInstallPackageCard({gitUrlInfo: this.gitUrlInfo});
});
return it("replaces the package card with the newly installed pack object", function() {
it("replaces the package card with the newly installed pack object", function() {
const newPack =
{gitUrlInfo: this.gitUrlInfo};
spyOn(this.panel, 'updateGitPackageCard');
this.packageManager.emitter.emit('package-installed', {pack: newPack});
return expect(this.panel.updateGitPackageCard).toHaveBeenCalledWith(newPack);
expect(this.panel.updateGitPackageCard).toHaveBeenCalledWith(newPack);
});
});
});

View File

@ -1,193 +0,0 @@
path = require 'path'
fs = require 'fs-plus'
InstalledPackagesPanel = require '../lib/installed-packages-panel'
PackageManager = require '../lib/package-manager'
PackageCard = require '../lib/package-card'
SettingsView = require '../lib/settings-view'
describe 'InstalledPackagesPanel', ->
describe 'when the packages are loading', ->
it 'filters packages by name once they have loaded', ->
settingsView = new SettingsView
@packageManager = new PackageManager
@installed = JSON.parse fs.readFileSync(path.join(__dirname, 'fixtures', 'installed.json'))
spyOn(@packageManager, 'getOutdated').andReturn new Promise ->
spyOn(@packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(@packageManager, 'getInstalled').andReturn Promise.resolve(@installed)
@panel = new InstalledPackagesPanel(settingsView, @packageManager)
@panel.refs.filterEditor.setText('user-')
window.advanceClock(@panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
waitsFor ->
@packageManager.getInstalled.callCount is 1 and @panel.refs.communityCount.textContent.indexOf('') < 0
runs ->
expect(@panel.refs.communityCount.textContent.trim()).toBe '1/1'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(@panel.refs.coreCount.textContent.trim()).toBe '0/1'
expect(@panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
expect(@panel.refs.devCount.textContent.trim()).toBe '0/1'
expect(@panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
describe 'when the packages have finished loading', ->
beforeEach ->
settingsView = new SettingsView
@packageManager = new PackageManager
@installed = JSON.parse fs.readFileSync(path.join(__dirname, 'fixtures', 'installed.json'))
spyOn(@packageManager, 'getOutdated').andReturn new Promise ->
spyOn(@packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(@packageManager, 'getInstalled').andReturn Promise.resolve(@installed)
@panel = new InstalledPackagesPanel(settingsView, @packageManager)
waitsFor ->
@packageManager.getInstalled.callCount is 1 and @panel.refs.communityCount.textContent.indexOf('') < 0
it 'shows packages', ->
expect(@panel.refs.communityCount.textContent.trim()).toBe '1'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(@panel.refs.coreCount.textContent.trim()).toBe '1'
expect(@panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(@panel.refs.devCount.textContent.trim()).toBe '1'
expect(@panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
it 'filters packages by name', ->
@panel.refs.filterEditor.setText('user-')
window.advanceClock(@panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
expect(@panel.refs.communityCount.textContent.trim()).toBe '1/1'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(@panel.refs.coreCount.textContent.trim()).toBe '0/1'
expect(@panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
expect(@panel.refs.devCount.textContent.trim()).toBe '0/1'
expect(@panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
it 'adds newly installed packages to the list', ->
[installCallback] = []
spyOn(@packageManager, 'runCommand').andCallFake (args, callback) ->
installCallback = callback
onWillThrowError: ->
spyOn(atom.packages, 'activatePackage').andCallFake (name) =>
@installed.user.push {name}
expect(@panel.refs.communityCount.textContent.trim()).toBe '1'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
@packageManager.install({name: 'another-user-package'})
installCallback(0, '', '')
advanceClock InstalledPackagesPanel.loadPackagesDelay()
waits 1
runs ->
expect(@panel.refs.communityCount.textContent.trim()).toBe '2'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 2
it 'removes uninstalled packages from the list', ->
[uninstallCallback] = []
spyOn(@packageManager, 'runCommand').andCallFake (args, callback) ->
uninstallCallback = callback
onWillThrowError: ->
spyOn(@packageManager, 'unload').andCallFake (name) =>
@installed.user = []
expect(@panel.refs.communityCount.textContent.trim()).toBe '1'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
@packageManager.uninstall({name: 'user-package'})
uninstallCallback(0, '', '')
advanceClock InstalledPackagesPanel.loadPackagesDelay()
waits 1
runs ->
expect(@panel.refs.communityCount.textContent.trim()).toBe '0'
expect(@panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
describe 'expanding and collapsing sub-sections', ->
beforeEach ->
settingsView = new SettingsView
@packageManager = new PackageManager
@installed = JSON.parse fs.readFileSync(path.join(__dirname, 'fixtures', 'installed.json'))
spyOn(@packageManager, 'getOutdated').andReturn new Promise ->
spyOn(@packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(@packageManager, 'getInstalled').andReturn Promise.resolve(@installed)
@panel = new InstalledPackagesPanel(settingsView, @packageManager)
waitsFor ->
@packageManager.getInstalled.callCount is 1 and @panel.refs.communityCount.textContent.indexOf('') < 0
it 'collapses and expands a sub-section if its header is clicked', ->
@panel.element.querySelector('.sub-section.installed-packages .sub-section-heading').click()
expect(@panel.element.querySelector('.sub-section.installed-packages')).toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
@panel.element.querySelector('.sub-section.installed-packages .sub-section-heading').click()
expect(@panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
it 'can collapse and expand any of the sub-sections', ->
expect(@panel.element.querySelectorAll('.sub-section-heading.has-items').length).toBe 3
for element in @panel.element.querySelectorAll('.sub-section-heading.has-items')
element.click()
expect(@panel.element.querySelector('.sub-section.installed-packages')).toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.core-packages')).toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.dev-packages')).toHaveClass 'collapsed'
for element in @panel.element.querySelectorAll('.sub-section-heading.has-items')
element.click()
expect(@panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
it 'can collapse sub-sections when filtering', ->
@panel.refs.filterEditor.setText('user-')
window.advanceClock(@panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
hasItems = @panel.element.querySelectorAll('.sub-section-heading.has-items')
expect(hasItems.length).toBe 1
expect(hasItems[0].textContent).toMatch /Community Packages/
describe 'when there are no packages', ->
beforeEach ->
settingsView = new SettingsView
@packageManager = new PackageManager
@installed =
dev: []
user: []
core: []
spyOn(@packageManager, 'getOutdated').andReturn new Promise ->
spyOn(@packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(@packageManager, 'getInstalled').andReturn Promise.resolve(@installed)
@panel = new InstalledPackagesPanel(settingsView, @packageManager)
waitsFor ->
@packageManager.getInstalled.callCount is 1 and @panel.refs.communityCount.textContent.indexOf('') < 0
it 'has a count of zero in all headings', ->
expect(@panel.element.querySelector('.section-heading-count').textContent).toMatch /^0+$/
expect(@panel.element.querySelectorAll('.sub-section .icon-package').length).toBe 4
expect(@panel.element.querySelectorAll('.sub-section .icon-package.has-items').length).toBe 0
it 'can not collapse and expand any of the sub-sections', ->
for element in @panel.element.querySelectorAll('.sub-section .icon-package')
element.click()
expect(@panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(@panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
it 'does not allow collapsing on any section when filtering', ->
@panel.refs.filterEditor.setText('user-')
window.advanceClock(@panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
expect(@panel.element.querySelector('.section-heading-count').textContent).toMatch /^(0\/0)+$/
expect(@panel.element.querySelectorAll('.sub-section .icon-package').length).toBe 4
expect(@panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe 0

View File

@ -1,9 +1,4 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const fs = require('fs-plus');
@ -28,7 +23,7 @@ describe('InstalledPackagesPanel', function() {
return (this.packageManager.getInstalled.callCount === 1) && (this.panel.refs.communityCount.textContent.indexOf('…') < 0);
});
return runs(function() {
runs(function() {
expect(this.panel.refs.communityCount.textContent.trim()).toBe('1/1');
expect(this.panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
@ -36,7 +31,7 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(this.panel.refs.devCount.textContent.trim()).toBe('0/1');
return expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
});
}));
@ -50,7 +45,7 @@ describe('InstalledPackagesPanel', function() {
spyOn(this.packageManager, 'getInstalled').andReturn(Promise.resolve(this.installed));
this.panel = new InstalledPackagesPanel(settingsView, this.packageManager);
return waitsFor(function() {
waitsFor(function() {
return (this.packageManager.getInstalled.callCount === 1) && (this.panel.refs.communityCount.textContent.indexOf('…') < 0);
});
});
@ -63,7 +58,7 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
expect(this.panel.refs.devCount.textContent.trim()).toBe('1');
return expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
});
it('filters packages by name', function() {
@ -76,7 +71,7 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(this.panel.refs.devCount.textContent.trim()).toBe('0/1');
return expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(this.panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
});
it('adds newly installed packages to the list', function() {
@ -97,13 +92,13 @@ describe('InstalledPackagesPanel', function() {
advanceClock(InstalledPackagesPanel.loadPackagesDelay());
waits(1);
return runs(function() {
runs(function() {
expect(this.panel.refs.communityCount.textContent.trim()).toBe('2');
return expect(this.panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(2);
expect(this.panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(2);
});
});
return it('removes uninstalled packages from the list', function() {
it('removes uninstalled packages from the list', function() {
let [uninstallCallback] = [];
spyOn(this.packageManager, 'runCommand').andCallFake(function(args, callback) {
uninstallCallback = callback;
@ -121,9 +116,9 @@ describe('InstalledPackagesPanel', function() {
advanceClock(InstalledPackagesPanel.loadPackagesDelay());
waits(1);
return runs(function() {
runs(function() {
expect(this.panel.refs.communityCount.textContent.trim()).toBe('0');
return expect(this.panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(this.panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
});
});
});
@ -138,7 +133,7 @@ describe('InstalledPackagesPanel', function() {
spyOn(this.packageManager, 'getInstalled').andReturn(Promise.resolve(this.installed));
this.panel = new InstalledPackagesPanel(settingsView, this.packageManager);
return waitsFor(function() {
waitsFor(function() {
return (this.packageManager.getInstalled.callCount === 1) && (this.panel.refs.communityCount.textContent.indexOf('…') < 0);
});
});
@ -151,7 +146,7 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
this.panel.element.querySelector('.sub-section.installed-packages .sub-section-heading').click();
return expect(this.panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(this.panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
});
it('can collapse and expand any of the sub-sections', function() {
@ -172,20 +167,20 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(this.panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass('collapsed');
return expect(this.panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
expect(this.panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
});
return it('can collapse sub-sections when filtering', function() {
it('can collapse sub-sections when filtering', function() {
this.panel.refs.filterEditor.setText('user-');
window.advanceClock(this.panel.refs.filterEditor.getBuffer().stoppedChangingDelay);
const hasItems = this.panel.element.querySelectorAll('.sub-section-heading.has-items');
expect(hasItems.length).toBe(1);
return expect(hasItems[0].textContent).toMatch(/Community Packages/);
expect(hasItems[0].textContent).toMatch(/Community Packages/);
});
});
return describe('when there are no packages', function() {
describe('when there are no packages', function() {
beforeEach(function() {
const settingsView = new SettingsView;
this.packageManager = new PackageManager;
@ -199,7 +194,7 @@ describe('InstalledPackagesPanel', function() {
spyOn(this.packageManager, 'getInstalled').andReturn(Promise.resolve(this.installed));
this.panel = new InstalledPackagesPanel(settingsView, this.packageManager);
return waitsFor(function() {
waitsFor(function() {
return (this.packageManager.getInstalled.callCount === 1) && (this.panel.refs.communityCount.textContent.indexOf('…') < 0);
});
});
@ -207,7 +202,7 @@ describe('InstalledPackagesPanel', function() {
it('has a count of zero in all headings', function() {
expect(this.panel.element.querySelector('.section-heading-count').textContent).toMatch(/^0+$/);
expect(this.panel.element.querySelectorAll('.sub-section .icon-package').length).toBe(4);
return expect(this.panel.element.querySelectorAll('.sub-section .icon-package.has-items').length).toBe(0);
expect(this.panel.element.querySelectorAll('.sub-section .icon-package.has-items').length).toBe(0);
});
it('can not collapse and expand any of the sub-sections', function() {
@ -218,16 +213,16 @@ describe('InstalledPackagesPanel', function() {
expect(this.panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(this.panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass('collapsed');
return expect(this.panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
expect(this.panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
});
return it('does not allow collapsing on any section when filtering', function() {
it('does not allow collapsing on any section when filtering', function() {
this.panel.refs.filterEditor.setText('user-');
window.advanceClock(this.panel.refs.filterEditor.getBuffer().stoppedChangingDelay);
expect(this.panel.element.querySelector('.section-heading-count').textContent).toMatch(/^(0\/0)+$/);
expect(this.panel.element.querySelectorAll('.sub-section .icon-package').length).toBe(4);
return expect(this.panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
expect(this.panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
});
});
});

View File

@ -1,132 +0,0 @@
path = require 'path'
KeybindingsPanel = require '../lib/keybindings-panel'
describe "KeybindingsPanel", ->
[keyBindings, panel] = []
beforeEach ->
expect(atom.keymaps).toBeDefined()
keySource = "#{atom.getLoadSettings().resourcePath}#{path.sep}keymaps"
keyBindings = [
{
source: keySource
keystrokes: 'ctrl-a'
command: 'core:select-all'
selector: '.editor, .platform-test'
}
{
source: keySource
keystrokes: 'ctrl-u'
command: 'core:undo'
selector: ".platform-test"
}
{
source: keySource
keystrokes: 'ctrl-u'
command: 'core:undo'
selector: ".platform-a, .platform-b"
}
{
source: keySource
keystrokes: 'shift-\\ \\'
command: 'core:undo'
selector: '.editor'
}
{
source: keySource
keystrokes: 'ctrl-z\''
command: 'core:toggle'
selector: 'atom-text-editor[data-grammar~=\'css\']'
}
]
spyOn(atom.keymaps, 'getKeyBindings').andReturn(keyBindings)
panel = new KeybindingsPanel
it "loads and displays core key bindings", ->
expect(panel.refs.keybindingRows.children.length).toBe 3
row = panel.refs.keybindingRows.children[0]
expect(row.querySelector('.keystroke').textContent).toBe 'ctrl-a'
expect(row.querySelector('.command').textContent).toBe 'core:select-all'
expect(row.querySelector('.source').textContent).toBe 'Core'
expect(row.querySelector('.selector').textContent).toBe '.editor, .platform-test'
describe "when a keybinding is copied", ->
describe "when the keybinding file ends in .cson", ->
it "writes a CSON snippet to the clipboard", ->
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn 'keymap.cson'
panel.element.querySelector('.copy-icon').click()
expect(atom.clipboard.read()).toBe """
'.editor, .platform-test':
'ctrl-a': 'core:select-all'
"""
describe "when the keybinding file ends in .json", ->
it "writes a JSON snippet to the clipboard", ->
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn 'keymap.json'
panel.element.querySelector('.copy-icon').click()
expect(atom.clipboard.read()).toBe """
".editor, .platform-test": {
"ctrl-a": "core:select-all"
}
"""
describe "when the keybinding contains special characters", ->
it "escapes the backslashes before copying", ->
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn 'keymap.cson'
panel.element.querySelectorAll('.copy-icon')[2].click()
expect(atom.clipboard.read()).toBe """
'.editor':
'shift-\\\\ \\\\': 'core:undo'
"""
it "escapes the single quotes before copying", ->
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn 'keymap.cson'
panel.element.querySelectorAll('.copy-icon')[1].click()
expect(atom.clipboard.read()).toBe """
'atom-text-editor[data-grammar~=\\'css\\']':
'ctrl-z\\'': 'core:toggle'
"""
describe "when the key bindings change", ->
it "reloads the key bindings", ->
keyBindings.push
source: atom.keymaps.getUserKeymapPath(), keystrokes: 'ctrl-b', command: 'core:undo', selector: '.editor'
atom.keymaps.emitter.emit 'did-reload-keymap'
waitsFor "the new keybinding to show up in the keybinding panel", ->
panel.refs.keybindingRows.children.length is 4
runs ->
row = panel.refs.keybindingRows.children[1]
expect(row.querySelector('.keystroke').textContent).toBe 'ctrl-b'
expect(row.querySelector('.command').textContent).toBe 'core:undo'
expect(row.querySelector('.source').textContent).toBe 'User'
expect(row.querySelector('.selector').textContent).toBe '.editor'
describe "when searching key bindings", ->
it "find case-insensitive results", ->
keyBindings.push
source: "#{atom.getLoadSettings().resourcePath}#{path.sep}keymaps", keystrokes: 'F11', command: 'window:toggle-full-screen', selector: 'body'
atom.keymaps.emitter.emit 'did-reload-keymap'
panel.filterKeyBindings keyBindings, 'f11'
expect(panel.refs.keybindingRows.children.length).toBe 1
row = panel.refs.keybindingRows.children[0]
expect(row.querySelector('.keystroke').textContent).toBe 'F11'
expect(row.querySelector('.command').textContent).toBe 'window:toggle-full-screen'
expect(row.querySelector('.source').textContent).toBe 'Core'
expect(row.querySelector('.selector').textContent).toBe 'body'
it "perform a fuzzy match for each keyword", ->
panel.filterKeyBindings keyBindings, 'core ctrl-a'
expect(panel.refs.keybindingRows.children.length).toBe 1
row = panel.refs.keybindingRows.children[0]
expect(row.querySelector('.keystroke').textContent).toBe 'ctrl-a'
expect(row.querySelector('.command').textContent).toBe 'core:select-all'
expect(row.querySelector('.source').textContent).toBe 'Core'
expect(row.querySelector('.selector').textContent).toBe '.editor, .platform-test'

View File

@ -1,8 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const KeybindingsPanel = require('../lib/keybindings-panel');
@ -55,14 +51,14 @@ describe("KeybindingsPanel", function() {
expect(row.querySelector('.keystroke').textContent).toBe('ctrl-a');
expect(row.querySelector('.command').textContent).toBe('core:select-all');
expect(row.querySelector('.source').textContent).toBe('Core');
return expect(row.querySelector('.selector').textContent).toBe('.editor, .platform-test');
expect(row.querySelector('.selector').textContent).toBe('.editor, .platform-test');
});
describe("when a keybinding is copied", function() {
describe("when the keybinding file ends in .cson", () => it("writes a CSON snippet to the clipboard", function() {
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn('keymap.cson');
panel.element.querySelector('.copy-icon').click();
return expect(atom.clipboard.read()).toBe(`\
expect(atom.clipboard.read()).toBe(`\
'.editor, .platform-test':
'ctrl-a': 'core:select-all'\
`
@ -72,7 +68,7 @@ describe("KeybindingsPanel", function() {
describe("when the keybinding file ends in .json", () => it("writes a JSON snippet to the clipboard", function() {
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn('keymap.json');
panel.element.querySelector('.copy-icon').click();
return expect(atom.clipboard.read()).toBe(`\
expect(atom.clipboard.read()).toBe(`\
".editor, .platform-test": {
"ctrl-a": "core:select-all"
}\
@ -80,21 +76,21 @@ describe("KeybindingsPanel", function() {
);
}));
return describe("when the keybinding contains special characters", function() {
describe("when the keybinding contains special characters", function() {
it("escapes the backslashes before copying", function() {
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn('keymap.cson');
panel.element.querySelectorAll('.copy-icon')[2].click();
return expect(atom.clipboard.read()).toBe(`\
expect(atom.clipboard.read()).toBe(`\
'.editor':
'shift-\\\\ \\\\': 'core:undo'\
`
);
});
return it("escapes the single quotes before copying", function() {
it("escapes the single quotes before copying", function() {
spyOn(atom.keymaps, 'getUserKeymapPath').andReturn('keymap.cson');
panel.element.querySelectorAll('.copy-icon')[1].click();
return expect(atom.clipboard.read()).toBe(`\
expect(atom.clipboard.read()).toBe(`\
'atom-text-editor[data-grammar~=\\'css\\']':
'ctrl-z\\'': 'core:toggle'\
`
@ -110,16 +106,16 @@ describe("KeybindingsPanel", function() {
waitsFor("the new keybinding to show up in the keybinding panel", () => panel.refs.keybindingRows.children.length === 4);
return runs(function() {
runs(function() {
const row = panel.refs.keybindingRows.children[1];
expect(row.querySelector('.keystroke').textContent).toBe('ctrl-b');
expect(row.querySelector('.command').textContent).toBe('core:undo');
expect(row.querySelector('.source').textContent).toBe('User');
return expect(row.querySelector('.selector').textContent).toBe('.editor');
expect(row.querySelector('.selector').textContent).toBe('.editor');
});
}));
return describe("when searching key bindings", function() {
describe("when searching key bindings", function() {
it("find case-insensitive results", function() {
keyBindings.push({
source: `${atom.getLoadSettings().resourcePath}${path.sep}keymaps`, keystrokes: 'F11', command: 'window:toggle-full-screen', selector: 'body'});
@ -133,10 +129,10 @@ describe("KeybindingsPanel", function() {
expect(row.querySelector('.keystroke').textContent).toBe('F11');
expect(row.querySelector('.command').textContent).toBe('window:toggle-full-screen');
expect(row.querySelector('.source').textContent).toBe('Core');
return expect(row.querySelector('.selector').textContent).toBe('body');
expect(row.querySelector('.selector').textContent).toBe('body');
});
return it("perform a fuzzy match for each keyword", function() {
it("perform a fuzzy match for each keyword", function() {
panel.filterKeyBindings(keyBindings, 'core ctrl-a');
expect(panel.refs.keybindingRows.children.length).toBe(1);
@ -145,7 +141,7 @@ describe("KeybindingsPanel", function() {
expect(row.querySelector('.keystroke').textContent).toBe('ctrl-a');
expect(row.querySelector('.command').textContent).toBe('core:select-all');
expect(row.querySelector('.source').textContent).toBe('Core');
return expect(row.querySelector('.selector').textContent).toBe('.editor, .platform-test');
expect(row.querySelector('.selector').textContent).toBe('.editor, .platform-test');
});
});
});

View File

@ -1,35 +0,0 @@
List = require '../lib/list'
describe 'List', ->
list = null
beforeEach ->
list = new List('name')
it 'emits add and remove events when setting items', ->
addHandler = jasmine.createSpy()
removeHandler = jasmine.createSpy()
list.onDidAddItem(addHandler)
list.onDidRemoveItem(removeHandler)
items = [{name: 'one', text: 'a'}, {name: 'two', text: 'b'}]
list.setItems(items)
expect(addHandler.callCount).toBe 2
expect(removeHandler.callCount).toBe 0
addHandler.reset()
removeHandler.reset()
items = [{name: 'three', text: 'c'}, {name: 'two', text: 'b'}]
list.setItems(items)
expect(addHandler.callCount).toBe 1
expect(removeHandler.callCount).toBe 1
expect(addHandler.mostRecentCall.args[0]).toEqual {name: 'three', text: 'c'}
expect(removeHandler.mostRecentCall.args[0]).toEqual {name: 'one', text: 'a'}
expect(list.getItems()).toEqual items
addHandler.reset()
removeHandler.reset()
items.push {name: 'four'}
list.setItems(items)
expect(addHandler.callCount).toBe 1

View File

@ -1,16 +1,12 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const List = require('../lib/list');
describe('List', function() {
describe('List', () => {
let list = null;
beforeEach(() => list = new List('name'));
return it('emits add and remove events when setting items', function() {
it('emits add and remove events when setting items', () => {
const addHandler = jasmine.createSpy();
const removeHandler = jasmine.createSpy();
list.onDidAddItem(addHandler);
@ -36,6 +32,6 @@ describe('List', function() {
removeHandler.reset();
items.push({name: 'four'});
list.setItems(items);
return expect(addHandler.callCount).toBe(1);
expect(addHandler.callCount).toBe(1);
});
});

View File

@ -1,67 +0,0 @@
List = require '../lib/list'
ListView = require '../lib/list-view'
describe 'ListView', ->
[list, view, container] = []
beforeEach ->
list = new List('name')
container = document.createElement('div')
view = new ListView list, container, (item) ->
element = document.createElement('div')
element.classList.add(item.name)
element.textContent = "#{item.name}|#{item.text}"
{element, destroy: -> element.remove()}
it 'updates the list when the items are changed', ->
expect(container.children.length).toBe 0
items = [{name: 'one', text: 'a'}, {name: 'two', text: 'b'}]
list.setItems(items)
expect(container.children.length).toBe 2
expect(container.querySelector('.one').textContent).toBe 'one|a'
expect(container.querySelector('.two').textContent).toBe 'two|b'
items = [{name: 'three', text: 'c'}, {name: 'two', text: 'b'}]
list.setItems(items)
expect(container.children.length).toBe 2
expect(container.querySelector('.one')).not.toExist()
expect(container.querySelector('.two').textContent).toBe 'two|b'
expect(container.querySelector('.three').textContent).toBe 'three|c'
it 'filters views', ->
items = [
{name: 'one', text: '', filterText: 'x'},
{name: 'two', text: '', filterText: 'y'}
{name: 'three', text: '', filterText: 'x'}
{name: 'four', text: '', filterText: 'z'}
]
list.setItems(items)
views = view.filterViews (item) -> item.filterText is 'x'
expect(views).toHaveLength 2
expect(views[0].element.textContent).toBe 'one|'
expect(views[1].element.textContent).toBe 'three|'
it 'filters views after an update', ->
items = [
{name: 'one', text: '', filterText: 'x'},
{name: 'two', text: '', filterText: 'y'}
{name: 'three', text: '', filterText: 'x'}
{name: 'four', text: '', filterText: 'z'}
]
list.setItems(items)
items = [
{name: 'one', text: '', filterText: 'x'},
{name: 'two', text: '', filterText: 'y'}
{name: 'three', text: '', filterText: 'x'}
{name: 'four', text: '', filterText: 'z'}
]
list.setItems(items)
views = view.filterViews (item) -> item.filterText is 'x'
expect(views).toHaveLength 2
expect(views[0].element.textContent).toBe 'one|'
expect(views[1].element.textContent).toBe 'three|'

View File

@ -1,15 +1,11 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const List = require('../lib/list');
const ListView = require('../lib/list-view');
describe('ListView', function() {
describe('ListView', () => {
let [list, view, container] = [];
beforeEach(function() {
beforeEach(() => {
list = new List('name');
container = document.createElement('div');
return view = new ListView(list, container, function(item) {
@ -19,7 +15,7 @@ describe('ListView', function() {
return {element, destroy() { return element.remove(); }};
});});
it('updates the list when the items are changed', function() {
it('updates the list when the items are changed', () => {
expect(container.children.length).toBe(0);
let items = [{name: 'one', text: 'a'}, {name: 'two', text: 'b'}];
@ -33,10 +29,10 @@ describe('ListView', function() {
expect(container.children.length).toBe(2);
expect(container.querySelector('.one')).not.toExist();
expect(container.querySelector('.two').textContent).toBe('two|b');
return expect(container.querySelector('.three').textContent).toBe('three|c');
expect(container.querySelector('.three').textContent).toBe('three|c');
});
it('filters views', function() {
it('filters views', () => {
const items = [
{name: 'one', text: '', filterText: 'x'},
{name: 'two', text: '', filterText: 'y'},
@ -49,10 +45,10 @@ describe('ListView', function() {
expect(views).toHaveLength(2);
expect(views[0].element.textContent).toBe('one|');
return expect(views[1].element.textContent).toBe('three|');
expect(views[1].element.textContent).toBe('three|');
});
return it('filters views after an update', function() {
it('filters views after an update', () => {
let items = [
{name: 'one', text: '', filterText: 'x'},
{name: 'two', text: '', filterText: 'y'},
@ -72,6 +68,6 @@ describe('ListView', function() {
expect(views).toHaveLength(2);
expect(views[0].element.textContent).toBe('one|');
return expect(views[1].element.textContent).toBe('three|');
expect(views[1].element.textContent).toBe('three|');
});
});

View File

@ -1,384 +0,0 @@
path = require 'path'
PackageCard = require '../lib/package-card'
PackageManager = require '../lib/package-manager'
SettingsView = require '../lib/settings-view'
describe "PackageCard", ->
setPackageStatusSpies = (opts) ->
spyOn(PackageCard.prototype, 'isInstalled').andReturn(opts.installed)
spyOn(PackageCard.prototype, 'isDisabled').andReturn(opts.disabled)
spyOn(PackageCard.prototype, 'hasSettings').andReturn(opts.hasSettings)
[card, packageManager] = []
beforeEach ->
packageManager = new PackageManager()
spyOn(packageManager, 'runCommand')
it "doesn't show the disable control for a theme", ->
setPackageStatusSpies {installed: true, disabled: false}
card = new PackageCard({theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.enablementButton).not.toBeVisible()
it "doesn't show the status indicator for a theme", ->
setPackageStatusSpies {installed: true, disabled: false}
card = new PackageCard {theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.statusIndicatorButton).not.toBeVisible()
it "doesn't show the settings button for a theme", ->
setPackageStatusSpies {installed: true, disabled: false}
card = new PackageCard {theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.settingsButton).not.toBeVisible()
it "doesn't show the settings button on the settings view", ->
setPackageStatusSpies {installed: true, disabled: false, hasSettings: true}
card = new PackageCard {name: 'test-package'}, new SettingsView(), packageManager, {onSettingsView: true}
jasmine.attachToDOM(card.element)
expect(card.refs.settingsButton).not.toBeVisible()
it "removes the settings button if a package has no settings", ->
setPackageStatusSpies {installed: true, disabled: false, hasSettings: false}
card = new PackageCard {name: 'test-package'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.settingsButton).not.toBeVisible()
it "removes the uninstall button if a package has is a bundled package", ->
setPackageStatusSpies {installed: true, disabled: false, hasSettings: true}
card = new PackageCard {name: 'find-and-replace'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.uninstallButton).not.toBeVisible()
it "displays the new version in the update button", ->
setPackageStatusSpies {installed: true, disabled: false, hasSettings: true}
card = new PackageCard {name: 'find-and-replace', version: '1.0.0', latestVersion: '1.2.0'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.updateButton).toBeVisible()
expect(card.refs.updateButton.textContent).toContain 'Update to 1.2.0'
it "displays the new version in the update button when the package is disabled", ->
setPackageStatusSpies {installed: true, disabled: true, hasSettings: true}
card = new PackageCard {name: 'find-and-replace', version: '1.0.0', latestVersion: '1.2.0'}, new SettingsView(), packageManager
jasmine.attachToDOM(card.element)
expect(card.refs.updateButton).toBeVisible()
expect(card.refs.updateButton.textContent).toContain 'Update to 1.2.0'
it "shows the author details", ->
authorName = "authorName"
pack =
name: 'some-package'
version: '0.1.0'
repository: "https://github.com/#{authorName}/some-package"
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.loginLink.textContent).toBe(authorName)
describe "when the package is not installed", ->
it "shows the settings, uninstall, and disable buttons", ->
pack =
name: 'some-package'
version: '0.1.0'
repository: 'http://github.com/omgwow/some-package'
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.installButtonGroup).toBeVisible()
expect(card.refs.updateButtonGroup).not.toBeVisible()
expect(card.refs.packageActionButtonGroup).not.toBeVisible()
it "can be installed if currently not installed", ->
setPackageStatusSpies {installed: false, disabled: false}
spyOn(packageManager, 'install')
card = new PackageCard {name: 'test-package'}, new SettingsView(), packageManager
expect(card.refs.installButton.style.display).not.toBe('none')
expect(card.refs.uninstallButton.style.display).toBe('none')
card.refs.installButton.click()
expect(packageManager.install).toHaveBeenCalled()
it "can be installed if currently not installed and package latest release engine match atom version", ->
spyOn(packageManager, 'install')
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake (packageName, callback) ->
pack =
name: packageName
version: '0.1.0'
engines:
atom: '>0.50.0'
callback(null, pack)
setPackageStatusSpies {installed: false, disabled: false}
card = new PackageCard {
name: 'test-package'
version: '0.1.0'
engines:
atom: '>0.50.0'
}, new SettingsView(), packageManager
# In that case there's no need to make a request to get all the versions
expect(packageManager.loadCompatiblePackageVersion).not.toHaveBeenCalled()
expect(card.refs.installButton.style.display).not.toBe('none')
expect(card.refs.uninstallButton.style.display).toBe('none')
card.refs.installButton.click()
expect(packageManager.install).toHaveBeenCalled()
expect(packageManager.install.mostRecentCall.args[0]).toEqual({
name: 'test-package'
version: '0.1.0'
engines:
atom: '>0.50.0'
})
it "can be installed with a previous version whose engine match the current atom version", ->
spyOn(packageManager, 'install')
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake (packageName, callback) ->
pack =
name: packageName
version: '0.0.1'
engines:
atom: '>0.50.0'
callback(null, pack)
setPackageStatusSpies {installed: false, disabled: false}
card = new PackageCard {
name: 'test-package'
version: '0.1.0'
engines:
atom: '>99.0.0'
}, new SettingsView(), packageManager
expect(card.refs.installButton.style.display).not.toBe('none')
expect(card.refs.uninstallButton.style.display).toBe('none')
expect(card.refs.versionValue.textContent).toBe('0.0.1')
expect(card.refs.versionValue).toHaveClass('text-warning')
expect(card.refs.packageMessage).toHaveClass('text-warning')
card.refs.installButton.click()
expect(packageManager.install).toHaveBeenCalled()
expect(packageManager.install.mostRecentCall.args[0]).toEqual({
name: 'test-package'
version: '0.0.1'
engines:
atom: '>0.50.0'
})
it "can't be installed if there is no version compatible with the current atom version", ->
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake (packageName, callback) ->
pack =
name: packageName
callback(null, pack)
setPackageStatusSpies {installed: false, disabled: false}
pack =
name: 'test-package'
engines:
atom: '>=99.0.0'
card = new PackageCard(pack , new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.installButtonGroup).not.toBeVisible()
expect(card.refs.packageActionButtonGroup).not.toBeVisible()
expect(card.refs.versionValue).toHaveClass('text-error')
expect(card.refs.packageMessage).toHaveClass('text-error')
describe "when the package is installed", ->
beforeEach ->
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-config'))
waitsFor ->
atom.packages.isPackageLoaded('package-with-config') is true
it "can be disabled if installed", ->
setPackageStatusSpies {installed: true, disabled: false}
spyOn(atom.packages, 'disablePackage').andReturn(true)
card = new PackageCard {name: 'test-package'}, new SettingsView(), packageManager
expect(card.refs.enablementButton.querySelector('.disable-text').textContent).toBe('Disable')
card.refs.enablementButton.click()
expect(atom.packages.disablePackage).toHaveBeenCalled()
it "can be updated", ->
pack = atom.packages.getLoadedPackage('package-with-config')
pack.latestVersion = '1.1.0'
packageUpdated = false
packageManager.on 'package-updated', -> packageUpdated = true
packageManager.runCommand.andCallFake (args, callback) ->
callback(0, '', '')
onWillThrowError: ->
originalLoadPackage = atom.packages.loadPackage
spyOn(atom.packages, 'loadPackage').andCallFake ->
originalLoadPackage.call(atom.packages, path.join(__dirname, 'fixtures', 'package-with-config'))
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.updateButton).toBeVisible()
card.update()
waitsFor ->
packageUpdated
runs ->
expect(card.refs.updateButton).not.toBeVisible()
it 'keeps the update button visible if the update failed', ->
pack = atom.packages.getLoadedPackage('package-with-config')
pack.latestVersion = '1.1.0'
updateFailed = false
packageManager.on 'package-update-failed', -> updateFailed = true
packageManager.runCommand.andCallFake (args, callback) ->
callback(1, '', '')
onWillThrowError: ->
originalLoadPackage = atom.packages.loadPackage
spyOn(atom.packages, 'loadPackage').andCallFake ->
originalLoadPackage.call(atom.packages, path.join(__dirname, 'fixtures', 'package-with-config'))
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.updateButton).toBeVisible()
card.update()
waitsFor ->
updateFailed
runs ->
expect(card.refs.updateButton).toBeVisible()
it 'does not error when attempting to update without any update available', ->
# While this cannot be done through the package card UI,
# updates can still be triggered through the Updates panel's Update All button
# https://github.com/atom/settings-view/issues/879
pack = atom.packages.getLoadedPackage('package-with-config')
originalLoadPackage = atom.packages.loadPackage
spyOn(atom.packages, 'loadPackage').andCallFake ->
originalLoadPackage.call(atom.packages, path.join(__dirname, 'fixtures', 'package-with-config'))
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.updateButton).not.toBeVisible()
waitsForPromise -> card.update()
runs ->
expect(card.refs.updateButton).not.toBeVisible()
it "will stay disabled after an update", ->
pack = atom.packages.getLoadedPackage('package-with-config')
pack.latestVersion = '1.1.0'
packageUpdated = false
packageManager.on 'package-updated', -> packageUpdated = true
packageManager.runCommand.andCallFake (args, callback) ->
callback(0, '', '')
onWillThrowError: ->
originalLoadPackage = atom.packages.loadPackage
spyOn(atom.packages, 'loadPackage').andCallFake ->
originalLoadPackage.call(atom.packages, path.join(__dirname, 'fixtures', 'package-with-config'))
pack.disable()
card = new PackageCard(pack, new SettingsView(), packageManager)
expect(atom.packages.isPackageDisabled('package-with-config')).toBe true
card.update()
waitsFor ->
packageUpdated
runs ->
expect(atom.packages.isPackageDisabled('package-with-config')).toBe true
it "is uninstalled when the uninstallButton is clicked", ->
setPackageStatusSpies {installed: true, disabled: false}
[uninstallCallback] = []
packageManager.runCommand.andCallFake (args, callback) ->
if args[0] is 'uninstall'
uninstallCallback = callback
onWillThrowError: ->
spyOn(packageManager, 'install').andCallThrough()
spyOn(packageManager, 'uninstall').andCallThrough()
pack = atom.packages.getLoadedPackage('package-with-config')
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.uninstallButton).toBeVisible()
expect(card.refs.enablementButton).toBeVisible()
card.refs.uninstallButton.click()
expect(card.refs.uninstallButton.disabled).toBe true
expect(card.refs.enablementButton.disabled).toBe true
expect(card.refs.uninstallButton).toHaveClass('is-uninstalling')
expect(packageManager.uninstall).toHaveBeenCalled()
expect(packageManager.uninstall.mostRecentCall.args[0].name).toEqual('package-with-config')
jasmine.unspy(PackageCard::, 'isInstalled')
spyOn(PackageCard.prototype, 'isInstalled').andReturn false
uninstallCallback(0, '', '')
waits 1
runs ->
expect(card.refs.uninstallButton.disabled).toBe false
expect(card.refs.uninstallButton).not.toHaveClass('is-uninstalling')
expect(card.refs.installButtonGroup).toBeVisible()
expect(card.refs.updateButtonGroup).not.toBeVisible()
expect(card.refs.packageActionButtonGroup).not.toBeVisible()
it "shows the settings, uninstall, and enable buttons when disabled", ->
atom.config.set('package-with-config.setting', 'something')
pack = atom.packages.getLoadedPackage('package-with-config')
spyOn(atom.packages, 'isPackageDisabled').andReturn(true)
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.updateButtonGroup).not.toBeVisible()
expect(card.refs.installButtonGroup).not.toBeVisible()
expect(card.refs.settingsButton).toBeVisible()
expect(card.refs.uninstallButton).toBeVisible()
expect(card.refs.enablementButton).toBeVisible()
expect(card.refs.enablementButton.textContent).toBe 'Enable'
it "shows the settings, uninstall, and disable buttons", ->
atom.config.set('package-with-config.setting', 'something')
pack = atom.packages.getLoadedPackage('package-with-config')
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.updateButtonGroup).not.toBeVisible()
expect(card.refs.installButtonGroup).not.toBeVisible()
expect(card.refs.settingsButton).toBeVisible()
expect(card.refs.uninstallButton).toBeVisible()
expect(card.refs.enablementButton).toBeVisible()
expect(card.refs.enablementButton.textContent).toBe 'Disable'
it "does not show the settings button when there are no settings", ->
pack = atom.packages.getLoadedPackage('package-with-config')
spyOn(PackageCard::, 'hasSettings').andReturn(false)
card = new PackageCard(pack, new SettingsView(), packageManager)
jasmine.attachToDOM(card.element)
expect(card.refs.settingsButton).not.toBeVisible()
expect(card.refs.uninstallButton).toBeVisible()
expect(card.refs.enablementButton).toBeVisible()
expect(card.refs.enablementButton.textContent).toBe 'Disable'

View File

@ -1,8 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const PackageCard = require('../lib/package-card');
const PackageManager = require('../lib/package-manager');
@ -12,56 +8,56 @@ describe("PackageCard", function() {
const setPackageStatusSpies = function(opts) {
spyOn(PackageCard.prototype, 'isInstalled').andReturn(opts.installed);
spyOn(PackageCard.prototype, 'isDisabled').andReturn(opts.disabled);
return spyOn(PackageCard.prototype, 'hasSettings').andReturn(opts.hasSettings);
spyOn(PackageCard.prototype, 'hasSettings').andReturn(opts.hasSettings);
};
let [card, packageManager] = [];
beforeEach(function() {
packageManager = new PackageManager();
return spyOn(packageManager, 'runCommand');
spyOn(packageManager, 'runCommand');
});
it("doesn't show the disable control for a theme", function() {
setPackageStatusSpies({installed: true, disabled: false});
card = new PackageCard({theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
return expect(card.refs.enablementButton).not.toBeVisible();
expect(card.refs.enablementButton).not.toBeVisible();
});
it("doesn't show the status indicator for a theme", function() {
setPackageStatusSpies({installed: true, disabled: false});
card = new PackageCard({theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
return expect(card.refs.statusIndicatorButton).not.toBeVisible();
expect(card.refs.statusIndicatorButton).not.toBeVisible();
});
it("doesn't show the settings button for a theme", function() {
setPackageStatusSpies({installed: true, disabled: false});
card = new PackageCard({theme: 'syntax', name: 'test-theme'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
return expect(card.refs.settingsButton).not.toBeVisible();
expect(card.refs.settingsButton).not.toBeVisible();
});
it("doesn't show the settings button on the settings view", function() {
setPackageStatusSpies({installed: true, disabled: false, hasSettings: true});
card = new PackageCard({name: 'test-package'}, new SettingsView(), packageManager, {onSettingsView: true});
jasmine.attachToDOM(card.element);
return expect(card.refs.settingsButton).not.toBeVisible();
expect(card.refs.settingsButton).not.toBeVisible();
});
it("removes the settings button if a package has no settings", function() {
setPackageStatusSpies({installed: true, disabled: false, hasSettings: false});
card = new PackageCard({name: 'test-package'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
return expect(card.refs.settingsButton).not.toBeVisible();
expect(card.refs.settingsButton).not.toBeVisible();
});
it("removes the uninstall button if a package has is a bundled package", function() {
setPackageStatusSpies({installed: true, disabled: false, hasSettings: true});
card = new PackageCard({name: 'find-and-replace'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
return expect(card.refs.uninstallButton).not.toBeVisible();
expect(card.refs.uninstallButton).not.toBeVisible();
});
it("displays the new version in the update button", function() {
@ -69,7 +65,7 @@ describe("PackageCard", function() {
card = new PackageCard({name: 'find-and-replace', version: '1.0.0', latestVersion: '1.2.0'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
expect(card.refs.updateButton).toBeVisible();
return expect(card.refs.updateButton.textContent).toContain('Update to 1.2.0');
expect(card.refs.updateButton.textContent).toContain('Update to 1.2.0');
});
it("displays the new version in the update button when the package is disabled", function() {
@ -77,7 +73,7 @@ describe("PackageCard", function() {
card = new PackageCard({name: 'find-and-replace', version: '1.0.0', latestVersion: '1.2.0'}, new SettingsView(), packageManager);
jasmine.attachToDOM(card.element);
expect(card.refs.updateButton).toBeVisible();
return expect(card.refs.updateButton.textContent).toContain('Update to 1.2.0');
expect(card.refs.updateButton.textContent).toContain('Update to 1.2.0');
});
it("shows the author details", function() {
@ -91,7 +87,7 @@ describe("PackageCard", function() {
jasmine.attachToDOM(card.element);
return expect(card.refs.loginLink.textContent).toBe(authorName);
expect(card.refs.loginLink.textContent).toBe(authorName);
});
describe("when the package is not installed", function() {
@ -107,7 +103,7 @@ describe("PackageCard", function() {
expect(card.refs.installButtonGroup).toBeVisible();
expect(card.refs.updateButtonGroup).not.toBeVisible();
return expect(card.refs.packageActionButtonGroup).not.toBeVisible();
expect(card.refs.packageActionButtonGroup).not.toBeVisible();
});
it("can be installed if currently not installed", function() {
@ -118,7 +114,7 @@ describe("PackageCard", function() {
expect(card.refs.installButton.style.display).not.toBe('none');
expect(card.refs.uninstallButton.style.display).toBe('none');
card.refs.installButton.click();
return expect(packageManager.install).toHaveBeenCalled();
expect(packageManager.install).toHaveBeenCalled();
});
it("can be installed if currently not installed and package latest release engine match atom version", function() {
@ -152,7 +148,7 @@ describe("PackageCard", function() {
expect(card.refs.uninstallButton.style.display).toBe('none');
card.refs.installButton.click();
expect(packageManager.install).toHaveBeenCalled();
return expect(packageManager.install.mostRecentCall.args[0]).toEqual({
expect(packageManager.install.mostRecentCall.args[0]).toEqual({
name: 'test-package',
version: '0.1.0',
engines: {
@ -192,7 +188,7 @@ describe("PackageCard", function() {
expect(card.refs.packageMessage).toHaveClass('text-warning');
card.refs.installButton.click();
expect(packageManager.install).toHaveBeenCalled();
return expect(packageManager.install.mostRecentCall.args[0]).toEqual({
expect(packageManager.install.mostRecentCall.args[0]).toEqual({
name: 'test-package',
version: '0.0.1',
engines: {
@ -201,7 +197,7 @@ describe("PackageCard", function() {
});
});
return it("can't be installed if there is no version compatible with the current atom version", function() {
it("can't be installed if there is no version compatible with the current atom version", function() {
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake(function(packageName, callback) {
const pack =
{name: packageName};
@ -223,11 +219,11 @@ describe("PackageCard", function() {
expect(card.refs.installButtonGroup).not.toBeVisible();
expect(card.refs.packageActionButtonGroup).not.toBeVisible();
expect(card.refs.versionValue).toHaveClass('text-error');
return expect(card.refs.packageMessage).toHaveClass('text-error');
expect(card.refs.packageMessage).toHaveClass('text-error');
});
});
return describe("when the package is installed", function() {
describe("when the package is installed", function() {
beforeEach(function() {
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-config'));
return waitsFor(() => atom.packages.isPackageLoaded('package-with-config') === true);
@ -240,7 +236,7 @@ describe("PackageCard", function() {
card = new PackageCard({name: 'test-package'}, new SettingsView(), packageManager);
expect(card.refs.enablementButton.querySelector('.disable-text').textContent).toBe('Disable');
card.refs.enablementButton.click();
return expect(atom.packages.disablePackage).toHaveBeenCalled();
expect(atom.packages.disablePackage).toHaveBeenCalled();
});
it("can be updated", function() {
@ -265,7 +261,7 @@ describe("PackageCard", function() {
waitsFor(() => packageUpdated);
return runs(() => expect(card.refs.updateButton).not.toBeVisible());
runs(() => expect(card.refs.updateButton).not.toBeVisible());
});
it('keeps the update button visible if the update failed', function() {
@ -290,7 +286,7 @@ describe("PackageCard", function() {
waitsFor(() => updateFailed);
return runs(() => expect(card.refs.updateButton).toBeVisible());
runs(() => expect(card.refs.updateButton).toBeVisible());
});
it('does not error when attempting to update without any update available', function() {
@ -309,7 +305,7 @@ describe("PackageCard", function() {
waitsForPromise(() => card.update());
return runs(() => expect(card.refs.updateButton).not.toBeVisible());
runs(() => expect(card.refs.updateButton).not.toBeVisible());
});
it("will stay disabled after an update", function() {
@ -333,7 +329,7 @@ describe("PackageCard", function() {
waitsFor(() => packageUpdated);
return runs(() => expect(atom.packages.isPackageDisabled('package-with-config')).toBe(true));
runs(() => expect(atom.packages.isPackageDisabled('package-with-config')).toBe(true));
});
it("is uninstalled when the uninstallButton is clicked", function() {
@ -370,12 +366,12 @@ describe("PackageCard", function() {
uninstallCallback(0, '', '');
waits(1);
return runs(function() {
runs(function() {
expect(card.refs.uninstallButton.disabled).toBe(false);
expect(card.refs.uninstallButton).not.toHaveClass('is-uninstalling');
expect(card.refs.installButtonGroup).toBeVisible();
expect(card.refs.updateButtonGroup).not.toBeVisible();
return expect(card.refs.packageActionButtonGroup).not.toBeVisible();
expect(card.refs.packageActionButtonGroup).not.toBeVisible();
});
});
@ -392,7 +388,7 @@ describe("PackageCard", function() {
expect(card.refs.settingsButton).toBeVisible();
expect(card.refs.uninstallButton).toBeVisible();
expect(card.refs.enablementButton).toBeVisible();
return expect(card.refs.enablementButton.textContent).toBe('Enable');
expect(card.refs.enablementButton.textContent).toBe('Enable');
});
it("shows the settings, uninstall, and disable buttons", function() {
@ -408,10 +404,10 @@ describe("PackageCard", function() {
expect(card.refs.settingsButton).toBeVisible();
expect(card.refs.uninstallButton).toBeVisible();
expect(card.refs.enablementButton).toBeVisible();
return expect(card.refs.enablementButton.textContent).toBe('Disable');
expect(card.refs.enablementButton.textContent).toBe('Disable');
});
return it("does not show the settings button when there are no settings", function() {
it("does not show the settings button when there are no settings", function() {
const pack = atom.packages.getLoadedPackage('package-with-config');
spyOn(PackageCard.prototype, 'hasSettings').andReturn(false);
card = new PackageCard(pack, new SettingsView(), packageManager);
@ -421,7 +417,7 @@ describe("PackageCard", function() {
expect(card.refs.settingsButton).not.toBeVisible();
expect(card.refs.uninstallButton).toBeVisible();
expect(card.refs.enablementButton).toBeVisible();
return expect(card.refs.enablementButton.textContent).toBe('Disable');
expect(card.refs.enablementButton.textContent).toBe('Disable');
});
});
});

View File

@ -1,155 +0,0 @@
fs = require 'fs'
path = require 'path'
{shell} = require 'electron'
PackageDetailView = require '../lib/package-detail-view'
PackageManager = require '../lib/package-manager'
SettingsView = require '../lib/settings-view'
AtomIoClient = require '../lib/atom-io-client'
SnippetsProvider =
getSnippets: -> {}
describe "PackageDetailView", ->
packageManager = null
view = null
createClientSpy = ->
jasmine.createSpyObj('client', ['package', 'avatar'])
beforeEach ->
packageManager = new PackageManager
view = null
loadPackageFromRemote = (packageName, opts) ->
opts ?= {}
packageManager.client = createClientSpy()
packageManager.client.package.andCallFake (name, cb) ->
packageData = require(path.join(__dirname, 'fixtures', packageName, 'package.json'))
packageData.readme = fs.readFileSync(path.join(__dirname, 'fixtures', packageName, 'README.md'), 'utf8')
cb(null, packageData)
view = new PackageDetailView({name: packageName}, new SettingsView(), packageManager, SnippetsProvider)
view.beforeShow(opts)
loadCustomPackageFromRemote = (packageName, opts) ->
opts ?= {}
packageManager.client = createClientSpy()
packageManager.client.package.andCallFake (name, cb) ->
packageData = require(path.join(__dirname, 'fixtures', packageName, 'package.json'))
cb(null, packageData)
view = new PackageDetailView({name: packageName}, new SettingsView(), packageManager, SnippetsProvider)
view.beforeShow(opts)
it "renders a package when provided in `initialize`", ->
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-config'))
pack = atom.packages.getLoadedPackage('package-with-config')
view = new PackageDetailView(pack, new SettingsView(), packageManager, SnippetsProvider)
# Perhaps there are more things to assert here.
expect(view.refs.title.textContent).toBe('Package With Config')
it "does not call the atom.io api for package metadata when present", ->
packageManager.client = createClientSpy()
view = new PackageDetailView({name: 'package-with-config'}, new SettingsView(), packageManager, SnippetsProvider)
# PackageCard is a subview, and it calls AtomIoClient::package once to load
# metadata from the cache.
expect(packageManager.client.package.callCount).toBe(1)
it "shows a loading message and calls out to atom.io when package metadata is missing", ->
loadPackageFromRemote('package-with-readme')
expect(view.refs.loadingMessage).not.toBe(null)
expect(view.refs.loadingMessage.classList.contains('hidden')).not.toBe(true)
expect(packageManager.client.package).toHaveBeenCalled()
it "shows an error when package metadata cannot be loaded via the API", ->
packageManager.client = createClientSpy()
packageManager.client.package.andCallFake (name, cb) ->
error = new Error('API error')
cb(error, null)
view = new PackageDetailView({name: 'nonexistent-package'}, new SettingsView(), packageManager, SnippetsProvider)
expect(view.refs.errorMessage.classList.contains('hidden')).not.toBe(true)
expect(view.refs.loadingMessage.classList.contains('hidden')).toBe(true)
expect(view.element.querySelectorAll('.package-card').length).toBe(0)
it "shows an error when package metadata cannot be loaded from the cache and the network is unavailable", ->
localStorage.removeItem('settings-view:packages/some-package')
spyOn(AtomIoClient.prototype, 'online').andReturn(false)
spyOn(AtomIoClient.prototype, 'request').andCallFake (path, callback) ->
callback(new Error('getaddrinfo ENOENT atom.io:443'))
spyOn(AtomIoClient.prototype, 'fetchFromCache').andCallThrough()
view = new PackageDetailView({name: 'some-package'}, new SettingsView(), packageManager, SnippetsProvider)
expect(AtomIoClient.prototype.fetchFromCache).toHaveBeenCalled()
expect(view.refs.errorMessage.classList.contains('hidden')).not.toBe(true)
expect(view.refs.loadingMessage.classList.contains('hidden')).toBe(true)
expect(view.element.querySelectorAll('.package-card').length).toBe(0)
it "renders the README successfully after a call to the atom.io api", ->
loadPackageFromRemote('package-with-readme')
expect(view.packageCard).toBeDefined()
expect(view.packageCard.refs.packageName.textContent).toBe('package-with-readme')
expect(view.element.querySelectorAll('.package-readme').length).toBe(1)
it "renders the README successfully with sanitized html", ->
loadPackageFromRemote('package-with-readme')
expect(view.element.querySelectorAll('.package-readme script').length).toBe(0)
expect(view.element.querySelectorAll('.package-readme iframe').length).toBe(0)
expect(view.element.querySelectorAll('.package-readme input[type="checkbox"][disabled]').length).toBe(2)
expect(view.element.querySelector('img[alt="AbsoluteImage"]').getAttribute('src')).toBe('https://example.com/static/image.jpg')
expect(view.element.querySelector('img[alt="RelativeImage"]').getAttribute('src')).toBe('https://github.com/example/package-with-readme/blob/master/static/image.jpg')
expect(view.element.querySelector('img[alt="Base64Image"]').getAttribute('src')).toBe('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')
it "renders the README when the package path is undefined", ->
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-readme'))
pack = atom.packages.getLoadedPackage('package-with-readme')
delete pack.path
view = new PackageDetailView(pack, new SettingsView(), packageManager, SnippetsProvider)
expect(view.packageCard).toBeDefined()
expect(view.packageCard.refs.packageName.textContent).toBe('package-with-readme')
expect(view.element.querySelectorAll('.package-readme').length).toBe(1)
it "triggers a report issue button click and checks that the fallback repository issue tracker URL was opened", ->
loadCustomPackageFromRemote('package-without-bugs-property')
spyOn(shell, 'openExternal')
view.refs.issueButton.click()
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-without-bugs-property/issues/new')
it "triggers a report issue button click and checks that the bugs URL string was opened", ->
loadCustomPackageFromRemote('package-with-bugs-property-url-string')
spyOn(shell, 'openExternal')
view.refs.issueButton.click()
expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new')
it "triggers a report issue button click and checks that the bugs URL was opened", ->
loadCustomPackageFromRemote('package-with-bugs-property-url')
spyOn(shell, 'openExternal')
view.refs.issueButton.click()
expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new')
it "triggers a report issue button click and checks that the bugs email link was opened", ->
loadCustomPackageFromRemote('package-with-bugs-property-email')
spyOn(shell, 'openExternal')
view.refs.issueButton.click()
expect(shell.openExternal).toHaveBeenCalledWith('mailto:issues@example.com')
it "should show 'Install' as the first breadcrumb by default", ->
loadPackageFromRemote('package-with-readme')
expect(view.refs.breadcrumb.textContent).toBe('Install')
it "should open repository url", ->
loadPackageFromRemote('package-with-readme')
spyOn(shell, 'openExternal')
view.refs.packageRepo.click()
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-with-readme')
it "should open internal package repository url", ->
loadPackageFromRemote('package-internal')
spyOn(shell, 'openExternal')
view.refs.packageRepo.click()
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/pulsar-edit/pulsar/tree/master/packages/package-internal')

View File

@ -1,9 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const fs = require('fs');
const path = require('path');
const {shell} = require('electron');
@ -23,7 +18,7 @@ describe("PackageDetailView", function() {
beforeEach(function() {
packageManager = new PackageManager;
return view = null;
view = null;
});
const loadPackageFromRemote = function(packageName, opts) {
@ -55,7 +50,7 @@ describe("PackageDetailView", function() {
view = new PackageDetailView(pack, new SettingsView(), packageManager, SnippetsProvider);
// Perhaps there are more things to assert here.
return expect(view.refs.title.textContent).toBe('Package With Config');
expect(view.refs.title.textContent).toBe('Package With Config');
});
it("does not call the atom.io api for package metadata when present", function() {
@ -64,14 +59,14 @@ describe("PackageDetailView", function() {
// PackageCard is a subview, and it calls AtomIoClient::package once to load
// metadata from the cache.
return expect(packageManager.client.package.callCount).toBe(1);
expect(packageManager.client.package.callCount).toBe(1);
});
it("shows a loading message and calls out to atom.io when package metadata is missing", function() {
loadPackageFromRemote('package-with-readme');
expect(view.refs.loadingMessage).not.toBe(null);
expect(view.refs.loadingMessage.classList.contains('hidden')).not.toBe(true);
return expect(packageManager.client.package).toHaveBeenCalled();
expect(packageManager.client.package).toHaveBeenCalled();
});
it("shows an error when package metadata cannot be loaded via the API", function() {
@ -85,7 +80,7 @@ describe("PackageDetailView", function() {
expect(view.refs.errorMessage.classList.contains('hidden')).not.toBe(true);
expect(view.refs.loadingMessage.classList.contains('hidden')).toBe(true);
return expect(view.element.querySelectorAll('.package-card').length).toBe(0);
expect(view.element.querySelectorAll('.package-card').length).toBe(0);
});
it("shows an error when package metadata cannot be loaded from the cache and the network is unavailable", function() {
@ -101,14 +96,14 @@ describe("PackageDetailView", function() {
expect(view.refs.errorMessage.classList.contains('hidden')).not.toBe(true);
expect(view.refs.loadingMessage.classList.contains('hidden')).toBe(true);
return expect(view.element.querySelectorAll('.package-card').length).toBe(0);
expect(view.element.querySelectorAll('.package-card').length).toBe(0);
});
it("renders the README successfully after a call to the atom.io api", function() {
loadPackageFromRemote('package-with-readme');
expect(view.packageCard).toBeDefined();
expect(view.packageCard.refs.packageName.textContent).toBe('package-with-readme');
return expect(view.element.querySelectorAll('.package-readme').length).toBe(1);
expect(view.element.querySelectorAll('.package-readme').length).toBe(1);
});
it("renders the README successfully with sanitized html", function() {
@ -118,7 +113,7 @@ describe("PackageDetailView", function() {
expect(view.element.querySelectorAll('.package-readme input[type="checkbox"][disabled]').length).toBe(2);
expect(view.element.querySelector('img[alt="AbsoluteImage"]').getAttribute('src')).toBe('https://example.com/static/image.jpg');
expect(view.element.querySelector('img[alt="RelativeImage"]').getAttribute('src')).toBe('https://github.com/example/package-with-readme/blob/master/static/image.jpg');
return expect(view.element.querySelector('img[alt="Base64Image"]').getAttribute('src')).toBe('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
expect(view.element.querySelector('img[alt="Base64Image"]').getAttribute('src')).toBe('data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==');
});
it("renders the README when the package path is undefined", function() {
@ -129,53 +124,53 @@ describe("PackageDetailView", function() {
expect(view.packageCard).toBeDefined();
expect(view.packageCard.refs.packageName.textContent).toBe('package-with-readme');
return expect(view.element.querySelectorAll('.package-readme').length).toBe(1);
expect(view.element.querySelectorAll('.package-readme').length).toBe(1);
});
it("triggers a report issue button click and checks that the fallback repository issue tracker URL was opened", function() {
loadCustomPackageFromRemote('package-without-bugs-property');
spyOn(shell, 'openExternal');
view.refs.issueButton.click();
return expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-without-bugs-property/issues/new');
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-without-bugs-property/issues/new');
});
it("triggers a report issue button click and checks that the bugs URL string was opened", function() {
loadCustomPackageFromRemote('package-with-bugs-property-url-string');
spyOn(shell, 'openExternal');
view.refs.issueButton.click();
return expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new');
expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new');
});
it("triggers a report issue button click and checks that the bugs URL was opened", function() {
loadCustomPackageFromRemote('package-with-bugs-property-url');
spyOn(shell, 'openExternal');
view.refs.issueButton.click();
return expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new');
expect(shell.openExternal).toHaveBeenCalledWith('https://example.com/custom-issue-tracker/new');
});
it("triggers a report issue button click and checks that the bugs email link was opened", function() {
loadCustomPackageFromRemote('package-with-bugs-property-email');
spyOn(shell, 'openExternal');
view.refs.issueButton.click();
return expect(shell.openExternal).toHaveBeenCalledWith('mailto:issues@example.com');
expect(shell.openExternal).toHaveBeenCalledWith('mailto:issues@example.com');
});
it("should show 'Install' as the first breadcrumb by default", function() {
loadPackageFromRemote('package-with-readme');
return expect(view.refs.breadcrumb.textContent).toBe('Install');
expect(view.refs.breadcrumb.textContent).toBe('Install');
});
it("should open repository url", function() {
loadPackageFromRemote('package-with-readme');
spyOn(shell, 'openExternal');
view.refs.packageRepo.click();
return expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-with-readme');
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/example/package-with-readme');
});
return it("should open internal package repository url", function() {
it("should open internal package repository url", function() {
loadPackageFromRemote('package-internal');
spyOn(shell, 'openExternal');
view.refs.packageRepo.click();
return expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/pulsar-edit/pulsar/tree/master/packages/package-internal');
expect(shell.openExternal).toHaveBeenCalledWith('https://github.com/pulsar-edit/pulsar/tree/master/packages/package-internal');
});
});

View File

@ -1,305 +0,0 @@
path = require 'path'
process = require 'process'
PackageManager = require '../lib/package-manager'
describe "PackageManager", ->
[packageManager] = []
beforeEach ->
spyOn(atom.packages, 'getApmPath').andReturn('/an/invalid/apm/command/to/run')
atom.config.set('core.useProxySettingsWhenCallingApm', false)
packageManager = new PackageManager()
it "handle errors spawning apm", ->
noSuchCommandError = if process.platform is 'win32' then ' cannot find the path ' else 'ENOENT'
waitsForPromise shouldReject: true, -> packageManager.getInstalled()
waitsForPromise shouldReject: true, -> packageManager.getOutdated()
waitsForPromise shouldReject: true, -> packageManager.getFeatured()
waitsForPromise shouldReject: true, -> packageManager.getPackage('foo')
installCallback = jasmine.createSpy('installCallback')
uninstallCallback = jasmine.createSpy('uninstallCallback')
updateCallback = jasmine.createSpy('updateCallback')
runs ->
packageManager.install {name: 'foo', version: '1.0.0'}, installCallback
waitsFor ->
installCallback.callCount is 1
runs ->
installArg = installCallback.argsForCall[0][0]
expect(installArg.message).toBe "Installing \u201Cfoo@1.0.0\u201D failed."
expect(installArg.packageInstallError).toBe true
expect(installArg.stderr).toContain noSuchCommandError
packageManager.uninstall {name: 'foo'}, uninstallCallback
waitsFor ->
uninstallCallback.callCount is 1
runs ->
uninstallArg = uninstallCallback.argsForCall[0][0]
expect(uninstallArg.message).toBe "Uninstalling \u201Cfoo\u201D failed."
expect(uninstallArg.stderr).toContain noSuchCommandError
packageManager.update {name: 'foo'}, '1.0.0', updateCallback
waitsFor ->
updateCallback.callCount is 1
runs ->
updateArg = updateCallback.argsForCall[0][0]
expect(updateArg.message).toBe "Updating to \u201Cfoo@1.0.0\u201D failed."
expect(updateArg.packageInstallError).toBe true
expect(updateArg.stderr).toContain noSuchCommandError
describe "::isPackageInstalled()", ->
it "returns false a package is not installed", ->
expect(packageManager.isPackageInstalled('some-package')).toBe false
it "returns true when a package is loaded", ->
spyOn(atom.packages, 'isPackageLoaded').andReturn true
expect(packageManager.isPackageInstalled('some-package')).toBe true
it "returns true when a package is disabled", ->
spyOn(atom.packages, 'getAvailablePackageNames').andReturn ['some-package']
expect(packageManager.isPackageInstalled('some-package')).toBe true
describe "::install()", ->
[runArgs, runCallback] = []
beforeEach ->
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
runArgs = args
runCallback = callback
onWillThrowError: ->
it "installs the latest version when a package version is not specified", ->
packageManager.install {name: 'something'}, ->
expect(packageManager.runCommand).toHaveBeenCalled()
expect(runArgs).toEqual ['install', 'something', '--json']
it "installs the package@version when a version is specified", ->
packageManager.install {name: 'something', version: '0.2.3'}, ->
expect(packageManager.runCommand).toHaveBeenCalled()
expect(runArgs).toEqual ['install', 'something@0.2.3', '--json']
describe "git url installation", ->
it 'installs https:// urls', ->
url = "https://github.com/user/repo.git"
packageManager.install {name: url}
expect(packageManager.runCommand).toHaveBeenCalled()
expect(runArgs).toEqual ['install', 'https://github.com/user/repo.git', '--json']
it 'installs git@ urls', ->
url = "git@github.com:user/repo.git"
packageManager.install {name: url}
expect(packageManager.runCommand).toHaveBeenCalled()
expect(runArgs).toEqual ['install', 'git@github.com:user/repo.git', '--json']
it 'installs user/repo url shortcuts', ->
url = "user/repo"
packageManager.install {name: url}
expect(packageManager.runCommand).toHaveBeenCalled()
expect(runArgs).toEqual ['install', 'user/repo', '--json']
it 'installs and activates git pacakges with names different from the repo name', ->
spyOn(atom.packages, 'activatePackage')
packageManager.install(name: 'git-repo-name')
json =
metadata:
name: 'real-package-name'
runCallback(0, JSON.stringify([json]), '')
expect(atom.packages.activatePackage).toHaveBeenCalledWith json.metadata.name
it 'emits an installed event with a copy of the pack including the full package metadata', ->
spyOn(packageManager, 'emitPackageEvent')
originalPackObject = name: 'git-repo-name', otherData: {will: 'beCopied'}
packageManager.install(originalPackObject)
json =
metadata:
name: 'real-package-name'
moreInfo: 'yep'
runCallback(0, JSON.stringify([json]), '')
installEmittedCount = 0
for call in packageManager.emitPackageEvent.calls
if call.args[0] is "installed"
expect(call.args[1]).not.toEqual originalPackObject
expect(call.args[1].moreInfo).toEqual "yep"
expect(call.args[1].otherData).toBe originalPackObject.otherData
installEmittedCount++
expect(installEmittedCount).toBe 1
describe "::uninstall()", ->
[runCallback] = []
beforeEach ->
spyOn(packageManager, 'unload')
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
runCallback = callback
onWillThrowError: ->
it "removes the package from the core.disabledPackages list", ->
atom.config.set('core.disabledPackages', ['something'])
packageManager.uninstall {name: 'something'}, ->
expect(atom.config.get('core.disabledPackages')).toContain('something')
runCallback(0, '', '')
expect(atom.config.get('core.disabledPackages')).not.toContain('something')
describe "::packageHasSettings", ->
it "returns true when the pacakge has config", ->
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-config'))
expect(packageManager.packageHasSettings('package-with-config')).toBe true
it "returns false when the pacakge does not have config and doesn't define language grammars", ->
expect(packageManager.packageHasSettings('random-package')).toBe false
it "returns true when the pacakge does not have config, but does define language grammars", ->
packageName = 'language-test'
waitsForPromise ->
atom.packages.activatePackage(path.join(__dirname, 'fixtures', packageName))
runs ->
expect(packageManager.packageHasSettings(packageName)).toBe true
describe "::loadOutdated", ->
it "caches results", ->
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}]', '')
onWillThrowError: ->
packageManager.loadOutdated false, ->
expect(packageManager.apmCache.loadOutdated.value).toMatch([{"name": "boop"}])
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(1)
it "expires results after a timeout", ->
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}]', '')
onWillThrowError: ->
packageManager.loadOutdated false, ->
now = Date.now()
spyOn(Date, 'now') unless Date.now.andReturn
Date.now.andReturn((-> now + packageManager.CACHE_EXPIRY + 1)())
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(2)
it "expires results after a package updated/installed", ->
packageManager.apmCache.loadOutdated =
value: ['hi']
expiry: Date.now() + 999999999
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}]', '')
onWillThrowError: ->
# Just prevent this stuff from calling through, it doesn't matter for this test
spyOn(atom.packages, 'deactivatePackage').andReturn(true)
spyOn(atom.packages, 'activatePackage').andReturn(true)
spyOn(atom.packages, 'unloadPackage').andReturn(true)
spyOn(atom.packages, 'loadPackage').andReturn(true)
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(0)
packageManager.update {}, {}, -> # +1 runCommand call to update the package
packageManager.loadOutdated false, -> # +1 runCommand call to load outdated because the cache should be wiped
expect(packageManager.runCommand.calls.length).toBe(2)
packageManager.install {}, -> # +1 runCommand call to install the package
packageManager.loadOutdated false, -> # +1 runCommand call to load outdated because the cache should be wiped
expect(packageManager.runCommand.calls.length).toBe(4)
packageManager.loadOutdated false, -> # +0 runCommand call, should be cached
expect(packageManager.runCommand.calls.length).toBe(4)
it "expires results if it is called with clearCache set to true", ->
packageManager.apmCache.loadOutdated =
value: ['hi']
expiry: Date.now() + 999999999
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}]', '')
onWillThrowError: ->
packageManager.loadOutdated true, ->
expect(packageManager.runCommand.calls.length).toBe(1)
expect(packageManager.apmCache.loadOutdated.value).toEqual [{"name": "boop"}]
describe "when there is a version pinned package", ->
beforeEach ->
atom.config.set('core.versionPinnedPackages', ['beep'])
it "caches results", ->
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}, {"name": "beep"}]', '')
onWillThrowError: ->
packageManager.loadOutdated false, ->
expect(packageManager.apmCache.loadOutdated.value).toMatch([{"name": "boop"}])
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(1)
it "expires results after a timeout", ->
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}, {"name": "beep"}]', '')
onWillThrowError: ->
packageManager.loadOutdated false, ->
now = Date.now()
spyOn(Date, 'now') unless Date.now.andReturn
Date.now.andReturn((-> now + packageManager.CACHE_EXPIRY + 1)())
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(2)
it "expires results after a package updated/installed", ->
packageManager.apmCache.loadOutdated =
value: ['hi']
expiry: Date.now() + 999999999
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}, {"name": "beep"}]', '')
onWillThrowError: ->
# Just prevent this stuff from calling through, it doesn't matter for this test
spyOn(atom.packages, 'deactivatePackage').andReturn(true)
spyOn(atom.packages, 'activatePackage').andReturn(true)
spyOn(atom.packages, 'unloadPackage').andReturn(true)
spyOn(atom.packages, 'loadPackage').andReturn(true)
packageManager.loadOutdated false, ->
expect(packageManager.runCommand.calls.length).toBe(0)
packageManager.update {}, {}, -> # +1 runCommand call to update the package
packageManager.loadOutdated false, -> # +1 runCommand call to load outdated because the cache should be wiped
expect(packageManager.runCommand.calls.length).toBe(2)
packageManager.install {}, -> # +1 runCommand call to install the package
packageManager.loadOutdated false, -> # +1 runCommand call to load outdated because the cache should be wiped
expect(packageManager.runCommand.calls.length).toBe(4)
packageManager.loadOutdated false, -> # +0 runCommand call, should be cached
expect(packageManager.runCommand.calls.length).toBe(4)
it "expires results if it is called with clearCache set to true", ->
packageManager.apmCache.loadOutdated =
value: ['hi']
expiry: Date.now() + 999999999
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
callback(0, '[{"name": "boop"}, {"name": "beep"}]', '')
onWillThrowError: ->
packageManager.loadOutdated true, ->
expect(packageManager.runCommand.calls.length).toBe(1)
expect(packageManager.apmCache.loadOutdated.value).toEqual [{"name": "boop"}]

View File

@ -1,9 +1,4 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const process = require('process');
const PackageManager = require('../lib/package-manager');
@ -14,7 +9,7 @@ describe("PackageManager", function() {
beforeEach(function() {
spyOn(atom.packages, 'getApmPath').andReturn('/an/invalid/apm/command/to/run');
atom.config.set('core.useProxySettingsWhenCallingApm', false);
return packageManager = new PackageManager();
packageManager = new PackageManager();
});
it("handle errors spawning apm", function() {
@ -57,7 +52,7 @@ describe("PackageManager", function() {
const updateArg = updateCallback.argsForCall[0][0];
expect(updateArg.message).toBe("Updating to \u201Cfoo@1.0.0\u201D failed.");
expect(updateArg.packageInstallError).toBe(true);
return expect(updateArg.stderr).toContain(noSuchCommandError);
expect(updateArg.stderr).toContain(noSuchCommandError);
});
});
@ -66,12 +61,12 @@ describe("PackageManager", function() {
it("returns true when a package is loaded", function() {
spyOn(atom.packages, 'isPackageLoaded').andReturn(true);
return expect(packageManager.isPackageInstalled('some-package')).toBe(true);
expect(packageManager.isPackageInstalled('some-package')).toBe(true);
});
return it("returns true when a package is disabled", function() {
it("returns true when a package is disabled", function() {
spyOn(atom.packages, 'getAvailablePackageNames').andReturn(['some-package']);
return expect(packageManager.isPackageInstalled('some-package')).toBe(true);
expect(packageManager.isPackageInstalled('some-package')).toBe(true);
});
});
@ -87,35 +82,35 @@ describe("PackageManager", function() {
it("installs the latest version when a package version is not specified", function() {
packageManager.install({name: 'something'}, function() {});
expect(packageManager.runCommand).toHaveBeenCalled();
return expect(runArgs).toEqual(['install', 'something', '--json']);
expect(runArgs).toEqual(['install', 'something', '--json']);
});
it("installs the package@version when a version is specified", function() {
packageManager.install({name: 'something', version: '0.2.3'}, function() {});
expect(packageManager.runCommand).toHaveBeenCalled();
return expect(runArgs).toEqual(['install', 'something@0.2.3', '--json']);
expect(runArgs).toEqual(['install', 'something@0.2.3', '--json']);
});
return describe("git url installation", function() {
describe("git url installation", function() {
it('installs https:// urls', function() {
const url = "https://github.com/user/repo.git";
packageManager.install({name: url});
expect(packageManager.runCommand).toHaveBeenCalled();
return expect(runArgs).toEqual(['install', 'https://github.com/user/repo.git', '--json']);
expect(runArgs).toEqual(['install', 'https://github.com/user/repo.git', '--json']);
});
it('installs git@ urls', function() {
const url = "git@github.com:user/repo.git";
packageManager.install({name: url});
expect(packageManager.runCommand).toHaveBeenCalled();
return expect(runArgs).toEqual(['install', 'git@github.com:user/repo.git', '--json']);
expect(runArgs).toEqual(['install', 'git@github.com:user/repo.git', '--json']);
});
it('installs user/repo url shortcuts', function() {
const url = "user/repo";
packageManager.install({name: url});
expect(packageManager.runCommand).toHaveBeenCalled();
return expect(runArgs).toEqual(['install', 'user/repo', '--json']);
expect(runArgs).toEqual(['install', 'user/repo', '--json']);
});
it('installs and activates git pacakges with names different from the repo name', function() {
@ -127,10 +122,10 @@ describe("PackageManager", function() {
}
};
runCallback(0, JSON.stringify([json]), '');
return expect(atom.packages.activatePackage).toHaveBeenCalledWith(json.metadata.name);
expect(atom.packages.activatePackage).toHaveBeenCalledWith(json.metadata.name);
});
return it('emits an installed event with a copy of the pack including the full package metadata', function() {
it('emits an installed event with a copy of the pack including the full package metadata', function() {
spyOn(packageManager, 'emitPackageEvent');
const originalPackObject = {name: 'git-repo-name', otherData: {will: 'beCopied'}};
packageManager.install(originalPackObject);
@ -151,7 +146,7 @@ describe("PackageManager", function() {
installEmittedCount++;
}
}
return expect(installEmittedCount).toBe(1);
expect(installEmittedCount).toBe(1);
});
});
});
@ -167,26 +162,26 @@ describe("PackageManager", function() {
});
});
return it("removes the package from the core.disabledPackages list", function() {
it("removes the package from the core.disabledPackages list", function() {
atom.config.set('core.disabledPackages', ['something']);
packageManager.uninstall({name: 'something'}, function() {});
expect(atom.config.get('core.disabledPackages')).toContain('something');
runCallback(0, '', '');
return expect(atom.config.get('core.disabledPackages')).not.toContain('something');
expect(atom.config.get('core.disabledPackages')).not.toContain('something');
});
});
describe("::packageHasSettings", function() {
it("returns true when the pacakge has config", function() {
atom.packages.loadPackage(path.join(__dirname, 'fixtures', 'package-with-config'));
return expect(packageManager.packageHasSettings('package-with-config')).toBe(true);
expect(packageManager.packageHasSettings('package-with-config')).toBe(true);
});
it("returns false when the pacakge does not have config and doesn't define language grammars", () => expect(packageManager.packageHasSettings('random-package')).toBe(false));
return it("returns true when the pacakge does not have config, but does define language grammars", function() {
it("returns true when the pacakge does not have config, but does define language grammars", function() {
const packageName = 'language-test';
waitsForPromise(() => atom.packages.activatePackage(path.join(__dirname, 'fixtures', packageName)));
@ -195,7 +190,7 @@ describe("PackageManager", function() {
});
});
return describe("::loadOutdated", function() {
describe("::loadOutdated", function() {
it("caches results", function() {
spyOn(packageManager, 'runCommand').andCallFake(function(args, callback) {
callback(0, '[{"name": "boop"}]', '');
@ -206,7 +201,7 @@ describe("PackageManager", function() {
expect(packageManager.apmCache.loadOutdated.value).toMatch([{"name": "boop"}]);
packageManager.loadOutdated(false, function() {});
return expect(packageManager.runCommand.calls.length).toBe(1);
expect(packageManager.runCommand.calls.length).toBe(1);
});
it("expires results after a timeout", function() {
@ -221,7 +216,7 @@ describe("PackageManager", function() {
Date.now.andReturn(((() => now + packageManager.CACHE_EXPIRY + 1))());
packageManager.loadOutdated(false, function() {});
return expect(packageManager.runCommand.calls.length).toBe(2);
expect(packageManager.runCommand.calls.length).toBe(2);
});
it("expires results after a package updated/installed", function() {
@ -253,7 +248,7 @@ describe("PackageManager", function() {
expect(packageManager.runCommand.calls.length).toBe(4);
packageManager.loadOutdated(false, function() {}); // +0 runCommand call, should be cached
return expect(packageManager.runCommand.calls.length).toBe(4);
expect(packageManager.runCommand.calls.length).toBe(4);
});
it("expires results if it is called with clearCache set to true", function() {
@ -269,10 +264,10 @@ describe("PackageManager", function() {
packageManager.loadOutdated(true, function() {});
expect(packageManager.runCommand.calls.length).toBe(1);
return expect(packageManager.apmCache.loadOutdated.value).toEqual([{"name": "boop"}]);
expect(packageManager.apmCache.loadOutdated.value).toEqual([{"name": "boop"}]);
});
return describe("when there is a version pinned package", function() {
describe("when there is a version pinned package", function() {
beforeEach(() => atom.config.set('core.versionPinnedPackages', ['beep']));
it("caches results", function() {
@ -285,7 +280,7 @@ describe("PackageManager", function() {
expect(packageManager.apmCache.loadOutdated.value).toMatch([{"name": "boop"}]);
packageManager.loadOutdated(false, function() {});
return expect(packageManager.runCommand.calls.length).toBe(1);
expect(packageManager.runCommand.calls.length).toBe(1);
});
it("expires results after a timeout", function() {
@ -300,7 +295,7 @@ describe("PackageManager", function() {
Date.now.andReturn(((() => now + packageManager.CACHE_EXPIRY + 1))());
packageManager.loadOutdated(false, function() {});
return expect(packageManager.runCommand.calls.length).toBe(2);
expect(packageManager.runCommand.calls.length).toBe(2);
});
it("expires results after a package updated/installed", function() {
@ -332,10 +327,10 @@ describe("PackageManager", function() {
expect(packageManager.runCommand.calls.length).toBe(4);
packageManager.loadOutdated(false, function() {}); // +0 runCommand call, should be cached
return expect(packageManager.runCommand.calls.length).toBe(4);
expect(packageManager.runCommand.calls.length).toBe(4);
});
return it("expires results if it is called with clearCache set to true", function() {
it("expires results if it is called with clearCache set to true", function() {
packageManager.apmCache.loadOutdated = {
value: ['hi'],
expiry: Date.now() + 999999999
@ -348,7 +343,7 @@ describe("PackageManager", function() {
packageManager.loadOutdated(true, function() {});
expect(packageManager.runCommand.calls.length).toBe(1);
return expect(packageManager.apmCache.loadOutdated.value).toEqual([{"name": "boop"}]);
expect(packageManager.apmCache.loadOutdated.value).toEqual([{"name": "boop"}]);
});
});
});

View File

@ -1,152 +0,0 @@
PackageManager = require '../lib/package-manager'
PackageUpdatesStatusView = require '../lib/package-updates-status-view'
describe "PackageUpdatesStatusView", ->
[statusBar, statusView, packageManager] = []
outdatedPackage1 =
name: 'out-dated-1'
outdatedPackage2 =
name: 'out-dated-2'
installedPackage =
name: 'user-package'
beforeEach ->
spyOn(PackageManager.prototype, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(PackageManager.prototype, 'getInstalled').andCallFake -> Promise.resolve([installedPackage])
spyOn(PackageManager.prototype, 'getOutdated').andCallFake -> Promise.resolve([outdatedPackage1, outdatedPackage2])
spyOn(PackageUpdatesStatusView.prototype, 'initialize').andCallThrough()
jasmine.attachToDOM(atom.views.getView(atom.workspace))
waitsForPromise ->
atom.packages.activatePackage('status-bar')
waitsForPromise ->
atom.packages.activatePackage('settings-view')
runs ->
atom.packages.emitter.emit('did-activate-all')
expect(document.querySelector('status-bar .package-updates-status-view')).toExist()
packageManager = PackageUpdatesStatusView.prototype.initialize.mostRecentCall.args[1]
describe "when packages are outdated", ->
it "adds a tile to the status bar", ->
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates'
describe "when the tile is clicked", ->
it "opens the Available Updates panel", ->
spyOn(atom.commands, 'dispatch').andCallFake ->
document.querySelector('status-bar .package-updates-status-view').click()
expect(atom.commands.dispatch).toHaveBeenCalledWith(atom.views.getView(atom.workspace), 'settings-view:check-for-package-updates')
it "does not destroy the tile", ->
document.querySelector('status-bar .package-updates-status-view').click()
expect(document.querySelector('status-bar .package-updates-status-view')).toExist()
describe "when a package is updating", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1/2 updating'
describe "when a package finishes updating", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('updated', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when a package is updated without a prior updating event", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updated', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when multiple packages are updating and one finishes", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('updating', outdatedPackage2)
packageManager.emitPackageEvent('updated', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1/1 updating'
describe "when a package fails to update", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates (1 failed)'
describe "when a package that previously failed to update starts updating again", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
packageManager.emitPackageEvent('updating', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1/2 updating'
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates (1 failed)'
describe "when a package update that previously failed succeeds on a subsequent try", ->
it "updates the tile", ->
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
packageManager.emitPackageEvent('updated', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when multiple events are happening at the same time", ->
it "updates the tile", ->
packageManager.emitPackageEvent('update-available', installedPackage)
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('update-failed', outdatedPackage2)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1/3 updating (1 failed)'
describe "when there are no more updates", ->
it "destroys the tile", ->
packageManager.emitPackageEvent('updated', outdatedPackage1)
packageManager.emitPackageEvent('updated', outdatedPackage2)
expect(document.querySelector('status-bar .package-updates-status-view')).not.toExist()
describe "when a new update becomes available and the tile is destroyed", ->
it "recreates the tile", ->
packageManager.emitPackageEvent('updated', outdatedPackage1)
packageManager.emitPackageEvent('updated', outdatedPackage2)
packageManager.emitPackageEvent('update-available', installedPackage)
expect(document.querySelector('status-bar .package-updates-status-view')).toExist()
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when an update becomes available for a package", ->
it "updates the tile", ->
packageManager.emitPackageEvent('update-available', installedPackage)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '3 updates'
describe "when updates are checked for multiple times and no new updates are available", ->
it "does not keep updating the tile", ->
packageManager.emitPackageEvent('update-available', outdatedPackage1)
packageManager.emitPackageEvent('update-available', outdatedPackage1)
packageManager.emitPackageEvent('update-available', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates'
# There are more fields in an actual package object,
# so make sure only name is tested and not object equality
packageManager.emitPackageEvent('update-available', {name: 'out-dated-1', date: Date.now()})
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates'
describe "when the same update fails multiple times", ->
it "does not keep updating the tile", ->
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '2 updates (1 failed)'
describe "when a package that can be updated is uninstalled", ->
it "updates the tile", ->
packageManager.emitPackageEvent('uninstalled', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when a package that is updating is uninstalled", ->
it "updates the tile", ->
packageManager.emitPackageEvent('updating', outdatedPackage1)
packageManager.emitPackageEvent('uninstalled', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'
describe "when a package that failed to update is uninstalled", ->
it "updates the tile", ->
packageManager.emitPackageEvent('update-failed', outdatedPackage1)
packageManager.emitPackageEvent('uninstalled', outdatedPackage1)
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe '1 update'

View File

@ -1,8 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const PackageManager = require('../lib/package-manager');
const PackageUpdatesStatusView = require('../lib/package-updates-status-view');
@ -27,7 +23,7 @@ describe("PackageUpdatesStatusView", function() {
waitsForPromise(() => atom.packages.activatePackage('settings-view'));
return runs(function() {
runs(function() {
atom.packages.emitter.emit('did-activate-all');
expect(document.querySelector('status-bar .package-updates-status-view')).toExist();
@ -40,42 +36,42 @@ describe("PackageUpdatesStatusView", function() {
spyOn(atom.commands, 'dispatch').andCallFake(function() {});
document.querySelector('status-bar .package-updates-status-view').click();
return expect(atom.commands.dispatch).toHaveBeenCalledWith(atom.views.getView(atom.workspace), 'settings-view:check-for-package-updates');
expect(atom.commands.dispatch).toHaveBeenCalledWith(atom.views.getView(atom.workspace), 'settings-view:check-for-package-updates');
});
return it("does not destroy the tile", function() {
it("does not destroy the tile", function() {
document.querySelector('status-bar .package-updates-status-view').click();
return expect(document.querySelector('status-bar .package-updates-status-view')).toExist();
expect(document.querySelector('status-bar .package-updates-status-view')).toExist();
});
});
describe("when a package is updating", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/2 updating');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/2 updating');
}));
describe("when a package finishes updating", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
packageManager.emitPackageEvent('updated', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
describe("when a package is updated without a prior updating event", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updated', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
describe("when multiple packages are updating and one finishes", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
packageManager.emitPackageEvent('updating', outdatedPackage2);
packageManager.emitPackageEvent('updated', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/1 updating');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/1 updating');
}));
describe("when a package fails to update", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
}));
describe("when a package that previously failed to update starts updating again", () => it("updates the tile", function() {
@ -84,26 +80,26 @@ describe("PackageUpdatesStatusView", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/2 updating');
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
}));
describe("when a package update that previously failed succeeds on a subsequent try", () => it("updates the tile", function() {
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
packageManager.emitPackageEvent('updated', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
describe("when multiple events are happening at the same time", () => it("updates the tile", function() {
packageManager.emitPackageEvent('update-available', installedPackage);
packageManager.emitPackageEvent('updating', outdatedPackage1);
packageManager.emitPackageEvent('update-failed', outdatedPackage2);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/3 updating (1 failed)');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1/3 updating (1 failed)');
}));
describe("when there are no more updates", () => it("destroys the tile", function() {
packageManager.emitPackageEvent('updated', outdatedPackage1);
packageManager.emitPackageEvent('updated', outdatedPackage2);
return expect(document.querySelector('status-bar .package-updates-status-view')).not.toExist();
expect(document.querySelector('status-bar .package-updates-status-view')).not.toExist();
}));
describe("when a new update becomes available and the tile is destroyed", () => it("recreates the tile", function() {
@ -111,12 +107,12 @@ describe("PackageUpdatesStatusView", function() {
packageManager.emitPackageEvent('updated', outdatedPackage2);
packageManager.emitPackageEvent('update-available', installedPackage);
expect(document.querySelector('status-bar .package-updates-status-view')).toExist();
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
describe("when an update becomes available for a package", () => it("updates the tile", function() {
packageManager.emitPackageEvent('update-available', installedPackage);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('3 updates');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('3 updates');
}));
describe("when updates are checked for multiple times and no new updates are available", () => it("does not keep updating the tile", function() {
@ -128,30 +124,30 @@ describe("PackageUpdatesStatusView", function() {
// There are more fields in an actual package object,
// so make sure only name is tested and not object equality
packageManager.emitPackageEvent('update-available', {name: 'out-dated-1', date: Date.now()});
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates');
}));
describe("when the same update fails multiple times", () => it("does not keep updating the tile", function() {
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('2 updates (1 failed)');
}));
describe("when a package that can be updated is uninstalled", () => it("updates the tile", function() {
packageManager.emitPackageEvent('uninstalled', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
describe("when a package that is updating is uninstalled", () => it("updates the tile", function() {
packageManager.emitPackageEvent('updating', outdatedPackage1);
packageManager.emitPackageEvent('uninstalled', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
return describe("when a package that failed to update is uninstalled", () => it("updates the tile", function() {
describe("when a package that failed to update is uninstalled", () => it("updates the tile", function() {
packageManager.emitPackageEvent('update-failed', outdatedPackage1);
packageManager.emitPackageEvent('uninstalled', outdatedPackage1);
return expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
expect(document.querySelector('status-bar .package-updates-status-view').textContent).toBe('1 update');
}));
});

View File

@ -1,159 +0,0 @@
{getSettingDescription} = require '../lib/rich-description'
describe "Rich descriptions", ->
beforeEach ->
config =
type: 'object'
properties:
plainText:
description: 'Plain text description'
type: 'string'
default: ''
italics:
description: 'Description *with* italics'
type: 'string'
default: ''
bold:
description: 'Description **with** bold'
type: 'string'
default: ''
link:
description: 'Description [with](http://www.example.com) link'
type: 'string'
default: ''
inlineCode:
description: 'Description `with` inline code'
type: 'string'
default: ''
lineBreak:
description: 'Description with<br/> line break'
type: 'string'
default: ''
strikethrough:
description: 'Description ~~with~~ strikethrough'
type: 'string'
default: ''
image:
description: 'Description without ![alt text](https://github.com/adam-p/markdown-here/raw/master/src/common/images/icon48.png "Logo Title Text 1") image'
type: 'string'
default: ''
fencedBlockCode:
description: '''Description without fenced block code
```
Test
```
'''
type: 'string'
default: ''
indentedBlockCode:
description: '''
Description without indented block code
Test
'''
type: 'string'
default: ''
blockquote:
description: '''
Description without blockquote
> Test
'''
type: 'string'
default: ''
html:
description: '''
Description without html
<html>Test</html>
'''
type: 'string'
default: ''
heading:
description: '''
Description without heading
## Test
'''
type: 'string'
default: ''
orderedList:
description: '''
Description without ordered list
1. Test
2. Test
3. Test
'''
type: 'string'
default: ''
unorderedList:
description: '''
Description without unordered list
* Test
* Test
* Test
'''
type: 'string'
default: ''
table:
description: '''
Description without table
<table><tr><td>Test</td></tr></table>
'''
type: 'string'
default: ''
atom.config.setSchema("foo", config)
describe 'supported Markdown', ->
it 'handles plain text', ->
expect(getSettingDescription('foo.plainText')).toEqual 'Plain text description'
it 'handles italics', ->
expect(getSettingDescription('foo.italics')).toEqual 'Description <em>with</em> italics'
it 'handles bold', ->
expect(getSettingDescription('foo.bold')).toEqual 'Description <strong>with</strong> bold'
it 'handles links', ->
expect(getSettingDescription('foo.link')).toEqual 'Description <a href="http://www.example.com">with</a> link'
it 'handles inline code', ->
expect(getSettingDescription('foo.inlineCode')).toEqual 'Description <code>with</code> inline code'
it 'handles line breaks', ->
expect(getSettingDescription('foo.lineBreak')).toEqual 'Description with<br/> line break'
it 'handles strikethrough', ->
expect(getSettingDescription('foo.strikethrough')).toEqual 'Description <del>with</del> strikethrough'
describe 'unsupported Markdown', ->
it 'strips images', ->
expect(getSettingDescription('foo.image')).toEqual 'Description without image'
it 'strips fenced code blocks', ->
expect(getSettingDescription('foo.fencedBlockCode')).toEqual 'Description without fenced block code'
it 'strips indented code blocks', ->
expect(getSettingDescription('foo.indentedBlockCode')).toEqual 'Description without indented block code'
it 'strips blockquotes', ->
expect(getSettingDescription('foo.blockquote')).toEqual 'Description without blockquote'
it 'strips html elements', ->
expect(getSettingDescription('foo.html')).toEqual 'Description without html'
it 'strips headings', ->
expect(getSettingDescription('foo.heading')).toEqual 'Description without heading'
it 'strips ordered lists', ->
expect(getSettingDescription('foo.orderedList')).toEqual 'Description without ordered list'
it 'strips unordered lists', ->
expect(getSettingDescription('foo.unorderedList')).toEqual 'Description without unordered list'
it 'strips tables', ->
expect(getSettingDescription('foo.table')).toEqual 'Description without table'

View File

@ -1,12 +1,8 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const {getSettingDescription} = require('../lib/rich-description');
describe("Rich descriptions", function() {
beforeEach(function() {
describe("Rich descriptions", () => {
beforeEach(() => {
const config = {
type: 'object',
properties: {
@ -129,10 +125,10 @@ Description without table
}
};
return atom.config.setSchema("foo", config);
atom.config.setSchema("foo", config);
});
describe('supported Markdown', function() {
describe('supported Markdown', () => {
it('handles plain text', () => expect(getSettingDescription('foo.plainText')).toEqual('Plain text description'));
it('handles italics', () => expect(getSettingDescription('foo.italics')).toEqual('Description <em>with</em> italics'));
@ -145,10 +141,10 @@ Description without table
it('handles line breaks', () => expect(getSettingDescription('foo.lineBreak')).toEqual('Description with<br/> line break'));
return it('handles strikethrough', () => expect(getSettingDescription('foo.strikethrough')).toEqual('Description <del>with</del> strikethrough'));
it('handles strikethrough', () => expect(getSettingDescription('foo.strikethrough')).toEqual('Description <del>with</del> strikethrough'));
});
return describe('unsupported Markdown', function() {
describe('unsupported Markdown', () => {
it('strips images', () => expect(getSettingDescription('foo.image')).toEqual('Description without image'));
it('strips fenced code blocks', () => expect(getSettingDescription('foo.fencedBlockCode')).toEqual('Description without fenced block code'));
@ -165,6 +161,6 @@ Description without table
it('strips unordered lists', () => expect(getSettingDescription('foo.unorderedList')).toEqual('Description without unordered list'));
return it('strips tables', () => expect(getSettingDescription('foo.table')).toEqual('Description without table'));
it('strips tables', () => expect(getSettingDescription('foo.table')).toEqual('Description without table'));
});
});

View File

@ -1,391 +0,0 @@
SettingsPanel = require '../lib/settings-panel'
_ = require 'underscore-plus'
describe "SettingsPanel", ->
settingsPanel = null
describe "sorted settings", ->
beforeEach ->
config =
type: 'object'
properties:
bar:
title: 'Bar'
description: 'The bar setting'
type: 'boolean'
default: true
haz:
title: 'Haz'
description: 'The haz setting'
type: 'string'
default: 'haz'
zing:
title: 'Zing'
description: 'The zing setting'
type: 'string'
default: 'zing'
order: 1
zang:
title: 'Zang'
description: 'The baz setting'
type: 'string'
default: 'zang'
order: 100
enum:
title: 'An enum'
type: 'string'
default: 'one'
enum: [
{value: 'one', description: 'One'}
'Two'
]
radio:
title: 'An enum with radio buttons'
radio: true
type: 'string'
default: 'Two'
enum: [
{value: 'one', description: 'One'}
'Two'
]
atom.config.setSchema("foo", config)
atom.config.setDefaults("foo", gong: 'gong')
expect(_.size(atom.config.get('foo'))).toBe 7
settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false})
it "sorts settings by order and then alphabetically by the key", ->
settings = atom.config.get('foo')
expect(_.size(settings)).toBe 7
sortedSettings = settingsPanel.sortSettings("foo", settings)
expect(sortedSettings[0]).toBe 'zing'
expect(sortedSettings[1]).toBe 'zang'
expect(sortedSettings[2]).toBe 'bar'
expect(sortedSettings[3]).toBe 'enum'
expect(sortedSettings[4]).toBe 'gong'
expect(sortedSettings[5]).toBe 'haz'
expect(sortedSettings[6]).toBe 'radio'
it "gracefully deals with a null settings object", ->
sortedSettings = settingsPanel.sortSettings("foo", null)
expect(sortedSettings).not.toBeNull
expect(_.size(sortedSettings)).toBe 0
it "presents enum options with their descriptions", ->
select = settingsPanel.element.querySelector('#foo\\.enum')
pairs = ([opt.value, opt.innerText] for opt in select.children)
expect(pairs).toEqual([['one', 'One'], ['Two', 'Two']])
it "presents radio options with their descriptions", ->
radio = settingsPanel.element.querySelector('#foo\\.radio')
options = for label in radio.querySelectorAll 'label'
button = label.querySelector('input[type=radio][name="foo.radio"]')
[button.id, button.value, label.innerText]
expect(options).toEqual([['foo.radio[one]', 'one', 'One'], ['foo.radio[Two]', 'Two', 'Two']])
describe 'default settings', ->
beforeEach ->
config =
type: 'object'
properties:
haz:
name: 'haz'
title: 'Haz'
description: 'The haz setting'
type: 'string'
default: 'haz'
qux:
name: 'qux'
title: 'Qux'
description: 'The qux setting'
type: 'string'
default: 'a'
enum: [
{value: 'a', description: 'Alice'},
{value: 'b', description: 'Bob'}
]
testZero:
name: 'testZero'
title: 'Test Zero'
description: 'Setting for testing zero as a default'
type: 'integer'
default: 0
radio:
title: 'An enum with radio buttons'
radio: true
type: 'string'
default: 'Two'
enum: [
{value: 'one', description: 'One'}
'Two'
'Three'
]
atom.config.setSchema("foo", config)
atom.config.setDefaults("foo", gong: 'gong')
expect(_.size(atom.config.get('foo'))).toBe 5
settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false})
it 'ensures default stays default', ->
expect(settingsPanel.getDefault('foo.haz')).toBe 'haz'
expect(settingsPanel.isDefault('foo.haz')).toBe true
settingsPanel.set('foo.haz', 'haz')
expect(settingsPanel.isDefault('foo.haz')).toBe true
it 'can be overwritten', ->
expect(settingsPanel.getDefault('foo.haz')).toBe 'haz'
expect(settingsPanel.isDefault('foo.haz')).toBe true
settingsPanel.set('foo.haz', 'newhaz')
expect(settingsPanel.isDefault('foo.haz')).toBe false
expect(atom.config.get('foo.haz')).toBe 'newhaz'
it "ignores project-specific overrides", ->
atom.project.replace(
originPath: 'TEST'
config:
foo:
haz: 'newhaz'
)
expect(settingsPanel.isDefault('foo.haz')).toBe true
expect(atom.config.get('foo.haz')).toBe 'newhaz'
it 'has a tooltip showing the default value', ->
hazEditor = settingsPanel.element.querySelector('[id="foo.haz"]')
tooltips = atom.tooltips.findTooltips(hazEditor)
expect(tooltips).toHaveLength 1
title = tooltips[0].options.title
expect(title).toBe "Default: haz"
it 'has a tooltip showing the description of the default value', ->
quxEditor = settingsPanel.element.querySelector('[id="foo.qux"]')
tooltips = atom.tooltips.findTooltips(quxEditor)
expect(tooltips).toHaveLength 1
title = tooltips[0].options.title
expect(title).toBe "Default: Alice"
# Regression test for #783
it 'allows 0 to be a default', ->
zeroEditor = settingsPanel.element.querySelector('[id="foo.testZero"]')
expect(zeroEditor.getModel().getText()).toBe('')
expect(zeroEditor.getModel().getPlaceholderText()).toBe('Default: 0')
expect(settingsPanel.getDefault('foo.testZero')).toBe 0
expect(settingsPanel.isDefault('foo.testZero')).toBe true
settingsPanel.set('foo.testZero', 15)
expect(settingsPanel.isDefault('foo.testZero')).toBe false
settingsPanel.set('foo.testZero', 0)
expect(settingsPanel.isDefault('foo.testZero')).toBe true
it "selects the default choice for radio options", ->
expect(settingsPanel.getDefault 'foo.radio').toBe 'Two'
settingsPanel.set 'foo.radio', 'Two'
expect(settingsPanel.element.querySelector '#foo\\.radio\\[Two\\]').toBeChecked()
describe 'scoped settings', ->
beforeEach ->
schema =
scopes:
'.source.python':
default: 4
atom.config.setScopedDefaultsFromSchema('editor.tabLength', schema)
expect(atom.config.get('editor.tabLength')).toBe(2)
it 'displays the scoped default', ->
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.python'})
tabLengthEditor = settingsPanel.element.querySelector('[id="editor.tabLength"]')
expect(tabLengthEditor.getModel().getText()).toBe('')
expect(tabLengthEditor.getModel().getPlaceholderText()).toBe('Default: 4')
it 'allows the scoped setting to be changed to its normal default if the unscoped value is different', ->
atom.config.set('editor.tabLength', 8)
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.js'})
tabLengthEditor = settingsPanel.element.querySelector('[id="editor.tabLength"]')
expect(tabLengthEditor.getModel().getText()).toBe('')
expect(tabLengthEditor.getModel().getPlaceholderText()).toBe('Default: 8')
# This is the unscoped default, but it differs from the current unscoped value
settingsPanel.set('editor.tabLength', 2)
expect(tabLengthEditor.getModel().getText()).toBe('2')
expect(atom.config.get('editor.tabLength', {scope: ['source.js']})).toBe(2)
it 'allows the scoped setting to be changed to the unscoped default if it is different', ->
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.python'})
tabLengthEditor = settingsPanel.element.querySelector('[id="editor.tabLength"]')
expect(tabLengthEditor.getModel().getText()).toBe('')
expect(tabLengthEditor.getModel().getPlaceholderText()).toBe('Default: 4')
# This is the unscoped default, but it differs from the scoped default
settingsPanel.set('editor.tabLength', 2)
expect(tabLengthEditor.getModel().getText()).toBe('2')
expect(atom.config.get('editor.tabLength', {scope: ['source.python']})).toBe(2)
describe 'grouped settings', ->
beforeEach ->
config =
type: 'object'
properties:
barGroup:
type: 'object'
title: 'Bar group'
description: 'description of bar group'
properties:
bar:
title: 'Bar'
description: 'The bar setting'
type: 'boolean'
default: false
bazGroup:
type: 'object'
collapsed: true
properties:
baz:
title: 'Baz'
description: 'The baz setting'
type: 'boolean'
default: false
zing:
type: 'string'
default: ''
atom.config.setSchema('foo', config)
expect(_.size(atom.config.get('foo'))).toBe 3
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false})
it 'ensures that only grouped settings have a group title', ->
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength 1
controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group')
expect(controlGroups).toHaveLength 3
expect(controlGroups[0].querySelectorAll('.sub-section .sub-section-heading')).toHaveLength 1
expect(controlGroups[0].querySelector('.sub-section .sub-section-heading').textContent).toBe 'Bar group'
expect(controlGroups[0].querySelectorAll('.sub-section .sub-section-body')).toHaveLength 1
subsectionBody = controlGroups[0].querySelector('.sub-section .sub-section-body')
expect(subsectionBody.querySelectorAll('.control-group')).toHaveLength 1
expect(controlGroups[1].querySelectorAll('.sub-section .sub-section-heading')).toHaveLength 1
expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').textContent).toBe 'Baz Group'
expect(controlGroups[1].querySelectorAll('.sub-section .sub-section-body')).toHaveLength 1
subsectionBody = controlGroups[1].querySelector('.sub-section .sub-section-body')
expect(subsectionBody.querySelectorAll('.control-group')).toHaveLength 1
expect(controlGroups[2].querySelectorAll('.sub-section')).toHaveLength 0
expect(controlGroups[2].querySelectorAll('.sub-section-heading')).toHaveLength 0
it 'ensures grouped settings are collapsable', ->
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength 1
controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group')
expect(controlGroups).toHaveLength 3
# Bar group
expect(controlGroups[0].querySelectorAll('.sub-section .sub-section-heading')).toHaveLength 1
expect(controlGroups[0].querySelector('.sub-section .sub-section-heading').classList.contains('has-items')).toBe true
# Baz Group
expect(controlGroups[1].querySelectorAll('.sub-section .sub-section-heading')).toHaveLength 1
expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').classList.contains('has-items')).toBe true
# Should be already collapsed
expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').parentElement.classList.contains('collapsed')).toBe true
it 'ensures grouped settings can have a description', ->
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength 1
controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group')
expect(controlGroups).toHaveLength 3
expect(controlGroups[0].querySelectorAll('.sub-section > .setting-description')).toHaveLength 1
expect(controlGroups[0].querySelector('.sub-section > .setting-description').textContent).toBe 'description of bar group'
describe 'settings validation', ->
beforeEach ->
config =
type: 'object'
properties:
minMax:
name: 'minMax'
title: 'Min max'
description: 'The minMax setting'
type: 'integer'
default: 10
minimum: 1
maximum: 100
commaValueArray:
name: 'commaValueArray'
title: 'Comma value in array'
description: 'An array with a comma value'
type: 'array'
default: []
atom.config.setSchema('foo', config)
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false})
it 'prevents setting a value below the minimum', ->
minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]')
minMaxEditor.getModel().setText('0')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '1'
minMaxEditor.getModel().setText('-5')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '1'
it 'prevents setting a value above the maximum', ->
minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]')
minMaxEditor.getModel().setText('1000')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '100'
minMaxEditor.getModel().setText('10000')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '100'
it 'prevents setting a value that cannot be coerced to the correct type', ->
minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]')
minMaxEditor.getModel().setText('"abcde"')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '' # aka default
minMaxEditor.getModel().setText('15')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '15'
minMaxEditor.getModel().setText('"abcde"')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '15'
it 'allows setting a valid scoped value', ->
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false, scopeName: 'source.js'})
minMaxEditor = settingsPanel.element.querySelector('atom-text-editor')
minMaxEditor.getModel().setText('15')
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(minMaxEditor.getModel().getText()).toBe '15'
describe 'commaValueArray', ->
it 'comma in value is escaped', ->
commaValueArrayEditor = settingsPanel.element.querySelector('[id="foo.commaValueArray"]')
commaValueArrayEditor.getModel().setText('1, \\,, 2')
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(atom.config.get("foo.commaValueArray")).toEqual ['1', ',', '2']
commaValueArrayEditor.getModel().setText('1\\, 2')
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(atom.config.get('foo.commaValueArray')).toEqual ['1, 2']
commaValueArrayEditor.getModel().setText('1\\,')
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(atom.config.get('foo.commaValueArray')).toEqual ['1,']
commaValueArrayEditor.getModel().setText('\\, 2')
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay())
expect(atom.config.get('foo.commaValueArray')).toEqual [', 2']
it 'renders an escaped comma', ->
commaValueArrayEditor = settingsPanel.element.querySelector('[id="foo.commaValueArray"]')
atom.config.set('foo.commaValueArray', ['3', ',', '4'])
advanceClock(1000)
expect(commaValueArrayEditor.getModel().getText()).toBe '3, \\,, 4'
atom.config.set('foo.commaValueArray', ['3, 4'])
advanceClock(1000)
expect(commaValueArrayEditor.getModel().getText()).toBe '3\\, 4'
atom.config.set('foo.commaValueArray', ['3,'])
advanceClock(1000)
expect(commaValueArrayEditor.getModel().getText()).toBe '3\\,'
atom.config.set('foo.commaValueArray', [', 4'])
advanceClock(1000)
expect(commaValueArrayEditor.getModel().getText()).toBe '\\, 4'

View File

@ -1,18 +1,12 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS205: Consider reworking code to avoid use of IIFEs
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const SettingsPanel = require('../lib/settings-panel');
const _ = require('underscore-plus');
describe("SettingsPanel", function() {
describe("SettingsPanel", () => {
let settingsPanel = null;
describe("sorted settings", function() {
beforeEach(function() {
describe("sorted settings", () => {
beforeEach(() => {
const config = {
type: 'object',
properties: {
@ -66,10 +60,10 @@ describe("SettingsPanel", function() {
atom.config.setSchema("foo", config);
atom.config.setDefaults("foo", {gong: 'gong'});
expect(_.size(atom.config.get('foo'))).toBe(7);
return settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false});
settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false});
});
it("sorts settings by order and then alphabetically by the key", function() {
it("sorts settings by order and then alphabetically by the key", () => {
const settings = atom.config.get('foo');
expect(_.size(settings)).toBe(7);
const sortedSettings = settingsPanel.sortSettings("foo", settings);
@ -79,22 +73,22 @@ describe("SettingsPanel", function() {
expect(sortedSettings[3]).toBe('enum');
expect(sortedSettings[4]).toBe('gong');
expect(sortedSettings[5]).toBe('haz');
return expect(sortedSettings[6]).toBe('radio');
expect(sortedSettings[6]).toBe('radio');
});
it("gracefully deals with a null settings object", function() {
it("gracefully deals with a null settings object", () => {
const sortedSettings = settingsPanel.sortSettings("foo", null);
expect(sortedSettings).not.toBeNull;
return expect(_.size(sortedSettings)).toBe(0);
expect(_.size(sortedSettings)).toBe(0);
});
it("presents enum options with their descriptions", function() {
it("presents enum options with their descriptions", () => {
const select = settingsPanel.element.querySelector('#foo\\.enum');
const pairs = (Array.from(select.children).map((opt) => [opt.value, opt.innerText]));
return expect(pairs).toEqual([['one', 'One'], ['Two', 'Two']]);
expect(pairs).toEqual([['one', 'One'], ['Two', 'Two']]);
});
return it("presents radio options with their descriptions", function() {
it("presents radio options with their descriptions", () => {
const radio = settingsPanel.element.querySelector('#foo\\.radio');
const options = (() => {
const result = [];
@ -104,12 +98,12 @@ describe("SettingsPanel", function() {
}
return result;
})();
return expect(options).toEqual([['foo.radio[one]', 'one', 'One'], ['foo.radio[Two]', 'Two', 'Two']]);
expect(options).toEqual([['foo.radio[one]', 'one', 'One'], ['foo.radio[Two]', 'Two', 'Two']]);
});
});
describe('default settings', function() {
beforeEach(function() {
describe('default settings', () => {
beforeEach(() => {
const config = {
type: 'object',
properties: {
@ -154,25 +148,25 @@ describe("SettingsPanel", function() {
atom.config.setSchema("foo", config);
atom.config.setDefaults("foo", {gong: 'gong'});
expect(_.size(atom.config.get('foo'))).toBe(5);
return settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false});
settingsPanel = new SettingsPanel({namespace: "foo", includeTitle: false});
});
it('ensures default stays default', function() {
it('ensures default stays default', () => {
expect(settingsPanel.getDefault('foo.haz')).toBe('haz');
expect(settingsPanel.isDefault('foo.haz')).toBe(true);
settingsPanel.set('foo.haz', 'haz');
return expect(settingsPanel.isDefault('foo.haz')).toBe(true);
expect(settingsPanel.isDefault('foo.haz')).toBe(true);
});
it('can be overwritten', function() {
it('can be overwritten', () => {
expect(settingsPanel.getDefault('foo.haz')).toBe('haz');
expect(settingsPanel.isDefault('foo.haz')).toBe(true);
settingsPanel.set('foo.haz', 'newhaz');
expect(settingsPanel.isDefault('foo.haz')).toBe(false);
return expect(atom.config.get('foo.haz')).toBe('newhaz');
expect(atom.config.get('foo.haz')).toBe('newhaz');
});
it("ignores project-specific overrides", function() {
it("ignores project-specific overrides", () => {
atom.project.replace({
originPath: 'TEST',
config: {
@ -182,31 +176,31 @@ describe("SettingsPanel", function() {
}
});
expect(settingsPanel.isDefault('foo.haz')).toBe(true);
return expect(atom.config.get('foo.haz')).toBe('newhaz');
expect(atom.config.get('foo.haz')).toBe('newhaz');
});
it('has a tooltip showing the default value', function() {
it('has a tooltip showing the default value', () => {
const hazEditor = settingsPanel.element.querySelector('[id="foo.haz"]');
const tooltips = atom.tooltips.findTooltips(hazEditor);
expect(tooltips).toHaveLength(1);
const {
title
} = tooltips[0].options;
return expect(title).toBe("Default: haz");
expect(title).toBe("Default: haz");
});
it('has a tooltip showing the description of the default value', function() {
it('has a tooltip showing the description of the default value', () => {
const quxEditor = settingsPanel.element.querySelector('[id="foo.qux"]');
const tooltips = atom.tooltips.findTooltips(quxEditor);
expect(tooltips).toHaveLength(1);
const {
title
} = tooltips[0].options;
return expect(title).toBe("Default: Alice");
expect(title).toBe("Default: Alice");
});
// Regression test for #783
it('allows 0 to be a default', function() {
it('allows 0 to be a default', () => {
const zeroEditor = settingsPanel.element.querySelector('[id="foo.testZero"]');
expect(zeroEditor.getModel().getText()).toBe('');
expect(zeroEditor.getModel().getPlaceholderText()).toBe('Default: 0');
@ -218,17 +212,17 @@ describe("SettingsPanel", function() {
expect(settingsPanel.isDefault('foo.testZero')).toBe(false);
settingsPanel.set('foo.testZero', 0);
return expect(settingsPanel.isDefault('foo.testZero')).toBe(true);
expect(settingsPanel.isDefault('foo.testZero')).toBe(true);
});
it("selects the default choice for radio options", function() {
it("selects the default choice for radio options", () => {
expect(settingsPanel.getDefault('foo.radio')).toBe('Two');
settingsPanel.set('foo.radio', 'Two');
return expect(settingsPanel.element.querySelector('#foo\\.radio\\[Two\\]')).toBeChecked();
expect(settingsPanel.element.querySelector('#foo\\.radio\\[Two\\]')).toBeChecked();
});
return describe('scoped settings', function() {
beforeEach(function() {
describe('scoped settings', () => {
beforeEach(() => {
const schema = {
scopes: {
'.source.python': {
@ -238,17 +232,17 @@ describe("SettingsPanel", function() {
};
atom.config.setScopedDefaultsFromSchema('editor.tabLength', schema);
return expect(atom.config.get('editor.tabLength')).toBe(2);
expect(atom.config.get('editor.tabLength')).toBe(2);
});
it('displays the scoped default', function() {
it('displays the scoped default', () => {
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.python'});
const tabLengthEditor = settingsPanel.element.querySelector('[id="editor.tabLength"]');
expect(tabLengthEditor.getModel().getText()).toBe('');
return expect(tabLengthEditor.getModel().getPlaceholderText()).toBe('Default: 4');
expect(tabLengthEditor.getModel().getPlaceholderText()).toBe('Default: 4');
});
it('allows the scoped setting to be changed to its normal default if the unscoped value is different', function() {
it('allows the scoped setting to be changed to its normal default if the unscoped value is different', () => {
atom.config.set('editor.tabLength', 8);
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.js'});
@ -259,10 +253,10 @@ describe("SettingsPanel", function() {
// This is the unscoped default, but it differs from the current unscoped value
settingsPanel.set('editor.tabLength', 2);
expect(tabLengthEditor.getModel().getText()).toBe('2');
return expect(atom.config.get('editor.tabLength', {scope: ['source.js']})).toBe(2);
expect(atom.config.get('editor.tabLength', {scope: ['source.js']})).toBe(2);
});
return it('allows the scoped setting to be changed to the unscoped default if it is different', function() {
it('allows the scoped setting to be changed to the unscoped default if it is different', () => {
settingsPanel = new SettingsPanel({namespace: "editor", includeTitle: false, scopeName: '.source.python'});
const tabLengthEditor = settingsPanel.element.querySelector('[id="editor.tabLength"]');
expect(tabLengthEditor.getModel().getText()).toBe('');
@ -271,13 +265,13 @@ describe("SettingsPanel", function() {
// This is the unscoped default, but it differs from the scoped default
settingsPanel.set('editor.tabLength', 2);
expect(tabLengthEditor.getModel().getText()).toBe('2');
return expect(atom.config.get('editor.tabLength', {scope: ['source.python']})).toBe(2);
expect(atom.config.get('editor.tabLength', {scope: ['source.python']})).toBe(2);
});
});
});
describe('grouped settings', function() {
beforeEach(function() {
describe('grouped settings', () => {
beforeEach(() => {
const config = {
type: 'object',
properties: {
@ -314,10 +308,10 @@ describe("SettingsPanel", function() {
};
atom.config.setSchema('foo', config);
expect(_.size(atom.config.get('foo'))).toBe(3);
return settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false});
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false});
});
it('ensures that only grouped settings have a group title', function() {
it('ensures that only grouped settings have a group title', () => {
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength(1);
const controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group');
expect(controlGroups).toHaveLength(3);
@ -332,10 +326,10 @@ describe("SettingsPanel", function() {
subsectionBody = controlGroups[1].querySelector('.sub-section .sub-section-body');
expect(subsectionBody.querySelectorAll('.control-group')).toHaveLength(1);
expect(controlGroups[2].querySelectorAll('.sub-section')).toHaveLength(0);
return expect(controlGroups[2].querySelectorAll('.sub-section-heading')).toHaveLength(0);
expect(controlGroups[2].querySelectorAll('.sub-section-heading')).toHaveLength(0);
});
it('ensures grouped settings are collapsable', function() {
it('ensures grouped settings are collapsable', () => {
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength(1);
const controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group');
expect(controlGroups).toHaveLength(3);
@ -346,20 +340,20 @@ describe("SettingsPanel", function() {
expect(controlGroups[1].querySelectorAll('.sub-section .sub-section-heading')).toHaveLength(1);
expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').classList.contains('has-items')).toBe(true);
// Should be already collapsed
return expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').parentElement.classList.contains('collapsed')).toBe(true);
expect(controlGroups[1].querySelector('.sub-section .sub-section-heading').parentElement.classList.contains('collapsed')).toBe(true);
});
return it('ensures grouped settings can have a description', function() {
it('ensures grouped settings can have a description', () => {
expect(settingsPanel.element.querySelectorAll('.section-container > .section-body')).toHaveLength(1);
const controlGroups = settingsPanel.element.querySelectorAll('.section-body > .control-group');
expect(controlGroups).toHaveLength(3);
expect(controlGroups[0].querySelectorAll('.sub-section > .setting-description')).toHaveLength(1);
return expect(controlGroups[0].querySelector('.sub-section > .setting-description').textContent).toBe('description of bar group');
expect(controlGroups[0].querySelector('.sub-section > .setting-description').textContent).toBe('description of bar group');
});
});
return describe('settings validation', function() {
beforeEach(function() {
describe('settings validation', () => {
beforeEach(() => {
const config = {
type: 'object',
properties: {
@ -383,10 +377,10 @@ describe("SettingsPanel", function() {
};
atom.config.setSchema('foo', config);
return settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false});
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false});
});
it('prevents setting a value below the minimum', function() {
it('prevents setting a value below the minimum', () => {
const minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]');
minMaxEditor.getModel().setText('0');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
@ -394,10 +388,10 @@ describe("SettingsPanel", function() {
minMaxEditor.getModel().setText('-5');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
return expect(minMaxEditor.getModel().getText()).toBe('1');
expect(minMaxEditor.getModel().getText()).toBe('1');
});
it('prevents setting a value above the maximum', function() {
it('prevents setting a value above the maximum', () => {
const minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]');
minMaxEditor.getModel().setText('1000');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
@ -405,10 +399,10 @@ describe("SettingsPanel", function() {
minMaxEditor.getModel().setText('10000');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
return expect(minMaxEditor.getModel().getText()).toBe('100');
expect(minMaxEditor.getModel().getText()).toBe('100');
});
it('prevents setting a value that cannot be coerced to the correct type', function() {
it('prevents setting a value that cannot be coerced to the correct type', () => {
const minMaxEditor = settingsPanel.element.querySelector('[id="foo.minMax"]');
minMaxEditor.getModel().setText('"abcde"');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
@ -420,19 +414,19 @@ describe("SettingsPanel", function() {
minMaxEditor.getModel().setText('"abcde"');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
return expect(minMaxEditor.getModel().getText()).toBe('15');
expect(minMaxEditor.getModel().getText()).toBe('15');
});
it('allows setting a valid scoped value', function() {
it('allows setting a valid scoped value', () => {
settingsPanel = new SettingsPanel({namespace: 'foo', includeTitle: false, scopeName: 'source.js'});
const minMaxEditor = settingsPanel.element.querySelector('atom-text-editor');
minMaxEditor.getModel().setText('15');
advanceClock(minMaxEditor.getModel().getBuffer().getStoppedChangingDelay());
return expect(minMaxEditor.getModel().getText()).toBe('15');
expect(minMaxEditor.getModel().getText()).toBe('15');
});
return describe('commaValueArray', function() {
it('comma in value is escaped', function() {
describe('commaValueArray', () => {
it('comma in value is escaped', () => {
const commaValueArrayEditor = settingsPanel.element.querySelector('[id="foo.commaValueArray"]');
commaValueArrayEditor.getModel().setText('1, \\,, 2');
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay());
@ -448,10 +442,10 @@ describe("SettingsPanel", function() {
commaValueArrayEditor.getModel().setText('\\, 2');
advanceClock(commaValueArrayEditor.getModel().getBuffer().getStoppedChangingDelay());
return expect(atom.config.get('foo.commaValueArray')).toEqual([', 2']);
expect(atom.config.get('foo.commaValueArray')).toEqual([', 2']);
});
return it('renders an escaped comma', function() {
it('renders an escaped comma', () => {
const commaValueArrayEditor = settingsPanel.element.querySelector('[id="foo.commaValueArray"]');
atom.config.set('foo.commaValueArray', ['3', ',', '4']);
advanceClock(1000);
@ -467,7 +461,7 @@ describe("SettingsPanel", function() {
atom.config.set('foo.commaValueArray', [', 4']);
advanceClock(1000);
return expect(commaValueArrayEditor.getModel().getText()).toBe('\\, 4');
expect(commaValueArrayEditor.getModel().getText()).toBe('\\, 4');
});
});
});

View File

@ -1,519 +0,0 @@
path = require 'path'
main = require '../lib/main'
PackageManager = require '../lib/package-manager'
SettingsView = require '../lib/settings-view'
SnippetsProvider =
getSnippets: -> {}
describe "SettingsView", ->
settingsView = null
packageManager = new PackageManager()
beforeEach ->
settingsView = main.createSettingsView({packageManager: packageManager, snippetsProvider: SnippetsProvider})
spyOn(settingsView, "initializePanels").andCallThrough()
window.advanceClock(10000)
waitsFor ->
settingsView.initializePanels.callCount > 0
describe "serialization", ->
it "remembers which panel was visible", ->
settingsView.showPanel('Themes')
newSettingsView = main.createSettingsView(settingsView.serialize())
settingsView.destroy()
jasmine.attachToDOM(newSettingsView.element)
newSettingsView.initializePanels()
expect(newSettingsView.activePanel).toEqual {name: 'Themes', options: {}}
it "shows the previously active panel if it is added after deserialization", ->
settingsView.addCorePanel('Panel 1', 'panel-1', ->
div = document.createElement('div')
div.id = 'panel-1'
{
element: div,
show: -> div.style.display = '',
focus: -> div.focus(),
destroy: -> div.remove()
}
)
settingsView.showPanel('Panel 1')
newSettingsView = main.createSettingsView(settingsView.serialize())
newSettingsView.addPanel('Panel 1', ->
div = document.createElement('div')
div.id = 'panel-1'
{
element: div,
show: -> div.style.display = '',
focus: -> div.focus(),
destroy: -> div.remove()
}
)
newSettingsView.initializePanels()
jasmine.attachToDOM(newSettingsView.element)
expect(newSettingsView.activePanel).toEqual {name: 'Panel 1', options: {}}
it "shows the Settings panel if the last saved active panel name no longer exists", ->
settingsView.addCorePanel('Panel 1', 'panel1', ->
div = document.createElement('div')
div.id = 'panel-1'
{
element: div,
show: -> div.style.display = '',
focus: -> div.focus(),
destroy: -> div.remove()
}
)
settingsView.showPanel('Panel 1')
newSettingsView = main.createSettingsView(settingsView.serialize())
settingsView.destroy()
jasmine.attachToDOM(newSettingsView.element)
newSettingsView.initializePanels()
expect(newSettingsView.activePanel).toEqual {name: 'Core', options: {}}
it "serializes the active panel name even when the panels were never initialized", ->
settingsView.showPanel('Themes')
settingsView2 = main.createSettingsView(settingsView.serialize())
settingsView3 = main.createSettingsView(settingsView2.serialize())
jasmine.attachToDOM(settingsView3.element)
settingsView3.initializePanels()
expect(settingsView3.activePanel).toEqual {name: 'Themes', options: {}}
describe ".addCorePanel(name, iconName, view)", ->
it "adds a menu entry to the left and a panel that can be activated by clicking it", ->
settingsView.addCorePanel('Panel 1', 'panel1', ->
div = document.createElement('div')
div.id = 'panel-1'
{
element: div,
show: -> div.style.display = '',
focus: -> div.focus(),
destroy: -> div.remove()
}
)
settingsView.addCorePanel('Panel 2', 'panel2', ->
div = document.createElement('div')
div.id = 'panel-2'
{
element: div,
show: -> div.style.display = '',
focus: -> div.focus(),
destroy: -> div.remove()
}
)
expect(settingsView.refs.panelMenu.querySelector('li[name="Panel 1"]')).toExist()
expect(settingsView.refs.panelMenu.querySelector('li[name="Panel 2"]')).toExist()
#expect(settingsView.refs.panelMenu.children[1]).toHaveClass 'active' # TODO FIX
jasmine.attachToDOM(settingsView.element)
settingsView.refs.panelMenu.querySelector('li[name="Panel 1"] a').click()
expect(settingsView.refs.panelMenu.querySelectorAll('.active').length).toBe 1
expect(settingsView.refs.panelMenu.querySelector('li[name="Panel 1"]')).toHaveClass('active')
expect(settingsView.refs.panels.querySelector('#panel-1')).toBeVisible()
expect(settingsView.refs.panels.querySelector('#panel-2')).not.toExist()
settingsView.refs.panelMenu.querySelector('li[name="Panel 2"] a').click()
expect(settingsView.refs.panelMenu.querySelectorAll('.active').length).toBe 1
expect(settingsView.refs.panelMenu.querySelector('li[name="Panel 2"]')).toHaveClass('active')
expect(settingsView.refs.panels.querySelector('#panel-1')).toBeHidden()
expect(settingsView.refs.panels.querySelector('#panel-2')).toBeVisible()
describe "when the package is activated", ->
openWithCommand = (command) ->
waitsFor (done) ->
openSubscription = atom.workspace.onDidOpen ->
openSubscription.dispose()
done()
atom.commands.dispatch(atom.views.getView(atom.workspace), command)
beforeEach ->
jasmine.attachToDOM(atom.views.getView(atom.workspace))
waitsForPromise ->
atom.packages.activatePackage('settings-view')
describe "when the settings view is opened with a settings-view:* command", ->
beforeEach ->
settingsView = null
describe "settings-view:open", ->
it "opens the settings view", ->
openWithCommand('settings-view:open')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Core', options: {}
it "always open existing item in workspace", ->
center = atom.workspace.getCenter()
[pane1, pane2] = []
waitsForPromise -> atom.workspace.open(null, split: 'right')
runs ->
expect(center.getPanes()).toHaveLength(2)
[pane1, pane2] = center.getPanes()
expect(atom.workspace.getActivePane()).toBe(pane2)
openWithCommand('settings-view:open')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel).toEqual name: 'Core', options: {}
expect(atom.workspace.getActivePane()).toBe(pane2)
runs ->
pane1.activate()
openWithCommand('settings-view:open')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel).toEqual name: 'Core', options: {}
expect(atom.workspace.getActivePane()).toBe(pane2)
describe "settings-view:core", ->
it "opens the core settings view", ->
openWithCommand('settings-view:editor')
runs ->
openWithCommand('settings-view:core')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Core', options: uri: 'atom://config/core'
describe "settings-view:editor", ->
it "opens the editor settings view", ->
openWithCommand('settings-view:editor')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Editor', options: uri: 'atom://config/editor'
describe "settings-view:show-keybindings", ->
it "opens the settings view to the keybindings page", ->
openWithCommand('settings-view:show-keybindings')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Keybindings', options: uri: 'atom://config/keybindings'
describe "settings-view:change-themes", ->
it "opens the settings view to the themes page", ->
openWithCommand('settings-view:change-themes')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Themes', options: uri: 'atom://config/themes'
describe "settings-view:uninstall-themes", ->
it "opens the settings view to the themes page", ->
openWithCommand('settings-view:uninstall-themes')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Themes', options: uri: 'atom://config/themes'
describe "settings-view:uninstall-packages", ->
it "opens the settings view to the install page", ->
openWithCommand('settings-view:uninstall-packages')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Packages', options: uri: 'atom://config/packages'
describe "settings-view:install-packages-and-themes", ->
it "opens the settings view to the install page", ->
openWithCommand('settings-view:install-packages-and-themes')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Install', options: uri: 'atom://config/install'
describe "settings-view:check-for-package-updates", ->
it "opens the settings view to the install page", ->
openWithCommand('settings-view:check-for-package-updates')
runs ->
expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual name: 'Updates', options: uri: 'atom://config/updates'
describe "when atom.workspace.open() is used with a config URI", ->
focusIsWithinActivePanel = ->
activePanel = settingsView.panelsByName[settingsView.activePanel.name]
activePanel.element is document.activeElement or activePanel.element.contains(document.activeElement)
expectActivePanelToBeKeyboardScrollable = ->
activePanel = settingsView.panelsByName[settingsView.activePanel.name]
spyOn(activePanel, 'pageDown')
atom.commands.dispatch(activePanel.element, 'core:page-down')
expect(activePanel.pageDown).toHaveBeenCalled()
spyOn(activePanel, 'pageUp')
atom.commands.dispatch(activePanel.element, 'core:page-up')
expect(activePanel.pageUp).toHaveBeenCalled()
beforeEach ->
settingsView = null
it "opens the settings to the correct panel with atom://config/<panel-name> and that panel is keyboard-scrollable", ->
waitsForPromise ->
atom.workspace.open('atom://config').then (s) -> settingsView = s
waitsFor (done) -> process.nextTick(done)
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Core', options: {}
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/editor').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Editor', options: uri: 'atom://config/editor'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/keybindings').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Keybindings', options: uri: 'atom://config/keybindings'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/packages').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Packages', options: uri: 'atom://config/packages'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/themes').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Themes', options: uri: 'atom://config/themes'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/updates').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Updates', options: uri: 'atom://config/updates'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
waitsForPromise ->
atom.workspace.open('atom://config/install').then (s) -> settingsView = s
hasSystemPanel = false
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Install', options: uri: 'atom://config/install'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
hasSystemPanel = settingsView.panelsByName['System']?
if hasSystemPanel
waitsForPromise ->
atom.workspace.open('atom://config/system').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'System', options: uri: 'atom://config/system'
expect(focusIsWithinActivePanel()).toBe true
expectActivePanelToBeKeyboardScrollable()
it "opens the package settings view with atom://config/packages/<package-name>", ->
waitsForPromise ->
atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-readme'))
waitsForPromise ->
atom.workspace.open('atom://config/packages/package-with-readme').then (s) -> settingsView = s
waitsFor (done) -> process.nextTick(done)
runs ->
expect(settingsView.activePanel)
.toEqual name: 'package-with-readme', options: {
uri: 'atom://config/packages/package-with-readme',
pack:
name: 'package-with-readme'
metadata:
name: 'package-with-readme'
back: 'Packages'
}
it "doesn't use cached package detail when package re-activated and opnes the package view with atom://config/packages/<package-name>", ->
[detailInitial, detailAfterReactivate] = []
waitsForPromise ->
atom.packages.activate()
new Promise (resolve) -> atom.packages.onDidActivateInitialPackages(resolve)
waitsForPromise ->
atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-readme'))
waitsForPromise ->
atom.workspace.open('atom://config/packages/package-with-readme').then (s) -> settingsView = s
waitsFor (done) -> process.nextTick(done)
runs ->
detailInitial = settingsView.getOrCreatePanel('package-with-readme')
expect(settingsView.getOrCreatePanel('package-with-readme')).toBe detailInitial
waitsForPromise ->
atom.packages.deactivatePackage('package-with-readme')
waitsForPromise ->
atom.packages.activatePackage(path.join(__dirname, 'fixtures', 'package-with-readme'))
waitsForPromise ->
atom.workspace.open('atom://config/packages/package-with-readme')
runs ->
detailAfterReactivate = settingsView.getOrCreatePanel('package-with-readme')
expect(settingsView.getOrCreatePanel('package-with-readme')).toBe detailAfterReactivate
expect(detailInitial).toBeTruthy()
expect(detailAfterReactivate).toBeTruthy()
expect(detailInitial).not.toBe(detailAfterReactivate)
it "passes the URI to a pane's beforeShow() method on settings view initialization", ->
InstallPanel = require '../lib/install-panel'
spyOn(InstallPanel::, 'beforeShow')
waitsForPromise ->
atom.workspace.open('atom://config/install/package:something').then (s) -> settingsView = s
waitsFor ->
settingsView.activePanel?
, 'The activePanel should be set', 5000
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Install', options: uri: 'atom://config/install/package:something'
expect(InstallPanel::beforeShow).toHaveBeenCalledWith {uri: 'atom://config/install/package:something'}
it "passes the URI to a pane's beforeShow() method after initialization", ->
InstallPanel = require '../lib/install-panel'
spyOn(InstallPanel::, 'beforeShow')
waitsForPromise ->
atom.workspace.open('atom://config').then (s) -> settingsView = s
waitsFor (done) -> process.nextTick(done)
runs ->
expect(settingsView.activePanel).toEqual {name: 'Core', options: {}}
waitsForPromise ->
atom.workspace.open('atom://config/install/package:something').then (s) -> settingsView = s
waits 1
runs ->
expect(settingsView.activePanel)
.toEqual name: 'Install', options: uri: 'atom://config/install/package:something'
expect(InstallPanel::beforeShow).toHaveBeenCalledWith {uri: 'atom://config/install/package:something'}
describe "when the package is then deactivated", ->
beforeEach ->
settingsView = null
it "calls the dispose method on all panels", ->
openWithCommand('settings-view:open')
waitsFor (done) -> process.nextTick(done)
runs ->
settingsView = atom.workspace.getActivePaneItem()
panels = [
settingsView.getOrCreatePanel('Core')
settingsView.getOrCreatePanel('Editor')
settingsView.getOrCreatePanel('Keybindings')
settingsView.getOrCreatePanel('Packages')
settingsView.getOrCreatePanel('Themes')
settingsView.getOrCreatePanel('Updates')
settingsView.getOrCreatePanel('Install')
]
systemPanel = settingsView.getOrCreatePanel('System')
if systemPanel?
panels.push systemPanel
for panel in panels
if panel.dispose
spyOn(panel, 'dispose')
else
spyOn(panel, 'destroy')
waitsForPromise ->
Promise.resolve(atom.packages.deactivatePackage('settings-view')) # Ensure works on promise and non-promise versions
runs ->
for panel in panels
if panel.dispose
expect(panel.dispose).toHaveBeenCalled()
else
expect(panel.destroy).toHaveBeenCalled()
return
describe "when an installed package is clicked from the Install panel", ->
it "displays the package details", ->
waitsFor ->
atom.packages.activatePackage('settings-view')
runs ->
settingsView.packageManager.getClient()
spyOn(settingsView.packageManager.client, 'featuredPackages').andCallFake (callback) ->
callback(null, [{name: 'settings-view'}])
settingsView.showPanel('Install')
waitsFor ->
settingsView.element.querySelectorAll('.package-card:not(.hidden)').length > 0
runs ->
settingsView.element.querySelectorAll('.package-card:not(.hidden)')[0].click()
packageDetail = settingsView.element.querySelector('.package-detail .active')
expect(packageDetail.textContent).toBe 'Settings View'
describe "when the active theme has settings", ->
panel = null
beforeEach ->
atom.packages.packageDirPaths.push(path.join(__dirname, 'fixtures'))
atom.packages.loadPackage('ui-theme-with-config')
atom.packages.loadPackage('syntax-theme-with-config')
atom.config.set('core.themes', ['ui-theme-with-config', 'syntax-theme-with-config'])
reloadedHandler = jasmine.createSpy('reloadedHandler')
atom.themes.onDidChangeActiveThemes(reloadedHandler)
atom.themes.activatePackages()
waitsFor "themes to be reloaded", ->
reloadedHandler.callCount is 1
runs ->
settingsView.showPanel('Themes')
panel = settingsView.element.querySelector('.themes-panel')
afterEach ->
atom.themes.unwatchUserStylesheet()
describe "when the UI theme's settings button is clicked", ->
it "navigates to that theme's detail view", ->
jasmine.attachToDOM(settingsView.element)
expect(panel.querySelector('.active-theme-settings')).toBeVisible()
panel.querySelector('.active-theme-settings').click()
packageDetail = settingsView.element.querySelector('.package-detail li.active')
expect(packageDetail.textContent).toBe 'Ui Theme With Config'
describe "when the syntax theme's settings button is clicked", ->
it "navigates to that theme's detail view", ->
jasmine.attachToDOM(settingsView.element)
expect(panel.querySelector('.active-syntax-settings')).toBeVisible()
panel.querySelector('.active-syntax-settings').click()
packageDetail = settingsView.element.querySelector('.package-detail li.active')
expect(packageDetail.textContent).toBe 'Syntax Theme With Config'

View File

@ -1,10 +1,4 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const main = require('../lib/main');
const PackageManager = require('../lib/package-manager');
@ -20,7 +14,7 @@ describe("SettingsView", function() {
settingsView = main.createSettingsView({packageManager, snippetsProvider: SnippetsProvider});
spyOn(settingsView, "initializePanels").andCallThrough();
window.advanceClock(10000);
return waitsFor(() => settingsView.initializePanels.callCount > 0);
waitsFor(() => settingsView.initializePanels.callCount > 0);
});
describe("serialization", function() {
@ -30,7 +24,7 @@ describe("SettingsView", function() {
settingsView.destroy();
jasmine.attachToDOM(newSettingsView.element);
newSettingsView.initializePanels();
return expect(newSettingsView.activePanel).toEqual({name: 'Themes', options: {}});
expect(newSettingsView.activePanel).toEqual({name: 'Themes', options: {}});
});
it("shows the previously active panel if it is added after deserialization", function() {
@ -58,7 +52,7 @@ describe("SettingsView", function() {
});
newSettingsView.initializePanels();
jasmine.attachToDOM(newSettingsView.element);
return expect(newSettingsView.activePanel).toEqual({name: 'Panel 1', options: {}});
expect(newSettingsView.activePanel).toEqual({name: 'Panel 1', options: {}});
});
it("shows the Settings panel if the last saved active panel name no longer exists", function() {
@ -77,16 +71,16 @@ describe("SettingsView", function() {
settingsView.destroy();
jasmine.attachToDOM(newSettingsView.element);
newSettingsView.initializePanels();
return expect(newSettingsView.activePanel).toEqual({name: 'Core', options: {}});
expect(newSettingsView.activePanel).toEqual({name: 'Core', options: {}});
});
return it("serializes the active panel name even when the panels were never initialized", function() {
it("serializes the active panel name even when the panels were never initialized", function() {
settingsView.showPanel('Themes');
const settingsView2 = main.createSettingsView(settingsView.serialize());
const settingsView3 = main.createSettingsView(settingsView2.serialize());
jasmine.attachToDOM(settingsView3.element);
settingsView3.initializePanels();
return expect(settingsView3.activePanel).toEqual({name: 'Themes', options: {}});
expect(settingsView3.activePanel).toEqual({name: 'Themes', options: {}});
});
});
@ -126,7 +120,7 @@ describe("SettingsView", function() {
expect(settingsView.refs.panelMenu.querySelectorAll('.active').length).toBe(1);
expect(settingsView.refs.panelMenu.querySelector('li[name="Panel 2"]')).toHaveClass('active');
expect(settingsView.refs.panels.querySelector('#panel-1')).toBeHidden();
return expect(settingsView.refs.panels.querySelector('#panel-2')).toBeVisible();
expect(settingsView.refs.panels.querySelector('#panel-2')).toBeVisible();
}));
describe("when the package is activated", function() {
@ -140,7 +134,7 @@ describe("SettingsView", function() {
beforeEach(function() {
jasmine.attachToDOM(atom.views.getView(atom.workspace));
return waitsForPromise(() => atom.packages.activatePackage('settings-view'));
waitsForPromise(() => atom.packages.activatePackage('settings-view'));
});
describe("when the settings view is opened with a settings-view:* command", function() {
@ -149,11 +143,11 @@ describe("SettingsView", function() {
describe("settings-view:open", function() {
it("opens the settings view", function() {
openWithCommand('settings-view:open');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Core', options: {}}));
});
return it("always open existing item in workspace", function() {
it("always open existing item in workspace", function() {
const center = atom.workspace.getCenter();
let [pane1, pane2] = [];
@ -161,23 +155,23 @@ describe("SettingsView", function() {
runs(function() {
expect(center.getPanes()).toHaveLength(2);
[pane1, pane2] = center.getPanes();
return expect(atom.workspace.getActivePane()).toBe(pane2);
expect(atom.workspace.getActivePane()).toBe(pane2);
});
openWithCommand('settings-view:open');
runs(function() {
expect(atom.workspace.getActivePaneItem().activePanel).toEqual({name: 'Core', options: {}});
return expect(atom.workspace.getActivePane()).toBe(pane2);
expect(atom.workspace.getActivePane()).toBe(pane2);
});
runs(() => pane1.activate());
openWithCommand('settings-view:open');
return runs(function() {
runs(function() {
expect(atom.workspace.getActivePaneItem().activePanel).toEqual({name: 'Core', options: {}});
return expect(atom.workspace.getActivePane()).toBe(pane2);
expect(atom.workspace.getActivePane()).toBe(pane2);
});
});
});
@ -185,49 +179,49 @@ describe("SettingsView", function() {
describe("settings-view:core", () => it("opens the core settings view", function() {
openWithCommand('settings-view:editor');
runs(() => openWithCommand('settings-view:core'));
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Core', options: {uri: 'atom://config/core'}}));
}));
describe("settings-view:editor", () => it("opens the editor settings view", function() {
openWithCommand('settings-view:editor');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Editor', options: {uri: 'atom://config/editor'}}));
}));
describe("settings-view:show-keybindings", () => it("opens the settings view to the keybindings page", function() {
openWithCommand('settings-view:show-keybindings');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Keybindings', options: {uri: 'atom://config/keybindings'}}));
}));
describe("settings-view:change-themes", () => it("opens the settings view to the themes page", function() {
openWithCommand('settings-view:change-themes');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Themes', options: {uri: 'atom://config/themes'}}));
}));
describe("settings-view:uninstall-themes", () => it("opens the settings view to the themes page", function() {
openWithCommand('settings-view:uninstall-themes');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Themes', options: {uri: 'atom://config/themes'}}));
}));
describe("settings-view:uninstall-packages", () => it("opens the settings view to the install page", function() {
openWithCommand('settings-view:uninstall-packages');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Packages', options: {uri: 'atom://config/packages'}}));
}));
describe("settings-view:install-packages-and-themes", () => it("opens the settings view to the install page", function() {
openWithCommand('settings-view:install-packages-and-themes');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Install', options: {uri: 'atom://config/install'}}));
}));
return describe("settings-view:check-for-package-updates", () => it("opens the settings view to the install page", function() {
describe("settings-view:check-for-package-updates", () => it("opens the settings view to the install page", function() {
openWithCommand('settings-view:check-for-package-updates');
return runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
runs(() => expect(atom.workspace.getActivePaneItem().activePanel)
.toEqual({name: 'Updates', options: {uri: 'atom://config/updates'}}));
}));
});
@ -245,7 +239,7 @@ describe("SettingsView", function() {
expect(activePanel.pageDown).toHaveBeenCalled();
spyOn(activePanel, 'pageUp');
atom.commands.dispatch(activePanel.element, 'core:page-up');
return expect(activePanel.pageUp).toHaveBeenCalled();
expect(activePanel.pageUp).toHaveBeenCalled();
};
beforeEach(() => settingsView = null);
@ -258,7 +252,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Core', options: {}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/editor').then(s => settingsView = s));
@ -268,7 +262,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Editor', options: {uri: 'atom://config/editor'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/keybindings').then(s => settingsView = s));
@ -278,7 +272,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Keybindings', options: {uri: 'atom://config/keybindings'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/packages').then(s => settingsView = s));
@ -288,7 +282,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Packages', options: {uri: 'atom://config/packages'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/themes').then(s => settingsView = s));
@ -298,7 +292,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Themes', options: {uri: 'atom://config/themes'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/updates').then(s => settingsView = s));
@ -308,7 +302,7 @@ describe("SettingsView", function() {
expect(settingsView.activePanel)
.toEqual({name: 'Updates', options: {uri: 'atom://config/updates'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
waitsForPromise(() => atom.workspace.open('atom://config/install').then(s => settingsView = s));
@ -327,11 +321,11 @@ describe("SettingsView", function() {
waitsForPromise(() => atom.workspace.open('atom://config/system').then(s => settingsView = s));
waits(1);
return runs(function() {
runs(function() {
expect(settingsView.activePanel)
.toEqual({name: 'System', options: {uri: 'atom://config/system'}});
expect(focusIsWithinActivePanel()).toBe(true);
return expectActivePanelToBeKeyboardScrollable();
expectActivePanelToBeKeyboardScrollable();
});
}
});
@ -342,7 +336,7 @@ describe("SettingsView", function() {
waitsForPromise(() => atom.workspace.open('atom://config/packages/package-with-readme').then(s => settingsView = s));
waitsFor(done => process.nextTick(done));
return runs(() => expect(settingsView.activePanel)
runs(() => expect(settingsView.activePanel)
.toEqual({name: 'package-with-readme', options: {
uri: 'atom://config/packages/package-with-readme',
pack: {
@ -371,7 +365,7 @@ describe("SettingsView", function() {
runs(function() {
detailInitial = settingsView.getOrCreatePanel('package-with-readme');
return expect(settingsView.getOrCreatePanel('package-with-readme')).toBe(detailInitial);
expect(settingsView.getOrCreatePanel('package-with-readme')).toBe(detailInitial);
});
waitsForPromise(() => atom.packages.deactivatePackage('package-with-readme'));
@ -380,12 +374,12 @@ describe("SettingsView", function() {
waitsForPromise(() => atom.workspace.open('atom://config/packages/package-with-readme'));
return runs(function() {
runs(function() {
detailAfterReactivate = settingsView.getOrCreatePanel('package-with-readme');
expect(settingsView.getOrCreatePanel('package-with-readme')).toBe(detailAfterReactivate);
expect(detailInitial).toBeTruthy();
expect(detailAfterReactivate).toBeTruthy();
return expect(detailInitial).not.toBe(detailAfterReactivate);
expect(detailInitial).not.toBe(detailAfterReactivate);
});
});
@ -398,13 +392,13 @@ describe("SettingsView", function() {
waitsFor(() => settingsView.activePanel != null
, 'The activePanel should be set', 5000);
return runs(function() {
runs(function() {
expect(settingsView.activePanel)
.toEqual({name: 'Install', options: {uri: 'atom://config/install/package:something'}});
return expect(InstallPanel.prototype.beforeShow).toHaveBeenCalledWith({uri: 'atom://config/install/package:something'});});
expect(InstallPanel.prototype.beforeShow).toHaveBeenCalledWith({uri: 'atom://config/install/package:something'});});
});
return it("passes the URI to a pane's beforeShow() method after initialization", function() {
it("passes the URI to a pane's beforeShow() method after initialization", function() {
const InstallPanel = require('../lib/install-panel');
spyOn(InstallPanel.prototype, 'beforeShow');
@ -417,22 +411,22 @@ describe("SettingsView", function() {
waitsForPromise(() => atom.workspace.open('atom://config/install/package:something').then(s => settingsView = s));
waits(1);
return runs(function() {
runs(function() {
expect(settingsView.activePanel)
.toEqual({name: 'Install', options: {uri: 'atom://config/install/package:something'}});
return expect(InstallPanel.prototype.beforeShow).toHaveBeenCalledWith({uri: 'atom://config/install/package:something'});});
expect(InstallPanel.prototype.beforeShow).toHaveBeenCalledWith({uri: 'atom://config/install/package:something'});});
});
});
return describe("when the package is then deactivated", function() {
describe("when the package is then deactivated", function() {
beforeEach(() => settingsView = null);
return it("calls the dispose method on all panels", function() {
it("calls the dispose method on all panels", function() {
openWithCommand('settings-view:open');
waitsFor(done => process.nextTick(done));
return runs(function() {
runs(function() {
let panel;
settingsView = atom.workspace.getActivePaneItem();
const panels = [
@ -458,7 +452,7 @@ describe("SettingsView", function() {
waitsForPromise(() => Promise.resolve(atom.packages.deactivatePackage('settings-view'))); // Ensure works on promise and non-promise versions
return runs(function() {
runs(function() {
for (panel of Array.from(panels)) {
if (panel.dispose) {
expect(panel.dispose).toHaveBeenCalled();
@ -484,15 +478,15 @@ describe("SettingsView", function() {
waitsFor(() => settingsView.element.querySelectorAll('.package-card:not(.hidden)').length > 0);
return runs(function() {
runs(function() {
settingsView.element.querySelectorAll('.package-card:not(.hidden)')[0].click();
const packageDetail = settingsView.element.querySelector('.package-detail .active');
return expect(packageDetail.textContent).toBe('Settings View');
expect(packageDetail.textContent).toBe('Settings View');
});
}));
return describe("when the active theme has settings", function() {
describe("when the active theme has settings", function() {
let panel = null;
beforeEach(function() {
@ -507,7 +501,7 @@ describe("SettingsView", function() {
waitsFor("themes to be reloaded", () => reloadedHandler.callCount === 1);
return runs(function() {
runs(function() {
settingsView.showPanel('Themes');
return panel = settingsView.element.querySelector('.themes-panel');
});
@ -521,16 +515,16 @@ describe("SettingsView", function() {
panel.querySelector('.active-theme-settings').click();
const packageDetail = settingsView.element.querySelector('.package-detail li.active');
return expect(packageDetail.textContent).toBe('Ui Theme With Config');
expect(packageDetail.textContent).toBe('Ui Theme With Config');
}));
return describe("when the syntax theme's settings button is clicked", () => it("navigates to that theme's detail view", function() {
describe("when the syntax theme's settings button is clicked", () => it("navigates to that theme's detail view", function() {
jasmine.attachToDOM(settingsView.element);
expect(panel.querySelector('.active-syntax-settings')).toBeVisible();
panel.querySelector('.active-syntax-settings').click();
const packageDetail = settingsView.element.querySelector('.package-detail li.active');
return expect(packageDetail.textContent).toBe('Syntax Theme With Config');
expect(packageDetail.textContent).toBe('Syntax Theme With Config');
}));
});
});

View File

@ -1,208 +0,0 @@
path = require 'path'
fs = require 'fs'
CSON = require 'season'
PackageManager = require '../lib/package-manager'
ThemesPanel = require '../lib/themes-panel'
describe "ThemesPanel", ->
[panel, packageManager, reloadedHandler] = []
settingsView = null
beforeEach ->
atom.packages.loadPackage('atom-light-ui')
atom.packages.loadPackage('atom-dark-ui')
atom.packages.loadPackage('atom-light-syntax')
atom.packages.loadPackage('atom-dark-syntax')
atom.packages.packageDirPaths.push(path.join(__dirname, 'fixtures'))
atom.config.set('core.themes', ['atom-dark-ui', 'atom-dark-syntax'])
reloadedHandler = jasmine.createSpy('reloadedHandler')
atom.themes.onDidChangeActiveThemes(reloadedHandler)
atom.themes.activatePackages()
waitsFor "themes to be reloaded", ->
reloadedHandler.callCount is 1
runs ->
packageManager = new PackageManager
themeMetadata = CSON.readFileSync(path.join(__dirname, 'fixtures', 'a-theme', 'package.json'))
spyOn(packageManager, 'getFeatured').andCallFake (callback) ->
Promise.resolve([themeMetadata])
panel = new ThemesPanel(settingsView, packageManager)
# Make updates synchronous
spyOn(panel, 'scheduleUpdateThemeConfig').andCallFake -> @updateThemeConfig()
afterEach ->
atom.packages.unloadPackage('a-theme') if atom.packages.isPackageLoaded('a-theme')
waitsForPromise ->
Promise.resolve(atom.themes.deactivateThemes()) # Ensure works on promise and non-promise versions
it "selects the active syntax and UI themes", ->
expect(panel.refs.uiMenu.value).toBe 'atom-dark-ui'
expect(panel.refs.syntaxMenu.value).toBe 'atom-dark-syntax'
describe "when a UI theme is selected", ->
it "updates the 'core.themes' config key with the selected UI theme", ->
for child in panel.refs.uiMenu.children
child.selected = child.value is 'atom-light-ui'
child.dispatchEvent(new Event('change', {bubbles: true}))
waitsFor ->
reloadedHandler.callCount is 2
runs ->
expect(atom.config.get('core.themes')).toEqual ['atom-light-ui', 'atom-dark-syntax']
describe "when a syntax theme is selected", ->
it "updates the 'core.themes' config key with the selected syntax theme", ->
for child in panel.refs.syntaxMenu.children
child.selected = child.value is 'atom-light-syntax'
child.dispatchEvent(new Event('change', {bubbles: true}))
waitsFor ->
reloadedHandler.callCount is 2
runs ->
expect(atom.config.get('core.themes')).toEqual ['atom-dark-ui', 'atom-light-syntax']
describe "when the 'core.config' key changes", ->
it "refreshes the theme menus", ->
reloadedHandler.reset()
atom.config.set('core.themes', ['atom-light-ui', 'atom-light-syntax'])
waitsFor ->
reloadedHandler.callCount is 1
runs ->
expect(panel.refs.uiMenu.value).toBe 'atom-light-ui'
expect(panel.refs.syntaxMenu.value).toBe 'atom-light-syntax'
xdescribe "when the themes panel is navigated to", ->
xit "focuses the search filter", ->
settingsView.showPanel('Themes')
expect(panel.refs.filterEditor.element).toHaveFocus()
describe "theme lists", ->
[installed] = []
beforeEach ->
installed = JSON.parse fs.readFileSync(path.join(__dirname, 'fixtures', 'installed.json'))
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(packageManager, 'getInstalled').andReturn Promise.resolve(installed)
panel = new ThemesPanel(settingsView, packageManager)
waitsFor ->
packageManager.getInstalled.callCount is 1 and panel.refs.communityCount.textContent.indexOf('') < 0
it 'shows the themes', ->
expect(panel.refs.communityCount.textContent.trim()).toBe '1'
expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(panel.refs.coreCount.textContent.trim()).toBe '1'
expect(panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(panel.refs.devCount.textContent.trim()).toBe '1'
expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
it 'filters themes by name', ->
panel.refs.filterEditor.setText('user-')
window.advanceClock(panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
expect(panel.refs.communityCount.textContent.trim()).toBe '1/1'
expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
expect(panel.refs.coreCount.textContent.trim()).toBe '0/1'
expect(panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
expect(panel.refs.devCount.textContent.trim()).toBe '0/1'
expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 0
it 'adds newly installed themes to the list', ->
[installCallback] = []
spyOn(packageManager, 'runCommand').andCallFake (args, callback) ->
installCallback = callback
onWillThrowError: ->
spyOn(atom.packages, 'loadPackage').andCallFake (name) ->
installed.user.push {name, theme: 'ui'}
expect(panel.refs.communityCount.textContent.trim()).toBe '1'
expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 1
packageManager.install({name: 'another-user-theme', theme: 'ui'})
installCallback(0, '', '')
advanceClock ThemesPanel.loadPackagesDelay()
waits 1
runs ->
expect(panel.refs.communityCount.textContent.trim()).toBe '2'
expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe 2
it 'collapses/expands a sub-section if its header is clicked', ->
expect(panel.element.querySelectorAll('.sub-section-heading.has-items').length).toBe 3
panel.element.querySelector('.sub-section.installed-packages .sub-section-heading.has-items').click()
expect(panel.element.querySelector('.sub-section.installed-packages')).toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
panel.element.querySelector('.sub-section.installed-packages .sub-section-heading.has-items').click()
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
it 'can collapse and expand any of the sub-sections', ->
expect(panel.element.querySelectorAll('.sub-section-heading.has-items').length).toBe 3
for heading in panel.element.querySelectorAll('.sub-section-heading.has-items')
heading.click()
expect(panel.element.querySelector('.sub-section.installed-packages')).toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.core-packages')).toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.dev-packages')).toHaveClass 'collapsed'
for heading in panel.element.querySelectorAll('.sub-section-heading.has-items')
heading.click()
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
it 'can collapse sub-sections when filtering', ->
panel.refs.filterEditor.setText('user-')
window.advanceClock(panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
hasItems = panel.element.querySelectorAll('.sub-section-heading.has-items')
expect(hasItems.length).toBe 1
expect(hasItems[0].textContent).toMatch /^Community Themes/
describe 'when there are no themes', ->
beforeEach ->
installed =
dev: []
user: []
core: []
spyOn(packageManager, 'loadCompatiblePackageVersion').andCallFake ->
spyOn(packageManager, 'getInstalled').andReturn Promise.resolve(installed)
panel = new ThemesPanel(settingsView, packageManager)
waitsFor ->
packageManager.getInstalled.callCount is 1 and panel.refs.communityCount.textContent.indexOf('') < 0
afterEach ->
waitsForPromise ->
Promise.resolve(atom.themes.deactivateThemes()) # Ensure works on promise and non-promise versions
it 'has a count of zero in all headings', ->
for heading in panel.element.querySelector('.section-heading-count')
expect(heading.textContent).toMatch /^0+$/
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan').length).toBe 4
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe 0
it 'can collapse and expand any of the sub-sections', ->
for heading in panel.element.querySelectorAll('.sub-section-heading')
heading.click()
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass 'collapsed'
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass 'collapsed'
it 'does not allow collapsing on any section when filtering', ->
panel.refs.filterEditor.setText('user-')
window.advanceClock(panel.refs.filterEditor.getBuffer().stoppedChangingDelay)
for heading in panel.element.querySelector('.section-heading-count')
expect(heading.textContent).toMatch /^(0\/0)+$/
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan').length).toBe 4
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe 0

View File

@ -1,9 +1,4 @@
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const path = require('path');
const fs = require('fs');
@ -29,25 +24,25 @@ describe("ThemesPanel", function() {
waitsFor("themes to be reloaded", () => reloadedHandler.callCount === 1);
return runs(function() {
runs(function() {
packageManager = new PackageManager;
const themeMetadata = CSON.readFileSync(path.join(__dirname, 'fixtures', 'a-theme', 'package.json'));
spyOn(packageManager, 'getFeatured').andCallFake(callback => Promise.resolve([themeMetadata]));
panel = new ThemesPanel(settingsView, packageManager);
// Make updates synchronous
return spyOn(panel, 'scheduleUpdateThemeConfig').andCallFake(function() { return this.updateThemeConfig(); });
spyOn(panel, 'scheduleUpdateThemeConfig').andCallFake(function() { return this.updateThemeConfig(); });
});
});
afterEach(function() {
if (atom.packages.isPackageLoaded('a-theme')) { atom.packages.unloadPackage('a-theme'); }
return waitsForPromise(() => Promise.resolve(atom.themes.deactivateThemes()));
waitsForPromise(() => Promise.resolve(atom.themes.deactivateThemes()));
}); // Ensure works on promise and non-promise versions
it("selects the active syntax and UI themes", function() {
expect(panel.refs.uiMenu.value).toBe('atom-dark-ui');
return expect(panel.refs.syntaxMenu.value).toBe('atom-dark-syntax');
expect(panel.refs.syntaxMenu.value).toBe('atom-dark-syntax');
});
describe("when a UI theme is selected", () => it("updates the 'core.themes' config key with the selected UI theme", function() {
@ -56,7 +51,7 @@ describe("ThemesPanel", function() {
child.dispatchEvent(new Event('change', {bubbles: true}));
}
waitsFor(() => reloadedHandler.callCount === 2);
return runs(() => expect(atom.config.get('core.themes')).toEqual(['atom-light-ui', 'atom-dark-syntax']));
runs(() => expect(atom.config.get('core.themes')).toEqual(['atom-light-ui', 'atom-dark-syntax']));
}));
describe("when a syntax theme is selected", () => it("updates the 'core.themes' config key with the selected syntax theme", function() {
@ -65,7 +60,7 @@ describe("ThemesPanel", function() {
child.dispatchEvent(new Event('change', {bubbles: true}));
}
waitsFor(() => reloadedHandler.callCount === 2);
return runs(() => expect(atom.config.get('core.themes')).toEqual(['atom-dark-ui', 'atom-light-syntax']));
runs(() => expect(atom.config.get('core.themes')).toEqual(['atom-dark-ui', 'atom-light-syntax']));
}));
describe("when the 'core.config' key changes", () => it("refreshes the theme menus", function() {
@ -74,15 +69,15 @@ describe("ThemesPanel", function() {
waitsFor(() => reloadedHandler.callCount === 1);
return runs(function() {
runs(function() {
expect(panel.refs.uiMenu.value).toBe('atom-light-ui');
return expect(panel.refs.syntaxMenu.value).toBe('atom-light-syntax');
expect(panel.refs.syntaxMenu.value).toBe('atom-light-syntax');
});
}));
xdescribe("when the themes panel is navigated to", () => xit("focuses the search filter", function() {
settingsView.showPanel('Themes');
return expect(panel.refs.filterEditor.element).toHaveFocus();
expect(panel.refs.filterEditor.element).toHaveFocus();
}));
describe("theme lists", function() {
@ -93,7 +88,7 @@ describe("ThemesPanel", function() {
spyOn(packageManager, 'getInstalled').andReturn(Promise.resolve(installed));
panel = new ThemesPanel(settingsView, packageManager);
return waitsFor(() => (packageManager.getInstalled.callCount === 1) && (panel.refs.communityCount.textContent.indexOf('…') < 0));
waitsFor(() => (packageManager.getInstalled.callCount === 1) && (panel.refs.communityCount.textContent.indexOf('…') < 0));
});
it('shows the themes', function() {
@ -104,7 +99,7 @@ describe("ThemesPanel", function() {
expect(panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
expect(panel.refs.devCount.textContent.trim()).toBe('1');
return expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(1);
});
it('filters themes by name', function() {
@ -117,7 +112,7 @@ describe("ThemesPanel", function() {
expect(panel.refs.corePackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(panel.refs.devCount.textContent.trim()).toBe('0/1');
return expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
expect(panel.refs.devPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(0);
});
it('adds newly installed themes to the list', function() {
@ -136,9 +131,9 @@ describe("ThemesPanel", function() {
advanceClock(ThemesPanel.loadPackagesDelay());
waits(1);
return runs(function() {
runs(function() {
expect(panel.refs.communityCount.textContent.trim()).toBe('2');
return expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(2);
expect(panel.refs.communityPackages.querySelectorAll('.package-card:not(.hidden)').length).toBe(2);
});
});
@ -151,7 +146,7 @@ describe("ThemesPanel", function() {
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
panel.element.querySelector('.sub-section.installed-packages .sub-section-heading.has-items').click();
return expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
});
it('can collapse and expand any of the sub-sections', function() {
@ -170,20 +165,20 @@ describe("ThemesPanel", function() {
}
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass('collapsed');
return expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
});
return it('can collapse sub-sections when filtering', function() {
it('can collapse sub-sections when filtering', function() {
panel.refs.filterEditor.setText('user-');
window.advanceClock(panel.refs.filterEditor.getBuffer().stoppedChangingDelay);
const hasItems = panel.element.querySelectorAll('.sub-section-heading.has-items');
expect(hasItems.length).toBe(1);
return expect(hasItems[0].textContent).toMatch(/^Community Themes/);
expect(hasItems[0].textContent).toMatch(/^Community Themes/);
});
});
return describe('when there are no themes', function() {
describe('when there are no themes', function() {
beforeEach(function() {
const installed = {
dev: [],
@ -195,7 +190,7 @@ describe("ThemesPanel", function() {
spyOn(packageManager, 'getInstalled').andReturn(Promise.resolve(installed));
panel = new ThemesPanel(settingsView, packageManager);
return waitsFor(() => (packageManager.getInstalled.callCount === 1) && (panel.refs.communityCount.textContent.indexOf('…') < 0));
waitsFor(() => (packageManager.getInstalled.callCount === 1) && (panel.refs.communityCount.textContent.indexOf('…') < 0));
});
afterEach(() => waitsForPromise(() => Promise.resolve(atom.themes.deactivateThemes()))); // Ensure works on promise and non-promise versions
@ -205,7 +200,7 @@ describe("ThemesPanel", function() {
expect(heading.textContent).toMatch(/^0+$/);
}
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan').length).toBe(4);
return expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
});
it('can collapse and expand any of the sub-sections', function() {
@ -214,10 +209,10 @@ describe("ThemesPanel", function() {
}
expect(panel.element.querySelector('.sub-section.installed-packages')).not.toHaveClass('collapsed');
expect(panel.element.querySelector('.sub-section.core-packages')).not.toHaveClass('collapsed');
return expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
expect(panel.element.querySelector('.sub-section.dev-packages')).not.toHaveClass('collapsed');
});
return it('does not allow collapsing on any section when filtering', function() {
it('does not allow collapsing on any section when filtering', function() {
panel.refs.filterEditor.setText('user-');
window.advanceClock(panel.refs.filterEditor.getBuffer().stoppedChangingDelay);
@ -225,7 +220,7 @@ describe("ThemesPanel", function() {
expect(heading.textContent).toMatch(/^(0\/0)+$/);
}
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan').length).toBe(4);
return expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
expect(panel.element.querySelectorAll('.sub-section .icon-paintcan.has-items').length).toBe(0);
});
});
});

View File

@ -1,225 +0,0 @@
UpdatesPanel = require '../lib/updates-panel'
PackageManager = require '../lib/package-manager'
SettingsView = require '../lib/settings-view'
describe 'UpdatesPanel', ->
panel = null
settingsView = null
packageManager = null
[resolveOutdated, rejectOutdated] = []
beforeEach ->
settingsView = new SettingsView
packageManager = new PackageManager
# This spy is only needed for the Check for Updates specs,
# but we have to instantiate it here because we need to pass the spy to the UpdatesPanel
spyOn(packageManager, 'getOutdated').andReturn(new Promise((resolve, reject) -> [resolveOutdated, rejectOutdated] = [resolve, reject]))
panel = new UpdatesPanel(settingsView, packageManager)
jasmine.attachToDOM(panel.element)
it "shows updates when updates are available", ->
pack =
name: 'test-package'
description: 'some description'
latestVersion: '99.0.0'
version: '1.0.0'
# skip packman stubbing
panel.beforeShow(updates: [pack])
expect(panel.refs.updatesContainer.children.length).toBe(1)
it "shows a message when updates are not available", ->
panel.beforeShow(updates: [])
expect(panel.refs.updatesContainer.children.length).toBe(0)
expect(panel.refs.noUpdatesMessage.style.display).not.toBe('none')
describe "version pinned packages message", ->
it 'shows a message when there are pinned version packages', ->
spyOn(packageManager, 'getVersionPinnedPackages').andReturn(['foo', 'bar', 'baz'])
panel.beforeShow(updates: [])
expect(panel.refs.versionPinnedPackagesMessage.style.display).not.toBe('none')
it 'does not show a message when there are no version pinned packages', ->
spyOn(packageManager, 'getVersionPinnedPackages').andReturn([])
panel.beforeShow(updates: [])
expect(panel.refs.versionPinnedPackagesMessage.style.display).toBe('none')
describe "the Update All button", ->
packA =
name: 'test-package-a'
description: 'some description'
latestVersion: '99.0.0'
version: '1.0.0'
packB =
name: 'test-package-b'
description: 'some description'
latestVersion: '99.0.0'
version: '1.0.0'
packC =
name: 'test-package-c'
description: 'some description'
latestVersion: '99.0.0'
version: '1.0.0'
[cardA, cardB, cardC] = []
[resolveA, resolveB, resolveC, rejectA, rejectB, rejectC] = []
beforeEach ->
# skip packman stubbing
panel.beforeShow(updates: [packA, packB, packC])
[cardA, cardB, cardC] = panel.packageCards
# fake a git url package
cardC.pack.apmInstallSource = {type: 'git', sha: 'cf23df2207d99a74fbe169e3eba035e633b65d94'}
cardC.pack.latestSha = 'a296114f3d0deec519a41f4c62e7fc56075b7f01'
spyOn(cardA, 'update').andReturn(new Promise((resolve, reject) -> [resolveA, rejectA] = [resolve, reject]))
spyOn(cardB, 'update').andReturn(new Promise((resolve, reject) -> [resolveB, rejectB] = [resolve, reject]))
spyOn(cardC, 'update').andReturn(new Promise((resolve, reject) -> [resolveC, rejectC] = [resolve, reject]))
atom.config.set("settings-view.packageUpdateConcurrency", -1)
it 'attempts to update all packages and prompts to restart if at least one package updates successfully', ->
expect(atom.notifications.getNotifications().length).toBe 0
expect(panel.refs.updateAllButton).toBeVisible()
panel.updateAll()
resolveA()
rejectB('Error updating package')
waits 0
runs ->
expect(atom.notifications.getNotifications().length).toBe 0
resolveC()
waitsFor ->
atom.notifications.getNotifications().length is 1
runs ->
notifications = atom.notifications.getNotifications()
expect(notifications.length).toBe 1
notif = notifications[0]
expect(notif.options.detail).toBe 'test-package-a@1.0.0 -> 99.0.0\ntest-package-b@1.0.0 -> 99.0.0\ntest-package-c@cf23df22 -> a296114f'
expect(notif.options.buttons.length).toBe(2)
spyOn(atom, 'restartApplication')
notif.options.buttons[0].onDidClick()
expect(atom.restartApplication).toHaveBeenCalled()
spyOn(notif, 'dismiss')
notif.options.buttons[1].onDidClick()
expect(notif.dismiss).toHaveBeenCalled()
it 'works with queue enabled', ->
expect(panel.refs.updateAllButton).not.toBeDisabled()
atom.config.set("settings-view.packageUpdateConcurrency", 2)
panel.updateAll()
resolveA()
resolveB()
resolveC()
waitsFor ->
panel.refs.updateAllButton.style.display is 'none'
it 'becomes hidden if all updates succeed', ->
expect(panel.refs.updateAllButton).not.toBeDisabled()
panel.updateAll()
expect(panel.refs.updateAllButton).toBeDisabled()
resolveA()
resolveB()
resolveC()
waitsFor ->
panel.refs.updateAllButton.style.display is 'none'
it 'remains enabled and visible if not all updates succeed', ->
expect(panel.refs.updateAllButton).not.toBeDisabled()
panel.updateAll()
expect(panel.refs.updateAllButton).toBeDisabled()
resolveA()
rejectB('Error updating package')
resolveC()
waitsFor ->
panel.refs.updateAllButton.disabled is false
runs ->
expect(panel.refs.updateAllButton).toBeVisible()
it 'does not attempt to update packages that are already updating', ->
cardA.update()
packageManager.emitPackageEvent 'updating', packA
panel.updateAll()
expect(cardA.update.calls.length).toBe 1
describe 'the Check for Updates button', ->
pack =
name: 'test-package'
description: 'some description'
latestVersion: '99.0.0'
version: '1.0.0'
beforeEach ->
# skip packman stubbing - without this, getOutdated() is called another time
# this is not an issue in actual usage as getOutdated() isn't blocked on a spy
panel.beforeShow(updates: [pack])
it 'disables itself when clicked until the list of outdated packages is returned', ->
# Updates panel checks for updates on initialization so resolve the promise
resolveOutdated()
waits 0
runs ->
expect(panel.refs.checkButton.disabled).toBe false
panel.checkForUpdates()
expect(panel.refs.checkButton.disabled).toBe true
resolveOutdated()
waits 0
runs ->
expect(panel.refs.checkButton.disabled).toBe false
it 'clears the outdated cache when checking for updates', ->
# This spec just tests that we're passing the clearCache bool through, not the actual implementation
# For that, look at the PackageManager specs
resolveOutdated()
waits 0
runs ->
panel.refs.checkButton.click()
expect(packageManager.getOutdated).toHaveBeenCalledWith true
it 'is disabled when packages are updating', ->
# Updates panel checks for updates on initialization so resolve the promise
resolveOutdated()
waits 0
runs ->
expect(panel.refs.checkButton.disabled).toBe false
packageManager.emitPackageEvent 'updating', {name: 'packA'}
expect(panel.refs.checkButton.disabled).toBe true
packageManager.emitPackageEvent 'updating', {name: 'packB'}
expect(panel.refs.checkButton.disabled).toBe true
packageManager.emitPackageEvent 'updated', {name: 'packB'}
expect(panel.refs.checkButton.disabled).toBe true
packageManager.emitPackageEvent 'update-failed', {name: 'packA'}
expect(panel.refs.checkButton.disabled).toBe false

View File

@ -1,8 +1,4 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const UpdatesPanel = require('../lib/updates-panel');
const PackageManager = require('../lib/package-manager');
const SettingsView = require('../lib/settings-view');
@ -33,26 +29,26 @@ describe('UpdatesPanel', function() {
// skip packman stubbing
panel.beforeShow({updates: [pack]});
return expect(panel.refs.updatesContainer.children.length).toBe(1);
expect(panel.refs.updatesContainer.children.length).toBe(1);
});
it("shows a message when updates are not available", function() {
panel.beforeShow({updates: []});
expect(panel.refs.updatesContainer.children.length).toBe(0);
return expect(panel.refs.noUpdatesMessage.style.display).not.toBe('none');
expect(panel.refs.noUpdatesMessage.style.display).not.toBe('none');
});
describe("version pinned packages message", function() {
it('shows a message when there are pinned version packages', function() {
spyOn(packageManager, 'getVersionPinnedPackages').andReturn(['foo', 'bar', 'baz']);
panel.beforeShow({updates: []});
return expect(panel.refs.versionPinnedPackagesMessage.style.display).not.toBe('none');
expect(panel.refs.versionPinnedPackagesMessage.style.display).not.toBe('none');
});
return it('does not show a message when there are no version pinned packages', function() {
it('does not show a message when there are no version pinned packages', function() {
spyOn(packageManager, 'getVersionPinnedPackages').andReturn([]);
panel.beforeShow({updates: []});
return expect(panel.refs.versionPinnedPackagesMessage.style.display).toBe('none');
expect(panel.refs.versionPinnedPackagesMessage.style.display).toBe('none');
});
});
@ -93,7 +89,7 @@ describe('UpdatesPanel', function() {
spyOn(cardB, 'update').andReturn(new Promise((resolve, reject) => [resolveB, rejectB] = [resolve, reject]));
spyOn(cardC, 'update').andReturn(new Promise((resolve, reject) => [resolveC, rejectC] = [resolve, reject]));
return atom.config.set("settings-view.packageUpdateConcurrency", -1);
atom.config.set("settings-view.packageUpdateConcurrency", -1);
});
it('attempts to update all packages and prompts to restart if at least one package updates successfully', function() {
@ -114,7 +110,7 @@ describe('UpdatesPanel', function() {
waitsFor(() => atom.notifications.getNotifications().length === 1);
return runs(function() {
runs(function() {
const notifications = atom.notifications.getNotifications();
expect(notifications.length).toBe(1);
const notif = notifications[0];
@ -129,7 +125,7 @@ describe('UpdatesPanel', function() {
spyOn(notif, 'dismiss');
notif.options.buttons[1].onDidClick();
return expect(notif.dismiss).toHaveBeenCalled();
expect(notif.dismiss).toHaveBeenCalled();
});
});
@ -143,7 +139,7 @@ describe('UpdatesPanel', function() {
resolveB();
resolveC();
return waitsFor(() => panel.refs.updateAllButton.style.display === 'none');
waitsFor(() => panel.refs.updateAllButton.style.display === 'none');
});
it('becomes hidden if all updates succeed', function() {
@ -157,7 +153,7 @@ describe('UpdatesPanel', function() {
resolveB();
resolveC();
return waitsFor(() => panel.refs.updateAllButton.style.display === 'none');
waitsFor(() => panel.refs.updateAllButton.style.display === 'none');
});
it('remains enabled and visible if not all updates succeed', function() {
@ -173,19 +169,19 @@ describe('UpdatesPanel', function() {
waitsFor(() => panel.refs.updateAllButton.disabled === false);
return runs(() => expect(panel.refs.updateAllButton).toBeVisible());
runs(() => expect(panel.refs.updateAllButton).toBeVisible());
});
return it('does not attempt to update packages that are already updating', function() {
it('does not attempt to update packages that are already updating', function() {
cardA.update();
packageManager.emitPackageEvent('updating', packA);
panel.updateAll();
return expect(cardA.update.calls.length).toBe(1);
expect(cardA.update.calls.length).toBe(1);
});
});
return describe('the Check for Updates button', function() {
describe('the Check for Updates button', function() {
const pack = {
name: 'test-package',
description: 'some description',
@ -212,7 +208,7 @@ describe('UpdatesPanel', function() {
});
waits(0);
return runs(() => expect(panel.refs.checkButton.disabled).toBe(false));
runs(() => expect(panel.refs.checkButton.disabled).toBe(false));
});
it('clears the outdated cache when checking for updates', function() {
@ -220,18 +216,18 @@ describe('UpdatesPanel', function() {
// For that, look at the PackageManager specs
resolveOutdated();
waits(0);
return runs(function() {
runs(function() {
panel.refs.checkButton.click();
return expect(packageManager.getOutdated).toHaveBeenCalledWith(true);
expect(packageManager.getOutdated).toHaveBeenCalledWith(true);
});
});
return it('is disabled when packages are updating', function() {
it('is disabled when packages are updating', function() {
// Updates panel checks for updates on initialization so resolve the promise
resolveOutdated();
waits(0);
return runs(function() {
runs(function() {
expect(panel.refs.checkButton.disabled).toBe(false);
packageManager.emitPackageEvent('updating', {name: 'packA'});
@ -244,7 +240,7 @@ describe('UpdatesPanel', function() {
expect(panel.refs.checkButton.disabled).toBe(true);
packageManager.emitPackageEvent('update-failed', {name: 'packA'});
return expect(panel.refs.checkButton.disabled).toBe(false);
expect(panel.refs.checkButton.disabled).toBe(false);
});
});
});

View File

@ -1,18 +1,14 @@
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
*/
const {ownerFromRepository} = require('../lib/utils');
describe("Utils", () => describe("ownerFromRepository", function() {
it("handles a long github url", function() {
describe("Utils", () => describe("ownerFromRepository", () => {
it("handles a long github url", () => {
const owner = ownerFromRepository("http://github.com/omgwow/some-package");
return expect(owner).toBe("omgwow");
expect(owner).toBe("omgwow");
});
return it("handles a short github url", function() {
it("handles a short github url", () => {
const owner = ownerFromRepository("omgwow/some-package");
return expect(owner).toBe("omgwow");
expect(owner).toBe("omgwow");
});
}));