diff --git a/core/device/device.py b/core/device/device.py index 4597d5e9..3a3683db 100644 --- a/core/device/device.py +++ b/core/device/device.py @@ -6,6 +6,7 @@ import pytesseract from PIL import Image +import atomac from core.device.device_type import DeviceType from core.device.helpers.adb import Adb @@ -85,8 +86,8 @@ def screen_match(device_name, device_id, expected_image, tolerance=0.1, timeout= type = type.replace('ProductType:', '').strip(' ') device_name = type - print "Verify {0} looks correct...".format(expected_image) expected_image_original_path = os.path.join("data", "images", device_name, "{0}.png".format(expected_image)) + print "Verify {0} looks correct...".format(expected_image_original_path) actual_image_path = os.path.join(OUTPUT_FOLDER, "images", device_name, "{0}_actual.png".format(expected_image)) diff_image_path = os.path.join(OUTPUT_FOLDER, "images", device_name, "{0}_diff.png".format(expected_image)) expected_image_path = os.path.join(OUTPUT_FOLDER, "images", device_name, @@ -241,8 +242,25 @@ def click(device_id, text, timeout): device_type = Device.__get_device_type(device_id) if (device_type == DeviceType.EMULATOR) or (device_type == DeviceType.ANDROID): UIAuto.click(device_id=device_id, text=text, timeout=timeout) + elif device_type == DeviceType.SIMULATOR: + simulator = atomac.getAppRefByBundleId("com.apple.iphonesimulator") + windows = simulator.findAll(AXRole='AXWindow') + names = list() + # Get all simulator's windows names + for window in windows: + names.append(window.AXTitle) + sim_title = Simulator.get_name(device_id) + # Get the full name of the window where the click will be performed + for name in names: + if sim_title in name: + window = simulator.findFirstR(AXTitle=name) + element = window.findFirstR(AXTitle=text) + if element is not None: + element.Press() + else: + raise TypeError("Cannot find element with text {0}".format(text)) else: - raise NotImplementedError("Click on text not implemented for iOS devices and simulators.") + raise NotImplementedError("Click on text not implemented for iOS devices.") @staticmethod def ensure_available(platform): diff --git a/core/device/simulator.py b/core/device/simulator.py index efacb7a8..b2fe12f9 100644 --- a/core/device/simulator.py +++ b/core/device/simulator.py @@ -8,7 +8,7 @@ from core.osutils.command_log_level import CommandLogLevel from core.osutils.file import File from core.osutils.process import Process -from core.settings.settings import SIMULATOR_NAME, TEST_RUN_HOME, SIMULATOR_TYPE, SIMULATOR_SDK +from core.settings.settings import SIMULATOR_NAME, TEST_RUN_HOME class Simulator(object): @@ -65,6 +65,21 @@ def __get_state(simulator_id): else: return lines[0].split('(')[-1].split(')')[0] + @staticmethod + def get_name(simulator_id): + """ + Find simulator name by Simulator GUID + :param simulator_id: Simulator GUID + :return: Simulator name + """ + output = run(command='xcrun simctl list | grep {0}'.format(simulator_id), log_level=CommandLogLevel.SILENT) + if output: + sim_name = output.split()[0] + return sim_name + + else: + raise AssertionError("Can not find device with id {0}".format(simulator_id)) + @staticmethod def create(name, device_type, ios_version): """ diff --git a/core/settings/settings.py b/core/settings/settings.py index 591ade6d..5a757b40 100644 --- a/core/settings/settings.py +++ b/core/settings/settings.py @@ -133,6 +133,10 @@ def resolve_path(package_env, default_value): SIMULATOR_TYPE = 'iPhone 7' SIMULATOR_SDK = '11.0' +SIMULATOR_NAME_2 = "iPhone8N" +SIMULATOR_TYPE_2 = 'iPhone 8' +SIMULATOR_SDK_2 = '11.4' + # Android Build Settings ANDROID_KEYSTORE_PATH = os.environ.get("ANDROID_KEYSTORE_PATH") ANDROID_KEYSTORE_PASS = os.environ.get("ANDROID_KEYSTORE_PASS") diff --git a/data/images/iPhone7N/hello-world_home_after_tap.png b/data/images/iPhone7N/hello-world_home_after_tap.png new file mode 100644 index 00000000..e5790b86 Binary files /dev/null and b/data/images/iPhone7N/hello-world_home_after_tap.png differ diff --git a/data/images/iPhone8N/hello-world_home_after_tap.png b/data/images/iPhone8N/hello-world_home_after_tap.png new file mode 100644 index 00000000..91631203 Binary files /dev/null and b/data/images/iPhone8N/hello-world_home_after_tap.png differ diff --git a/data/images/iPhone8N/livesync-hello-world_home.png b/data/images/iPhone8N/livesync-hello-world_home.png new file mode 100644 index 00000000..93f1bb69 Binary files /dev/null and b/data/images/iPhone8N/livesync-hello-world_home.png differ diff --git a/data/issues/nativescript-cli-3529/main-view-model.js b/data/issues/nativescript-cli-3529/main-view-model.js new file mode 100644 index 00000000..c819c6ea --- /dev/null +++ b/data/issues/nativescript-cli-3529/main-view-model.js @@ -0,0 +1,22 @@ +var observable = require("data/observable"); +var HelloWorldModel = (function (_super) { + __extends(HelloWorldModel, _super); + function HelloWorldModel() { + _super.call(this); + this.counter = 42; + this.set("message", this.counter + " taps left"); + } + HelloWorldModel.prototype.tapAction = function () { + console.log("The button was clicked!") + this.counter--; + if (this.counter <= 0) { + this.set("message", "Hoorraaay! You unlocked the NativeScript clicker achievement!"); + } + else { + this.set("message", this.counter + " taps left"); + } + }; + return HelloWorldModel; +})(observable.Observable); +exports.HelloWorldModel = HelloWorldModel; +exports.mainViewModel = new HelloWorldModel(); diff --git a/runNose.py b/runNose.py index c8971601..ec4a274d 100644 --- a/runNose.py +++ b/runNose.py @@ -15,7 +15,7 @@ from core.osutils.folder import Folder from core.settings.settings import OUTPUT_FOLDER, CURRENT_OS, OSType, \ ANDROID_PATH, IOS_PATH, SUT_FOLDER, CLI_PATH, IOS_INSPECTOR_PATH, SIMULATOR_NAME, SIMULATOR_TYPE, SIMULATOR_SDK, \ - TEST_RUN_HOME + TEST_RUN_HOME, SIMULATOR_NAME_2, SIMULATOR_TYPE_2, SIMULATOR_SDK_2 from core.tns.tns import Tns from core.tns.tns_platform_type import Platform from core.xcode.xcode import Xcode @@ -85,6 +85,7 @@ def get_repos(): SIMULATOR_SDK = '10.0' Simulator.create(SIMULATOR_NAME, SIMULATOR_TYPE, SIMULATOR_SDK) + Simulator.create(SIMULATOR_NAME_2, SIMULATOR_TYPE_2, SIMULATOR_SDK_2) Xcode.cleanup_cache() # Clean Xcode cache folders Device.uninstall_app(app_prefix="org.nativescript.", platform=Platform.ANDROID) Device.uninstall_app(app_prefix="org.nativescript.", platform=Platform.IOS) diff --git a/tests/simulator/run_ios_tests.py b/tests/simulator/run_ios_tests.py index 3f099452..6cd65e9e 100644 --- a/tests/simulator/run_ios_tests.py +++ b/tests/simulator/run_ios_tests.py @@ -23,7 +23,7 @@ from core.device.simulator import Simulator from core.osutils.file import File from core.osutils.folder import Folder -from core.settings.settings import IOS_PACKAGE, SIMULATOR_NAME, TEST_RUN_HOME +from core.settings.settings import IOS_PACKAGE, SIMULATOR_NAME, TEST_RUN_HOME, SIMULATOR_NAME_2 from core.tns.replace_helper import ReplaceHelper from core.tns.tns import Tns from core.tns.tns_platform_type import Platform @@ -70,6 +70,10 @@ def tearDown(self): Tns.kill() BaseClass.tearDown(self) + if Simulator.is_running(SIMULATOR_NAME_2)[0]: + sim_id = Simulator.is_running(SIMULATOR_NAME_2)[1] + Simulator.stop(sim_id) + @classmethod def tearDownClass(cls): BaseClass.tearDownClass() @@ -573,6 +577,43 @@ def test_385_tns_run_ios_source_code_in_ios_part_plugin(self): Device.screen_match(device_name=SIMULATOR_NAME, device_id=self.SIMULATOR_ID, expected_image='livesync-hello-world_home') + def test_387_tns_run_ios_console_log_on_multiple_simulators(self): + """ + https://github.com/NativeScript/nativescript-cli/issues/3529 + """ + + # Start one more simulator + Simulator.start(SIMULATOR_NAME_2) + SIMULATOR_ID_2 = Simulator.ensure_available(simulator_name=SIMULATOR_NAME_2) + + # Add console logging when tap the button + source_js = os.path.join('data', "issues", 'nativescript-cli-3529', 'main-view-model.js') + target_js = os.path.join(self.app_name, 'app', 'main-view-model.js') + File.copy(src=source_js, dest=target_js) + + # `tns run ios` and wait until app is deployed on both simulators + log = Tns.run_ios(attributes={'--path': self.app_name, '--emulator': ''}, wait=False, assert_success=False) + strings = ['Project successfully built', + 'Successfully installed on device with identifier \'{0}\''.format(self.SIMULATOR_ID), + 'Successfully installed on device with identifier \'{0}\''.format(SIMULATOR_ID_2)] + Tns.wait_for_log(log_file=log, string_list=strings, timeout=240, check_interval=10) + + Device.screen_match(device_name=SIMULATOR_NAME, device_id=self.SIMULATOR_ID, + expected_image='livesync-hello-world_home', timeout=60) + Device.click(self.SIMULATOR_ID, 'TAP', timeout=60) + Tns.wait_for_log(log_file=log, string_list=['The button was clicked!'], timeout=120) + Device.screen_match(device_name=SIMULATOR_NAME, device_id=self.SIMULATOR_ID, + expected_image='hello-world_home_after_tap', timeout=60) + + Device.screen_match(device_name=SIMULATOR_NAME_2, device_id=self.SIMULATOR_ID, + expected_image='livesync-hello-world_home', timeout=60) + Device.click(SIMULATOR_ID_2, 'TAP', timeout=60) + Tns.wait_for_log(log_file=log, string_list=['The button was clicked!'], timeout=120) + Device.screen_match(device_name=SIMULATOR_NAME_2, device_id=SIMULATOR_ID_2, + expected_image='hello-world_home_after_tap', timeout=60) + + Simulator.stop(SIMULATOR_ID_2) + def test_390_tns_run_ios_should_warn_if_package_ids_do_not_match(self): """ If bundle identifiers in package.json and Info.plist do not match CLI should warn the user.