class TnsRunJSTestsApi28(TnsRunAndroidTest): app_name = Settings.AppName.DEFAULT source_project_dir = TnsPaths.get_app_path(app_name) target_project_dir = os.path.join(Settings.TEST_RUN_HOME, 'data', 'temp', app_name) @classmethod def setUpClass(cls): TnsRunAndroidTest.setUpClass() Docker.start() # Create app result = Tns.create(app_name=cls.app_name, template='[email protected]', verify=False) TnsAssert.created(app_name=cls.app_name, output=result.output, path=Settings.TEST_RUN_HOME, theme=False) # Copy TestApp to data folder. Folder.copy(source=cls.source_project_dir, target=cls.target_project_dir) def setUp(self): TnsRunAndroidTest.setUp(self) # "src" folder of TestApp will be restored before each test. # This will ensure failures in one test do not cause common failures. source_src = os.path.join(self.target_project_dir, 'app') target_src = os.path.join(self.source_project_dir, 'app') Folder.clean(target_src) Folder.copy(source=source_src, target=target_src) @classmethod def tearDownClass(cls): TnsRunAndroidTest.tearDownClass() Docker.stop() def test_100_run_android(self): """ Run android, verify app is built with api28 and verify livesync """ # Run app and verify on emulator sync_hello_world_js(self.app_name, Platform.ANDROID, self.emu, default_andr_sdk='28') def test_200_run_android_release_snapshot(self): """ Run android, verify app is built with api28 """ # Run app and verify on emulator run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, default_andr_sdk='28', release=True, snapshot=True)
def test_302_build_project_with_space_debug_with_plugin(self): # skip remove platform because androidx is not released official app_space_path = TnsPaths.get_app_path(app_name=self.app_name_with_space) # Tns.platform_remove(app_name='"' + self.app_name_with_space + '"', platform=Platform.ANDROID) Npm.install(package='nativescript-mapbox', option='--save', folder=app_space_path) result = Tns.build_android(app_name='"' + self.app_name_with_space + '"') assert "Project successfully built" in result.output
def test_100_run_android_app_bundle_compile_snapshot(self): """Run app on android with --aab option with optimisations for snapshot. Verify the output(app.aab).""" path_to_aab = os.path.join(TnsPaths.get_app_path(self.app_name), "platforms", "android", "app", "build", "outputs", "bundle", "release", "app-release.aab") path_to_apks = os.path.join(TnsPaths.get_app_path(self.app_name), "platforms", "android", "app", "build", "outputs", "bundle", "release", "app-release.apks") # env.snapshot is applicable only in release build result = Tns.run_android(self.app_path, aab=True, release=True, snapshot=True, uglify=True, verify=False, compile_snapshot=True) strings = [ 'Successfully generated snapshots', 'The build result is located at: {0}'.format(path_to_aab) ] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=300) # Verify app can be deployed on emulator via nativescript # Verify app looks correct inside emulator self.emu.wait_for_text(text='TAP', timeout=60) # Verify that the correct .so file is included in the package File.unzip(path_to_apks, os.path.join(self.app_name, 'apks')) File.unzip( os.path.join(self.app_name, 'apks', 'standalones', 'standalone-arm64_v8a_hdpi.apk'), os.path.join(self.app_name, 'standalone-arm64')) assert File.exists( os.path.join(self.app_name, 'standalone-arm64', 'lib', 'arm64-v8a', 'libNativeScript.so')) assert not File.exists( os.path.join(self.app_name, 'standalone-arm64', 'assets', 'snapshots', 'x86_64', 'snapshot.blob'))
class NGGenerateNGTests(TnsTest): app_name = Settings.AppName.DEFAULT app_path = TnsPaths.get_app_path(app_name=app_name) @classmethod def setUpClass(cls): TnsTest.setUpClass() NG.kill() Folder.clean(cls.app_path) # Create app NG.new(collection=NS_SCHEMATICS, project=cls.app_name, shared=False) # TODO: Rollback theme=False when schematics use @nativescript/theme TnsAssert.created(app_name=cls.app_name, app_data=None, theme=False) def setUp(self): TnsTest.setUpClass() NG.kill() def tearDown(self): NG.kill() TnsTest.tearDown(self) def test_001_generate_component(self): result = NG.exec_command(command='g c component-test', cwd=self.app_path) assert 'CREATE app/component-test/component-test.component.html' in result.output assert 'CREATE app/component-test/component-test.component.ts' in result.output assert 'CREATE app/component-test/component-test.component.css' in result.output assert 'UPDATE app/app.module.ts' in result.output def test_002_generate_module(self): result = NG.exec_command(command='g m module-test', cwd=self.app_path) assert 'CREATE app/module-test/module-test.module.ts' in result.output def test_003_generate_component_in_existing_modules(self): result = NG.exec_command(command='g m module-test2', cwd=self.app_path) assert 'CREATE app/module-test2/module-test2.module.ts' in result.output result = NG.exec_command(command='g c module-test2/component-name', cwd=self.app_path) assert 'CREATE app/module-test2/component-name/component-name.component.html' in result.output assert 'CREATE app/module-test2/component-name/component-name.component.ts' in result.output assert 'CREATE app/module-test2/component-name/component-name.component.css' in result.output assert 'UPDATE app/module-test2/module-test2.module.ts' in result.output @unittest.skip('Skip because of https://github.com/NativeScript/nativescript-schematics/issues/194') def test_004_generate_master_detail(self): result = NG.exec_command(command='g master-detail --master=dogs --detail=dog', cwd=self.app_path) assert 'CREATE app/dogs/dog-detail/dog-detail.component.html' in result.output assert 'CREATE app/dogs/dogs/dogs.component.html' in result.output assert 'data.service.ts' in result.output assert 'dogs.module.ts' in result.output
def platform_removed(app_name, platform, output): platform_string = str(platform) # Verify output assert 'Platform {0} successfully removed'.format( platform_string) in output # Verify package.json app_path = TnsPaths.get_app_path(app_name) package_json = os.path.join(app_path, 'package.json') json = JsonUtils.read(package_json) assert not 'tns-' + platform_string in json if platform == Platform.ANDROID: assert not Folder.exists( TnsPaths.get_platforms_android_folder(app_name)) else: assert not Folder.exists( TnsPaths.get_platforms_ios_folder(app_name))
def workflow(app_name, device, platform, shared): # Create an app app_path = TnsPaths.get_app_path(app_name=app_name) Folder.clean(app_path) NG.new(collection=NS_SCHEMATICS, project=app_name, shared=shared) TnsAssert.created(app_name=app_name, app_data=None) # Run app initially text = 'TAP' if shared: text = 'Welcome to' result = Tns.run(app_name=app_name, platform=platform, emulator=True, hmr=True) strings = TnsLogs.run_messages(app_name=app_name, platform=platform, bundle=True, hmr=True, app_type=AppType.NG) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=300) device.wait_for_text(text=text) # Generate module and component NG.exec_command(command='g m module-test', cwd=app_path) NG.exec_command(command='g c module-test/component-test', cwd=app_path) # Update app.modules.ts app_module_name = 'app.module.ts' app_module_path = os.path.join(app_path, 'app', app_module_name) if shared: app_module_name = 'app.module.tns.ts' app_module_path = os.path.join(app_path, 'src', 'app', app_module_name) old_string = "import { HomeComponent } from './home/home.component';" new_string = "import { ComponentTestComponent } from './module-test/component-test/component-test.component';" File.replace(path=app_module_path, old_string=old_string, new_string=new_string) File.replace(path=app_module_path, old_string='HomeComponent,', new_string='ComponentTestComponent,') # Update app-routing.module.ts app_routing_module_name = 'app-routing.module.ts' app_routing_module_path = os.path.join(app_path, 'app', app_routing_module_name) if shared: app_routing_module_name = 'app.routes.ts' app_routing_module_path = os.path.join(app_path, 'src', 'app', app_routing_module_name) old_string = "import { HomeComponent } from './home/home.component';" new_string = "import { ComponentTestComponent } from './module-test/component-test/component-test.component';" File.replace(path=app_routing_module_path, old_string=old_string, new_string=new_string) File.replace(path=app_routing_module_path, old_string='HomeComponent', new_string='ComponentTestComponent') # Verify app is updated logs = [app_module_name.replace('.tns', ''), app_routing_module_name.replace('.tns', ''), 'Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=logs, timeout=120) device.wait_for_text(text='component-test works!')
def platform_clean(app_name, platform=Platform.NONE, verify=True): platform_string = str(platform) command = 'platform clean ' + platform_string result = Tns.exec_command(command=command, path=app_name) if verify: assert "Platform {0} successfully removed".format( platform_string) in result.output assert "error" not in result.output if platform is Platform.ANDROID: assert Folder.exists( TnsPaths.get_platforms_android_folder(app_name)) if platform is Platform.IOS: assert Folder.exists( TnsPaths.get_platforms_ios_folder(app_name)) assert "Platform {0} successfully added".format( platform_string) in result.output package_json = os.path.join(TnsPaths.get_app_path(app_name), 'package.json') json = JsonUtils.read(package_json) assert json['nativescript']['tns-' + platform_string]['version'] is not None
def test_init(app_name, framework, update=True, verify=True): """ Execute `tns test init` command. :param app_name: App name (passed as --path <App name>) :param framework: Unit testing framework as string (jasmin, mocha, quinit). :param update: Update nativescript-unit-test-runner if True. :param verify: Verify command was executed successfully. :return: Result of `tns test init` command. """ app_path = TnsPaths.get_app_path(app_name=app_name) command = 'test init --framework {0}'.format(str(framework)) result = Tns.exec_command(command=command, path=app_name, timeout=300) if verify: TnsAssert.test_initialized(app_name=app_name, framework=framework, output=result.output) if update: Npm.uninstall(package='nativescript-unit-test-runner', option='--save', folder=app_path) Npm.install(package='nativescript-unit-test-runner@next', option='--save --save-exact', folder=app_path) return result
class PrepareTests(TnsTest): app_name = Settings.AppName.DEFAULT app_path = TnsPaths.get_app_path(app_name=app_name) app_temp_path = os.path.join(Settings.TEST_RUN_HOME, 'data', 'temp', 'TestApp') @classmethod def setUpClass(cls): TnsTest.setUpClass() Tns.create(app_name=cls.app_name, template=Template.HELLO_WORLD_JS.local_package, update=True) if Settings.HOST_OS is OSType.OSX: Tns.platform_add_ios(cls.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) Tns.platform_add_android(cls.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) Folder.copy(cls.app_path, cls.app_temp_path) def setUp(self): TnsTest.setUp(self) Folder.clean(self.app_path) Folder.copy(self.app_temp_path, self.app_path) def tearDown(self): TnsTest.tearDown(self) @classmethod def tearDownClass(cls): TnsTest.tearDownClass() Folder.clean(cls.app_temp_path) def test_100_prepare_android(self): Tns.prepare_android(self.app_name) result = Tns.prepare_android(self.app_name) # assert "Skipping prepare" in result.output Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) result = Tns.prepare_android(self.app_name) assert "Preparing project..." in result.output @unittest.skip("https://github.com/NativeScript/nativescript-dev-webpack/issues/892") def test_200_prepare_xml_error(self): Tns.platform_remove(self.app_name, platform=Platform.ANDROID) Sync.replace(app_name=self.app_name, change_set=Changes.AppFileChanges.CHANGE_XML_INVALID_SYNTAX) result = Tns.prepare_android(self.app_name) assert "main-page.xml has syntax errors." in result.output assert "unclosed xml attribute" in result.output @unittest.skipIf(Settings.HOST_OS == OSType.WINDOWS, "Skip on Windows") def test_210_platform_not_need_remove_after_bitcode_error(self): # https://github.com/NativeScript/nativescript-cli/issues/3741 Tns.platform_remove(self.app_name, platform=Platform.ANDROID) run("touch a", cwd=os.path.join(self.app_name, 'app')) run("ln -s a b", cwd=os.path.join(self.app_name, 'app')) run("rm a", cwd=os.path.join(self.app_name, 'app')) result = Tns.prepare_android(self.app_name) assert "Project successfully prepared" in result.output @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_100_prepare_ios(self): Tns.prepare_ios(self.app_name) result = Tns.prepare_ios(self.app_name) # assert "Skipping prepare" in result.output Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) result = Tns.prepare_ios(self.app_name) assert "Preparing project..." in result.output # Verify Xcode Schemes result = run("xcodebuild -project " + os.path.join(TnsPaths.get_platforms_ios_folder(self.app_name), 'TestApp.xcodeproj', ' -list')) assert "This project contains no schemes." not in result.output result1 = re.search(r"Targets:\n\s*TestApp", result.output) assert result1 is not None result1 = re.search(r"Schemes:\n\s*TestApp", result.output) assert result1 is not None Tns.prepare_android(self.app_name) Tns.prepare_ios(self.app_name) result = Tns.prepare_ios(self.app_name) # assert "Skipping prepare" in result.output @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_200_prepare_additional_appresources(self): Tns.prepare_ios(self.app_name) # Create new files in AppResources File.copy(os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'iOS', 'Assets.xcassets', 'AppIcon.appiconset', 'icon-76.png'), os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'iOS', 'newDefault.png')) Tns.prepare_ios(self.app_name) # Verify XCode Project include files from App Resources folder result = run("cat " + os.path.join(TnsPaths.get_platforms_ios_folder(self.app_name), 'TestApp.xcodeproj', 'project.pbxproj | grep newDefault.png')) assert "newDefault.png" in result.output @unittest.skip("This test doesn't pass now. Remove skip after webpack only") @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_210_prepare_android_does_not_prepare_ios(self): Tns.plugin_add(plugin_name='nativescript-social-share', path=self.app_name) Tns.plugin_add(plugin_name='[email protected]', path=self.app_name) result = Tns.prepare_android(self.app_name) assert "Successfully prepared plugin nativescript-social-share for android" in result.output assert "nativescript-iqkeyboardmanager is not supported for android" in result.output @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_220_prepare_ios_with_provisioning(self): # Prepare with --provision (debug, emulator) Tns.prepare_ios(self.app_name, provision=Settings.IOS.PROVISIONING) # Prepare with --provision (release, emulator) Tns.prepare_ios(self.app_name, provision=Settings.IOS.PROVISIONING, release=True) # Prepare with --provision (debug, device) Tns.prepare_ios(self.app_name, for_device=True, provision=Settings.IOS.PROVISIONING) # Prepare with --provision (release, device) Tns.prepare_ios(self.app_name, release=True, for_device=True, provision=Settings.IOS.PROVISIONING)
def test_002_js_app_node_modules(self): folder = os.path.join(TnsPaths.get_app_path(app_name=self.js_app), 'node_modules') assert PerfUtils.is_value_in_range(actual=Folder.get_size(folder), expected=51791943, tolerance=0.2)
def test_001_js_app_app_resources(self): folder = os.path.join(TnsPaths.get_app_path(app_name=self.js_app), 'app') assert PerfUtils.is_value_in_range(actual=Folder.get_size(folder), expected=2991548, tolerance=0.1)
def test_101_ng_app_node_modules(self): app_folder = os.path.join(TnsPaths.get_app_path(app_name=self.ng_app), 'node_modules') assert PerfUtils.is_value_in_range(actual=Folder.get_size(app_folder), expected=200248003, tolerance=0.2)
def test_100_ng_app_app_resources(self): app_folder = os.path.join(TnsPaths.get_app_path(app_name=self.ng_app), 'App_Resources') assert PerfUtils.is_value_in_range(actual=Folder.get_size(app_folder), expected=2986244, tolerance=0.1)
class TnsRunJSTests(TnsRunTest): app_name = Settings.AppName.DEFAULT app_name_space = Settings.AppName.WITH_SPACE app_path = TnsPaths.get_app_path(app_name) app_resources_path = TnsPaths.get_path_app_resources(app_name) source_project_dir = TnsPaths.get_app_path(app_name) target_project_dir = os.path.join(Settings.TEST_RUN_HOME, 'data', 'temp', app_name) app_resources_android = os.path.join(app_resources_path, 'Android') app_resources_ios = os.path.join(app_resources_path, 'iOS') @classmethod def setUpClass(cls): TnsRunTest.setUpClass() # Create app Tns.create(app_name=cls.app_name, template=Template.HELLO_WORLD_JS.local_package, update=True) src = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'logs', 'hello-world-js', 'app.js') target = os.path.join(cls.app_path, 'app') File.copy(source=src, target=target) Tns.platform_add_android(app_name=cls.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) if Settings.HOST_OS is OSType.OSX: Tns.platform_add_ios(app_name=cls.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) # Copy TestApp to data folder. Folder.copy(source=cls.source_project_dir, target=cls.target_project_dir) def setUp(self): TnsRunTest.setUp(self) # "src" folder of TestApp will be restored before each test. # This will ensure failures in one test do not cause common failures. source_src = os.path.join(self.target_project_dir, 'app') target_src = os.path.join(self.source_project_dir, 'app') Folder.clean(target_src) Folder.copy(source=source_src, target=target_src) def test_100_run_android_break_and_fix_app(self): """ Make changes in xml that break the app and then changes thet fix the app. Add/remove js files thst break the app and then fix it. Verify recovery. """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu) # Make changes in xml that will break the app Sync.replace(self.app_name, Changes.JSHelloWord.XML_INVALID) strings = ['main-page.xml', 'Error: Building UI from XML'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text='Exception') # Revert changes Sync.revert(self.app_name, Changes.JSHelloWord.XML_INVALID) # Verify app is synced and recovered strings = ['Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) assert not self.emu.is_text_visible(text='Exception') # Delete app.js and verify app crash with error activity dialog app_js_origin_path = os.path.join(self.source_project_dir, 'app', 'app.js') app_js_backup_path = os.path.join(self.target_project_dir, 'app', 'app.js') File.delete(app_js_origin_path) # Verify app is synced strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, device=self.emu, run_type=RunType.UNKNOWN) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text='Exception') # Restore app.js and verify app is synced and recovered File.copy(app_js_backup_path, app_js_origin_path) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) assert not self.emu.is_text_visible(text='Exception') @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_100_run_ios_break_and_fix_app(self): """ Make changes in xml that break the app and then changes thet fix the app. Add/remove js files thst break the app and then fix it. Verify recovery. """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim) # Make changes in xml that will break the app Sync.replace(self.app_name, Changes.JSHelloWord.XML_INVALID) strings = ['main-page.xml', 'Error: Building UI from XML'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Revert changes Sync.revert(self.app_name, Changes.JSHelloWord.XML_INVALID) # Verify app is synced and recovered strings = ['Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.old_text) @unittest.skipIf(Settings.HOST_OS == OSType.WINDOWS, 'skip on windows untill we fix wait_rof_log method') def test_105_tns_run_android_changes_in_app_resounces(self): """ Make changes in AndroidManifest.xml in App_Resources and verify this triggers rebuild of the app. Verify that when run on android changes in AppResources/iOS do not trigger rebuild """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu) # Make changes in AndroidManifest.xml manifest_path = os.path.join(self.app_resources_android, 'src', 'main', 'AndroidManifest.xml') File.replace(manifest_path, 'largeScreens="true"', 'largeScreens="false"') # Verify rebuild is triggered and app is synced strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.old_text) # Make changes in AppResources/Android File.copy(os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'android', 'drawable-hdpi', 'icon.png'), os.path.join(self.app_resources_android, 'src', 'main', 'res', 'drawable-hdpi', 'icon.png')) # Verify only build for android is triggered strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) not_existing_strings = ['Xcode build'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings, timeout=120) # https://github.com/NativeScript/nativescript-cli/issues/3658 Tns.kill() # Make changes in AppResources/iOS File.copy(os.path.join('assets', 'resources', 'ios', 'Default.png'), os.path.join(self.app_resources_ios, 'Assets.xcassets', 'LaunchImage.launchimage', 'Default.png')) result = Tns.run_android(app_name=self.app_name, device=self.emu.id) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) # Verify no build is triggered not_existing_strings = ['Xcode build', 'Gradle build'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_105_tns_run_ios_changes_in_app_resounces(self): """ Make changes in AndroidManifest.xml in App_Resources and verify this triggers rebuild of the app. Verify that when run on android changes in AppResources/iOS do not trigger rebuild """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim) # Make changes in app resources, add aditional icon File.copy(os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'ios', 'Default.png'), os.path.join(self.app_resources_ios, 'Assets.xcassets', 'icon.png')) # Verify rebuild is triggered and app is synced strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.UNKNOWN, device=self.sim) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.old_text) # Make changes in AppResources/IOS File.copy(os.path.join(os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'ios', 'Default.png')), os.path.join(self.app_resources_ios, 'Assets.xcassets', 'AppIcon.appiconset', 'icon-20.png')) # Verify only build for ios is triggered strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.UNKNOWN, device=self.sim) not_existing_strings = ['Gradle build'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) # https://github.com/NativeScript/nativescript-cli/issues/3658 Tns.kill() # Make changes in AppResources/Android File.copy(os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'android', 'drawable-hdpi', 'icon.png'), os.path.join(self.app_resources_android, 'src', 'main', 'res', 'drawable-hdpi', 'icon.png')) result = Tns.run_ios(app_name=self.app_name, emulator=True, provision=False) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.UNKNOWN, device=self.sim) # Verify no build is triggered not_existing_strings = ['Xcode build', 'Gradle build'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) def test_110_tns_run_android_release(self): # Run app and verify on device result = Tns.run_android(app_name=self.app_name, release=True, verify=True, emulator=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.FIRST_TIME, device=self.emu) strings.remove('Restarting application on device') strings.remove('Successfully synced application org.nativescript.TestApp on device') # Verify https://github.com/NativeScript/android-runtime/issues/1024 not_existing_strings = ['JS:'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings, timeout=120) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.old_text) blue_count = self.emu.get_pixels_by_color(color=Colors.LIGHT_BLUE) assert blue_count > 100, 'Failed to find blue color on {0}'.format(self.emu.name) Tns.kill() # Make changes in js, css and xml files Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.XML) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.CSS) # Run with --release again and verify changes are deployed on device result = Tns.run_android(app_name=self.app_name, release=True, verify=True, emulator=True) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.new_text) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.new_text) self.emu.wait_for_color(color=Colors.LIGHT_BLUE, pixel_count=blue_count * 2, delta=25) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_110_tns_run_ios_release(self): # Run app and verify on device result = Tns.run_ios(app_name=self.app_name, release=True, verify=True, emulator=True) strings = ['Webpack compilation complete', 'Project successfully built', 'Successfully installed on device'] # Verify console logs are not displayed in release builds not_existing_strings = ['JS:'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.old_text) blue_count = self.sim.get_pixels_by_color(color=Colors.LIGHT_BLUE) assert blue_count > 100, 'Failed to find blue color on {0}'.format(self.sim.name) Tns.kill() # Make changes in js, css and xml files Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.XML) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.CSS) # Run with --release again and verify changes are deployed on device result = Tns.run_ios(app_name=self.app_name, release=True, verify=True, emulator=True) self.sim.wait_for_text(text=Changes.JSHelloWord.JS.new_text) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.new_text) self.sim.wait_for_color(color=Colors.LIGHT_BLUE, pixel_count=blue_count * 2, delta=25) @unittest.skipIf(Settings.HOST_OS == OSType.WINDOWS, 'skip on windows untill we fix wait_rof_log method') def test_115_tns_run_android_add_remove_files_and_folders(self): """ Add/delete files and folders should be synced properly """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu) # Add new file # To verify that file is synced on device we have to refer some function # from it and verify it is executed. We will use console.log app_folder = os.path.join(self.source_project_dir, 'app') new_file = os.path.join(app_folder, 'test.js') renamed_file = os.path.join(app_folder, 'test_2.js') app_js_file = os.path.join(app_folder, 'app.js') File.write(new_file, "console.log('test.js synced!!!');") File.append(app_js_file, "require('./test.js');") strings = ["JS: test.js synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Rename file os.rename(new_file, renamed_file) File.replace(renamed_file, 'test.js', 'renamed file') time.sleep(1) File.replace(app_js_file, 'test.js', 'test_2.js') strings = ["JS: renamed file synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Delete file File.delete(renamed_file) strings = ["Module build failed: Error: ENOENT", 'Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text='Exception') File.replace(app_js_file, "require('./test_2.js');", ' ') strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, device=self.emu, run_type=RunType.UNKNOWN) not_existing_strings = ['12345'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) # Add folder folder_name = os.path.join(app_folder, 'test_folder') new_file = os.path.join(folder_name, 'test_in_folder.js') Folder.create(folder_name) File.write(new_file, "console.log('test_in_folder.js synced!!!');") File.append(app_js_file, "require('./test_folder/test_in_folder.js');") strings = ["JS: test_in_folder.js synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Delete folder Folder.clean(folder_name) strings = ["Module build failed: Error: ENOENT"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text='Exception') @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_115_tns_run_ios_add_remove_files_and_folders(self): """ Add/delete files and folders should be synced properly """ # Run app and verify on device result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim) # Add new file # To verify that file is synced on device we have to refer some function # from it and verify it is executed. We will use console.log app_folder = os.path.join(self.source_project_dir, 'app') new_file = os.path.join(app_folder, 'test.js') renamed_file = os.path.join(app_folder, 'test_2.js') app_js_file = os.path.join(app_folder, 'main-view-model.js') File.write(new_file, "console.log('test.js synced!!!');") File.append(app_js_file, "require('./test.js');") strings = ["test.js synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Rename file os.rename(new_file, renamed_file) File.replace(renamed_file, 'test.js', 'renamed file') time.sleep(1) File.replace(app_js_file, 'test.js', 'test_2.js') strings = ["renamed file synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Delete file File.delete(renamed_file) strings = ["Module build failed: Error: ENOENT", "NativeScript debugger detached"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) File.replace(app_js_file, "require('./test_2.js');", ' ') strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, device=self.sim, run_type=RunType.UNKNOWN) not_existing_strings = ['123'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) # Add folder folder_name = os.path.join(app_folder, 'test_folder') new_file = os.path.join(folder_name, 'test_in_folder.js') Folder.create(folder_name) File.write(new_file, "console.log('test_in_folder.js synced!!!');") File.append(app_js_file, "require('./test_folder/test_in_folder.js');") strings = ["test_in_folder.js synced!!!"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) # Delete folder Folder.clean(folder_name) strings = ["Module build failed: Error: ENOENT"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) def test_120_tns_run_android_just_launch(self): """ This test verify following things: 1. `--justlaunch` option release the console. 2. Full rebuild and prepare are not trigerred if no changes are done. 3. Incremental prepare is triggered if js, xml and css files are changed. """ # Run app with --justlaunch and verify on device run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, just_launch=True) # On some machines it takes time for thr process to die time.sleep(5) assert not Process.is_running_by_commandline(Settings.Executables.TNS) # Execute run with --justlaunch again and verify no rebuild is triggered result = Tns.run_android(app_name=self.app_name, emulator=True, just_launch=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.JUST_LAUNCH, device=self.emu, just_launch=True) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Make changes in js, css and xml files Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.XML) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.CSS) # Execute run with --justlaunch again and verify prepare is triggered result = Tns.run_android(app_name=self.app_name, emulator=True, just_launch=True) strings = ['Project successfully prepared', 'Webpack compilation complete'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.new_text) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_120_tns_run_ios_just_launch(self): """ This test verify following things: 1. `--justlaunch` option release the console. 2. Full rebuild and prepare are not trigerred if no changes are done. 3. Incremental prepare is triggered if js, xml and css files are changed. """ # Run app with --justlaunch and verify on device result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim, just_launch=True) # On some machines it takes time for thr process to die time.sleep(5) assert not Process.is_running_by_commandline(Settings.Executables.TNS) # Execute run with --justlaunch again and verify no rebuild is triggered result = Tns.run_ios(app_name=self.app_name, emulator=True, just_launch=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.JUST_LAUNCH, device=self.sim, just_launch=True) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Make changes in js, css and xml files Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.JS) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.XML) Sync.replace(app_name=self.app_name, change_set=Changes.JSHelloWord.CSS) # Execute run with --justlaunch again and verify prepare is triggered result = Tns.run_ios(app_name=self.app_name, emulator=True, just_launch=True) strings = ['Project successfully prepared', 'Webpack compilation complete'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.new_text) @unittest.skip("Skip because of https://github.com/NativeScript/nativescript-cli/issues/4607") def test_290_tns_run_android_should_refresh_images(self): """ Test for https://github.com/NativeScript/nativescript-cli/issues/2981 """ # Update app to reference picture from app folder source_file = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'issues', 'nativescript-cli-2981', 'main-page.xml') dest_file = os.path.join(self.app_path, 'app', 'main-page.xml') File.copy(source_file, dest_file) # Copy image file to app folder source_file = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'star.png') dest_file = os.path.join(self.app_path, 'app', 'test.png') File.copy(source_file, dest_file) result = Tns.run_android(app_name=self.app_name, verify=True, device=self.emu.id) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.FIRST_TIME, device=self.emu) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) yellow_count = self.emu.get_pixels_by_color(color=Colors.YELLOW_ICON) green_count = self.emu.get_pixels_by_color(color=Colors.GREEN_ICON) # Verify the referenced image file is displayed on device screen assert yellow_count > 0, 'Failed to find yellow color on {0}'.format(self.emu.name) assert green_count == 0, 'Found green color on {0}'.format(self.emu.name) # Change the image file source_file = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'resources', 'android', 'drawable-hdpi', 'background.png') dest_file = os.path.join(self.app_path, 'app', 'test.png') File.copy(source_file, dest_file) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Verify the new image is synced and displayed on device screen yellow_count = self.emu.get_pixels_by_color(color=Colors.YELLOW_ICON) green_count = self.emu.get_pixels_by_color(color=Colors.GREEN_ICON) assert green_count > 0, 'Failed to find green color on {0}'.format(self.emu.name) assert yellow_count == 0, 'Found yellow color on {0}'.format(self.emu.name) @unittest.skipIf(Settings.HOST_OS == OSType.WINDOWS, 'skip on windows untill we fix wait_rof_log method') def test_300_tns_run_android_clean(self): """ If set --clean rebuilds the native project """ # Run the project once so it is build for the first time run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu) # Verify run --clean without changes skip prepare and rebuild of native project result = Tns.run_android(app_name=self.app_name, verify=True, device=self.emu.id, clean=True, just_launch=True) strings = ['Preparing project', 'Building project', 'Gradle clean', 'Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.old_text) # Verify if changes are applied and then run with clean it will apply changes on device # Verify https://github.com/NativeScript/nativescript-cli/issues/2670 run --clean does # clean build only the first time Sync.replace(self.app_name, Changes.JSHelloWord.XML) result = Tns.run_android(app_name=self.app_name, verify=True, device=self.emu.id, clean=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.FULL, device=self.emu) strings.append('Gradle clean') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) self.emu.wait_for_text(text=Changes.JSHelloWord.XML.new_text) # Make changes again and verify changes are synced and clean build is not triggered again Sync.revert(self.app_name, Changes.JSHelloWord.XML) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.INCREMENTAL, device=self.emu, file_name='main-page.xml') not_existing_strings = ['Gradle clean'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_300_tns_run_ios_clean(self): """ If set --clean rebuilds the native project """ # Run the project once so it is build for the first time result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim, just_launch=True) # Verify run --clean without changes rebuilds native project result = Tns.run_ios(app_name=self.app_name, verify=True, device=self.sim.id, clean=True, just_launch=True) strings = ['Building project', 'Xcode build...', 'Successfully synced application'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.old_text) # Verify if changes are applied and then run with clean it will apply changes on device # Verify https://github.com/NativeScript/nativescript-cli/issues/2670 run --clean does # clean build only the first time Sync.replace(self.app_name, Changes.JSHelloWord.XML) result = Tns.run_ios(app_name=self.app_name, verify=True, device=self.sim.id, clean=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.FULL, device=self.sim) strings.append('Xcode build...') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.sim.wait_for_text(text=Changes.JSHelloWord.XML.new_text) # Make changes again and verify changes are synced and clean build is not triggered again Sync.revert(self.app_name, Changes.JSHelloWord.XML) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.INCREMENTAL, device=self.sim, file_name='main-page.xml') not_existing_strings = ['Xcode build...'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, not_existing_string_list=not_existing_strings) @unittest.skip("Skip because of https://github.com/NativeScript/nativescript-dev-webpack/issues/899") def test_310_tns_run_android_sync_changes_in_node_modules(self): """ Verify changes in node_modules are synced during run command """ # Run the project result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, sync_all_files=True) # Make code changes in tns-core-modules verify livesync is triggered Sync.replace(self.app_name, Changes.NodeModules.TNS_MODULES) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.INCREMENTAL, device=self.emu, file_name='application-common.js') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) @unittest.skip("Skip because of https://github.com/NativeScript/nativescript-dev-webpack/issues/899") @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_310_tns_run_ios_sync_changes_in_node_modules(self): """ Verify changes in node_modules are synced during run command """ # Run the project result = run_hello_world_js_ts(self.app_name, Platform.IOS, self.sim, sync_all_files=True) # Make code changes in tns-core-modules verify livesync is triggered Sync.replace(self.app_name, Changes.NodeModules.TNS_MODULES) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.INCREMENTAL, device=self.emu, file_name='application-common.js') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) def test_315_tns_run_android_sync_changes_in_aar_files(self): """ Livesync should sync aar file changes inside a plugin https://github.com/NativeScript/nativescript-cli/issues/3610 """ # Add plugin and run the project Tns.plugin_add('nativescript-camera', self.app_name) result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu) # Make changes in nativescript-camera .aar file and verify livesync is triggered new_aar = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'issues', 'nativescript-cli-3932', 'nativescript-ui-listview', 'platforms', 'android', 'TNSListView-release.aar') target_aar = os.path.join(self.app_name, 'node_modules', 'nativescript-camera', 'platforms', 'android') File.copy(new_aar, target_aar) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.ANDROID, run_type=RunType.UNKNOWN, device=self.emu) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) self.emu.wait_for_text(text=Changes.JSHelloWord.JS.old_text) def test_320_tns_run_android_should_warn_if_package_ids_dont_match(self): """ If bundle identifiers in package.json and app.gradle do not match CLI should warn the user. """ # Change app id in app.gradle file app_gradle = os.path.join(Settings.TEST_RUN_HOME, self.app_name, 'app', 'App_Resources', 'Android', 'app.gradle') File.replace(app_gradle, old_string='generatedDensities = []', new_string='applicationId = "org.nativescript.MyApp"') # Run the app on device and verify the warnings result = Tns.run_android(app_name=self.app_name, just_launch=False) strings = ["WARNING: The Application identifier is different from the one inside \"package.json\" file.", "NativeScript CLI might not work properly.", "Project successfully built"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_320_tns_run_ios_should_warn_if_package_ids_dont_match(self): """ If bundle identifiers in package.json and Info.plist do not match CLI should warn the user. """ # Change app id in app.gradle file old_string = "<string>${EXECUTABLE_NAME}</string>" new_string = "<string>${EXECUTABLE_NAME}</string>" \ "<key>CFBundleIdentifier</key>" \ "<string>org.nativescript.myapp</string>" info_plist = os.path.join(Settings.TEST_RUN_HOME, self.app_resources_ios, 'Info.plist') File.replace(info_plist, old_string, new_string) # Run the app on device and verify the warnings result = Tns.run_ios(app_name=self.app_name, just_launch=False) strings = ["[WARNING]: The CFBundleIdentifier key inside the 'Info.plist' will be overriden", "Project successfully built"] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) def test_325_tns_run_android_should_start_emulator(self): """ `tns run android` should start emulator if device is not connected. """ # Run the test only if there are no connected devices conected_devices = Adb.get_ids() if conected_devices.__len__() == 0: DeviceManager.Emulator.stop() result = Tns.run_android(self.app_name) strings = ['Starting Android emulator with image'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) DeviceManager.Emulator.stop() DeviceManager.Emulator.ensure_available(Settings.Emulators.DEFAULT) else: raise nose.SkipTest('This test is not valid when devices are connected.') @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_325_tns_run_ios_should_start_simulator(self): """ `tns run android` should start emulator if device is not connected. """ # Run the test only if there are no connected devices conected_devices = DeviceManager.get_devices(device_type=DeviceType.IOS) if conected_devices.__len__() == 0: DeviceManager.Simulator.stop() result = Tns.run_ios(self.app_name) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.FULL, device=self.sim) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120) DeviceManager.Simulator.stop() DeviceManager.Simulator.ensure_available(Settings.Simulators.DEFAULT) else: raise nose.SkipTest('This test is not valid when devices are connected.') @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_345_tns_run_ios_source_code_in_ios_part_plugin(self): """ https://github.com/NativeScript/nativescript-cli/issues/3650 """ # Add plugin with source code in iOS part of the plugin plugin_path = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'plugins', 'sample-plugin', 'src') Tns.plugin_add(plugin_path, path=self.app_name, verify=True) # Call method from the source code of the plugin in main-view-model.js old_value = 'viewModel.counter = 42;' new_value = 'viewModel.counter = 42;\n var objTC = new TestClass();\n console.log(objTC.sayHey());' target_js = os.path.join(Settings.TEST_RUN_HOME, self.app_name, 'app', 'main-view-model.js') File.replace(target_js, old_value, new_value) result = Tns.run_ios(self.app_name, emulator=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.FIRST_TIME, device=self.sim) strings.append('Hey!') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Verify app looks correct inside simulator self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_350_tns_run_ios_source_code_in_app_resources(self): """ https://github.com/NativeScript/nativescript-cli/issues/4343 """ # Add plugin with source code in iOS part of the plugin source_path = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'issues', 'nativescript-cli-4343', 'src') dest_path = os.path.join(self.app_resources_ios, 'src') Folder.copy(source_path, dest_path, clean_target=False) # Call method from the source code of the plugin in main-view-model.js old_value = 'viewModel.counter = 42;' new_value = 'viewModel.counter = 42;\n var objTC = new TestClass2();\n console.log(objTC.sayHey());' target_js = os.path.join(Settings.TEST_RUN_HOME, self.app_name, 'app', 'main-view-model.js') File.replace(target_js, old_value, new_value) result = Tns.run_ios(self.app_name, emulator=True) strings = TnsLogs.run_messages(app_name=self.app_name, platform=Platform.IOS, run_type=RunType.FIRST_TIME, device=self.sim) strings.append('Hey Native!') TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings) # Verify app looks correct inside simulator self.sim.wait_for_text(text=Changes.JSHelloWord.JS.old_text) # @unittest.skip("Webpack only") def test_355_tns_run_android_delete_node_modules(self): """ Run should not fail if node_modules folder is deleted https://github.com/NativeScript/nativescript-cli/issues/3944 """ # Run the project with --justLaunch run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, just_launch=True) # Delete node_modules node_modules = os.path.join(Settings.TEST_RUN_HOME, self.app_name, 'node_modules') Folder.clean(node_modules) # Run the project again, verify it is build and node_modules folder exists run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, just_launch=True) assert Folder.exists(node_modules) # @unittest.skip("Webpack only") @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_360_tns_run_ios_on_folder_with_spaces(self): """ `tns run ios` for apps with spaces """ Tns.create(app_name=self.app_name_space, template=Template.HELLO_WORLD_JS.local_package, update=True) app_name = '"' + self.app_name_space + '"' run_hello_world_js_ts(app_name, Platform.ANDROID, self.emu, just_launch=True) @unittest.skip("Skip this test due to emulator api28 ui crashing when no space left on device") @unittest.skipIf(Settings.HOST_OS != OSType.OSX, '`shell cp -r` fails on emulators on Linux and Win.') def test_365_tns_run_android_should_respect_adb_errors(self): """ If device memory is full and error is thrown during deploy cli should respect it https://github.com/NativeScript/nativescript-cli/issues/2170 """ # Deploy the app to make sure we have something at /data/data/org.nativescript.TestApp result = run_hello_world_js_ts(self.app_name, Platform.ANDROID, self.emu, just_launch=True) # Use all the disk space on emulator dest_file = '/data/data/' + TnsPaths.get_bundle_id(self.app_name) for index in range(1, 3000): command = "shell 'su 0 cp -r {0} {0}{1}'".format(dest_file, str(index)) result = Adb.run_adb_command(device_id=self.emu.id, command=command) Log.info(result.output) if "No space left on device" in result.output: break # Create new app Tns.create(app_name='TestApp2', template=Template.HELLO_WORLD_JS.local_package, update=True) # Run the app and verify there is appropriate error result = Tns.run_android('TestApp2', verify=True, device=self.emu.id, just_launch=True) strings = ['No space left on device'] TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=120)
class BuildTests(TnsTest): app_name = Settings.AppName.DEFAULT app_name_with_space = Settings.AppName.WITH_SPACE app_path = TnsPaths.get_app_path(app_name=app_name) app_temp_path = os.path.join(Settings.TEST_RUN_HOME, 'data', 'temp', 'TestApp') debug_apk = "app-debug.apk" app_identifier = "org.nativescript.testapp" temp_folder = os.path.join(app_path, 'temp') @classmethod def setUpClass(cls): TnsTest.setUpClass() Docker.start() Tns.create(app_name=cls.app_name, template=Template.HELLO_WORLD_JS.local_package, update=True) Tns.create(cls.app_name_with_space, template=Template.HELLO_WORLD_JS.local_package, update=True) Tns.platform_add_android(cls.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) Tns.platform_add_android(app_name='"' + cls.app_name_with_space + '"', framework_path=Settings.Android.FRAMEWORK_PATH, verify=False) if Settings.HOST_OS is OSType.OSX: Tns.platform_add_ios(cls.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) Folder.copy(cls.app_path, cls.app_temp_path) def setUp(self): TnsTest.setUp(self) Folder.clean(self.app_path) Folder.copy(self.app_temp_path, self.app_path) def tearDown(self): TnsTest.tearDown(self) @classmethod def tearDownClass(cls): TnsTest.tearDownClass() Docker.stop() Folder.clean(TnsPaths.get_app_path(app_name=cls.app_temp_path)) Folder.clean(TnsPaths.get_app_path(cls.app_name_with_space)) def test_001_build_android(self): Tns.build_android(self.app_name) assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.plist')) assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.android.js')) assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.ios.js')) src = os.path.join(self.app_name, 'app', 'app.js') dest_1 = os.path.join(self.app_name, 'app', 'new.android.js') dest_2 = os.path.join(self.app_name, 'app', 'new.ios.js') File.copy(src, dest_1) File.copy(src, dest_2) result = Tns.build_android(self.app_name) assert "Gradle build..." in result.output, "Gradle build not called." assert result.output.count("Gradle build...") == 1, "Only one gradle build is triggered." assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.plist')) assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.android.js')) assert not File.exists(os.path.join(TnsPaths.get_platforms_android_folder(self.app_name), '*.ios.js')) # Verify apk does not contain aar files apk_path = TnsPaths.get_apk_path(app_name=self.app_name, release=False) File.unzip(apk_path, self.temp_folder) # Clean META-INF folder. It contains com.android.support.... files which are expected to be there due to # https://github.com/NativeScript/nativescript-cli/pull/3923 Folder.clean(os.path.join(self.temp_folder, 'META-INF')) assert not File.pattern_exists(self.temp_folder, '*.aar') assert not File.pattern_exists(self.temp_folder, '*.plist') assert not File.pattern_exists(self.temp_folder, '*.android.*') assert not File.pattern_exists(self.temp_folder, '*.ios.*') # Verify app is built with android sdk 29 by default TnsAssert.string_in_android_manifest(apk_path, 'compileSdkVersion="29"') Folder.clean(self.temp_folder) # Verify incremental native build result = Tns.exec_command(command='build --clean', path=self.app_name, platform=Platform.ANDROID) assert "Gradle clean..." in result.output, "Gradle clean is not called." assert "Gradle build..." in result.output, "Gradle build is not called." assert result.output.count("Gradle build...") == 1, "More than 1 gradle build is triggered." 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 test_301_build_project_with_space_release(self): # Ensure ANDROID_KEYSTORE_PATH contain spaces (verification for CLI issue 2650) Folder.create("with space") file_name = os.path.basename(Settings.Android.ANDROID_KEYSTORE_PATH) cert_with_space_path = os.path.join("with space", file_name) File.copy(Settings.Android.ANDROID_KEYSTORE_PATH, cert_with_space_path) Tns.build_android(app_name='"' + self.app_name_with_space + '"', release=True) output = File.read(os.path.join(self.app_name_with_space, "package.json")) assert self.app_identifier in output.lower() output = File.read(os.path.join(TnsPaths.get_platforms_android_src_main_path(self.app_name_with_space), 'AndroidManifest.xml')) assert self.app_identifier in output.lower() def test_302_build_project_with_space_debug_with_plugin(self): # skip remove platform because androidx is not released official app_space_path = TnsPaths.get_app_path(app_name=self.app_name_with_space) # Tns.platform_remove(app_name='"' + self.app_name_with_space + '"', platform=Platform.ANDROID) Npm.install(package='nativescript-mapbox', option='--save', folder=app_space_path) result = Tns.build_android(app_name='"' + self.app_name_with_space + '"') assert "Project successfully built" in result.output def test_310_build_android_with_custom_compile_sdk_new(self): Tns.platform_remove(self.app_name, platform=Platform.ANDROID) Tns.platform_add_android(self.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) Tns.exec_command(command='build --compileSdk 28', path=self.app_name, platform=Platform.ANDROID, bundle=True) File.delete(self.debug_apk) Tns.exec_command(command='build --copy-to ./', path=self.app_name, platform=Platform.ANDROID, bundle=True) assert File.exists(self.debug_apk) File.delete(self.debug_apk) def test_441_android_typings(self): Tns.exec_command(command='build --androidTypings', path=self.app_name, platform=Platform.ANDROID, bundle=True) assert File.exists(os.path.join(self.app_name, 'android.d.ts')) assert File.exists(os.path.join(self.app_name, 'android-declarations.d.ts')) def test_450_resources_update_android(self): target_app = os.path.join(self.app_name, 'app', 'App_Resources') source_app = os.path.join(TEST_RUN_HOME, 'assets', 'apps', 'test-app-js-41', 'app', 'App_Resources') Folder.clean(target_app) Folder.copy(source_app, target_app) result = Tns.exec_command(command='resources update android', path=self.app_name) assert "Successfully updated your project's application resources '/Android' directory structure" in \ result.output assert "The previous version of your Android application resources has been renamed to '/Android-Pre-v4'" in \ result.output assert File.exists(os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'Android-Pre-v4', 'app.gradle')) assert File.exists(os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'Android', 'app.gradle')) assert File.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'AndroidManifest.xml')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'assets')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'java')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'res', 'values')) Tns.prepare_android(self.app_name) assert File.exists( os.path.join(TnsPaths.get_platforms_android_src_main_path(self.app_name), 'AndroidManifest.xml')) def test_451_resources_update(self): target_app = os.path.join(self.app_name, 'app', 'App_Resources') source_app = os.path.join(TEST_RUN_HOME, 'assets', 'apps', 'test-app-js-41', 'app', 'App_Resources') Folder.clean(target_app) Folder.copy(source_app, target_app) result = Tns.exec_command(command='resources update', path=self.app_name) assert "Successfully updated your project's application resources '/Android' directory structure" in \ result.output assert "The previous version of your Android application resources has been renamed to '/Android-Pre-v4'" in \ result.output assert File.exists(os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'Android-Pre-v4', 'app.gradle')) assert File.exists(os.path.join(TnsPaths.get_path_app_resources(self.app_name), 'Android', 'app.gradle')) assert File.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'AndroidManifest.xml')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'assets')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'java')) assert Folder.exists(os.path.join(TnsPaths.get_path_app_resources_main_android(self.app_name), 'res', 'values')) Tns.prepare_android(self.app_name) assert File.exists( os.path.join(TnsPaths.get_platforms_android_src_main_path(self.app_name), 'AndroidManifest.xml')) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') 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 @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_190_build_ios_distribution_provisions(self): Tns.platform_remove(self.app_name, platform=Platform.ANDROID) result = Tns.exec_command(command='build ios --provision', path=self.app_name) assert "Provision Name" in result.output assert "Provision UUID" in result.output assert "App Id" in result.output assert "Team" in result.output assert "Type" in result.output assert "Due" in result.output assert "Devices" in result.output assert Settings.IOS.PROVISIONING in result.output assert Settings.IOS.DISTRIBUTION_PROVISIONING in result.output assert Settings.IOS.DEVELOPMENT_TEAM in result.output # Build with correct distribution provision Tns.build_ios(self.app_name, provision=Settings.IOS.DISTRIBUTION_PROVISIONING, for_device=True, release=True) # Verify that passing wrong provision shows user friendly error result = Tns.build_ios(self.app_name, provision="fake", verify=False) assert "Failed to find mobile provision with UUID or Name: fake" in result.output @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_310_build_ios_with_copy_to(self): Tns.platform_remove(self.app_name, platform=Platform.IOS) Tns.exec_command(command='build --copy-to ' + TEST_RUN_HOME, path=self.app_name, platform=Platform.IOS, bundle=True) assert Folder.exists(os.path.join(TEST_RUN_HOME, 'TestApp.app')) Tns.exec_command(command='build --copy-to ' + TEST_RUN_HOME, path=self.app_name, platform=Platform.IOS, bundle=True, for_device=True, release=True, provision=Settings.IOS.PROVISIONING) assert File.exists(os.path.join(TEST_RUN_HOME, 'TestApp.ipa')) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_320_build_ios_with_custom_entitlements(self): # Add entitlements in app/App_Resources/iOS/app.entitlements source = os.path.join(TEST_RUN_HOME, 'assets', 'entitlements', 'app.entitlements') target = os.path.join(self.app_name, 'app', 'App_Resources', 'iOS', 'app.entitlements') File.copy(source, target) # Build again and verify entitlements are merged Tns.build_ios(self.app_name) entitlements_path = os.path.join(TnsPaths.get_platforms_ios_folder(self.app_name), self.app_name, 'TestApp.entitlements') assert File.exists(entitlements_path), "Entitlements file is missing!" entitlements_content = File.read(entitlements_path) assert '<key>aps-environment</key>' in entitlements_content, "Entitlements file content is wrong!" assert '<string>development</string>' in entitlements_content, "Entitlements file content is wrong!" # Install plugin with entitlements, build again and verify entitlements are merged plugin_path = os.path.join(TEST_RUN_HOME, 'assets', 'plugins', 'nativescript-test-entitlements-1.0.0.tgz') Npm.install(package=plugin_path, option='--save', folder=self.app_name) Tns.build_ios(self.app_name) entitlements_content = File.read(entitlements_path) assert '<key>aps-environment</key>' in entitlements_content, "Entitlements file content is wrong!" assert '<string>development</string>' in entitlements_content, "Entitlements file content is wrong!" assert '<key>inter-app-audio</key>' in entitlements_content, "Entitlements file content is wrong!" assert '<true/>' in entitlements_content, "Entitlements file content is wrong!" # Build in release, for device (provision without entitlements) result = Tns.build_ios(self.app_name, for_device=True, release=True, verify=False) assert "Provisioning profile" in result.output assert "doesn't include the aps-environment and inter-app-audio entitlements" in result.output
class TemplateTests(TnsRunTest): app_name = Settings.AppName.DEFAULT app_folder = TnsPaths.get_app_path(app_name=app_name) test_data = [ [Template.BLANK_JS.name, Template.BLANK_JS], [Template.BLANK_TS.name, Template.BLANK_TS], [Template.BLANK_NG.name, Template.BLANK_NG], [Template.VUE_BLANK.name, Template.VUE_BLANK], [Template.DRAWER_NAVIGATION_JS.name, Template.DRAWER_NAVIGATION_JS], [Template.DRAWER_NAVIGATION_TS.name, Template.DRAWER_NAVIGATION_TS], [Template.DRAWER_NAVIGATION_NG.name, Template.DRAWER_NAVIGATION_NG], [Template.DRAWER_NAVIGATION_VUE.name, Template.DRAWER_NAVIGATION_VUE], [Template.HELLO_WORLD_JS.name, Template.HELLO_WORLD_JS], [Template.HELLO_WORLD_TS.name, Template.HELLO_WORLD_TS], [Template.HELLO_WORLD_NG.name, Template.HELLO_WORLD_NG], [ Template.MASTER_DETAIL_KINVEY_JS.name, Template.MASTER_DETAIL_KINVEY_JS ], [ Template.MASTER_DETAIL_KINVEY_TS.name, Template.MASTER_DETAIL_KINVEY_TS ], [ Template.MASTER_DETAIL_KINVEY_NG.name, Template.MASTER_DETAIL_KINVEY_NG ], [Template.MASTER_DETAIL_JS.name, Template.MASTER_DETAIL_JS], [Template.MASTER_DETAIL_TS.name, Template.MASTER_DETAIL_TS], [Template.MASTER_DETAIL_NG.name, Template.MASTER_DETAIL_NG], [Template.MASTER_DETAIL_VUE.name, Template.MASTER_DETAIL_VUE], [Template.TAB_NAVIGATION_JS.name, Template.TAB_NAVIGATION_JS], [Template.TAB_NAVIGATION_TS.name, Template.TAB_NAVIGATION_TS], [Template.TAB_NAVIGATION_NG.name, Template.TAB_NAVIGATION_NG], [Template.TAB_NAVIGATION_VUE.name, Template.TAB_NAVIGATION_VUE] ] @parameterized.expand(test_data) def test(self, template_name, template_info): TnsRunTest.setUp(self) # Create app app_name = template_info.name.replace('template-', '') Tns.create(app_name=app_name, template='tns-' + template_name, update=False) if Settings.ENV != EnvironmentType.LIVE and Settings.ENV != EnvironmentType.PR: App.update(app_name=app_name) # Run Android result = Tns.run_android(app_name=app_name, device=self.emu.id) strings = TnsLogs.run_messages(app_name=app_name, run_type=RunType.UNKNOWN, platform=Platform.ANDROID) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=300) if template_info.texts is not None: for text in template_info.texts: self.emu.wait_for_text(text=text, timeout=60) else: self.emu.wait_for_main_color(color=Colors.WHITE, timeout=60) # Run iOS if Settings.HOST_OS is OSType.OSX: Simctl.uninstall_all(simulator_info=self.sim) result = Tns.run_ios(app_name=app_name, device=self.sim.id) strings = TnsLogs.run_messages(app_name=app_name, run_type=RunType.UNKNOWN, platform=Platform.IOS) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=300) if template_info.texts is not None: for text in template_info.texts: self.sim.wait_for_text(text=text, timeout=60) else: self.sim.wait_for_main_color(color=Colors.WHITE, timeout=60) # Cleanup Folder.clean(os.path.join(Settings.TEST_RUN_HOME, app_name)) TnsRunTest.tearDown(self)
class PluginTests(TnsTest): app_name = Settings.AppName.DEFAULT app_path = TnsPaths.get_app_path(app_name=app_name) app_temp_path = os.path.join(Settings.TEST_RUN_HOME, 'data', 'temp', 'TestApp') @classmethod def setUpClass(cls): TnsTest.setUpClass() Tns.create(app_name=cls.app_name, template=Template.HELLO_WORLD_JS.local_package, update=True) Tns.platform_add_android( cls.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) if Settings.HOST_OS is OSType.OSX: Tns.platform_add_ios(cls.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) Folder.copy(cls.app_path, cls.app_temp_path) def setUp(self): TnsTest.setUp(self) Folder.clean(self.app_path) Folder.copy(self.app_temp_path, self.app_path) def tearDown(self): TnsTest.tearDown(self) @classmethod def tearDownClass(cls): TnsTest.tearDownClass() Folder.clean(cls.app_temp_path) def test_100_plugin_add_after_platform_add_android(self): result = Tns.plugin_add(plugin_name='tns-plugin', path=self.app_name) assert 'Successfully installed plugin tns-plugin' in result.output assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'index.js')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'package.json')) output = File.read(os.path.join(self.app_path, 'package.json')) assert 'org.nativescript.TestApp' in output assert 'dependencies' in output assert 'tns-plugin' in output def test_101_plugin_add_prepare_verify_apk_android(self): Tns.plugin_add(plugin_name='tns-plugin', path=self.app_name) Tns.build_android(app_name=self.app_name) assert File.exists(os.path.join(TnsPaths.get_apk_path(self.app_name))) # assert File.exists(os.path.join(TnsPaths.get_platforms_android_npm_modules(self.app_name), 'tns-plugin', # 'index.js')) def test_102_plugin_add_verify_command_list_used_plugins_android(self): Tns.plugin_add(plugin_name='tns-plugin', path=self.app_name) Tns.prepare_android(app_name=self.app_name) result = Tns.exec_command(command='plugin', path=self.app_name) assert 'tns-plugin' in result.output @unittest.skip("Webpack only") def test_200_plugin_platforms_should_not_exist_in_tns_modules_android( self): """ Test for issue https://github.com/NativeScript/nativescript-cli/issues/3932 """ issue_path = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'issues', 'nativescript-cli-3932') Tns.platform_remove(app_name=self.app_name, platform=Platform.ANDROID) Tns.plugin_add(plugin_name='nativescript-ui-listview', path=self.app_name) Folder.clean(os.path.join(self.app_name, 'node_modules')) File.delete(os.path.join(self.app_name, 'package.json')) copy = os.path.join(issue_path, 'nativescript-ui-listview') paste = os.path.join(self.app_path, 'nativescript-ui-listview') Folder.copy(copy, paste) copy = os.path.join(issue_path, 'package.json') paste = os.path.join(self.app_name) File.copy(copy, paste) Tns.platform_add_android( app_name=self.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) folder_path = os.path.join(self.app_path, 'nativescript-ui-listview') Npm.install(option='--ignore-scripts', folder=folder_path) Tns.build_android(app_name=self.app_name, bundle=False) app_path = os.path.join( TnsPaths.get_platforms_android_npm_modules(self.app_name)) assert not File.exists( os.path.join(app_path, 'nativescript-ui-listview', 'node_modules', 'nativescript-ui-core', 'platforms')) @unittest.skip("Webpack only") def test_210_plugin_with_promise_in_hooks_android(self): Tns.plugin_add(plugin_name='[email protected]', path=self.app_name) result = Tns.prepare_android(app_name=self.app_name, verify=False) assert 'Failed to execute hook' in result.output assert 'nativescript-fabric.js' in result.output assert 'TypeError' not in result.output assert 'Cannot read property' not in result.output def test_302_plugin_and_npm_modules_in_same_project_android(self): Tns.plugin_add(plugin_name='nativescript-social-share', path=self.app_name) output = Npm.install(package='nativescript-appversion', option='--save', folder=self.app_path) assert 'ERR!' not in output assert 'nativescript-appversion@' in output Tns.build_android(app_name=self.app_name, verify=False) def test_410_plugin_remove_should_not_fail_if_plugin_name_has_dot_android( self): """ Test for issue https://github.com/NativeScript/nativescript-cli/issues/3451 """ Tns.platform_remove(app_name=self.app_name, platform=Platform.ANDROID) Tns.plugin_add(plugin_name='[email protected]', path=self.app_name) assert Folder.exists( os.path.join(self.app_path, 'node_modules', 'nativescript-socket.io')) result = Tns.plugin_remove(plugin_name='nativescript-socket.io', path=self.app_name, log_trace=True) assert 'Successfully removed plugin nativescript-socket.io' in result.output assert 'stdout: removed 1 package' in result.output assert 'Exec npm uninstall nativescript-socket.io --save' in result.output output = File.read(os.path.join(self.app_path, 'package.json')) assert 'nativescript-socket.io' not in output @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_101_plugin_add_prepare_verify_app_ios(self): Tns.plugin_add(plugin_name='tns-plugin', path=self.app_name) Tns.build_ios(app_name=self.app_name) path_app = os.path.join(TnsPaths.get_ipa_path(self.app_name)) assert Folder.exists(path_app) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_201_build_app_for_both_platforms(self): Tns.plugin_add(plugin_name='tns-plugin', path=self.app_name) # Verify files of the plugin assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'index.js')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'package.json')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'test.android.js')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'test.ios.js')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'test2.android.xml')) assert File.exists( os.path.join(TnsPaths.get_app_node_modules_path(self.app_name), 'tns-plugin', 'test2.ios.xml')) Tns.build_ios(app_name=self.app_name) Tns.build_android(app_name=self.app_name) apk_path = os.path.join(TnsPaths.get_apk_path(self.app_name)) output = Adb.get_package_permission(apk_path) assert 'android.permission.READ_EXTERNAL_STORAGE' in output assert 'android.permission.WRITE_EXTERNAL_STORAGE' in output assert 'android.permission.INTERNET' in output @unittest.skip("Webpack only") @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_311_plugin_platforms_should_not_exist_in_tnsmodules_ios(self): """ Test for issue https://github.com/NativeScript/nativescript-cli/issues/3932 """ Tns.platform_remove(app_name=self.app_name, platform=Platform.IOS) Tns.plugin_add(plugin_name='nativescript-ui-listview', path=self.app_name) Folder.clean(os.path.join(self.app_name, 'node_modules')) File.delete(os.path.join(self.app_name, 'package.json')) copy = os.path.join('assets', 'issues', 'nativescript-cli-3932', 'nativescript-ui-listview') paste = os.path.join(self.app_name, 'nativescript-ui-listview') Folder.copy(copy, paste) copy = os.path.join('assets', 'issues', 'nativescript-cli-3932', 'package.json') paste = os.path.join(self.app_name) File.copy(copy, paste) Tns.platform_add_ios(app_name=self.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) folder_path = os.path.join(self.app_name, 'nativescript-ui-listview') Npm.install(option='--ignore-scripts', folder=folder_path) Tns.build_ios(app_name=self.app_name, bundle=False) app_path = os.path.join( TnsPaths.get_platforms_ios_folder(self.app_name)) assert not File.exists( os.path.join(app_path, 'nativescript-ui-listview', 'node_modules', 'nativescript-ui-core', 'platforms')) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_320_cfbundleurltypes_overridden_from_plugin_ios(self): """ Test for issue https://github.com/NativeScript/nativescript-cli/issues/2936 """ Tns.platform_remove(app_name=self.app_name, platform=Platform.IOS) plugin_path = os.path.join(Settings.TEST_RUN_HOME, 'assets', 'plugins', 'CFBundleURLName-Plugin.tgz') Tns.plugin_add(plugin_path, path=self.app_name) Tns.prepare_ios(app_name=self.app_name) plist = File.read( os.path.join(TnsPaths.get_platforms_ios_folder(self.app_name), self.app_name, self.app_name + '-Info.plist')) assert '<key>NSAllowsArbitraryLoads</key>' in plist, \ 'NSAppTransportSecurity from plugin is not found in final Info.plist' assert '<string>bar</string>' in plist, 'CFBundleURLTypes from plugin is not found in final Info.plist' @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'iOS tests can be executed only on macOS.') def test_401_plugin_add_invalid_plugin(self): Tns.platform_remove(app_name=self.app_name, platform=Platform.IOS) Tns.platform_remove(app_name=self.app_name, platform=Platform.ANDROID) result = Tns.plugin_add(plugin_name='wd', path=self.app_name, verify=False) assert 'wd is not a valid NativeScript plugin' in result.output assert 'Verify that the plugin package.json file ' + \ 'contains a nativescript key and try again' in result.output Tns.platform_add_android( self.app_name, framework_path=Settings.Android.FRAMEWORK_PATH) Tns.platform_add_ios(self.app_name, framework_path=Settings.IOS.FRAMEWORK_PATH) # Verify iOS only plugin result = Tns.plugin_add(plugin_name='[email protected]', path=self.app_name) assert 'tns-plugin is not supported for android' in result.output assert 'Successfully installed plugin tns-plugin' in result.output # Verify Android only plugin result = Tns.plugin_add(plugin_name='acra-telerik-analytics', path=self.app_name) assert 'acra-telerik-analytics is not supported for ios' in result.output assert 'Successfully installed plugin acra-telerik-analytics' in result.output Tns.build_ios(app_name=self.app_name, bundle=False) ios_path = os.path.join( TnsPaths.get_platforms_ios_folder(self.app_name)) assert not File.pattern_exists(ios_path, pattern='*.aar') assert not File.pattern_exists(ios_path, pattern='*acra*') Tns.build_android(app_name=self.app_name, bundle=False) android_path = os.path.join( TnsPaths.get_platforms_android_folder(self.app_name)) assert File.pattern_exists(android_path, pattern='*.aar') assert File.pattern_exists(android_path, pattern='*acra*')
class NGNewTests(TnsRunTest): app_name = Settings.AppName.DEFAULT app_path = TnsPaths.get_app_path(app_name=app_name) def setUp(self): TnsRunTest.setUp(self) NG.kill() Folder.clean(self.app_path) def tearDown(self): NG.kill() TnsRunTest.tearDown(self) def test_001_simple(self): NGNewTests.create_and_run(shared=False) NGNewTests.build_release() def test_010_shared(self): NGNewTests.create_and_run(shared=True) NG.serve(project=self.app_name) NG.kill() NGNewTests.build_release() NG.serve(project=self.app_name, prod=True) def test_100_shared_with_sample(self): NGNewTests.create_and_run(shared=True, sample=True) def test_200_simple_no_theme(self): NGNewTests.create_and_run(shared=False, theme=False) def test_201_shared_with_sass(self): NGNewTests.create_and_run(shared=False, style=StylingType.SCSS) def test_202_shared_with_custom_source_dir_and_prefix(self): NGNewTests.create_and_run(shared=True, prefix='myapp', source_dir='mysrc', style=StylingType.CSS) @unittest.skip( 'Ignore because of https://github.com/NativeScript/nativescript-schematics/issues/157' ) def test_300_help_ng_new(self): output = NG.exec_command( 'new --collection={0} --help'.format(NS_SCHEMATICS)).output assert '--sample' in output assert 'Specifies whether a sample master detail should be generated' in output assert '--shared' in output assert 'Specifies whether to generate a shared project or a {N} only' in output assert '--source-dir (-sd)' in output assert 'The path of the source directory' in output assert '--style' in output assert 'The file extension to be used for style files. Supported are css and scss' in output assert '--theme' in output assert 'Specifies whether the {N} theme for styling should be included' in output assert '--webpack' in output assert 'Specifies whether the new application has webpack set up' in output @staticmethod def create_and_run(shared=True, sample=False, theme=True, style=None, prefix=None, source_dir=None, webpack=True): # Get test data based on app type app_data = Apps.SCHEMATICS_NS if shared: if sample: app_data = Apps.SCHEMATICS_SHARED_SAMPLE else: app_data = Apps.SCHEMATICS_SHARED # Create app NGNewTests.create_app(app_data=app_data, shared=shared, sample=sample, theme=theme, style=style, prefix=prefix, source_dir=source_dir, webpack=webpack) # Update the app if Settings.ENV != EnvironmentType.LIVE: App.update(app_name=NGNewTests.app_name, modules=True, angular=True, typescript=True, web_pack=True) # Run the app NGNewTests.run_bundle(app_data=app_data, webpack=webpack, shared=shared, theme=theme, emu=NGNewTests.emu, sim=NGNewTests.sim) @staticmethod def create_app(app_data, shared, sample, theme, style, prefix, source_dir, webpack): # Create shared project with sample data result = NG.new(collection=NS_SCHEMATICS, project=NGNewTests.app_name, theme=theme, shared=shared, sample=sample, style=style, prefix=prefix, source_dir=source_dir, webpack=webpack) # Verify valid {N} app is created TnsAssert.created(app_name=NGNewTests.app_name, app_data=app_data, theme=theme, webpack=webpack) assert 'Directory is already under version control. Skipping initialization of git.' in result.output, \ 'Git init should be skipped because app is created already existing repo (the one with tests).' # Check sample if sample: # TODO: Implement it pass # Check theme if theme: assert App.is_dependency(app_name=NGNewTests.app_name, dependency='nativescript-theme-core') else: assert not App.is_dependency(app_name=NGNewTests.app_name, dependency='nativescript-theme-core') # Check styling if style is None or style is StylingType.CSS: assert 'app.css' in result.output else: assert 'app.android.scss' in result.output assert 'app.ios.scss' in result.output assert '_app-common.scss' in result.output assert '_app-variables.scss' in result.output # Check webpack if webpack: assert App.is_dev_dependency(app_name=NGNewTests.app_name, dependency='nativescript-dev-webpack') else: assert not App.is_dev_dependency( app_name=NGNewTests.app_name, dependency='nativescript-dev-webpack') # Check prefix if prefix is None: prefix = 'app' path = os.path.join(Settings.TEST_RUN_HOME, NGNewTests.app_name, 'angular.json') actual_prefix = JsonUtils.read( file_path=path)['projects'][NGNewTests.app_name]['prefix'] assert str(actual_prefix) == prefix, 'Prefix not set in angular.json' # Check source dir exists (applicable only for shared projects). if shared: if source_dir is None: source_dir = 'src' assert Folder.exists( os.path.join(Settings.TEST_RUN_HOME, NGNewTests.app_name, source_dir)) @staticmethod def run_bundle(app_data, webpack, shared, theme, emu, sim): # Run android (if webpack is available -> use --bundle) Tns.run(app_name=NGNewTests.app_name, platform=Platform.ANDROID, emulator=True, bundle=webpack) for text in app_data.texts: emu.wait_for_text(text=text, timeout=300) # Check if theme is really applied (only for non shared projects, shared is not good example to check) if not shared: blue_pixels = emu.get_pixels_by_color(color=Colors.LIGHT_BLUE) if theme: assert blue_pixels > 1000, 'Default {N} theme is NOT applied on Android.' else: assert blue_pixels == 0, 'Default {N} theme is applied, but it should not.' # Run ios (if webpack is available -> use --bundle) if Settings.HOST_OS is OSType.OSX: Tns.run(app_name=NGNewTests.app_name, platform=Platform.IOS, emulator=True, bundle=webpack) for text in app_data.texts: sim.wait_for_text(text=text, timeout=300) # Check if theme is really applied (only for non shared projects, shared is not good example to check) if not shared: blue_pixels = emu.get_pixels_by_color( color=Colors.LIGHT_BLUE) if theme: assert blue_pixels > 1000, 'Default {N} theme is NOT applied on iOS.' else: assert blue_pixels == 0, 'Default {N} theme is applied, but it should not.' @staticmethod def build_release(): Tns.build(app_name=NGNewTests.app_name, platform=Platform.ANDROID, release=True, bundle=True, aot=True, uglify=True, snapshot=True) if Settings.HOST_OS is OSType.OSX: Tns.build(app_name=NGNewTests.app_name, platform=Platform.IOS, release=True, for_device=True, bundle=True, aot=True, uglify=True)
class NGGenE2ETestsNS(TnsRunTest): app_name = Settings.AppName.DEFAULT app_path = TnsPaths.get_app_path(app_name=app_name) @classmethod def setUpClass(cls): TnsRunTest.setUpClass() NG.kill() def setUp(self): TnsRunTest.setUp(self) NG.kill() def tearDown(self): NG.kill() TnsRunTest.tearDown(self) def test_100_ns_generate_during_run_android(self): NGGenE2ETestsNS.workflow(app_name=self.app_name, device=self.emu, platform=Platform.ANDROID, shared=False) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'Skip iOS tests on non macOS machines.') def test_100_ns_generate_during_run_ios(self): NGGenE2ETestsNS.workflow(app_name=self.app_name, device=self.sim, platform=Platform.IOS, shared=False) def test_200_shared_generate_during_run_android(self): NGGenE2ETestsNS.workflow(app_name=self.app_name, device=self.emu, platform=Platform.ANDROID, shared=True) @unittest.skipIf(Settings.HOST_OS != OSType.OSX, 'Skip iOS tests on non macOS machines.') def test_200_shared_generate_during_run_ios(self): NGGenE2ETestsNS.workflow(app_name=self.app_name, device=self.sim, platform=Platform.IOS, shared=True) @staticmethod def workflow(app_name, device, platform, shared): # Create an app app_path = TnsPaths.get_app_path(app_name=app_name) Folder.clean(app_path) NG.new(collection=NS_SCHEMATICS, project=app_name, shared=shared) TnsAssert.created(app_name=app_name, app_data=None) # Run app initially text = 'TAP' if shared: text = 'Welcome to' result = Tns.run(app_name=app_name, platform=platform, emulator=True, hmr=True) strings = TnsLogs.run_messages(app_name=app_name, platform=platform, hmr=True, app_type=AppType.NG) TnsLogs.wait_for_log(log_file=result.log_file, string_list=strings, timeout=300) device.wait_for_text(text=text) # Generate module and component NG.exec_command(command='g m module-test', cwd=app_path) sleep(3) NG.exec_command(command='g c module-test/component-test', cwd=app_path) sleep(3) # Update app.modules.ts app_module_name = 'app.module.ts' app_module_path = os.path.join(app_path, 'app', app_module_name) old_string = "import { HomeComponent } from './home/home.component';" new_string = "import { ComponentTestComponent } from './module-test/component-test/component-test.component';" if shared: app_module_name = 'app.module.tns.ts' app_module_path = os.path.join(app_path, 'src', 'app', app_module_name) old_string = "import { HomeComponent } from '@src/app/home/home.component';" new_string = \ "import { ComponentTestComponent } from '@src/app/module-test/component-test/component-test.component';" File.replace(path=app_module_path, old_string=old_string, new_string=new_string) File.replace(path=app_module_path, old_string='HomeComponent,', new_string='ComponentTestComponent,') sleep(3) # Update app-routing.module.ts app_routing_module_name = 'app-routing.module.ts' app_routing_module_path = os.path.join(app_path, 'app', app_routing_module_name) old_string = "import { HomeComponent } from './home/home.component';" new_string = "import { ComponentTestComponent } from './module-test/component-test/component-test.component';" if shared: app_routing_module_name = 'app.routes.ts' app_routing_module_path = os.path.join(app_path, 'src', 'app', app_routing_module_name) old_string = "import { HomeComponent } from '@src/app/home/home.component';" new_string = \ "import { ComponentTestComponent } from '@src/app/module-test/component-test/component-test.component';" File.replace(path=app_routing_module_path, old_string=old_string, new_string=new_string) File.replace(path=app_routing_module_path, old_string='HomeComponent', new_string='ComponentTestComponent') sleep(3) # Verify app is updated logs = [ app_module_name, app_routing_module_name, 'Successfully synced application' ] TnsLogs.wait_for_log(log_file=result.log_file, string_list=logs, timeout=120) device.wait_for_text(text='component-test works!')
def tearDownClass(cls): TnsTest.tearDownClass() Docker.stop() Folder.clean(TnsPaths.get_app_path(app_name=cls.app_temp_path)) Folder.clean(TnsPaths.get_app_path(cls.app_name_with_space))
def create(app_name=Settings.AppName.DEFAULT, template=None, path=None, app_id=None, force=False, default=False, update=True, force_clean=True, log_trace=False, verify=True, app_data=None): """ Create {N} application. :param app_name: Application name (TestApp by default). :param template: Template string (it can be everything that can be npm installed - npm package, git url ...) :param path: Path where app to be created (Passes `--path <value>` to tns command. None by default). :param app_id: Application identifier. :param force: If true passes '--force' to tns command. :param default: If true passes '--default' to tns command. :param update: If True update the app (modules and plugins). :param force_clean: If True clean app folder before creating a project. :param log_trace: If True runs tns command with '--log trace'. :param verify: If True assert app is created properly. :param app_data: AppInfo object with expected data (used to verify app is created properly). """ # Cleanup app folder if force_clean: Folder.clean(TnsPaths.get_app_path(app_name=app_name)) # Create app normalized_app_name = app_name if ' ' in app_name: normalized_app_name = '"' + app_name + '"' command = 'create ' + normalized_app_name if template is not None: command = command + ' --template ' + template if path is not None: command = command + ' --path ' + path if app_id is not None: # noinspection SpellCheckingInspection command = command + ' --appid ' + app_id if force: command += ' --force' if default: command += ' --default' result = Tns.exec_command(command, log_trace=log_trace) # Update the app (if specified) if update: App.update(app_name=app_name) # Let TestContext know app is created TestContext.TEST_APP_NAME = app_name # Verify app is created properly if verify is not False: # Usually we do not pass path on tns create, which actually equals to cwd. # In such cases pass correct path to TnsAssert.created() if path is None: path = Settings.TEST_RUN_HOME TnsAssert.created(app_name=app_name, output=result.output, app_data=app_data, path=path) return result