Skip to content

Commit

Permalink
upgrade RN in test app + fix simulators handling + fix test app to ru…
Browse files Browse the repository at this point in the history
…n tests immediatelly and exit afterwards
  • Loading branch information
blagoev committed Dec 4, 2017
1 parent 92ab314 commit 7e8b7d7
Show file tree
Hide file tree
Showing 14 changed files with 436 additions and 153 deletions.
9 changes: 9 additions & 0 deletions scripts/find-ios-runtime.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/ruby

require 'json'

runtime = JSON.parse(%x{xcrun simctl list devices --json})['runtimes']
.select{|x| (x['identifier'].include? 'com.apple.CoreSimulator.SimRuntime.iOS') &&
(x['availability'] == "(available)")}[0]["identifier"]

puts runtime
146 changes: 41 additions & 105 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ if [ -n "${JENKINS_HOME}" ]; then
CI_RUN=true
fi

SIM_DEVICE_NAME=realm-js-test

# Start current working directory at the root of the project.
cd "$SRCROOT"

Expand Down Expand Up @@ -97,7 +99,11 @@ cleanup() {
fi
}

open_chrome() {
open_chrome() {
if [ $CONFIGURATION == 'Release' ]; then
break
fi

local dir
for dir in "$HOME/Applications" "/Applications"; do
if [ -d "$dir/Google Chrome.app" ]; then
Expand All @@ -124,122 +130,52 @@ start_packager() {
xctest() {
setup_ios_simulator

# - Wait until the simulator is fully booted by waiting for it to launch SpringBoard
printf "Waiting for springboard to ensure device is ready..."
xcrun simctl launch "$IOS_SIM_DEVICE" com.apple.springboard 1>/dev/null 2>/dev/null || true
echo " done"

# - Run the build and test
xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$IOS_SIM_DEVICE" build || {
echo "Building application"
xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="${IOS_SIM_DEVICE_ID}" -derivedDataPath ./build build || {
EXITCODE=$?
echo "*** Failure (exit code $EXITCODE). ***"
exit $EXITCODE
}
if [ -n "$XCPRETTY" ]; then
log_temp=$(mktemp build.log.XXXXXX)
if [ -e "$log_temp" ]; then
rm "$log_temp"
fi
xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination name="iPhone 5s" test 2>&1 | tee "$log_temp" | "$XCPRETTY" -c --no-utf --report junit --output build/reports/junit.xml || {
EXITCODE=$?
printf "*** Xcode Failure (exit code %s). The full xcode log follows: ***\n\n" "$EXITCODE"
cat "$log_temp"
printf "\n\n*** End Xcode Failure ***\n"
exit $EXITCODE
}
rm "$log_temp"

echo "Installing application on ${SIM_DEVICE_NAME}"
echo "Application Path" $(pwd)/build/Build/Products/$CONFIGURATION-iphonesimulator/ReactTests.app
xcrun simctl install ${SIM_DEVICE_NAME} $(pwd)/build/Build/Products/$CONFIGURATION-iphonesimulator/ReactTests.app


echo "Launching application"
xcrun simctl launch --console ${SIM_DEVICE_NAME} io.realm.ReactTests | tee out.txt

echo "Shuttting down ${SIM_DEVICE_NAME} simulator. (device is not deleted. you can use it to debug the app)"
xcrun simctl shutdown ${SIM_DEVICE_NAME} || true

echo "Checking tests results"
if grep -q "REALM_FAILING_TESTS" out.txt; then
echo "*** REALM JS TESTS FAILED. See tests results above ***"
exit 20
else
xcrun xcodebuild -scheme "$1" -configuration "$CONFIGURATION" -sdk iphonesimulator -destination id="$IOS_SIM_DEVICE" test || {
EXITCODE=$?
echo "*** Failure (exit code $EXITCODE). ***"
exit $EXITCODE
}
echo "*** REALM JS TESTS SUCCESS ***"
fi
}

setup_ios_simulator() {
# - Ensure one version of xcode is chosen by all tools
if [[ -z "$DEVELOPER_DIR" ]]; then
DEV_DIR="$(xcode-select -p)"
export DEVELOPER_DIR=$DEV_DIR
fi

# -- Ensure that the simulator is ready

if [ $CI_RUN == true ]; then
# - Kill the Simulator to ensure we are running the correct one, only when running in CI
echo "Resetting simulator using toolchain from: $DEVELOPER_DIR"
setup_ios_simulator() {
shutdown_ios_simulator

# Quit Simulator.app to give it a chance to go down gracefully
local deadline=$((SECONDS+5))
while pgrep -qx Simulator && [ $SECONDS -lt $deadline ]; do
osascript -e 'tell app "Simulator" to quit without saving' || true
sleep 0.25 # otherwise the pkill following will get it too early
done

# stop CoreSimulatorService
launchctl remove com.apple.CoreSimulator.CoreSimulatorService 2>/dev/null || true
sleep 0.25 # launchtl can take a small moment to kill services

# kill them with fire
while pgrep -qx Simulator com.apple.CoreSimulator.CoreSimulatorService; do
pkill -9 -x Simulator com.apple.CoreSimulator.CoreSimulatorService || true
sleep 0.05
done

# - Prod `simctl` a few times as sometimes it fails the first couple of times after switching XCode vesions
local deadline=$((SECONDS+5))
while [ -z "$(xcrun simctl list devices 2>/dev/null)" ] && [ $SECONDS -lt $deadline ]; do
: # nothing to see here, will stop cycling on the first successful run
done
#parse devices
IOS_RUNTIME=$(xcrun simctl list runtimes | grep -m1 -o '(com.apple.CoreSimulator.SimRuntime.iOS.*)' | sed 's/[()]//g')
echo using iOS Runtime ${IOS_RUNTIME} to create new simulator ${SIM_DEVICE_NAME}

# - Choose a device, if it has not already been chosen
local deadline=$((SECONDS+5))
IOS_DEVICE=""
while [ -z "$IOS_DEVICE" ] && [ $SECONDS -lt $deadline ]; do
IOS_DEVICE="$(ruby $SRCROOT/scripts/find-ios-device.rb best)"
done
if [ -z "$IOS_DEVICE" ]; then
echo "*** Failed to determine the iOS Simulator device to use ***"
exit 1
fi
export IOS_SIM_DEVICE=$IOS_DEVICE

# - Reset the device we will be using if running in CI
xcrun simctl shutdown "$IOS_SIM_DEVICE" 1>/dev/null 2>/dev/null || true # sometimes simctl gets confused
xcrun simctl erase "$IOS_SIM_DEVICE"

# - Start the target in Simulator.app
# Note: as of Xcode 7.3.1 `simctl` can not completely boot a simulator, specifically it can not bring up backboard, so GUI apps can not run.
# This is fixed in version 8 of Xcode, but we still need the compatibility

"$DEVELOPER_DIR/Applications/Simulator.app/Contents/MacOS/Simulator" -CurrentDeviceUDID "$IOS_SIM_DEVICE" & # will get killed with all other children at exit
startedSimulator=true

else
# - ensure that the simulator is running on a developer's workstation
open "$DEVELOPER_DIR/Applications/Simulator.app"

# - Select the first device booted in the simulator, since it will boot something for us
local deadline=$((SECONDS+10))
IOS_DEVICE=""
while [ -z "$IOS_DEVICE" ] && [ $SECONDS -lt $deadline ]; do
IOS_DEVICE="$(ruby $SRCROOT/scripts/find-ios-device.rb booted)"
done
if [ -z "$IOS_DEVICE" ]; then
echo "*** Failed to determine the iOS Simulator device in use ***"
exit 1
fi
export IOS_SIM_DEVICE=$IOS_DEVICE
fi
#create new test simulator
IOS_SIM_DEVICE_ID=$(xcrun simctl create ${SIM_DEVICE_NAME} com.apple.CoreSimulator.SimDeviceType.iPhone-SE ${IOS_RUNTIME})
#boot new test simulator
xcrun simctl boot ${SIM_DEVICE_NAME}
}

# Wait until the boot completes
printf " waiting for simulator (%s) to boot..." "$IOS_SIM_DEVICE"
until ruby -rjson -e "exit JSON.parse(%x{xcrun simctl list devices --json})['devices'].flat_map { |d| d[1] }.any? { |d| d['availability'] == '(available)' && d['state'] == 'Booted' }"; do
sleep 0.25
done
echo " done"
echo "It will take some time before the simulator is fully ready, continuing on to other work"
shutdown_ios_simulator() {
#shutdown test simulator
xcrun simctl shutdown ${SIM_DEVICE_NAME} || true
#delete test simulator
xcrun simctl delete ${SIM_DEVICE_NAME} || true
}

# Cleanup now and also cleanup when this script exits.
Expand Down
4 changes: 2 additions & 2 deletions tests/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,15 @@ function runTests() {

return Object.keys(testNames).reduce((suitePromiseChain, suiteName) => {
return suitePromiseChain.then(() => {
console.log('Starting ' + suiteName);
console.warn('Starting ' + suiteName);

return testNames[suiteName].reduce((testPromiseChain, testName) => {
return testPromiseChain.then(() => {
return RealmTests.runTest(suiteName, 'beforeEach');
}).then(() => {
return RealmTests.runTest(suiteName, testName);
}).then(() => {
console.log('+ ' + testName);
console.warn('+ ' + testName);
}, (err) => {
console.warn('- ' + testName);
console.warn(err.message || err);
Expand Down
7 changes: 6 additions & 1 deletion tests/js/asserts.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,12 @@ module.exports = {
},

assertType: function(value, type, depth) {
this.assertEqual(typeof value, type, `Value ${value} expected to be of type ${type}`, 1 + depth || 0);
try {
this.assertEqual(typeof value, type, "", 1 + depth || 0);
}
catch (e) {
throw new Error(`Value ${value} expected to be of type ${type}`)
}
},

assertDefined: function(value, errorMessage, depth) {
Expand Down
2 changes: 1 addition & 1 deletion tests/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ exports.runTest = function(suiteName, testName) {
if (testMethod) {
// Start fresh in case of a crash in a previous run.
Realm.clearTestState();
console.log("Starting test " + testName);
console.warn("Starting test " + testName);
var promise;
try {
promise = testMethod.call(testSuite);
Expand Down
4 changes: 1 addition & 3 deletions tests/js/list-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,13 @@ const DATE3 = new Date(3);
module.exports = {
testListConstructor: function() {
const realm = new Realm({schema: [schemas.PersonObject, schemas.PersonList]});

realm.write(() => {
let obj = realm.create('PersonList', {list: []});
TestCase.assertInstanceOf(obj.list, Realm.List);
TestCase.assertInstanceOf(obj.list, Realm.Collection);
});

TestCase.assertThrowsContaining(() => new Realm.List(), 'constructor');

TestCase.assertType(Realm.List, 'function');
TestCase.assertInstanceOf(Realm.List, Function);
},
Expand Down
48 changes: 24 additions & 24 deletions tests/js/results-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,35 +386,36 @@ module.exports = {

testResultsFindIndexOfObject: function() {
var realm = new Realm({schema: [schemas.TestObject]});

var object1, object2, object3;
realm.write(function() {
object1 = realm.create('TestObject', {doubleCol: 1});
object2 = realm.create('TestObject', {doubleCol: 2});
object3 = realm.create('TestObject', {doubleCol: 2});
});

// Search in base table
const objects = realm.objects('TestObject');
TestCase.assertEqual(objects.indexOf(object1), 0);
TestCase.assertEqual(objects.indexOf(object2), 1);
TestCase.assertEqual(objects.indexOf(object3), 2);

// Search in filtered query
const results = objects.filtered("doubleCol == 2");
TestCase.assertEqual(results.indexOf(object1), -1);
TestCase.assertEqual(results.indexOf(object2), 0);
TestCase.assertEqual(results.indexOf(object3), 1);

const nonRealmObject = {test: "this is an object"};
TestCase.assertEqual(objects.indexOf(nonRealmObject), -1);

// Searching for object from the wrong realm
var realm2 = new Realm({path: '2.realm', schema: realm.schema});
var object4;
realm2.write(function() {
object4 = realm2.create('TestObject', {doubleCol: 1});
});

TestCase.assertThrows(function() {
objects.indexOf(object4);
});
Expand All @@ -423,7 +424,7 @@ module.exports = {
testAddListener: function() {
if (typeof navigator !== 'undefined' && /Chrome/.test(navigator.userAgent)) { // eslint-disable-line no-undef
// FIXME: async callbacks do not work correctly in Chrome debugging mode
return;
return Promise.resolve();
}

const realm = new Realm({ schema: [schemas.TestObject] });
Expand All @@ -433,29 +434,28 @@ module.exports = {
realm.create('TestObject', { doubleCol: 3 });
});

let resolve, first = true;
let resolve = () => {};
let first = true;

realm.objects('TestObject').addListener((testObjects, changes) => {
if (first) {
TestCase.assertEqual(testObjects.length, 3);
TestCase.assertEqual(changes.insertions.length, 0);
}
else {
TestCase.assertEqual(testObjects.length, 4);
TestCase.assertEqual(changes.insertions.length, 1);
}
first = false;
resolve();
});

return new Promise((r, _reject) => {
resolve = r;
realm.objects('TestObject').addListener((testObjects, changes) => {
if (first) {
TestCase.assertEqual(testObjects.length, 3);
TestCase.assertEqual(changes.insertions.length, 0);
}
else {
TestCase.assertEqual(testObjects.length, 4);
TestCase.assertEqual(changes.insertions.length, 1);
}
first = false;
resolve();
});
}).then(() => {
return new Promise((r, _reject) => {
resolve = r;
realm.write(() => {
realm.create('TestObject', { doubleCol: 1 });
});
resolve = r;
});
})
},

testResultsAggregateFunctions: function() {
Expand Down
2 changes: 2 additions & 0 deletions tests/react-test-app/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ android {
}

dependencies {
compile project(':react-native-exception-handler')
compile project(':react-native-exit-app-no-history')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import android.util.Log;

import com.facebook.react.ReactApplication;
import com.masteratul.exceptionhandler.ReactNativeExceptionHandlerPackage;
import com.github.wumke.RNExitApp.RNExitAppPackage;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
Expand All @@ -28,6 +30,8 @@ protected boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new ReactNativeExceptionHandlerPackage(),
new RNExitAppPackage(),
new RNFSPackage(),
new RealmReactPackage()
);
Expand Down
5 changes: 5 additions & 0 deletions tests/react-test-app/android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ project(':realm').projectDir = new File(settingsDir, '../node_modules/realm/andr

include ':react-native-fs'
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')

include ':react-native-exception-handler'
project(':react-native-exception-handler').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-exception-handler/android')
include ':react-native-exit-app-no-history'
project(':react-native-exit-app-no-history').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-exit-app-no-history/android')
Loading

0 comments on commit 7e8b7d7

Please sign in to comment.