Select Git revision
RegisterNameWindow.strings
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
plugins.manager.test.ts 13.75 KiB
/*
* Copyright (C) 2023-2032 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import 'reflect-metadata';
import 'module-alias/register';
import Sinon, { createStubInstance, restore, stub } from 'sinon';
import { Stats } from 'fs';
import { PluginsManager } from "../src/services/plugins.manager.service";
import { FileManagerService } from '../src/services/file.manager.service';
import { CertificateManager} from '../src/services/certificate.manager.service';
import { ArchitectureManager } from '../src/services/architecture.manager';
import { TranslationService } from '../src/services/translation.service';
describe('Plugins manager service tests', function () {
let pluginsManagerService: PluginsManager;
let architectureService: Sinon.SinonStubbedInstance<ArchitectureManager>;
let transaltionStub: Sinon.SinonStubbedInstance<TranslationService>;
let fileManager: Sinon.SinonStubbedInstance<FileManagerService>;
let certificateManager: Sinon.SinonStubbedInstance<CertificateManager>;
beforeEach(() => {
fileManager = createStubInstance(FileManagerService);
certificateManager = createStubInstance(CertificateManager);
architectureService = createStubInstance(ArchitectureManager);
transaltionStub = createStubInstance(TranslationService);
pluginsManagerService = new PluginsManager(architectureService, transaltionStub, fileManager, certificateManager);
});
afterEach(() => {
restore();
});
it('should return a list of plugins', async () => {
const fakePlugin = [
{
id: 'test',
name: 'test',
version: '',
description: 'test',
icon: '',
arches: ['test'],
timestamp: '',
author: '',
background: '',
signature: Buffer.from(''),
}];
const expectedPlugin = [
{
id: 'test',
name: 'test',
version: '',
description: 'test',
icon: '',
background: '',
timestamp: '',
author: ''
}];
transaltionStub.formatText.resolves(expectedPlugin[0].description);
stub(Object.getPrototypeOf(pluginsManagerService), 'isPluginAvailable').returns(true);
pluginsManagerService['plugins'] = fakePlugin;
const actual = await pluginsManagerService.getPlugins('test', 'en');
expect(actual).toEqual(expectedPlugin);
});
it('should return a plugin', async () => {
const plugin =
{
id: 'test',
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
background: 'test',
timestamp: 'test',
author: 'test',
signature: Buffer.from(''),
}
const expected = [{
...plugin,
arches: ["test"],
}];
pluginsManagerService['plugins'] = expected;
transaltionStub.formatText.resolves(plugin.name);
const actual = await pluginsManagerService.getPlugin("test", 'en');
expect(actual).toEqual({
id: plugin.id,
name: plugin.name,
version: plugin.version,
description: plugin.description,
icon: plugin.icon,
background: plugin.background,
timestamp: plugin.timestamp,
author: plugin.author,
});
});
it('should return undefined if plugin not found', async () => {
const actual = await pluginsManagerService.getPlugin("test", 'en');
expect(actual).toBeUndefined();
});
it('should return plugin path', async () => {
const plugin = {
id: 'test',
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
background: 'test',
timestamp: 'test',
author: 'test',
signature: Buffer.from(''),
};
const expected = [{
...plugin,
arches: ["test"],
}];
const expectedPath =
'/path/to/plugins/test/test/test.jpl';
pluginsManagerService['plugins'] = expected;
// Stub the required methods for this test
fileManager.listArchiveFiles.resolves(['test']);
process.env.DATA_DIRECTORY = '/path/to/plugins';
stub(Object.getPrototypeOf(pluginsManagerService), 'isPluginAvailable').returns(true);
architectureService.getPlatform.returns('test');
const actualPath = await pluginsManagerService.getPluginPath('test', 'test');
expect(actualPath).toContain(expectedPath);
})
it('should return undefined if plugin path not found', async () => {
const actual = await pluginsManagerService.getPluginPath("test", "test");
expect(actual).toBeUndefined();
})
it('should add a plugin', async () => {
const pluginPath = '/path/to/plugin.jpl';
const manifest = {
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
};
const expectedTimestamp = 'test';
stub(Object.getPrototypeOf(pluginsManagerService), 'readManifest').resolves(manifest);
architectureService.getAllPluginArches.resolves(['arch1', 'arch2']);
fileManager.getStat.resolves({ mtime: { toString: () => expectedTimestamp } } as Stats);
certificateManager.getIssuer.resolves({ CN: 'author' });
// Get the modification timestamp of the file
const newPlugin = await pluginsManagerService.getNewPlugin(pluginPath, ['arch1', 'arch2']);
const expectedPlugin = {
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
arches: ['arch1', 'arch2'],
timestamp: expectedTimestamp,
author: 'author',
};
expect(newPlugin).toEqual(expectedPlugin);
});
it('should remove plugin', async () => {
const pluginPath = '/path/to/plugin.jpl';
const manifest = {
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
};
const expectedTimestamp = 'test';
stub(Object.getPrototypeOf(pluginsManagerService), 'readManifest').resolves(manifest);
architectureService.getAllPluginArches.resolves(['arch1', 'arch2']);
fileManager.getStat.resolves({ mtime: { toString: () => expectedTimestamp } } as Stats);
certificateManager.getIssuer.resolves({ CN: 'author' });
// Get the modification timestamp of the file
await pluginsManagerService.getNewPlugin(pluginPath, ['test']);
pluginsManagerService.removePlugin('test');
const isAvailable = pluginsManagerService['isPluginAvailable']('test', 'test');
expect(isAvailable).toBeFalsy();
});
it('should return true if plugin is available', () => {
const plugin = {
id: 'test',
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
background: 'test',
timestamp: 'test',
author: 'test',
signature: Buffer.from(''),
};
const expected = [{
...plugin,
arches: ["test"],
}];
pluginsManagerService['plugins'] = expected;
const isAvailable = pluginsManagerService['isPluginAvailable']('test', 'test');
expect(isAvailable).toBeTruthy();
});
it('should return false if plugin is not available', async () => {
const isAvailable = pluginsManagerService['isPluginAvailable']('test', 'test');
expect(isAvailable).toBeFalsy();
});
it('should return manifest', async () => {
const pluginPath = '/path/to/plugin.jpl';
const manifest = {
name: 'test',
version: '1.0.0',
description: 'test',
iconPath: 'test.svg',
};
const expected = {
description: 'test',
icon: 'test.svg',
id: "test",
name: 'test',
version: '1.0.0',
};
fileManager.readArchive.resolves(Buffer.from(JSON.stringify(manifest)));
const actual = await pluginsManagerService['readManifest'](pluginPath);
expect(actual).toEqual(expected);
});
it('should return an array of plugin versions', async () => {
const plugins = [
{
id: 'plugin1',
name: 'plugin1',
version: '1.0.0',
description: 'Plugin 1',
icon: 'icon1',
background: 'background1',
arches: ['x64'],
timestamp: 'timestamp1',
author: 'author1',
signature: Buffer.from(''),
},
{
id: 'plugin2',
name: 'plugin2',
version: '2.0.0',
description: 'Plugin 2',
icon: 'icon2',
background: 'background2',
arches: ['x86', 'x64'],
timestamp: 'timestamp2',
author: 'author2',
signature: Buffer.from(''),
},
{
id: 'plugin3',
name: 'plugin3',
version: '3.0.0',
description: 'Plugin 3',
icon: 'icon3',
background: 'background3',
arches: ['x64'],
timestamp: 'timestamp3',
author: 'author3',
signature: Buffer.from(''),
},
];
pluginsManagerService['plugins'] = plugins;
const expectedVersions = [
{ id: 'plugin1', version: '1.0.0' },
{ id: 'plugin2', version: '2.0.0' },
{ id: 'plugin3', version: '3.0.0' },
];
const actualVersions = await pluginsManagerService.getVersions('x64');
expect(actualVersions).toEqual(expectedVersions);
});
it('should return undefined', async () => {
const actual = await pluginsManagerService['setPlugins']();
expect(actual).toBeUndefined();
});
it('should set plugins', async () => {
const dataDirectory = '/path/to/plugins';
const pluginsPath = '/path/to/plugins/plugin1';
const platformPath = 'platform1';
// Mock the necessary methods for this test
process.env.DATA_DIRECTORY = dataDirectory;
fileManager.listFiles.onFirstCall().resolves([pluginsPath]).onSecondCall().resolves([platformPath]);
// Create a spy for the getNewPlugin method
const getNewPluginStub = Sinon.stub(pluginsManagerService, 'getNewPlugin');
await pluginsManagerService['setPlugins']();
// Assert that the getNewPlugin method was called once
expect(getNewPluginStub.calledOnce).toBeTruthy();
// Restore the original getNewPlugin method
getNewPluginStub.restore();
});
it('should return true if plugin is not already installed and signature is valid', async () => {
const pluginPath = 'path/to/plugin';
const signature = Buffer.from('valid-signature');
architectureService.getAllPluginArches.resolves(['arch1', 'arch2']);
fileManager.readArchive.resolves(signature);
pluginsManagerService['plugins'] = [];
const result = await pluginsManagerService['checkPluginAlreadyPull'](pluginPath);
expect(result).toBe(true);
});
it('should return true if plugin is not already installed and signature is invalid', async () => {
const pluginPath = 'path/to/plugin';
const signature = Buffer.from('invalid-signature');
architectureService.getAllPluginArches.resolves(['arch1', 'arch2']);
fileManager.readArchive.resolves(signature);
pluginsManagerService['plugins'] = [];
const result = await pluginsManagerService['checkPluginAlreadyPull'](pluginPath);
expect(result).toBe(true);
});
it('should return false if plugin is already installed and signature is valid', async () => {
const pluginPath = 'path/to/plugin';
const signature = Buffer.from('valid-signature');
const plugin = {
id: 'test',
name: 'test',
version: '1.0.0',
description: 'test',
icon: 'test',
background: 'test',
timestamp: 'test',
signature: signature,
author: 'test',
};
const expected = [{
...plugin,
arches: ["test"],
}];
architectureService.getAllPluginArches.resolves(['test']);
fileManager.readArchive.resolves(signature);
pluginsManagerService['plugins'] = expected;
Sinon.stub(pluginsManagerService, 'findPlugin').resolves({...plugin, arches: ['test']});
const result = await pluginsManagerService['checkPluginAlreadyPull'](pluginPath);
expect(result).toBe(false);
});
});