def test_002_build_android_release_uglify_snapshot_sourcemap(self): # https://github.com/NativeScript/nativescript-dev-webpack/issues/920 result = Tns.build_android(self.app_name, release=True, uglify=True, snapshot=True, source_map=True) assert "ERROR in NativeScriptSnapshot. Snapshot generation failed!" not in result.output assert "Target architecture: arm64-v8a" not in result.output # Verify snapshot files in the built .apk apk_path = TnsPaths.get_apk_path(app_name=self.app_name, release=True) if Settings.HOST_OS != OSType.WINDOWS: TnsAssert.snapshot_build(apk_path, self.temp_folder) # Verify app is built with android sdk 29 by default TnsAssert.string_in_android_manifest(apk_path, 'compileSdkVersion="29"') # Configs are respected assert File.exists(TnsPaths.get_apk_path(self.app_name, release=True)) # Create zip command = "tar -czf " + self.app_name + "/app/app.tar.gz " + self.app_name + "/app/app.js" run(cmd=command, cwd=Settings.TEST_RUN_HOME, wait=True) assert File.exists(os.path.join(self.app_path, 'app', 'app.tar.gz'))
def start(emulator): # Define emulator start options and command emulator_path = os.path.join(ANDROID_HOME, 'emulator', 'emulator') options = '-port {0} -wipe-data -no-snapshot-save -no-boot-anim -no-audio -netspeed lte'.format( emulator.port) # Check if clean snapshot is available and use it snapshot_name = 'clean_boot' home = os.path.expanduser("~") snapshot = os.path.join(home, '.android', 'avd', '{0}.avd'.format(emulator.avd), 'snapshots', snapshot_name) if Folder.exists(snapshot): Log.info('{0} has clean boot snapshot! Will user it.'.format(emulator.avd)) options = '-port {0} -no-snapshot-save -no-boot-anim -no-audio -snapshot {1}'.format(emulator.port, snapshot_name) command = '{0} @{1} {2}'.format(emulator_path, emulator.avd, options) Log.info('Booting {0} with cmd:'.format(emulator.avd)) Log.info(command) run(cmd=command, wait=False, register=False) booted = Adb.wait_until_boot(device_id=emulator.emu_id) if booted: Log.info('{0} is up and running!'.format(emulator.avd)) device = Device(id=emulator.emu_id, name=emulator.avd, type=DeviceType.EMU, version=emulator.os_version) TestContext.STARTED_DEVICES.append(device) return device else: raise Exception('Failed to boot {0}!'.format(emulator.avd))
def kill(): Log.info("Kill gradle processes.") if Settings.HOST_OS is OSType.WINDOWS: Process.kill(proc_name='java.exe', proc_cmdline='gradle') else: command = "ps -ef | grep '.gradle/wrapper' | grep -v grep | awk '{ print $2 }' | xargs kill -9" run(cmd=command)
def dismiss_simulator_alert(): """When preview url is loaded in simulator there is alert for confirmation. This method will dismiss it. It is implemented only for one instance of simulator for the moment""" dismiss_sim_alert = os.path.join(TEST_RUN_HOME, 'assets', 'scripts', 'send_enter_to_simulator.scpt') command = "osascript " + dismiss_sim_alert run(command)
def test_003_js_app_apk(self): # Extract APK apk = TnsPaths.get_apk_path(app_name=self.js_app, release=True) extracted_apk = os.path.join(Settings.TEST_OUT_TEMP, 'js-apk') File.unzip(file_path=apk, dest_dir=extracted_apk) res = os.path.join(extracted_apk, 'res') assets_app = os.path.join(extracted_apk, 'assets', 'app') assets_snapshots = os.path.join(extracted_apk, 'assets', 'snapshots') lib = os.path.join(extracted_apk, 'lib') run(cmd='du -hs *', cwd=lib, wait=True, log_level=logging.INFO) # Verify content of APK assert PerfUtils.is_value_in_range(actual=Folder.get_size(lib), expected=38724352, tolerance=0.1) assert PerfUtils.is_value_in_range(actual=Folder.get_size(res), expected=843827, tolerance=0.1) assert PerfUtils.is_value_in_range(actual=Folder.get_size(assets_app), expected=641606, tolerance=0.1) assert PerfUtils.is_value_in_range( actual=Folder.get_size(assets_snapshots), expected=5811260, tolerance=0.1) # Verify final apk size assert PerfUtils.is_value_in_range(actual=File.get_size(apk), expected=18216351, tolerance=0.05)
def clean_repo_changes(local_folder): """ :param local_folder: the folder of the git project in which clean and reset commands will be called """ commands = ['git clean -fdx', 'git reset', 'git checkout .'] Log.info(commands) for command in commands: run(cmd=command, cwd=local_folder)
def test_10_run_command_with_wait_true_that_exceed_timeout(self): # noinspection PyBroadException # pylint: disable=broad-except try: run(cmd='sleep 3', wait=True, timeout=1, fail_safe=False) assert False, 'This line should not be executed, because the line above should raise an exception.' except Exception: pass
def test_002_build_android_release(self): Tns.build_android(self.app_name, release=True) # Configs are respected assert File.exists(TnsPaths.get_apk_path(self.app_name, release=True)) # Create zip command = "tar -czf " + self.app_name + "/app/app.tar.gz " + self.app_name + "/app/app.js" run(cmd=command, cwd=Settings.TEST_RUN_HOME, wait=True) assert File.exists(os.path.join(self.app_path, 'app', 'app.tar.gz'))
def get_all_apps(simulator_info): bundle_ids = [] root = '~/Library/Developer/CoreSimulator/Devices/{0}'.format(simulator_info.id) shell = 'find {0}/data/Containers/Bundle/Application -maxdepth 3 | grep .app | grep Info.plist'.format(root) result = run(cmd=shell, timeout=30) for plist in result.output.splitlines(): bundle_id = run(cmd='/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" {0}'.format(plist)).output if '.' in bundle_id: bundle_ids.append(bundle_id) return bundle_ids
def get_screen(device_id, file_path): """ Save screen of iOS real device. :param device_id: Device identifier. :param file_path: Path where image will be saved. """ tiff_image_path = file_path.replace('.png', '.tiff') run(cmd="idevicescreenshot -u {0} {1}".format(device_id, tiff_image_path)) run(cmd="sips -s format png {0} --out {1}".format( tiff_image_path, file_path)) File.clean(tiff_image_path)
def stop(sim_id='booted'): """ Stop running simulators (by default stop all simulators) :param sim_id: Device identifier (Simulator ID) """ if sim_id == 'booted': Log.info('Stop all running simulators.') Process.kill('Simulator') Process.kill('tail') Process.kill('launchd_sim') Process.kill_by_commandline('CoreSimulator') else: Log.info('Stop simulator with id ' + sim_id) run(cmd='xcrun simctl shutdown {0}'.format(sim_id), timeout=60)
def get_devices(): """ Get available iOS devices (only real devices). """ device_ids = list() output = run(cmd='idevice_id --list', timeout=60).output for line in output.splitlines(): command = 'instruments -s | grep {0}'.format(line) check_connected = run(cmd=command, timeout=30).output if 'null' not in check_connected: device_ids.append(line) else: message = '{0} is not trusted!'.format(line) Log.error(message) return device_ids
def test_01_run_simple_command(self): result = run(cmd='ls ' + self.current_folder, wait=True, timeout=5) assert result.exit_code == 0, 'Wrong exit code of successful command.' assert result.log_file is None, 'No log file should be generated if wait=True.' assert result.complete is True, 'Complete should be true when process execution is complete.' assert result.duration < 1, 'Process duration took too much time.' assert self.current_file in result.output, 'Listing do not return correct output.'
def run_npm_command(cmd, folder=Settings.TEST_RUN_HOME, verify=True): command = 'npm {0}'.format(cmd).strip() Log.info(command + " (at " + str(folder) + ").") result = run(cmd=command, cwd=folder, wait=True, timeout=300) if verify: assert result.exit_code == 0, '" + command + " exited with non zero exit code!: \n' + result.output return result.output.strip()
def sign_apk(apk_path): unzip_folder = apk_path.replace(".apk", "") File.unzip(apk_path, unzip_folder) meta_inf_folder_path = os.path.join(unzip_folder, "META-INF") File.delete(os.path.join(meta_inf_folder_path, "MANIFEST.MF")) AndroidErrorActivityTests.files_to_delete_in_apk(meta_inf_folder_path, ".RSA") AndroidErrorActivityTests.files_to_delete_in_apk(meta_inf_folder_path, ".SF") File.delete(apk_path) File.zip(unzip_folder, apk_path) command = "jarsigner" command = command + " -keystore $ANDROID_KEYSTORE_PATH " command = command + "-keypass $ANDROID_KEYSTORE_PASS " command = command + "-storepass $ANDROID_KEYSTORE_ALIAS_PASS " command = command + apk_path command = command + " $ANDROID_KEYSTORE_ALIAS" run(cmd=command)
def version(): """ Java version. :rtype: float """ result = run('java -version') return Version.get(result.output.split('"')[1])
def test_11_run_command_with_wait_true_and_fail_safe_that_exceed_timeout(self): result = run(cmd='sleep 3', wait=True, timeout=1, fail_safe=True) assert result.exit_code is None, 'Exit code on non completed programs should be None.' assert result.log_file is None, 'No log file should be generated if wait=True.' assert result.complete is False, 'Complete should be true when process execution is complete.' assert result.duration < 2, 'Process duration should be same as timeout.' assert result.output == '', 'No output for not completed programs.'
def test_03_run_command_with_pipe(self): result = run(cmd='echo "test case" | wc -w ', wait=True, timeout=1) assert result.exit_code == 0, 'Wrong exit code of successful command.' assert result.log_file is None, 'No log file should be generated if wait=True.' assert result.complete is True, 'Complete should be true when process execution is complete.' assert result.duration < 1, 'Process duration took too much time.' assert result.output == '2', 'Output should be 2.'
def test_001_build_ios(self): Tns.platform_remove(self.app_name, platform=Platform.ANDROID) Tns.build_ios(self.app_name) Tns.build_ios(self.app_name, release=True) Tns.build_ios(self.app_name, for_device=True) Tns.build_ios(self.app_name, for_device=True, release=True) assert not File.exists(os.path.join(TnsPaths.get_platforms_ios_folder(self.app_name), '*.aar')) assert not File.exists(os.path.join(TnsPaths.get_platforms_ios_npm_modules(self.app_name), '*.framework')) # Verify ipa has both armv7 and arm64 archs ipa_path = TnsPaths.get_ipa_path(app_name=self.app_name, release=True, for_device=True) run("mv " + ipa_path + " TestApp-ipa.tgz") run("unzip -o TestApp-ipa.tgz") result = run("lipo -info Payload/TestApp.app/TestApp") Folder.clean("Payload") assert "Architectures in the fat file: Payload/TestApp.app/TestApp are: armv7 arm64" in result.output
def __init__(self, id, name, type, model, version): self.id = id self.type = type self.version = version self.model = model self.name = name if type is DeviceType.IOS: type = run(cmd="ideviceinfo | grep ProductType").output type = type.replace(',', '') type = type.replace('ProductType:', '').strip(' ') self.name = type if type is DeviceType.SIM: self.model = name if type is DeviceType.EMU: cmd = 'shell getprop ro.product.model' model = Adb.run_adb_command(command=cmd, wait=True, device_id=self.id).output self.model = model.strip('\n\r') else: self.name = name if type is DeviceType.SIM: self.device_log_file = Simctl.get_log_file(self.id)
def bundletool_deploy(bundletool_path, path_to_apks, device_id): deploy_command = ('java -jar {0} install-apks --apks="{1}" --device-id={2}').format(bundletool_path, path_to_apks, device_id) result = run(deploy_command) assert "Error" not in result.output, "deploy of app failed" assert "The APKs have been extracted in the directory:" in result.output, "deploy of app failed"
def get_package_permission(apk_file): """ Get permission from apk file. :param apk_file: Path to apk file. :return: Permissions as string. """ command = Adb.__find_aapt() + ' d permissions ' + apk_file return run(cmd=command, log_level=logging.WARNING).output
def get_version(): """ Get Xcode version :return: Version as int. """ result = run(cmd='xcodebuild -version').output.splitlines()[0].replace( ' ', '').replace('Xcode', '') return Version.get(result)
def start(simulator_info): # Start iOS Simulator Log.info('Booting {0} ...'.format(simulator_info.name)) simulator_info = Simctl.start(simulator_info=simulator_info) # Start GUI if Process.get_proc_by_commandline('Simulator.app') is not None: Log.debug('Simulator GUI is already running.') else: Log.info('Start simulator GUI.') run(cmd='open -a Simulator') # Return result device = Device(id=simulator_info.id, name=simulator_info.name, type=DeviceType.SIM, version=simulator_info.sdk) TestContext.STARTED_DEVICES.append(device) return device
def create(simulator_info): cmd = 'xcrun simctl create {0} "{1}" com.apple.CoreSimulator.SimRuntime.iOS-{2}' \ .format(simulator_info.name, simulator_info.device_type, str(simulator_info.sdk).replace('.', '-')) result = run(cmd=cmd, timeout=60) assert result.exit_code == 0, 'Failed to create iOS Simulator with name {0}'.format(simulator_info.name) assert '-' in result.output, 'Failed to create iOS Simulator with name {0}'.format(simulator_info.name) simulator_info.id = result.output.splitlines()[0] return simulator_info
def test_02_run_command_with_redirect(self): out_file = os.path.join(Settings.TEST_OUT_HOME, 'log.txt') result = run(cmd='ls ' + self.current_folder + ' > ' + out_file, wait=True, timeout=1) assert result.exit_code == 0, 'Wrong exit code of successful command.' assert result.log_file is None, 'No log file should be generated if wait=True.' assert result.complete is True, 'Complete should be true when process execution is complete.' assert result.duration < 1, 'Process duration took too much time.' assert result.output == '', 'Output should be empty.' assert self.current_file in File.read(path=out_file)
def bundletool_build(bundletool_path, path_to_aab, path_to_apks): build_command = ('java -jar {0} build-apks --bundle="{1}" --output="{2}" --ks="{3}" --ks-pass=pass:"******" \ --ks-key-alias="{5}" --key-pass=pass:"******"').format(bundletool_path, path_to_aab, path_to_apks, Android.ANDROID_KEYSTORE_PATH, Android.ANDROID_KEYSTORE_PASS, Android.ANDROID_KEYSTORE_ALIAS, Android.ANDROID_KEYSTORE_ALIAS_PASS) result = run(build_command) assert "Error" not in result.output, "create of .apks file failed"
def test_40_run_npm_pack(self): package = 'tns-core-modules' version = '5.0.0' tarball = '{0}-{1}.tgz'.format(package, version) path = os.path.join(Settings.TEST_SUT_HOME, tarball) File.delete(path) result = run(cmd='npm pack https://registry.npmjs.org/{0}/-/{1}'.format(package, tarball), cwd=Settings.TEST_SUT_HOME, wait=True) assert File.exists(path) assert tarball in result.output assert '=== Tarball Contents ===' in result.output
def save_screen(path, log_level=logging.DEBUG): """ Save screen of host machine. :param path: Path where screen will be saved. :param log_level: Log level of the command. """ Log.log(level=log_level, msg='Save current host screen at {0}'.format(path)) if Settings.HOST_OS is OSType.LINUX: os.system("import -window root {0}".format(path)) else: try: from PIL import ImageGrab image = ImageGrab.grab() image.save(path) except IOError: Log.error('Failed to take screen of host OS') if Settings.HOST_OS is OSType.OSX: Log.info('Retry...') run(cmd='screencapture ' + path)
def test_442_assert_arm64_is_enabled_by_default(self): """ Test arm64-v8 is enabled by default """ Tns.build_android(os.path.join(TEST_RUN_HOME, APP_NAME), verify=True) apk_folder = os.path.join(TEST_RUN_HOME, APP_NAME, "platforms", "android", "app", "build", "outputs", "apk", "debug") apk_file = os.path.join(apk_folder, "app-debug.apk") apk_folder_to_unzip = os.path.join(apk_folder, "apk") Folder.create(apk_folder_to_unzip) command = "unzip " + apk_file + " -d " + apk_folder_to_unzip run(command, wait=False) time.sleep(20) unzip_apk_folder = os.path.join(apk_folder, "apk") arm64_folder = os.path.join(unzip_apk_folder, "lib", "arm64-v8a") assert Folder.exists( arm64_folder), "arm64-v8a architecture is missing!" error_message = "libNativeScript.so in arm64-v8a folder is missing!" assert File.exists(os.path.join(arm64_folder, "libNativeScript.so")), error_message