Skip to content
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

test: add RN E2E test based on detox framework #1383

Merged
merged 11 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"eslint-config-prettier": "6.11.0",
"eslint-plugin-prettier": "3.1.4",
"eslint-plugin-simple-import-sort": "5.0.3",
"figlet": "^1.5.0",
"fs-extra": "^9.0.0",
"generate-changelog": "^1.7.1",
"husky": "^4.2.3",
Expand Down
3 changes: 2 additions & 1 deletion scripts/verdaccio-publish/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
const { spawn, execSync } = require("child_process");
const pipeStdIo = { stdio: [process.stdin, process.stdout, process.stderr] };

execSync("rm -rf verdaccio/storage/@aws-sdk");
execSync("rm -rf verdaccio/storage");

// Start verdaccio in the background
const verdaccio = spawn("npx", ["verdaccio", "-c", "verdaccio/config.yaml"], pipeStdIo).on("error", (e) => {
Expand All @@ -21,6 +21,7 @@ const args = [
"lerna",
"publish",
"prerelease",
"--force-publish",
"--preid",
"ci",
"--exact",
Expand Down
6 changes: 6 additions & 0 deletions tests/react-native/End2End/.buckconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

[android]
target = Google Inc.:Google APIs:23

[maven_repositories]
central = https://repo1.maven.org/maven2
14 changes: 14 additions & 0 deletions tests/react-native/End2End/.detoxrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"testRunner": "jest",
"runnerConfig": "e2e/config.json",
"configurations": {
"ios": {
"type": "ios.simulator",
"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/End2End.app",
"build": "xcodebuild -workspace ios/End2End.xcworkspace -scheme End2End -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build",
"device": {
"type": "iPhone X"
}
}
}
}
5 changes: 5 additions & 0 deletions tests/react-native/End2End/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# When building and testing the app, please rename this file to .env and replace the
# keys with proper resources
AWS_SMOKE_TEST_IDENTITY_POOL_ID=[identity-pool-id]
AWS_SMOKE_TEST_BUCKET=[bucket-name]
AWS_SMOKE_TEST_REGION=[region]
4 changes: 4 additions & 0 deletions tests/react-native/End2End/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
root: true,
extends: "@react-native-community"
};
1 change: 1 addition & 0 deletions tests/react-native/End2End/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pbxproj -text
65 changes: 65 additions & 0 deletions tests/react-native/End2End/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# OSX
#
.DS_Store

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IntelliJ
#
build/
.idea
.gradle
local.properties
*.iml

# node.js
#
node_modules/
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
*.keystore

# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://docs.fastlane.tools/best-practices/source-control/

*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots

# Bundle artifact
*.jsbundle

# CocoaPods
/ios/Pods/

.env
junit.xml

# No need to track package SHA because of the testing local packages
yarn.lock
1 change: 1 addition & 0 deletions tests/react-native/End2End/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@aws-sdk:registry=http://localhost:4873/
1 change: 1 addition & 0 deletions tests/react-native/End2End/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
185 changes: 185 additions & 0 deletions tests/react-native/End2End/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/**
* Sample React Native App
* https://github.com/facebook/react-native
*
* Generated with the TypeScript template
* https://github.com/emin93/react-native-template-typescript
*
* @format
*/

import React, { Fragment, useState } from "react";
import { SafeAreaView, StyleSheet, ScrollView, StatusBar, Button, Text } from "react-native";
import { S3 } from "@aws-sdk/client-s3";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-provider-cognito-identity";
import { CognitoIdentityClient } from "@aws-sdk/client-cognito-identity";
import {
//@ts-ignore imported ENVs are injected by Babel at compile time
AWS_SMOKE_TEST_IDENTITY_POOL_ID,
//@ts-ignore
AWS_SMOKE_TEST_REGION,
//@ts-ignore
AWS_SMOKE_TEST_BUCKET,
} from "react-native-dotenv";

const App = () => {
const [responseContent, setResponseContent] = useState("");
const [uploadId, setUploadId] = useState("");
const [uploadParts, setUploadParts] = useState<Array<{ ETag: string; PartNumber: number }>>([]);
const s3 = new S3({
credentials: fromCognitoIdentityPool({
identityPoolId: AWS_SMOKE_TEST_IDENTITY_POOL_ID,
client: new CognitoIdentityClient({
region: AWS_SMOKE_TEST_REGION,
}),
}),
region: AWS_SMOKE_TEST_REGION,
});
const Key = `smoke-test-rn`;

return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<ScrollView contentInsetAdjustmentBehavior="automatic" contentContainerStyle={styles.scrollViewContainer}>
<Fragment>
<Button
title="S3.PutObject"
testID="s3PutObject"
onPress={async () => {
const res = await s3.putObject({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key,
Body: "this is a test payload from RN end-to-end test.",
});
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.getObject"
testID="s3GetObject"
onPress={async () => {
const res = await s3.getObject({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key,
});
if (!(res.Body instanceof Blob))
throw new Error(`Expected Blob payload but got ${res.Body.constructor}`);
const reader = new FileReader();
reader.addEventListener("loadend", (data) => {
setResponseContent(reader.result as string);
});
reader.readAsText(res.Body);
}}
/>
<Button
title="S3.listObjects"
testID="s3ListObjects"
onPress={async () => {
const res = await s3.listObjects({
Bucket: AWS_SMOKE_TEST_BUCKET,
});
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.createMultipartUpload"
testID="s3CreateMultipartUpload"
onPress={async () => {
const res = await s3.createMultipartUpload({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
});
setUploadId(res.UploadId);
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.uploadPart"
testID="s3UploadPart"
onPress={async () => {
console.log("uploadId ", uploadId);
const res = await s3.uploadPart({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
PartNumber: 1,
UploadId: uploadId,
Body: new Blob(new Array(1024).fill("x")),
});
uploadParts.push({ PartNumber: 1, ETag: res.ETag });
setUploadParts(uploadParts);
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.listParts"
testID="s3ListParts"
onPress={async () => {
const res = await s3.listParts({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
UploadId: uploadId,
});
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.completeMultipartUpload"
testID="s3CompleteMultipartUpload"
onPress={async () => {
const res = await s3.completeMultipartUpload({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
UploadId: uploadId,
MultipartUpload: { Parts: uploadParts },
});
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.headObject"
testID="s3HeadObject"
onPress={async () => {
const res = await s3.headObject({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
});
setResponseContent(JSON.stringify(res));
}}
/>
<Button
title="S3.deleteObject"
testID="s3DeleteObject"
onPress={async () => {
const res0 = await s3.deleteObject({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key,
});
const res1 = await s3.deleteObject({
Bucket: AWS_SMOKE_TEST_BUCKET,
Key: `${Key}-multipart`,
});
setResponseContent(`${JSON.stringify(res0)}\n${JSON.stringify(res1)}`);
}}
/>
<Text testID="responseContent">{responseContent}</Text>
</Fragment>
</ScrollView>
</SafeAreaView>
</>
);
};

const styles = StyleSheet.create({
safeArea: {
flexGrow: 1,
paddingTop: StatusBar.currentHeight,
},
scrollViewContainer: {
flexGrow: 1,
alignItems: "center",
justifyContent: "center",
},
});

export default App;
75 changes: 75 additions & 0 deletions tests/react-native/End2End/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# End2End

> end-to-end test run on React-Native testing a subset of AWS SDK clients

## Prerequisite

- See [Detox requirement](https://github.com/wix/Detox#environment)
- Launch XCode.app, if it asks you to install the update or extra components, please follow the instructions to install
them.
- Confirm iPhone X simulator is installed locally, by running:
```console
applesimutils --list | grep "name" | grep iPhone
```
If `applesimutils` command is not found, you can install it [following the guidance](https://github.com/wix/AppleSimulatorUtils#installing).
If iPhone X simulator is not available in the runtime, you can install it following the next step.
- Launch XCode.app, click `Open another project`, choose the directory `tests/react-native/End2End/ios`. Open XCode ->
Open Developer Tool -> simulator. In the simulator.app, open Hardware -> Device -> Manage Devices... -> Simulators ->
click "+" at the button of left side bar. In the pop-up, "Device Type" drop-down, choose "iPhone X", click "Create".
Make sure iPhone X is available in the last step.

## Steps to Setup

1. Build the project:

- change directory to project root: `cd ../../..`
- `yarn`
- `yarn build:all`
- If the command above takes too long on local machine, you can build the only packages that used by the RN test. As
of now\*, the RN test only touches `client-cognito-identity`, `client-s3`, `client-cloudformation`,
`credential-provider-cognito-identity`. You can build them by:

```console
yarn build:crypto-dependencies && lerna run pretest --scope '{@aws-sdk/client-cognito-identity,@aws-sdk/client-s3,@aws-sdk/client-cloudformation,@aws-sdk/credential-provider-cognito-identity}' --include-dependencies
```

- `git fetch [remove] --tags`

1. Launch the ReactNative test:

- change directory to RN test root: `cd tests/react-native/End2End`
- make sure you have configured the SDK with the the credentials from the testing account that contains
`SdkReleaseV3IntegTestResourcesStack`
- `node launch-app.js --local-publish`

## Steps to Re-run the Tests

If the scripts above fail and you need to re-run the test script, you need to make sure the workspace is cleaned and
ready to run the test script again. Follow the steps bellow to clean the workspace.

1. Kill the local NPM registry process. You can get the process PID by running:

```console
lsof -i -P -n | grep "TCP 127.0.0.1:4873"
```

The number after `node` is the PID.

Kill the process by running:

```console
kill -9 [PID]
```

1. Reset the temporary changes to the workspace in git from project root:

```console
git reset --hard clients/*/package.json packages/*/package.json protocol_tests/*/package.json
```

1. Follow the `Launch the ReactNative test:` step of [Steps to Setup](#steps-to-setup). If you don't plan to install
the packages to `End2End` test APP again, you can omit the `--local-publish` option the test script:

```console
node launch-app.js
```