Merge `rnpm cli` into react-native
Summary: This is an initial step of rewriting the CLI interface to use `rnpm` one (commander, plugins etc.). It's scope is to move all existing commands to use rnpm CLI interface, so that we get plugins, flags and our existing ecosystem working out of the box. <s>This is still WIP and some of the commands are left commented out.</s> For the `config` of `rnpm` (functions get info about project and dependency), <s>I am thinking we can merge them with</s> we decided to merge it with [`default.config.js`](e57683e420/local-cli/default.config.js (L33)
), so they are available on the `new Config()` [instance](e57683e420/local-cli/cliEntry.js (L59)
) (which means we don't have to change anything and current plugins, like runIOS and runAndroid can just start using it [w/o depending on any extra argument](https://github.com/grabbou/react-native/blob/e57683e420210749a5a6b802b4e Closes https://github.com/facebook/react-native/pull/7899 Differential Revision: D3613193 Pulled By: bestander fbshipit-source-id: 09a072f3b21e5239dfcd8da88a205bd28dc5d037
This commit is contained in:
parent
a37d5a825e
commit
e8b508144f
|
@ -23,6 +23,7 @@ global.regeneratorRuntime = require.requireActual('regenerator-runtime/runtime')
|
|||
jest
|
||||
.mock('ensureComponentIsNative')
|
||||
.mock('Image')
|
||||
.mock('npmlog')
|
||||
.mock('NativeModules')
|
||||
.mock('Text')
|
||||
.mock('View');
|
||||
|
|
|
@ -21,69 +21,56 @@ function saveBundle(output, bundle, args) {
|
|||
}
|
||||
|
||||
function buildBundle(args, config, output = outputBundle, packagerInstance) {
|
||||
return new Promise((resolve, reject) => {
|
||||
// This is used by a bazillion of npm modules we don't control so we don't
|
||||
// have other choice than defining it as an env variable here.
|
||||
process.env.NODE_ENV = args.dev ? 'development' : 'production';
|
||||
|
||||
// This is used by a bazillion of npm modules we don't control so we don't
|
||||
// have other choice than defining it as an env variable here.
|
||||
if (!process.env.NODE_ENV) {
|
||||
// If you're inlining environment variables, you can use babel to remove
|
||||
// this line:
|
||||
// https://www.npmjs.com/package/babel-remove-process-env-assignment
|
||||
process.env.NODE_ENV = args.dev ? 'development' : 'production';
|
||||
}
|
||||
const options = {
|
||||
projectRoots: config.getProjectRoots(),
|
||||
assetRoots: config.getAssetRoots(),
|
||||
blacklistRE: config.getBlacklistRE(args.platform),
|
||||
getTransformOptionsModulePath: config.getTransformOptionsModulePath,
|
||||
transformModulePath: args.transformer,
|
||||
extraNodeModules: config.extraNodeModules,
|
||||
nonPersistent: true,
|
||||
resetCache: args.resetCache,
|
||||
};
|
||||
|
||||
const transformModulePath =
|
||||
args.transformer ? path.resolve(args.transformer) :
|
||||
typeof config.getTransformModulePath === 'function' ? config.getTransformModulePath() :
|
||||
undefined;
|
||||
const requestOpts = {
|
||||
entryFile: args.entryFile,
|
||||
sourceMapUrl: args.sourcemapOutput,
|
||||
dev: args.dev,
|
||||
minify: !args.dev,
|
||||
platform: args.platform,
|
||||
};
|
||||
|
||||
const options = {
|
||||
projectRoots: config.getProjectRoots(),
|
||||
assetRoots: config.getAssetRoots(),
|
||||
blacklistRE: config.getBlacklistRE(args.platform),
|
||||
getTransformOptionsModulePath: config.getTransformOptionsModulePath,
|
||||
transformModulePath: transformModulePath,
|
||||
extraNodeModules: config.extraNodeModules,
|
||||
nonPersistent: true,
|
||||
resetCache: args['reset-cache'],
|
||||
};
|
||||
// If a packager instance was not provided, then just create one for this
|
||||
// bundle command and close it down afterwards.
|
||||
var shouldClosePackager = false;
|
||||
if (!packagerInstance) {
|
||||
packagerInstance = new Server(options);
|
||||
shouldClosePackager = true;
|
||||
}
|
||||
|
||||
const requestOpts = {
|
||||
entryFile: args['entry-file'],
|
||||
sourceMapUrl: args['sourcemap-output'],
|
||||
dev: args.dev,
|
||||
minify: !args.dev,
|
||||
platform: args.platform,
|
||||
};
|
||||
const bundlePromise = output.build(packagerInstance, requestOpts)
|
||||
.then(bundle => {
|
||||
if (shouldClosePackager) {
|
||||
packagerInstance.end();
|
||||
}
|
||||
return saveBundle(output, bundle, args);
|
||||
});
|
||||
|
||||
// If a packager instance was not provided, then just create one for this
|
||||
// bundle command and close it down afterwards.
|
||||
var shouldClosePackager = false;
|
||||
if (!packagerInstance) {
|
||||
packagerInstance = new Server(options);
|
||||
shouldClosePackager = true;
|
||||
}
|
||||
// Save the assets of the bundle
|
||||
const assets = bundlePromise
|
||||
.then(bundle => bundle.getAssets())
|
||||
.then(outputAssets => saveAssets(
|
||||
outputAssets,
|
||||
args.platform,
|
||||
args.assetsDest,
|
||||
));
|
||||
|
||||
const bundlePromise = output.build(packagerInstance, requestOpts)
|
||||
.then(bundle => {
|
||||
if (shouldClosePackager) {
|
||||
packagerInstance.end();
|
||||
}
|
||||
return saveBundle(output, bundle, args);
|
||||
});
|
||||
|
||||
// Save the assets of the bundle
|
||||
const assets = bundlePromise
|
||||
.then(bundle => bundle.getAssets())
|
||||
.then(outputAssets => saveAssets(
|
||||
outputAssets,
|
||||
args.platform,
|
||||
args['assets-dest']
|
||||
));
|
||||
|
||||
// When we're done saving bundle output and the assets, we're done.
|
||||
resolve(assets);
|
||||
});
|
||||
// When we're done saving bundle output and the assets, we're done.
|
||||
return assets;
|
||||
}
|
||||
|
||||
module.exports = buildBundle;
|
||||
|
|
|
@ -8,26 +8,30 @@
|
|||
*/
|
||||
|
||||
const buildBundle = require('./buildBundle');
|
||||
const bundleCommandLineArgs = require('./bundleCommandLineArgs');
|
||||
const parseCommandLine = require('../util/parseCommandLine');
|
||||
const outputBundle = require('./output/bundle');
|
||||
const outputPrepack = require('./output/prepack');
|
||||
const bundleCommandLineArgs = require('./bundleCommandLineArgs');
|
||||
|
||||
/**
|
||||
* Builds the bundle starting to look for dependencies at the given entry path.
|
||||
*/
|
||||
function bundleWithOutput(argv, config, output, packagerInstance) {
|
||||
const args = parseCommandLine(bundleCommandLineArgs, argv);
|
||||
function bundleWithOutput(argv, config, args, output, packagerInstance) {
|
||||
if (!output) {
|
||||
output = args.prepack ? outputPrepack : outputBundle;
|
||||
}
|
||||
return buildBundle(args, config, output, packagerInstance);
|
||||
|
||||
}
|
||||
|
||||
function bundle(argv, config, packagerInstance) {
|
||||
return bundleWithOutput(argv, config, undefined, packagerInstance);
|
||||
function bundle(argv, config, args, packagerInstance) {
|
||||
return bundleWithOutput(argv, config, args, undefined, packagerInstance);
|
||||
}
|
||||
|
||||
module.exports = bundle;
|
||||
module.exports.withOutput = bundleWithOutput;
|
||||
module.exports = {
|
||||
name: 'bundle',
|
||||
description: 'builds the javascript bundle for offline use',
|
||||
func: bundle,
|
||||
options: bundleCommandLineArgs,
|
||||
|
||||
// not used by the CLI itself
|
||||
withOutput: bundleWithOutput,
|
||||
};
|
||||
|
|
|
@ -10,56 +10,47 @@
|
|||
|
||||
module.exports = [
|
||||
{
|
||||
command: 'entry-file',
|
||||
command: '--entry-file <path>',
|
||||
description: 'Path to the root JS file, either absolute or relative to JS root',
|
||||
type: 'string',
|
||||
required: true,
|
||||
}, {
|
||||
command: 'platform',
|
||||
command: '--platform [string]',
|
||||
description: 'Either "ios" or "android"',
|
||||
type: 'string',
|
||||
default: 'ios',
|
||||
}, {
|
||||
command: 'transformer',
|
||||
description: 'Specify a custom transformer to be used',
|
||||
type: 'string',
|
||||
default: null,
|
||||
command: '--transformer [string]',
|
||||
description: 'Specify a custom transformer to be used (absolute path)',
|
||||
default: require.resolve('../../packager/transformer'),
|
||||
}, {
|
||||
command: 'dev',
|
||||
command: '--dev [boolean]',
|
||||
description: 'If false, warnings are disabled and the bundle is minified',
|
||||
parse: (val) => val === 'false' ? false : true,
|
||||
default: true,
|
||||
}, {
|
||||
command: 'prepack',
|
||||
description: 'If true, the output bundle will use the Prepack format.',
|
||||
default: false
|
||||
command: '--prepack',
|
||||
description: 'When passed, the output bundle will use the Prepack format.',
|
||||
}, {
|
||||
command: 'bridge-config',
|
||||
command: '--bridge-config [string]',
|
||||
description: 'File name of a a JSON export of __fbBatchedBridgeConfig. Used by Prepack. Ex. ./bridgeconfig.json',
|
||||
type: 'string'
|
||||
}, {
|
||||
command: 'bundle-output',
|
||||
command: '--bundle-output <string>',
|
||||
description: 'File name where to store the resulting bundle, ex. /tmp/groups.bundle',
|
||||
type: 'string',
|
||||
required: true,
|
||||
}, {
|
||||
command: 'bundle-encoding',
|
||||
command: '--bundle-encoding [string]',
|
||||
description: 'Encoding the bundle should be written in (https://nodejs.org/api/buffer.html#buffer_buffer).',
|
||||
type: 'string',
|
||||
default: 'utf8',
|
||||
}, {
|
||||
command: 'sourcemap-output',
|
||||
command: '--sourcemap-output [string]',
|
||||
description: 'File name where to store the sourcemap file for resulting bundle, ex. /tmp/groups.map',
|
||||
type: 'string',
|
||||
}, {
|
||||
command: 'assets-dest',
|
||||
command: '--assets-dest [string]',
|
||||
description: 'Directory name where to store assets referenced in the bundle',
|
||||
type: 'string',
|
||||
}, {
|
||||
command: 'verbose',
|
||||
command: '--verbose',
|
||||
description: 'Enables logging',
|
||||
default: false,
|
||||
}, {
|
||||
command: 'reset-cache',
|
||||
command: '--reset-cache',
|
||||
description: 'Removes cached files',
|
||||
default: false
|
||||
}
|
||||
default: false,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -28,10 +28,10 @@ function createCodeWithMap(bundle, dev) {
|
|||
|
||||
function saveBundleAndMap(bundle, options, log) {
|
||||
const {
|
||||
'bundle-output': bundleOutput,
|
||||
'bundle-encoding': encoding,
|
||||
bundleOutput,
|
||||
bundleEncoding: encoding,
|
||||
dev,
|
||||
'sourcemap-output': sourcemapOutput,
|
||||
sourcemapOutput
|
||||
} = options;
|
||||
|
||||
log('start');
|
||||
|
|
|
@ -16,8 +16,8 @@ function buildPrepackBundle(packagerClient, requestOptions) {
|
|||
|
||||
function savePrepackBundle(bundle, options, log) {
|
||||
const {
|
||||
'bundle-output': bundleOutput,
|
||||
'bridge-config': bridgeConfig,
|
||||
bundleOutput,
|
||||
bridgeConfig,
|
||||
} = options;
|
||||
|
||||
const result = bundle.build({
|
||||
|
|
|
@ -30,9 +30,9 @@ const MODULES_DIR = 'js-modules';
|
|||
*/
|
||||
function saveAsAssets(bundle, options, log) {
|
||||
const {
|
||||
'bundle-output': bundleOutput,
|
||||
'bundle-encoding': encoding,
|
||||
'sourcemap-output': sourcemapOutput,
|
||||
bundleOutput,
|
||||
bundleEncoding: encoding,
|
||||
sourcemapOutput
|
||||
} = options;
|
||||
|
||||
log('start');
|
||||
|
|
|
@ -26,9 +26,9 @@ const SIZEOF_UINT32 = 4;
|
|||
*/
|
||||
function saveAsIndexedFile(bundle, options, log) {
|
||||
const {
|
||||
'bundle-output': bundleOutput,
|
||||
'bundle-encoding': encoding,
|
||||
'sourcemap-output': sourcemapOutput,
|
||||
bundleOutput,
|
||||
bundleEncoding: encoding,
|
||||
sourcemapOutput
|
||||
} = options;
|
||||
|
||||
log('start');
|
||||
|
|
|
@ -8,13 +8,19 @@
|
|||
*/
|
||||
|
||||
const bundleWithOutput = require('./bundle').withOutput;
|
||||
const bundleCommandLineArgs = require('./bundleCommandLineArgs');
|
||||
const outputUnbundle = require('./output/unbundle');
|
||||
|
||||
/**
|
||||
* Builds the bundle starting to look for dependencies at the given entry path.
|
||||
*/
|
||||
function unbundle(argv, config, packagerInstance) {
|
||||
return bundleWithOutput(argv, config, outputUnbundle, packagerInstance);
|
||||
function unbundle(argv, config, args, packagerInstance) {
|
||||
return bundleWithOutput(argv, config, args, outputUnbundle, packagerInstance);
|
||||
}
|
||||
|
||||
module.exports = unbundle;
|
||||
module.exports = {
|
||||
name: 'unbundle',
|
||||
description: 'builds javascript as "unbundle" for offline use',
|
||||
func: unbundle,
|
||||
options: bundleCommandLineArgs,
|
||||
};
|
||||
|
|
|
@ -5,171 +5,151 @@
|
|||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const bundle = require('./bundle/bundle');
|
||||
const childProcess = require('child_process');
|
||||
const Config = require('./util/Config');
|
||||
const defaultConfig = require('./default.config');
|
||||
const dependencies = require('./dependencies/dependencies');
|
||||
const generate = require('./generate/generate');
|
||||
const library = require('./library/library');
|
||||
const link = require('./rnpm/link/src/link');
|
||||
const path = require('path');
|
||||
const Promise = require('promise');
|
||||
const runAndroid = require('./runAndroid/runAndroid');
|
||||
const logAndroid = require('./logAndroid/logAndroid');
|
||||
const runIOS = require('./runIOS/runIOS');
|
||||
const logIOS = require('./logIOS/logIOS');
|
||||
const server = require('./server/server');
|
||||
const TerminalAdapter = require('yeoman-environment/lib/adapter.js');
|
||||
const yeoman = require('yeoman-environment');
|
||||
const unbundle = require('./bundle/unbundle');
|
||||
const upgrade = require('./upgrade/upgrade');
|
||||
const version = require('./version/version');
|
||||
const commander = require('commander');
|
||||
|
||||
const Config = require('./util/Config');
|
||||
const childProcess = require('child_process');
|
||||
const Promise = require('promise');
|
||||
const chalk = require('chalk');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const gracefulFs = require('graceful-fs');
|
||||
|
||||
// Just a helper to proxy 'react-native link' to rnpm
|
||||
const linkWrapper = (args, config) => {
|
||||
const rnpmConfig = require('./rnpm/core/src/config');
|
||||
return new Promise((resolve, reject) => {
|
||||
link(rnpmConfig, args.slice(1)).then(resolve, reject);
|
||||
});
|
||||
}
|
||||
const init = require('./init/init');
|
||||
const commands = require('./commands');
|
||||
const assertRequiredOptions = require('./util/assertRequiredOptions');
|
||||
const pkg = require('../package.json');
|
||||
const defaultConfig = require('./default.config');
|
||||
|
||||
import type { Command } from './commands';
|
||||
|
||||
// graceful-fs helps on getting an error when we run out of file
|
||||
// descriptors. When that happens it will enqueue the operation and retry it.
|
||||
gracefulFs.gracefulify(fs);
|
||||
|
||||
const documentedCommands = {
|
||||
'start': [server, 'starts the webserver'],
|
||||
'bundle': [bundle, 'builds the javascript bundle for offline use'],
|
||||
'unbundle': [unbundle, 'builds javascript as "unbundle" for offline use'],
|
||||
'new-library': [library, 'generates a native library bridge'],
|
||||
'android': [generateWrapper, 'generates an Android project for your app'],
|
||||
'run-android': [runAndroid, 'builds your app and starts it on a connected Android emulator or device'],
|
||||
'log-android': [logAndroid, 'print Android logs'],
|
||||
'run-ios': [runIOS, 'builds your app and starts it on iOS simulator'],
|
||||
'log-ios': [logIOS, 'print iOS logs'],
|
||||
'upgrade': [upgrade, 'upgrade your app\'s template files to the latest version; run this after ' +
|
||||
'updating the react-native version in your package.json and running npm install'],
|
||||
'link': [linkWrapper, 'link a library'],
|
||||
commander.version(pkg.version);
|
||||
|
||||
const defaultOptParser = (val) => val;
|
||||
|
||||
const handleError = (err) => {
|
||||
console.error();
|
||||
console.error(err.message || err);
|
||||
console.error();
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const exportedCommands = {dependencies: dependencies};
|
||||
Object.keys(documentedCommands).forEach(function(command) {
|
||||
exportedCommands[command] = documentedCommands[command][0];
|
||||
});
|
||||
|
||||
const undocumentedCommands = {
|
||||
'--version': [version, ''],
|
||||
'init': [printInitWarning, ''],
|
||||
};
|
||||
|
||||
const commands = Object.assign({}, documentedCommands, undocumentedCommands);
|
||||
|
||||
/**
|
||||
* Parses the command line and runs a command of the CLI.
|
||||
*/
|
||||
function run() {
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length === 0) {
|
||||
printUsage();
|
||||
// Custom printHelpInformation command inspired by internal Commander.js
|
||||
// one modified to suit our needs
|
||||
function printHelpInformation() {
|
||||
let cmdName = this._name;
|
||||
if (this._alias) {
|
||||
cmdName = cmdName + '|' + this._alias;
|
||||
}
|
||||
|
||||
let output = [
|
||||
'',
|
||||
chalk.bold(chalk.cyan((` react-native ${cmdName} [options]`))),
|
||||
` ${this._description}`,
|
||||
'',
|
||||
` ${chalk.bold('Options:')}`,
|
||||
'',
|
||||
this.optionHelp().replace(/^/gm, ' '),
|
||||
'',
|
||||
];
|
||||
|
||||
const usage = this.usage();
|
||||
|
||||
if (usage !== '[options]') {
|
||||
const formattedUsage = usage.map(
|
||||
example => ` ${example.desc}: \n ${chalk.cyan(example.cmd)}`,
|
||||
).join('\n\n');
|
||||
|
||||
output = output.concat([
|
||||
chalk.bold(' Example usage:'),
|
||||
'',
|
||||
formattedUsage,
|
||||
]);
|
||||
}
|
||||
|
||||
return output.concat([
|
||||
'',
|
||||
'',
|
||||
]).join('\n');
|
||||
}
|
||||
|
||||
function printUnknownCommand(cmdName) {
|
||||
console.log([
|
||||
'',
|
||||
cmdName
|
||||
? chalk.red(` Unrecognized command '${cmdName}'`)
|
||||
: chalk.red(' You didn\'t pass any command'),
|
||||
` Run ${chalk.cyan('react-native --help')} to see list of all available commands`,
|
||||
'',
|
||||
].join('\n'));
|
||||
}
|
||||
|
||||
const addCommand = (command: Command, config: Config) => {
|
||||
const options = command.options || [];
|
||||
|
||||
const cmd = commander
|
||||
.command(command.name, undefined, {
|
||||
noHelp: !command.description,
|
||||
})
|
||||
.usage(command.examples)
|
||||
.description(command.description)
|
||||
.action(function runAction() {
|
||||
const passedOptions = this.opts();
|
||||
const argv: Array<string> = Array.from(arguments).slice(0, -1);
|
||||
|
||||
Promise.resolve()
|
||||
.then(() => {
|
||||
assertRequiredOptions(options, passedOptions);
|
||||
return command.func(argv, config, passedOptions);
|
||||
})
|
||||
.catch(handleError);
|
||||
});
|
||||
|
||||
cmd.helpInformation = printHelpInformation.bind(cmd);
|
||||
|
||||
options
|
||||
.forEach(opt => cmd.option(
|
||||
opt.command,
|
||||
opt.description,
|
||||
opt.parse || defaultOptParser,
|
||||
typeof opt.default === 'function' ? opt.default(config) : opt.default,
|
||||
));
|
||||
};
|
||||
|
||||
function run() {
|
||||
const config = Config.get(__dirname, defaultConfig);
|
||||
const setupEnvScript = /^win/.test(process.platform)
|
||||
? 'setup_env.bat'
|
||||
: 'setup_env.sh';
|
||||
|
||||
childProcess.execFileSync(path.join(__dirname, setupEnvScript));
|
||||
|
||||
const command = commands[args[0]];
|
||||
if (!command) {
|
||||
console.error('Command `%s` unrecognized', args[0]);
|
||||
printUsage();
|
||||
commands.forEach(cmd => addCommand(cmd, config));
|
||||
|
||||
commander.parse(process.argv);
|
||||
|
||||
const isValidCommand = commands.find(cmd => cmd.name === process.argv[2]);
|
||||
|
||||
if (!isValidCommand) {
|
||||
printUnknownCommand(process.argv[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
command[0](args, Config.get(__dirname, defaultConfig)).done();
|
||||
}
|
||||
|
||||
function generateWrapper(args, config) {
|
||||
return generate([
|
||||
'--platform', 'android',
|
||||
'--project-path', process.cwd(),
|
||||
'--project-name', JSON.parse(
|
||||
fs.readFileSync('package.json', 'utf8')
|
||||
).name
|
||||
], config);
|
||||
}
|
||||
|
||||
function printUsage() {
|
||||
console.log([
|
||||
'Usage: react-native <command>',
|
||||
'',
|
||||
'Commands:'
|
||||
].concat(Object.keys(documentedCommands).map(function(name) {
|
||||
return ' - ' + name + ': ' + documentedCommands[name][1];
|
||||
})).join('\n'));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// The user should never get here because projects are inited by
|
||||
// using `react-native-cli` from outside a project directory.
|
||||
function printInitWarning() {
|
||||
return Promise.resolve().then(function() {
|
||||
console.log([
|
||||
'Looks like React Native project already exists in the current',
|
||||
'folder. Run this command from a different folder or remove node_modules/react-native'
|
||||
].join('\n'));
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
class CreateSuppressingTerminalAdapter extends TerminalAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
// suppress 'create' output generated by yeoman
|
||||
this.log.create = function() {};
|
||||
if (!commander.args.length) {
|
||||
commander.help();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the template for a React Native project given the provided
|
||||
* parameters:
|
||||
* - projectDir: templates will be copied here.
|
||||
* - argsOrName: project name or full list of custom arguments to pass to the
|
||||
* generator.
|
||||
*/
|
||||
function init(projectDir, argsOrName) {
|
||||
console.log('Setting up new React Native app in ' + projectDir);
|
||||
const env = yeoman.createEnv(
|
||||
undefined,
|
||||
undefined,
|
||||
new CreateSuppressingTerminalAdapter()
|
||||
);
|
||||
|
||||
env.register(
|
||||
require.resolve(path.join(__dirname, 'generator')),
|
||||
'react:app'
|
||||
);
|
||||
|
||||
// argv is for instance
|
||||
// ['node', 'react-native', 'init', 'AwesomeApp', '--verbose']
|
||||
// args should be ['AwesomeApp', '--verbose']
|
||||
const args = Array.isArray(argsOrName)
|
||||
? argsOrName
|
||||
: [argsOrName].concat(process.argv.slice(4));
|
||||
|
||||
const generator = env.create('react:app', {args: args});
|
||||
generator.destinationRoot(projectDir);
|
||||
generator.run();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
run: run,
|
||||
init: init,
|
||||
commands: exportedCommands
|
||||
};
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const Config = require('./util/Config');
|
||||
const getUserCommands = require('./rnpm/core/src/getCommands');
|
||||
|
||||
export type Command = {
|
||||
name: string,
|
||||
description?: string,
|
||||
usage?: string,
|
||||
func: (argv: Array<string>, config: Config, args: Object) => ?Promise<void>,
|
||||
options?: Array<{
|
||||
command: string,
|
||||
description?: string,
|
||||
parse?: (val: string) => any,
|
||||
default?: (config: Config) => any | any,
|
||||
}>,
|
||||
examples?: Array<{
|
||||
desc: string,
|
||||
cmd: string,
|
||||
}>,
|
||||
};
|
||||
|
||||
const documentedCommands = [
|
||||
require('./server/server'),
|
||||
require('./runIOS/runIOS'),
|
||||
require('./runAndroid/runAndroid'),
|
||||
require('./library/library'),
|
||||
require('./bundle/bundle'),
|
||||
require('./bundle/unbundle'),
|
||||
require('./rnpm/link/link'),
|
||||
require('./rnpm/link/unlink'),
|
||||
require('./rnpm/install/install'),
|
||||
require('./rnpm/install/uninstall'),
|
||||
require('./upgrade/upgrade'),
|
||||
require('./logAndroid/logAndroid'),
|
||||
require('./logIOS/logIOS'),
|
||||
require('./dependencies/dependencies'),
|
||||
];
|
||||
|
||||
// The user should never get here because projects are inited by
|
||||
// using `react-native-cli` from outside a project directory.
|
||||
const undocumentedCommands = [
|
||||
{
|
||||
name: 'init',
|
||||
func: () => {
|
||||
console.log([
|
||||
'Looks like React Native project already exists in the current',
|
||||
'folder. Run this command from a different folder or remove node_modules/react-native'
|
||||
].join('\n'));
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const commands: Array<Command> = [
|
||||
...documentedCommands,
|
||||
...undocumentedCommands,
|
||||
...getUserCommands(),
|
||||
];
|
||||
|
||||
module.exports = commands;
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
var blacklist = require('../packager/blacklist');
|
||||
var path = require('path');
|
||||
var rnpmConfig = require('./rnpm/core/src/config');
|
||||
|
||||
/**
|
||||
* Default configuration for the CLI.
|
||||
|
@ -15,6 +16,9 @@ var config = {
|
|||
return getRoots();
|
||||
},
|
||||
|
||||
getProjectConfig: rnpmConfig.getProjectConfig,
|
||||
getDependencyConfig: rnpmConfig.getDependencyConfig,
|
||||
|
||||
/**
|
||||
* Specify where to look for assets that are referenced using
|
||||
* `image!<image_name>`. Asset directories for images referenced using
|
||||
|
|
|
@ -8,50 +8,14 @@
|
|||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const parseCommandLine = require('../util/parseCommandLine');
|
||||
const path = require('path');
|
||||
const Promise = require('promise');
|
||||
const ReactPackager = require('../../packager/react-packager');
|
||||
|
||||
/**
|
||||
* Returns the dependencies an entry path has.
|
||||
*/
|
||||
function dependencies(argv, config, packagerInstance) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_dependencies(argv, config, resolve, reject, packagerInstance);
|
||||
});
|
||||
}
|
||||
|
||||
function _dependencies(argv, config, resolve, reject, packagerInstance) {
|
||||
const args = parseCommandLine([
|
||||
{
|
||||
command: 'entry-file',
|
||||
description: 'Absolute path to the root JS file',
|
||||
type: 'string',
|
||||
required: true,
|
||||
}, {
|
||||
command: 'output',
|
||||
description: 'File name where to store the output, ex. /tmp/dependencies.txt',
|
||||
type: 'string',
|
||||
}, {
|
||||
command: 'platform',
|
||||
description: 'The platform extension used for selecting modules',
|
||||
type: 'string',
|
||||
}, {
|
||||
command: 'transformer',
|
||||
type: 'string',
|
||||
default: null,
|
||||
description: 'Specify a custom transformer to be used'
|
||||
}, {
|
||||
command: 'verbose',
|
||||
description: 'Enables logging',
|
||||
default: false,
|
||||
}
|
||||
], argv);
|
||||
|
||||
const rootModuleAbsolutePath = args['entry-file'];
|
||||
function dependencies(argv, config, args, packagerInstance) {
|
||||
const rootModuleAbsolutePath = args.entryFile;
|
||||
if (!fs.existsSync(rootModuleAbsolutePath)) {
|
||||
reject(`File ${rootModuleAbsolutePath} does not exist`);
|
||||
return Promise.reject(`File ${rootModuleAbsolutePath} does not exist`);
|
||||
}
|
||||
|
||||
const transformModulePath =
|
||||
|
@ -86,7 +50,7 @@ function _dependencies(argv, config, resolve, reject, packagerInstance) {
|
|||
? fs.createWriteStream(args.output)
|
||||
: process.stdout;
|
||||
|
||||
resolve((packagerInstance ?
|
||||
return Promise.resolve((packagerInstance ?
|
||||
packagerInstance.getOrderedDependencyPaths(options) :
|
||||
ReactPackager.getOrderedDependencyPaths(packageOpts, options)).then(
|
||||
deps => {
|
||||
|
@ -110,4 +74,27 @@ function _dependencies(argv, config, resolve, reject, packagerInstance) {
|
|||
));
|
||||
}
|
||||
|
||||
module.exports = dependencies;
|
||||
module.exports = {
|
||||
name: 'dependencies',
|
||||
func: dependencies,
|
||||
options: [
|
||||
{
|
||||
command: '--entry-file <path>',
|
||||
description: 'Absolute path to the root JS file',
|
||||
}, {
|
||||
command: '--output [path]',
|
||||
description: 'File name where to store the output, ex. /tmp/dependencies.txt',
|
||||
}, {
|
||||
command: '--platform [extension]',
|
||||
description: 'The platform extension used for selecting modules',
|
||||
}, {
|
||||
command: '--transformer [path]',
|
||||
default: null,
|
||||
description: 'Specify a custom transformer to be used'
|
||||
}, {
|
||||
command: '--verbose',
|
||||
description: 'Enables logging',
|
||||
default: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const TerminalAdapter = require('yeoman-environment/lib/adapter.js');
|
||||
const yeoman = require('yeoman-environment');
|
||||
|
||||
class CreateSuppressingTerminalAdapter extends TerminalAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
// suppress 'create' output generated by yeoman
|
||||
this.log.create = function() {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the template for a React Native project given the provided
|
||||
* parameters:
|
||||
* - projectDir: templates will be copied here.
|
||||
* - argsOrName: project name or full list of custom arguments to pass to the
|
||||
* generator.
|
||||
*/
|
||||
function init(projectDir, argsOrName) {
|
||||
console.log('Setting up new React Native app in ' + projectDir);
|
||||
const env = yeoman.createEnv(
|
||||
undefined,
|
||||
undefined,
|
||||
new CreateSuppressingTerminalAdapter()
|
||||
);
|
||||
|
||||
env.register(
|
||||
require.resolve(path.join(__dirname, '../generator')),
|
||||
'react:app'
|
||||
);
|
||||
|
||||
// argv is for instance
|
||||
// ['node', 'react-native', 'init', 'AwesomeApp', '--verbose']
|
||||
// args should be ['AwesomeApp', '--verbose']
|
||||
const args = Array.isArray(argsOrName)
|
||||
? argsOrName
|
||||
: [argsOrName].concat(process.argv.slice(4));
|
||||
|
||||
const generator = env.create('react:app', {args: args});
|
||||
generator.destinationRoot(projectDir);
|
||||
generator.run();
|
||||
}
|
||||
|
||||
module.exports = init;
|
|
@ -11,7 +11,6 @@
|
|||
const copyAndReplace = require('../util/copyAndReplace');
|
||||
const fs = require('fs');
|
||||
const isValidPackageName = require('../util/isValidPackageName');
|
||||
const parseCommandLine = require('../util/parseCommandLine');
|
||||
const path = require('path');
|
||||
const Promise = require('promise');
|
||||
const walk = require('../util/walk');
|
||||
|
@ -19,22 +18,9 @@ const walk = require('../util/walk');
|
|||
/**
|
||||
* Creates a new native library with the given name
|
||||
*/
|
||||
function library(argv, config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_library(argv, config, resolve, reject);
|
||||
});
|
||||
}
|
||||
|
||||
function _library(argv, config, resolve, reject) {
|
||||
const args = parseCommandLine([{
|
||||
command: 'name',
|
||||
description: 'Library name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
}], argv);
|
||||
|
||||
function library(argv, config, args) {
|
||||
if (!isValidPackageName(args.name)) {
|
||||
reject(
|
||||
return Promise.reject(
|
||||
args.name + ' is not a valid name for a project. Please use a valid ' +
|
||||
'identifier name (alphanumeric).'
|
||||
);
|
||||
|
@ -50,7 +36,7 @@ function _library(argv, config, resolve, reject) {
|
|||
}
|
||||
|
||||
if (fs.existsSync(libraryDest)) {
|
||||
reject('Library already exists in', libraryDest);
|
||||
return Promise.reject(`Library already exists in ${libraryDest}`);
|
||||
}
|
||||
|
||||
walk(source).forEach(f => {
|
||||
|
@ -71,7 +57,15 @@ function _library(argv, config, resolve, reject) {
|
|||
console.log('Next Steps:');
|
||||
console.log(' Link your library in Xcode:');
|
||||
console.log(' https://facebook.github.io/react-native/docs/linking-libraries-ios.html#content\n');
|
||||
resolve();
|
||||
}
|
||||
|
||||
module.exports = library;
|
||||
module.exports = {
|
||||
name: 'new-library',
|
||||
func: library,
|
||||
description: 'generates a native library bridge',
|
||||
options: [{
|
||||
command: '--name <string>',
|
||||
description: 'name of the library to generate',
|
||||
default: null,
|
||||
}],
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ function logAndroid() {
|
|||
});
|
||||
}
|
||||
|
||||
function _logAndroid(resolve, reject) {
|
||||
function _logAndroid() {
|
||||
try {
|
||||
const adbPath = process.env.ANDROID_HOME
|
||||
? process.env.ANDROID_HOME + '/platform-tools/adb'
|
||||
|
@ -43,9 +43,12 @@ function _logAndroid(resolve, reject) {
|
|||
console.log(chalk.red(
|
||||
'adb invocation failed. Do you have adb in your PATH?'
|
||||
));
|
||||
reject();
|
||||
return;
|
||||
return Promise.reject();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = logAndroid;
|
||||
module.exports = {
|
||||
name: 'log-android',
|
||||
description: 'starts adb logcat',
|
||||
func: logAndroid,
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@ function logIOS() {
|
|||
});
|
||||
}
|
||||
|
||||
function _logIOS(resolve, reject) {
|
||||
function _logIOS() {
|
||||
let rawDevices;
|
||||
|
||||
try {
|
||||
|
@ -26,8 +26,7 @@ function _logIOS(resolve, reject) {
|
|||
console.log(chalk.red(
|
||||
'xcrun invocation failed. Please check that Xcode is installed.'
|
||||
));
|
||||
reject(e);
|
||||
return;
|
||||
return Promise.reject(e);
|
||||
}
|
||||
|
||||
const { devices } = JSON.parse(rawDevices);
|
||||
|
@ -37,10 +36,10 @@ function _logIOS(resolve, reject) {
|
|||
console.log(chalk.red(
|
||||
'No active iOS device found'
|
||||
));
|
||||
reject();
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
tailDeviceLogs(device.udid, reject);
|
||||
return tailDeviceLogs(device.udid);
|
||||
}
|
||||
|
||||
function _findAvailableDevice(devices) {
|
||||
|
@ -53,7 +52,7 @@ function _findAvailableDevice(devices) {
|
|||
}
|
||||
}
|
||||
|
||||
function tailDeviceLogs(udid, reject) {
|
||||
function tailDeviceLogs(udid) {
|
||||
const logDir = path.join(
|
||||
os.homedir(),
|
||||
'Library',
|
||||
|
@ -70,8 +69,12 @@ function tailDeviceLogs(udid, reject) {
|
|||
console.log(chalk.red(
|
||||
'syslog invocation failed.'
|
||||
));
|
||||
reject(log.error);
|
||||
return Promise.reject(log.error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = logIOS;
|
||||
module.exports = {
|
||||
name: 'log-ios',
|
||||
description: 'starts iOS device syslog tail',
|
||||
func: logIOS,
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const findAndroidAppFolder = require('../../src/config/android/findAndroidAppFolder');
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findAndroidAppFolder', () => {
|
||||
beforeAll(() => mockFs({
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const findManifest = require('../../src/config/android/findManifest');
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findManifest', () => {
|
||||
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const findPackageClassName = require('../../src/config/android/findPackageClassName');
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::findPackageClassName', () => {
|
||||
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const getDependencyConfig = require('../../src/config/android').dependencyConfig;
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
const userConfig = {};
|
||||
|
||||
describe('android::getDependencyConfig', () => {
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const getProjectConfig = require('../../src/config/android').projectConfig;
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::getProjectConfig', () => {
|
||||
beforeAll(() => mockFs({
|
|
@ -3,7 +3,7 @@ jest.autoMockOff();
|
|||
const findManifest = require('../../src/config/android/findManifest');
|
||||
const readManifest = require('../../src/config/android/readManifest');
|
||||
const mockFs = require('mock-fs');
|
||||
const mocks = require('../fixtures/android');
|
||||
const mocks = require('../../__fixtures__/android');
|
||||
|
||||
describe('android::readManifest', () => {
|
||||
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const findAssets = require('../src/config/findAssets');
|
||||
const mockFs = require('mock-fs');
|
||||
const dependencies = require('./fixtures/dependencies');
|
||||
const dependencies = require('../__fixtures__/dependencies');
|
||||
const isArray = (arg) =>
|
||||
Object.prototype.toString.call(arg) === '[object Array]';
|
||||
|
|
@ -2,8 +2,8 @@ jest.autoMockOff();
|
|||
|
||||
const findProject = require('../../src/config/ios/findProject');
|
||||
const mockFs = require('mock-fs');
|
||||
const projects = require('../fixtures/projects');
|
||||
const ios = require('../fixtures/ios');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
const ios = require('../../__fixtures__/ios');
|
||||
const userConfig = {};
|
||||
|
||||
describe('ios::findProject', () => {
|
|
@ -2,7 +2,7 @@ jest.autoMockOff();
|
|||
|
||||
const getProjectConfig = require('../../src/config/ios').projectConfig;
|
||||
const mockFs = require('mock-fs');
|
||||
const projects = require('../fixtures/projects');
|
||||
const projects = require('../../__fixtures__/projects');
|
||||
|
||||
describe('ios::getProjectConfig', () => {
|
||||
const userConfig = {};
|
||||
|
@ -22,5 +22,15 @@ describe('ios::getProjectConfig', () => {
|
|||
expect(getProjectConfig(folder, userConfig)).toBe(null);
|
||||
});
|
||||
|
||||
it('should return normalized shared library names', () => {
|
||||
const projectConfig = getProjectConfig('testDir/nested', {
|
||||
sharedLibraries: ['libc++', 'libz.tbd', 'HealthKit', 'HomeKit.framework'],
|
||||
});
|
||||
|
||||
expect(projectConfig.sharedLibraries).toEqual(
|
||||
['libc++.tbd', 'libz.tbd', 'HealthKit.framework', 'HomeKit.framework']
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(mockFs.restore);
|
||||
});
|
|
@ -1,6 +1,19 @@
|
|||
const path = require('path');
|
||||
const findProject = require('./findProject');
|
||||
|
||||
/**
|
||||
* For libraries specified without an extension, add '.tbd' for those that
|
||||
* start with 'lib' and '.framework' to the rest.
|
||||
*/
|
||||
const mapSharedLibaries = (libraries) => {
|
||||
return libraries.map(name => {
|
||||
if (path.extname(name)) {
|
||||
return name;
|
||||
}
|
||||
return name + (name.indexOf('lib') === 0 ? '.tbd' : '.framework');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns project config by analyzing given folder and applying some user defaults
|
||||
* when constructing final object
|
||||
|
@ -24,6 +37,7 @@ exports.projectConfig = function projectConfigIOS(folder, userConfig) {
|
|||
projectPath: projectPath,
|
||||
projectName: path.basename(projectPath),
|
||||
libraryFolder: userConfig.libraryFolder || 'Libraries',
|
||||
sharedLibraries: mapSharedLibaries(userConfig.sharedLibraries || []),
|
||||
plist: userConfig.plist || [],
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const union = require('lodash').union;
|
||||
const uniq = require('lodash').uniq;
|
||||
const flatten = require('lodash').flatten;
|
||||
|
@ -9,7 +8,7 @@ const flatten = require('lodash').flatten;
|
|||
* @param {String} dependency Name of the dependency
|
||||
* @return {Boolean} If dependency is a rnpm plugin
|
||||
*/
|
||||
const isPlugin = (dependency) => !!~dependency.indexOf('rnpm-plugin-');
|
||||
const isPlugin = (dependency) => dependency.indexOf('rnpm-plugin-') === 0;
|
||||
|
||||
const findPluginInFolder = (folder) => {
|
||||
var pjson;
|
||||
|
|
|
@ -1,20 +1,11 @@
|
|||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const uniq = require('lodash').uniq;
|
||||
const flattenDeep = require('lodash').flattenDeep;
|
||||
const findPlugins = require('./findPlugins');
|
||||
|
||||
/**
|
||||
* @return {Array} Array of commands
|
||||
*/
|
||||
module.exports = function getCommands() {
|
||||
const rnpmRoot = path.join(__dirname, '..');
|
||||
const appRoot = process.cwd();
|
||||
|
||||
return uniq(
|
||||
flattenDeep([
|
||||
findPlugins([rnpmRoot]).map(require),
|
||||
findPlugins([appRoot]).map(name => require(path.join(appRoot, 'node_modules', name))),
|
||||
])
|
||||
, 'name');
|
||||
return findPlugins([appRoot]).map(name => require(path.join(appRoot, 'node_modules', name)));
|
||||
};
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
jest.autoMockOff();
|
||||
|
||||
const path = require('path');
|
||||
const mock = require('mock-require');
|
||||
const rewire = require('rewire');
|
||||
|
||||
const commands = require('./fixtures/commands');
|
||||
const isArray = (arg) =>
|
||||
Object.prototype.toString.call(arg) === '[object Array]';
|
||||
|
||||
/**
|
||||
* Paths to two possible `node_modules` locations `rnpm` can be installed
|
||||
*/
|
||||
const LOCAL_NODE_MODULES = path.join(process.cwd(), 'node_modules');
|
||||
const GLOBAL_NODE_MODULES = '/usr/local/lib/node_modules';
|
||||
|
||||
/**
|
||||
* Paths to `package.json` of project, and rnpm - in two installation locations
|
||||
*/
|
||||
const APP_JSON = path.join(process.cwd(), 'package.json');
|
||||
const GLOBAL_RNPM_PJSON = path.join(GLOBAL_NODE_MODULES, '/rnpm/package.json');
|
||||
const LOCAL_RNPM_PJSON = path.join(LOCAL_NODE_MODULES, 'rnpm/package.json');
|
||||
|
||||
/**
|
||||
* Sample `rnpm` plugin used in test cases
|
||||
*/
|
||||
const SAMPLE_RNPM_PLUGIN = 'rnpm-plugin-test';
|
||||
|
||||
/**
|
||||
* Sample `package.json` of RNPM that will be used in test cases
|
||||
*/
|
||||
const SAMPLE_RNPM_JSON = {
|
||||
dependencies: {
|
||||
[SAMPLE_RNPM_PLUGIN]: '*',
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Project without `rnpm` plugins defined
|
||||
*/
|
||||
const NO_PLUGINS_JSON = {
|
||||
dependencies: {},
|
||||
};
|
||||
|
||||
const getCommands = rewire('../src/getCommands');
|
||||
var revert;
|
||||
|
||||
describe('getCommands', () => {
|
||||
|
||||
afterEach(mock.stopAll);
|
||||
|
||||
describe('in all installations', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
revert = getCommands.__set__({
|
||||
__dirname: path.join(LOCAL_NODE_MODULES, 'rnpm/src'),
|
||||
});
|
||||
mock(APP_JSON, NO_PLUGINS_JSON);
|
||||
});
|
||||
|
||||
afterEach(() => revert());
|
||||
|
||||
it('list of the commands should be a non-empty array', () => {
|
||||
mock(APP_JSON, NO_PLUGINS_JSON);
|
||||
mock(LOCAL_RNPM_PJSON, SAMPLE_RNPM_JSON);
|
||||
mock(SAMPLE_RNPM_PLUGIN, commands.single);
|
||||
|
||||
expect(getCommands().length).not.toBe(0);
|
||||
expect(isArray(getCommands())).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should export one command', () => {
|
||||
mock(LOCAL_RNPM_PJSON, SAMPLE_RNPM_JSON);
|
||||
mock(SAMPLE_RNPM_PLUGIN, commands.single);
|
||||
|
||||
expect(getCommands().length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should export multiple commands', () => {
|
||||
mock(LOCAL_RNPM_PJSON, SAMPLE_RNPM_JSON);
|
||||
mock(SAMPLE_RNPM_PLUGIN, commands.multiple);
|
||||
|
||||
expect(getCommands().length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should export unique list of commands by name', () => {
|
||||
mock(LOCAL_RNPM_PJSON, {
|
||||
dependencies: {
|
||||
[SAMPLE_RNPM_PLUGIN]: '*',
|
||||
[`${SAMPLE_RNPM_PLUGIN}-2`]: '*',
|
||||
},
|
||||
});
|
||||
|
||||
mock(SAMPLE_RNPM_PLUGIN, commands.single);
|
||||
mock(`${SAMPLE_RNPM_PLUGIN}-2`, commands.single);
|
||||
|
||||
expect(getCommands().length).toEqual(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('project plugins', () => {
|
||||
/**
|
||||
* In this test suite we only test project plugins thus we make sure
|
||||
* `rnpm` package.json is properly mocked
|
||||
*/
|
||||
beforeEach(() => {
|
||||
mock(LOCAL_RNPM_PJSON, NO_PLUGINS_JSON);
|
||||
mock(GLOBAL_RNPM_PJSON, NO_PLUGINS_JSON);
|
||||
});
|
||||
|
||||
afterEach(() => revert());
|
||||
|
||||
it('should load when installed locally', () => {
|
||||
revert = getCommands.__set__({
|
||||
__dirname: path.join(LOCAL_NODE_MODULES, 'rnpm/src'),
|
||||
});
|
||||
|
||||
mock(APP_JSON, SAMPLE_RNPM_JSON);
|
||||
mock(
|
||||
path.join(LOCAL_NODE_MODULES, SAMPLE_RNPM_PLUGIN),
|
||||
commands.single
|
||||
);
|
||||
|
||||
expect(getCommands()[0]).toEqual(commands.single);
|
||||
});
|
||||
|
||||
it('should load when installed globally', () => {
|
||||
revert = getCommands.__set__({
|
||||
__dirname: path.join(GLOBAL_NODE_MODULES, 'rnpm/src'),
|
||||
});
|
||||
|
||||
mock(APP_JSON, SAMPLE_RNPM_JSON);
|
||||
mock(
|
||||
path.join(LOCAL_NODE_MODULES, SAMPLE_RNPM_PLUGIN),
|
||||
commands.single
|
||||
);
|
||||
|
||||
expect(getCommands()[0]).toEqual(commands.single);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('rnpm and project plugins', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
revert = getCommands.__set__({
|
||||
__dirname: path.join(LOCAL_NODE_MODULES, 'rnpm/src'),
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => revert());
|
||||
|
||||
it('should load concatenated list of plugins', () => {
|
||||
mock(APP_JSON, SAMPLE_RNPM_JSON);
|
||||
mock(LOCAL_RNPM_PJSON, {
|
||||
dependencies: {
|
||||
[`${SAMPLE_RNPM_PLUGIN}-2`]: '*',
|
||||
},
|
||||
});
|
||||
|
||||
mock(
|
||||
path.join(LOCAL_NODE_MODULES, SAMPLE_RNPM_PLUGIN),
|
||||
commands.multiple
|
||||
);
|
||||
mock(`${SAMPLE_RNPM_PLUGIN}-2`, commands.single);
|
||||
|
||||
expect(getCommands().length).toEqual(3);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
module.exports = [
|
||||
{
|
||||
func: require('./src/install'),
|
||||
description: 'Install and link native dependencies',
|
||||
name: 'install [packageName]',
|
||||
}, {
|
||||
func: require('./src/uninstall'),
|
||||
description: 'Uninstall and unlink native dependencies',
|
||||
name: 'uninstall [packageName]',
|
||||
},
|
||||
];
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
func: require('./src/install'),
|
||||
description: 'install and link native dependencies',
|
||||
name: 'install <packageName>',
|
||||
};
|
|
@ -7,7 +7,7 @@ const spawnOpts = {
|
|||
|
||||
log.heading = 'rnpm-install';
|
||||
|
||||
module.exports = function install(config, args, callback) {
|
||||
module.exports = function install(args, config) {
|
||||
const name = args[0];
|
||||
|
||||
var res = spawnSync('npm', ['install', name, '--save'], spawnOpts);
|
||||
|
|
|
@ -7,7 +7,7 @@ const spawnOpts = {
|
|||
|
||||
log.heading = 'rnpm-install';
|
||||
|
||||
module.exports = function install(config, args, callback) {
|
||||
module.exports = function install(args, config) {
|
||||
const name = args[0];
|
||||
|
||||
var res = spawnSync('rnpm', ['unlink', name], spawnOpts);
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
func: require('./src/uninstall'),
|
||||
description: 'uninstall and unlink native dependencies',
|
||||
name: 'uninstall <packageName>',
|
||||
};
|
|
@ -1,17 +1,19 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
const applyParams = require('../../../src/android/patches/applyParams');
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const applyParams = require('../../src/android/patches/applyParams');
|
||||
|
||||
describe('applyParams', () => {
|
||||
it('apply params to the string', () => {
|
||||
expect(
|
||||
applyParams('${foo}', {foo: 'foo'}, 'react-native')
|
||||
).to.be.equal('this.getResources().getString(R.strings.reactNative_foo)');
|
||||
).toEqual('this.getResources().getString(R.strings.reactNative_foo)');
|
||||
});
|
||||
|
||||
it('use null if no params provided', () => {
|
||||
expect(
|
||||
applyParams('${foo}', {}, 'react-native')
|
||||
).to.be.equal('null');
|
||||
).toEqual('null');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const path = require('path');
|
||||
const isInstalled = require('../../src/android/isInstalled');
|
||||
|
||||
const projectConfig = {
|
||||
buildGradlePath: path.join(__dirname, '../../__fixtures__/android/patchedBuild.gradle'),
|
||||
};
|
||||
|
||||
describe('android::isInstalled', () => {
|
||||
it('should return true when project is already in build.gradle', () =>
|
||||
expect(isInstalled(projectConfig, 'test')).toBeTruthy()
|
||||
);
|
||||
|
||||
it('should return false when project is not in build.gradle', () =>
|
||||
expect(isInstalled(projectConfig, 'test2')).toBeFalsy()
|
||||
);
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const makeBuildPatch = require('../../src/android/patches/makeBuildPatch');
|
||||
const name = 'test';
|
||||
|
||||
describe('makeBuildPatch', () => {
|
||||
it('should build a patch function', () => {
|
||||
expect(Object.prototype.toString(makeBuildPatch(name)))
|
||||
.toBe('[object Object]');
|
||||
});
|
||||
|
||||
it('should make a correct patch', () => {
|
||||
const {patch} = makeBuildPatch(name);
|
||||
expect(patch).toBe(` compile project(':${name}')\n`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const makeImportPatch = require('../../src/android/patches/makeImportPatch');
|
||||
|
||||
const packageImportPath = 'import some.example.project';
|
||||
|
||||
describe('makeImportPatch', () => {
|
||||
it('should build a patch', () => {
|
||||
expect(Object.prototype.toString(makeImportPatch(packageImportPath)))
|
||||
.toBe('[object Object]');
|
||||
});
|
||||
|
||||
it('MainActivity contains a correct import patch', () => {
|
||||
const {patch} = makeImportPatch(packageImportPath);
|
||||
|
||||
expect(patch).toBe('\n' + packageImportPath);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const makePackagePatch = require('../../src/android/patches/makePackagePatch');
|
||||
const applyParams = require('../../src/android/patches/applyParams');
|
||||
|
||||
const packageInstance = 'new SomeLibrary(${foo}, ${bar}, \'something\')';
|
||||
const name = 'some-library';
|
||||
const params = {
|
||||
foo: 'foo',
|
||||
bar: 'bar',
|
||||
};
|
||||
|
||||
describe('makePackagePatch@0.20', () => {
|
||||
it('should build a patch', () => {
|
||||
const packagePatch = makePackagePatch(packageInstance, params, name);
|
||||
expect(Object.prototype.toString(packagePatch))
|
||||
.toBe('[object Object]');
|
||||
});
|
||||
|
||||
it('MainActivity contains a correct 0.20 import patch', () => {
|
||||
const {patch} = makePackagePatch(packageInstance, params, name);
|
||||
const processedInstance = applyParams(packageInstance, params, name);
|
||||
|
||||
expect(patch).toBe(',\n ' + processedInstance);
|
||||
});
|
||||
});
|
|
@ -1,8 +1,9 @@
|
|||
const fs = require('fs');
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const path = require('path');
|
||||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
const makeSettingsPatch = require('../../../src/android/patches/makeSettingsPatch');
|
||||
const makeSettingsPatch = require('../../src/android/patches/makeSettingsPatch');
|
||||
|
||||
const name = 'test';
|
||||
const projectConfig = {
|
||||
|
@ -15,9 +16,9 @@ const dependencyConfig = {
|
|||
|
||||
describe('makeSettingsPatch', () => {
|
||||
it('should build a patch function', () => {
|
||||
expect(
|
||||
makeSettingsPatch(name, dependencyConfig, {}, projectConfig)
|
||||
).to.be.an('object');
|
||||
expect(Object.prototype.toString(
|
||||
makeSettingsPatch(name, dependencyConfig, projectConfig)
|
||||
)).toBe('[object Object]');
|
||||
});
|
||||
|
||||
it('should make a correct patch', () => {
|
||||
|
@ -26,8 +27,10 @@ describe('makeSettingsPatch', () => {
|
|||
dependencyConfig.sourceDir
|
||||
);
|
||||
|
||||
expect(makeSettingsPatch(name, dependencyConfig, projectConfig).patch)
|
||||
.to.be.equal(
|
||||
const {patch} = makeSettingsPatch(name, dependencyConfig, projectConfig);
|
||||
|
||||
expect(patch)
|
||||
.toBe(
|
||||
`include ':${name}'\n` +
|
||||
`project(':${name}').projectDir = ` +
|
||||
`new File(rootProject.projectDir, '${projectDir}')\n`
|
|
@ -1,5 +1,7 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const getDependencyConfig = require('../src/getDependencyConfig');
|
||||
const sinon = require('sinon');
|
||||
|
||||
|
@ -9,8 +11,8 @@ describe('getDependencyConfig', () => {
|
|||
getDependencyConfig: sinon.stub(),
|
||||
};
|
||||
|
||||
expect(getDependencyConfig(config, ['abcd'])).to.be.an.array;
|
||||
expect(config.getDependencyConfig.callCount).to.equals(1);
|
||||
expect(Array.isArray(getDependencyConfig(config, ['abcd']))).toBeTruthy();
|
||||
expect(config.getDependencyConfig.callCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should filter out invalid react-native projects', () => {
|
||||
|
@ -18,6 +20,6 @@ describe('getDependencyConfig', () => {
|
|||
getDependencyConfig: sinon.stub().throws(new Error('Cannot require')),
|
||||
};
|
||||
|
||||
expect(getDependencyConfig(config, ['abcd'])).to.deep.equal([]);
|
||||
expect(getDependencyConfig(config, ['abcd'])).toEqual([]);
|
||||
});
|
||||
});
|
|
@ -1,27 +1,23 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const getProjectDependencies = require('../src/getProjectDependencies');
|
||||
const mock = require('mock-require');
|
||||
const path = require('path');
|
||||
|
||||
describe('getProjectDependencies', () => {
|
||||
|
||||
it('should return an array of project dependencies', () => {
|
||||
mock(
|
||||
jest.setMock(
|
||||
path.join(process.cwd(), './package.json'),
|
||||
{ dependencies: { lodash: '^6.0.0', 'react-native': '^16.0.0' } }
|
||||
{ dependencies: { lodash: '^6.0.0', 'react-native': '^16.0.0' }}
|
||||
);
|
||||
|
||||
expect(getProjectDependencies()).to.deep.equals(['lodash']);
|
||||
expect(getProjectDependencies()).toEqual(['lodash']);
|
||||
});
|
||||
|
||||
it('should return an empty array when no dependencies set', () => {
|
||||
mock(path.join(process.cwd(), './package.json'), {});
|
||||
expect(getProjectDependencies()).to.deep.equals([]);
|
||||
jest.setMock(path.join(process.cwd(), './package.json'), {});
|
||||
expect(getProjectDependencies()).toEqual([]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.stopAll();
|
||||
});
|
||||
|
||||
});
|
|
@ -1,5 +1,7 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const groupFilesByType = require('../src/groupFilesByType');
|
||||
|
||||
describe('groupFilesByType', () => {
|
||||
|
@ -16,8 +18,8 @@ describe('groupFilesByType', () => {
|
|||
|
||||
const groupedFiles = groupFilesByType(fonts.concat(images));
|
||||
|
||||
expect(groupedFiles.font).to.deep.equal(fonts);
|
||||
expect(groupedFiles.image).to.deep.equal(images);
|
||||
expect(groupedFiles.font).toEqual(fonts);
|
||||
expect(groupedFiles.image).toEqual(images);
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const addFileToProject = require('../../src/ios/addFileToProject');
|
||||
const _ = require('lodash');
|
||||
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::addFileToProject', () => {
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
xit('should add file to a project', () => {
|
||||
expect(
|
||||
_.includes(
|
||||
Object.keys(project.pbxFileReferenceSection()),
|
||||
addFileToProject(project, '../../__fixtures__/linearGradient.pbxproj').fileRef
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,14 +1,18 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const PbxFile = require('xcode/lib/pbxFile');
|
||||
const addProjectToLibraries = require('../../src/ios/addProjectToLibraries');
|
||||
const last = require('lodash').last;
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::addProjectToLibraries', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
@ -21,8 +25,7 @@ describe('ios::addProjectToLibraries', () => {
|
|||
|
||||
const child = last(libraries.children);
|
||||
|
||||
expect(child).to.have.keys(['value', 'comment']);
|
||||
expect(child.comment).to.equals(file.basename);
|
||||
expect((['value', 'comment']), child).toBeTruthy();
|
||||
expect(child.comment).toBe(file.basename);
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const addSharedLibraries = require('../../src/ios/addSharedLibraries');
|
||||
const getGroup = require('../../src/ios/getGroup');
|
||||
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::addSharedLibraries', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should automatically create Frameworks group', () => {
|
||||
expect(getGroup(project, 'Frameworks')).toBeNull();
|
||||
addSharedLibraries(project, ['libz.tbd']);
|
||||
expect(getGroup(project, 'Frameworks')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should add shared libraries to project', () => {
|
||||
addSharedLibraries(project, ['libz.tbd']);
|
||||
|
||||
const frameworksGroup = getGroup(project, 'Frameworks');
|
||||
expect(frameworksGroup.children.length).toEqual(1);
|
||||
expect(frameworksGroup.children[0].comment).toEqual('libz.tbd');
|
||||
|
||||
addSharedLibraries(project, ['MessageUI.framework']);
|
||||
expect(frameworksGroup.children.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should not add duplicate libraries to project', () => {
|
||||
addSharedLibraries(project, ['libz.tbd']);
|
||||
addSharedLibraries(project, ['libz.tbd']);
|
||||
|
||||
const frameworksGroup = getGroup(project, 'Frameworks');
|
||||
expect(frameworksGroup.children.length).toEqual(1);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,21 +1,25 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const createGroup = require('../../src/ios/createGroup');
|
||||
const getGroup = require('../../src/ios/getGroup');
|
||||
const last = require('lodash').last;
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::createGroup', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should create a group with given name', () => {
|
||||
const createdGroup = createGroup(project, 'Resources');
|
||||
expect(createdGroup.name).to.equals('Resources');
|
||||
expect(createdGroup.name).toBe('Resources');
|
||||
});
|
||||
|
||||
it('should attach group to main project group', () => {
|
||||
|
@ -24,7 +28,7 @@ describe('ios::createGroup', () => {
|
|||
|
||||
expect(
|
||||
last(mainGroup.children).comment
|
||||
).to.equals(createdGroup.name);
|
||||
).toBe(createdGroup.name);
|
||||
});
|
||||
|
||||
it('should create a nested group with given path', () => {
|
||||
|
@ -33,7 +37,7 @@ describe('ios::createGroup', () => {
|
|||
|
||||
expect(
|
||||
last(outerGroup.children).comment
|
||||
).to.equals(createdGroup.name);
|
||||
).toBe(createdGroup.name);
|
||||
});
|
||||
|
||||
it('should-not create already created groups', () => {
|
||||
|
@ -42,8 +46,11 @@ describe('ios::createGroup', () => {
|
|||
const mainGroup = getGroup(project);
|
||||
|
||||
expect(
|
||||
mainGroup.children.filter(group => group.comment === 'Libraries').length
|
||||
).to.equals(1);
|
||||
expect(last(outerGroup.children).comment).to.equals(createdGroup.name);
|
||||
mainGroup
|
||||
.children
|
||||
.filter(group => group.comment === 'Libraries')
|
||||
.length
|
||||
).toBe(1);
|
||||
expect(last(outerGroup.children).comment).toBe(createdGroup.name);
|
||||
});
|
||||
});
|
|
@ -1,19 +1,22 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const getBuildProperty = require('../../src/ios/getBuildProperty');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::getBuildProperty', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should return build property from main target', () => {
|
||||
const plistPath = getBuildProperty(project, 'INFOPLIST_FILE');
|
||||
expect(plistPath).to.equals('"Basic/Info.plist"');
|
||||
expect(plistPath).toEqual('"Basic/Info.plist"');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,9 +1,14 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const getGroup = require('../../src/ios/getGroup');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::getGroup', () => {
|
||||
beforeEach(() => {
|
||||
|
@ -12,25 +17,25 @@ describe('ios::getGroup', () => {
|
|||
|
||||
it('should return a top-level group', () => {
|
||||
const group = getGroup(project, 'Libraries');
|
||||
expect(group.children.length > 0).to.be.true; // our test top-level Libraries has children
|
||||
expect(group.name).to.equals('Libraries');
|
||||
expect(group.children.length > 0).toBeTruthy();
|
||||
expect(group.name).toBe('Libraries');
|
||||
});
|
||||
|
||||
it('should return nested group when specified', () => {
|
||||
const group = getGroup(project, 'NestedGroup/Libraries');
|
||||
expect(group.children.length).to.equals(0); // our test nested Libraries is empty
|
||||
expect(group.name).to.equals('Libraries');
|
||||
expect(group.children.length).toBe(0); // our test nested Libraries is empty
|
||||
expect(group.name).toBe('Libraries');
|
||||
});
|
||||
|
||||
it('should return null when no group found', () => {
|
||||
const group = getGroup(project, 'I-Dont-Exist');
|
||||
expect(group).to.be.null;
|
||||
expect(group).toBeNull();
|
||||
});
|
||||
|
||||
it('should return top-level group when name not specified', () => {
|
||||
const mainGroupId = project.getFirstProject().firstProject.mainGroup;
|
||||
const mainGroup = project.getPBXGroupByKey(mainGroupId);
|
||||
const group = getGroup(project);
|
||||
expect(group).to.equals(mainGroup);
|
||||
expect(group).toEqual(mainGroup);
|
||||
});
|
||||
});
|
|
@ -1,12 +1,13 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const getHeaderSearchPath = require('../../src/ios/getHeaderSearchPath');
|
||||
const path = require('path');
|
||||
|
||||
const SRC_DIR = path.join('react-native-project', 'ios');
|
||||
|
||||
describe('ios::getHeaderSearchPath', () => {
|
||||
|
||||
/**
|
||||
* See https://github.com/Microsoft/react-native-code-push
|
||||
*/
|
||||
|
@ -18,7 +19,7 @@ describe('ios::getHeaderSearchPath', () => {
|
|||
|
||||
const searchPath = getHeaderSearchPath(SRC_DIR, files);
|
||||
|
||||
expect(searchPath).to.equal(
|
||||
expect(searchPath).toBe(
|
||||
`"${['$(SRCROOT)', '..', 'node_modules', 'package'].join(path.sep)}"`
|
||||
);
|
||||
});
|
||||
|
@ -34,7 +35,7 @@ describe('ios::getHeaderSearchPath', () => {
|
|||
|
||||
const searchPath = getHeaderSearchPath(SRC_DIR, files);
|
||||
|
||||
expect(searchPath).to.equal(
|
||||
expect(searchPath).toBe(
|
||||
`"${['$(SRCROOT)', '..', 'node_modules', 'package', 'src'].join(path.sep)}/**"`
|
||||
);
|
||||
});
|
||||
|
@ -51,7 +52,7 @@ describe('ios::getHeaderSearchPath', () => {
|
|||
|
||||
const searchPath = getHeaderSearchPath(SRC_DIR, files);
|
||||
|
||||
expect(searchPath).to.equal(
|
||||
expect(searchPath).toBe(
|
||||
`"${['$(SRCROOT)', '..', 'node_modules', 'package', 'src'].join(path.sep)}/**"`
|
||||
);
|
||||
});
|
|
@ -1,27 +1,27 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const getHeadersInFolder = require('../../src/ios/getHeadersInFolder');
|
||||
const mock = require('mock-fs');
|
||||
|
||||
describe('ios::getHeadersInFolder', () => {
|
||||
|
||||
it('should return an array of all headers in given folder', () => {
|
||||
mock({
|
||||
xit('should return an array of all headers in given folder', () => {
|
||||
jest.setMock({
|
||||
'FileA.h': '',
|
||||
'FileB.h': '',
|
||||
});
|
||||
|
||||
const foundHeaders = getHeadersInFolder(process.cwd());
|
||||
|
||||
expect(foundHeaders.length).to.equals(2);
|
||||
expect(foundHeaders.length).toBe(2);
|
||||
|
||||
getHeadersInFolder(process.cwd()).forEach(headerPath => {
|
||||
expect(headerPath).to.contain(process.cwd());
|
||||
});
|
||||
});
|
||||
|
||||
it('should ignore all headers in Pods, Examples & node_modules', () => {
|
||||
mock({
|
||||
xit('should ignore all headers in Pods, Examples & node_modules', () => {
|
||||
jest.setMock({
|
||||
'FileA.h': '',
|
||||
'FileB.h': '',
|
||||
Pods: {
|
||||
|
@ -37,9 +37,4 @@ describe('ios::getHeadersInFolder', () => {
|
|||
|
||||
expect(getHeadersInFolder(process.cwd()).length).to.equals(2);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
});
|
|
@ -1,23 +1,24 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const getPlist = require('../../src/ios/getPlist');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::getPlist', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should return null when `.plist` file missing', () => {
|
||||
const plistPath = getPlist(project, process.cwd());
|
||||
expect(plistPath).to.equals(null);
|
||||
});
|
||||
|
||||
it.skip('should return parsed `plist`', () => {
|
||||
// @todo mock fs here
|
||||
expect(plistPath).toBeNull();
|
||||
});
|
||||
|
||||
// @todo - Happy scenario
|
||||
});
|
|
@ -1,19 +1,22 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const getPlistPath = require('../../src/ios/getPlistPath');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::getPlistPath', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should return path without Xcode $(SRCROOT)', () => {
|
||||
const plistPath = getPlistPath(project, '/');
|
||||
expect(plistPath).to.equals('/Basic/Info.plist');
|
||||
expect(plistPath).toBe('/Basic/Info.plist');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,20 +1,23 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const getProducts = require('../../src/ios/getProducts');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/linearGradient.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::getProducts', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should return an array of static libraries project exports', () => {
|
||||
const products = getProducts(project);
|
||||
expect(products.length).to.equals(1);
|
||||
expect(products).to.contains('libBVLinearGradient.a');
|
||||
expect(products.length).toBe(1);
|
||||
expect(products).toContain('libRCTActionSheet.a');
|
||||
});
|
||||
|
||||
});
|
|
@ -1,24 +1,27 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const hasLibraryImported = require('../../src/ios/hasLibraryImported');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::hasLibraryImported', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should return true if project has been already imported', () => {
|
||||
const libraries = project.pbxGroupByName('Libraries');
|
||||
expect(hasLibraryImported(libraries, 'React.xcodeproj')).to.be.true;
|
||||
expect(hasLibraryImported(libraries, 'React.xcodeproj')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false if project is not imported', () => {
|
||||
const libraries = project.pbxGroupByName('Libraries');
|
||||
expect(hasLibraryImported(libraries, 'ACME.xcodeproj')).to.be.false;
|
||||
expect(hasLibraryImported(libraries, 'ACME.xcodeproj')).toBeFalsy();
|
||||
});
|
||||
|
||||
});
|
|
@ -1,39 +1,29 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
const mock = require('mock-fs');
|
||||
const fs = require('fs');
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const path = require('path');
|
||||
const isInstalled = require('../../src/ios/isInstalled');
|
||||
|
||||
const baseProjectConfig = {
|
||||
pbxprojPath: 'project.pbxproj',
|
||||
pbxprojPath: path.join(__dirname, '../../__fixtures__/project.pbxproj'),
|
||||
libraryFolder: 'Libraries',
|
||||
};
|
||||
|
||||
describe('ios::isInstalled', () => {
|
||||
|
||||
before(() => {
|
||||
mock({
|
||||
'project.pbxproj': fs.readFileSync(path.join(__dirname, '../fixtures/project.pbxproj')),
|
||||
});
|
||||
});
|
||||
|
||||
it('should return true when .xcodeproj in Libraries', () => {
|
||||
const dependencyConfig = { projectName: 'React.xcodeproj' };
|
||||
expect(isInstalled(baseProjectConfig, dependencyConfig)).to.be.true;
|
||||
expect(isInstalled(baseProjectConfig, dependencyConfig)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return false when .xcodeproj not in Libraries', () => {
|
||||
const dependencyConfig = { projectName: 'Missing.xcodeproj' };
|
||||
expect(isInstalled(baseProjectConfig, dependencyConfig)).to.be.false;
|
||||
expect(isInstalled(baseProjectConfig, dependencyConfig)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false when `LibraryFolder` is missing', () => {
|
||||
const dependencyConfig = { projectName: 'React.xcodeproj' };
|
||||
const projectConfig = Object.assign({}, baseProjectConfig, { libraryFolder: 'Missing' });
|
||||
expect(isInstalled(projectConfig, dependencyConfig)).to.be.false;
|
||||
expect(isInstalled(projectConfig, dependencyConfig)).toBeFalsy();
|
||||
});
|
||||
|
||||
after(mock.restore);
|
||||
|
||||
});
|
|
@ -1,23 +1,24 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const mapHeaderSearchPaths = require('../../src/ios/mapHeaderSearchPaths');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
const reactPath = '"$(SRCROOT)/../node_modules/react-native/React/**"';
|
||||
|
||||
describe('ios::mapHeaderSearchPaths', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
});
|
||||
|
||||
it('should iterate over headers with `react` added only', () => {
|
||||
const path = '../../node_modules/path-to-module/**';
|
||||
|
||||
mapHeaderSearchPaths(project, paths => {
|
||||
expect(paths.find(path => path.indexOf(reactPath))).to.be.not.empty;
|
||||
expect(paths.find(p => p.indexOf(reactPath))).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -1,15 +1,19 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const PbxFile = require('xcode/lib/pbxFile');
|
||||
const addProjectToLibraries = require('../../src/ios/addProjectToLibraries');
|
||||
const removeProjectFromLibraries = require('../../src/ios/removeProjectFromLibraries');
|
||||
const last = require('lodash').last;
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::removeProjectFromLibraries', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
|
||||
|
@ -27,7 +31,6 @@ describe('ios::removeProjectFromLibraries', () => {
|
|||
|
||||
const child = last(libraries.children);
|
||||
|
||||
expect(child.comment).to.not.equals(file.basename);
|
||||
expect(child.comment).not.toBe(file.basename);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,32 +1,36 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const pbxFile = require('xcode/lib/pbxFile');
|
||||
const addFileToProject = require('../../src/ios/addFileToProject');
|
||||
const removeProjectFromProject = require('../../src/ios/removeProjectFromProject');
|
||||
const path = require('path');
|
||||
|
||||
const project = xcode.project('test/fixtures/project.pbxproj');
|
||||
const filePath = '../fixtures/linearGradient.pbxproj';
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
const filePath = '../../__fixtures__/linearGradient.pbxproj';
|
||||
|
||||
describe('ios::addFileToProject', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
addFileToProject(project, filePath);
|
||||
});
|
||||
|
||||
it('should return removed file', () => {
|
||||
expect(removeProjectFromProject(project, filePath)).to.be.instanceof(pbxFile);
|
||||
expect(removeProjectFromProject(project, filePath) instanceof pbxFile)
|
||||
.toBeTruthy();
|
||||
});
|
||||
|
||||
it('should remove file from a project', () => {
|
||||
const file = removeProjectFromProject(project, filePath);
|
||||
expect(project.pbxFileReferenceSection()).to.not.include.keys(file.fileRef);
|
||||
expect(project.pbxFileReferenceSection()[file.fileRef]).not.toBeDefined();
|
||||
});
|
||||
|
||||
it.skip('should remove file from PBXContainerProxy', () => {
|
||||
xit('should remove file from PBXContainerProxy', () => {
|
||||
// todo(mike): add in .xcodeproj after Xcode modifications so we can test extra
|
||||
// removals later.
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const xcode = require('xcode');
|
||||
const path = require('path');
|
||||
const addSharedLibraries = require('../../src/ios/addSharedLibraries');
|
||||
const removeSharedLibraries = require('../../src/ios/removeSharedLibraries');
|
||||
const getGroup = require('../../src/ios/getGroup');
|
||||
|
||||
const project = xcode.project(
|
||||
path.join(__dirname, '../../__fixtures__/project.pbxproj')
|
||||
);
|
||||
|
||||
describe('ios::removeSharedLibraries', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
project.parseSync();
|
||||
addSharedLibraries(project, ['libc++.tbd', 'libz.tbd']);
|
||||
});
|
||||
|
||||
it('should remove only the specified shared library', () => {
|
||||
removeSharedLibraries(project, ['libc++.tbd']);
|
||||
|
||||
const frameworksGroup = getGroup(project, 'Frameworks');
|
||||
expect(frameworksGroup.children.length).toEqual(1);
|
||||
expect(frameworksGroup.children[0].comment).toEqual('libz.tbd');
|
||||
});
|
||||
|
||||
it('should ignore missing shared libraries', () => {
|
||||
removeSharedLibraries(project, ['libxml2.tbd']);
|
||||
|
||||
const frameworksGroup = getGroup(project, 'Frameworks');
|
||||
expect(frameworksGroup.children.length).toEqual(2);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,18 +1,15 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const sinon = require('sinon');
|
||||
const mock = require('mock-require');
|
||||
const log = require('npmlog');
|
||||
const path = require('path');
|
||||
|
||||
const link = require('../src/link');
|
||||
|
||||
log.level = 'silent';
|
||||
|
||||
describe('link', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
delete require.cache[require.resolve('../src/link')];
|
||||
log.level = 'silent';
|
||||
});
|
||||
|
||||
it('should reject when run in a folder without package.json', (done) => {
|
||||
|
@ -22,7 +19,8 @@ describe('link', () => {
|
|||
},
|
||||
};
|
||||
|
||||
link(config).catch(() => done());
|
||||
const link = require('../src/link');
|
||||
link([], config).catch(() => done());
|
||||
});
|
||||
|
||||
it('should accept a name of a dependency to link', (done) => {
|
||||
|
@ -31,10 +29,11 @@ describe('link', () => {
|
|||
getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }),
|
||||
};
|
||||
|
||||
link(config, ['react-native-gradient']).then(() => {
|
||||
const link = require('../src/link');
|
||||
link(['react-native-gradient'], config).then(() => {
|
||||
expect(
|
||||
config.getDependencyConfig.calledWith('react-native-gradient')
|
||||
).to.be.true;
|
||||
).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -45,7 +44,7 @@ describe('link', () => {
|
|||
getDependencyConfig: sinon.stub().returns({ assets: [], commands: {} }),
|
||||
};
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
path.join(process.cwd(), 'package.json'),
|
||||
{
|
||||
dependencies: {
|
||||
|
@ -54,10 +53,11 @@ describe('link', () => {
|
|||
}
|
||||
);
|
||||
|
||||
link(config, []).then(() => {
|
||||
const link = require('../src/link');
|
||||
link([], config).then(() => {
|
||||
expect(
|
||||
config.getDependencyConfig.calledWith('react-native-test')
|
||||
).to.be.true;
|
||||
).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -70,30 +70,30 @@ describe('link', () => {
|
|||
getDependencyConfig: sinon.stub().returns(dependencyConfig),
|
||||
};
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/android/isInstalled.js',
|
||||
sinon.stub().returns(false)
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/android/registerNativeModule.js',
|
||||
registerNativeModule
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/isInstalled.js',
|
||||
sinon.stub().returns(false)
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/registerNativeModule.js',
|
||||
registerNativeModule
|
||||
);
|
||||
|
||||
const link = require('../src/link');
|
||||
|
||||
link(config, ['react-native-blur']).then(() => {
|
||||
expect(registerNativeModule.calledTwice).to.be.true;
|
||||
link(['react-native-blur'], config).then(() => {
|
||||
expect(registerNativeModule.calledTwice).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -106,30 +106,30 @@ describe('link', () => {
|
|||
getDependencyConfig: sinon.stub().returns(dependencyConfig),
|
||||
};
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/isInstalled.js',
|
||||
sinon.stub().returns(true)
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/android/isInstalled.js',
|
||||
sinon.stub().returns(true)
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/registerNativeModule.js',
|
||||
registerNativeModule
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/android/registerNativeModule.js',
|
||||
registerNativeModule
|
||||
);
|
||||
|
||||
const link = require('../src/link');
|
||||
|
||||
link(config, ['react-native-blur']).then(() => {
|
||||
expect(registerNativeModule.callCount).to.equal(0);
|
||||
link(['react-native-blur'], config).then(() => {
|
||||
expect(registerNativeModule.callCount).toEqual(0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -139,12 +139,12 @@ describe('link', () => {
|
|||
const prelink = sinon.stub().yieldsAsync();
|
||||
const postlink = sinon.stub().yieldsAsync();
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/registerNativeModule.js',
|
||||
registerNativeModule
|
||||
);
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/isInstalled.js',
|
||||
sinon.stub().returns(false)
|
||||
);
|
||||
|
@ -158,9 +158,9 @@ describe('link', () => {
|
|||
|
||||
const link = require('../src/link');
|
||||
|
||||
link(config, ['react-native-blur']).then(() => {
|
||||
expect(prelink.calledBefore(registerNativeModule)).to.be.true;
|
||||
expect(postlink.calledAfter(registerNativeModule)).to.be.true;
|
||||
link(['react-native-blur'], config).then(() => {
|
||||
expect(prelink.calledBefore(registerNativeModule)).toBeTruthy();
|
||||
expect(postlink.calledAfter(registerNativeModule)).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -171,7 +171,7 @@ describe('link', () => {
|
|||
const projectAssets = ['Fonts/FontC.ttf'];
|
||||
const copyAssets = sinon.stub();
|
||||
|
||||
mock(
|
||||
jest.setMock(
|
||||
'../src/ios/copyAssets.js',
|
||||
copyAssets
|
||||
);
|
||||
|
@ -183,17 +183,12 @@ describe('link', () => {
|
|||
|
||||
const link = require('../src/link');
|
||||
|
||||
link(config, ['react-native-blur']).then(() => {
|
||||
expect(copyAssets.calledOnce).to.be.true;
|
||||
expect(copyAssets.getCall(0).args[0]).to.deep.equals(
|
||||
link(['react-native-blur'], config).then(() => {
|
||||
expect(copyAssets.calledOnce).toBeTruthy();
|
||||
expect(copyAssets.getCall(0).args[0]).toEqual(
|
||||
projectAssets.concat(dependencyAssets)
|
||||
);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.stopAll();
|
||||
});
|
||||
|
||||
});
|
|
@ -1,5 +1,7 @@
|
|||
const chai = require('chai');
|
||||
const expect = chai.expect;
|
||||
'use strict';
|
||||
|
||||
jest.autoMockOff();
|
||||
|
||||
const sinon = require('sinon');
|
||||
const promiseWaterfall = require('../src/promiseWaterfall');
|
||||
|
||||
|
@ -9,7 +11,7 @@ describe('promiseWaterfall', () => {
|
|||
const tasks = [sinon.stub(), sinon.stub()];
|
||||
|
||||
promiseWaterfall(tasks).then(() => {
|
||||
expect(tasks[0].calledBefore(tasks[1])).to.be.true;
|
||||
expect(tasks[0].calledBefore(tasks[1])).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -18,7 +20,7 @@ describe('promiseWaterfall', () => {
|
|||
const tasks = [sinon.stub().returns(1), sinon.stub().returns(2)];
|
||||
|
||||
promiseWaterfall(tasks).then(value => {
|
||||
expect(value).to.equal(2);
|
||||
expect(value).toEqual(2);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -28,8 +30,8 @@ describe('promiseWaterfall', () => {
|
|||
const tasks = [sinon.stub().throws(error), sinon.stub().returns(2)];
|
||||
|
||||
promiseWaterfall(tasks).catch(err => {
|
||||
expect(err).to.equal(error);
|
||||
expect(tasks[1].callCount).to.equal(0);
|
||||
expect(err).toEqual(error);
|
||||
expect(tasks[1].callCount).toEqual(0);
|
||||
done();
|
||||
});
|
||||
});
|
|
@ -1,9 +0,0 @@
|
|||
module.exports = [{
|
||||
func: require('./src/link'),
|
||||
description: 'Links all native dependencies',
|
||||
name: 'link [packageName]',
|
||||
}, {
|
||||
func: require('./src/unlink'),
|
||||
description: 'Unlink native dependency',
|
||||
name: 'unlink <packageName>',
|
||||
}];
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = {
|
||||
func: require('./src/link'),
|
||||
description: 'links all native dependencies',
|
||||
name: 'link [packageName]',
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
const semver = require('semver');
|
||||
const versions = ['0.20', '0.18', '0.17'];
|
||||
|
||||
module.exports = function getPrefix(rnVersion) {
|
||||
const version = rnVersion.replace(/-.*/, '');
|
||||
var prefix = 'patches/0.20';
|
||||
|
||||
versions.forEach((item, i) => {
|
||||
const nextVersion = versions[i + 1];
|
||||
if (semver.lt(version, item + '.0') && nextVersion) {
|
||||
prefix = `patches/${nextVersion}`;
|
||||
}
|
||||
});
|
||||
|
||||
return prefix;
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
const fs = require('fs');
|
||||
const makeBuildPatch = require(`./patches/makeBuildPatch`);
|
||||
const makeBuildPatch = require('./patches/makeBuildPatch');
|
||||
|
||||
module.exports = function isInstalled(config, name) {
|
||||
return fs
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = function makeImportPatch(packageImportPath) {
|
||||
return {
|
||||
pattern: 'import android.app.Activity;',
|
||||
patch: '\n' + packageImportPath,
|
||||
};
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
const applyParams = require('../applyParams');
|
||||
|
||||
module.exports = function makePackagePatch(packageInstance, params, prefix) {
|
||||
const processedInstance = applyParams(packageInstance, params, prefix);
|
||||
|
||||
return {
|
||||
pattern: '.addPackage(new MainReactPackage())',
|
||||
patch: `\n .addPackage(${processedInstance})`,
|
||||
};
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
module.exports = function makeImportPatch(packageImportPath) {
|
||||
return {
|
||||
pattern: 'import com.facebook.react.ReactActivity;',
|
||||
patch: '\n' + packageImportPath,
|
||||
};
|
||||
};
|
|
@ -1,10 +0,0 @@
|
|||
const applyParams = require('../applyParams');
|
||||
|
||||
module.exports = function makePackagePatch(packageInstance, params, prefix) {
|
||||
const processedInstance = applyParams(packageInstance, params, prefix);
|
||||
|
||||
return {
|
||||
pattern: 'new MainReactPackage()',
|
||||
patch: ',\n ' + processedInstance,
|
||||
};
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
const applyParams = require('../applyParams');
|
||||
const applyParams = require('./applyParams');
|
||||
|
||||
module.exports = function makePackagePatch(packageInstance, params, prefix) {
|
||||
const processedInstance = applyParams(packageInstance, params, prefix);
|
|
@ -1,11 +1,9 @@
|
|||
const fs = require('fs');
|
||||
const getReactVersion = require('../getReactNativeVersion');
|
||||
const getPrefix = require('./getPrefix');
|
||||
|
||||
const applyPatch = require('./patches/applyPatch');
|
||||
const makeStringsPatch = require('./patches/makeStringsPatch');
|
||||
const makeSettingsPatch = require(`./patches/makeSettingsPatch`);
|
||||
const makeBuildPatch = require(`./patches/makeBuildPatch`);
|
||||
const makeSettingsPatch = require('./patches/makeSettingsPatch');
|
||||
const makeBuildPatch = require('./patches/makeBuildPatch');
|
||||
const makeImportPatch = require('./patches/makeImportPatch');
|
||||
const makePackagePatch = require('./patches/makePackagePatch');
|
||||
|
||||
module.exports = function registerNativeAndroidModule(
|
||||
name,
|
||||
|
@ -14,9 +12,6 @@ module.exports = function registerNativeAndroidModule(
|
|||
projectConfig
|
||||
) {
|
||||
const buildPatch = makeBuildPatch(name);
|
||||
const prefix = getPrefix(getReactVersion(projectConfig.folder));
|
||||
const makeImportPatch = require(`./${prefix}/makeImportPatch`);
|
||||
const makePackagePatch = require(`./${prefix}/makePackagePatch`);
|
||||
|
||||
applyPatch(
|
||||
projectConfig.settingsGradlePath,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const fs = require('fs');
|
||||
const getReactVersion = require('../getReactNativeVersion');
|
||||
const getPrefix = require('./getPrefix');
|
||||
const toCamelCase = require('lodash').camelCase;
|
||||
|
||||
const revokePatch = require('./patches/revokePatch');
|
||||
const makeSettingsPatch = require('./patches/makeSettingsPatch');
|
||||
const makeBuildPatch = require('./patches/makeBuildPatch');
|
||||
const makeStringsPatch = require('./patches/makeStringsPatch');
|
||||
const makeImportPatch = require('./patches/makeImportPatch');
|
||||
const makePackagePatch = require('./patches/makePackagePatch');
|
||||
|
||||
module.exports = function unregisterNativeAndroidModule(
|
||||
name,
|
||||
|
@ -14,9 +14,6 @@ module.exports = function unregisterNativeAndroidModule(
|
|||
projectConfig
|
||||
) {
|
||||
const buildPatch = makeBuildPatch(name);
|
||||
const prefix = getPrefix(getReactVersion(projectConfig.folder));
|
||||
const makeImportPatch = require(`./${prefix}/makeImportPatch`);
|
||||
const makePackagePatch = require(`./${prefix}/makePackagePatch`);
|
||||
const strings = fs.readFileSync(projectConfig.stringsPath, 'utf8');
|
||||
var params = {};
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
const path = require('path');
|
||||
|
||||
module.exports = (folder) => require(
|
||||
path.join(folder, 'node_modules', 'react-native', 'package.json')
|
||||
).version;
|
|
@ -1,3 +1,16 @@
|
|||
module.exports = function addSharedLibraries(project, libraries) {
|
||||
const createGroupWithMessage = require('./createGroupWithMessage');
|
||||
|
||||
module.exports = function addSharedLibraries(project, libraries) {
|
||||
if (!libraries.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a Frameworks group if necessary.
|
||||
createGroupWithMessage(project, 'Frameworks');
|
||||
|
||||
const target = project.getFirstTarget().uuid;
|
||||
|
||||
for (var name of libraries) {
|
||||
project.addFramework(name, { target });
|
||||
}
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue