diff --git a/lib/Api.js b/lib/Api.js index 3478108617..c131f1b83b 100644 --- a/lib/Api.js +++ b/lib/Api.js @@ -81,39 +81,20 @@ class Api { setupEvents(events); - let xcodeProjDir; - let xcodeCordovaProj; - - try { - const xcodeProjDir_array = fs.readdirSync(this.root).filter(e => e.match(/\.xcodeproj$/i)); - if (xcodeProjDir_array.length > 1) { - for (let x = 0; x < xcodeProjDir_array.length; x++) { - if (xcodeProjDir_array[x].substring(0, 2) === '._') { - xcodeProjDir_array.splice(x, 1); - } - } - } - xcodeProjDir = xcodeProjDir_array[0]; - - if (!xcodeProjDir) { - throw new CordovaError(`The provided path "${this.root}" is not a Cordova iOS project.`); - } - - const cordovaProjName = xcodeProjDir.substring(xcodeProjDir.lastIndexOf(path.sep) + 1, xcodeProjDir.indexOf('.xcodeproj')); - xcodeCordovaProj = path.join(this.root, cordovaProjName); - } catch (e) { - throw new CordovaError(`The provided path "${this.root}" is not a Cordova iOS project.`); + const xcodeProjDir = path.join(this.root, 'App.xcodeproj'); + if (!fs.existsSync(xcodeProjDir)) { + throw new CordovaError(`The provided path "${this.root}" is not an up-to-date Cordova iOS project.`); } this.locations = { root: this.root, www: path.join(this.root, 'www'), platformWww: path.join(this.root, 'platform_www'), - configXml: path.join(xcodeCordovaProj, 'config.xml'), + configXml: path.join(this.root, 'App', 'config.xml'), defaultConfigXml: path.join(this.root, 'cordova', 'defaults.xml'), - pbxproj: path.join(this.root, xcodeProjDir, 'project.pbxproj'), - xcodeProjDir: path.join(this.root, xcodeProjDir), - xcodeCordovaProj + pbxproj: path.join(xcodeProjDir, 'project.pbxproj'), + xcodeProjDir, + xcodeCordovaProj: path.join(this.root, 'App') }; } diff --git a/lib/Podfile.js b/lib/Podfile.js index 97269d0a93..6f95851978 100644 --- a/lib/Podfile.js +++ b/lib/Podfile.js @@ -50,10 +50,6 @@ function Podfile (podFilePath, projectName, minDeploymentTarget) { throw new CordovaError(util.format('Podfile: The file at %s is not `%s`.', this.path, Podfile.FILENAME)); } - if (!projectName) { - throw new CordovaError('Podfile: The projectName was not specified in the constructor.'); - } - if (!fs.existsSync(this.path)) { events.emit('verbose', util.format('Podfile: The file at %s does not exist.', this.path)); events.emit('verbose', 'Creating new Podfile in platforms/ios'); @@ -168,18 +164,16 @@ Podfile.prototype.escapeSingleQuotes = function (string) { }; Podfile.prototype.getTemplate = function () { - // Escaping possible ' in the project name - const projectName = this.escapeSingleQuotes(this.projectName); return util.format( '# DO NOT MODIFY -- auto-generated by Apache Cordova\n' + '%s\n' + 'platform :ios, \'%s\'\n' + '%s\n' + - 'target \'%s\' do\n' + - '\tproject \'%s.xcodeproj\'\n' + + 'target \'App\' do\n' + + '\tproject \'App.xcodeproj\'\n' + '%s\n' + 'end\n', - this.sourceToken, this.minDeploymentTarget, this.declarationToken, projectName, projectName, this.podToken); + this.sourceToken, this.minDeploymentTarget, this.declarationToken, this.podToken); }; Podfile.prototype.addSpec = function (name, spec) { @@ -361,10 +355,10 @@ Podfile.prototype.before_install = function (toolOptions) { // Template tokens in order: project name, project name, debug | release const template = '// DO NOT MODIFY -- auto-generated by Apache Cordova\n' + - '#include "Pods/Target Support Files/Pods-%s/Pods-%s.%s.xcconfig"'; + '#include "Pods/Target Support Files/Pods-App/Pods-App.%s.xcconfig"'; - const debugContents = util.format(template, this.projectName, this.projectName, 'debug'); - const releaseContents = util.format(template, this.projectName, this.projectName, 'release'); + const debugContents = util.format(template, 'debug'); + const releaseContents = util.format(template, 'release'); const debugConfigPath = path.join(this.path, '..', 'pods-debug.xcconfig'); const releaseConfigPath = path.join(this.path, '..', 'pods-release.xcconfig'); diff --git a/lib/build.js b/lib/build.js index fbca274349..11a6df6148 100644 --- a/lib/build.js +++ b/lib/build.js @@ -61,12 +61,11 @@ const buildFlagMatchers = { * a project path and name * * @param {*} projectPath - * @param {*} projectName */ -function createProjectObject (projectPath, projectName) { +function createProjectObject (projectPath) { const locations = { root: projectPath, - pbxproj: path.join(projectPath, `${projectName}.xcodeproj`, 'project.pbxproj') + pbxproj: path.join(projectPath, 'App.xcodeproj', 'project.pbxproj') }; return projectFile.parse(locations); @@ -103,7 +102,6 @@ function getDefaultSimulatorTarget () { module.exports.run = function (buildOpts) { const projectPath = this.root; let emulatorTarget = 'iOS Device'; - let projectName = ''; buildOpts = buildOpts || {}; @@ -180,9 +178,7 @@ module.exports.run = function (buildOpts) { } }) .then(() => check_reqs.run()) - .then(() => findXCodeProjectIn(projectPath)) - .then(name => { - projectName = name; + .then(() => { let extraConfig = ''; if (buildOpts.codeSignIdentity) { extraConfig += `CODE_SIGN_IDENTITY = ${buildOpts.codeSignIdentity}\n`; @@ -201,7 +197,7 @@ module.exports.run = function (buildOpts) { } function writeCodeSignStyle (value) { - const project = createProjectObject(projectPath, projectName); + const project = createProjectObject(projectPath); events.emit('verbose', `Set CODE_SIGN_STYLE Build Property to ${value}.`); project.xcode.updateBuildProperty('CODE_SIGN_STYLE', value); @@ -223,7 +219,7 @@ module.exports.run = function (buildOpts) { }).then(() => { const configuration = buildOpts.release ? 'Release' : 'Debug'; - events.emit('log', `Building project: ${path.join(projectPath, `${projectName}.xcworkspace`)}`); + events.emit('log', `Building project: ${path.join(projectPath, 'App.xcworkspace')}`); events.emit('log', `\tConfiguration: ${configuration}`); events.emit('log', `\tPlatform: ${buildOpts.device ? 'device' : 'emulator'}`); events.emit('log', `\tTarget: ${emulatorTarget}`); @@ -233,14 +229,14 @@ module.exports.run = function (buildOpts) { // remove the build output folder before building fs.rmSync(buildOutputDir, { recursive: true, force: true }); - const xcodebuildArgs = getXcodeBuildArgs(projectName, projectPath, configuration, emulatorTarget, buildOpts); + const xcodebuildArgs = getXcodeBuildArgs(projectPath, configuration, emulatorTarget, buildOpts); return execa('xcodebuild', xcodebuildArgs, { cwd: projectPath, stdio: 'inherit' }); }).then(() => { if (!buildOpts.device || buildOpts.catalyst || buildOpts.noSign) { return; } - const project = createProjectObject(projectPath, projectName); + const project = createProjectObject(projectPath); const bundleIdentifier = project.getPackageName(); const exportOptions = { ...buildOpts.exportOptions, compileBitcode: false, method: 'development' }; @@ -287,7 +283,7 @@ module.exports.run = function (buildOpts) { } function packageArchive () { - const xcodearchiveArgs = getXcodeArchiveArgs(projectName, projectPath, buildOutputDir, exportOptionsPath, buildOpts); + const xcodearchiveArgs = getXcodeArchiveArgs(projectPath, buildOutputDir, exportOptionsPath, buildOpts); return execa('xcodebuild', xcodearchiveArgs, { cwd: projectPath, stdio: 'inherit' }); } @@ -298,38 +294,15 @@ module.exports.run = function (buildOpts) { .then(() => {}); // resolve to undefined }; -/** - * Searches for first XCode project in specified folder - * @param {String} projectPath Path where to search project - * @return {Promise} Promise either fulfilled with project name or rejected - */ -function findXCodeProjectIn (projectPath) { - // 'Searching for Xcode project in ' + projectPath); - const xcodeProjFiles = fs.readdirSync(projectPath).filter(name => path.extname(name) === '.xcodeproj'); - - if (xcodeProjFiles.length === 0) { - return Promise.reject(new CordovaError(`No Xcode project found in ${projectPath}`)); - } - if (xcodeProjFiles.length > 1) { - events.emit('warn', `Found multiple .xcodeproj directories in \n${projectPath}\nUsing first one`); - } - - const projectName = path.basename(xcodeProjFiles[0], '.xcodeproj'); - return Promise.resolve(projectName); -} - -module.exports.findXCodeProjectIn = findXCodeProjectIn; - /** * Returns array of arguments for xcodebuild - * @param {String} projectName Name of xcode project * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild * @param {String} configuration Configuration name: debug|release * @param {String} emulatorTarget Target for emulator (rather than default) * @param {Object} buildConfig The build configuration options * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTarget, buildConfig = {}) { +function getXcodeBuildArgs (projectPath, configuration, emulatorTarget, buildConfig = {}) { let options; let buildActions; let settings; @@ -349,11 +322,11 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTar if (buildConfig.device && !buildConfig.catalyst) { options = [ - '-workspace', customArgs.workspace || `${projectName}.xcworkspace`, - '-scheme', customArgs.scheme || projectName, + '-workspace', customArgs.workspace || 'App.xcworkspace', + '-scheme', customArgs.scheme || 'App', '-configuration', customArgs.configuration || configuration, '-destination', customArgs.destination || 'generic/platform=iOS', - '-archivePath', customArgs.archivePath || `${projectName}.xcarchive` + '-archivePath', customArgs.archivePath || 'App.xcarchive' ]; buildActions = ['archive']; settings = []; @@ -386,8 +359,8 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTar } } else { // emulator options = [ - '-workspace', customArgs.workspace || `${projectName}.xcworkspace`, - '-scheme', customArgs.scheme || projectName, + '-workspace', customArgs.workspace || 'App.xcworkspace', + '-scheme', customArgs.scheme || 'App', '-configuration', customArgs.configuration || configuration ]; @@ -425,15 +398,27 @@ function getXcodeBuildArgs (projectName, projectPath, configuration, emulatorTar /** * Returns array of arguments for xcodebuild - * @param {String} projectName Name of xcode project * @param {String} projectPath Path to project file. Will be used to set CWD for xcodebuild * @param {String} outputPath Output directory to contain the IPA * @param {String} exportOptionsPath Path to the exportOptions.plist file * @param {Object} buildConfig Build configuration options * @return {Array} Array of arguments that could be passed directly to spawn method */ -function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOptionsPath, buildConfig = {}) { +function getXcodeArchiveArgs (projectPath, outputPath, exportOptionsPath, buildConfig = {}) { const options = []; + const buildFlags = buildConfig.buildFlag; + const customArgs = {}; + customArgs.otherFlags = []; + + if (buildFlags) { + if (typeof buildFlags === 'string' || buildFlags instanceof String) { + parseBuildFlag(buildFlags, customArgs); + } else { // buildFlags is an Array of strings + buildFlags.forEach(flag => { + parseBuildFlag(flag, customArgs); + }); + } + } if (buildConfig.automaticProvisioning) { options.push('-allowProvisioningUpdates'); @@ -450,10 +435,10 @@ function getXcodeArchiveArgs (projectName, projectPath, outputPath, exportOption return [ '-exportArchive', - '-archivePath', `${projectName}.xcarchive`, + '-archivePath', customArgs.archivePath || 'App.xcarchive', '-exportOptionsPlist', exportOptionsPath, '-exportPath', outputPath - ].concat(options); + ].concat(options).concat(customArgs.otherFlags); } function parseBuildFlag (buildFlag, args) { diff --git a/lib/clean.js b/lib/clean.js index 2c8c2e6b2c..f1e9595edc 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -20,21 +20,15 @@ const path = require('node:path'); const fs = require('node:fs'); const execa = require('execa'); -const { CordovaError } = require('cordova-common'); module.exports.run = function () { const projectPath = this.root; - const projectName = fs.readdirSync(projectPath).filter(name => path.extname(name) === '.xcodeproj'); - - if (!projectName) { - return Promise.reject(new CordovaError(`No Xcode project found in ${projectPath}`)); - } const xcodebuildClean = configName => { return execa( 'xcodebuild', - ['-project', projectName, '-configuration', configName, '-alltargets', 'clean'], - { cwd: projectPath, stdio: 'inherit' } + ['-project', 'App.xcodeproj', '-configuration', configName, '-alltargets', 'clean'], + { cwd: this.root, stdio: 'inherit' } ); }; diff --git a/lib/create.js b/lib/create.js index 6ac4c3cba9..2c4ea38d39 100755 --- a/lib/create.js +++ b/lib/create.js @@ -19,8 +19,8 @@ const path = require('node:path'); const fs = require('node:fs'); -const xmlescape = require('xml-escape'); const { CordovaError, events } = require('cordova-common'); +const xcode = require('xcode'); const pkg = require('../package'); const ROOT = path.join(__dirname, '..'); @@ -71,16 +71,15 @@ class ProjectCreator { create () { this.provideProjectTemplate(); this.provideCordovaJs(); - this.provideCordovaLib(); this.provideBuildScripts(); - this.expandTokens(); + this.updateProjectSettings(); } provideProjectTemplate () { fs.cpSync(this.options.templatePath, this.project.path, { recursive: true }); // TODO: why two .gitignores? - const r = this.projectPath('__PROJECT_NAME__'); + const r = this.projectPath('App'); fs.renameSync(path.join(r, 'gitignore'), path.join(r, '.gitignore')); fs.cpSync(path.join(r, '.gitignore'), this.projectPath('.gitignore')); } @@ -92,135 +91,40 @@ class ProjectCreator { ); } - provideCordovaLib () { - this.copyOrLinkCordovaLib(); - this.configureCordovaLibPath(); - } - provideBuildScripts () { const srcScriptsDir = path.join(ROOT, 'templates', 'cordova'); const destScriptsDir = this.projectPath('cordova'); fs.cpSync(srcScriptsDir, destScriptsDir, { recursive: true }); } - expandTokens () { - this.expandTokensInFileContents(); - this.expandTokensInFileNames(); - } - - copyOrLinkCordovaLib () { - const cordovaLibPathSrc = path.join(ROOT, 'CordovaLib'); - const cordovaLibPathDest = this.projectPath('CordovaLib'); - - if (this.options.linkLib) { - // Symlink not used in project file, but is currently required for plugman because - // it reads the VERSION file from it (instead of using the cordova/version script - // like it should). - fs.symlinkSync(cordovaLibPathSrc, cordovaLibPathDest); - } else { - fs.cpSync(cordovaLibPathSrc, cordovaLibPathDest, { recursive: true }); - } - } - - configureCordovaLibPath () { - // CordovaLib could be a symlink, so we resolve it - const cdvLibRealPath = fs.realpathSync(this.projectPath('CordovaLib')); - - const cdvLibXcodeAbsPath = path.join(cdvLibRealPath, 'CordovaLib.xcodeproj'); - let cdvLibXcodePath = path.relative(this.project.path, cdvLibXcodeAbsPath); - - if (path.sep !== path.posix.sep) { - // If the Cordova project is being created on Windows, we need to - // make sure the Xcode project file uses POSIX-style paths or else - // Xcode considers it invalid - cdvLibXcodePath = cdvLibXcodePath.replace(path.sep, path.posix.sep); - } - - // Replace magic line in project.pbxproj - const pbxprojPath = this.projectPath('__PROJECT_NAME__.xcodeproj', 'project.pbxproj'); - transformFileContents(pbxprojPath, contents => { - const regex = /(.+CordovaLib.xcodeproj.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)/; - const line = contents.split(/\r?\n/) - .find(l => regex.test(l)); - - if (!line) { - throw new Error(`Entry not found in project file for sub-project: ${cdvLibXcodePath}`); - } - - let newLine = line - .replace(/path = .+?;/, `path = ${cdvLibXcodePath};`) - .replace(/sourceTree.+?;/, 'sourceTree = "";'); - - if (!newLine.match('name')) { - newLine = newLine.replace('path = ', 'name = CordovaLib.xcodeproj; path = '); + updateProjectSettings () { + const projectPath = this.projectPath('App.xcodeproj', 'project.pbxproj'); + const xcodeproj = xcode.project(projectPath); + xcodeproj.parseSync(); + + xcodeproj.updateBuildProperty('PRODUCT_NAME', `"${this.project.name}"`, null, 'App'); + xcodeproj.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', `"${this.project.id}"`, null, 'App'); + + // Update the CordovaLib Swift package reference path + const pkgRefs = xcodeproj.hash.project.objects.XCLocalSwiftPackageReference; + if (pkgRefs) { + for (const [key, ref] of Object.entries(pkgRefs)) { + /* istanbul ignore if */ + if (key.endsWith('_comment')) { + continue; + } + + if (ref.relativePath?.match(/\/cordova-ios/)) { + ref.relativePath = `"${path.relative(this.project.path, ROOT).replaceAll(path.sep, path.posix.sep)}"`; + break; + } } - - return contents.replace(line, newLine); - }); - } - - expandTokensInFileContents () { - // Expand __PROJECT_ID__ token in file contents - transformFileContents( - this.projectPath('__PROJECT_NAME__.xcodeproj', 'project.pbxproj'), - contents => contents.replace(/__PROJECT_ID__/g, this.project.id) - ); - - // Expand __PROJECT_NAME__ token in file contents - for (const p of [ - ['cordova', 'build-debug.xcconfig'], - ['cordova', 'build-release.xcconfig'], - ['__PROJECT_NAME__.xcworkspace', 'contents.xcworkspacedata'], - ['__PROJECT_NAME__.xcworkspace', 'xcshareddata', 'xcschemes', '__PROJECT_NAME__.xcscheme'], - ['__PROJECT_NAME__.xcodeproj', 'project.pbxproj'], - ['__PROJECT_NAME__', 'AppDelegate.h'], - ['__PROJECT_NAME__', 'MainViewController.h'], - ['__PROJECT_NAME__', 'AppDelegate.swift'], - ['__PROJECT_NAME__', 'SceneDelegate.swift'], - ['__PROJECT_NAME__', 'ViewController.swift'], - ['__PROJECT_NAME__', '__PROJECT_NAME__-Info.plist'] - ]) { - this.expandProjectNameInFileContents(this.projectPath(...p)); } - } - expandTokensInFileNames () { - // Expand __PROJECT_NAME__ token in file & folder names - for (const p of [ - ['__PROJECT_NAME__.xcworkspace', 'xcshareddata', 'xcschemes', '__PROJECT_NAME__.xcscheme'], - ['__PROJECT_NAME__.xcworkspace'], - ['__PROJECT_NAME__.xcodeproj'], - ['__PROJECT_NAME__', '__PROJECT_NAME__-Info.plist'], - ['__PROJECT_NAME__'] - ]) { - this.expandProjectNameInBaseName(this.projectPath(...p)); - } - } - - expandProjectNameInBaseName (f) { - const { dir, base } = path.parse(f); - const newBase = base.replace('__PROJECT_NAME__', this.project.name); - return fs.renameSync(f, path.join(dir, newBase)); - } - - expandProjectNameInFileContents (f) { - // https://issues.apache.org/jira/browse/CB-12402 - Encode XML characters properly - const xmlExtensions = new Set(['.xcworkspacedata', '.xcscheme']); - const escape = xmlExtensions.has(path.extname(f)) - ? xmlescape - : s => s.replace(/&/g, '\\&'); - - transformFileContents(f, contents => - contents.replace(/__PROJECT_NAME__/g, escape(this.project.name)) - ); + fs.writeFileSync(projectPath, xcodeproj.writeSync()); } projectPath (...projectRelativePaths) { return path.join(this.project.path, ...projectRelativePaths); } } - -function transformFileContents (file, transform) { - const contents = fs.readFileSync(file, 'utf-8'); - fs.writeFileSync(file, transform(contents)); -} diff --git a/lib/prepare.js b/lib/prepare.js index 73f900443c..54ca51fe56 100644 --- a/lib/prepare.js +++ b/lib/prepare.js @@ -119,7 +119,7 @@ function overwritePrivacyManifest (manifest, locations) { return; } // Set default privacy manifest - const defaultPrivacyManifest = path.join(__dirname, '..', 'templates', 'project', '__PROJECT_NAME__', 'PrivacyInfo.xcprivacy'); + const defaultPrivacyManifest = path.join(__dirname, '..', 'templates', 'project', 'App', 'PrivacyInfo.xcprivacy'); const xmlString = fs.readFileSync(defaultPrivacyManifest, 'utf8'); fs.writeFileSync(privacyManifestDest, xmlString, 'utf-8'); } @@ -217,32 +217,13 @@ function cleanWww (projectRoot, locations) { * @param {Object} locations A map of locations for this platform (In/Out) */ function updateProject (platformConfig, locations) { - // CB-6992 it is necessary to normalize characters - // because node and shell scripts handles unicode symbols differently - // We need to normalize the name to NFD form since iOS uses NFD unicode form - const name = platformConfig.name().normalize('NFD'); - const version = platformConfig.version(); - const displayName = platformConfig.shortName && platformConfig.shortName(); - - const originalName = path.basename(locations.xcodeCordovaProj); - - // Update package id (bundle id) - const plistFile = path.join(locations.xcodeCordovaProj, `${originalName}-Info.plist`); + const plistFile = path.join(locations.xcodeCordovaProj, 'App-Info.plist'); const infoPlist = plist.parse(fs.readFileSync(plistFile, 'utf8')); - // Update version (bundle version) - infoPlist.CFBundleShortVersionString = version; - const CFBundleVersion = platformConfig.getAttribute('ios-CFBundleVersion') || default_CFBundleVersion(version); - infoPlist.CFBundleVersion = CFBundleVersion; - if (platformConfig.getAttribute('defaultlocale')) { infoPlist.CFBundleDevelopmentRegion = platformConfig.getAttribute('defaultlocale'); } - if (displayName) { - infoPlist.CFBundleDisplayName = displayName; - } - // replace Info.plist ATS entries according to and config.xml entries const ats = writeATSEntries(platformConfig); if (Object.keys(ats).length > 0) { @@ -251,8 +232,6 @@ function updateProject (platformConfig, locations) { delete infoPlist.NSAppTransportSecurity; } - handleOrientationSettings(platformConfig, infoPlist); - /* eslint-disable no-tabs */ // Write out the plist file with the same formatting as Xcode does let info_contents = plist.build(infoPlist, { indent: '\t', offset: -1 }); @@ -260,56 +239,49 @@ function updateProject (platformConfig, locations) { info_contents = info_contents.replace(/[\s\r\n]*<\/string>/g, ''); fs.writeFileSync(plistFile, info_contents, 'utf-8'); - events.emit('verbose', `Wrote out iOS Bundle Version "${version}" to ${plistFile}`); - - return handleBuildSettings(platformConfig, locations, infoPlist).then(() => { - if (name === originalName) { - events.emit('verbose', `iOS Product Name has not changed (still "${originalName}")`); - return Promise.resolve(); - } else { // CB-11712 was changed, we don't support it' - const errorString = - 'The product name change ( tag) in config.xml is not supported dynamically.\n' + - 'To change your product name, you have to remove, then add your ios platform again.\n' + - 'Make sure you save your plugins beforehand using `cordova plugin save`.\n' + - '\tcordova plugin save\n' + - '\tcordova platform rm ios\n' + - '\tcordova platform add ios\n'; - - return Promise.reject(new CordovaError(errorString)); - } - }); + + return handleBuildSettings(platformConfig, locations, infoPlist); } -function handleOrientationSettings (platformConfig, infoPlist) { +function handleOrientationSettings (platformConfig, project) { + function setProp (name, value) { + if (value) { + project.xcode.updateBuildProperty(`INFOPLIST_KEY_${name}`, `"${value}"`, null, 'App'); + } else { + project.xcode.updateBuildProperty(`INFOPLIST_KEY_${name}`, null, null, 'App'); + } + } + + const kPort = 'UIInterfaceOrientationPortrait'; + const kPortU = 'UIInterfaceOrientationPortraitUpsideDown'; + const kLandL = 'UIInterfaceOrientationLandscapeLeft'; + const kLandR = 'UIInterfaceOrientationLandscapeRight'; + switch (getOrientationValue(platformConfig)) { case 'portrait': - infoPlist.UIInterfaceOrientation = ['UIInterfaceOrientationPortrait']; - infoPlist.UISupportedInterfaceOrientations = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown']; - infoPlist['UISupportedInterfaceOrientations~ipad'] = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown']; + setProp('UIInterfaceOrientation', kPort); + setProp('UISupportedInterfaceOrientations_iPhone', [kPort, kPortU].join(' ')); + setProp('UISupportedInterfaceOrientations_iPad', [kPort, kPortU].join(' ')); break; case 'landscape': - infoPlist.UIInterfaceOrientation = ['UIInterfaceOrientationLandscapeLeft']; - infoPlist.UISupportedInterfaceOrientations = ['UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; - infoPlist['UISupportedInterfaceOrientations~ipad'] = ['UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; + setProp('UIInterfaceOrientation', kLandL); + setProp('UISupportedInterfaceOrientations_iPhone', [kLandL, kLandR].join(' ')); + setProp('UISupportedInterfaceOrientations_iPad', [kLandL, kLandR].join(' ')); break; case 'all': - infoPlist.UIInterfaceOrientation = ['UIInterfaceOrientationPortrait']; - infoPlist.UISupportedInterfaceOrientations = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; - infoPlist['UISupportedInterfaceOrientations~ipad'] = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; + // TODO: Should we default to portrait in this case or set it to null? + setProp('UIInterfaceOrientation', kPort); + setProp('UISupportedInterfaceOrientations_iPhone', [kPort, kPortU, kLandL, kLandR].join(' ')); + setProp('UISupportedInterfaceOrientations_iPad', [kPort, kPortU, kLandL, kLandR].join(' ')); break; case 'default': - infoPlist.UISupportedInterfaceOrientations = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; - infoPlist['UISupportedInterfaceOrientations~ipad'] = ['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']; - delete infoPlist.UIInterfaceOrientation; + setProp('UIInterfaceOrientation', null); + setProp('UISupportedInterfaceOrientations_iPhone', [kPort, kLandL, kLandR].join(' ')); + setProp('UISupportedInterfaceOrientations_iPad', [kPort, kPortU, kLandL, kLandR].join(' ')); } } function handleBuildSettings (platformConfig, locations, infoPlist) { - const pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName(); - const targetDevice = parseTargetDevicePreference(platformConfig.getPreference('target-device', 'ios')); - const deploymentTarget = platformConfig.getPreference('deployment-target', 'ios'); - const swiftVersion = platformConfig.getPreference('SwiftVersion', 'ios'); - let project; try { @@ -318,34 +290,51 @@ function handleBuildSettings (platformConfig, locations, infoPlist) { return Promise.reject(new CordovaError(`Could not parse ${locations.pbxproj}: ${err}`)); } - const origPkg = project.xcode.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, platformConfig.name()); + const pkg = platformConfig.getAttribute('ios-CFBundleIdentifier') || platformConfig.packageName(); + const name = platformConfig.name(); + const version = platformConfig.version(); + const displayName = platformConfig.shortName(); + const CFBundleVersion = platformConfig.getAttribute('ios-CFBundleVersion') || default_CFBundleVersion(version); - // no build settings provided and we don't need to update build settings for launch storyboards, - // then we don't need to parse and update .pbxproj file - if (origPkg === pkg && !targetDevice && !deploymentTarget && !swiftVersion) { - return Promise.resolve(); - } + events.emit('verbose', `Set PRODUCT_BUNDLE_IDENTIFIER to ${pkg}.`); + project.xcode.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', `"${pkg}"`, null, 'App'); - if (origPkg !== pkg) { - events.emit('verbose', `Set PRODUCT_BUNDLE_IDENTIFIER to ${pkg}.`); - project.xcode.updateBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', pkg, null, platformConfig.name()); + events.emit('verbose', `Set PRODUCT_NAME to ${name}.`); + project.xcode.updateBuildProperty('PRODUCT_NAME', `"${name}"`, null, 'App'); + + events.emit('verbose', `Set MARKETING_VERSION to ${version}.`); + project.xcode.updateBuildProperty('MARKETING_VERSION', version, null, 'App'); + + events.emit('verbose', `Set CURRENT_PROJECT_VERSION to ${CFBundleVersion}.`); + project.xcode.updateBuildProperty('CURRENT_PROJECT_VERSION', CFBundleVersion, null, 'App'); + + if (displayName !== name) { + events.emit('verbose', `Set INFOPLIST_KEY_CFBundleDisplayName to ${displayName}.`); + project.xcode.updateBuildProperty('INFOPLIST_KEY_CFBundleDisplayName', `"${displayName}"`, null, 'App'); + } else { + project.xcode.updateBuildProperty('INFOPLIST_KEY_CFBundleDisplayName', '"$(PRODUCT_NAME)"', null, 'App'); } + const targetDevice = parseTargetDevicePreference(platformConfig.getPreference('target-device', 'ios')); if (targetDevice) { events.emit('verbose', `Set TARGETED_DEVICE_FAMILY to ${targetDevice}.`); project.xcode.updateBuildProperty('TARGETED_DEVICE_FAMILY', targetDevice); } + const deploymentTarget = platformConfig.getPreference('deployment-target', 'ios'); if (deploymentTarget) { events.emit('verbose', `Set IPHONEOS_DEPLOYMENT_TARGET to "${deploymentTarget}".`); project.xcode.updateBuildProperty('IPHONEOS_DEPLOYMENT_TARGET', deploymentTarget); } + const swiftVersion = platformConfig.getPreference('SwiftVersion', 'ios'); if (swiftVersion) { events.emit('verbose', `Set SwiftVersion to "${swiftVersion}".`); project.xcode.updateBuildProperty('SWIFT_VERSION', swiftVersion); } + handleOrientationSettings(platformConfig, project); + project.write(); // If we have a Podfile, we want to update the deployment target there too @@ -1136,7 +1125,7 @@ function getOrientationValue (platformConfig) { let orientation = platformConfig.getPreference('orientation'); if (!orientation) { - return ''; + return ORIENTATION_DEFAULT; } orientation = orientation.toLowerCase(); diff --git a/lib/projectFile.js b/lib/projectFile.js index 1ad65f7b2e..1e9fa06da2 100644 --- a/lib/projectFile.js +++ b/lib/projectFile.js @@ -20,7 +20,6 @@ const fs = require('node:fs'); const path = require('node:path'); const xcode = require('xcode'); -const plist = require('plist'); const pluginHandlers = require('./plugman/pluginHandlers'); const CordovaError = require('cordova-common').CordovaError; @@ -38,13 +37,10 @@ function parseProjectFile (locations) { const xcodeproj = xcode.project(pbxPath); xcodeproj.parseSync(); - const xcBuildConfiguration = xcodeproj.pbxXCBuildConfigurationSection(); - const plist_file_entry = Object.values(xcBuildConfiguration).find(entry => entry.buildSettings && entry.buildSettings.INFOPLIST_FILE); - const plist_file = path.join(project_dir, plist_file_entry.buildSettings.INFOPLIST_FILE.replace(/^"(.*)"$/g, '$1').replace(/\\&/g, '&')); - const config_file = path.join(path.dirname(plist_file), 'config.xml'); + const config_file = path.join(project_dir, 'App', 'config.xml'); - if (!fs.existsSync(plist_file) || !fs.existsSync(config_file)) { - throw new CordovaError('Could not find *-Info.plist file, or config.xml file.'); + if (!fs.existsSync(config_file)) { + throw new CordovaError('Could not find config.xml file.'); } const frameworks_file = path.join(project_dir, 'frameworks.json'); @@ -53,7 +49,7 @@ function parseProjectFile (locations) { frameworks = require(frameworks_file); } catch (e) { } - const xcode_dir = path.dirname(plist_file); + const xcode_dir = path.join(project_dir, 'App'); const pluginsDir = path.resolve(xcode_dir, 'Plugins'); const resourcesDir = path.resolve(xcode_dir, 'Resources'); @@ -67,7 +63,7 @@ function parseProjectFile (locations) { platformWww: path.join(project_dir, 'platform_www'), www: path.join(project_dir, 'www'), write: function () { - fs.writeFileSync(pbxPath, xcodeproj.writeSync()); + fs.writeFileSync(pbxPath, xcodeproj.writeSync({ omitEmptyValues: true })); if (Object.keys(this.frameworks).length === 0) { // If there is no framework references remain in the project, just remove this file fs.rmSync(frameworks_file, { force: true }); @@ -76,15 +72,7 @@ function parseProjectFile (locations) { fs.writeFileSync(frameworks_file, JSON.stringify(this.frameworks, null, 4)); }, getPackageName: function () { - const packageName = plist.parse(fs.readFileSync(plist_file, 'utf8')).CFBundleIdentifier; - let bundleIdentifier = packageName; - - const variables = packageName.match(/\$\((\w+)\)/); // match $(VARIABLE), if any - if (variables && variables.length >= 2) { - bundleIdentifier = xcodeproj.getBuildProperty(variables[1]); - } - - return bundleIdentifier.replace(/^"/, '').replace(/"$/, ''); + return xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'App').replace(/^"/, '').replace(/"$/, ''); }, getInstaller: function (name) { return pluginHandlers.getInstaller(name); diff --git a/lib/run.js b/lib/run.js index a1899e8d79..eb35c6b095 100644 --- a/lib/run.js +++ b/lib/run.js @@ -23,10 +23,12 @@ const execa = require('execa'); const { CordovaError, events } = require('cordova-common'); const build = require('./build'); const check_reqs = require('./check_reqs'); +const projectFile = require('./projectFile'); /** @returns {Promise} */ module.exports.run = function (runOptions) { const projectPath = this.root; + const locations = this.locations; // Validate args if (runOptions.device && runOptions.emulator) { @@ -62,28 +64,36 @@ module.exports.run = function (runOptions) { }) .then(() => { if (!runOptions.nobuild) { - return build.run(runOptions); + return build.run.call(this, runOptions); } }) - .then(() => build.findXCodeProjectIn(projectPath)) - .then(projectName => { + .then(() => { + try { + const project = projectFile.parse(locations); + + return project.xcode.getBuildProperty('PRODUCT_NAME', undefined, 'App').replace(/^"/, '').replace(/"$/, ''); + } catch (err) { + return Promise.reject(new CordovaError(`Could not parse ${locations.pbxproj}: ${err}`)); + } + }) + .then(productName => { // select command to run and arguments depending whether // we're running on device/catalyst/emulator if (useDevice) { const buildOutputDir = path.join(projectPath, 'build', `${configuration}-iphoneos`); - const appPath = path.join(buildOutputDir, `${projectName}.app`); + const appPath = path.join(buildOutputDir, `${productName}.app`); return module.exports.checkDeviceConnected() .then(() => { // Unpack IPA - const ipafile = path.join(buildOutputDir, `${projectName}.ipa`); + const ipafile = path.join(buildOutputDir, `${productName}.ipa`); // unpack the existing platform/ios/build/device/appname.ipa (zipfile), will create a Payload folder return execa('unzip', ['-o', '-qq', ipafile], { cwd: buildOutputDir, stdio: 'inherit' }); }) .then(() => { // Uncompress IPA (zip file) - const appFileInflated = path.join(buildOutputDir, 'Payload', `${projectName}.app`); + const appFileInflated = path.join(buildOutputDir, 'Payload', `${productName}.app`); const payloadFolder = path.join(buildOutputDir, 'Payload'); // delete the existing platform/ios/build/device/appname.app @@ -109,10 +119,10 @@ module.exports.run = function (runOptions) { () => module.exports.deployToSim(appPath, runOptions.target) ); } else if (useCatalyst) { - const appPath = path.join(projectPath, 'build', `${configuration}-maccatalyst`, `${projectName}.app`); + const appPath = path.join(projectPath, 'build', `${configuration}-maccatalyst`, `${productName}.app`); return module.exports.deployToMac(appPath); } else { - const appPath = path.join(projectPath, 'build', `${configuration}-iphonesimulator`, `${projectName}.app`); + const appPath = path.join(projectPath, 'build', `${configuration}-iphonesimulator`, `${productName}.app`); return module.exports.deployToSim(appPath, runOptions.target); } }) diff --git a/package-lock.json b/package-lock.json index fca349fa91..b4546bb76f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,7 @@ "plist": "^3.0.6", "semver": "^7.4.0", "which": "^4.0.0", - "xcode": "^3.0.1", - "xml-escape": "^1.1.0" + "xcode": "^3.0.1" }, "devDependencies": { "@cordova/eslint-config": "^5.1.0", @@ -60,9 +59,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "dev": true, "license": "MIT", "engines": { @@ -118,13 +117,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", + "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.0", + "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -238,14 +237,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.0.tgz", - "integrity": "sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.6.tgz", + "integrity": "sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.25.0", - "@babel/types": "^7.25.0" + "@babel/types": "^7.25.6" }, "engines": { "node": ">=6.9.0" @@ -346,13 +345,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.3.tgz", - "integrity": "sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.25.2" + "@babel/types": "^7.25.6" }, "bin": { "parser": "bin/babel-parser.js" @@ -377,17 +376,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.3.tgz", - "integrity": "sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", + "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.3", + "@babel/generator": "^7.25.6", + "@babel/parser": "^7.25.6", "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", + "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -406,9 +405,9 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dev": true, "license": "MIT", "dependencies": { @@ -1350,9 +1349,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001651", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001651.tgz", - "integrity": "sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==", + "version": "1.0.30001655", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", + "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", "dev": true, "funding": [ { @@ -1727,9 +1726,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.11", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.11.tgz", - "integrity": "sha512-R1CccCDYqndR25CaXFd6hp/u9RaaMcftMkphmvuepXr5b1vfLkRml6aWVeBhXJ7rbevHkKEMJtz8XqPf7ffmew==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", "dev": true, "license": "ISC" }, @@ -1911,9 +1910,9 @@ "license": "MIT" }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -2042,9 +2041,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", - "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.2.tgz", + "integrity": "sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==", "dev": true, "license": "MIT", "dependencies": { @@ -3137,9 +3136,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", - "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -3851,6 +3850,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -5616,12 +5616,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/xml-escape": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xml-escape/-/xml-escape-1.1.0.tgz", - "integrity": "sha512-B/T4sDK8Z6aUh/qNr7mjKAwwncIljFuUP+DO/D5hloYFj+90O88z8Wf7oSucZTHxBAsC1/CTP4rtx/x1Uf72Mg==", - "license": "MIT License" - }, "node_modules/xmlbuilder": { "version": "15.1.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", diff --git a/package.json b/package.json index 92558849ee..39828d1856 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "semver": "^7.4.0", "which": "^4.0.0", "xcode": "^3.0.1", - "xml-escape": "^1.1.0", "elementtree": "^0.1.7" }, "nyc": { diff --git a/templates/project/__PROJECT_NAME__.xcodeproj/project.pbxproj b/templates/project/App.xcodeproj/project.pbxproj similarity index 82% rename from templates/project/__PROJECT_NAME__.xcodeproj/project.pbxproj rename to templates/project/App.xcodeproj/project.pbxproj index 7765440c06..13c3d643c3 100755 --- a/templates/project/__PROJECT_NAME__.xcodeproj/project.pbxproj +++ b/templates/project/App.xcodeproj/project.pbxproj @@ -21,14 +21,14 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ - 902AE2142C6C059A0041150F /* Cordova.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 907F985F2C06B8DE00D2D242 /* Cordova.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 907F98562C06B87200D2D242 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 907F98552C06B87200D2D242 /* PrivacyInfo.xcprivacy */; }; 907F98662C06BC1B00D2D242 /* config.xml in Resources */ = {isa = PBXBuildFile; fileRef = 907F98652C06BC1B00D2D242 /* config.xml */; }; 907F986A2C06BCD300D2D242 /* www in Resources */ = {isa = PBXBuildFile; fileRef = 907F98692C06BCD300D2D242 /* www */; }; + 90A914592CA3D370003DB979 /* CordovaLib in Frameworks */ = {isa = PBXBuildFile; productRef = 90A914582CA3D370003DB979 /* CordovaLib */; }; 90BD9B7A2C06907D000DEBAB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B792C06907D000DEBAB /* Base */; }; 90BD9B7C2C06907E000DEBAB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B7B2C06907E000DEBAB /* Assets.xcassets */; }; 90BD9B7F2C06907E000DEBAB /* Base in Resources */ = {isa = PBXBuildFile; fileRef = 90BD9B7E2C06907E000DEBAB /* Base */; }; @@ -37,23 +37,6 @@ 90CBB52C2C06968500B805A2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90CBB52B2C06968500B805A2 /* ViewController.swift */; }; /* End PBXBuildFile section */ -/* Begin PBXContainerItemProxy section */ - 907F985C2C06B8DE00D2D242 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 68A32D7114102E1C006B237C; - remoteInfo = CordovaLib; - }; - 907F985E2C06B8DE00D2D242 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = C0C01EB21E3911D50056E6CB; - remoteInfo = Cordova; - }; -/* End PBXContainerItemProxy section */ - /* Begin PBXCopyFilesBuildPhase section */ 902AE2152C6C059A0041150F /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; @@ -61,7 +44,6 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 902AE2142C6C059A0041150F /* Cordova.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -72,17 +54,16 @@ 9040B1872C6DD3EB00662C5D /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; 9040B1882C6DD41B00662C5D /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = ""; }; 907F98552C06B87200D2D242 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; - 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = CordovaLib/CordovaLib.xcodeproj; sourceTree = ""; }; 907F98622C06B97000D2D242 /* Entitlements-Debug.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Entitlements-Debug.plist"; sourceTree = ""; }; 907F98632C06B9C800D2D242 /* Entitlements-Release.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Entitlements-Release.plist"; sourceTree = ""; }; 907F98652C06BC1B00D2D242 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = config.xml; sourceTree = ""; }; 907F98692C06BCD300D2D242 /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = SOURCE_ROOT; }; 9080B40F2C6DD7EC00078F33 /* config.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = ""; }; - 90BD9B6C2C06907D000DEBAB /* __PROJECT_NAME__.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "__PROJECT_NAME__.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 90BD9B6C2C06907D000DEBAB /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; 90BD9B792C06907D000DEBAB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 90BD9B7B2C06907E000DEBAB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 90BD9B7E2C06907E000DEBAB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/CDVLaunchScreen.storyboard; sourceTree = ""; }; - 90BD9B802C06907E000DEBAB /* __PROJECT_NAME__-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "__PROJECT_NAME__-Info.plist"; sourceTree = ""; }; + 90BD9B802C06907E000DEBAB /* App-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "App-Info.plist"; sourceTree = ""; }; 90CBB5272C06968500B805A2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 90CBB5292C06968500B805A2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 90CBB52B2C06968500B805A2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -99,6 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 90A914592CA3D370003DB979 /* CordovaLib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -119,15 +101,6 @@ path = Plugins; sourceTree = ""; }; - 907F98582C06B8DE00D2D242 /* Products */ = { - isa = PBXGroup; - children = ( - 907F985D2C06B8DE00D2D242 /* libCordova.a */, - 907F985F2C06B8DE00D2D242 /* Cordova.framework */, - ); - name = Products; - sourceTree = ""; - }; 907F98602C06B8F000D2D242 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -155,27 +128,27 @@ name = staging; sourceTree = ""; }; - 90BD9B632C06907D000DEBAB = { + 90BD9B632C06907D000DEBAB /* CustomTemplate */ = { isa = PBXGroup; children = ( - 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */, 9080B40F2C6DD7EC00078F33 /* config.xml */, 9040B1882C6DD41B00662C5D /* www */, - 90BD9B6E2C06907D000DEBAB /* __PROJECT_NAME__ */, + 90BD9B6E2C06907D000DEBAB /* App */, 90BD9B6D2C06907D000DEBAB /* Products */, 907F98602C06B8F000D2D242 /* Frameworks */, ); + name = CustomTemplate; sourceTree = ""; }; 90BD9B6D2C06907D000DEBAB /* Products */ = { isa = PBXGroup; children = ( - 90BD9B6C2C06907D000DEBAB /* __PROJECT_NAME__.app */, + 90BD9B6C2C06907D000DEBAB /* App.app */, ); name = Products; sourceTree = ""; }; - 90BD9B6E2C06907D000DEBAB /* __PROJECT_NAME__ */ = { + 90BD9B6E2C06907D000DEBAB /* App */ = { isa = PBXGroup; children = ( 90CBB5272C06968500B805A2 /* AppDelegate.swift */, @@ -196,15 +169,15 @@ 9080B40D2C6DD79000078F33 /* config */, 9080B40E2C6DD7A100078F33 /* staging */, ); - path = "__PROJECT_NAME__"; + path = App; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 90BD9B6B2C06907D000DEBAB /* __PROJECT_NAME__ */ = { + 90BD9B6B2C06907D000DEBAB /* App */ = { isa = PBXNativeTarget; - buildConfigurationList = 90BD9B852C06907E000DEBAB /* Build configuration list for PBXNativeTarget "__PROJECT_NAME__" */; + buildConfigurationList = 90BD9B852C06907E000DEBAB /* Build configuration list for PBXNativeTarget "App" */; buildPhases = ( 90BD9B682C06907D000DEBAB /* Sources */, 90BD9B692C06907D000DEBAB /* Frameworks */, @@ -215,11 +188,12 @@ ); dependencies = ( ); - name = "__PROJECT_NAME__"; + name = App; packageProductDependencies = ( + 90A914582CA3D370003DB979 /* CordovaLib */, ); - productName = "__PROJECT_NAME__"; - productReference = 90BD9B6C2C06907D000DEBAB /* __PROJECT_NAME__.app */; + productName = App; + productReference = 90BD9B6C2C06907D000DEBAB /* App.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -237,49 +211,27 @@ }; }; }; - buildConfigurationList = 90BD9B672C06907D000DEBAB /* Build configuration list for PBXProject "__PROJECT_NAME__" */; - compatibilityVersion = "Xcode 11.0"; + buildConfigurationList = 90BD9B672C06907D000DEBAB /* Build configuration list for PBXProject "App" */; + compatibilityVersion = "Xcode 15.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = 90BD9B632C06907D000DEBAB; + mainGroup = 90BD9B632C06907D000DEBAB /* CustomTemplate */; packageReferences = ( + 90A914572CA3D370003DB979 /* XCLocalSwiftPackageReference "../../../cordova-ios" */, ); productRefGroup = 90BD9B6D2C06907D000DEBAB /* Products */; projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 907F98582C06B8DE00D2D242 /* Products */; - ProjectRef = 907F98572C06B8DE00D2D242 /* CordovaLib.xcodeproj */; - }, - ); projectRoot = ""; targets = ( - 90BD9B6B2C06907D000DEBAB /* __PROJECT_NAME__ */, + 90BD9B6B2C06907D000DEBAB /* App */, ); }; /* End PBXProject section */ -/* Begin PBXReferenceProxy section */ - 907F985D2C06B8DE00D2D242 /* libCordova.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libCordova.a; - remoteRef = 907F985C2C06B8DE00D2D242 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 907F985F2C06B8DE00D2D242 /* Cordova.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = Cordova.framework; - remoteRef = 907F985E2C06B8DE00D2D242 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - /* Begin PBXResourcesBuildPhase section */ 90BD9B6A2C06907D000DEBAB /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -452,7 +404,6 @@ SWIFT_COMPILATION_MODE = wholemodule; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; - VALIDATE_WORKSPACE = NO; }; name = Release; }; @@ -461,10 +412,17 @@ baseConfigurationReference = 90EB303F2C6DD87600CEEB2F /* build-debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = "$(PROJECT_NAME)/Entitlements-$(CONFIGURATION).plist"; + CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/Entitlements-$(CONFIGURATION).plist"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = "__PROJECT_NAME__/__PROJECT_NAME__-Info.plist"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "$(TARGET_NAME)/$(TARGET_NAME)-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = CDVLaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -474,16 +432,16 @@ "$(OTHER_LDFLAGS)", "-ObjC", ); - PRODUCT_BUNDLE_IDENTIFIER = "__PROJECT_ID__"; + PRODUCT_BUNDLE_IDENTIFIER = "org.apache.cordova.AppTemplate$(DEVELOPMENT_TEAM)"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator"; SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_NAME)/Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "$(TARGET_NAME)/Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,7"; + TARGETED_DEVICE_FAMILY = "1,2,6,7"; }; name = Debug; }; @@ -492,10 +450,17 @@ baseConfigurationReference = 90EB30402C6DD87600CEEB2F /* build-release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_ENTITLEMENTS = "$(PROJECT_NAME)/Entitlements-$(CONFIGURATION).plist"; + CODE_SIGN_ENTITLEMENTS = "$(TARGET_NAME)/Entitlements-$(CONFIGURATION).plist"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = "__PROJECT_NAME__/__PROJECT_NAME__-Info.plist"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "$(TARGET_NAME)/$(TARGET_NAME)-Info.plist"; + INFOPLIST_KEY_CFBundleDisplayName = "$(PRODUCT_NAME)"; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = CDVLaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -505,23 +470,23 @@ "$(OTHER_LDFLAGS)", "-ObjC", ); - PRODUCT_BUNDLE_IDENTIFIER = "__PROJECT_ID__"; + PRODUCT_BUNDLE_IDENTIFIER = "org.apache.cordova.AppTemplate$(DEVELOPMENT_TEAM)"; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator xros xrsimulator"; SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "$(PROJECT_NAME)/Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = "$(TARGET_NAME)/Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,7"; + TARGETED_DEVICE_FAMILY = "1,2,6,7"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 90BD9B672C06907D000DEBAB /* Build configuration list for PBXProject "__PROJECT_NAME__" */ = { + 90BD9B672C06907D000DEBAB /* Build configuration list for PBXProject "App" */ = { isa = XCConfigurationList; buildConfigurations = ( 90BD9B832C06907E000DEBAB /* Debug */, @@ -530,7 +495,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 90BD9B852C06907E000DEBAB /* Build configuration list for PBXNativeTarget "__PROJECT_NAME__" */ = { + 90BD9B852C06907E000DEBAB /* Build configuration list for PBXNativeTarget "App" */ = { isa = XCConfigurationList; buildConfigurations = ( 90BD9B862C06907E000DEBAB /* Debug */, @@ -540,6 +505,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 90A914572CA3D370003DB979 /* XCLocalSwiftPackageReference "../../../cordova-ios" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "../../../cordova-ios"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 90A914582CA3D370003DB979 /* CordovaLib */ = { + isa = XCSwiftPackageProductDependency; + productName = CordovaLib; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 90BD9B642C06907D000DEBAB /* Project object */; } diff --git a/templates/project/__PROJECT_NAME__.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/templates/project/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from templates/project/__PROJECT_NAME__.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to templates/project/App.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/templates/project/__PROJECT_NAME__.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/templates/project/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from templates/project/__PROJECT_NAME__.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to templates/project/App.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/templates/project/__PROJECT_NAME__.xcworkspace/contents.xcworkspacedata b/templates/project/App.xcworkspace/contents.xcworkspacedata similarity index 94% rename from templates/project/__PROJECT_NAME__.xcworkspace/contents.xcworkspacedata rename to templates/project/App.xcworkspace/contents.xcworkspacedata index 48a0b2724c..4bae5d8d7f 100644 --- a/templates/project/__PROJECT_NAME__.xcworkspace/contents.xcworkspacedata +++ b/templates/project/App.xcworkspace/contents.xcworkspacedata @@ -20,6 +20,6 @@ + location = "group:App.xcodeproj"> diff --git a/templates/project/__PROJECT_NAME__.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/templates/project/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from templates/project/__PROJECT_NAME__.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to templates/project/App.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/templates/project/__PROJECT_NAME__.xcworkspace/xcshareddata/xcschemes/__PROJECT_NAME__.xcscheme b/templates/project/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme similarity index 83% rename from templates/project/__PROJECT_NAME__.xcworkspace/xcshareddata/xcschemes/__PROJECT_NAME__.xcscheme rename to templates/project/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme index 4d1f67299c..2df61af28e 100644 --- a/templates/project/__PROJECT_NAME__.xcworkspace/xcshareddata/xcschemes/__PROJECT_NAME__.xcscheme +++ b/templates/project/App.xcworkspace/xcshareddata/xcschemes/App.xcscheme @@ -33,9 +33,9 @@ + BuildableName = "App.app" + BlueprintName = "App" + ReferencedContainer = "container:App.xcodeproj"> @@ -51,9 +51,9 @@ + BuildableName = "App.app" + BlueprintName = "App" + ReferencedContainer = "container:App.xcodeproj"> @@ -74,9 +74,9 @@ + BuildableName = "App.app" + BlueprintName = "App" + ReferencedContainer = "container:App.xcodeproj"> @@ -93,9 +93,9 @@ + BuildableName = "App.app" + BlueprintName = "App" + ReferencedContainer = "container:App.xcodeproj"> diff --git a/templates/project/__PROJECT_NAME__/__PROJECT_NAME__-Info.plist b/templates/project/App/App-Info.plist similarity index 58% rename from templates/project/__PROJECT_NAME__/__PROJECT_NAME__-Info.plist rename to templates/project/App/App-Info.plist index 02e5742002..96685af8be 100644 --- a/templates/project/__PROJECT_NAME__/__PROJECT_NAME__-Info.plist +++ b/templates/project/App/App-Info.plist @@ -20,49 +20,6 @@ - CFBundleDevelopmentRegion - en_US - CFBundleDisplayName - $(PRODUCT_NAME) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UIApplicationSupportsIndirectInputEvents - - UIMainStoryboardFile - Main - UILaunchStoryboardName - CDVLaunchScreen - UIRequiresFullScreen - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeRight - UTImportedTypeDeclarations diff --git a/templates/project/__PROJECT_NAME__/AppDelegate.h b/templates/project/App/AppDelegate.h similarity index 96% rename from templates/project/__PROJECT_NAME__/AppDelegate.h rename to templates/project/App/AppDelegate.h index 26c1f333ac..99e6a3e5ec 100644 --- a/templates/project/__PROJECT_NAME__/AppDelegate.h +++ b/templates/project/App/AppDelegate.h @@ -25,4 +25,4 @@ @class AppDelegate; -#import "__PROJECT_NAME__-Swift.h" +#import "App-Swift.h" diff --git a/templates/project/__PROJECT_NAME__/AppDelegate.swift b/templates/project/App/AppDelegate.swift similarity index 100% rename from templates/project/__PROJECT_NAME__/AppDelegate.swift rename to templates/project/App/AppDelegate.swift diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json b/templates/project/App/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/Contents.json rename to templates/project/App/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png b/templates/project/App/Assets.xcassets/AppIcon.appiconset/icon.png similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/AppIcon.appiconset/icon.png rename to templates/project/App/Assets.xcassets/AppIcon.appiconset/icon.png diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/BackgroundColor.colorset/Contents.json b/templates/project/App/Assets.xcassets/BackgroundColor.colorset/Contents.json similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/BackgroundColor.colorset/Contents.json rename to templates/project/App/Assets.xcassets/BackgroundColor.colorset/Contents.json diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/Contents.json b/templates/project/App/Assets.xcassets/Contents.json similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/Contents.json rename to templates/project/App/Assets.xcassets/Contents.json diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/LaunchStoryboard.imageset/Contents.json b/templates/project/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/LaunchStoryboard.imageset/Contents.json rename to templates/project/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json diff --git a/templates/project/__PROJECT_NAME__/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json b/templates/project/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json similarity index 100% rename from templates/project/__PROJECT_NAME__/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json rename to templates/project/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json diff --git a/templates/project/__PROJECT_NAME__/Base.lproj/CDVLaunchScreen.storyboard b/templates/project/App/Base.lproj/CDVLaunchScreen.storyboard similarity index 100% rename from templates/project/__PROJECT_NAME__/Base.lproj/CDVLaunchScreen.storyboard rename to templates/project/App/Base.lproj/CDVLaunchScreen.storyboard diff --git a/templates/project/__PROJECT_NAME__/Base.lproj/Main.storyboard b/templates/project/App/Base.lproj/Main.storyboard similarity index 100% rename from templates/project/__PROJECT_NAME__/Base.lproj/Main.storyboard rename to templates/project/App/Base.lproj/Main.storyboard diff --git a/templates/project/__PROJECT_NAME__/Bridging-Header.h b/templates/project/App/Bridging-Header.h similarity index 100% rename from templates/project/__PROJECT_NAME__/Bridging-Header.h rename to templates/project/App/Bridging-Header.h diff --git a/templates/project/__PROJECT_NAME__/Entitlements-Debug.plist b/templates/project/App/Entitlements-Debug.plist similarity index 100% rename from templates/project/__PROJECT_NAME__/Entitlements-Debug.plist rename to templates/project/App/Entitlements-Debug.plist diff --git a/templates/project/__PROJECT_NAME__/Entitlements-Release.plist b/templates/project/App/Entitlements-Release.plist similarity index 100% rename from templates/project/__PROJECT_NAME__/Entitlements-Release.plist rename to templates/project/App/Entitlements-Release.plist diff --git a/templates/project/__PROJECT_NAME__/MainViewController.h b/templates/project/App/MainViewController.h similarity index 96% rename from templates/project/__PROJECT_NAME__/MainViewController.h rename to templates/project/App/MainViewController.h index f684f12113..22c0cb26ce 100644 --- a/templates/project/__PROJECT_NAME__/MainViewController.h +++ b/templates/project/App/MainViewController.h @@ -25,4 +25,4 @@ @class MainViewController; -#import "__PROJECT_NAME__-Swift.h" +#import "App-Swift.h" diff --git a/templates/project/__PROJECT_NAME__/Plugins/README b/templates/project/App/Plugins/README similarity index 100% rename from templates/project/__PROJECT_NAME__/Plugins/README rename to templates/project/App/Plugins/README diff --git a/templates/project/__PROJECT_NAME__/PrivacyInfo.xcprivacy b/templates/project/App/PrivacyInfo.xcprivacy similarity index 100% rename from templates/project/__PROJECT_NAME__/PrivacyInfo.xcprivacy rename to templates/project/App/PrivacyInfo.xcprivacy diff --git a/templates/project/__PROJECT_NAME__/Resources/README b/templates/project/App/Resources/README similarity index 100% rename from templates/project/__PROJECT_NAME__/Resources/README rename to templates/project/App/Resources/README diff --git a/templates/project/__PROJECT_NAME__/SceneDelegate.swift b/templates/project/App/SceneDelegate.swift similarity index 100% rename from templates/project/__PROJECT_NAME__/SceneDelegate.swift rename to templates/project/App/SceneDelegate.swift diff --git a/templates/project/__PROJECT_NAME__/ViewController.swift b/templates/project/App/ViewController.swift similarity index 100% rename from templates/project/__PROJECT_NAME__/ViewController.swift rename to templates/project/App/ViewController.swift diff --git a/templates/project/__PROJECT_NAME__/config.xml b/templates/project/App/config.xml similarity index 100% rename from templates/project/__PROJECT_NAME__/config.xml rename to templates/project/App/config.xml diff --git a/templates/project/__PROJECT_NAME__/gitignore b/templates/project/App/gitignore similarity index 100% rename from templates/project/__PROJECT_NAME__/gitignore rename to templates/project/App/gitignore diff --git a/tests/CordovaLibTests/CordovaLibApp/Bridging-Header.h b/tests/CordovaLibTests/CordovaLibApp/Bridging-Header.h index bd4f30b78b..82c5749c01 100644 --- a/tests/CordovaLibTests/CordovaLibApp/Bridging-Header.h +++ b/tests/CordovaLibTests/CordovaLibApp/Bridging-Header.h @@ -6,7 +6,9 @@ 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 @@ -14,15 +16,6 @@ specific language governing permissions and limitations under the License. */ -// -// Bridging-Header.h -// __PROJECT_NAME__ -// -// Created by ___FULLUSERNAME___ on ___DATE___. -// Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved. -// -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// #import + diff --git a/tests/spec/createAndBuild.spec.js b/tests/spec/createAndBuild.spec.js index 1d858d245a..2f6fe51729 100644 --- a/tests/spec/createAndBuild.spec.js +++ b/tests/spec/createAndBuild.spec.js @@ -36,10 +36,9 @@ const makeTempDir = () => path.join( * @param {String} projectName */ function verifyProjectFiles (tmpDir, projectName) { - expect(fs.existsSync(path.join(tmpDir, projectName))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, `${projectName}.xcodeproj`))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, `${projectName}.xcworkspace`))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, 'CordovaLib'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App.xcodeproj'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App.xcworkspace'))).toBe(true); } /** @@ -50,11 +49,15 @@ function verifyProjectFiles (tmpDir, projectName) { * @param {String} expectedBundleIdentifier */ function verifyProjectBundleIdentifier (tmpDir, projectName, expectedBundleIdentifier) { - const pbxproj = path.join(tmpDir, `${projectName}.xcodeproj`, 'project.pbxproj'); + const pbxproj = path.join(tmpDir, 'App.xcodeproj', 'project.pbxproj'); const xcodeproj = xcode.project(pbxproj); xcodeproj.parseSync(); - const actualBundleIdentifier = xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER'); + + const actualBundleIdentifier = xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'App'); expect(actualBundleIdentifier).toBe(`"${expectedBundleIdentifier}"`); + + const actualBundleName = xcodeproj.getBuildProperty('PRODUCT_NAME', undefined, 'App'); + expect(actualBundleName).toBe(`"${projectName}"`); } /** @@ -74,7 +77,7 @@ function verifyBuild (tmpDir) { const Api = require(path.join(tmpDir, 'cordova', 'Api.js')); - return expectAsync(new Api('ios', tmpDir).build({ emulator: true })) + return expectAsync(new Api('ios', tmpDir).build({ emulator: true, buildFlag: ['-quiet'] })) .toBeResolved(); } @@ -93,26 +96,28 @@ async function verifyCreateAndBuild (tmpDir, packageName, projectName) { .then(() => verifyBuild(tmpDir)); } -describe('create', () => { - let tmpDir; +if (process.platform === 'darwin') { + describe('create', () => { + let tmpDir; - beforeEach(function () { - tmpDir = makeTempDir(); - }); + beforeEach(function () { + tmpDir = makeTempDir(); + }); - afterEach(() => { - fs.rmSync(tmpDir, { recursive: true, force: true }); - }); + afterEach(() => { + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); - it('Test#001 : create project with ascii name, no spaces', () => { - const packageName = 'com.test.app1'; - const projectName = 'testcreate'; - return verifyCreateAndBuild(tmpDir, packageName, projectName); - }, 10 * 60 * 1000); // first build takes longer (probably cold caches) - - it('Test#002 : create project with complicated name', () => { - const packageName = 'com.test.app2'; - const projectName = '応応応応 hello & إثرا 用用用用'; - return verifyCreateAndBuild(tmpDir, packageName, projectName); - }, 5 * 60 * 1000); -}); + it('Test#001 : create project with ascii name, no spaces', () => { + const packageName = 'com.test.app1'; + const projectName = 'testcreate'; + return verifyCreateAndBuild(tmpDir, packageName, projectName); + }, 10 * 60 * 1000); // first build takes longer (probably cold caches) + + it('Test#002 : create project with complicated name', () => { + const packageName = 'com.test.app2'; + const projectName = '応応応応 hello & إثرا 用用用用'; + return verifyCreateAndBuild(tmpDir, packageName, projectName); + }, 5 * 60 * 1000); + }); +} diff --git a/tests/spec/unit/Api.spec.js b/tests/spec/unit/Api.spec.js index fe8b7a4306..ac63858479 100644 --- a/tests/spec/unit/Api.spec.js +++ b/tests/spec/unit/Api.spec.js @@ -56,10 +56,10 @@ describe('Platform Api', () => { expect(() => { const p = new Api('ios', iosProjectFixture, new EventEmitter()); expect(p.locations.root).toEqual(iosProjectFixture); - expect(p.locations.pbxproj).toEqual(path.join(iosProjectFixture, 'SampleApp.xcodeproj', 'project.pbxproj')); - expect(p.locations.xcodeProjDir).toEqual(path.join(iosProjectFixture, 'SampleApp.xcodeproj')); + expect(p.locations.pbxproj).toEqual(path.join(iosProjectFixture, 'App.xcodeproj', 'project.pbxproj')); + expect(p.locations.xcodeProjDir).toEqual(path.join(iosProjectFixture, 'App.xcodeproj')); expect(p.locations.www).toEqual(path.join(iosProjectFixture, 'www')); - expect(p.locations.configXml).toEqual(path.join(iosProjectFixture, 'SampleApp', 'config.xml')); + expect(p.locations.configXml).toEqual(path.join(iosProjectFixture, 'App', 'config.xml')); }).not.toThrow(); }); }); diff --git a/tests/spec/unit/Plugman/pluginHandler.spec.js b/tests/spec/unit/Plugman/pluginHandler.spec.js index ca4853083f..9091fb7ac0 100644 --- a/tests/spec/unit/Plugman/pluginHandler.spec.js +++ b/tests/spec/unit/Plugman/pluginHandler.spec.js @@ -76,7 +76,7 @@ describe('ios plugin handler', () => { dummyProject = projectFile.parse({ root: temp, - pbxproj: path.join(temp, 'SampleApp.xcodeproj', 'project.pbxproj') + pbxproj: path.join(temp, 'App.xcodeproj', 'project.pbxproj') }); }); @@ -100,7 +100,7 @@ describe('ios plugin handler', () => { }); it('Test 002 : should throw if source-file target already exists', () => { const source = copyArray(valid_source); - const target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'); + const target = path.join(temp, 'App', 'Plugins', dummy_id, 'DummyPluginCommand.m'); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, 'some bs', 'utf-8'); expect(() => { @@ -123,20 +123,20 @@ describe('ios plugin handler', () => { const source = copyArray(valid_source).filter(s => s.targetDir === undefined); spyOn(fs, 'cpSync'); install(source[0], dummyPluginInfo, dummyProject); - expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.m'), { recursive: true }); + expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.m'), path.join(temp, 'App', 'Plugins', dummy_id, 'DummyPluginCommand.m'), { recursive: true }); }); it('Test 006 : should cp the file to the right target location when element has a target-dir', () => { const source = copyArray(valid_source).filter(s => s.targetDir !== undefined); spyOn(fs, 'cpSync'); install(source[0], dummyPluginInfo, dummyProject); - expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), { recursive: true }); + expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.m'), path.join(temp, 'App', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.m'), { recursive: true }); }); it('Test 007 : should call into xcodeproj\'s addFramework appropriately when element has framework=true set', () => { const source = copyArray(valid_source).filter(s => s.framework); spyOn(dummyProject.xcode, 'addFramework'); install(source[0], dummyPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m'), { weak: false }); + .toHaveBeenCalledWith(path.join('App', 'Plugins', dummy_id, 'SourceWithFramework.m'), { weak: false }); }); }); @@ -155,7 +155,7 @@ describe('ios plugin handler', () => { }); it('Test 009 : should throw if header-file target already exists', () => { const headers = copyArray(valid_headers); - const target = path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'); + const target = path.join(temp, 'App', 'Plugins', dummy_id, 'DummyPluginCommand.h'); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, 'some bs', 'utf-8'); expect(() => { @@ -178,13 +178,13 @@ describe('ios plugin handler', () => { const headers = copyArray(valid_headers).filter(s => s.targetDir === undefined); spyOn(fs, 'cpSync'); install(headers[0], dummyPluginInfo, dummyProject); - expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'DummyPluginCommand.h'), { recursive: true }); + expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPluginCommand.h'), path.join(temp, 'App', 'Plugins', dummy_id, 'DummyPluginCommand.h'), { recursive: true }); }); it('Test 013 : should cp the file to the right target location when element has a target-dir', () => { const headers = copyArray(valid_headers).filter(s => s.targetDir !== undefined); spyOn(fs, 'cpSync'); install(headers[0], dummyPluginInfo, dummyProject); - expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'), { recursive: true }); + expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'TargetDirTest.h'), path.join(temp, 'App', 'Plugins', dummy_id, 'targetDir', 'TargetDirTest.h'), { recursive: true }); }); }); @@ -203,7 +203,7 @@ describe('ios plugin handler', () => { }); it('Test 015 : should throw if resource-file target already exists', () => { const resources = copyArray(valid_resources); - const target = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'); + const target = path.join(temp, 'App', 'Resources', 'DummyPlugin.bundle'); fs.mkdirSync(path.dirname(target), { recursive: true }); fs.writeFileSync(target, 'some bs', 'utf-8'); expect(() => { @@ -220,7 +220,7 @@ describe('ios plugin handler', () => { const resources = copyArray(valid_resources); spyOn(fs, 'cpSync'); install(resources[0], dummyPluginInfo, dummyProject); - expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'), { recursive: true }); + expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'), path.join(temp, 'App', 'Resources', 'DummyPlugin.bundle'), { recursive: true }); }); it('Test 018 : should link files to the right target location', () => { @@ -228,7 +228,7 @@ describe('ios plugin handler', () => { const spy = spyOn(fs, 'linkSync'); install(resources[0], dummyPluginInfo, dummyProject, { link: true }); const src_bundle = path.join(dummyplugin, 'src', 'ios', 'DummyPlugin.bundle'); - const dest_bundle = path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'); + const dest_bundle = path.join(temp, 'App', 'Resources', 'DummyPlugin.bundle'); expect(spy).toHaveBeenCalledWith(src_bundle, dest_bundle); }); }); @@ -243,12 +243,12 @@ describe('ios plugin handler', () => { let frameworks = copyArray(valid_custom_frameworks); install(frameworks[0], dummyPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework', { customFramework: true, embed: false, link: true, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.dummyplugin/Custom.framework', { customFramework: true, embed: false, link: true, sign: true }); frameworks = copyArray(valid_embeddable_custom_frameworks); install(frameworks[0], dummyPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.dummyplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.dummyplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); frameworks = copyArray(valid_weak_frameworks); install(frameworks[0], dummyPluginInfo, dummyProject); @@ -269,7 +269,7 @@ describe('ios plugin handler', () => { }); it('Test 021 : should throw if framework target already exists', () => { const frameworks = copyArray(valid_custom_frameworks); - const target = path.join(temp, 'SampleApp', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'); + const target = path.join(temp, 'App', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'); fs.mkdirSync(target, { recursive: true }); expect(() => { install(frameworks[0], dummyPluginInfo, dummyProject); @@ -280,7 +280,7 @@ describe('ios plugin handler', () => { spyOn(fs, 'cpSync'); install(frameworks[0], dummyPluginInfo, dummyProject); expect(fs.cpSync).toHaveBeenCalledWith(path.join(dummyplugin, 'src', 'ios', 'Custom.framework'), - path.join(temp, 'SampleApp', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'), { recursive: true }); + path.join(temp, 'App', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'), { recursive: true }); }); it('Test 023 : should deep symlink files to the right target location', () => { @@ -288,7 +288,7 @@ describe('ios plugin handler', () => { const spy = spyOn(fs, 'linkSync'); install(frameworks[0], dummyPluginInfo, dummyProject, { link: true }); const src_binlib = path.join(dummyplugin, 'src', 'ios', 'Custom.framework', 'somebinlib'); - const dest_binlib = path.join(temp, 'SampleApp', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework', 'somebinlib'); + const dest_binlib = path.join(temp, 'App', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework', 'somebinlib'); expect(spy).toHaveBeenCalledWith(src_binlib, dest_binlib); }); }); @@ -299,43 +299,43 @@ describe('ios plugin handler', () => { it('Test 046 : embed true, link true', () => { install(frameworks[0], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: true, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: true, sign: true }); }); it('Test 047 : embed true, link false', () => { install(frameworks[1], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); }); it('Test 048 : embed false, link true', () => { install(frameworks[2], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); }); it('Test 049 : embed false, link false', () => { install(frameworks[3], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: false, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: false, sign: true }); }); it('Test 050 : embed undefined, link undefined', () => { install(frameworks[4], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); }); it('Test 051 : embed true, link undefined', () => { install(frameworks[5], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: true, link: false, sign: true }); }); it('Test 052 : embed false, link undefined', () => { install(frameworks[6], embedlinkPluginInfo, dummyProject); expect(dummyProject.xcode.addFramework) - .toHaveBeenCalledWith('SampleApp/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); + .toHaveBeenCalledWith('App/Plugins/org.test.plugins.embedlinkplugin/CustomEmbeddable.framework', { customFramework: true, embed: false, link: true, sign: true }); }); }); }); @@ -400,7 +400,7 @@ describe('ios plugin handler', () => { .then(() => { const xcode = projectFile.parse({ root: temp, - pbxproj: path.join(temp, 'SampleApp.xcodeproj', 'project.pbxproj') + pbxproj: path.join(temp, 'App.xcodeproj', 'project.pbxproj') }).xcode; // from org.test.plugins.dummyplugin @@ -410,7 +410,7 @@ describe('ios plugin handler', () => { expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 'targetDir', 'TargetDirTest.h'))).toEqual(jasmine.any(Object)); expect(xcode.hasFile(slashJoin('org.test.plugins.dummyplugin', 'targetDir', 'TargetDirTest.m'))).toEqual(jasmine.any(Object)); expect(xcode.hasFile('usr/lib/libsqlite3.dylib')).toEqual(jasmine.any(Object)); - expect(xcode.hasFile(slashJoin('SampleApp', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'))).toEqual(jasmine.any(Object)); + expect(xcode.hasFile(slashJoin('App', 'Plugins', 'org.test.plugins.dummyplugin', 'Custom.framework'))).toEqual(jasmine.any(Object)); // from org.test.plugins.weblessplugin expect(xcode.hasFile(slashJoin('WeblessPluginViewController.xib'))).toEqual(jasmine.any(Object)); expect(xcode.hasFile(slashJoin('org.test.plugins.weblessplugin', 'WeblessPluginCommand.h'))).toEqual(jasmine.any(Object)); @@ -442,18 +442,18 @@ describe('ios plugin handler', () => { const source = copyArray(valid_source).filter(s => s.targetDir === undefined); const spy = spyOn(fs, 'rmSync'); uninstall(source[0], dummyPluginInfo, dummyProject); - expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'Plugins', dummy_id), { recursive: true, force: true }); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'App', 'Plugins', dummy_id), { recursive: true, force: true }); }); it('Test 032 : should rm the file from the right target location when element has a target-dir', () => { const source = copyArray(valid_source).filter(s => s.targetDir !== undefined); const spy = spyOn(fs, 'rmSync'); uninstall(source[0], dummyPluginInfo, dummyProject); - expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true }); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'App', 'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true }); }); it('Test 033 : should call into xcodeproj\'s removeFramework appropriately when element framework=true set', () => { const source = copyArray(valid_source).filter(s => s.framework); uninstall(source[0], dummyPluginInfo, dummyProject); - expect(dummyProject.xcode.removeFramework).toHaveBeenCalledWith(path.join('SampleApp', 'Plugins', dummy_id, 'SourceWithFramework.m')); + expect(dummyProject.xcode.removeFramework).toHaveBeenCalledWith(path.join('App', 'Plugins', dummy_id, 'SourceWithFramework.m')); }); }); @@ -477,7 +477,7 @@ describe('ios plugin handler', () => { const headers = copyArray(valid_headers).filter(s => s.targetDir !== undefined); const spy = spyOn(fs, 'rmSync'); uninstall(headers[0], dummyPluginInfo, dummyProject); - expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true }); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'App', 'Plugins', dummy_id, 'targetDir'), { recursive: true, force: true }); }); }); @@ -496,7 +496,7 @@ describe('ios plugin handler', () => { const resources = copyArray(valid_resources); const spy = spyOn(fs, 'rmSync'); uninstall(resources[0], dummyPluginInfo, dummyProject); - expect(spy).toHaveBeenCalledWith(path.join(temp, 'SampleApp', 'Resources', 'DummyPlugin.bundle'), { recursive: true, force: true }); + expect(spy).toHaveBeenCalledWith(path.join(temp, 'App', 'Resources', 'DummyPlugin.bundle'), { recursive: true, force: true }); }); }); @@ -506,7 +506,7 @@ describe('ios plugin handler', () => { spyOn(dummyProject.xcode, 'removeFramework'); }); - const frameworkPath = path.join(temp, 'SampleApp/Plugins/org.test.plugins.dummyplugin/Custom.framework').replace(/\\/g, '/'); + const frameworkPath = path.join(temp, 'App/Plugins/org.test.plugins.dummyplugin/Custom.framework').replace(/\\/g, '/'); it('Test 039 : should call into xcodeproj\'s removeFramework', () => { const frameworks = copyArray(valid_custom_frameworks); diff --git a/tests/spec/unit/Podfile.spec.js b/tests/spec/unit/Podfile.spec.js index 27a0531611..98a9a23c99 100644 --- a/tests/spec/unit/Podfile.spec.js +++ b/tests/spec/unit/Podfile.spec.js @@ -40,12 +40,6 @@ describe('unit tests for Podfile module', () => { }).toThrow(new CordovaError(util.format('Podfile: The file at %s is not `%s`.', dummyPath, Podfile.FILENAME))); }); - it('Test 002 : throws CordovaError when no projectName provided when creating a Podfile', () => { - expect(() => { - new Podfile(fixturePodfile); /* eslint no-new : 0 */ - }).toThrow(new CordovaError('Podfile: The projectName was not specified in the constructor.')); - }); - it('Test 003 : throws CordovaError when no pod name provided when adding a spec', () => { expect(() => { podfile.addSpec(null); @@ -129,10 +123,10 @@ describe('unit tests for Podfile module', () => { // Template tokens in order: project name, project name, debug | release const template = '// DO NOT MODIFY -- auto-generated by Apache Cordova\n' + - '#include "Pods/Target Support Files/Pods-%s/Pods-%s.%s.xcconfig"'; + '#include "Pods/Target Support Files/Pods-App/Pods-App.%s.xcconfig"'; - const expectedDebugContents = util.format(template, PROJECT_NAME, PROJECT_NAME, 'debug'); - const expectedReleaseContents = util.format(template, PROJECT_NAME, PROJECT_NAME, 'release'); + const expectedDebugContents = util.format(template, 'debug'); + const expectedReleaseContents = util.format(template, 'release'); const actualDebugContents = fs.readFileSync(fixturePodXcconfigDebug, 'utf8'); const actualReleaseContents = fs.readFileSync(fixturePodXcconfigRelease, 'utf8'); diff --git a/tests/spec/unit/build.spec.js b/tests/spec/unit/build.spec.js index c683d9eb0a..25dbbccf7d 100644 --- a/tests/spec/unit/build.spec.js +++ b/tests/spec/unit/build.spec.js @@ -20,7 +20,7 @@ const fs = require('node:fs'); const path = require('node:path'); const rewire = require('rewire'); -const { CordovaError, events } = require('cordova-common'); +const { CordovaError } = require('cordova-common'); const build = rewire('../../../lib/build'); describe('build', () => { @@ -31,18 +31,18 @@ describe('build', () => { build.__set__('__dirname', path.join('/test', 'dir')); it('should generate appropriate args if a single buildFlag is passed in', () => { - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: '' }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: '' }); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-destination', 'generic/platform=iOS', '-archivePath', - 'TestProjectName.xcarchive', + 'App.xcarchive', 'archive' ]); expect(args.length).toEqual(11); @@ -59,7 +59,7 @@ describe('build', () => { 'SHARED_PRECOMPS_DIR=TestSharedPrecompsDirFlag' ]; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: buildFlags }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: buildFlags }); expect(args).toEqual([ '-workspace', 'TestWorkspaceFlag', @@ -79,30 +79,30 @@ describe('build', () => { }); it('should generate appropriate args for device', () => { - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', { device: true }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', { device: true }); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-destination', 'generic/platform=iOS', '-archivePath', - 'TestProjectName.xcarchive', + 'App.xcarchive', 'archive' ]); expect(args.length).toEqual(11); }); it('should generate appropriate args for simulator', () => { - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false }); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-sdk', @@ -126,7 +126,7 @@ describe('build', () => { 'SHARED_PRECOMPS_DIR=TestSharedPrecompsDirFlag' ]; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false, buildFlag: buildFlags }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false, buildFlag: buildFlags }); expect(args).toEqual([ '-workspace', 'TestWorkspaceFlag', @@ -151,18 +151,18 @@ describe('build', () => { it('should add matched flags that are not overriding for device', () => { const buildFlags = '-sdk TestSdkFlag'; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: buildFlags }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', { device: true, buildFlag: buildFlags }); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-destination', 'generic/platform=iOS', '-archivePath', - 'TestProjectName.xcarchive', + 'App.xcarchive', 'archive', '-sdk', 'TestSdkFlag' @@ -173,12 +173,12 @@ describe('build', () => { it('should add matched flags that are not overriding for simulator', () => { const buildFlags = '-archivePath TestArchivePathFlag'; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false, buildFlag: buildFlags }); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', 'iPhone 5s', { device: false, buildFlag: buildFlags }); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-sdk', @@ -202,18 +202,18 @@ describe('build', () => { authenticationKeyIssuerID: '00000000-0000-0000-0000-000000000000' }; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', buildOpts); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', buildOpts); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-destination', 'generic/platform=iOS', '-archivePath', - 'TestProjectName.xcarchive', + 'App.xcarchive', '-allowProvisioningUpdates', '-authenticationKeyPath', '/tmp/asc-key.p8', @@ -231,12 +231,12 @@ describe('build', () => { catalyst: true }; - const args = getXcodeBuildArgs('TestProjectName', testProjectPath, 'TestConfiguration', '', buildOpts); + const args = getXcodeBuildArgs(testProjectPath, 'TestConfiguration', '', buildOpts); expect(args).toEqual([ '-workspace', - 'TestProjectName.xcworkspace', + 'App.xcworkspace', '-scheme', - 'TestProjectName', + 'App', '-configuration', 'TestConfiguration', '-destination', @@ -252,10 +252,10 @@ describe('build', () => { const getXcodeArchiveArgs = build.__get__('getXcodeArchiveArgs'); it('should generate the appropriate arguments', () => { - const archiveArgs = getXcodeArchiveArgs('TestProjectName', testProjectPath, '/test/output/path', '/test/export/options/path'); + const archiveArgs = getXcodeArchiveArgs(testProjectPath, '/test/output/path', '/test/export/options/path'); expect(archiveArgs[0]).toEqual('-exportArchive'); expect(archiveArgs[1]).toEqual('-archivePath'); - expect(archiveArgs[2]).toEqual('TestProjectName.xcarchive'); + expect(archiveArgs[2]).toEqual('App.xcarchive'); expect(archiveArgs[3]).toEqual('-exportOptionsPlist'); expect(archiveArgs[4]).toEqual('/test/export/options/path'); expect(archiveArgs[5]).toEqual('-exportPath'); @@ -271,10 +271,10 @@ describe('build', () => { authenticationKeyIssuerID: '00000000-0000-0000-0000-000000000000' }; - const archiveArgs = getXcodeArchiveArgs('TestProjectName', testProjectPath, '/test/output/path', '/test/export/options/path', buildOpts); + const archiveArgs = getXcodeArchiveArgs(testProjectPath, '/test/output/path', '/test/export/options/path', buildOpts); expect(archiveArgs[0]).toEqual('-exportArchive'); expect(archiveArgs[1]).toEqual('-archivePath'); - expect(archiveArgs[2]).toEqual('TestProjectName.xcarchive'); + expect(archiveArgs[2]).toEqual('App.xcarchive'); expect(archiveArgs[3]).toEqual('-exportOptionsPlist'); expect(archiveArgs[4]).toEqual('/test/export/options/path'); expect(archiveArgs[5]).toEqual('-exportPath'); @@ -288,6 +288,35 @@ describe('build', () => { expect(archiveArgs[13]).toEqual('00000000-0000-0000-0000-000000000000'); expect(archiveArgs.length).toEqual(14); }); + + it('should generate the appropriate arguments with build flag overrides', () => { + const buildFlags = '-archivePath TestArchivePathFlag'; + + const archiveArgs = getXcodeArchiveArgs(testProjectPath, '/test/output/path', '/test/export/options/path', { buildFlag: buildFlags }); + expect(archiveArgs[0]).toEqual('-exportArchive'); + expect(archiveArgs[1]).toEqual('-archivePath'); + expect(archiveArgs[2]).toEqual('TestArchivePathFlag'); + expect(archiveArgs[3]).toEqual('-exportOptionsPlist'); + expect(archiveArgs[4]).toEqual('/test/export/options/path'); + expect(archiveArgs[5]).toEqual('-exportPath'); + expect(archiveArgs[6]).toEqual('/test/output/path'); + expect(archiveArgs.length).toEqual(7); + }); + + it('should generate the appropriate arguments with build flag overrides', () => { + const buildFlags = ['-archivePath TestArchivePathFlag', '-quiet']; + + const archiveArgs = getXcodeArchiveArgs(testProjectPath, '/test/output/path', '/test/export/options/path', { buildFlag: buildFlags }); + expect(archiveArgs[0]).toEqual('-exportArchive'); + expect(archiveArgs[1]).toEqual('-archivePath'); + expect(archiveArgs[2]).toEqual('TestArchivePathFlag'); + expect(archiveArgs[3]).toEqual('-exportOptionsPlist'); + expect(archiveArgs[4]).toEqual('/test/export/options/path'); + expect(archiveArgs[5]).toEqual('-exportPath'); + expect(archiveArgs[6]).toEqual('/test/output/path'); + expect(archiveArgs[7]).toEqual('-quiet'); + expect(archiveArgs.length).toEqual(8); + }); }); describe('parseBuildFlag method', () => { @@ -442,45 +471,4 @@ describe('build', () => { }); }); }); - - describe('findXCodeProjectIn method', () => { - const fakePath = '/path/foobar'; - let buildRequire; - - beforeEach(() => { - // rewire causes some issues so for these tests, we will require instead. - buildRequire = require('../../../lib/build'); - spyOn(events, 'emit'); - }); - - it('should find not find Xcode project', () => { - spyOn(fs, 'readdirSync').and.returnValue(['README.md']); - return buildRequire.findXCodeProjectIn(fakePath).then( - () => {}, - (error) => { - expect(error.message).toBe(`No Xcode project found in ${fakePath}`); - } - ); - }); - - it('should emit finding multiple Xcode projects', () => { - spyOn(fs, 'readdirSync').and.returnValue(['Test1.xcodeproj', 'Test2.xcodeproj']); - return buildRequire.findXCodeProjectIn(fakePath).then( - (projectName) => { - expect(events.emit).toHaveBeenCalledWith(jasmine.any(String), jasmine.stringMatching(/Found multiple .xcodeproj directories in/)); - expect(projectName).toBe('Test1'); - } - ); - }); - - it('should detect and return only one projects', () => { - spyOn(fs, 'readdirSync').and.returnValue(['Test1.xcodeproj']); - return buildRequire.findXCodeProjectIn(fakePath).then( - (projectName) => { - expect(events.emit).not.toHaveBeenCalled(); - expect(projectName).toBe('Test1'); - } - ); - }); - }); }); diff --git a/tests/spec/unit/create.spec.js b/tests/spec/unit/create.spec.js index 1b3bf17018..f07c4bbe57 100644 --- a/tests/spec/unit/create.spec.js +++ b/tests/spec/unit/create.spec.js @@ -36,17 +36,31 @@ const makeTempDir = () => path.join( * @param {String} projectName */ function verifyProjectFiles (tmpDir, projectName) { - expect(fs.existsSync(path.join(tmpDir, projectName))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, `${projectName}.xcodeproj`))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, `${projectName}.xcworkspace`))).toBe(true); - expect(fs.existsSync(path.join(tmpDir, 'CordovaLib'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App.xcodeproj'))).toBe(true); + expect(fs.existsSync(path.join(tmpDir, 'App.xcworkspace'))).toBe(true); - const pbxproj = path.join(tmpDir, `${projectName}.xcodeproj`, 'project.pbxproj'); - const pbxcontents = fs.readFileSync(pbxproj, 'utf-8'); - const regex = /(.+CordovaLib.xcodeproj.+PBXFileReference.+wrapper.pb-project.+)(path = .+?;)(.*)(sourceTree.+;)(.+)/; - const line = pbxcontents.split(/\r?\n/).find(l => regex.test(l)); + const pbxproj = path.join(tmpDir, 'App.xcodeproj', 'project.pbxproj'); + const xcodeproj = xcode.project(pbxproj); + xcodeproj.parseSync(); + + const packageLoc = path.dirname(require.resolve('../../../package.json')); + const relativePath = path.relative(tmpDir, packageLoc).replaceAll(path.sep, path.posix.sep); - expect(line).toMatch(/path = CordovaLib\/CordovaLib.xcodeproj;/); + let foundRef = false; + const pkgRefs = xcodeproj.hash.project.objects.XCLocalSwiftPackageReference; + for (const [key, ref] of Object.entries(pkgRefs)) { + if (key.endsWith('_COMMENT')) { + continue; + } + + if (ref.relativePath.match(/\/cordova-ios/)) { + foundRef = true; + expect(ref.relativePath).toMatch(relativePath); + break; + } + } + expect(foundRef).toBeTruthy(); } /** @@ -57,11 +71,15 @@ function verifyProjectFiles (tmpDir, projectName) { * @param {String} expectedBundleIdentifier */ function verifyProjectBundleIdentifier (tmpDir, projectName, expectedBundleIdentifier) { - const pbxproj = path.join(tmpDir, `${projectName}.xcodeproj`, 'project.pbxproj'); + const pbxproj = path.join(tmpDir, 'App.xcodeproj', 'project.pbxproj'); const xcodeproj = xcode.project(pbxproj); xcodeproj.parseSync(); - const actualBundleIdentifier = xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER'); + + const actualBundleIdentifier = xcodeproj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'App'); expect(actualBundleIdentifier).toBe(`"${expectedBundleIdentifier}"`); + + const actualBundleName = xcodeproj.getBuildProperty('PRODUCT_NAME', undefined, 'App'); + expect(actualBundleName).toBe(`"${projectName}"`); } /** diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj b/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj similarity index 90% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj rename to tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj index 50c0f94795..c5be465dec 100755 --- a/tests/spec/unit/fixtures/ios-config-xml/SampleApp.xcodeproj/project.pbxproj +++ b/tests/spec/unit/fixtures/ios-config-xml/App.xcodeproj/project.pbxproj @@ -58,10 +58,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 0207DA571B56EA530066E2B4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = "SampleApp/Assets.xcassets"; sourceTree = SOURCE_ROOT; }; + 0207DA571B56EA530066E2B4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = "App/Assets.xcassets"; sourceTree = SOURCE_ROOT; }; 1D3623240D0F684500981E51 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - 1D6058910D05DD3D006BFB54 /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SampleApp.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1D6058910D05DD3D006BFB54 /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 301BF52D109A57CC0062928A /* CordovaLib/CordovaLib.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CordovaLib.xcodeproj; path = CordovaLib/CordovaLib.xcodeproj; sourceTree = ""; }; 301BF56E109A69640062928A /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; path = www; sourceTree = SOURCE_ROOT; }; @@ -71,13 +71,13 @@ 3047A50F1AB8059700498E2A /* build-debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "build-debug.xcconfig"; path = "cordova/build-debug.xcconfig"; sourceTree = SOURCE_ROOT; }; 3047A5101AB8059700498E2A /* build-release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = "build-release.xcconfig"; path = "cordova/build-release.xcconfig"; sourceTree = SOURCE_ROOT; }; 3047A5111AB8059700498E2A /* build.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = build.xcconfig; path = cordova/build.xcconfig; sourceTree = SOURCE_ROOT; }; - 32CA4F630368D1EE00C91783 /* SampleApp-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SampleApp-Prefix.pch"; sourceTree = ""; }; - 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = CDVLaunchScreen.storyboard; path = "SampleApp/CDVLaunchScreen.storyboard"; sourceTree = SOURCE_ROOT; }; - 8D1107310486CEB800E47090 /* SampleApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "SampleApp-Info.plist"; path = "SampleApp/SampleApp-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = SOURCE_ROOT; }; + 32CA4F630368D1EE00C91783 /* App-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "App-Prefix.pch"; sourceTree = ""; }; + 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = CDVLaunchScreen.storyboard; path = "App/CDVLaunchScreen.storyboard"; sourceTree = SOURCE_ROOT; }; + 8D1107310486CEB800E47090 /* App-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "App-Info.plist"; path = "App/App-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = SOURCE_ROOT; }; EB87FDF31871DA8E0020F90C /* www */ = {isa = PBXFileReference; lastKnownFileType = folder; name = www; path = ../../www; sourceTree = ""; }; EB87FDF41871DAF40020F90C /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = ../../config.xml; sourceTree = ""; }; ED33DF2A687741AEAF9F8254 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; - F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = "SampleApp/config.xml"; sourceTree = ""; }; + F840E1F0165FE0F500CFE078 /* config.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = config.xml; path = "App/config.xml"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -102,13 +102,13 @@ 1D3623250D0F684500981E51 /* AppDelegate.m */, ); name = Classes; - path = "SampleApp/Classes"; + path = "App/Classes"; sourceTree = SOURCE_ROOT; }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( - 1D6058910D05DD3D006BFB54 /* SampleApp.app */, + 1D6058910D05DD3D006BFB54 /* App.app */, ); name = Products; sourceTree = ""; @@ -133,12 +133,12 @@ 29B97315FDCFA39411CA2CEA /* Other Sources */ = { isa = PBXGroup; children = ( - 32CA4F630368D1EE00C91783 /* SampleApp-Prefix.pch */, + 32CA4F630368D1EE00C91783 /* App-Prefix.pch */, 29B97316FDCFA39411CA2CEA /* main.m */, ED33DF2A687741AEAF9F8254 /* Bridging-Header.h */, ); name = "Other Sources"; - path = "SampleApp"; + path = "App"; sourceTree = ""; }; 29B97317FDCFA39411CA2CEA /* Resources */ = { @@ -146,11 +146,11 @@ children = ( 0207DA571B56EA530066E2B4 /* Assets.xcassets */, 3047A50E1AB8057F00498E2A /* config */, - 8D1107310486CEB800E47090 /* SampleApp-Info.plist */, + 8D1107310486CEB800E47090 /* App-Info.plist */, 6AFF5BF81D6E424B00AB3073 /* CDVLaunchScreen.storyboard */, ); name = Resources; - path = "SampleApp/Resources"; + path = "App/Resources"; sourceTree = ""; }; 29B97323FDCFA39411CA2CEA /* Frameworks */ = { @@ -184,7 +184,7 @@ children = ( ); name = Plugins; - path = "SampleApp/Plugins"; + path = "App/Plugins"; sourceTree = SOURCE_ROOT; }; EB87FDF11871DA420020F90C /* Staging */ = { @@ -199,9 +199,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 1D6058900D05DD3D006BFB54 /* SampleApp */ = { + 1D6058900D05DD3D006BFB54 /* App */ = { isa = PBXNativeTarget; - buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "SampleApp" */; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "App" */; buildPhases = ( 857339E32710CC9700A1C74C /* Copy Staging Resources */, 1D60588D0D05DD3D006BFB54 /* Resources */, @@ -213,9 +213,9 @@ dependencies = ( 301BF551109A68C00062928A /* PBXTargetDependency */, ); - name = "SampleApp"; - productName = "SampleApp"; - productReference = 1D6058910D05DD3D006BFB54 /* SampleApp.app */; + name = "App"; + productName = "App"; + productReference = 1D6058910D05DD3D006BFB54 /* App.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -232,7 +232,7 @@ }; }; }; - buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SampleApp" */; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "App" */; compatibilityVersion = "Xcode 11.0"; developmentRegion = en; hasScannedForEncodings = 1; @@ -250,7 +250,7 @@ ); projectRoot = ""; targets = ( - 1D6058900D05DD3D006BFB54 /* SampleApp */, + 1D6058900D05DD3D006BFB54 /* App */, ); }; /* End PBXProject section */ @@ -320,10 +320,10 @@ GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch"; + GCC_PREFIX_HEADER = "App/App-Prefix.pch"; GCC_THUMB_SUPPORT = NO; GCC_VERSION = ""; - INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist"; + INFOPLIST_FILE = "App/App-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.example.friendstring; @@ -345,10 +345,10 @@ CLANG_ENABLE_OBJC_ARC = YES; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "SampleApp/SampleApp-Prefix.pch"; + GCC_PREFIX_HEADER = "App/App-Prefix.pch"; GCC_THUMB_SUPPORT = NO; GCC_VERSION = ""; - INFOPLIST_FILE = "SampleApp/SampleApp-Info.plist"; + INFOPLIST_FILE = "App/App-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.example.friendstring; @@ -454,7 +454,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "SampleApp" */ = { + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "App" */ = { isa = XCConfigurationList; buildConfigurations = ( 1D6058940D05DD3E006BFB54 /* Debug */, @@ -463,7 +463,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C01FCF4E08A954540054247B /* Build configuration list for PBXProject "SampleApp" */ = { + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "App" */ = { isa = XCConfigurationList; buildConfigurations = ( C01FCF4F08A954540054247B /* Debug */, diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/.gitignore b/tests/spec/unit/fixtures/ios-config-xml/App/.gitignore similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/.gitignore rename to tests/spec/unit/fixtures/ios-config-xml/App/.gitignore diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist b/tests/spec/unit/fixtures/ios-config-xml/App/App-Info.plist similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Info.plist rename to tests/spec/unit/fixtures/ios-config-xml/App/App-Info.plist 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/App/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/Contents.json rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/AppIcon.appiconset/Contents.json 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/App/Assets.xcassets/AppIcon.appiconset/icon.png similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/AppIcon.appiconset/icon.png rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/AppIcon.appiconset/icon.png diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/BackgroundColor.colorset/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/BackgroundColor.colorset/Contents.json similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/BackgroundColor.colorset/Contents.json rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/BackgroundColor.colorset/Contents.json diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/Contents.json similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/Contents.json rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/Contents.json diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/LaunchStoryboard.imageset/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/LaunchStoryboard.imageset/Contents.json rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/LaunchStoryboard.imageset/Contents.json diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json b/tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json rename to tests/spec/unit/fixtures/ios-config-xml/App/Assets.xcassets/SplashScreenBackgroundColor.colorset/Contents.json diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Bridging-Header.h b/tests/spec/unit/fixtures/ios-config-xml/App/Bridging-Header.h similarity index 74% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Bridging-Header.h rename to tests/spec/unit/fixtures/ios-config-xml/App/Bridging-Header.h index bd4f30b78b..82c5749c01 100644 --- a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Bridging-Header.h +++ b/tests/spec/unit/fixtures/ios-config-xml/App/Bridging-Header.h @@ -6,7 +6,9 @@ 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 @@ -14,15 +16,6 @@ specific language governing permissions and limitations under the License. */ -// -// Bridging-Header.h -// __PROJECT_NAME__ -// -// Created by ___FULLUSERNAME___ on ___DATE___. -// Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved. -// -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// #import + diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/CDVLaunchScreen.storyboard b/tests/spec/unit/fixtures/ios-config-xml/App/CDVLaunchScreen.storyboard similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/CDVLaunchScreen.storyboard rename to tests/spec/unit/fixtures/ios-config-xml/App/CDVLaunchScreen.storyboard diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/AppDelegate.h b/tests/spec/unit/fixtures/ios-config-xml/App/Classes/AppDelegate.h similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/AppDelegate.h rename to tests/spec/unit/fixtures/ios-config-xml/App/Classes/AppDelegate.h diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/AppDelegate.m b/tests/spec/unit/fixtures/ios-config-xml/App/Classes/AppDelegate.m similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/AppDelegate.m rename to tests/spec/unit/fixtures/ios-config-xml/App/Classes/AppDelegate.m diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.h b/tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.h similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.h rename to tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.h diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.m b/tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.m similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.m rename to tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.m diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.xib b/tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.xib similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Classes/MainViewController.xib rename to tests/spec/unit/fixtures/ios-config-xml/App/Classes/MainViewController.xib diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Entitlements-Debug.plist b/tests/spec/unit/fixtures/ios-config-xml/App/Entitlements-Debug.plist similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Entitlements-Debug.plist rename to tests/spec/unit/fixtures/ios-config-xml/App/Entitlements-Debug.plist diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Entitlements-Release.plist b/tests/spec/unit/fixtures/ios-config-xml/App/Entitlements-Release.plist similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Entitlements-Release.plist rename to tests/spec/unit/fixtures/ios-config-xml/App/Entitlements-Release.plist diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Plugins/README b/tests/spec/unit/fixtures/ios-config-xml/App/Plugins/README similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Plugins/README rename to tests/spec/unit/fixtures/ios-config-xml/App/Plugins/README diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Prefix.pch b/tests/spec/unit/fixtures/ios-config-xml/App/SampleApp-Prefix.pch similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/SampleApp-Prefix.pch rename to tests/spec/unit/fixtures/ios-config-xml/App/SampleApp-Prefix.pch diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/Scripts/copy-www-build-step.sh b/tests/spec/unit/fixtures/ios-config-xml/App/Scripts/copy-www-build-step.sh similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/Scripts/copy-www-build-step.sh rename to tests/spec/unit/fixtures/ios-config-xml/App/Scripts/copy-www-build-step.sh diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml b/tests/spec/unit/fixtures/ios-config-xml/App/config.xml similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/config.xml rename to tests/spec/unit/fixtures/ios-config-xml/App/config.xml diff --git a/tests/spec/unit/fixtures/ios-config-xml/SampleApp/main.m b/tests/spec/unit/fixtures/ios-config-xml/App/main.m similarity index 100% rename from tests/spec/unit/fixtures/ios-config-xml/SampleApp/main.m rename to tests/spec/unit/fixtures/ios-config-xml/App/main.m diff --git a/tests/spec/unit/fixtures/test-Bridging-Header.h b/tests/spec/unit/fixtures/test-Bridging-Header.h index dee003af88..23f42e7766 100644 --- a/tests/spec/unit/fixtures/test-Bridging-Header.h +++ b/tests/spec/unit/fixtures/test-Bridging-Header.h @@ -6,7 +6,9 @@ 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 @@ -14,16 +16,6 @@ specific language governing permissions and limitations under the License. */ -// -// Bridging-Header.h -// __PROJECT_NAME__ -// -// Created by ___FULLUSERNAME___ on ___DATE___. -// Copyright ___ORGANIZATIONNAME___ ___YEAR___. All rights reserved. -// -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// #import #import "CDVSwift22Object.h" diff --git a/tests/spec/unit/prepare.spec.js b/tests/spec/unit/prepare.spec.js index c6e7e1f78f..0282b24ea9 100644 --- a/tests/spec/unit/prepare.spec.js +++ b/tests/spec/unit/prepare.spec.js @@ -274,7 +274,7 @@ describe('prepare', () => { const projectRoot = iosProject; it('should find the Assets.xcassets file in a project with an asset catalog', () => { - const platformProjDir = path.join('platforms', 'ios', 'SampleApp'); + const platformProjDir = path.join('platforms', 'ios', 'App'); const assetCatalogPath = path.join(iosProject, platformProjDir, 'Assets.xcassets'); const expectedPath = path.join(platformProjDir, 'Assets.xcassets', 'LaunchStoryboard.imageset'); @@ -306,7 +306,7 @@ describe('prepare', () => { // get appropriate paths const projectRoot = iosProject; - const platformProjDir = path.join('platforms', 'ios', 'SampleApp'); + const platformProjDir = path.join('platforms', 'ios', 'App'); const storyboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir); // create a suitable mock project for our method @@ -357,7 +357,7 @@ describe('prepare', () => { it('should move launch images and update contents.json', () => { const projectRoot = iosProject; - const platformProjDir = path.join('platforms', 'ios', 'SampleApp'); + const platformProjDir = path.join('platforms', 'ios', 'App'); const storyboardImagesDir = getLaunchStoryboardImagesDir(projectRoot, platformProjDir); const project = { root: iosProject, @@ -945,7 +945,6 @@ describe('prepare', () => { update_name = spyOn(xc, 'updateProductName').and.callThrough(); return xc; }); - cfg.name = () => 'SampleApp'; // this is to match p's original project name (based on .xcodeproj) cfg.packageName = () => 'testpkg'; cfg.version = () => 'one point oh'; @@ -953,22 +952,10 @@ describe('prepare', () => { }); it('should resolve', () => { - // the original name here will be `SampleApp` (based on the xcodeproj basename) from p - cfg2.name = () => 'SampleApp'; // new config does *not* have a name change - return updateProject(cfg2, p.locations); // since the name has not changed it *should not* error - }); - - it('should reject when the app name has changed', () => { - // the original name here will be `SampleApp` (based on the xcodeproj basename) from p - cfg2.name = () => 'NotSampleApp'; // new config has name change - return updateProject(cfg2, p.locations).then( // since the name has changed it *should* error - () => fail('Expected promise to be rejected'), - err => expect(err).toEqual(jasmine.any(Error)) - ); + return updateProject(cfg2, p.locations); }); it('should write target-device preference', () => { - cfg2.name = () => 'SampleApp'; // new config does *not* have a name change writeFileSyncSpy.and.callThrough(); return updateProject(cfg2, p.locations).then(() => { @@ -979,7 +966,6 @@ describe('prepare', () => { }); }); it('should write deployment-target preference', () => { - cfg2.name = () => 'SampleApp'; // new config does *not* have a name change writeFileSyncSpy.and.callThrough(); return updateProject(cfg2, p.locations).then(() => { @@ -990,7 +976,6 @@ describe('prepare', () => { }); }); it('should write SwiftVersion preference (4.1)', () => { - cfg3.name = () => 'SampleApp'; // new config does *not* have a name change writeFileSyncSpy.and.callThrough(); return updateProject(cfg3, p.locations).then(() => { const proj = new XcodeProject(p.locations.pbxproj); @@ -1000,7 +985,6 @@ describe('prepare', () => { }); }); it('should write SwiftVersion preference (3.3)', () => { - cfg3.name = () => 'SampleApp'; // new config does *not* have a name change const pref = cfg3.doc.findall('platform[@name=\'ios\']/preference') .filter(elem => elem.attrib.name.toLowerCase() === 'swiftversion')[0]; pref.attrib.value = '3.3'; @@ -1026,8 +1010,8 @@ describe('prepare', () => { return updateProject(cfg, p.locations).then(() => { const proj = new XcodeProject(p.locations.pbxproj); proj.parseSync(); - const prop = proj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'SampleApp'); - expect(prop).toEqual('testpkg'); + const prop = proj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'App'); + expect(prop).toEqual('"testpkg"'); }); }); it('Test#003 : should write out the app id to info plist as CFBundleIdentifier with ios-CFBundleIdentifier', () => { @@ -1044,66 +1028,136 @@ describe('prepare', () => { return updateProject(cfg, p.locations).then(() => { const proj = new XcodeProject(p.locations.pbxproj); proj.parseSync(); - const prop = proj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'SampleApp'); - expect(prop).toEqual('testpkg_ios'); + const prop = proj.getBuildProperty('PRODUCT_BUNDLE_IDENTIFIER', undefined, 'App'); + expect(prop).toEqual('"testpkg_ios"'); }); }); it('Test#004 : should write out the app version to info plist as CFBundleVersion', () => { + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].CFBundleShortVersionString).toEqual('one point oh'); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + const prop = proj.getBuildProperty('MARKETING_VERSION', undefined, 'App'); + expect(prop).toEqual('one point oh'); }); }); it('Test#005 : should write out the orientation preference value', () => { cfg.getPreference.and.callThrough(); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown']); - expect(plist.build.calls.mostRecent().args[0]['UISupportedInterfaceOrientations~ipad']).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toEqual(['UIInterfaceOrientationPortrait']); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toEqual('"UIInterfaceOrientationPortrait"'); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"'); }); }); it('Test#006 : should handle no orientation', () => { - cfg.getPreference.and.returnValue(''); + cfg.getPreference.and.returnValue(null); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toBeUndefined(); - expect(plist.build.calls.mostRecent().args[0]['UISupportedInterfaceOrientations~ipad']).toBeUndefined(); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toBeUndefined(); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toBeUndefined(); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); }); }); it('Test#007 : should handle default orientation', () => { cfg.getPreference.and.returnValue('default'); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0]['UISupportedInterfaceOrientations~ipad']).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toBeUndefined(); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toBeUndefined(); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); }); }); it('Test#008 : should handle portrait orientation', () => { cfg.getPreference.and.returnValue('portrait'); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toEqual(['UIInterfaceOrientationPortrait']); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toEqual('"UIInterfaceOrientationPortrait"'); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"'); }); }); it('Test#009 : should handle landscape orientation', () => { cfg.getPreference.and.returnValue('landscape'); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toEqual(['UIInterfaceOrientationLandscapeLeft']); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toEqual('"UIInterfaceOrientationLandscapeLeft"'); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); }); }); it('Test#010 : should handle all orientation on ios', () => { cfg.getPreference.and.returnValue('all'); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toEqual(['UIInterfaceOrientationPortrait']); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toEqual('"UIInterfaceOrientationPortrait"'); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); }); }); it('Test#011 : should handle custom orientation', () => { cfg.getPreference.and.returnValue('some-custom-orientation'); + writeFileSyncSpy.and.callThrough(); return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].UISupportedInterfaceOrientations).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0]['UISupportedInterfaceOrientations~ipad']).toEqual(['UIInterfaceOrientationPortrait', 'UIInterfaceOrientationPortraitUpsideDown', 'UIInterfaceOrientationLandscapeLeft', 'UIInterfaceOrientationLandscapeRight']); - expect(plist.build.calls.mostRecent().args[0].UIInterfaceOrientation).toBeUndefined(); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + + const orientation = proj.getBuildProperty('INFOPLIST_KEY_UIInterfaceOrientation', undefined, 'App'); + expect(orientation).toBeUndefined(); + + const phone_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone', undefined, 'App'); + expect(phone_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); + + const pad_supported = proj.getBuildProperty('INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad', undefined, 'App'); + expect(pad_supported).toEqual('"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"'); }); }); @@ -1439,11 +1493,6 @@ describe('prepare', () => { }); /// /////////////////////////////////////////////// it('Test#016 : , - http and https, no clobber', () => { - // original name here is 'SampleApp' based on p - // we are not testing a name change here, but testing a new config being used (name change test is above) - // so we set it to the name expected - cfg2.name = () => 'SampleApp'; // new config does *not* have a name change - return updateProject(cfg2, p.locations).then(() => { const ats = plist.build.calls.mostRecent().args[0].NSAppTransportSecurity; const exceptionDomains = ats.NSExceptionDomains; @@ -1864,15 +1913,20 @@ describe('prepare', () => { }); it('Test#020 : - should write out the display name to info plist as CFBundleDisplayName', () => { cfg.shortName = () => 'MyApp'; + writeFileSyncSpy.and.callThrough(); + return updateProject(cfg, p.locations).then(() => { - expect(plist.build.calls.mostRecent().args[0].CFBundleDisplayName).toEqual('MyApp'); + const proj = new XcodeProject(p.locations.pbxproj); + proj.parseSync(); + const prop = proj.getBuildProperty('INFOPLIST_KEY_CFBundleDisplayName', undefined, 'App'); + expect(prop).toEqual('"MyApp"'); }); }); it('Test#021 : - should write out the privacy manifest ', () => { plist.parse.and.callThrough(); writeFileSyncSpy.and.callThrough(); const projectRoot = iosProject; - const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'SampleApp'); + const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'App'); const PlatformConfigParser = require('../../../lib/PlatformConfigParser'); const my_config = new PlatformConfigParser(path.join(FIXTURES, 'prepare', 'privacy-manifest.xml')); const privacyManifest = my_config.getPrivacyManifest(); @@ -1891,7 +1945,7 @@ describe('prepare', () => { plist.parse.and.callThrough(); writeFileSyncSpy.and.callThrough(); const projectRoot = iosProject; - const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'SampleApp'); + const platformProjDir = path.join(projectRoot, 'platforms', 'ios', 'App'); const PlatformConfigParser = require('../../../lib/PlatformConfigParser'); const my_config = new PlatformConfigParser(path.join(FIXTURES, 'prepare', 'no-privacy-manifest.xml')); const privacyManifest = my_config.getPrivacyManifest(); diff --git a/tests/spec/unit/projectFile.spec.js b/tests/spec/unit/projectFile.spec.js index 184213a98b..97a2ab129c 100644 --- a/tests/spec/unit/projectFile.spec.js +++ b/tests/spec/unit/projectFile.spec.js @@ -27,7 +27,7 @@ const iosProjectFixture = path.join(__dirname, 'fixtures/ios-config-xml'); const locations = { root: iosProject, - pbxproj: path.join(iosProject, 'SampleApp.xcodeproj', 'project.pbxproj') + pbxproj: path.join(iosProject, 'App.xcodeproj', 'project.pbxproj') }; describe('projectFile', () => { @@ -41,24 +41,19 @@ describe('projectFile', () => { describe('parse method', () => { it('Test#001 : should throw if project is not an xcode project', () => { - fs.rmSync(path.join(iosProject, 'SampleApp', 'SampleApp.xcodeproj'), { recursive: true, force: true }); + fs.rmSync(path.join(iosProject, 'App', 'App.xcodeproj'), { recursive: true, force: true }); expect(() => { projectFile.parse(); }).toThrow(); }); it('Test#002 : should throw if project does not contain an appropriate config.xml file', () => { - fs.rmSync(path.join(iosProject, 'SampleApp', 'config.xml')); + fs.rmSync(path.join(iosProject, 'App', 'config.xml')); expect(() => { projectFile.parse(locations); }) - .toThrow(new Error('Could not find *-Info.plist file, or config.xml file.')); - }); - it('Test#003 : should throw if project does not contain an appropriate -Info.plist file', () => { - fs.rmSync(path.join(iosProject, 'SampleApp', 'SampleApp-Info.plist')); - expect(() => { projectFile.parse(locations); }) - .toThrow(new Error('Could not find *-Info.plist file, or config.xml file.')); + .toThrow(new Error('Could not find config.xml file.')); }); it('Test#004 : should return right directory when multiple .plist files are present', () => { // Create a folder named A with config.xml and .plist files in it const pathToFolderA = path.join(iosProject, 'A'); fs.mkdirSync(pathToFolderA, { recursive: true }); - fs.cpSync(path.join(iosProject, 'SampleApp'), pathToFolderA, { recursive: true }); + fs.cpSync(path.join(iosProject, 'App'), pathToFolderA, { recursive: true }); const parsedProjectFile = projectFile.parse(locations); const pluginsDir = parsedProjectFile.plugins_dir; @@ -67,7 +62,7 @@ describe('projectFile', () => { const pluginsDirParent = path.dirname(pluginsDir); const resourcesDirParent = path.dirname(resourcesDir); - const sampleAppDir = path.join(iosProject, 'SampleApp'); + const sampleAppDir = path.join(iosProject, 'App'); expect(pluginsDirParent).toEqual(sampleAppDir); expect(resourcesDirParent).toEqual(sampleAppDir); diff --git a/tests/spec/unit/run.spec.js b/tests/spec/unit/run.spec.js index df8ad49d16..8b693103ac 100644 --- a/tests/spec/unit/run.spec.js +++ b/tests/spec/unit/run.spec.js @@ -22,6 +22,7 @@ const { CordovaError, events } = require('cordova-common'); const build = require('../../../lib/build'); const check_reqs = require('../../../lib/check_reqs'); const run = require('../../../lib/run'); +const projectFile = require('../../../lib/projectFile'); describe('cordova/lib/run', () => { const testProjectPath = path.join('/test', 'project', 'path'); @@ -67,9 +68,17 @@ describe('cordova/lib/run', () => { }); describe('run method', () => { + const fakeXcodeProject = { + xcode: { + getBuildProperty (n, c, t) { + return 'ProjectName'; + } + } + }; + beforeEach(() => { spyOn(build, 'run').and.returnValue(Promise.resolve()); - spyOn(build, 'findXCodeProjectIn').and.returnValue('ProjectName'); + spyOn(projectFile, 'parse').and.returnValue(fakeXcodeProject); spyOn(run, 'execListDevices').and.resolveTo([]); spyOn(run, 'execListEmulatorTargets').and.resolveTo([]); spyOn(run, 'listDevices').and.resolveTo();