This is an automated email from the ASF dual-hosted git repository.
erisu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-browser.git
The following commit(s) were added to refs/heads/master by this push:
new d8b667d feat!: use PluginManager (#163)
d8b667d is described below
commit d8b667da8066b35114c1cb8b08e81dd64fc7207c
Author: エリス <[email protected]>
AuthorDate: Sun Jul 12 12:38:23 2026 +0900
feat!: use PluginManager (#163)
* Cleaned plugin add and remove APIs to use cordova-common PluginManager.
* Updated handlers API signature to match other platforms.
* PluginManager to handle writting the plugin module.
* Updated Tests
---
lib/Api.js | 253 ++++-----------------
lib/BrowserProject.js | 81 +++++++
lib/browser_handler.js | 127 ++++-------
test/browser_handler.spec.js | 139 ++++++-----
.../fixtures/fakeBrowserPlatformProject/config.xml | 34 +++
.../fakeBrowserPlatformProject/www/index.html | 28 +++
test/fixtures/fakePlugin/assets/ServiceWorker.txt | 20 ++
test/fixtures/fakePlugin/assets/folder/file1.txt | 20 ++
test/fixtures/fakePlugin/assets/folder/file2.txt | 20 ++
test/fixtures/fakePlugin/assets/reformat1.txt | 20 ++
test/fixtures/fakePlugin/assets/reformat2.txt | 20 ++
test/fixtures/fakePlugin/plugin.xml | 35 +++
12 files changed, 429 insertions(+), 368 deletions(-)
diff --git a/lib/Api.js b/lib/Api.js
index e253303..521d272 100644
--- a/lib/Api.js
+++ b/lib/Api.js
@@ -26,7 +26,6 @@ const path = require('node:path');
const fs = require('node:fs');
const {
- ActionStack,
ConfigChanges: { PlatformMunger },
ConfigParser,
CordovaLogger,
@@ -35,9 +34,11 @@ const {
FileUpdater,
PlatformJson,
PluginInfoProvider,
+ PluginManager,
xmlHelpers
} = require('cordova-common');
+const BrowserProject = require('./BrowserProject');
const { createProject } = require('./create');
const VERSION = require('../package').version;
@@ -75,7 +76,6 @@ class Api {
if (!dirExists(this.root) || !dirExists(path.join(this.root,
'cordova'))) {
throw new CordovaError(`The provided path "${this.root}" is not a
valid browser project.`);
}
- this._handler = require('./browser_handler');
this.locations = {
platformRootDir,
@@ -286,238 +286,63 @@ class Api {
}
async addPlugin (pluginInfo, installOptions) {
- // console.log(new Error().stack);
if (!pluginInfo) {
- return Promise.reject(
- new Error('The parameter is incorrect. The first parameter
should be valid PluginInfo instance')
- );
+ throw new Error('The parameter is incorrect. The first parameter
should be valid PluginInfo instance');
}
+ const project = BrowserProject.getProjectFile(this.root);
+
installOptions = installOptions || {};
installOptions.variables = installOptions.variables || {};
- // CB-10108 platformVersion option is required for proper plugin
installation
- installOptions.platformVersion = installOptions.platformVersion ||
- this.getPlatformInfo().version;
-
- const actions = new ActionStack();
- const projectFile = this._handler.parseProjectFile &&
this._handler.parseProjectFile(this.root);
-
- // gather all files needs to be handled during install
- pluginInfo.getFilesAndFrameworks(this.platform)
- .concat(pluginInfo.getAssets(this.platform))
- .concat(pluginInfo.getJsModules(this.platform))
- .forEach(item => {
- actions.push(actions.createAction(
- this._getInstaller(item.itemType, item, pluginInfo.dir,
pluginInfo.id, installOptions, projectFile),
- this._getUninstaller(item.itemType, item, pluginInfo.dir,
pluginInfo.id, installOptions, projectFile)
- ));
- });
-
- // run through the action stack
- return actions.process(this.platform, this.root)
- .then(() => {
- if (projectFile) {
- projectFile.write();
- }
-
- // Add PACKAGE_NAME variable into vars
- if (!installOptions.variables.PACKAGE_NAME) {
- installOptions.variables.PACKAGE_NAME =
this._handler.package_name(this.root);
- }
-
- this._munger
- // Ignore passed `is_top_level` option since platform
itself doesn't know
- // anything about managing dependencies - it's
responsibility of caller.
- .add_plugin_changes(pluginInfo, installOptions.variables,
/* is_top_level= */true, /* should_increment= */true)
- .save_all();
-
- const targetDir = installOptions.usePlatformWww
- ? this.getPlatformInfo().locations.platformWww
- : this.getPlatformInfo().locations.www;
- this.#addModulesInfo(pluginInfo, targetDir);
- });
- }
-
- async removePlugin (plugin, uninstallOptions) {
- // console.log("NotImplemented :: browser-platform:Api:removePlugin
",plugin, uninstallOptions);
-
- uninstallOptions = uninstallOptions || {};
// CB-10108 platformVersion option is required for proper plugin
installation
- uninstallOptions.platformVersion = uninstallOptions.platformVersion ||
+ installOptions.platformVersion = installOptions.platformVersion ||
this.getPlatformInfo().version;
- const actions = new ActionStack();
- const projectFile = this._handler.parseProjectFile &&
this._handler.parseProjectFile(this.root);
-
- // queue up plugin files
- plugin.getFilesAndFrameworks(this.platform)
- .concat(plugin.getAssets(this.platform))
- .concat(plugin.getJsModules(this.platform))
- .forEach(item => {
- actions.push(actions.createAction(
- this._getUninstaller(item.itemType, item, plugin.dir,
plugin.id, uninstallOptions, projectFile),
- this._getInstaller(item.itemType, item, plugin.dir,
plugin.id, uninstallOptions, projectFile)
- ));
- });
-
- // run through the action stack
- return actions.process(this.platform, this.root)
- .then(() => {
- if (projectFile) {
- projectFile.write();
- }
-
- this._munger
- // Ignore passed `is_top_level` option since platform
itself doesn't know
- // anything about managing dependencies - it's
responsibility of caller.
- .remove_plugin_changes(plugin, /* is_top_level= */true)
- .save_all();
-
- const targetDir = uninstallOptions.usePlatformWww
- ? this.getPlatformInfo().locations.platformWww
- : this.getPlatformInfo().locations.www;
-
- this.#removeModulesInfo(plugin, targetDir);
- // Remove stale plugin directory
- // TODO: this should be done by plugin files uninstaller
- fs.rmSync(
- path.resolve(this.root, 'Plugins', plugin.id),
- { force: true, recursive: true }
- );
- });
- }
-
- _getInstaller (type, item, plugin_dir, plugin_id, options, project) {
- const installer = this._handler[type];
-
- if (!installer) {
- console.log(`unrecognized type ${type}`);
- } else {
- const wwwDest = options.usePlatformWww
- ? this.getPlatformInfo().locations.platformWww
- : this._handler.www_dir(this.root);
-
- if (type === 'asset') {
- installer.install(item, plugin_dir, wwwDest);
- } else if (type === 'js-module') {
- installer.install(item, plugin_dir, plugin_id, wwwDest);
- } else {
- installer.install(item, plugin_dir, this.root, plugin_id,
options, project);
- }
+ // Add PACKAGE_NAME variable into vars
+ if (!installOptions.variables.PACKAGE_NAME) {
+ installOptions.variables.PACKAGE_NAME =
project.getPackageName(this.root);
}
- }
- _getUninstaller (type, item, plugin_dir, plugin_id, options, project) {
- const installer = this._handler[type];
+ await PluginManager.get(this.platform, this.locations, project)
+ .addPlugin(pluginInfo, installOptions);
- if (!installer) {
- console.log(`browser plugin uninstall: unrecognized type, skipping
: ${type}`);
- } else {
- const wwwDest = options.usePlatformWww
- ? this.getPlatformInfo().locations.platformWww
- : this._handler.www_dir(this.root);
-
- if (['asset', 'js-module'].includes(type)) {
- return installer.uninstall(item, wwwDest, plugin_id);
- } else {
- return installer.uninstall(item, this.root, plugin_id,
options, project);
- }
- }
+ return true;
}
- /**
- * Removes the specified modules from list of installed modules and updates
- * platform_json and cordova_plugins.js on disk.
- *
- * @param {PluginInfo} plugin PluginInfo instance for plugin, which
modules
- * needs to be added.
- * @param {String} targetDir The directory, where updated
cordova_plugins.js
- * should be written to.
- */
- #addModulesInfo (plugin, targetDir) {
- const installedModules = this._platformJson.root.modules || [];
- const installedPaths = installedModules.map(installedModule =>
installedModule.file);
-
- const modulesToInstall = plugin.getJsModules(this.platform)
- .filter(moduleToInstall =>
!installedPaths.includes(moduleToInstall.file))
- .map(moduleToInstall => {
- const moduleName = plugin.id + '.' + (moduleToInstall.name ||
moduleToInstall.src.match(/([^/]+)\.js/)[1]);
- const obj = {
- file: ['plugins', plugin.id,
moduleToInstall.src].join('/'),
- id: moduleName,
- pluginId: plugin.id
- };
- if (moduleToInstall.clobbers.length > 0) {
- obj.clobbers = moduleToInstall.clobbers.map(o => o.target);
- }
- if (moduleToInstall.merges.length > 0) {
- obj.merges = moduleToInstall.merges.map(o => o.target);
- }
- if (moduleToInstall.runs) {
- obj.runs = true;
- }
-
- return obj;
- });
-
- this._platformJson.root.modules =
installedModules.concat(modulesToInstall);
- if (!this._platformJson.root.plugin_metadata) {
- this._platformJson.root.plugin_metadata = {};
+ async removePlugin (pluginInfo, uninstallOptions) {
+ if (!pluginInfo) {
+ throw new Error('The parameter is incorrect. The first parameter
should be valid PluginInfo instance');
}
- this._platformJson.root.plugin_metadata[plugin.id] = plugin.version;
- this.#writePluginModules(targetDir);
- this._platformJson.save();
- }
-
- /**
- * Fetches all installed modules, generates cordova_plugins contents and
writes
- * it to file.
- *
- * @param {String} targetDir Directory, where write cordova_plugins.js
to.
- * Ususally it is either <platform>/www or <platform>/platform_www
- * directories.
- */
- #writePluginModules (targetDir) {
- // Write out moduleObjects as JSON wrapped in a cordova module to
cordova_plugins.js
- let final_contents = 'cordova.define(\'cordova/plugin_list\',
function(require, exports, module) {\n';
- final_contents += `module.exports =
${JSON.stringify(this._platformJson.root.modules, null, ' ')};\n`;
- final_contents += 'module.exports.metadata = \n';
- final_contents += '// TOP OF METADATA\n';
- final_contents +=
JSON.stringify(this._platformJson.root.plugin_metadata || {}, null, ' ') +
'\n';
- final_contents += '// BOTTOM OF METADATA\n';
- final_contents += '});'; // Close cordova.define.
-
- fs.mkdirSync(targetDir, { recursive: true });
- fs.writeFileSync(path.join(targetDir, 'cordova_plugins.js'),
final_contents, 'utf-8');
- }
+ const project = BrowserProject.getProjectFile(this.root);
- /**
- * Removes the specified modules from list of installed modules and updates
- * platform_json and cordova_plugins.js on disk.
- *
- * @param {PluginInfo} plugin PluginInfo instance for plugin, which
modules
- * needs to be removed.
- * @param {String} targetDir The directory, where updated
cordova_plugins.js
- * should be written to.
- */
- #removeModulesInfo (plugin, targetDir) {
- const installedModules = this._platformJson.root.modules || [];
- const modulesToRemove = plugin.getJsModules(this.platform)
- .map(jsModule => ['plugins', plugin.id, jsModule.src].join('/'));
-
- const updatedModules = installedModules.filter(
- installedModule => !modulesToRemove.includes(installedModule.file)
- );
+ uninstallOptions = uninstallOptions || {};
+ uninstallOptions.variables = uninstallOptions.variables || {};
- this._platformJson.root.modules = updatedModules;
- if (this._platformJson.root.plugin_metadata) {
- delete this._platformJson.root.plugin_metadata[plugin.id];
+ // Add PACKAGE_NAME variable into vars
+ if (!uninstallOptions.variables.PACKAGE_NAME) {
+ uninstallOptions.variables.PACKAGE_NAME =
project.getPackageName(this.root);
}
- this.#writePluginModules(targetDir);
- this._platformJson.save();
+ await PluginManager.get(this.platform, this.locations, project)
+ .removePlugin(pluginInfo, uninstallOptions)
+ .then(
+ () => {
+ const targetDir = uninstallOptions.usePlatformWww
+ ? this.getPlatformInfo().locations.platformWww
+ : this.getPlatformInfo().locations.www;
+
+ // Remove stale plugin directory
+ // TODO: this should be done by plugin files uninstaller
+ fs.rmSync(
+ path.resolve(targetDir, 'plugins', pluginInfo.id),
+ { force: true, recursive: true }
+ );
+ }
+ );
+
+ return true;
}
async build (buildOptions) {
diff --git a/lib/BrowserProject.js b/lib/BrowserProject.js
new file mode 100644
index 0000000..b14fb53
--- /dev/null
+++ b/lib/BrowserProject.js
@@ -0,0 +1,81 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+const fs = require('node:fs');
+const path = require('node:path');
+const pluginHandlers = require('./browser_handler');
+
+let projectFileCache = {};
+
+class BrowserProject {
+ constructor (projectDir) {
+ this._dirty = false;
+ this.projectDir = projectDir;
+ this.platformWww = path.join(this.projectDir, 'platform_www');
+ this.www = path.join(this.projectDir, 'www');
+ }
+
+ /**
+ * Reads the package name out of the project's config.xml
+ *
+ * @param {String} projectDir The absolute path to the directory
containing the project
+ * @return {String} The name of the package
+ */
+ getPackageName (projectDir) {
+ // this method should the id from root config.xml => <widget id=xxx
+ let pkgName = 'io.cordova.hellocordova';
+ const widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
+
+ const configPath = path.join(projectDir, 'config.xml');
+ if (fs.existsSync(configPath)) {
+ const configStr = fs.readFileSync(configPath, 'utf8');
+ const res = configStr.match(widget_id_regex);
+ if (res && res.length > 1) {
+ pkgName = res[1];
+ }
+ }
+ return pkgName;
+ }
+
+ getInstaller (type) {
+ return pluginHandlers.getInstaller(type);
+ }
+
+ getUninstaller (type) {
+ return pluginHandlers.getUninstaller(type);
+ }
+
+ static getProjectFile (projectDir) {
+ if (!projectFileCache[projectDir]) {
+ projectFileCache[projectDir] = new BrowserProject(projectDir);
+ }
+
+ return projectFileCache[projectDir];
+ }
+
+ static purgeCache (projectDir) {
+ if (projectDir) {
+ delete projectFileCache[projectDir];
+ } else {
+ projectFileCache = {};
+ }
+ }
+}
+
+module.exports = BrowserProject;
diff --git a/lib/browser_handler.js b/lib/browser_handler.js
index fb786bb..604738b 100644
--- a/lib/browser_handler.js
+++ b/lib/browser_handler.js
@@ -22,101 +22,48 @@ const fs = require('node:fs');
const { events } = require('cordova-common');
-module.exports = {
- www_dir: function (project_dir) {
- return path.join(project_dir, 'www');
- },
- package_name: function (project_dir) {
- // this method should the id from root config.xml => <widget id=xxx
- // return common.package_name(project_dir, this.www_dir(project_dir));
- // console.log('package_name called with ' + project_dir);
- let pkgName = 'io.cordova.hellocordova';
- const widget_id_regex = /(?:<widget\s+id=['"])(\S+)(?:['"])/;
-
- const configPath = path.join(project_dir, 'config.xml');
- if (fs.existsSync(configPath)) {
- const configStr = fs.readFileSync(configPath, 'utf8');
- const res = configStr.match(widget_id_regex);
- if (res && res.length > 1) {
- pkgName = res[1];
- }
- }
- return pkgName;
- },
+const handlers = {
'js-module': {
- install: function (jsModule, plugin_dir, plugin_id, www_dir) {
+ install: function (obj, plugin, project, options) {
+ const destRoot = options && options.usePlatformWww
+ ? project.platformWww
+ : project.www;
// Copy the plugin's files into the www directory.
- const moduleSource = path.resolve(plugin_dir, jsModule.src);
+ const moduleSource = path.resolve(plugin.dir, obj.src);
// Get module name based on existing 'name' attribute or filename
// Must use path.extname/path.basename instead of path.parse due
to CB-9981
- const moduleName = plugin_id + '.' + (jsModule.name ||
path.basename(jsModule.src, path.extname(jsModule.src)));
-
+ const moduleName = plugin.id + '.' + (obj.name ||
path.basename(obj.src, path.extname(obj.src)));
// Read in the file, prepend the cordova.define, and write it back
out.
let scriptContent = fs.readFileSync(moduleSource,
'utf-8').replace(/^\ufeff/, ''); // Window BOM
+
if (moduleSource.match(/.*\.json$/)) {
scriptContent = `module.exports = ${scriptContent}`;
}
scriptContent = `cordova.define("${moduleName}", function(require,
exports, module) { ${scriptContent}\n});\n`;
- const moduleDestination = path.resolve(www_dir, 'plugins',
plugin_id, jsModule.src);
+ const moduleDestination = path.resolve(destRoot, 'plugins',
plugin.id, obj.src);
+
fs.mkdirSync(path.dirname(moduleDestination), { recursive: true });
fs.writeFileSync(moduleDestination, scriptContent, 'utf-8');
},
- uninstall: function (jsModule, www_dir, plugin_id) {
- const pluginRelativePath = path.join('plugins', plugin_id,
jsModule.src);
- // common.removeFileAndParents(www_dir, pluginRelativePath);
- console.log(`js-module uninstall called : ${pluginRelativePath}`);
- }
- },
- 'source-file': {
- install: function (obj, plugin_dir, project_dir, plugin_id, options) {
- // var dest = path.join(obj.targetDir, path.basename(obj.src));
- // common.copyFile(plugin_dir, obj.src, project_dir, dest);
- console.log('install called');
- },
- uninstall: function (obj, project_dir, plugin_id, options) {
- // var dest = path.join(obj.targetDir, path.basename(obj.src));
- // common.removeFile(project_dir, dest);
- console.log('uninstall called');
- }
- },
- 'header-file': {
- install: function (obj, plugin_dir, project_dir, plugin_id, options) {
- events.emit('verbose', 'header-fileinstall is not supported for
browser');
- },
- uninstall: function (obj, project_dir, plugin_id, options) {
- events.emit('verbose', 'header-file.uninstall is not supported for
browser');
- }
- },
- 'resource-file': {
- install: function (obj, plugin_dir, project_dir, plugin_id, options) {
- events.emit('verbose', 'resource-file.install is not supported for
browser');
- },
- uninstall: function (obj, project_dir, plugin_id, options) {
- events.emit('verbose', 'resource-file.uninstall is not supported
for browser');
- }
- },
- framework: {
- install: function (obj, plugin_dir, project_dir, plugin_id, options) {
- events.emit('verbose', 'framework.install is not supported for
browser');
- },
- uninstall: function (obj, project_dir, plugin_id, options) {
- events.emit('verbose', 'framework.uninstall is not supported for
browser');
- }
- },
- 'lib-file': {
- install: function (obj, plugin_dir, project_dir, plugin_id, options) {
- events.emit('verbose', 'lib-file.install is not supported for
browser');
- },
- uninstall: function (obj, project_dir, plugin_id, options) {
- events.emit('verbose', 'lib-file.uninstall is not supported for
browser');
+ uninstall: function (obj, plugin, project, options) {
+ const destRoot = options && options.usePlatformWww
+ ? project.platformWww
+ : project.www;
+ const pluginRelativePath = path.join('plugins', plugin.id,
obj.src);
+
+ fs.rmSync(path.join(destRoot, pluginRelativePath), { force: true
});
}
},
asset: {
- install: function (asset, plugin_dir, wwwDest) {
- const src = path.join(plugin_dir, asset.src);
- const dest = path.join(wwwDest, asset.target);
+ install: function (obj, plugin, project, options) {
+ const destRoot = options && options.usePlatformWww
+ ? project.platformWww
+ : project.www;
+ const src = path.join(plugin.dir, obj.src);
+ const dest = path.join(destRoot, obj.target);
const destDir = path.parse(dest).dir;
+
if (destDir !== '' && !fs.existsSync(destDir)) {
fs.mkdirSync(destDir, { recursive: true });
}
@@ -127,9 +74,29 @@ module.exports = {
fs.cpSync(src, dest, { force: true });
}
},
- uninstall: function (asset, wwwDest, plugin_id) {
- fs.rmSync(path.join(wwwDest, asset.target), { recursive: true,
force: true });
- fs.rmSync(path.join(wwwDest, 'plugins', plugin_id), { recursive:
true, force: true });
+ uninstall: function (obj, plugin, project, options) {
+ const destRoot = options && options.usePlatformWww
+ ? project.platformWww
+ : project.www;
+
+ fs.rmSync(path.join(destRoot, obj.target), { recursive: true,
force: true });
+ fs.rmSync(path.join(destRoot, 'plugins', plugin.id), { recursive:
true, force: true });
}
}
};
+
+module.exports.getInstaller = function (type) {
+ if (handlers[type] && handlers[type].install) {
+ return handlers[type].install;
+ }
+
+ events.emit('verbose', '<' + type + '> is not supported for browser
plugins');
+};
+
+module.exports.getUninstaller = function (type) {
+ if (handlers[type] && handlers[type].uninstall) {
+ return handlers[type].uninstall;
+ }
+
+ events.emit('verbose', '<' + type + '> is not supported for browser
plugins');
+};
diff --git a/test/browser_handler.spec.js b/test/browser_handler.spec.js
index 84e4b8d..ca95513 100644
--- a/test/browser_handler.spec.js
+++ b/test/browser_handler.spec.js
@@ -17,112 +17,103 @@
under the License.
*/
-const { describe, it, mock } = require('node:test');
+const { describe, it, mock, before } = require('node:test');
const assert = require('node:assert');
const fs = require('node:fs');
const path = require('node:path');
+const tmp = require('tmp');
+const { PluginInfo } = require('cordova-common');
-const browser_handler = require('../lib/browser_handler');
+const BrowserHandler = require('../lib/browser_handler');
+const BrowserProject = require('../lib/BrowserProject');
+
+tmp.setGracefulCleanup();
+
+function makeTempDir () {
+ const tempdir = tmp.dirSync({ unsafeCleanup: true });
+ return path.join(tempdir.name,
`cordova-browser-browser-handler-test-${Date.now()}`);
+}
describe('Asset install tests', () => {
- const asset = {
- itemType: 'asset',
- src: path.join('someSrc', 'ServiceWorker.js'),
- target: 'ServiceWorker.js'
- };
- const assetWithPath = {
- itemType: 'asset',
- src: path.join('someSrc', 'reformat.js'),
- target: path.join('js', 'deepdown', 'reformat.js')
- };
- const assetWithPath2 = {
- itemType: 'asset',
- src: path.join('someSrc', 'reformat.js'),
- target: path.join('js', 'deepdown', 'reformat2.js')
- };
-
- const plugin_dir = 'pluginDir';
- const wwwDest = 'dest';
-
- it('if src is a directory, should be called with cpSync recursive force',
() => {
- const cpSyncSpy = mock.method(fs, 'cpSync', () => {});
- const mkdirSyncSpy = mock.method(fs, 'mkdirSync', () => {});
- mock.method(fs, 'statSync', () => ({
- isDirectory: () => true
- }));
-
- browser_handler.asset.install(asset, plugin_dir, wwwDest);
+ let pluginInfo;
+ let browserProject;
+
+ before(() => {
+ const testDir = makeTempDir();
+ fs.cpSync(path.join(__dirname, 'fixtures',
'fakeBrowserPlatformProject'), testDir, { recursive: true });
+ pluginInfo = new PluginInfo(path.join(__dirname, 'fixtures',
'fakePlugin'));
+ browserProject = new BrowserProject(testDir);
+ });
- assert.ok(
- mkdirSyncSpy.mock.calls.some(({ arguments: args }) => (
- args[0] === wwwDest &&
- args[1]?.recursive === true
- ))
- );
+ it('if src is a file, should call cpSync with force', async () => {
+ const cpSyncSpy = mock.method(fs, 'cpSync');
+ const mkdirSyncSpy = mock.method(fs, 'mkdirSync');
+ const assets = pluginInfo.getAssets('browser');
+ const asset = assets.find(a => a.src.includes('ServiceWorker.txt'));
+
+ const install = BrowserHandler.getInstaller('asset');
+ await install(asset, pluginInfo, browserProject, {});
+ assert.strictEqual(mkdirSyncSpy.mock.calls.length, 0);
assert.ok(
cpSyncSpy.mock.calls.some(({ arguments: args }) => (
- typeof args[0] === 'string' &&
- args[1] === path.join('dest', asset.target) &&
- args[2]?.recursive === true &&
+ args[0].endsWith(path.join('fakePlugin', 'assets',
'ServiceWorker.txt')) &&
+ args[1].endsWith(path.join('www', 'ServiceWorker.txt')) &&
args[2]?.force === true
))
);
});
- it('if src is not a directory and asset has no path, should be called with
cp, -f', () => {
- const cpSyncSpy = mock.method(fs, 'cpSync', () => {});
+ it('if the target directory path does not exist, should call mkdirSync &
cpSync', async () => {
+ const cpSyncSpy = mock.method(fs, 'cpSync');
const mkdirSyncSpy = mock.method(fs, 'mkdirSync');
- mock.method(fs, 'existsSync', () => true);
- mock.method(fs, 'statSync', () => ({
- isDirectory: () => false
- }));
+ const assets = pluginInfo.getAssets('browser');
+ const asset1 = assets.find(a => a.src.includes('reformat1.txt'));
- browser_handler.asset.install(asset, plugin_dir, wwwDest);
+ const install = BrowserHandler.getInstaller('asset');
+ await install(asset1, pluginInfo, browserProject, {});
- assert.strictEqual(mkdirSyncSpy.mock.calls.length, 0); // not was
called
+ assert.strictEqual(mkdirSyncSpy.mock.calls.length, 1);
assert.ok(
cpSyncSpy.mock.calls.some(({ arguments: args }) => (
- args[0] === path.join('pluginDir', asset.src) &&
- args[1] === path.join('dest', asset.target) &&
+ args[0].endsWith(path.join('fakePlugin', 'assets',
'reformat1.txt')) &&
+ args[1].endsWith(path.join('www', 'js', 'deepdown',
'reformat1.txt')) &&
args[2]?.force === true
))
);
- });
- it('if src is not a directory and asset has a path, should be called with
cp, -f', () => {
- /*
- Test that a dest directory gets created if it does not exist
- */
- const cpSyncSpy = mock.method(fs, 'cpSync', () => {});
- const mkdirSyncSpy = mock.method(fs, 'mkdirSync');
- mock.method(fs, 'statSync', () => ({
- isDirectory: () => false
- }));
- mock.method(fs, 'existsSync', () => false);
-
- browser_handler.asset.install(assetWithPath, plugin_dir, wwwDest);
+ // Test another upload
+ const asset2 = assets.find(a => a.src.includes('reformat2.txt'));
+ await install(asset2, pluginInfo, browserProject, {});
+ // Should still be 1
+ assert.strictEqual(mkdirSyncSpy.mock.calls.length, 1);
assert.ok(
- mkdirSyncSpy.mock.calls.some(({ arguments: args }) => (
- args[0] === path.join('dest', 'js', 'deepdown') &&
- args[1]?.recursive === true
+ cpSyncSpy.mock.calls.some(({ arguments: args }) => (
+ args[0].endsWith(path.join('fakePlugin', 'assets',
'reformat2.txt')) &&
+ args[1].endsWith(path.join('www', 'js', 'deepdown',
'reformat2.txt')) &&
+ args[2]?.force === true
))
);
+ });
+ it('if src is a directory, it should call cpSync with force and
recursive', async () => {
+ const cpSyncSpy = mock.method(fs, 'cpSync');
+ const mkdirSyncSpy = mock.method(fs, 'mkdirSync');
+ const assets = pluginInfo.getAssets('browser');
+ const asset = assets.find(a => a.src.includes('folder'));
+
+ const install = BrowserHandler.getInstaller('asset');
+ await install(asset, pluginInfo, browserProject, {});
+
+ assert.strictEqual(mkdirSyncSpy.mock.calls.length, 0);
assert.ok(
cpSyncSpy.mock.calls.some(({ arguments: args }) => (
- args[0] === path.join('pluginDir', assetWithPath.src) &&
- args[1] === path.join('dest', assetWithPath.target) &&
- args[2]?.force === true
+ args[0].endsWith(path.join('fakePlugin', 'assets', 'folder'))
&&
+ args[1].endsWith(path.join('www', 'folder')) &&
+ args[2]?.force === true &&
+ args[2]?.recursive === true
))
);
-
- /*
- Now test that a second call to the same dest folder skips mkdir
because the first asset call should have created it.
- */
- mock.method(fs, 'existsSync', () => true);
- browser_handler.asset.install(assetWithPath2, plugin_dir, wwwDest);
- assert.strictEqual(mkdirSyncSpy.mock.calls.length, 1); // not called
again
});
});
diff --git a/test/fixtures/fakeBrowserPlatformProject/config.xml
b/test/fixtures/fakeBrowserPlatformProject/config.xml
new file mode 100644
index 0000000..c3eede9
--- /dev/null
+++ b/test/fixtures/fakeBrowserPlatformProject/config.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<widget xmlns="http://www.w3.org/ns/widgets"
+ xmlns:cdv="http://cordova.apache.org/ns/1.0"
+ id="org.apache.cordova.hellocordova"
+ version="1.0.0">
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready
event.
+ </description>
+ <author email="[email protected]" href="https://cordova.apache.org">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+ <allow-intent href="http://*/*" />
+ <allow-intent href="https://*/*" />
+</widget>
diff --git a/test/fixtures/fakeBrowserPlatformProject/www/index.html
b/test/fixtures/fakeBrowserPlatformProject/www/index.html
new file mode 100644
index 0000000..003848b
--- /dev/null
+++ b/test/fixtures/fakeBrowserPlatformProject/www/index.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="user-scalable=no, initial-scale=1,
maximum-scale=1, minimum-scale=1, width=device-width, height=device-height,
target-densitydpi=device-dpi" />
+ <title>Fake Project</title>
+ </head>
+ <body>
+ </body>
+</html>
diff --git a/test/fixtures/fakePlugin/assets/ServiceWorker.txt
b/test/fixtures/fakePlugin/assets/ServiceWorker.txt
new file mode 100644
index 0000000..5949aff
--- /dev/null
+++ b/test/fixtures/fakePlugin/assets/ServiceWorker.txt
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// empty test file
diff --git a/test/fixtures/fakePlugin/assets/folder/file1.txt
b/test/fixtures/fakePlugin/assets/folder/file1.txt
new file mode 100644
index 0000000..5949aff
--- /dev/null
+++ b/test/fixtures/fakePlugin/assets/folder/file1.txt
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// empty test file
diff --git a/test/fixtures/fakePlugin/assets/folder/file2.txt
b/test/fixtures/fakePlugin/assets/folder/file2.txt
new file mode 100644
index 0000000..5949aff
--- /dev/null
+++ b/test/fixtures/fakePlugin/assets/folder/file2.txt
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// empty test file
diff --git a/test/fixtures/fakePlugin/assets/reformat1.txt
b/test/fixtures/fakePlugin/assets/reformat1.txt
new file mode 100644
index 0000000..5949aff
--- /dev/null
+++ b/test/fixtures/fakePlugin/assets/reformat1.txt
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// empty test file
diff --git a/test/fixtures/fakePlugin/assets/reformat2.txt
b/test/fixtures/fakePlugin/assets/reformat2.txt
new file mode 100644
index 0000000..5949aff
--- /dev/null
+++ b/test/fixtures/fakePlugin/assets/reformat2.txt
@@ -0,0 +1,20 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+*/
+
+// empty test file
diff --git a/test/fixtures/fakePlugin/plugin.xml
b/test/fixtures/fakePlugin/plugin.xml
new file mode 100644
index 0000000..32207b4
--- /dev/null
+++ b/test/fixtures/fakePlugin/plugin.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+ id="cordova-plugin-fake-plugin"
+ version="1.0.0">
+ <name>Fake Plugin</name>
+ <description>Cordova Fake Plugin</description>
+ <license>Apache 2.0</license>
+ <keywords>cordova</keywords>
+
+ <!-- Test Case 1: Copies to www dir -->
+ <asset src="assets/ServiceWorker.txt" target="ServiceWorker.txt" />
+ <!-- Test Case 2: Makes js/deepdown directory then copies file -->
+ <asset src="assets/reformat1.txt" target="js/deepdown/reformat1.txt" />
+ <asset src="assets/reformat2.txt" target="js/deepdown/reformat2.txt" />
+ <!-- Test Case 3: recursive copies -->
+ <asset src="assets/folder" target="folder" />
+</plugin>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]