You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by dp...@apache.org on 2024/08/21 07:22:28 UTC
(cordova-ios) branch master updated: feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations (#1465)
This is an automated email from the ASF dual-hosted git repository.
dpogue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cordova-ios.git
The following commit(s) were added to refs/heads/master by this push:
new 3ce3a7e0 feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations (#1465)
3ce3a7e0 is described below
commit 3ce3a7e081442b9906030bec7e8800a598d470e8
Author: Darryl Pogue <da...@dpogue.ca>
AuthorDate: Wed Aug 21 00:22:23 2024 -0700
feat(icons)!: Support a single 1024⨉1024 icon, but also more complex customizations (#1465)
* feat(icons)!: Use a single 1024⨉1024 icon
Closes GH-1462.
* feat!(icons): Allow a lot more control over icon assignment
Ironically, this also allows most people to drastically simplify their
icons by only providing a single 1024⨉1024 image with no special
attributes.
Closes GH-592.
Closes GH-623.
Closes GH-657.
Closes GH-658.
Closes GH-1019.
Closes GH-1233.
Closes GH-1387.
* fix: Only support tinted/dark icons if using Xcode 16+
Xcode 15 doesn't understand the appearance variants, and if variants are
specified then it thinks there are 3 images assigned to the same slot
and ends up picking one at random and we don't want that.
---------
Co-authored-by: jcesarmobile <jc...@gmail.com>
---
lib/prepare.js | 281 ++++++++++++----
.../AppIcon.appiconset/Contents.json | 237 +-------------
.../AppIcon.appiconset/icon-1024.png | Bin 35783 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-20.png | Bin 476 -> 0 bytes
.../AppIcon.appiconset/icon-20@2x.png | Bin 934 -> 0 bytes
.../AppIcon.appiconset/icon-20@3x.png | Bin 1417 -> 0 bytes
.../AppIcon.appiconset/icon-24@2x.png | Bin 1136 -> 0 bytes
.../AppIcon.appiconset/icon-27.5@2x.png | Bin 1325 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-29.png | Bin 723 -> 0 bytes
.../AppIcon.appiconset/icon-29@2x.png | Bin 1367 -> 0 bytes
.../AppIcon.appiconset/icon-29@3x.png | Bin 2065 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-40.png | Bin 934 -> 0 bytes
.../AppIcon.appiconset/icon-40@2x.png | Bin 1892 -> 0 bytes
.../AppIcon.appiconset/icon-44@2x.png | Bin 2069 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-50.png | Bin 1173 -> 0 bytes
.../AppIcon.appiconset/icon-50@2x.png | Bin 2270 -> 0 bytes
.../AppIcon.appiconset/icon-60@2x.png | Bin 2712 -> 0 bytes
.../AppIcon.appiconset/icon-60@3x.png | Bin 4304 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-72.png | Bin 1681 -> 0 bytes
.../AppIcon.appiconset/icon-72@2x.png | Bin 3315 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-76.png | Bin 1764 -> 0 bytes
.../AppIcon.appiconset/icon-76@2x.png | Bin 3518 -> 0 bytes
.../AppIcon.appiconset/icon-83.5@2x.png | Bin 3842 -> 0 bytes
.../AppIcon.appiconset/icon-86@2x.png | Bin 4022 -> 0 bytes
.../AppIcon.appiconset/icon-98@2x.png | Bin 4744 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon.png | Bin 1376 -> 31816 bytes
.../Assets.xcassets/AppIcon.appiconset/icon@2x.png | Bin 2568 -> 0 bytes
.../unit/fixtures/icon-support/configs/multi.xml | 42 +++
.../unit/fixtures/icon-support/configs/none.xml | 24 ++
.../fixtures/icon-support/configs/single-only.xml | 27 ++
.../icon-support/configs/single-variants.xml | 27 ++
.../fixtures/icon-support/contents-json/multi.js | 145 ++++++++
.../fixtures/icon-support/contents-json/none.js | 39 +++
.../icon-support/contents-json/single-only.js | 39 +++
.../icon-support/contents-json/single-variants.js | 63 ++++
.../icon-support/res/ios/AppIcon-1024x1024@1x.png | Bin 0 -> 11062 bytes
.../icon-support/res/ios/AppIcon-20x20@2x.png | Bin 0 -> 730 bytes
.../icon-support/res/ios/AppIcon-20x20@3x.png | Bin 0 -> 947 bytes
.../icon-support/res/ios/AppIcon-29x29@2x.png | Bin 0 -> 959 bytes
.../icon-support/res/ios/AppIcon-29x29@3x.png | Bin 0 -> 1219 bytes
.../icon-support/res/ios/AppIcon-38x38@2x.png | Bin 0 -> 1182 bytes
.../icon-support/res/ios/AppIcon-38x38@3x.png | Bin 0 -> 1542 bytes
.../icon-support/res/ios/AppIcon-40x40@2x.png | Bin 0 -> 1284 bytes
.../icon-support/res/ios/AppIcon-40x40@3x.png | Bin 0 -> 1797 bytes
.../icon-support/res/ios/AppIcon-60x60@2x.png | Bin 0 -> 1598 bytes
.../icon-support/res/ios/AppIcon-60x60@3x.png | Bin 0 -> 2192 bytes
.../icon-support/res/ios/AppIcon-64x64@2x.png | Bin 0 -> 6809 bytes
.../icon-support/res/ios/AppIcon-64x64@3x.png | Bin 0 -> 6812 bytes
.../icon-support/res/ios/AppIcon-68x68@2x.png | Bin 0 -> 6537 bytes
.../icon-support/res/ios/AppIcon-76x76@2x.png | Bin 0 -> 1930 bytes
.../icon-support/res/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 2067 bytes
.../fixtures/icon-support/res/ios/appicon-dark.png | Bin 0 -> 12297 bytes
.../fixtures/icon-support/res/ios/appicon-tint.png | Bin 0 -> 11244 bytes
.../unit/fixtures/icon-support/res/ios/appicon.png | Bin 0 -> 11668 bytes
.../AppIcon.appiconset/Contents.json | 178 +---------
.../Assets.xcassets/AppIcon.appiconset/icon-40.png | Bin 4082 -> 0 bytes
.../AppIcon.appiconset/icon-40@2x.png | Bin 7411 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-50.png | Bin 4874 -> 0 bytes
.../AppIcon.appiconset/icon-50@2x.png | Bin 9611 -> 0 bytes
.../AppIcon.appiconset/icon-60@2x.png | Bin 11924 -> 0 bytes
.../AppIcon.appiconset/icon-60@3x.png | Bin 30083 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-72.png | Bin 4944 -> 0 bytes
.../AppIcon.appiconset/icon-72@2x.png | Bin 11706 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon-76.png | Bin 7025 -> 0 bytes
.../AppIcon.appiconset/icon-76@2x.png | Bin 15262 -> 0 bytes
.../AppIcon.appiconset/icon-83.5@2x.png | Bin 20563 -> 0 bytes
.../AppIcon.appiconset/icon-small.png | Bin 3294 -> 0 bytes
.../AppIcon.appiconset/icon-small@2x.png | Bin 5608 -> 0 bytes
.../AppIcon.appiconset/icon-small@3x.png | Bin 7040 -> 0 bytes
.../Assets.xcassets/AppIcon.appiconset/icon.png | Bin 3902 -> 31816 bytes
.../Assets.xcassets/AppIcon.appiconset/icon@2x.png | Bin 7869 -> 0 bytes
tests/spec/unit/prepare.spec.js | 364 +++++++++++++++++++++
72 files changed, 999 insertions(+), 467 deletions(-)
diff --git a/lib/prepare.js b/lib/prepare.js
index 722fc641..73f90044 100644
--- a/lib/prepare.js
+++ b/lib/prepare.js
@@ -33,11 +33,21 @@ const projectFile = require('./projectFile');
const Podfile = require('./Podfile').Podfile;
const check_reqs = require('./check_reqs');
const PlatformConfigParser = require('./PlatformConfigParser');
+const versions = require('./versions');
// launch storyboard and related constants
const IMAGESET_COMPACT_SIZE_CLASS = 'compact';
const CDV_ANY_SIZE_CLASS = 'any';
+const ASSUMED_XCODE_VERSION = '15.0.0';
+function checkOrAssumeXcodeVersion () {
+ if (process.platform === 'darwin') {
+ return versions.get_apple_xcode_version();
+ } else {
+ return Promise.resolve(ASSUMED_XCODE_VERSION);
+ }
+}
+
module.exports.prepare = function (cordovaProject, options) {
const platformJson = PlatformJson.load(this.locations.root, 'ios');
const munger = new PlatformMunger('ios', this.locations.root, platformJson, new PluginInfoProvider());
@@ -55,15 +65,11 @@ module.exports.prepare = function (cordovaProject, options) {
return updateWww(cordovaProject, this.locations)
// update project according to config.xml changes.
.then(() => updateProject(this._config, this.locations))
- .then(() => {
- updateIcons(cordovaProject, this.locations);
- updateLaunchStoryboardImages(cordovaProject, this.locations);
- updateBackgroundColor(cordovaProject, this.locations);
- updateFileResources(cordovaProject, this.locations);
- })
- .then(() => {
- alertDeprecatedPreference(this._config);
- })
+ .then(() => updateIcons(cordovaProject, this.locations))
+ .then(() => updateLaunchStoryboardImages(cordovaProject, this.locations))
+ .then(() => updateBackgroundColor(cordovaProject, this.locations))
+ .then(() => updateFileResources(cordovaProject, this.locations))
+ .then(() => alertDeprecatedPreference(this._config))
.then(() => {
events.emit('verbose', 'Prepared iOS project successfully');
});
@@ -83,13 +89,12 @@ module.exports.clean = function (options) {
const projectConfig = new ConfigParser(this.locations.configXml);
- return Promise.resolve().then(() => {
- cleanWww(projectRoot, this.locations);
- cleanIcons(projectRoot, projectConfig, this.locations);
- cleanLaunchStoryboardImages(projectRoot, projectConfig, this.locations);
- cleanBackgroundColor(projectRoot, projectConfig, this.locations);
- cleanFileResources(projectRoot, projectConfig, this.locations);
- });
+ return Promise.resolve()
+ .then(() => cleanWww(projectRoot, this.locations))
+ .then(() => cleanIcons(projectRoot, projectConfig, this.locations))
+ .then(() => cleanLaunchStoryboardImages(projectRoot, projectConfig, this.locations))
+ .then(() => cleanBackgroundColor(projectRoot, projectConfig, this.locations))
+ .then(() => cleanFileResources(projectRoot, projectConfig, this.locations));
};
/**
@@ -362,59 +367,173 @@ function handleBuildSettings (platformConfig, locations, infoPlist) {
return Promise.resolve();
}
-function mapIconResources (icons, iconsDir) {
- // See https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
- // for launch images sizes reference.
+function mapIconResources (icons, iconsDir, xcodeversion) {
+ // Ref: https://developer.apple.com/design/human-interface-guidelines/app-icons
+ // These are ordered according to how Xcode puts them in the Contents.json file
const platformIcons = [
- { dest: 'icon-20.png', width: 20, height: 20 },
+ // iOS fallback icon sizes
{ dest: 'icon-20@2x.png', width: 40, height: 40 },
{ dest: 'icon-20@3x.png', width: 60, height: 60 },
- { dest: 'icon-40.png', width: 40, height: 40 },
- { dest: 'icon-40@2x.png', width: 80, height: 80 },
- { dest: 'icon-50.png', width: 50, height: 50 },
- { dest: 'icon-50@2x.png', width: 100, height: 100 },
+ { dest: 'icon-29@2x.png', width: 58, height: 58 },
+ { dest: 'icon-29@3x.png', width: 87, height: 87 },
+ { dest: 'icon-38@2x.png', width: 76, height: 76 },
+ { dest: 'icon-38@3x.png', width: 114, height: 114 },
+ { dest: 'icon-40@2x.png', width: 80, height: 80, target: 'spotlight' },
+ { dest: 'icon-40@3x.png', width: 120, height: 120, target: 'spotlight' },
{ dest: 'icon-60@2x.png', width: 120, height: 120 },
{ dest: 'icon-60@3x.png', width: 180, height: 180 },
- { dest: 'icon-72.png', width: 72, height: 72 },
- { dest: 'icon-72@2x.png', width: 144, height: 144 },
- { dest: 'icon-76.png', width: 76, height: 76 },
+ { dest: 'icon-64@2x.png', width: 128, height: 128 },
+ { dest: 'icon-64@3x.png', width: 192, height: 192 },
+ { dest: 'icon-68@2x.png', width: 136, height: 136 },
{ dest: 'icon-76@2x.png', width: 152, height: 152 },
{ dest: 'icon-83.5@2x.png', width: 167, height: 167 },
- { dest: 'icon-1024.png', width: 1024, height: 1024 },
- { dest: 'icon-29.png', width: 29, height: 29 },
- { dest: 'icon-29@2x.png', width: 58, height: 58 },
- { dest: 'icon-29@3x.png', width: 87, height: 87 },
- { dest: 'icon.png', width: 57, height: 57 },
- { dest: 'icon@2x.png', width: 114, height: 114 },
- { dest: 'icon-24@2x.png', width: 48, height: 48 },
- { dest: 'icon-27.5@2x.png', width: 55, height: 55 },
- { dest: 'icon-44@2x.png', width: 88, height: 88 },
- { dest: 'icon-86@2x.png', width: 172, height: 172 },
- { dest: 'icon-98@2x.png', width: 196, height: 196 }
+
+ // Default iOS icon
+ { dest: 'icon.png', width: 1024, height: 1024, useDefault: true },
+
+ // macOS icon sizes
+ { dest: 'mac-16.png', width: 16, height: 16, target: 'mac' },
+ { dest: 'mac-16@2x.png', width: 32, height: 32, target: 'mac' },
+ { dest: 'mac-32.png', width: 32, height: 32, target: 'mac' },
+ { dest: 'mac-32@2x.png', width: 64, height: 64, target: 'mac' },
+ { dest: 'mac-128.png', width: 128, height: 128, target: 'mac' },
+ { dest: 'mac-128@2x.png', width: 256, height: 256, target: 'mac' },
+ { dest: 'mac-256.png', width: 256, height: 256, target: 'mac' },
+ { dest: 'mac-256@2x.png', width: 512, height: 512, target: 'mac' },
+ { dest: 'mac-512.png', width: 512, height: 512, target: 'mac' },
+ { dest: 'mac-512@2x.png', width: 1024, height: 1024, target: 'mac' },
+
+ // WatchOS fallback icon sizes
+ { dest: 'watchos-22@2x.png', width: 44, height: 44, target: 'watchos' },
+ { dest: 'watchos-24@2x.png', width: 48, height: 48, target: 'watchos' },
+ { dest: 'watchos-27.5@2x.png', width: 55, height: 55, target: 'watchos' },
+ { dest: 'watchos-29@2x.png', width: 58, height: 58, target: 'watchos' },
+ { dest: 'watchos-30@2x.png', width: 60, height: 60, target: 'watchos' },
+ { dest: 'watchos-32@2x.png', width: 64, height: 64, target: 'watchos' },
+ { dest: 'watchos-33@2x.png', width: 66, height: 66, target: 'watchos' },
+ { dest: 'watchos-40@2x.png', width: 80, height: 80, target: 'watchos' },
+ { dest: 'watchos-43.5@2x.png', width: 87, height: 87, target: 'watchos' },
+ { dest: 'watchos-44@2x.png', width: 88, height: 88, target: 'watchos' },
+ { dest: 'watchos-46@2x.png', width: 92, height: 92, target: 'watchos' },
+ { dest: 'watchos-50@2x.png', width: 100, height: 100, target: 'watchos' },
+ { dest: 'watchos-51@2x.png', width: 102, height: 102, target: 'watchos' },
+ { dest: 'watchos-54@2x.png', width: 108, height: 108, target: 'watchos' },
+ { dest: 'watchos-86@2x.png', width: 172, height: 172, target: 'watchos' },
+ { dest: 'watchos-98@2x.png', width: 196, height: 196, target: 'watchos' },
+ { dest: 'watchos-108@2x.png', width: 216, height: 216, target: 'watchos' },
+ { dest: 'watchos-117@2x.png', width: 234, height: 234, target: 'watchos' },
+ { dest: 'watchos-129@2x.png', width: 258, height: 258, target: 'watchos' },
+
+ // Allow customizing the watchOS icon with target="watchos"
+ // This falls back to using the iOS app icon by default
+ { dest: 'watchos.png', width: 1024, height: 1024, target: 'watchos', useDefault: true }
];
const pathMap = {};
+
+ // We can only support dark mode and tinted icons with Xcode 16
+ const isAtLeastXcode16 = versions.compareVersions(xcodeversion, '16.0.0') >= 0;
+
+ function getDefaultIconForTarget (target) {
+ const def = icons.filter(res => !res.width && !res.height && !res.target).pop();
+
+ if (target) {
+ return icons
+ .filter(res => res.target === target)
+ .filter(res => !res.width && !res.height)
+ .pop() || def;
+ }
+
+ return def;
+ }
+
+ function getIconBySizeAndTarget (width, height, target) {
+ return icons
+ .filter(res => res.target === target)
+ .find(res =>
+ (res.width || res.height) &&
+ (!res.width || (width === res.width)) &&
+ (!res.height || (height === res.height))
+ ) || null;
+ }
+
platformIcons.forEach(item => {
- const icon = icons.getBySize(item.width, item.height) || icons.getDefault();
+ const dest = path.join(iconsDir, item.dest);
+ let icon = getIconBySizeAndTarget(item.width, item.height, item.target);
+
+ if (!icon && item.target === 'spotlight') {
+ // Fall back to a non-targeted icon
+ icon = getIconBySizeAndTarget(item.width, item.height);
+ }
+
+ if (!icon && item.useDefault) {
+ if (item.target) {
+ icon = getIconBySizeAndTarget(item.width, item.height);
+ }
+
+ const defaultIcon = getDefaultIconForTarget(item.target);
+ if (!icon && defaultIcon) {
+ icon = defaultIcon;
+ }
+ }
+
if (icon) {
- const target = path.join(iconsDir, item.dest);
- pathMap[target] = icon.src;
+ if (icon.src) {
+ pathMap[dest] = icon.src;
+ }
+
+ // Only iOS has dark/tinted icon variants
+ if (isAtLeastXcode16 && (!item.target || item.target === 'spotlight')) {
+ if (icon.foreground) {
+ pathMap[dest.replace('.png', '-dark.png')] = icon.foreground;
+ }
+
+ if (icon.monochrome) {
+ pathMap[dest.replace('.png', '-tinted.png')] = icon.monochrome;
+ }
+ }
}
});
+
return pathMap;
}
-function getIconsDir (projectRoot, platformProjDir) {
- let iconsDir;
- const xcassetsExists = folderExists(path.join(projectRoot, platformProjDir, 'Assets.xcassets'));
+function generateAppIconContentsJson (resourceMap) {
+ const contentsJSON = {
+ images: [],
+ info: {
+ author: 'xcode',
+ version: 1
+ }
+ };
- if (xcassetsExists) {
- iconsDir = path.join(platformProjDir, 'Assets.xcassets', 'AppIcon.appiconset');
- } else {
- iconsDir = path.join(platformProjDir, 'Resources', 'icons');
- }
+ Object.keys(resourceMap).forEach(res => {
+ const [filename, platform, size, scale, variant] = path.basename(res).match(/([A-Za-z]+)(?:-([0-9.]+)(?:@([0-9.]x))?)?(?:-([a-z]+))?\.png/);
- return iconsDir;
+ const entry = {
+ filename,
+ idiom: 'universal',
+ platform: (platform === 'icon') ? 'ios' : platform,
+ size: `${size ?? 1024}x${size ?? 1024}`
+ };
+
+ if (scale) {
+ entry.scale = scale;
+ }
+
+ if (variant) {
+ entry.appearances = [
+ {
+ appearance: 'luminosity',
+ value: variant
+ }
+ ];
+ }
+
+ contentsJSON.images.push(entry);
+ });
+
+ return contentsJSON;
}
function updateIcons (cordovaProject, locations) {
@@ -422,32 +541,58 @@ function updateIcons (cordovaProject, locations) {
if (icons.length === 0) {
events.emit('verbose', 'This app does not have icons defined');
- return;
+ return Promise.resolve();
}
const platformProjDir = path.relative(cordovaProject.root, locations.xcodeCordovaProj);
- const iconsDir = getIconsDir(cordovaProject.root, platformProjDir);
- const resourceMap = mapIconResources(icons, iconsDir);
- events.emit('verbose', `Updating icons at ${iconsDir}`);
- FileUpdater.updatePaths(
- resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+ const iconsDir = path.join(platformProjDir, 'Assets.xcassets', 'AppIcon.appiconset');
+
+ return checkOrAssumeXcodeVersion()
+ .then((xcodeversion) => {
+ const resourceMap = mapIconResources(icons, iconsDir, xcodeversion);
+ events.emit('verbose', `Updating icons at ${iconsDir}`);
+ FileUpdater.updatePaths(
+ resourceMap, { rootDir: cordovaProject.root }, logFileOp);
+
+ // Now we need to update the AppIcon.appiconset/Contents.json file
+ const contentsJSON = generateAppIconContentsJson(resourceMap);
+
+ events.emit('verbose', 'Updating App Icon image set contents.json');
+ fs.writeFileSync(path.join(cordovaProject.root, iconsDir, 'Contents.json'), JSON.stringify(contentsJSON, null, 2));
+ });
}
function cleanIcons (projectRoot, projectConfig, locations) {
const icons = projectConfig.getIcons('ios');
- if (icons.length > 0) {
- const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
- const iconsDir = getIconsDir(projectRoot, platformProjDir);
- const resourceMap = mapIconResources(icons, iconsDir);
- Object.keys(resourceMap).forEach(targetIconPath => {
- resourceMap[targetIconPath] = null;
- });
- events.emit('verbose', `Cleaning icons at ${iconsDir}`);
-
- // Source paths are removed from the map, so updatePaths() will delete the target files.
- FileUpdater.updatePaths(
- resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+ if (icons.length === 0) {
+ return Promise.resolve();
}
+
+ const platformProjDir = path.relative(projectRoot, locations.xcodeCordovaProj);
+ const iconsDir = path.join(platformProjDir, 'Assets.xcassets', 'AppIcon.appiconset');
+
+ return checkOrAssumeXcodeVersion()
+ .then((xcodeversion) => {
+ const resourceMap = mapIconResources(icons, iconsDir, xcodeversion);
+ Object.keys(resourceMap).forEach(targetIconPath => {
+ resourceMap[targetIconPath] = null;
+ });
+ events.emit('verbose', `Cleaning icons at ${iconsDir}`);
+
+ // Source paths are removed from the map, so updatePaths() will delete the target files.
+ FileUpdater.updatePaths(
+ resourceMap, { rootDir: projectRoot, all: true }, logFileOp);
+
+ const contentsJSON = generateAppIconContentsJson(resourceMap);
+
+ // delete filename from contents.json
+ contentsJSON.images.forEach(image => {
+ image.filename = undefined;
+ });
+
+ events.emit('verbose', 'Updating App Icon image set contents.json');
+ fs.writeFileSync(path.join(projectRoot, iconsDir, 'Contents.json'), JSON.stringify(contentsJSON, null, 2));
+ });
}
/**
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json
index 2ce78c1b..2c8c083a 100644
--- a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,241 +1,20 @@
{
"images" : [
{
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "icon-20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "icon-20@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "icon-29@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "icon-60@2x.png",
- "scale" : "3x"
- },
- {
- "size" : "57x57",
- "idiom" : "iphone",
"filename" : "icon.png",
- "scale" : "1x"
- },
- {
- "size" : "57x57",
- "idiom" : "iphone",
- "filename" : "icon@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "icon-60@2x.png",
- "scale" : "2x"
+ "idiom" : "universal",
+ "platform": "ios",
+ "size" : "1024x1024"
},
{
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "icon-60@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "icon-20.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "icon-20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "icon-29.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "icon-29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "icon-40.png",
- "scale" : "1x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "50x50",
- "idiom" : "ipad",
- "filename" : "icon-50.png",
- "scale" : "1x"
- },
- {
- "size" : "50x50",
- "idiom" : "ipad",
- "filename" : "icon-50@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "72x72",
- "idiom" : "ipad",
- "filename" : "icon-72.png",
- "scale" : "1x"
- },
- {
- "size" : "72x72",
- "idiom" : "ipad",
- "filename" : "icon-72@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "icon-76.png",
- "scale" : "1x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "icon-76@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "83.5x83.5",
- "idiom" : "ipad",
- "filename" : "icon-83.5@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "icon-1024.png",
- "scale" : "1x"
- },
- {
- "size" : "24x24",
- "idiom" : "watch",
- "filename" : "icon-24@2x.png",
- "scale" : "2x",
- "role" : "notificationCenter",
- "subtype" : "38mm"
- },
- {
- "size" : "27.5x27.5",
- "idiom" : "watch",
- "filename" : "icon-27.5@2x.png",
- "scale" : "2x",
- "role" : "notificationCenter",
- "subtype" : "42mm"
- },
- {
- "size" : "29x29",
- "idiom" : "watch",
- "filename" : "icon-29@2x.png",
- "role" : "companionSettings",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "watch",
- "filename" : "icon-29@3x.png",
- "role" : "companionSettings",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "watch",
- "filename" : "icon-40@2x.png",
- "scale" : "2x",
- "role" : "appLauncher",
- "subtype" : "38mm"
- },
- {
- "size" : "44x44",
- "idiom" : "watch",
- "filename" : "icon-44@2x.png",
- "scale" : "2x",
- "role" : "appLauncher",
- "subtype" : "40mm"
- },
- {
- "size" : "50x50",
- "idiom" : "watch",
- "filename" : "icon-50@2x.png",
- "scale" : "2x",
- "role" : "appLauncher",
- "subtype" : "44mm"
- },
- {
- "size" : "86x86",
- "idiom" : "watch",
- "filename" : "icon-86@2x.png",
- "scale" : "2x",
- "role" : "quickLook",
- "subtype" : "38mm"
- },
- {
- "size" : "98x98",
- "idiom" : "watch",
- "filename" : "icon-98@2x.png",
- "scale" : "2x",
- "role" : "quickLook",
- "subtype" : "42mm"
- },
- {
- "size" : "108x108",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "quickLook",
- "subtype" : "44mm"
- },
- {
- "size" : "1024x1024",
- "idiom" : "watch-marketing",
- "filename" : "icon-1024.png",
- "scale" : "1x"
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "watchos",
+ "size" : "1024x1024"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
-}
\ No newline at end of file
+}
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-1024.png
deleted file mode 100644
index 1b9cbb91..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-1024.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20.png
deleted file mode 100644
index 5788eed9..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png
deleted file mode 100644
index 4feefdf8..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png
deleted file mode 100644
index 69ce592c..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-24@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-24@2x.png
deleted file mode 100644
index f0babf9d..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-24@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-27.5@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-27.5@2x.png
deleted file mode 100644
index 78f21bb3..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-27.5@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29.png
deleted file mode 100644
index 5dff98e9..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png
deleted file mode 100644
index 34b39085..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png
deleted file mode 100644
index c63fd776..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40.png
deleted file mode 100644
index 4feefdf8..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
deleted file mode 100644
index 32897363..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-44@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-44@2x.png
deleted file mode 100644
index 01c5af72..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-44@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50.png
deleted file mode 100644
index 81f93f16..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
deleted file mode 100644
index a980efe1..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
deleted file mode 100644
index 1e794a48..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
deleted file mode 100644
index db10c553..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72.png
deleted file mode 100644
index 097f5b40..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
deleted file mode 100644
index e3d49a2f..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76.png
deleted file mode 100644
index aa6810c3..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
deleted file mode 100644
index da3a050f..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
deleted file mode 100644
index 039a02ae..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-86@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-86@2x.png
deleted file mode 100644
index f32a034a..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-86@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-98@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-98@2x.png
deleted file mode 100644
index 85ec9e36..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon-98@2x.png and /dev/null differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png
index bbdba9ee..b9250b12 100644
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png and b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png differ
diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon@2x.png b/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon@2x.png
deleted file mode 100644
index 41e6be4a..00000000
Binary files a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/icon-support/configs/multi.xml b/tests/spec/unit/fixtures/icon-support/configs/multi.xml
new file mode 100644
index 00000000..504ca297
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/configs/multi.xml
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+
+ <platform name="ios">
+ <preference name="orientation" value="all" />
+ <preference name="target-device" value="handset" />
+ <preference name="deployment-target" value="13.0" />
+
+ <icon src="res/ios/AppIcon-20x20@2x.png" height="40" width="40" />
+ <icon src="res/ios/AppIcon-20x20@3x.png" height="60" width="60" />
+ <icon src="res/ios/AppIcon-29x29@2x.png" height="58" width="58" />
+ <icon src="res/ios/AppIcon-29x29@3x.png" height="87" width="87" />
+ <icon src="res/ios/AppIcon-38x38@2x.png" height="76" width="76" />
+ <icon src="res/ios/AppIcon-38x38@3x.png" height="114" width="114" />
+ <icon src="res/ios/AppIcon-40x40@2x.png" height="80" width="80" target="spotlight" />
+ <icon src="res/ios/AppIcon-40x40@3x.png" height="120" width="120" target="spotlight" />
+ <icon src="res/ios/AppIcon-60x60@2x.png" height="120" width="120" />
+ <icon src="res/ios/AppIcon-60x60@3x.png" height="180" width="180" />
+ <icon src="res/ios/AppIcon-64x64@2x.png" height="128" width="128" />
+ <icon src="res/ios/AppIcon-64x64@3x.png" height="192" width="192" />
+ <icon src="res/ios/AppIcon-68x68@2x.png" height="136" width="136" />
+ <icon src="res/ios/AppIcon-76x76@2x.png" height="152" width="152" />
+ <icon src="res/ios/AppIcon-83.5x83.5@2x.png" height="167" width="167" />
+ <icon src="res/ios/AppIcon-1024x1024@1x.png" height="1024" width="1024" />
+ </platform>
+
+ <access origin="http://*.apache.org" />
+ <access origin="https://*.apache.org" />
+
+ <allow-navigation href="http://*.apache.org" />
+ <allow-navigation href="https://*.apache.org" />
+
+</widget>
+
diff --git a/tests/spec/unit/fixtures/icon-support/configs/none.xml b/tests/spec/unit/fixtures/icon-support/configs/none.xml
new file mode 100644
index 00000000..f1b8751c
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/configs/none.xml
@@ -0,0 +1,24 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+
+ <platform name="ios">
+ <preference name="orientation" value="all" />
+ <preference name="target-device" value="handset" />
+ <preference name="deployment-target" value="13.0" />
+ </platform>
+
+ <access origin="http://*.apache.org" />
+ <access origin="https://*.apache.org" />
+
+ <allow-navigation href="http://*.apache.org" />
+ <allow-navigation href="https://*.apache.org" />
+
+</widget>
diff --git a/tests/spec/unit/fixtures/icon-support/configs/single-only.xml b/tests/spec/unit/fixtures/icon-support/configs/single-only.xml
new file mode 100644
index 00000000..975364f7
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/configs/single-only.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+
+ <platform name="ios">
+ <preference name="orientation" value="all" />
+ <preference name="target-device" value="handset" />
+ <preference name="deployment-target" value="13.0" />
+
+ <icon src="res/ios/appicon.png" />
+ </platform>
+
+ <access origin="http://*.apache.org" />
+ <access origin="https://*.apache.org" />
+
+ <allow-navigation href="http://*.apache.org" />
+ <allow-navigation href="https://*.apache.org" />
+
+</widget>
+
diff --git a/tests/spec/unit/fixtures/icon-support/configs/single-variants.xml b/tests/spec/unit/fixtures/icon-support/configs/single-variants.xml
new file mode 100644
index 00000000..52cd0d5d
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/configs/single-variants.xml
@@ -0,0 +1,27 @@
+<?xml version='1.0' encoding='utf-8'?>
+<widget android-packageName="io.cordova.hellocordova.android" id="io.cordova.hellocordova" ios-CFBundleIdentifier="io.cordova.hellocordova.ios" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+ <name>Hello Cordova</name>
+ <description>
+ A sample Apache Cordova application that responds to the deviceready event.
+ </description>
+ <author email="dev@cordova.apache.org" href="http://cordova.io">
+ Apache Cordova Team
+ </author>
+ <content src="index.html" />
+
+ <platform name="ios">
+ <preference name="orientation" value="all" />
+ <preference name="target-device" value="handset" />
+ <preference name="deployment-target" value="13.0" />
+
+ <icon src="res/ios/appicon.png" foreground="res/ios/appicon-dark.png" monochrome="res/ios/appicon-tint.png" />
+ </platform>
+
+ <access origin="http://*.apache.org" />
+ <access origin="https://*.apache.org" />
+
+ <allow-navigation href="http://*.apache.org" />
+ <allow-navigation href="https://*.apache.org" />
+
+</widget>
+
diff --git a/tests/spec/unit/fixtures/icon-support/contents-json/multi.js b/tests/spec/unit/fixtures/icon-support/contents-json/multi.js
new file mode 100644
index 00000000..2b5a317a
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/contents-json/multi.js
@@ -0,0 +1,145 @@
+/**
+ 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.
+*/
+
+module.exports = {
+ "images" : [
+ {
+ "filename": "icon-20@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "filename": "icon-20@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "filename": "icon-29@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "filename": "icon-29@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "filename": "icon-38@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "38x38"
+ },
+ {
+ "filename": "icon-38@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "38x38"
+ },
+ {
+ "filename": "icon-40@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "filename": "icon-40@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "filename": "icon-60@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "filename": "icon-60@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "filename": "icon-64@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "64x64"
+ },
+ {
+ "filename": "icon-64@3x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "3x",
+ "size" : "64x64"
+ },
+ {
+ "filename": "icon-68@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "68x68"
+ },
+ {
+ "filename": "icon-76@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "filename": "icon-83.5@2x.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "filename" : "watchos.png",
+ "idiom" : "universal",
+ "platform": "watchos",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+};
+
diff --git a/tests/spec/unit/fixtures/icon-support/contents-json/none.js b/tests/spec/unit/fixtures/icon-support/contents-json/none.js
new file mode 100644
index 00000000..e08f8af5
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/contents-json/none.js
@@ -0,0 +1,39 @@
+/**
+ 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.
+*/
+
+module.exports = {
+ "images" : [
+ {
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "watchos",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+};
diff --git a/tests/spec/unit/fixtures/icon-support/contents-json/single-only.js b/tests/spec/unit/fixtures/icon-support/contents-json/single-only.js
new file mode 100644
index 00000000..600c3f12
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/contents-json/single-only.js
@@ -0,0 +1,39 @@
+/**
+ 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.
+*/
+
+module.exports = {
+ "images" : [
+ {
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "filename" : "watchos.png",
+ "idiom" : "universal",
+ "platform": "watchos",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+};
diff --git a/tests/spec/unit/fixtures/icon-support/contents-json/single-variants.js b/tests/spec/unit/fixtures/icon-support/contents-json/single-variants.js
new file mode 100644
index 00000000..1b3dc339
--- /dev/null
+++ b/tests/spec/unit/fixtures/icon-support/contents-json/single-variants.js
@@ -0,0 +1,63 @@
+/**
+ 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.
+*/
+
+module.exports = {
+ "images" : [
+ {
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "dark"
+ }
+ ],
+ "filename" : "icon-dark.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "appearances" : [
+ {
+ "appearance" : "luminosity",
+ "value" : "tinted"
+ }
+ ],
+ "filename" : "icon-tinted.png",
+ "idiom" : "universal",
+ "platform" : "ios",
+ "size" : "1024x1024"
+ },
+ {
+ "filename" : "watchos.png",
+ "idiom" : "universal",
+ "platform" : "watchos",
+ "size" : "1024x1024"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+};
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-1024x1024@1x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-1024x1024@1x.png
new file mode 100644
index 00000000..8cfcb974
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-1024x1024@1x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@2x.png
new file mode 100644
index 00000000..dac81388
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@3x.png
new file mode 100644
index 00000000..79e2e927
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-20x20@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@2x.png
new file mode 100644
index 00000000..662beedc
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@3x.png
new file mode 100644
index 00000000..9f8bfb09
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-29x29@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@2x.png
new file mode 100644
index 00000000..85a74483
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@3x.png
new file mode 100644
index 00000000..0e0c498d
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-38x38@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@2x.png
new file mode 100644
index 00000000..601336d4
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@3x.png
new file mode 100644
index 00000000..c2e5c98d
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-40x40@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@2x.png
new file mode 100644
index 00000000..aef9bf51
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@3x.png
new file mode 100644
index 00000000..d9f5559b
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-60x60@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@2x.png
new file mode 100644
index 00000000..a436d035
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@3x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@3x.png
new file mode 100644
index 00000000..56482a3b
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-64x64@3x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-68x68@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-68x68@2x.png
new file mode 100644
index 00000000..f756ba8c
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-68x68@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-76x76@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-76x76@2x.png
new file mode 100644
index 00000000..30380807
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-76x76@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-83.5x83.5@2x.png b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-83.5x83.5@2x.png
new file mode 100644
index 00000000..efed7886
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/AppIcon-83.5x83.5@2x.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/appicon-dark.png b/tests/spec/unit/fixtures/icon-support/res/ios/appicon-dark.png
new file mode 100644
index 00000000..884c4231
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/appicon-dark.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/appicon-tint.png b/tests/spec/unit/fixtures/icon-support/res/ios/appicon-tint.png
new file mode 100644
index 00000000..b37e8115
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/appicon-tint.png differ
diff --git a/tests/spec/unit/fixtures/icon-support/res/ios/appicon.png b/tests/spec/unit/fixtures/icon-support/res/ios/appicon.png
new file mode 100644
index 00000000..07afba0e
Binary files /dev/null and b/tests/spec/unit/fixtures/icon-support/res/ios/appicon.png differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json
index d19e65fd..2c8c083a 100644
--- a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,182 +1,20 @@
{
"images" : [
{
- "idiom" : "iphone",
- "size" : "29x29",
- "filename" : "icon-small.png",
- "scale" : "1x"
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "filename" : "icon-small@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "filename" : "icon-small@3x.png",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "filename" : "icon-60@2x.png",
- "scale" : "3x"
- },
- {
- "idiom" : "iphone",
- "size" : "57x57",
"filename" : "icon.png",
- "scale" : "1x"
- },
- {
- "idiom" : "iphone",
- "size" : "57x57",
- "filename" : "icon@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "filename" : "icon-60@2x.png",
- "scale" : "2x"
+ "idiom" : "universal",
+ "platform": "ios",
+ "size" : "1024x1024"
},
{
- "idiom" : "iphone",
- "size" : "60x60",
- "filename" : "icon-60@3x.png",
- "scale" : "3x"
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "filename" : "icon-small.png",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "filename" : "icon-small@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "filename" : "icon-40.png",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "filename" : "icon-40@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "50x50",
- "filename" : "icon-50.png",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "50x50",
- "filename" : "icon-50@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "72x72",
- "filename" : "icon-72.png",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "72x72",
- "filename" : "icon-72@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "76x76",
- "filename" : "icon-76.png",
- "scale" : "1x"
- },
- {
- "idiom" : "ipad",
- "size" : "76x76",
- "filename" : "icon-76@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "ipad",
- "size" : "83.5x83.5",
- "filename" : "icon-83.5@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "24x24",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "notificationCenter",
- "subtype" : "38mm"
- },
- {
- "size" : "27.5x27.5",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "notificationCenter",
- "subtype" : "42mm"
- },
- {
- "size" : "29x29",
- "idiom" : "watch",
- "role" : "companionSettings",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "watch",
- "role" : "companionSettings",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "appLauncher",
- "subtype" : "38mm"
- },
- {
- "size" : "44x44",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "longLook",
- "subtype" : "42mm"
- },
- {
- "size" : "86x86",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "quickLook",
- "subtype" : "38mm"
- },
- {
- "size" : "98x98",
- "idiom" : "watch",
- "scale" : "2x",
- "role" : "quickLook",
- "subtype" : "42mm"
+ "filename" : "icon.png",
+ "idiom" : "universal",
+ "platform": "watchos",
+ "size" : "1024x1024"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
-}
\ No newline at end of file
+}
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40.png
deleted file mode 100644
index e865adbc..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png
deleted file mode 100644
index 6d07dce5..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50.png
deleted file mode 100644
index 98a9d96d..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png
deleted file mode 100644
index bac693f7..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-50@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png
deleted file mode 100644
index 955af362..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png
deleted file mode 100644
index e1268916..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72.png
deleted file mode 100644
index 8c6e5df3..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png
deleted file mode 100644
index dd819da6..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76.png
deleted file mode 100644
index 63afe7f1..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png
deleted file mode 100644
index 4cff29a2..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png
deleted file mode 100644
index 3c1a0115..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small.png
deleted file mode 100644
index 0ea1c42f..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png
deleted file mode 100644
index 2c72038e..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png
deleted file mode 100644
index 5c37dfc2..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png and /dev/null differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon.png
index b2571a71..b9250b12 100644
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon.png and b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon.png differ
diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon@2x.png b/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon@2x.png
deleted file mode 100644
index d75098f5..00000000
Binary files a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon@2x.png and /dev/null differ
diff --git a/tests/spec/unit/prepare.spec.js b/tests/spec/unit/prepare.spec.js
index 769a3afa..a84a601c 100644
--- a/tests/spec/unit/prepare.spec.js
+++ b/tests/spec/unit/prepare.spec.js
@@ -29,6 +29,7 @@ const rewire = require('rewire');
const prepare = rewire('../../../lib/prepare');
const projectFile = require('../../../lib/projectFile');
const FileUpdater = require('cordova-common').FileUpdater;
+const versions = require('../../../lib/versions');
const tmpDir = path.join(__dirname, '../../../tmp');
const FIXTURES = path.join(__dirname, 'fixtures');
@@ -400,6 +401,369 @@ describe('prepare', () => {
});
});
+ describe('App Icon handling', () => {
+ const xcver = '16.0.0';
+ const mapIconResources = prepare.__get__('mapIconResources');
+
+ describe('#mapIconResources', () => {
+ it('should handle a default icon', () => {
+ const icons = [
+ { src: 'dummy.png' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon.png': 'dummy.png',
+ 'watchos.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle a default icon for a watchos target', () => {
+ const icons = [
+ { src: 'dummy.png' },
+ { src: 'dummy-watch.png', target: 'watchos' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon.png': 'dummy.png',
+ 'watchos.png': 'dummy-watch.png'
+ }));
+ });
+
+ it('should handle default icon variants on Xcode 16+', () => {
+ const icons = [
+ { src: 'dummy.png', monochrome: 'dummy-tint.png', foreground: 'dummy-dark.png' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon.png': 'dummy.png',
+ 'icon-dark.png': 'dummy-dark.png',
+ 'icon-tinted.png': 'dummy-tint.png',
+ 'watchos.png': 'dummy.png'
+ }));
+ });
+
+ it('should ignore default icon variants on Xcode 15', () => {
+ const icons = [
+ { src: 'dummy.png', monochrome: 'dummy-tint.png', foreground: 'dummy-dark.png' }
+ ];
+
+ const resMap = mapIconResources(icons, '', '15.0.0');
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon.png': 'dummy.png',
+ 'watchos.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle a single sized icon', () => {
+ const icons = [
+ { src: 'dummy.png', height: 1024, width: 1024 }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon.png': 'dummy.png',
+ 'watchos.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle a single sized icon for watchos target', () => {
+ const icons = [
+ { src: 'dummy.png', height: 1024, width: 1024, target: 'watchos' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'watchos.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle a sized icon', () => {
+ const icons = [
+ { src: 'dummy.png', height: 120, width: 120 }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon-40@3x.png': 'dummy.png',
+ 'icon-60@2x.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle a sized spotlight icon', () => {
+ const icons = [
+ { src: 'dummy.png', height: 120, width: 120 },
+ { src: 'dummy-spot.png', height: 120, width: 120, target: 'spotlight' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon-40@3x.png': 'dummy-spot.png',
+ 'icon-60@2x.png': 'dummy.png'
+ }));
+ });
+
+ it('should handle sized icon variants', () => {
+ const icons = [
+ { src: 'dummy.png', height: 76, width: 76, monochrome: 'dummy-tint.png', foreground: 'dummy-dark.png' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'icon-38@2x.png': 'dummy.png',
+ 'icon-38@2x-dark.png': 'dummy-dark.png',
+ 'icon-38@2x-tinted.png': 'dummy-tint.png'
+ }));
+ });
+
+ it('should ignore sized watchos icons without a target', () => {
+ const icons = [
+ { src: 'dummy.png', height: 216, width: 216 }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual({});
+ });
+
+ it('should handle a sized macOS icon', () => {
+ const icons = [
+ { src: 'dummy.png', height: 256, width: 256, target: 'mac' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual(jasmine.objectContaining({
+ 'mac-128@2x.png': 'dummy.png',
+ 'mac-256.png': 'dummy.png'
+ }));
+ });
+
+ it('should ignore tinted icons for non-iOS targets', () => {
+ const icons = [
+ { monochrome: 'dummy-tint.png', height: 256, width: 256, target: 'mac' },
+ { foreground: 'dummy-dark.png', height: 216, width: 216, target: 'watchos' }
+ ];
+
+ const resMap = mapIconResources(icons, '', xcver);
+
+ expect(resMap).toEqual({});
+ });
+ });
+
+ describe('#updateIcons', () => {
+ const updateIcons = prepare.__get__('updateIcons');
+ const logFileOp = prepare.__get__('logFileOp');
+ let iconsDir = '';
+
+ beforeEach(() => {
+ prepare.__set__('ASSUMED_XCODE_VERSION', '15.0.0');
+
+ const platformProjDir = path.relative(iosProject, p.locations.xcodeCordovaProj);
+ iconsDir = path.join(platformProjDir, 'Assets.xcassets', 'AppIcon.appiconset');
+ });
+
+ function updateIconsWithConfig (configFile) {
+ // create a suitable mock project for our method
+ const project = {
+ root: iosProject,
+ locations: p.locations,
+ projectConfig: new ConfigParser(path.join(FIXTURES, 'icon-support', 'configs', configFile))
+ };
+
+ // copy the icon fixtures to the iOS project
+ fs.cpSync(path.join(FIXTURES, 'icon-support', 'res'), path.join(iosProject, 'res'), { recursive: true });
+
+ // copy icons and update Contents.json
+ return updateIcons(project, p.locations);
+ }
+
+ it('should not update paths if no icons are specified', () => {
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+
+ return updateIconsWithConfig('none.xml')
+ .then(() => {
+ expect(updatePaths).not.toHaveBeenCalled();
+
+ // verify that that Contents.json is as we expect
+ const result = JSON.parse(fs.readFileSync(path.join(iosProject, iconsDir, 'Contents.json')));
+ expect(result).toEqual(require('./fixtures/icon-support/contents-json/none'));
+ });
+ });
+
+ it('should update paths if a single icon is specified', () => {
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+
+ return updateIconsWithConfig('single-only.xml')
+ .then(() => {
+ expect(updatePaths).toHaveBeenCalledWith({
+ [path.join(iconsDir, 'icon.png')]: 'res/ios/appicon.png',
+ [path.join(iconsDir, 'watchos.png')]: 'res/ios/appicon.png'
+ }, { rootDir: iosProject }, logFileOp);
+
+ // verify that that Contents.json is as we expect
+ const result = JSON.parse(fs.readFileSync(path.join(iosProject, iconsDir, 'Contents.json')));
+ expect(result).toEqual(require('./fixtures/icon-support/contents-json/single-only'));
+ });
+ });
+
+ it('should update only some paths if a single icon with variants is specified with Xcode 15', () => {
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+ spyOn(versions, 'get_apple_xcode_version').and.returnValue(Promise.resolve('15.0.0'));
+
+ return updateIconsWithConfig('single-variants.xml')
+ .then(() => {
+ expect(updatePaths).toHaveBeenCalledWith({
+ [path.join(iconsDir, 'icon.png')]: 'res/ios/appicon.png',
+ [path.join(iconsDir, 'watchos.png')]: 'res/ios/appicon.png'
+ }, { rootDir: iosProject }, logFileOp);
+
+ // verify that that Contents.json is as we expect
+ const result = JSON.parse(fs.readFileSync(path.join(iosProject, iconsDir, 'Contents.json')));
+ expect(result).toEqual(require('./fixtures/icon-support/contents-json/single-only'));
+ });
+ });
+
+ it('should update paths if a single icon with variants is specified with Xcode 16', () => {
+ prepare.__set__('ASSUMED_XCODE_VERSION', '16.0.0');
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+ spyOn(versions, 'get_apple_xcode_version').and.returnValue(Promise.resolve('16.0.0'));
+
+ return updateIconsWithConfig('single-variants.xml')
+ .then(() => {
+ expect(updatePaths).toHaveBeenCalledWith({
+ [path.join(iconsDir, 'icon.png')]: 'res/ios/appicon.png',
+ [path.join(iconsDir, 'icon-dark.png')]: 'res/ios/appicon-dark.png',
+ [path.join(iconsDir, 'icon-tinted.png')]: 'res/ios/appicon-tint.png',
+ [path.join(iconsDir, 'watchos.png')]: 'res/ios/appicon.png'
+ }, { rootDir: iosProject }, logFileOp);
+
+ // verify that that Contents.json is as we expect
+ const result = JSON.parse(fs.readFileSync(path.join(iosProject, iconsDir, 'Contents.json')));
+ expect(result).toEqual(require('./fixtures/icon-support/contents-json/single-variants'));
+ });
+ });
+
+ it('should update paths if multiple icon sizes are specified', () => {
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+
+ return updateIconsWithConfig('multi.xml')
+ .then(() => {
+ expect(updatePaths).toHaveBeenCalledWith({
+ [path.join(iconsDir, 'icon.png')]: 'res/ios/AppIcon-1024x1024@1x.png',
+ [path.join(iconsDir, 'watchos.png')]: 'res/ios/AppIcon-1024x1024@1x.png',
+ [path.join(iconsDir, 'icon-20@2x.png')]: 'res/ios/AppIcon-20x20@2x.png',
+ [path.join(iconsDir, 'icon-20@3x.png')]: 'res/ios/AppIcon-20x20@3x.png',
+ [path.join(iconsDir, 'icon-29@2x.png')]: 'res/ios/AppIcon-29x29@2x.png',
+ [path.join(iconsDir, 'icon-29@3x.png')]: 'res/ios/AppIcon-29x29@3x.png',
+ [path.join(iconsDir, 'icon-38@2x.png')]: 'res/ios/AppIcon-38x38@2x.png',
+ [path.join(iconsDir, 'icon-38@3x.png')]: 'res/ios/AppIcon-38x38@3x.png',
+ [path.join(iconsDir, 'icon-40@2x.png')]: 'res/ios/AppIcon-40x40@2x.png',
+ [path.join(iconsDir, 'icon-40@3x.png')]: 'res/ios/AppIcon-40x40@3x.png',
+ [path.join(iconsDir, 'icon-60@2x.png')]: 'res/ios/AppIcon-60x60@2x.png',
+ [path.join(iconsDir, 'icon-60@3x.png')]: 'res/ios/AppIcon-60x60@3x.png',
+ [path.join(iconsDir, 'icon-64@2x.png')]: 'res/ios/AppIcon-64x64@2x.png',
+ [path.join(iconsDir, 'icon-64@3x.png')]: 'res/ios/AppIcon-64x64@3x.png',
+ [path.join(iconsDir, 'icon-68@2x.png')]: 'res/ios/AppIcon-68x68@2x.png',
+ [path.join(iconsDir, 'icon-76@2x.png')]: 'res/ios/AppIcon-76x76@2x.png',
+ [path.join(iconsDir, 'icon-83.5@2x.png')]: 'res/ios/AppIcon-83.5x83.5@2x.png'
+ }, { rootDir: iosProject }, logFileOp);
+
+ // verify that that Contents.json is as we expect
+ const result = JSON.parse(fs.readFileSync(path.join(iosProject, iconsDir, 'Contents.json')));
+ expect(result).toEqual(require('./fixtures/icon-support/contents-json/multi'));
+ });
+ });
+ });
+
+ describe('#cleanIcons', () => {
+ const updateIcons = prepare.__get__('updateIcons');
+ const cleanIcons = prepare.__get__('cleanIcons');
+ const logFileOp = prepare.__get__('logFileOp');
+ let iconsDir = '';
+
+ beforeEach(() => {
+ const platformProjDir = path.relative(iosProject, p.locations.xcodeCordovaProj);
+ iconsDir = path.join(platformProjDir, 'Assets.xcassets', 'AppIcon.appiconset');
+ });
+
+ it('should remove icon images', () => {
+ // create a suitable mock project for our method
+ const project = {
+ root: iosProject,
+ locations: p.locations,
+ projectConfig: new ConfigParser(path.join(FIXTURES, 'icon-support', 'configs', 'multi.xml'))
+ };
+
+ // copy the icon fixtures to the iOS project
+ fs.cpSync(path.join(FIXTURES, 'icon-support', 'res'), path.join(iosProject, 'res'), { recursive: true });
+
+ // copy icons and update Contents.json
+ updateIcons(project, p.locations);
+
+ // now, clean the images
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+
+ return cleanIcons(iosProject, project.projectConfig, p.locations)
+ .then(() => {
+ expect(updatePaths).toHaveBeenCalledWith({
+ [path.join(iconsDir, 'icon.png')]: null,
+ [path.join(iconsDir, 'watchos.png')]: null,
+ [path.join(iconsDir, 'icon-20@2x.png')]: null,
+ [path.join(iconsDir, 'icon-20@3x.png')]: null,
+ [path.join(iconsDir, 'icon-29@2x.png')]: null,
+ [path.join(iconsDir, 'icon-29@3x.png')]: null,
+ [path.join(iconsDir, 'icon-38@2x.png')]: null,
+ [path.join(iconsDir, 'icon-38@3x.png')]: null,
+ [path.join(iconsDir, 'icon-40@2x.png')]: null,
+ [path.join(iconsDir, 'icon-40@3x.png')]: null,
+ [path.join(iconsDir, 'icon-60@2x.png')]: null,
+ [path.join(iconsDir, 'icon-60@3x.png')]: null,
+ [path.join(iconsDir, 'icon-64@2x.png')]: null,
+ [path.join(iconsDir, 'icon-64@3x.png')]: null,
+ [path.join(iconsDir, 'icon-68@2x.png')]: null,
+ [path.join(iconsDir, 'icon-76@2x.png')]: null,
+ [path.join(iconsDir, 'icon-83.5@2x.png')]: null
+ }, { rootDir: iosProject, all: true }, logFileOp);
+ });
+ });
+
+ it('should have no effect if no icons are specified', () => {
+ // create a suitable mock project for our method
+ const project = {
+ root: iosProject,
+ locations: p.locations,
+ projectConfig: new ConfigParser(path.join(FIXTURES, 'icon-support', 'configs', 'none.xml'))
+ };
+
+ // copy the icon fixtures to the iOS project
+ fs.cpSync(path.join(FIXTURES, 'icon-support', 'res'), path.join(iosProject, 'res'), { recursive: true });
+
+ // copy icons and update Contents.json
+ updateIcons(project, p.locations);
+
+ // now, clean the images
+ const updatePaths = spyOn(FileUpdater, 'updatePaths');
+
+ return cleanIcons(iosProject, project.projectConfig, p.locations)
+ .then(() => {
+ expect(updatePaths).not.toHaveBeenCalled();
+ });
+ });
+ });
+ });
+
describe('colorPreferenceToComponents', () => {
const colorPreferenceToComponents = prepare.__get__('colorPreferenceToComponents');
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org