-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Add Share module #5904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Share module #5904
Changes from all commits
a76c6c0
424a665
5da16c7
8c3bece
1f5f0c0
fb5f6ea
f21d709
8917788
767f914
de58c94
68804ca
fb88c94
9917041
72c6d50
2678aee
32847bb
0371750
dfe1f63
772523e
43209dc
74e6966
dc7fdaa
7f39ae3
08c29bd
375ee94
851c4ea
4d6add8
e398fd9
71a67fb
4351eec
92a793b
68ca817
d3e13ed
ae290f0
918aaf6
f4d7d3a
29b5e3b
db99ac4
d0f6fb8
bc14456
a404f49
9c896e5
de1ab8f
5127f30
0834fc7
994cda0
2b52ff5
dc1c57c
94023f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/** | ||
* The examples provided by Facebook are for non-commercial testing and | ||
* evaluation purposes only. | ||
* | ||
* Facebook reserves all rights not expressly granted. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | ||
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | ||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
* | ||
* @flow | ||
*/ | ||
'use strict'; | ||
|
||
var React = require('react'); | ||
var ReactNative = require('react-native'); | ||
var { | ||
StyleSheet, | ||
View, | ||
Text, | ||
TouchableHighlight, | ||
Share, | ||
} = ReactNative; | ||
|
||
exports.framework = 'React'; | ||
exports.title = 'Share'; | ||
exports.description = 'Share data with other Apps.'; | ||
exports.examples = [{ | ||
title: 'Share Text Content', | ||
render() { | ||
return <ShareMessageExample />; | ||
} | ||
}]; | ||
|
||
class ShareMessageExample extends React.Component { | ||
_shareMessage: Function; | ||
_shareText: Function; | ||
_showResult: Function; | ||
state: any; | ||
|
||
constructor(props) { | ||
super(props); | ||
|
||
this._shareMessage = this._shareMessage.bind(this); | ||
this._shareText = this._shareText.bind(this); | ||
this._showResult = this._showResult.bind(this); | ||
|
||
this.state = { | ||
result: '' | ||
}; | ||
} | ||
|
||
render() { | ||
return ( | ||
<View> | ||
<TouchableHighlight style={styles.wrapper} | ||
onPress={this._shareMessage}> | ||
<View style={styles.button}> | ||
<Text>Click to share message</Text> | ||
</View> | ||
</TouchableHighlight> | ||
<TouchableHighlight style={styles.wrapper} | ||
onPress={this._shareText}> | ||
<View style={styles.button}> | ||
<Text>Click to share message, URL and title</Text> | ||
</View> | ||
</TouchableHighlight> | ||
<Text>{this.state.result}</Text> | ||
</View> | ||
); | ||
} | ||
|
||
_shareMessage() { | ||
Share.share({ | ||
message: 'React Native | A framework for building native apps using React' | ||
}) | ||
.then(this._showResult) | ||
.catch((error) => this.setState({result: 'error: ' + error.message})); | ||
} | ||
|
||
_shareText() { | ||
Share.share({ | ||
message: 'A framework for building native apps using React', | ||
url: 'http://facebook.github.io/react-native/', | ||
title: 'React Native' | ||
}, { | ||
dialogTitle: 'Share React Native website', | ||
excludedActivityTypes: [ | ||
'com.apple.UIKit.activity.PostToTwitter' | ||
], | ||
tintColor: 'green' | ||
}) | ||
.then(this._showResult) | ||
.catch((error) => this.setState({result: 'error: ' + error.message})); | ||
} | ||
|
||
_showResult(result) { | ||
if (result.action === Share.sharedAction) { | ||
if (result.activityType) { | ||
this.setState({result: 'shared with an activityType: ' + result.activityType}); | ||
} else { | ||
this.setState({result: 'shared'}); | ||
} | ||
} else if (result.action === Share.dismissedAction) { | ||
this.setState({result: 'dismissed'}); | ||
} | ||
} | ||
|
||
} | ||
|
||
|
||
var styles = StyleSheet.create({ | ||
wrapper: { | ||
borderRadius: 5, | ||
marginBottom: 5, | ||
}, | ||
button: { | ||
backgroundColor: '#eeeeee', | ||
padding: 10, | ||
}, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
/** | ||
* Copyright (c) 2016-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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-trailing-spaces: Trailing spaces not allowed. |
||
* of patent rights can be found in the PATENTS file in the same directory. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-trailing-spaces: Trailing spaces not allowed. |
||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-trailing-spaces: Trailing spaces not allowed. |
||
* @providesModule Share | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-trailing-spaces: Trailing spaces not allowed. |
||
* @flow | ||
*/ | ||
'use strict'; | ||
|
||
const Platform = require('Platform'); | ||
const { | ||
ActionSheetManager, | ||
ShareModule | ||
} = require('NativeModules'); | ||
const invariant = require('fbjs/lib/invariant'); | ||
const processColor = require('processColor'); | ||
|
||
type Content = { title?: string, message: string } | { title?: string, url: string }; | ||
type Options = { dialogTitle?: string, excludeActivityTypes?: Array<string>, tintColor?: string }; | ||
|
||
class Share { | ||
|
||
/** | ||
* Open a dialog to share text content. | ||
* | ||
* In iOS, Returns a Promise which will be invoked an object containing `action`, `activityType`. | ||
* If the user dismissed the dialog, the Promise will still be resolved with action being `Share.dismissedAction` | ||
* and all the other keys being undefined. | ||
* | ||
* In Android, Returns a Promise which always be resolved with action being `Share.sharedAction`. | ||
* | ||
* ### Content | ||
* | ||
* - `message` - a message to share | ||
* - `title` - title of the message | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Potentially unsafe get/set usage Getters and setters with side effects are potentially unsafe and disabled by default. You may opt-in to using them anyway by putting |
||
* | ||
* #### iOS | ||
* | ||
* - `url` - an URL to share | ||
* | ||
* At least one of URL and message is required. | ||
* | ||
* ### Options | ||
* | ||
* #### iOS | ||
* | ||
* - `excludedActivityTypes` | ||
* - `tintColor` | ||
* | ||
* #### Android | ||
* | ||
* - `dialogTitle` | ||
* | ||
*/ | ||
static share(content: Content, options: Options = {}): Promise<Object> { | ||
invariant( | ||
typeof content === 'object' && content !== null, | ||
'Content must a valid object' | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no-trailing-spaces: Trailing spaces not allowed. |
||
invariant( | ||
typeof content.url === 'string' || typeof content.message === 'string', | ||
'At least one of URL and message is required' | ||
); | ||
invariant( | ||
typeof options === 'object' && options !== null, | ||
'Options must be a valid object' | ||
); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this invariant should go under |
||
|
||
if (Platform.OS === 'android') { | ||
invariant( | ||
!content.title || typeof content.title === 'string', | ||
'Invalid title: title should be a string.' | ||
); | ||
return ShareModule.share(content, options.dialogTitle); | ||
} else if (Platform.OS === 'ios') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we skip this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @grabbou this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok - then probably something to remember for other files :) thanks. |
||
return new Promise((resolve, reject) => { | ||
ActionSheetManager.showShareActionSheetWithOptions( | ||
{...content, ...options, tintColor: processColor(options.tintColor)}, | ||
(error) => reject(error), | ||
(success, activityType) => { | ||
if (success) { | ||
resolve({ | ||
'action': 'sharedAction', | ||
'activityType': activityType | ||
}); | ||
} else { | ||
resolve({ | ||
'action': 'dismissedAction' | ||
}); | ||
} | ||
} | ||
); | ||
}); | ||
} else { | ||
return Promise.reject(new Error('Unsupported platform')); | ||
} | ||
} | ||
|
||
/** | ||
* The content was successfully shared. | ||
*/ | ||
static get sharedAction() { return 'sharedAction'; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's just have plain strings instead of constants. |
||
|
||
/** | ||
* The dialog has been dismissed. | ||
* @platform ios | ||
*/ | ||
static get dismissedAction() { return 'dismissedAction'; } | ||
|
||
} | ||
|
||
module.exports = Share; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/** | ||
* Copyright (c) 2014-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. | ||
*/ | ||
|
||
package com.facebook.react.tests; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import android.app.Activity; | ||
import android.app.AlertDialog; | ||
import android.app.Instrumentation.ActivityMonitor; | ||
import android.content.DialogInterface; | ||
import android.content.Intent; | ||
import android.content.IntentFilter; | ||
import android.content.IntentFilter.MalformedMimeTypeException; | ||
import android.support.v4.app.DialogFragment; | ||
|
||
import com.facebook.react.bridge.BaseJavaModule; | ||
import com.facebook.react.testing.ReactInstanceSpecForTest; | ||
import com.facebook.react.bridge.ReactMethod; | ||
import com.facebook.react.bridge.JavaScriptModule; | ||
import com.facebook.react.bridge.WritableMap; | ||
import com.facebook.react.bridge.WritableNativeMap; | ||
import com.facebook.react.modules.share.ShareModule; | ||
import com.facebook.react.testing.ReactAppInstrumentationTestCase; | ||
|
||
/** | ||
* Test case for {@link ShareModule}. | ||
*/ | ||
public class ShareTestCase extends ReactAppInstrumentationTestCase { | ||
|
||
private static interface ShareTestModule extends JavaScriptModule { | ||
public void showShareDialog(WritableMap content, WritableMap options); | ||
} | ||
|
||
private static class ShareRecordingModule extends BaseJavaModule { | ||
|
||
private int mOpened = 0; | ||
private int mErrors = 0; | ||
|
||
@Override | ||
public String getName() { | ||
return "ShareRecordingModule"; | ||
} | ||
|
||
@ReactMethod | ||
public void recordOpened() { | ||
mOpened++; | ||
} | ||
|
||
@ReactMethod | ||
public void recordError() { | ||
mErrors++; | ||
} | ||
|
||
public int getOpened() { | ||
return mOpened; | ||
} | ||
|
||
public int getErrors() { | ||
return mErrors; | ||
} | ||
|
||
} | ||
|
||
final ShareRecordingModule mRecordingModule = new ShareRecordingModule(); | ||
|
||
@Override | ||
protected ReactInstanceSpecForTest createReactInstanceSpecForTest() { | ||
return super.createReactInstanceSpecForTest() | ||
.addNativeModule(mRecordingModule) | ||
.addJSModule(ShareTestModule.class); | ||
} | ||
|
||
@Override | ||
protected String getReactApplicationKeyUnderTest() { | ||
return "ShareTestApp"; | ||
} | ||
|
||
private ShareTestModule getTestModule() { | ||
return getReactContext().getCatalystInstance().getJSModule(ShareTestModule.class); | ||
} | ||
|
||
public void testShowBasicShareDialog() { | ||
final WritableMap content = new WritableNativeMap(); | ||
content.putString("message", "Hello, ReactNative!"); | ||
final WritableMap options = new WritableNativeMap(); | ||
|
||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_CHOOSER); | ||
intentFilter.addCategory(Intent.CATEGORY_DEFAULT); | ||
ActivityMonitor monitor = getInstrumentation().addMonitor(intentFilter, null, true); | ||
|
||
getTestModule().showShareDialog(content, options); | ||
|
||
waitForBridgeAndUIIdle(); | ||
getInstrumentation().waitForIdleSync(); | ||
|
||
assertEquals(1, monitor.getHits()); | ||
assertEquals(1, mRecordingModule.getOpened()); | ||
assertEquals(0, mRecordingModule.getErrors()); | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright (c) 2013-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. | ||
* | ||
* @providesModule ShareTestModule | ||
*/ | ||
|
||
'use strict'; | ||
|
||
var BatchedBridge = require('BatchedBridge'); | ||
var React = require('React'); | ||
var RecordingModule = require('NativeModules').ShareRecordingModule; | ||
var Share = require('Share'); | ||
var View = require('View'); | ||
|
||
var ShareTestApp = React.createClass({ | ||
render: function() { | ||
return (<View />); | ||
}, | ||
}); | ||
|
||
var ShareTestModule = { | ||
ShareTestApp: ShareTestApp, | ||
showShareDialog: function(content, options) { | ||
Share.share(content, options).then( | ||
() => RecordingModule.recordOpened(), | ||
({code, message}) => RecordingModule.recordError() | ||
); | ||
}, | ||
}; | ||
|
||
BatchedBridge.registerCallableModule( | ||
'ShareTestModule', | ||
ShareTestModule | ||
); | ||
|
||
module.exports = ShareTestModule; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
include_defs('//ReactAndroid/DEFS') | ||
|
||
android_library( | ||
name = 'share', | ||
srcs = glob(['**/*.java']), | ||
deps = [ | ||
react_native_target('java/com/facebook/react/bridge:bridge'), | ||
react_native_target('java/com/facebook/react/common:common'), | ||
react_native_dep('libraries/fbcore/src/main/java/com/facebook/common/logging:logging'), | ||
react_native_dep('third-party/java/infer-annotations:infer-annotations'), | ||
react_native_dep('third-party/java/jsr-305:jsr-305'), | ||
], | ||
visibility = [ | ||
'PUBLIC', | ||
], | ||
) | ||
|
||
project_config( | ||
src_target = ':share', | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/** | ||
* Copyright (c) 2016-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. | ||
*/ | ||
|
||
package com.facebook.react.modules.share; | ||
|
||
import android.app.Activity; | ||
import android.content.Intent; | ||
import android.net.Uri; | ||
|
||
import com.facebook.react.bridge.Arguments; | ||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException; | ||
import com.facebook.react.bridge.Promise; | ||
import com.facebook.react.bridge.ReactApplicationContext; | ||
import com.facebook.react.bridge.ReactContextBaseJavaModule; | ||
import com.facebook.react.bridge.ReactMethod; | ||
import com.facebook.react.bridge.ReadableMap; | ||
import com.facebook.react.bridge.WritableMap; | ||
import com.facebook.react.common.ReactConstants; | ||
|
||
/** | ||
* Intent module. Launch other activities or open URLs. | ||
*/ | ||
public class ShareModule extends ReactContextBaseJavaModule { | ||
|
||
/* package */ static final String ACTION_SHARED = "sharedAction"; | ||
/* package */ static final String ERROR_INVALID_CONTENT = "E_INVALID_CONTENT"; | ||
/* package */ static final String ERROR_UNABLE_TO_OPEN_DIALOG = "E_UNABLE_TO_OPEN_DIALOG"; | ||
|
||
public ShareModule(ReactApplicationContext reactContext) { | ||
super(reactContext); | ||
} | ||
|
||
@Override | ||
public String getName() { | ||
return "ShareModule"; | ||
} | ||
|
||
/** | ||
* Open a chooser dialog to send text content to other apps. | ||
* | ||
* Refer http://developer.android.com/intl/ko/training/sharing/send.html | ||
* | ||
* @param content the data to send | ||
* @param dialogTitle the title of the chooser dialog | ||
*/ | ||
@ReactMethod | ||
public void share(ReadableMap content, String dialogTitle, Promise promise) { | ||
if (content == null) { | ||
promise.reject(ERROR_INVALID_CONTENT, "Content cannot be null"); | ||
return; | ||
} | ||
|
||
try { | ||
Intent intent = new Intent(Intent.ACTION_SEND); | ||
intent.setTypeAndNormalize("text/plain"); | ||
|
||
if (content.hasKey("title")) { | ||
intent.putExtra(Intent.EXTRA_SUBJECT, content.getString("title")); | ||
} | ||
|
||
if (content.hasKey("message")) { | ||
intent.putExtra(Intent.EXTRA_TEXT, content.getString("message")); | ||
} | ||
|
||
Intent chooser = Intent.createChooser(intent, dialogTitle); | ||
chooser.addCategory(Intent.CATEGORY_DEFAULT); | ||
|
||
Activity currentActivity = getCurrentActivity(); | ||
if (currentActivity != null) { | ||
currentActivity.startActivity(chooser); | ||
} else { | ||
getReactApplicationContext().startActivity(chooser); | ||
} | ||
WritableMap result = Arguments.createMap(); | ||
result.putString("action", ACTION_SHARED); | ||
promise.resolve(result); | ||
|
||
} catch (Exception e) { | ||
promise.reject(ERROR_UNABLE_TO_OPEN_DIALOG, "Failed to open share dialog"); | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
/** | ||
* 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. | ||
*/ | ||
|
||
package com.facebook.react.modules.share; | ||
|
||
import android.app.Activity; | ||
import android.content.Intent; | ||
|
||
import com.facebook.react.bridge.Arguments; | ||
import com.facebook.react.bridge.Promise; | ||
import com.facebook.react.bridge.ReactApplicationContext; | ||
import com.facebook.react.bridge.ReactTestHelper; | ||
import com.facebook.react.bridge.JavaOnlyMap; | ||
|
||
import javax.annotation.Nullable; | ||
|
||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.junit.Rule; | ||
import org.junit.runner.RunWith; | ||
import org.mockito.Mockito; | ||
import org.mockito.invocation.InvocationOnMock; | ||
import org.mockito.stubbing.Answer; | ||
import org.powermock.api.mockito.PowerMockito; | ||
import org.powermock.core.classloader.annotations.PrepareForTest; | ||
import org.powermock.core.classloader.annotations.PowerMockIgnore; | ||
import org.powermock.modules.junit4.rule.PowerMockRule; | ||
import org.robolectric.internal.ShadowExtractor; | ||
import org.robolectric.Robolectric; | ||
import org.robolectric.RobolectricTestRunner; | ||
import org.robolectric.RuntimeEnvironment; | ||
import org.robolectric.shadows.ShadowApplication; | ||
|
||
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertNotNull; | ||
|
||
@PrepareForTest({Arguments.class}) | ||
@RunWith(RobolectricTestRunner.class) | ||
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*"}) | ||
public class ShareModuleTest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! Mind also adding a test that verifies we reject incorrect calls? |
||
|
||
private Activity mActivity; | ||
private ShareModule mShareModule; | ||
|
||
@Rule | ||
public PowerMockRule rule = new PowerMockRule(); | ||
|
||
@Before | ||
public void prepareModules() throws Exception { | ||
PowerMockito.mockStatic(Arguments.class); | ||
Mockito.when(Arguments.createMap()).thenAnswer(new Answer<Object>() { | ||
@Override | ||
public Object answer(InvocationOnMock invocation) throws Throwable { | ||
return new JavaOnlyMap(); | ||
} | ||
}); | ||
|
||
mShareModule = new ShareModule(ReactTestHelper.createCatalystContextForTest()); | ||
} | ||
|
||
@After | ||
public void cleanUp() { | ||
mActivity = null; | ||
mShareModule = null; | ||
} | ||
|
||
@Test | ||
public void testShareDialog() { | ||
final String title = "Title"; | ||
final String message = "Message"; | ||
final String dialogTitle = "Dialog Title"; | ||
|
||
JavaOnlyMap content = new JavaOnlyMap(); | ||
content.putString("title", title); | ||
content.putString("message", message); | ||
|
||
final SimplePromise promise = new SimplePromise(); | ||
|
||
mShareModule.share(content, dialogTitle, promise); | ||
|
||
final Intent chooserIntent = | ||
((ShadowApplication)ShadowExtractor.extract(RuntimeEnvironment.application)).getNextStartedActivity(); | ||
assertNotNull("Dialog was not displayed", chooserIntent); | ||
assertEquals(Intent.ACTION_CHOOSER, chooserIntent.getAction()); | ||
assertEquals(dialogTitle, chooserIntent.getExtras().get(Intent.EXTRA_TITLE)); | ||
|
||
final Intent contentIntent = (Intent)chooserIntent.getExtras().get(Intent.EXTRA_INTENT); | ||
assertNotNull("Intent was not built correctly", contentIntent); | ||
assertEquals(Intent.ACTION_SEND, contentIntent.getAction()); | ||
assertEquals(title, contentIntent.getExtras().get(Intent.EXTRA_SUBJECT)); | ||
assertEquals(message, contentIntent.getExtras().get(Intent.EXTRA_TEXT)); | ||
|
||
assertEquals(1, promise.getResolved()); | ||
} | ||
|
||
@Test | ||
public void testInvalidContent() { | ||
final String dialogTitle = "Dialog Title"; | ||
|
||
final SimplePromise promise = new SimplePromise(); | ||
|
||
mShareModule.share(null, dialogTitle, promise); | ||
|
||
assertEquals(1, promise.getRejected()); | ||
assertEquals(ShareModule.ERROR_INVALID_CONTENT, promise.getErrorCode()); | ||
} | ||
|
||
final static class SimplePromise implements Promise { | ||
private static final String DEFAULT_ERROR = "EUNSPECIFIED"; | ||
|
||
private int mResolved; | ||
private int mRejected; | ||
private Object mValue; | ||
private String mErrorCode; | ||
private String mErrorMessage; | ||
|
||
public int getResolved() { | ||
return mResolved; | ||
} | ||
|
||
public int getRejected() { | ||
return mRejected; | ||
} | ||
|
||
public Object getValue() { | ||
return mValue; | ||
} | ||
|
||
public String getErrorCode() { | ||
return mErrorCode; | ||
} | ||
|
||
public String getErrorMessage() { | ||
return mErrorMessage; | ||
} | ||
|
||
@Override | ||
public void resolve(Object value) { | ||
mResolved++; | ||
mValue = value; | ||
} | ||
|
||
@Override | ||
public void reject(String code, String message) { | ||
reject(code, message, /*Throwable*/null); | ||
} | ||
|
||
@Override | ||
@Deprecated | ||
public void reject(String message) { | ||
reject(DEFAULT_ERROR, message, /*Throwable*/null); | ||
} | ||
|
||
@Override | ||
public void reject(String code, Throwable e) { | ||
reject(code, e.getMessage(), e); | ||
} | ||
|
||
@Override | ||
public void reject(Throwable e) { | ||
reject(DEFAULT_ERROR, e.getMessage(), e); | ||
} | ||
|
||
@Override | ||
public void reject(String code, String message, @Nullable Throwable e) { | ||
mRejected++; | ||
mErrorCode = code; | ||
mErrorMessage = message; | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no-trailing-spaces: Trailing spaces not allowed.