mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96ac277cca | ||
|
|
7a32f77f73 | ||
|
|
9864c3a0df | ||
|
|
e3c81fa5ee | ||
|
|
cadc727854 | ||
|
|
a738b5157e | ||
|
|
34294a1c7c | ||
|
|
15238fb139 | ||
|
|
f9b78d111a | ||
|
|
73b24acf4c | ||
|
|
1e5c46df87 | ||
|
|
b957ea4d17 | ||
|
|
4a0b201334 | ||
|
|
5c6c7a2b40 | ||
|
|
86cbaedb7a | ||
|
|
f5bdd52ddc | ||
|
|
07a970195d | ||
|
|
c5d1ae0144 | ||
|
|
a6d0f27ecf | ||
|
|
9958afbcec |
@@ -2,8 +2,6 @@ Thanks for submitting a pull request! Please provide enough information so that
|
||||
|
||||
> **Unless you are a React Native release maintainer and cherry-picking an *existing* commit into a current release, ensure your pull request is targeting the `master` React Native branch.**
|
||||
|
||||
(You can skip this if you're fixing a typo or adding an app to the Showcase.)
|
||||
|
||||
Explain the **motivation** for making this change. What existing problem does the pull request solve?
|
||||
|
||||
Prefer **small pull requests**. These are much easier to review and more likely to get merged. Make sure the PR does only one thing, otherwise please split it.
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ The core team will be monitoring for pull requests. When we get one, we'll run s
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. **Describe your test plan in your commit.** If you've added code that should be tested, add tests!
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. If you've updated the docs, verify the website locally and submit screenshots if applicable
|
||||
4. If you've updated the docs, verify the website locally and submit screenshots if applicable.
|
||||
|
||||
```
|
||||
$ cd website
|
||||
|
||||
@@ -400,14 +400,14 @@ var TextExample = React.createClass({
|
||||
Demo text shadow
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
<UIExplorerBlock title="Line break mode">
|
||||
<UIExplorerBlock title="Ellipsize mode">
|
||||
<Text numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the end.
|
||||
</Text>
|
||||
<Text lineBreakMode="middle" numberOfLines={1}>
|
||||
<Text ellipsizeMode="middle" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the middle.
|
||||
</Text>
|
||||
<Text lineBreakMode="head" numberOfLines={1}>
|
||||
<Text ellipsizeMode="head" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the beginning.
|
||||
</Text>
|
||||
</UIExplorerBlock>
|
||||
|
||||
@@ -445,20 +445,20 @@ exports.examples = [
|
||||
);
|
||||
},
|
||||
}, {
|
||||
title: 'Line break mode',
|
||||
title: 'Ellipsize mode',
|
||||
render: function() {
|
||||
return (
|
||||
<View>
|
||||
<Text numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the end.
|
||||
</Text>
|
||||
<Text lineBreakMode="middle" numberOfLines={1}>
|
||||
<Text ellipsizeMode="middle" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the middle.
|
||||
</Text>
|
||||
<Text lineBreakMode="head" numberOfLines={1}>
|
||||
<Text ellipsizeMode="head" numberOfLines={1}>
|
||||
This very long text should be truncated with dots in the beginning.
|
||||
</Text>
|
||||
<Text lineBreakMode="clip" numberOfLines={1}>
|
||||
<Text ellipsizeMode="clip" numberOfLines={1}>
|
||||
This very looooooooooooooooooooooooooooong text should be clipped.
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -86,6 +86,11 @@ RCT_EXPORT_MODULE()
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:_decodedImageCache];
|
||||
}
|
||||
|
||||
- (float)handlerPriority
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (id<RCTImageURLLoader>)imageURLLoaderForURL:(NSURL *)URL
|
||||
{
|
||||
if (!_maxConcurrentLoadingTasks) {
|
||||
|
||||
@@ -24,7 +24,7 @@ extern NSString *const RCTReactTagAttributeName;
|
||||
@property (nonatomic, assign) CGFloat letterSpacing;
|
||||
@property (nonatomic, assign) CGFloat lineHeight;
|
||||
@property (nonatomic, assign) NSUInteger numberOfLines;
|
||||
@property (nonatomic, assign) NSLineBreakMode lineBreakMode;
|
||||
@property (nonatomic, assign) NSLineBreakMode ellipsizeMode;
|
||||
@property (nonatomic, assign) CGSize shadowOffset;
|
||||
@property (nonatomic, assign) NSTextAlignment textAlign;
|
||||
@property (nonatomic, assign) NSWritingDirection writingDirection;
|
||||
|
||||
@@ -190,7 +190,7 @@ static CSSSize RCTMeasure(void *context, float width, CSSMeasureMode widthMode,
|
||||
textContainer.lineFragmentPadding = 0.0;
|
||||
|
||||
if (_numberOfLines > 0) {
|
||||
textContainer.lineBreakMode = _lineBreakMode;
|
||||
textContainer.lineBreakMode = _ellipsizeMode;
|
||||
} else {
|
||||
textContainer.lineBreakMode = NSLineBreakByClipping;
|
||||
}
|
||||
@@ -470,7 +470,7 @@ RCT_TEXT_PROPERTY(IsHighlighted, _isHighlighted, BOOL)
|
||||
RCT_TEXT_PROPERTY(LetterSpacing, _letterSpacing, CGFloat)
|
||||
RCT_TEXT_PROPERTY(LineHeight, _lineHeight, CGFloat)
|
||||
RCT_TEXT_PROPERTY(NumberOfLines, _numberOfLines, NSUInteger)
|
||||
RCT_TEXT_PROPERTY(LineBreakMode, _lineBreakMode, NSLineBreakMode)
|
||||
RCT_TEXT_PROPERTY(EllipsizeMode, _ellipsizeMode, NSLineBreakMode)
|
||||
RCT_TEXT_PROPERTY(TextAlign, _textAlign, NSTextAlignment)
|
||||
RCT_TEXT_PROPERTY(TextDecorationColor, _textDecorationColor, UIColor *);
|
||||
RCT_TEXT_PROPERTY(TextDecorationLine, _textDecorationLine, RCTTextDecorationLineType);
|
||||
|
||||
@@ -64,7 +64,7 @@ RCT_EXPORT_SHADOW_PROPERTY(isHighlighted, BOOL)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(letterSpacing, CGFloat)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(lineHeight, CGFloat)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(numberOfLines, NSUInteger)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(lineBreakMode, NSLineBreakMode)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(ellipsizeMode, NSLineBreakMode)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textAlign, NSTextAlignment)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textDecorationStyle, NSUnderlineStyle)
|
||||
RCT_EXPORT_SHADOW_PROPERTY(textDecorationColor, UIColor)
|
||||
|
||||
@@ -29,7 +29,7 @@ const viewConfig = {
|
||||
validAttributes: merge(ReactNativeViewAttributes.UIView, {
|
||||
isHighlighted: true,
|
||||
numberOfLines: true,
|
||||
lineBreakMode: true,
|
||||
ellipsizeMode: true,
|
||||
allowFontScaling: true,
|
||||
selectable: true,
|
||||
}),
|
||||
@@ -90,7 +90,7 @@ const viewConfig = {
|
||||
const Text = React.createClass({
|
||||
propTypes: {
|
||||
/**
|
||||
* Line Break mode. This can be one of the following values:
|
||||
* This can be one of the following values:
|
||||
*
|
||||
* - `head` - The line is displayed so that the end fits in the container and the missing text
|
||||
* at the beginning of the line is indicated by an ellipsis glyph. e.g., "...wxyz"
|
||||
@@ -106,13 +106,13 @@ const Text = React.createClass({
|
||||
*
|
||||
* > `clip` is working only for iOS
|
||||
*/
|
||||
lineBreakMode: React.PropTypes.oneOf(['head', 'middle', 'tail', 'clip']),
|
||||
ellipsizeMode: React.PropTypes.oneOf(['head', 'middle', 'tail', 'clip']),
|
||||
/**
|
||||
* Used to truncate the text with an ellipsis after computing the text
|
||||
* layout, including line wrapping, such that the total number of lines
|
||||
* does not exceed this number.
|
||||
*
|
||||
* This prop is commonly used with `lineBreakMode`.
|
||||
* This prop is commonly used with `ellipsizeMode`.
|
||||
*/
|
||||
numberOfLines: React.PropTypes.number,
|
||||
/**
|
||||
@@ -172,7 +172,7 @@ const Text = React.createClass({
|
||||
return {
|
||||
accessible: true,
|
||||
allowFontScaling: true,
|
||||
lineBreakMode: 'tail',
|
||||
ellipsizeMode: 'tail',
|
||||
};
|
||||
},
|
||||
getInitialState: function(): Object {
|
||||
|
||||
+8
-2
@@ -4,7 +4,7 @@ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "React"
|
||||
s.version = package['version']
|
||||
s.version = "0.31.0"
|
||||
s.summary = package['description']
|
||||
s.description = <<-DESC
|
||||
React Native apps are built using the React JS
|
||||
@@ -29,8 +29,9 @@ Pod::Spec.new do |s|
|
||||
s.preserve_paths = "cli.js", "Libraries/**/*.js", "lint", "linter.js", "node_modules", "package.json", "packager", "PATENTS", "react-native-cli"
|
||||
|
||||
s.subspec 'Core' do |ss|
|
||||
ss.dependency 'React/CSSLayout'
|
||||
ss.source_files = "React/**/*.{c,h,m,mm,S}"
|
||||
ss.exclude_files = "**/__tests__/*", "IntegrationTests/*"
|
||||
ss.exclude_files = "**/__tests__/*", "IntegrationTests/*", "React/CSSLayout/*"
|
||||
ss.frameworks = "JavaScriptCore"
|
||||
ss.libraries = "stdc++"
|
||||
ss.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++14" }
|
||||
@@ -42,6 +43,11 @@ Pod::Spec.new do |s|
|
||||
ss.preserve_paths = "Libraries/ART/**/*.js"
|
||||
end
|
||||
|
||||
s.subspec 'CSSLayout' do |ss|
|
||||
ss.source_files = "React/CSSLayout/**/*.{c,h}"
|
||||
ss.header_mappings_dir = "React"
|
||||
end
|
||||
|
||||
s.subspec 'RCTActionSheet' do |ss|
|
||||
ss.dependency 'React/Core'
|
||||
ss.source_files = "Libraries/ActionSheetIOS/*.{h,m}"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
VERSION_NAME=1000.0.0-master
|
||||
VERSION_NAME=0.31.0
|
||||
GROUP=com.facebook.react
|
||||
|
||||
POM_NAME=ReactNative
|
||||
|
||||
@@ -283,7 +283,7 @@ public class ReactContext extends ContextWrapper {
|
||||
* DO NOT HOLD LONG-LIVED REFERENCES TO THE OBJECT RETURNED BY THIS METHOD, AS THIS WILL CAUSE
|
||||
* MEMORY LEAKS.
|
||||
*/
|
||||
/* package */ @Nullable Activity getCurrentActivity() {
|
||||
public @Nullable Activity getCurrentActivity() {
|
||||
if (mCurrentActivity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class ViewProps {
|
||||
public static final String LINE_HEIGHT = "lineHeight";
|
||||
public static final String NEEDS_OFFSCREEN_ALPHA_COMPOSITING = "needsOffscreenAlphaCompositing";
|
||||
public static final String NUMBER_OF_LINES = "numberOfLines";
|
||||
public static final String LINE_BREAK_MODE = "lineBreakMode";
|
||||
public static final String LINE_BREAK_MODE = "ellipsizeMode";
|
||||
public static final String ON = "on";
|
||||
public static final String RESIZE_MODE = "resizeMode";
|
||||
public static final String TEXT_ALIGN = "textAlign";
|
||||
|
||||
@@ -74,16 +74,16 @@ public class ReactTextViewManager extends BaseViewManager<ReactTextView, ReactTe
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.LINE_BREAK_MODE)
|
||||
public void setLineBreakMode(ReactTextView view, @Nullable String lineBreakMode) {
|
||||
if(lineBreakMode == null) {
|
||||
public void setLineBreakMode(ReactTextView view, @Nullable String ellipsizeMode) {
|
||||
if(ellipsizeMode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lineBreakMode.equals("head")) {
|
||||
if (ellipsizeMode.equals("head")) {
|
||||
view.setEllipsize(TextUtils.TruncateAt.START);
|
||||
} else if (lineBreakMode.equals("middle")) {
|
||||
} else if (ellipsizeMode.equals("middle")) {
|
||||
view.setEllipsize(TextUtils.TruncateAt.MIDDLE);
|
||||
} else if (lineBreakMode.equals("tail")) {
|
||||
} else if (ellipsizeMode.equals("tail")) {
|
||||
view.setEllipsize(TextUtils.TruncateAt.END);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -94,14 +94,14 @@ The debugger will receive a list of all project roots, separated by a space. For
|
||||
|
||||
### Debugging with [Stetho](http://facebook.github.io/stetho/) on Android
|
||||
|
||||
1. In ```android/app/build.gradle``` , add
|
||||
1. In ```android/app/build.gradle```, add these lines in the `dependencies` section:
|
||||
|
||||
```gradle
|
||||
compile 'com.facebook.stetho:stetho:1.3.1'
|
||||
compile 'com.facebook.stetho:stetho-okhttp3:1.3.1'
|
||||
```
|
||||
|
||||
2. In ```android/app/src/main/java/com/{yourAppName}/MainApplication.java```, add the following imports :
|
||||
2. In ```android/app/src/main/java/com/{yourAppName}/MainApplication.java```, add the following imports:
|
||||
|
||||
```java
|
||||
import com.facebook.react.modules.network.ReactCookieJarContainer;
|
||||
|
||||
@@ -31,11 +31,12 @@ import React, { Component } from 'react';
|
||||
import { View, Text } from 'react-native';
|
||||
|
||||
export default class MyScene extends Component {
|
||||
getDefaultProps() {
|
||||
return {
|
||||
title: 'MyScene'
|
||||
};
|
||||
}
|
||||
static propTypes = {
|
||||
title: React.PropTypes.string,
|
||||
};
|
||||
static defaultProps = {
|
||||
title: 'MyScene',
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
|
||||
@@ -19,4 +19,6 @@ global.__fbBatchedBridgeConfig = {
|
||||
global.Promise = require('promise');
|
||||
global.regeneratorRuntime = require.requireActual('regenerator-runtime/runtime');
|
||||
|
||||
jest.mock('npmlog');
|
||||
|
||||
jest.setMock('ErrorUtils', require('ErrorUtils'));
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
+115
-137
@@ -5,171 +5,149 @@
|
||||
* 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} ${this.usage()}`))),
|
||||
` ${this._description}`,
|
||||
'',
|
||||
` ${chalk.bold('Options:')}`,
|
||||
'',
|
||||
this.optionHelp().replace(/^/gm, ' '),
|
||||
'',
|
||||
];
|
||||
|
||||
if (this.examples && this.examples.length > 0) {
|
||||
const formattedUsage = this.examples.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,
|
||||
})
|
||||
.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);
|
||||
cmd.examples = command.examples;
|
||||
|
||||
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.split(' ')[0] === 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,
|
||||
};
|
||||
|
||||
+1
-1
@@ -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({
|
||||
+1
-1
@@ -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', () => {
|
||||
|
||||
+1
-1
@@ -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', () => {
|
||||
|
||||
+1
-1
@@ -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', () => {
|
||||
+1
-1
@@ -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({
|
||||
+1
-1
@@ -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', () => {
|
||||
|
||||
+1
-1
@@ -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
-2
@@ -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', () => {
|
||||
+11
-1
@@ -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);
|
||||
});
|
||||
@@ -31,7 +31,7 @@ exports.getProjectConfig = function getProjectConfig() {
|
||||
exports.getDependencyConfig = function getDependencyConfig(packageName) {
|
||||
const folder = path.join(process.cwd(), 'node_modules', packageName);
|
||||
const rnpm = getRNPMConfig(
|
||||
path.join(process.cwd(), 'node_modules', packageName.split('/')[0])
|
||||
path.join(process.cwd(), 'node_modules', packageName)
|
||||
);
|
||||
|
||||
return Object.assign({}, rnpm, {
|
||||
|
||||
@@ -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,13 +8,29 @@ 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 isRNPMPlugin = (dependency) => dependency.indexOf('rnpm-plugin-') === 0;
|
||||
const isReactNativePlugin = (dependency) => dependency.indexOf('react-native-') === 0;
|
||||
|
||||
const readPackage = (folder) => {
|
||||
try {
|
||||
return require(path.join(folder, 'package.json'));
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const findPluginsInReactNativePackage = (pjson) => {
|
||||
if (!pjson.rnpm || !pjson.rnpm.plugin) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return path.join(pjson.name, pjson.rnpm.plugin);
|
||||
};
|
||||
|
||||
const findPluginInFolder = (folder) => {
|
||||
var pjson;
|
||||
try {
|
||||
pjson = require(path.join(folder, 'package.json'));
|
||||
} catch (e) {
|
||||
const pjson = readPackage(folder);
|
||||
|
||||
if (!pjson) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -24,7 +39,22 @@ const findPluginInFolder = (folder) => {
|
||||
Object.keys(pjson.devDependencies || {})
|
||||
);
|
||||
|
||||
return deps.filter(isPlugin);
|
||||
return deps.reduce(
|
||||
(acc, pkg) => {
|
||||
if (isRNPMPlugin(pkg)) {
|
||||
return acc.concat(pkg);
|
||||
}
|
||||
if (isReactNativePlugin(pkg)) {
|
||||
const pkgJson = readPackage(path.join(folder, 'node_modules', pkg));
|
||||
if (!pkgJson) {
|
||||
return acc;
|
||||
}
|
||||
return acc.concat(findPluginsInReactNativePackage(pkgJson));
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
[]
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const uniq = require('lodash').uniq;
|
||||
const flattenDeep = require('lodash').flattenDeep;
|
||||
const findPlugins = require('./findPlugins');
|
||||
const flatten = require('lodash').flatten;
|
||||
|
||||
/**
|
||||
* @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');
|
||||
const plugins = findPlugins([appRoot]).map(name => require(path.join(appRoot, 'node_modules', name)));
|
||||
return flatten(plugins);
|
||||
};
|
||||
|
||||
@@ -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>',
|
||||
};
|
||||
+7
-5
@@ -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);
|
||||
});
|
||||
});
|
||||
+12
-9
@@ -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`
|
||||
+7
-5
@@ -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([]);
|
||||
});
|
||||
});
|
||||
+9
-13
@@ -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();
|
||||
});
|
||||
|
||||
});
|
||||
+6
-4
@@ -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();
|
||||
});
|
||||
});
|
||||
+10
-7
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
+17
-10
@@ -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);
|
||||
});
|
||||
});
|
||||
+9
-6
@@ -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"');
|
||||
});
|
||||
|
||||
});
|
||||
+14
-9
@@ -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);
|
||||
});
|
||||
});
|
||||
+7
-6
@@ -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)}/**"`
|
||||
);
|
||||
});
|
||||
+9
-14
@@ -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();
|
||||
});
|
||||
|
||||
});
|
||||
+10
-9
@@ -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
|
||||
});
|
||||
+9
-6
@@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
+10
-7
@@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
+10
-7
@@ -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();
|
||||
});
|
||||
|
||||
});
|
||||
+8
-18
@@ -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);
|
||||
|
||||
});
|
||||
+9
-8
@@ -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();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
+9
-6
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
+13
-9
@@ -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.
|
||||
});
|
||||
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user