| /** |
| 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 { tmpDir: getTmpDir, testPlatform } = require('../helpers'); |
| const projectTestHelpers = require('../project-test-helpers'); |
| |
| /** |
| * Checks if "cordova/restore-util" is restoring platforms and plugins as |
| * expected given different configurations of package.json and/or config.xml. |
| */ |
| describe('cordova/restore-util', () => { |
| let tmpDir, project, pkgJsonPath, configXmlPath; |
| let restore, cordovaPlatform, cordovaPlugin; |
| const { |
| getPkgJsonPath, getConfigXmlPath, setupBaseProject, getCfg, getPkgJson, setPkgJson |
| } = projectTestHelpers(() => project); |
| |
| beforeEach(() => { |
| tmpDir = getTmpDir('pkgJson'); |
| project = path.join(tmpDir, 'project'); |
| pkgJsonPath = getPkgJsonPath(); |
| configXmlPath = getConfigXmlPath(); |
| delete process.env.PWD; |
| |
| restore = require('../../src/cordova/restore-util'); |
| |
| cordovaPlugin = require('../../src/cordova/plugin'); |
| spyOn(cordovaPlugin, 'add') |
| .and.returnValue(Promise.resolve()); |
| |
| cordovaPlatform = require('../../src/cordova/platform'); |
| spyOn(cordovaPlatform, 'add') |
| .and.returnValue(Promise.resolve()); |
| |
| setupBaseProject(); |
| }); |
| |
| afterEach(() => { |
| process.chdir(__dirname); // Needed to rm the dir on Windows. |
| fs.rmSync(tmpDir, { recursive: true, force: true }); |
| }); |
| |
| function getCfgEngineNames (cfg = getCfg()) { |
| return cfg.getEngines().map(({ name }) => name); |
| } |
| |
| function platformPkgName (platformName) { |
| return platformName.replace(/^(?:cordova-)?/, 'cordova-'); |
| } |
| |
| function expectPluginsInPkgJson (plugins) { |
| const pkgJson = getPkgJson(); |
| expect(pkgJson).toBeDefined(); |
| |
| // Check that cordova.plugins key in package.json contains the expected |
| // variables and ONLY them |
| const variables = plugins.reduce((o, { name, variables }) => { |
| o[name] = variables; |
| return o; |
| }, {}); |
| expect(pkgJson.cordova).toBeDefined(); |
| expect(pkgJson.cordova.plugins).toEqual(variables); |
| |
| // Check that dependencies key in package.json contains the expected specs |
| // We only check the specs for plugins where an expected spec was given |
| const expectedSpecs = plugins.reduce((o, { name, spec }) => { |
| if (spec) o[name] = spec; |
| return o; |
| }, {}); |
| if (Object.keys(expectedSpecs).length > 0) { |
| const specs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies); |
| expect(specs).toEqual(jasmine.objectContaining(expectedSpecs)); |
| } |
| } |
| |
| function expectPlatformAdded (platform) { |
| const expectedOpts = { |
| platforms: jasmine.arrayContaining([ |
| jasmine.stringMatching(platform) |
| ]) |
| }; |
| |
| expect(cordovaPlatform.add).toHaveBeenCalledWith( |
| jasmine.anything(), jasmine.any(String), |
| jasmine.arrayContaining([platform]), |
| jasmine.objectContaining(expectedOpts) |
| ); |
| } |
| |
| function expectPluginAdded (plugin) { |
| const expectedOpts = { |
| plugins: jasmine.arrayContaining([ |
| jasmine.stringMatching(plugin.name) |
| ]) |
| }; |
| if ('variables' in plugin) { |
| expectedOpts.cli_variables = plugin.variables; |
| } |
| expect(cordovaPlugin.add).toHaveBeenCalledWith( |
| jasmine.any(String), jasmine.anything(), |
| jasmine.objectContaining(expectedOpts) |
| ); |
| } |
| |
| function expectPluginsAddedAndSavedToPkgJson (plugins) { |
| expectPluginsInPkgJson(plugins); |
| plugins.forEach(expectPluginAdded); |
| } |
| |
| describe('installPlatformsFromConfigXML', () => { |
| it('Test#001 : should restore saved platform from package.json', () => { |
| setPkgJson('cordova.platforms', [testPlatform]); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| // Check that the platform was properly restored |
| expectPlatformAdded(testPlatform); |
| }); |
| }); |
| |
| it('Test#017 : should restore saved platform from package.json using an URL spec', () => { |
| const PLATFORM = 'browser'; |
| const PLATFORM_URL = 'https://github.com/apache/cordova-browser'; |
| |
| setPkgJson('dependencies', { |
| [platformPkgName(PLATFORM)]: `git+${PLATFORM_URL}.git` |
| }); |
| setPkgJson('cordova.platforms', [PLATFORM]); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| // Check config.xml for spec modification. |
| expect(getCfg().getEngines()).not.toEqual([{ |
| name: PLATFORM, |
| spec: `git+${PLATFORM_URL}.git` |
| }]); |
| // No change to pkg.json. |
| const pkgJson = getPkgJson(); |
| expect(pkgJson.cordova.platforms).toEqual([PLATFORM]); |
| |
| const specs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies); |
| expect(specs[platformPkgName(PLATFORM)]).toEqual(`git+${PLATFORM_URL}.git`); |
| }); |
| }); |
| |
| it('Test#004 : should not modify either file if both have the same platforms', () => { |
| getCfg() |
| .addEngine(testPlatform) |
| .write(); |
| setPkgJson('cordova.platforms', [testPlatform]); |
| |
| const getModTimes = _ => ({ |
| cfg: fs.statSync(configXmlPath).mtime, |
| pkg: fs.statSync(pkgJsonPath).mtime |
| }); |
| const modTimes = getModTimes(); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| expect(getModTimes()).toEqual(modTimes); |
| }); |
| }); |
| |
| it('Test#005 : should update package.json to include platforms from config.xml', () => { |
| const PLATFORM_1 = 'android'; |
| const PLATFORM_2 = 'browser'; |
| |
| getCfg() |
| .addEngine(PLATFORM_1, '7.0.0') |
| .addEngine(PLATFORM_2, '^5.0.3') |
| .write(); |
| setPkgJson('cordova.platforms', [testPlatform]); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| const pkgJson = getPkgJson(); |
| // Expect both pkg.json and config.xml to each have both platforms in their arrays. |
| expect(getCfgEngineNames()).toEqual([PLATFORM_1, PLATFORM_2]); |
| expect(pkgJson.cordova.platforms).toEqual([PLATFORM_1, PLATFORM_2]); |
| |
| // Platform specs from config.xml have been added to pkg.json. |
| const specs = Object.assign({}, pkgJson.dependencies, pkgJson.devDependencies); |
| expect(specs).toEqual({ |
| [platformPkgName(PLATFORM_1)]: '7.0.0', |
| [platformPkgName(PLATFORM_2)]: '^5.0.3' |
| }); |
| }); |
| }); |
| |
| it('Test#006 : should update a package.json without `cordova` key to match platforms from config.xml', () => { |
| getCfg() |
| .addEngine('android') |
| .write(); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| // Expect no change to config.xml. |
| expect(getCfgEngineNames()).toEqual(['android']); |
| // Expect cordova key and 'android' platform to be added to pkg.json. |
| expect(getPkgJson('cordova.platforms')).toEqual(['android']); |
| }); |
| }); |
| |
| it('Test#007 : should find platform spec', () => { |
| setPkgJson('cordova.platforms', ['android']); |
| setPkgJson('devDependencies', { |
| 'cordova-android': '1.0.0' |
| }); |
| |
| return restore.installPlatformsFromConfigXML(['android'], {}).then(() => { |
| expect(cordovaPlatform.add).toHaveBeenCalledWith( |
| jasmine.anything(), |
| jasmine.anything(), |
| ['android@1.0.0'], |
| jasmine.anything() |
| ); |
| }); |
| }); |
| |
| it('Test#016 : should restore platforms & plugins and create a missing package.json', () => { |
| getCfg() |
| .addEngine(testPlatform) |
| .write(); |
| fs.rmSync(pkgJsonPath, { recursive: true, force: true }); |
| |
| return restore.installPlatformsFromConfigXML().then(() => { |
| // Package.json should be auto-created using values from config.xml |
| const cfg = getCfg(); |
| expect(getPkgJson()).toEqual(jasmine.objectContaining({ |
| name: cfg.packageName().toLowerCase(), |
| version: cfg.version(), |
| displayName: cfg.name() |
| })); |
| }); |
| }); |
| }); |
| |
| // These tests will check the plugin/variable list in package.json and config.xml. |
| describe('installPluginsFromConfigXML', () => { |
| beforeEach(() => { |
| // Add some platform to test the plugins with |
| setPkgJson('cordova.platforms', [testPlatform]); |
| }); |
| |
| it('Test#011 : restores saved plugin', () => { |
| setPkgJson('dependencies', { |
| 'cordova-plugin-camera': '^2.3.0' |
| }); |
| setPkgJson('cordova.plugins', { |
| 'cordova-plugin-camera': { variable_1: 'value_1' } |
| }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expectPluginAdded({ |
| name: 'cordova-plugin-camera', |
| spec: '^2.3.0', |
| variables: { variable_1: 'value_1' } |
| }); |
| }); |
| }); |
| |
| it('Test#012 : restores saved plugin using an URL spec', () => { |
| const PLUGIN_ID = 'cordova-plugin-splashscreen'; |
| const PLUGIN_URL = 'https://github.com/apache/cordova-plugin-splashscreen'; |
| |
| setPkgJson('dependencies', { |
| [PLUGIN_ID]: `git+${PLUGIN_URL}.git` |
| }); |
| setPkgJson('cordova.plugins', { [PLUGIN_ID]: {} }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expectPluginAdded({ |
| name: PLUGIN_ID, |
| spec: `git+${PLUGIN_URL}.git`, |
| variables: {} |
| }); |
| }); |
| }); |
| |
| it('Test#013 : does NOT detect plugins from dependencies ', () => { |
| setPkgJson('dependencies', { 'cordova-plugin-device': '~1.0.0' }); |
| setPkgJson('devDependencies', { 'cordova-plugin-camera': '~1.0.0' }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expect(cordovaPlugin.add).not.toHaveBeenCalled(); |
| }); |
| }); |
| |
| it('Test#014 : adds any plugins only present in config.xml to pkg.json', () => { |
| getCfg() |
| .addPlugin({ |
| name: 'cordova-plugin-device', |
| spec: '~1.0.0', |
| variables: {} |
| }) |
| .write(); |
| |
| setPkgJson('cordova.plugins', { 'cordova-plugin-camera': {} }); |
| setPkgJson('devDependencies', { 'cordova-plugin-camera': '^2.3.0' }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expectPluginsAddedAndSavedToPkgJson([{ |
| name: 'cordova-plugin-camera', |
| spec: '^2.3.0', |
| variables: {} |
| }, { |
| name: 'cordova-plugin-device', |
| spec: '~1.0.0', |
| variables: {} |
| }]); |
| }); |
| }); |
| |
| it('Test#015 : prefers pkg.json plugins over those from config.xml', () => { |
| getCfg() |
| .addPlugin({ |
| name: 'cordova-plugin-camera', |
| spec: '~2.2.0', |
| variables: { common_var: 'xml', xml_var: 'foo' } |
| }) |
| .write(); |
| |
| setPkgJson('cordova.plugins', { |
| 'cordova-plugin-camera': { common_var: 'json', json_var: 'foo' } |
| }); |
| setPkgJson('devDependencies', { 'cordova-plugin-camera': '^2.3.0' }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expectPluginsAddedAndSavedToPkgJson([{ |
| name: 'cordova-plugin-camera', |
| spec: '^2.3.0', |
| variables: { common_var: 'json', json_var: 'foo' } |
| }]); |
| }); |
| }); |
| |
| it('Test#018 : does NOT produce conflicting dependencies', () => { |
| getCfg() |
| .addPlugin({ |
| name: 'cordova-plugin-camera', |
| spec: '~2.2.0', |
| variables: { common_var: 'xml', xml_var: 'foo' } |
| }) |
| .write(); |
| |
| setPkgJson('dependencies', { 'cordova-plugin-camera': '^2.3.0' }); |
| |
| return restore.installPluginsFromConfigXML({ save: true }).then(() => { |
| expectPluginsAddedAndSavedToPkgJson([{ |
| name: 'cordova-plugin-camera', |
| spec: '^2.3.0', |
| variables: { common_var: 'xml', xml_var: 'foo' } |
| }]); |
| |
| const pluginOccurences = !!getPkgJson('dependencies.cordova-plugin-camera') + |
| !!getPkgJson('devDependencies.cordova-plugin-camera'); |
| expect(pluginOccurences).toBe(1); |
| }); |
| }); |
| }); |
| }); |