From 7ec9747cd5098fa594420b5896b58e06e4c678c5 Mon Sep 17 00:00:00 2001 From: Koza Date: Tue, 7 May 2024 15:00:52 +0200 Subject: [PATCH] Upgrade archive-view to use jasmine2 test runner --- packages/archive-view/package.json | 1 + .../archive-view/spec/archive-editor-spec.js | 6 +- .../spec/archive-editor-view-spec.js | 84 +++++++++++++------ .../archive-view/spec/async-spec-helpers.js | 82 +----------------- 4 files changed, 65 insertions(+), 108 deletions(-) diff --git a/packages/archive-view/package.json b/packages/archive-view/package.json index 64389cb8b5..20f728d7a8 100644 --- a/packages/archive-view/package.json +++ b/packages/archive-view/package.json @@ -14,6 +14,7 @@ "engines": { "atom": "*" }, + "atomTestRunner": "runners/jasmine2-test-runner", "deserializers": { "ArchiveEditor": "deserialize", "ArchiveEditorView": "deserialize" diff --git a/packages/archive-view/spec/archive-editor-spec.js b/packages/archive-view/spec/archive-editor-spec.js index 7b0bea958c..d34ea9afc9 100644 --- a/packages/archive-view/spec/archive-editor-spec.js +++ b/packages/archive-view/spec/archive-editor-spec.js @@ -1,5 +1,3 @@ -const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars - const path = require('path') const ArchiveEditor = require('../lib/archive-editor') const ArchiveEditorView = require('../lib/archive-editor-view') @@ -26,7 +24,7 @@ describe('ArchiveEditor', () => { }) describe('.deactivate()', () => { - it('removes all ArchiveEditorViews from the workspace and does not open any new ones', async () => { + it('removes all ArchiveEditorViews from the workspace and does not open any new ones', async (done) => { const getArchiveEditorViews = () => { return atom.workspace.getPaneItems().filter(item => item instanceof ArchiveEditorView) } @@ -41,6 +39,8 @@ describe('ArchiveEditor', () => { await atom.workspace.open(path.join(__dirname, 'fixtures', 'nested.tar')) expect(getArchiveEditorViews().length).toBe(0) + + done(); }) }) }) diff --git a/packages/archive-view/spec/archive-editor-view-spec.js b/packages/archive-view/spec/archive-editor-view-spec.js index 4ded3e5a8e..f670b3c3fa 100644 --- a/packages/archive-view/spec/archive-editor-view-spec.js +++ b/packages/archive-view/spec/archive-editor-view-spec.js @@ -1,6 +1,6 @@ const {Disposable, File} = require('atom') const getIconServices = require('../lib/get-icon-services') -const {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars +const {conditionPromise} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars async function condition (handler) { if (jasmine.isSpy(window.setTimeout)) { @@ -12,22 +12,22 @@ async function condition (handler) { describe('ArchiveEditorView', () => { let archiveEditorView, onDidChangeCallback, onDidRenameCallback, onDidDeleteCallback - beforeEach(async () => { - spyOn(File.prototype, 'onDidChange').andCallFake(function (callback) { + beforeEach(async (done) => { + spyOn(File.prototype, 'onDidChange').and.callFake(function (callback) { if (/\.tar$/.test(this.getPath())) { onDidChangeCallback = callback } return new Disposable() }) - spyOn(File.prototype, 'onDidRename').andCallFake(function (callback) { + spyOn(File.prototype, 'onDidRename').and.callFake(function (callback) { if (/\.tar$/.test(this.getPath())) { onDidRenameCallback = callback } return new Disposable() }) - spyOn(File.prototype, 'onDidDelete').andCallFake(function (callback) { + spyOn(File.prototype, 'onDidDelete').and.callFake(function (callback) { if (/\.tar$/.test(this.getPath())) { onDidDeleteCallback = callback } @@ -36,10 +36,12 @@ describe('ArchiveEditorView', () => { await atom.packages.activatePackage('archive-view') archiveEditorView = await atom.workspace.open('nested.tar') + + done(); }) describe('.constructor()', () => { - it('displays the files and folders in the archive file', async () => { + it('displays the files and folders in the archive file', async (done) => { expect(archiveEditorView.element).toExist() await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) @@ -57,11 +59,15 @@ describe('ArchiveEditorView', () => { expect(fileElements[0].textContent).toBe('f1.txt') expect(fileElements[1].textContent).toBe('f2.txt') expect(fileElements[2].textContent).toBe('fa.txt') + + done(); }) - it('selects the first file', async () => { + it('selects the first file', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) expect(archiveEditorView.element.querySelector('.selected').textContent).toBe('f1.txt') + + done(); }) }) @@ -73,17 +79,21 @@ describe('ArchiveEditorView', () => { }) describe('archive summary', () => { - beforeEach(async () => { + beforeEach(async (done) => { await atom.workspace.open('multiple-entries.zip') archiveEditorView = atom.workspace.getActivePaneItem() jasmine.attachToDOM(atom.views.getView(atom.workspace)) + + done(); }) - it('shows correct statistics', async () => { + it('shows correct statistics', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) const heading = archiveEditorView.element.querySelector('.inset-panel .panel-heading') expect(heading).not.toBe(null) expect(heading.textContent).toBe('704 bytes with 4 files and 1 folder') + + done(); }) }) @@ -95,7 +105,7 @@ describe('ArchiveEditorView', () => { return true } - it('selects the next/previous file', async () => { + it('selects the next/previous file', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) expect(archiveEditorView.element).toBeDefined() dispatch('core:move-up') && expect(selectedEntry).toBe('f1.txt') @@ -104,21 +114,25 @@ describe('ArchiveEditorView', () => { dispatch('core:move-down') && expect(selectedEntry).toBe('fa.txt') dispatch('core:move-up') && expect(selectedEntry).toBe('f2.txt') dispatch('core:move-up') && expect(selectedEntry).toBe('f1.txt') + + done(); }) }) describe('when a file is clicked', () => { - it('copies the contents to a temp file and opens it in a new editor', async () => { + it('copies the contents to a temp file and opens it in a new editor', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) archiveEditorView.element.querySelectorAll('.file')[2].click() await condition(() => atom.workspace.getActivePane().getItems().length > 1) expect(atom.workspace.getActivePaneItem().getText()).toBe('hey there\n') expect(atom.workspace.getActivePaneItem().getTitle()).toBe('fa.txt') + + done(); }) }) describe('when a directory is clicked', () => { - it('collapses/expands itself', async () => { + it('collapses/expands itself', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) let directory = archiveEditorView.element.querySelectorAll('.list-nested-item.entry')[0] expect(directory.classList.contains('collapsed')).toBeFalsy() @@ -126,59 +140,73 @@ describe('ArchiveEditorView', () => { expect(directory.classList.contains('collapsed')).toBeTruthy() directory.querySelector('.list-item').click() expect(directory.classList.contains('collapsed')).toBeFalsy() + + done(); }) }) describe('when core:confirm is triggered', () => { - it('copies the contents to a temp file and opens it in a new editor', async () => { + it('copies the contents to a temp file and opens it in a new editor', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) atom.commands.dispatch(archiveEditorView.element.querySelector('.file'), 'core:confirm') await condition(() => atom.workspace.getActivePane().getItems().length > 1) expect(atom.workspace.getActivePaneItem().getText()).toBe('') expect(atom.workspace.getActivePaneItem().getTitle()).toBe('f1.txt') + + done(); }) }) describe('when the file is modified', () => { - it('refreshes the view', async () => { + it('refreshes the view', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) spyOn(archiveEditorView, 'refresh') onDidChangeCallback() expect(archiveEditorView.refresh).toHaveBeenCalled() + + done(); }) }) describe('when the file is renamed', () => { - it('refreshes the view and updates the title', async () => { - spyOn(File.prototype, 'getPath').andReturn('nested-renamed.tar') + it('refreshes the view and updates the title', async (done) => { + spyOn(File.prototype, 'getPath').and.returnValue('nested-renamed.tar') await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) - spyOn(archiveEditorView, 'refresh').andCallThrough() + spyOn(archiveEditorView, 'refresh').and.callThrough() spyOn(archiveEditorView, 'getTitle') onDidRenameCallback() expect(archiveEditorView.refresh).toHaveBeenCalled() expect(archiveEditorView.getTitle).toHaveBeenCalled() + + done(); }) }) describe('when the file is removed', () => { - it('destroys the view', async () => { + it('destroys the view', async (done) => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) expect(atom.workspace.getActivePane().getItems().length).toBe(1) onDidDeleteCallback() expect(atom.workspace.getActivePaneItem()).toBeUndefined() + + done(); }) }) describe('when the file is invalid', () => { - beforeEach(async () => { + beforeEach(async (done) => { await atom.workspace.open('invalid.zip') archiveEditorView = atom.workspace.getActivePaneItem() jasmine.attachToDOM(atom.views.getView(atom.workspace)) + + done(); }) - it('shows the error', async () => { + it('shows the error', async (done) => { await condition(() => archiveEditorView.refs.errorMessage.offsetHeight > 0) expect(archiveEditorView.refs.errorMessage.textContent.length).toBeGreaterThan(0) + + done(); }) }) @@ -224,15 +252,17 @@ describe('ArchiveEditorView', () => { expect(findEntryContainingText('font.ttf').querySelector('.file.icon').className).toBe('file icon binary ttf-icon font') } - it('displays default file-icons', async () => { + it('displays default file-icons', async (done) => { await openFile() await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) expect(findEntryContainingText('adobe.pdf').querySelector('.file.icon.icon-file-pdf').length).not.toBe(0) expect(findEntryContainingText('spacer.gif').querySelector('.file.icon.icon-file-media').length).not.toBe(0) expect(findEntryContainingText('sunn.o').querySelector('.file.icon.icon-file-binary').length).not.toBe(0) + + done(); }) - it('allows multiple classes to be passed', async () => { + it('allows multiple classes to be passed', async (done) => { getIconServices().setFileIcons({ iconClassForPath: (path) => { switch (path.match(/\w*$/)[0]) { @@ -245,9 +275,11 @@ describe('ArchiveEditorView', () => { await openFile() await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) checkMultiClass() + + done(); }) - it('allows an array of classes to be passed', async () => { + it('allows an array of classes to be passed', async (done) => { getIconServices().setFileIcons({ iconClassForPath: (path) => { switch (path.match(/\w*$/)[0]) { @@ -260,9 +292,11 @@ describe('ArchiveEditorView', () => { await openFile() await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) checkMultiClass() + + done(); }) - it('identifies context to icon-service providers', async () => { + it('identifies context to icon-service providers', async (done) => { getIconServices().setFileIcons({ iconClassForPath: (path, context) => `icon-${context}` }) @@ -270,6 +304,8 @@ describe('ArchiveEditorView', () => { await condition(() => archiveEditorView.element.querySelectorAll('.entry').length > 0) const icons = findEntryContainingText('adobe.pdf').querySelectorAll('.file.icon-archive-view') expect(icons.length).not.toBe(0) + + done(); }) }) }) diff --git a/packages/archive-view/spec/async-spec-helpers.js b/packages/archive-view/spec/async-spec-helpers.js index 73002c049a..019902ce82 100644 --- a/packages/archive-view/spec/async-spec-helpers.js +++ b/packages/archive-view/spec/async-spec-helpers.js @@ -1,39 +1,5 @@ /** @babel */ -export function beforeEach (fn) { - global.beforeEach(function () { - const result = fn() - if (result instanceof Promise) { - waitsForPromise(() => result) - } - }) -} - -export function afterEach (fn) { - global.afterEach(function () { - const result = fn() - if (result instanceof Promise) { - waitsForPromise(() => result) - } - }) -} - -['it', 'fit', 'ffit', 'fffit'].forEach(function (name) { - module.exports[name] = function (description, fn) { - if (fn === undefined) { - global[name](description) - return - } - - global[name](description, function () { - const result = fn() - if (result instanceof Promise) { - waitsForPromise(() => result) - } - }) - } -}) - export async function conditionPromise (condition, description = 'anonymous condition') { const startTime = Date.now() @@ -50,54 +16,8 @@ export async function conditionPromise (condition, description = 'anonymous cond } } -export function timeoutPromise (timeout) { +function timeoutPromise (timeout) { return new Promise(function (resolve) { global.setTimeout(resolve, timeout) }) } - -function waitsForPromise (fn) { - const promise = fn() - global.waitsFor('spec promise to resolve', function (done) { - promise.then(done, function (error) { - jasmine.getEnv().currentSpec.fail(error) - done() - }) - }) -} - -export function emitterEventPromise (emitter, event, timeout = 15000) { - return new Promise((resolve, reject) => { - const timeoutHandle = setTimeout(() => { - reject(new Error(`Timed out waiting for '${event}' event`)) - }, timeout) - emitter.once(event, () => { - clearTimeout(timeoutHandle) - resolve() - }) - }) -} - -export function promisify (original) { - return function (...args) { - return new Promise((resolve, reject) => { - args.push((err, ...results) => { - if (err) { - reject(err) - } else { - resolve(...results) - } - }) - - return original(...args) - }) - } -} - -export function promisifySome (obj, fnNames) { - const result = {} - for (const fnName of fnNames) { - result[fnName] = promisify(obj[fnName]) - } - return result -}