├── .gitignore ├── README.md ├── XtcGuide ├── Droid │ ├── Assets │ │ └── AboutAssets.txt │ ├── MainActivity.cs │ ├── Properties │ │ ├── AndroidManifest.xml │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── AboutResources.txt │ │ ├── Resource.designer.cs │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ ├── drawable-xhdpi │ │ │ └── icon.png │ │ ├── drawable-xxhdpi │ │ │ └── icon.png │ │ ├── drawable │ │ │ └── icon.png │ │ ├── layout │ │ │ ├── Tabbar.axml │ │ │ └── Toolbar.axml │ │ └── values │ │ │ └── styles.xml │ ├── XtcGuide.Droid.csproj │ └── packages.config ├── UITests │ ├── AppInitializer.cs │ ├── Tests.cs │ ├── XtcGuide.UITests.csproj │ └── packages.config ├── XtcGuide.sln ├── XtcGuide │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── XtcGuide.cs │ ├── XtcGuide.csproj │ └── packages.config └── iOS │ ├── AppDelegate.cs │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Entitlements.plist │ ├── Info.plist │ ├── LaunchScreen.storyboard │ ├── Main.cs │ ├── Resources │ └── icon.png │ ├── XtcGuide.iOS.csproj │ └── packages.config └── images ├── ActivityIndicator.png ├── BoxView.png ├── Button.png ├── DatePicker.png ├── Editor.png ├── Entry.png ├── Image.png ├── Label.png ├── ListView.png ├── OpenGL.png ├── ProgressBar.png ├── SearchBar.png ├── Stepper.png ├── Switch.png ├── TableViewNewest.png ├── TimePicker.png └── WebView.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/xamarinstudio,visualstudio 3 | 4 | ### XamarinStudio ### 5 | bin/ 6 | obj/ 7 | *.userprefs 8 | 9 | 10 | ### VisualStudio ### 11 | ## Ignore Visual Studio temporary files, build results, and 12 | ## files generated by popular Visual Studio add-ons. 13 | ## 14 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 15 | 16 | # User-specific files 17 | *.suo 18 | *.user 19 | *.userosscache 20 | *.sln.docstates 21 | *.vcxproj.filters 22 | 23 | # User-specific files (MonoDevelop/Xamarin Studio) 24 | 25 | # Build results 26 | [Dd]ebug/ 27 | [Dd]ebugPublic/ 28 | [Rr]elease/ 29 | [Rr]eleases/ 30 | x64/ 31 | x86/ 32 | bld/ 33 | [Bb]in/ 34 | [Oo]bj/ 35 | [Ll]og/ 36 | 37 | # Visual Studio 2015 cache/options directory 38 | .vs/ 39 | # Uncomment if you have tasks that create the project's static files in wwwroot 40 | #wwwroot/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUNIT 47 | *.VisualState.xml 48 | TestResult.xml 49 | 50 | # Build Results of an ATL Project 51 | [Dd]ebugPS/ 52 | [Rr]eleasePS/ 53 | dlldata.c 54 | 55 | # .NET Core 56 | project.lock.json 57 | project.fragment.lock.json 58 | artifacts/ 59 | **/Properties/launchSettings.json 60 | 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.pch 68 | *.pdb 69 | *.pgc 70 | *.pgd 71 | *.rsp 72 | *.sbr 73 | *.tlb 74 | *.tli 75 | *.tlh 76 | *.tmp 77 | *.tmp_proj 78 | *.log 79 | *.vspscc 80 | *.vssscc 81 | .builds 82 | *.pidb 83 | *.svclog 84 | *.scc 85 | 86 | # Chutzpah Test files 87 | _Chutzpah* 88 | 89 | # Visual C++ cache files 90 | ipch/ 91 | *.aps 92 | *.ncb 93 | *.opendb 94 | *.opensdf 95 | *.sdf 96 | *.cachefile 97 | *.VC.db 98 | *.VC.VC.opendb 99 | 100 | # Visual Studio profiler 101 | *.psess 102 | *.vsp 103 | *.vspx 104 | *.sap 105 | 106 | # TFS 2012 Local Workspace 107 | $tf/ 108 | 109 | # Guidance Automation Toolkit 110 | *.gpState 111 | 112 | # ReSharper is a .NET coding add-in 113 | _ReSharper*/ 114 | *.[Rr]e[Ss]harper 115 | *.DotSettings.user 116 | 117 | # JustCode is a .NET coding add-in 118 | .JustCode 119 | 120 | # TeamCity is a build add-in 121 | _TeamCity* 122 | 123 | # DotCover is a Code Coverage Tool 124 | *.dotCover 125 | 126 | # Visual Studio code coverage results 127 | *.coverage 128 | *.coveragexml 129 | 130 | # NCrunch 131 | _NCrunch_* 132 | .*crunch*.local.xml 133 | nCrunchTemp_* 134 | 135 | # MightyMoose 136 | *.mm.* 137 | AutoTest.Net/ 138 | 139 | # Web workbench (sass) 140 | .sass-cache/ 141 | 142 | # Installshield output folder 143 | [Ee]xpress/ 144 | 145 | # DocProject is a documentation generator add-in 146 | DocProject/buildhelp/ 147 | DocProject/Help/*.HxT 148 | DocProject/Help/*.HxC 149 | DocProject/Help/*.hhc 150 | DocProject/Help/*.hhk 151 | DocProject/Help/*.hhp 152 | DocProject/Help/Html2 153 | DocProject/Help/html 154 | 155 | # Click-Once directory 156 | publish/ 157 | 158 | # Publish Web Output 159 | *.[Pp]ublish.xml 160 | *.azurePubxml 161 | # TODO: Comment the next line if you want to checkin your web deploy settings 162 | # but database connection strings (with potential passwords) will be unencrypted 163 | *.pubxml 164 | *.publishproj 165 | 166 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 167 | # checkin your Azure Web App publish settings, but sensitive information contained 168 | # in these scripts will be unencrypted 169 | PublishScripts/ 170 | 171 | # NuGet Packages 172 | *.nupkg 173 | # The packages folder can be ignored because of Package Restore 174 | **/packages/* 175 | # except build/, which is used as an MSBuild target. 176 | !**/packages/build/ 177 | # Uncomment if necessary however generally it will be regenerated when needed 178 | #!**/packages/repositories.config 179 | # NuGet v3's project.json files produces more ignoreable files 180 | *.nuget.props 181 | *.nuget.targets 182 | 183 | # Microsoft Azure Build Output 184 | csx/ 185 | *.build.csdef 186 | 187 | # Microsoft Azure Emulator 188 | ecf/ 189 | rcf/ 190 | 191 | # Windows Store app package directories and files 192 | AppPackages/ 193 | BundleArtifacts/ 194 | Package.StoreAssociation.xml 195 | _pkginfo.txt 196 | 197 | # Visual Studio cache files 198 | # files ending in .cache can be ignored 199 | *.[Cc]ache 200 | # but keep track of directories ending in .cache 201 | !*.[Cc]ache/ 202 | 203 | # Others 204 | ClientBin/ 205 | ~$* 206 | *~ 207 | *.dbmdl 208 | *.dbproj.schemaview 209 | *.jfm 210 | *.pfx 211 | *.publishsettings 212 | node_modules/ 213 | orleans.codegen.cs 214 | 215 | # Since there are multiple workflows, uncomment next line to ignore bower_components 216 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 217 | #bower_components/ 218 | 219 | # RIA/Silverlight projects 220 | Generated_Code/ 221 | 222 | # Backup & report files from converting an old project file 223 | # to a newer Visual Studio version. Backup files are not needed, 224 | # because we have git ;-) 225 | _UpgradeReport_Files/ 226 | Backup*/ 227 | UpgradeLog*.XML 228 | UpgradeLog*.htm 229 | 230 | # SQL Server files 231 | *.mdf 232 | *.ldf 233 | 234 | # Business Intelligence projects 235 | *.rdl.data 236 | *.bim.layout 237 | *.bim_*.settings 238 | 239 | # Microsoft Fakes 240 | FakesAssemblies/ 241 | 242 | # GhostDoc plugin setting file 243 | *.GhostDoc.xml 244 | 245 | # Node.js Tools for Visual Studio 246 | .ntvs_analysis.dat 247 | 248 | # Visual Studio 6 build log 249 | *.plg 250 | 251 | # Visual Studio 6 workspace options file 252 | *.opt 253 | 254 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 255 | *.vbw 256 | 257 | # Visual Studio LightSwitch build output 258 | **/*.HTMLClient/GeneratedArtifacts 259 | **/*.DesktopClient/GeneratedArtifacts 260 | **/*.DesktopClient/ModelManifest.xml 261 | **/*.Server/GeneratedArtifacts 262 | **/*.Server/ModelManifest.xml 263 | _Pvt_Extensions 264 | 265 | # Paket dependency manager 266 | .paket/paket.exe 267 | paket-files/ 268 | 269 | # FAKE - F# Make 270 | .fake/ 271 | 272 | # JetBrains Rider 273 | .idea/ 274 | *.sln.iml 275 | 276 | # CodeRush 277 | .cr/ 278 | 279 | # Python Tools for Visual Studio (PTVS) 280 | __pycache__/ 281 | *.pyc 282 | 283 | # Cake - Uncomment if you are using it 284 | # tools/ 285 | 286 | ### VisualStudio Patch ### 287 | build/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Xamarin Test Cloud Guide for Xamarin.Forms Applications 2 | When we begin writing C# UI test scripts for our Xamarin.Forms application, it is important that we know how to interact with each UI element on iOS and Android. This guide is meant to cover all control scenarios in Xamarin.Forms. 3 | 4 | ## Xamarin.Forms UI Controls 5 | We will begin with the [Views]() Xamarin has documented and explain the best way to interact with that control on iOS and Android in a C# UI test. 6 | 7 | ### `ActivityIndicator` 8 | ![ActivityIndicator](images/ActivityIndicator.png) 9 | 10 | ### Uniquely Identifying a `ActivityIndicator` on iOS 11 | Native Control: [`UIActivityIndicatorView`](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/ActivityIndicatorRenderer.cs) 12 | Setting the `AutomationId` property on the `ActivityIndicator` will translate to the `Id` property to identify in `Xamarin.UITest`. 13 | 14 | ### Uniquely Identifying a `ActivityIndicator` on Android 15 | Native Control: [Android.Widget.ProgressBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ActivityIndicatorRenderer.cs) 16 | Setting the `AutomationId` property on the `ActivityIndicator` will translate to the `Label` property to identify in `Xamarin.UITest`. 17 | 18 | Setting `AutomationId` in Xamarin.Forms Project: 19 | 20 | ```C# 21 | ActivityIndicator indicator = new ActivityIndicator { AutomationId = "LoadingIndicator"}; 22 | 23 | ``` 24 | 25 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `ActivityIndicator` on both iOS and Android. 26 | ```C# 27 | app.WaitForElement(x=>x.Marked("LoadingIndicator")); 28 | app.WaitForNoElement(x=>x.Marked("LoadingIndicator)) 29 | ``` 30 | The code above would be an example of waiting for the `ActivityIndicator` to appear on the screen or disappear from the screen. It is common to use the `ActivityIndicator` appearing to wait for information to begin loading on the screen and then the `ActivityIndicator` disappearrance to assume all of the data has been loaded on the screen. The code above would acheive this desired effect. 31 | 32 | ### `BoxView` 33 | ![BoxView](images/BoxView.png) 34 | ### Uniquely Identifying a `BoxView` on iOS 35 | Native Control: [BoxView](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/BoxRenderer.cs) 36 | Setting the `AutomationId` property on the `BoxView` will translate to the `Id` property to identify in `Xamarin.UITest`. 37 | 38 | ### Uniquely Identifying a `BoxView` on Android 39 | Native Control: [BoxView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/BoxRenderer.cs) 40 | Setting the `AutomationId` property on the `BoxView` will translate to the `Label` property to identify in `Xamarin.UITest`. 41 | 42 | Setting `AutomationId` in Xamarin.Forms Project: 43 | 44 | ```C# 45 | BoxView indicator = new BoxView { AutomationId = "MyBox"}; 46 | 47 | ``` 48 | 49 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `BoxView` on both iOS and Android. 50 | ```C# 51 | app.Tap(x=>x.Marked("MyBox")); 52 | ``` 53 | I'm not sure why you would need to interact with a `BoxView`, but there it is. 54 | 55 | ### `Button` 56 | ![Button](images/Button.png) 57 | ### Uniquely Identifying a `Button` on iOS 58 | Native Control: [UIButton](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/ButtonRenderer.cs) 59 | Setting the `AutomationId` property on the `Button` will translate to the `Id` property to identify in `Xamarin.UITest`. The `Label` property to identify in `Xamarin.UITest` will be whatever the `Button.Text` property is set to. 60 | 61 | ### Uniquely Identifying a `Button` on Android 62 | Native Control: [Android.Widget.Button](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ButtonRenderer.cs) 63 | Setting the `AutomationId` property on the `Button` will translate to the `Label` property to identify in `Xamarin.UITest`. The `Text` property to identify in `Xamarin.UITest` will be whatever the `Button.Text` property is set to. 64 | 65 | Setting `AutomationId` in Xamarin.Forms Project: 66 | 67 | ```C# 68 | Button loginButton = new Button { AutomationId = "LoginButton"}; 69 | 70 | ``` 71 | 72 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Button` on both iOS and Android. 73 | ```C# 74 | app.Tap(x=>x.Marked("LoginButton")); 75 | ``` 76 | 77 | ### `DatePicker` 78 | ![DatePicker](images/DatePicker.png) 79 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 80 | 81 | ### Uniquely Identifying a `DatePicker` on iOS 82 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs) with internal `UIDatePicker` 83 | Setting the `AutomationId` property on the `DatePicker` will translate to the `Id` property to identify in `Xamarin.UITest`. 84 | 85 | We will need to first tap on the `UITextField` to engage the `UIDatePicker`. From there we will need to invoke the native method `selectRow()` on the `UIDatePicker` and press the "ok" button. 86 | 87 | In Code: 88 | ```C# 89 | //Activate the DatePicker 90 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}")); 91 | 92 | //Wait for DatePicker animation to completed 93 | app.WaitForElement(x=>x.Class("UIPickerView")); 94 | 95 | //Invoke the native method selectRow() 96 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Month - 1 , "inComponent", 0, "animated", true)); 97 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Day - 1, "inComponent", 1, "animated", true)); 98 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", date.Year - 1, "inComponent", 2, "animated", true)); 99 | ``` 100 | 101 | The code above shows how we can invoke the `selectRow()` method on the DatePicker. The "Done" button will always have an `Class` property of "UIToolbarTextButton". 102 | 103 | ### Uniquely Identifying a `DatePicker` on Android 104 | Native Control: [Android.Widget.DatePicker](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/DatePickerRenderer.cs) with `Android.Widget.EditText` 105 | Setting the `AutomationId` property on the `DatePicker` will translate to the `Label` property to identify the `Android.Widget.EditText`. 106 | 107 | We will need to first tap on the `Android.Widget.EditText` to engage the `Android.Widget.DatePicker`. From there we will need to invoke the native method `updateDate()` on the `Android.Widget.DatePicker` and press the "ok" button. 108 | 109 | In code: 110 | ```C# 111 | //Activate the DatePicker 112 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}")); 113 | 114 | //Wait for DatePicker animation to completed 115 | app.WaitForElement(x=>x.Class("DatePicker")); 116 | 117 | //Invoke updateDate() method on displayed DatePicker 118 | app.Query(x=>x.Class("DatePicker").Invoke("updateDate",date.Year,date.Month,date.Day)); 119 | 120 | //Tap the ok button to close the DatePicker dialogue 121 | app.Tap(x=>x.Id("button1"));//Ok Button in DatePicker Dialogue 122 | ``` 123 | 124 | The code above shows how we can invoke the `updateDate()` method on the DatePicker. The "ok" button will always have an `Id` property of "button1". The "cancel" button will always have an `Id` property of "button2" 125 | 126 | ### `Editor` 127 | ![Editor](images/Editor.png) 128 | 129 | ### Uniquely Identifying a `Editor` on iOS 130 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/EditorRenderer.cs) 131 | Setting the `AutomationId` property on the `Editor` will translate to the `Id` property to identify in `Xamarin.UITest`. 132 | 133 | ### Uniquely Identifying a `Editor` on Android 134 | Native Control: [Android.Widget.EditText](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs) 135 | Setting the `AutomationId` property on the `EditText` will translate to the `Label` property to identify the `Android.Widget.EditText`. 136 | 137 | Setting `AutomationId` in Xamarin.Forms Project: 138 | 139 | ```C# 140 | Editor editor = new Editor { AutomationId = "NewsEditor"}; 141 | ``` 142 | 143 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Editor` on both iOS and Android. 144 | ```C# 145 | //EnterText into Editor 146 | app.EnterText(x=>x.Marked("NewsEditor"), "This is some text"); 147 | app.DismissKeyboard(); 148 | 149 | //ClearText from Editor 150 | app.ClearText(x=>x.Marked("NewsEditor")); 151 | app.DismissKeyboard(); 152 | ``` 153 | The code above is an example of entering text into the Editor and clearing text from the Editor. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements. 154 | 155 | ### `Entry` 156 | ![Entry](images/Entry.png) 157 | 158 | ### Uniquely Identifying a `Entry` on iOS 159 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs) 160 | Setting the `AutomationId` property on the `Entry` will translate to the `Id` property to identify in `Xamarin.UITest`. 161 | 162 | ### Uniquely Identifying a `Entry` on Android 163 | Native Control: [Android.Widget.EditText](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/EntryEditText.cs) 164 | Setting the `AutomationId` property on the `EditText` will translate to the `Label` property to identify the `Android.Widget.EditText`. 165 | 166 | Setting `AutomationId` in Xamarin.Forms Project: 167 | 168 | ```C# 169 | Entry usernameEntry = new Entry { AutomationId = "UsernameEntry"}; 170 | ``` 171 | 172 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Entry` on both iOS and Android. 173 | ```C# 174 | //EnterText into Entry 175 | app.EnterText(x=>x.Marked("UsernameEntry"), "This is some text"); 176 | app.DismissKeyboard(); 177 | 178 | //ClearText from Entry 179 | app.ClearText(x=>x.Marked("UsernameEntry")); 180 | app.DismissKeyboard(); 181 | ``` 182 | The code above is an example of entering text into the Entry and clearing text from the Entry. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements. 183 | 184 | ### `Image` 185 | ![Image](images/Image.png) 186 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 187 | 188 | ### Uniquely Identifying a `Image` on iOS 189 | Native Control: [UIImage](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ImageRenderer.cs) 190 | Setting the `AutomationId` property on the `Entry` will translate to the `Id` property to identify in `Xamarin.UITest`. 191 | 192 | ### Uniquely Identifying a `Image` on Android 193 | Native Control: [Android.Widget.ImageView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ImageRenderer.cs) 194 | Setting the `AutomationId` property on the `Image` will translate to the `Label` property to identify the `Android.Widget.ImageView`. 195 | 196 | ```C# 197 | Image profilePic = new Image { AutomationId = "ProfilePicture"}; 198 | ``` 199 | 200 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Image` on both iOS and Android. 201 | ```C# 202 | app.Query((x=>x.Marked("ProfilePicture")); 203 | ``` 204 | 205 | ### `Label` 206 | ![Label](images/Label.png) 207 | 208 | ### Uniquely Identifying a `Label` on iOS 209 | Native Control: [UILabel](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/LabelRenderer.cs) 210 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Id` property to identify in `Xamarin.UITest`. 211 | 212 | ### Uniquely Identifying a `Label` on Android 213 | Native Control: [Android.Widget.TextView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/LabelRenderer.cs) 214 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Label` property to identify the `Android.Widget.TextView`. 215 | 216 | ```C# 217 | Label usernameLabel = new Label { AutomationId = "ProfilePicture"}; 218 | ``` 219 | 220 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.Label` on both iOS and Android. 221 | ```C# 222 | app.Query((x=>x.Marked("ProfilePicture")); 223 | ``` 224 | 225 | ### `ListView` 226 | ![ListView](images/ListView.png) 227 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 228 | 229 | ### Uniquely Identifying a `ListView` on iOS 230 | Native Control: [UITableView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ListViewRenderer.cs) 231 | Setting the `AutomationId` property on the `Xamarin.Forms.Label` will translate to the `Id` property to identify in `Xamarin.UITest`. 232 | 233 | ### Uniquely Identifying a `ListView` on Android 234 | Native Control: [Android.Widget.ListView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ListViewRenderer.cs) 235 | Setting the `AutomationId` property on the `Xamarin.Forms.ListView` will translate to the `Label` property to identify the `Android.Widget.ListView`. 236 | 237 | ```C# 238 | ListView myList = new ListView { AutomationId = "MyListView"}; 239 | ``` 240 | 241 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.ListView` on both iOS and Android. 242 | ```C# 243 | app.Query((x=>x.Marked("MyListView")); 244 | ``` 245 | 246 | ### Interacting with Pull-to-refresh on Xamarin.Forms.ListView 247 | We must handle the Pull-to-refresh differently between iOS and Android. This is because the refreshing indicator is handled differently on each platform. On iOS, there is a `UIRefreshControl` that is displayed when the pull-to-refresh command is executing. On Android, we have to invoke the native `android.support.v4.widget.SwipeRefreshLayout.isRefreshing()` method. This will tell us if the refresh loading indicator is displayed or not. 248 | 249 | ```C# 250 | public bool RefreshIndicatorIsDisplayed 251 | { 252 | get 253 | { 254 | if (OnAndroid) 255 | return (bool)app.Query(x => x.Class("SwipeRefreshLayout").Invoke("isRefreshing")).First(); 256 | 257 | if (OniOS) 258 | return (bool)app.Query(x => x.Class("UIRefreshControl")).Any(); 259 | 260 | throw new Exception("Platform Not Recognized"); 261 | } 262 | } 263 | ``` 264 | The above code example returns a boolean whether the `Xamarin.Forms.ListView` refresh indicator is displayed or not. We may want to wait for the refresh indicator to appear or disappear, so we will need to create a method to handle this for us. 265 | 266 | ```C# 267 | public void WaitForIndicatorToDisappear(int timeoutInSeconds = 10) 268 | { 269 | int counter = 0; 270 | while (RefreshIndicatorIsDisplayed) 271 | { 272 | Thread.Sleep(200);//Value determined by user 273 | counter++; 274 | 275 | if (counter >= timeoutInSeconds) 276 | throw new Exception($"Loading the list took longer than {timeoutInSeconds}"); 277 | } 278 | } 279 | ``` 280 | 281 | In this example we are periodically checking to see if the refresh indicator is displayed and performing this in a loop. If we exceed the timeout given, we throw an exception with an error message that is specific to our application. 282 | 283 | ### Interacting with Cells in the ListView 284 | I get questions about this a lot and we are going to discuss a little theory here. This guide is meant to explain how to test your application, not how to test the native operating system. For example, if your application has a list of cells that are all the same type (DataTemplate is the same for each cell), we should only test interacting with the first cell in the list. This is because every cell in the list should be handled the exact same way. If we test tapping every single cell, we are really testing that the native operating system acts as we expect. In my opinion, this is a waste of time because you have no control over bugs introduced by Apple or Android. We should expect the native SDKs to work as expected and we can consider this an assumption of our tests. 285 | 286 | To interact with the first cell in the ListView, we would do something like the following: 287 | 288 | ```C# 289 | public void SelectFirstCellInList(int timeoutInSeconds = 20) 290 | { 291 | Func firstCellInList; 292 | 293 | if (OnAndroid) 294 | firstCellInList = x => x.Class("ViewCellRenderer_ViewCellContainer").Index(0); 295 | else if (OniOS) 296 | firstCellInList = x => x.Marked("{AutomationId of ViewCell}").Index(0); 297 | 298 | app.WaitForElement(firstCellInList, "Timed our waiting for the first user to appear", TimeSpan.FromSeconds(timeoutInSeconds)); 299 | app.Tap(firstCellInList); 300 | } 301 | ``` 302 | 303 | In the code above, we have to identify our cells differently. On Android, we can simply use the `ViewCellRenderer_ViewCellContainer` class to identify the cells. On iOS, we can set the `AutomationId` property of the `Xamarin.Forms.ViewCell`. 304 | 305 | ### `OpenGL` 306 | ![OpenGL](images/OpenGL.png) 307 | TBD 308 | 309 | ### `ProgressBar` 310 | ![ProgressBar](images/ProgressBar.png) 311 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 312 | 313 | ### Uniquely Identifying a `ProgressBar` on iOS 314 | Native Control: [UIProgressView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/ProgressBarRenderer.cs) 315 | Setting the `AutomationId` property on the `ProgressBar` will translate to the `Id` property to identify in `Xamarin.UITest`. 316 | 317 | ### Uniquely Identifying a `ProgressBar` on Android 318 | Native Control: [Android.Widget.ProgressBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ProgressBarRenderer.cs) 319 | Setting the `AutomationId` property on the `ProgressBar` will translate to the `Label` property to identify the `Android.Widget.ProgressBar`. 320 | 321 | Setting `AutomationId` in Xamarin.Forms Project: 322 | 323 | ```C# 324 | ProgressBar progressBar = new ProgressBar { AutomationId = "LoadingProgress"}; 325 | ``` 326 | 327 | ### Getting ProgressBar current level 328 | ```C# 329 | if(OnAndroid) 330 | app.Query(x => x.Class("ProgressBar").Invoke("getProgress")) 331 | else if(OniOS) 332 | app.Query(x => x.Class("UIProgressView").Invoke("progress")) 333 | ``` 334 | 335 | In the code above, we have to invoke native methods to check the progress level. On Android, we invoke the `Android.Widget.ProgressBar.getProgress()` method that returns a value between 0 and 10,000 (0 is 0% and 10,000 is 100%). On iOS, we invoke the `progress` property on the `UIProgressView` to return a value between 0 and 1. 336 | 337 | ### Setting ProgressBar current level 338 | ```C# 339 | if(OnAndroid) 340 | app.Query(x => x.Class("ProgressBar").Invoke("setProgress",5000)) //Sets ProgressBar to 50%, 100% = 10,000 341 | else if(OniOS) 342 | app.Query(x => x.Class("UIProgressView").Invoke("setProgress:animated",0.5f)) //Sets ProgressBar to 50%, 100% = 1.0f 343 | ``` 344 | 345 | In the code above, we have to invoke native methods to set the progress level. On Android, we invoke the `Android.Widget.ProgressBar.setProgress()` method with value between 0 and 10,000 (0 is 0% and 10,000 is 100%). On iOS, we invoke the `setProgress(Float,animated: Bool)` method on the `UIProgressView` to return a value between 0 and 1. 346 | 347 | ### `SearchBar` 348 | ![SearchBar](images/SearchBar.png) 349 | 350 | ### Uniquely Identifying a `SearchBar` on iOS 351 | Native Control: [UISearchBar](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/SearchBarRenderer.cs) 352 | Setting the `AutomationId` property on the `SearchBar` will translate to the `Id` property to identify the `UISearchBar` in `Xamarin.UITest`. The "Cancel" button will have a `Label` property of "Cancel". 353 | 354 | ### Uniquely Identifying a `SearchBar` on Android 355 | Native Control: [Android.Widget.SearchView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/SearchBarRenderer.cs) 356 | Setting the `AutomationId` property on the `SearchBar` will translate to the `Label` property to identify the `Android.Widget.SearchView`. 357 | 358 | Setting `AutomationId` in Xamarin.Forms Project: 359 | 360 | ```C# 361 | SearchBar searchBar = new SearchBar { AutomationId = "UserSearchBar"}; 362 | ``` 363 | 364 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `SearchBar` on both iOS and Android. 365 | ```C# 366 | //EnterText into SearchBar 367 | app.EnterText(x=>x.Marked("UserSearchBar"), "This is some text"); 368 | app.DismissKeyboard(); 369 | 370 | //ClearText from SearchBar 371 | app.ClearText(x=>x.Marked("UserSearchBar")); 372 | app.DismissKeyboard(); 373 | ``` 374 | The code above is an example of entering text into the Editor and clearing text from the Editor. Make sure you don't forget to dismiss the keyboard afterwards to ensure the keyboard isn't covering up any UI elements. 375 | 376 | ### Cancelling the SearchBar search 377 | 378 | ```C# 379 | if(OnAndroid) 380 | app.Tap(x=>x.Marked("Cancel")); 381 | else if(OniOS) 382 | app.Tap(x => x.Id("search_close_btn")); 383 | ``` 384 | 385 | In the code above, we can interact with the "Cancel" button found on the search controls. It is important to note that on Android, you might need to call `DismissKeyboard()` depending on how you are using the search and what version of Android you are on. 386 | 387 | ### `Stepper` 388 | ![Stepper](images/Stepper.png) 389 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 390 | 391 | ### Uniquely Identifying a `Stepper` on iOS 392 | Native Control: [UIStepper](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/StepperRenderer.cs) 393 | Setting the `AutomationId` property on the `Stepper` will translate to the `Id` property to identify the `UIStepper` in `Xamarin.UITest`. The '+' and '-' buttons of the UIStepper will have `Label` properties of "Increment" and "Decrement". 394 | 395 | ### Uniquely Identifying a `Stepper` on Android 396 | Native Control: [Android.Widget.LinearLayout](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/StepperRenderer.cs) with two internal `Android.Widget.Button` 397 | Setting the `AutomationId` property on the `Stepper` will translate to the `Label` property to identify the `Android.Widget.SearchView`. 398 | 399 | Setting `AutomationId` in Xamarin.Forms Project: 400 | 401 | ```C# 402 | Stepper stepper = new Stepper { AutomationId = "MyStepper"}; 403 | ``` 404 | 405 | ### Increasing the value of `Stepper` 406 | 407 | ```C# 408 | if(OnAndroid) 409 | app.Tap(x => x.Class("android.widget.Button").Text("+")) 410 | else if(OniOS) 411 | app.Tap(x=>x.Marked("Increment")); 412 | ``` 413 | 414 | ### Decreasing the value of `Stepper` 415 | 416 | ```C# 417 | if(OnAndroid) 418 | app.Tap(x => x.Class("android.widget.Button").Text("-")) 419 | else if(OniOS) 420 | app.Tap(x=>x.Marked("Decrement")); 421 | ``` 422 | 423 | ### Getting value of `Stepper` 424 | 425 | ```C# 426 | if(OnAndroid) 427 | //Would need to expose through Backdoor 428 | // TODO 429 | else if(OniOS) 430 | app.Query(x => x.Id("MyStepper").Invoke("value")); 431 | ``` 432 | 433 | ### `Switch` 434 | ![Switch](images/Switch.png) 435 | 436 | ### Uniquely Identifying a `Switch` on iOS 437 | Native Control: [UISwitch](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/SwitchRenderer.cs) 438 | Setting the `AutomationId` property on the `Switch` will translate to the `Id` property to identify the `UISwitch` in `Xamarin.UITest`. The '+' and '-' buttons of the UIStepper will have `Label` properties of "Increment" and "Decrement". 439 | 440 | ### Uniquely Identifying a `Switch` on Android 441 | Native Control: [Android.Widget.Switch](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/SwitchRenderer.cs) with two internal `Android.Widget.Button` 442 | Setting the `AutomationId` property on the `Switch` will translate to the `Label` property to identify the `Android.Widget.Switch`. 443 | 444 | Setting `AutomationId` in Xamarin.Forms Project: 445 | 446 | ```C# 447 | Switch stepper = new Switch { AutomationId = "MySwitch"}; 448 | ``` 449 | 450 | ### `TableView` 451 | ![TableView](images/TableViewNewest.png) 452 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the date. 453 | 454 | ### Uniquely Identifying a `TableView` on iOS 455 | Native Control: [UITableView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/TableViewRenderer.cs) 456 | Setting the `AutomationId` property on the `TableView` will translate to the `Id` property to identify the `UITableView` in `Xamarin.UITest`. 457 | 458 | ### Uniquely Identifying a `TableView` on Android 459 | Native Control: [Android.Widget.LinearLayout](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/TableViewRenderer.cs) with two internal `Android.Widget.Button` 460 | Setting the `AutomationId` property on the `TableView` will translate to the `Label` property to identify the `Android.Widget.SearchView`. 461 | 462 | ```C# 463 | TableView tableView = new TableView { AutomationId = "MyTableView"}; 464 | ``` 465 | 466 | Since `Marked` looks at both the `Id` and `Label` properties, we can use `Marked` to uniquely identify the `Xamarin.Forms.ListView` on both iOS and Android. 467 | ```C# 468 | app.Query((x=>x.Marked("MyTableView")); 469 | ``` 470 | 471 | ### Built in Xamarin.Forms.Cells 472 | These cells are typically constructed together with a combination of other elements. Due to this, we typically have to identify the cell in some way and access the objects through the `Child()` method in `Xamarin.UITest`. 473 | 474 | ### Interacting with an `TextCell` 475 | 476 | ```C# 477 | app.Query(x=>x.Marked("TextCell Text")); 478 | ``` 479 | 480 | ### Interacting with an `EntryCell` 481 | 482 | ```C# 483 | //Enter some text 484 | if(OniOS) 485 | { 486 | app.EnterText(x => x.Class("Xamarin_Forms_Platform_iOS_EntryCellRenderer_EntryCellTableViewCell").Child(0).Child(0), "Text to enter"); 487 | app.DismissKeyboard(); 488 | } else if (OnAndroid) 489 | { 490 | app.EnterText(x => x.Class("EntryCellView").Child(1), "Text to enter"); 491 | app.DismissKeyboard(); 492 | } 493 | 494 | //Clear text 495 | if(OniOS) 496 | app.ClearText(x => x.Class("Xamarin_Forms_Platform_iOS_EntryCellRenderer_EntryCellTableViewCell").Child(0).Child(0)); 497 | else if (OnAndroid) 498 | app.ClearText(x => x.Class("EntryCellView").Child(1)); 499 | ``` 500 | 501 | In the code above on iOS, we have to interact with the cell children to enter text or clear text. Each `EntryCell` will have three children on iOS, the first index (0) is the physical view of the cell while the next two indexes (1 and 2) are the `UITableViewCellSeparatorView`. After we access the Cell view, there are two more children of this view: the `UILabel` and `UITextField` of the `EntryCell`. We will want to access the first child which is the `UITextField`. 502 | 503 | In the code above on Android, we have to interact with the cell children to enter text or clear text. Each `EntryCell` will have two children on Android, the first index (0) is the `TextView` containing the text displayed in the cell. The second index (1) is the physical `Entry` for the user to input. 504 | 505 | ### Interacting with an `SwitchCell` 506 | 507 | ```C# 508 | if(OnAndroid) 509 | app.Query(x => x.Class("SwitchCellView").Class("Switch").Invoke("setChecked", {true or false}); 510 | else if(OniOS) 511 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_CellTableViewCell").Class("UISwitch").Invoke("setOn:animated", {true or false})); 512 | ``` 513 | In the code above, we have to interact with the cell children to toggle the `Switch`. We can directly invoke the native class of the `Switch` element to toggle it. 514 | 515 | ### `TimePicker` 516 | ![TimePicker](images/TimePicker.png) 517 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the time. 518 | 519 | ### Uniquely Identifying a `TimePicker` on iOS 520 | Native Control: [UITextField](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs) with internal `UIDatePicker` 521 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Id` property to identify in `Xamarin.UITest`. 522 | 523 | We will need to first tap on the `UITextField` to engage the `UIDatePicker`. From there we will need to invoke the native method `selectRow()` on the `UIDatePicker` and press the "ok" button. 524 | 525 | In Code: 526 | ```C# 527 | //Activate the DatePicker 528 | app.Tap(x=>x.Id("{AutomationId of Xamarin.Forms.DatePicker}")); 529 | 530 | //Wait for DatePicker animation to completed 531 | app.WaitForElement(x=>x.Class("UIPickerView")); 532 | 533 | //Invoke the native method selectRow() 534 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", time.Hour , "inComponent", 0, "animated", true)); //if time.Hour == 0, than hour is '1'. if time.Hour == 11, than hour is '12' 535 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", time.Minutes, "inComponent", 1, "animated", true)); //if time.Minute == 0, than minutes is '1'. if time.Minute == 59, than minutes is '59' 536 | app.Query (x => x.Class ("UIPickerView").Invoke ("selectRow", 0, "inComponent", 2, "animated", true)); //0 == AM and 1 == PM 537 | ``` 538 | 539 | The code above shows how we can invoke the `selectRow()` method on the DatePicker. The "Done" button will always have an `Class` property of "UIToolbarTextButton". 540 | 541 | ### Uniquely Identifying a `TimePicker` on Android 542 | Native Control: [Android.Widget.TimePicker](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/TimePickerRenderer.cs) with `Android.Widget.EditText` 543 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Label` property to identify the `Android.Widget.EditText`. 544 | 545 | We will need to first tap on the `Android.Widget.EditText` to engage the `Android.Widget.TimePicker`. From there we will need to invoke the native method `updateDate()` on the `Android.Widget.TimePicker` and press the "ok" button. 546 | 547 | Setting `AutomationId` in Xamarin.Forms Project: 548 | 549 | ```C# 550 | TimePicker myTime = new TimePicker { AutomationId = "MyTimePicker"}; 551 | ``` 552 | 553 | In code: 554 | ```C# 555 | //Activate the TimePicker 556 | app.Tap(x=>x.Id("MyTimePicker")); 557 | 558 | //Wait for TimePicker animation to completed 559 | app.WaitForElement(x=>x.Id("timePicker")); 560 | 561 | //Invoke methods to select time 562 | app.Query(x=>x.Id("timePicker").Invoke("setHour",3)); 563 | app.Query(x=>x.Id("timePicker").Invoke("setMinute",30)); 564 | 565 | //Tap the ok button to close the TimePicker dialogue 566 | app.Tap(x=>x.Id("button1"));//Ok Button in TimePicker Dialogue 567 | ``` 568 | 569 | The code above shows how we can invoke the `Android.Widget.TimePicker` methods to set the time. The "ok" button will always have an `Id` property of "button1". The "cancel" button will always have an `Id` property of "button2". 570 | 571 | 572 | ### `WebView` 573 | ![WebView](images/WebView.png) 574 | This is a control that needs to be handled differently for iOS and Android. We will also need to know how to invoke the native methods to set the time. 575 | 576 | ### Uniquely Identifying a `WebView` on iOS 577 | Native Control: [UIWebView](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Renderers/WebViewRenderer.cs) 578 | Setting the `AutomationId` property does not work for the `WebView` control and we must identify the `WebView` through its class: `Xamarin_Forms_Platform_iOS_WebViewRenderer`. 579 | 580 | ### Uniquely Identifying a `WebView` on Android 581 | Native Control: [Android.Widget.WebView](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/WebViewRenderer.cs). 582 | Setting the `AutomationId` property on the `TimePicker` will translate to the `Label` property to identify the `Android.Widget.WebView`. 583 | 584 | ##### Is the WebView Loading? 585 | ```C# 586 | if(OnAndroid) 587 | int loadingProgress = app.Query(x => x.Marked("{WebView AutomationId}").Invoke("getProgress")); //Returns a value between 0-100 588 | else if(OniOS) 589 | int isLoading = app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("isLoading")); //0 = false, 1 = true 590 | ``` 591 | 592 | #### What is the current WebView request URL? 593 | ```C# 594 | if(OnAndroid) 595 | string url = app.Query(x => x.Marked("{WebView AutomationId}").Invoke("getUrl"); 596 | else if(OniOS) 597 | string url = app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("request")); 598 | ``` 599 | 600 | #### Reload the current WebView 601 | ```C# 602 | if(OnAndroid) 603 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("reload")); 604 | else if(OniOS) 605 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("reload")); 606 | ``` 607 | 608 | #### Navigate back in current WebView 609 | ```C# 610 | if(OnAndroid) 611 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("goBack")); 612 | else if(OniOS) 613 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("goBack")); 614 | ``` 615 | 616 | #### Navigate forward in current WebView 617 | ```C# 618 | if(OnAndroid) 619 | app.Query(x => x.Marked("{WebView AutomationId}").Invoke("goForward")); 620 | else if(OniOS) 621 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").Invoke("goForward")); 622 | ``` 623 | 624 | #### Evaluate Javascript in current WebView 625 | ```C# 626 | string javascript = "document.getElementById(\"lst-ib\").value=\"Hello\"; //Javascript to change google.com search bar text to "Hello" 627 | 628 | if(OnAndroid) 629 | app.Query(x => x.Marked("{WebView AutomationId}").InvokeJS(javascript)); 630 | else if(OniOS) 631 | app.Query(x => x.Class("Xamarin_Forms_Platform_iOS_WebViewRenderer").InvokeJS(javascript)); 632 | ``` 633 | 634 | ### ToolbarItems 635 | 636 | ### Uniquely Identifying a `ToolbarItem` on iOS 637 | Native Control: [UIBarButtonItem](https://github.com/xamarin/Xamarin.Forms/blob/74cb5c4a97dcb123eb471f6b1dffa1267d0305aa/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs) 638 | Setting the `AutomationId` property on the `ToolbarItem` will translate to the `Id` property to identify the `UINavigationBarButton` in `Xamarin.UITest`. 639 | 640 | Setting `AutomationId` in Xamarin.Forms Project: 641 | 642 | ```C# 643 | //Setting the AutomationId property of ToolBarItem 644 | ToolbarItem firstButton = new ToolbarItem { AutomationId = "ToolbarButtonOne"}; 645 | 646 | //Tapping the NavBar button 647 | app.Tap(x=>x.Id("ToolbarButtonOne")); 648 | ``` 649 | 650 | ### Uniquely Identifying a `ToolbarItem` on Android 651 | Native Control: [Android.Widget.Button](https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.Android/Renderers/ToolbarButton.cs) with two internal `Android.Widget.Button` 652 | Setting the `AutomationId` property on the `ToolbarItem` does not work. Whatever the `ToolbarItem.Text` property is set to will be translated to the `Label` property in `Xamarin.UITest`. 653 | 654 | Setting `ToolbarItem.Text` property in Xamarin.Forms Project: 655 | 656 | ```C# 657 | //Setting the AutomationId property of ToolBarItem 658 | ToolbarItem firstButton = new ToolbarItem { AutomationId = "ToolbarButtonOne", Text = "ToolBarButtonText" }; 659 | 660 | //Tapping the NavBar button 661 | app.Tap(x=>x.Marked("ToolBarButtonText")); 662 | ``` -------------------------------------------------------------------------------- /XtcGuide/Droid/Assets/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories) and given a Build Action of "AndroidAsset". 3 | 4 | These files will be deployed with your package and will be accessible using Android's 5 | AssetManager, like this: 6 | 7 | public class ReadAsset : Activity 8 | { 9 | protected override void OnCreate (Bundle bundle) 10 | { 11 | base.OnCreate (bundle); 12 | 13 | InputStream input = Assets.Open ("my_asset.txt"); 14 | } 15 | } 16 | 17 | Additionally, some Android functions will automatically load asset files: 18 | 19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); 20 | -------------------------------------------------------------------------------- /XtcGuide/Droid/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Android.App; 4 | using Android.Content; 5 | using Android.Content.PM; 6 | using Android.Runtime; 7 | using Android.Views; 8 | using Android.Widget; 9 | using Android.OS; 10 | 11 | namespace XtcGuide.Droid 12 | { 13 | [Activity(Label = "XtcGuide.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] 14 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity 15 | { 16 | protected override void OnCreate(Bundle bundle) 17 | { 18 | TabLayoutResource = Resource.Layout.Tabbar; 19 | ToolbarResource = Resource.Layout.Toolbar; 20 | 21 | base.OnCreate(bundle); 22 | 23 | global::Xamarin.Forms.Forms.Init(this, bundle); 24 | 25 | LoadApplication(new App()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Properties/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Android.App; 4 | 5 | // Information about this assembly is defined by the following attributes. 6 | // Change them to the values specific to your project. 7 | 8 | [assembly: AssemblyTitle("XtcGuide.Droid")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("")] 13 | [assembly: AssemblyCopyright("michaelw")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 20 | 21 | [assembly: AssemblyVersion("1.0.0")] 22 | 23 | // The following attributes are used to specify the signing key for the assembly, 24 | // if desired. See the Mono documentation for more information about signing. 25 | 26 | //[assembly: AssemblyDelaySign(false)] 27 | //[assembly: AssemblyKeyFile("")] 28 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/AboutResources.txt: -------------------------------------------------------------------------------- 1 | Images, layout descriptions, binary blobs and string dictionaries can be included 2 | in your application as resource files. Various Android APIs are designed to 3 | operate on the resource IDs instead of dealing with images, strings or binary blobs 4 | directly. 5 | 6 | For example, a sample Android app that contains a user interface layout (main.axml), 7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) 8 | would keep its resources in the "Resources" directory of the application: 9 | 10 | Resources/ 11 | drawable/ 12 | icon.png 13 | 14 | layout/ 15 | main.axml 16 | 17 | values/ 18 | strings.xml 19 | 20 | In order to get the build system to recognize Android resources, set the build action to 21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but 22 | instead operate on resource IDs. When you compile an Android application that uses resources, 23 | the build system will package the resources for distribution and generate a class called "R" 24 | (this is an Android convention) that contains the tokens for each one of the resources 25 | included. For example, for the above Resources layout, this is what the R class would expose: 26 | 27 | public class R { 28 | public class drawable { 29 | public const int icon = 0x123; 30 | } 31 | 32 | public class layout { 33 | public const int main = 0x456; 34 | } 35 | 36 | public class strings { 37 | public const int first_string = 0xabc; 38 | public const int second_string = 0xbcd; 39 | } 40 | } 41 | 42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main 43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first 44 | string in the dictionary file values/strings.xml. 45 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/XtcGuide/Droid/Resources/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/XtcGuide/Droid/Resources/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/XtcGuide/Droid/Resources/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/XtcGuide/Droid/Resources/drawable/icon.png -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/layout/Tabbar.axml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/layout/Toolbar.axml: -------------------------------------------------------------------------------- 1 |  2 | 3 | -------------------------------------------------------------------------------- /XtcGuide/Droid/Resources/values/styles.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 5 | 6 | 24 | 27 | 28 | -------------------------------------------------------------------------------- /XtcGuide/Droid/XtcGuide.Droid.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {C2A66189-3E04-426E-8190-42B085B68BBF} 7 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | Library 9 | XtcGuide.Droid 10 | XtcGuide.Droid 11 | v7.0 12 | True 13 | Resources\Resource.designer.cs 14 | Resource 15 | Properties\AndroidManifest.xml 16 | Resources 17 | Assets 18 | true 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug 25 | DEBUG; 26 | prompt 27 | 4 28 | None 29 | 30 | 31 | true 32 | pdbonly 33 | true 34 | bin\Release 35 | prompt 36 | 4 37 | true 38 | false 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ..\packages\Xamarin.Android.Support.v4.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll 47 | 48 | 49 | ..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Vector.Drawable.dll 50 | 51 | 52 | ..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll 53 | 54 | 55 | ..\packages\Xamarin.Android.Support.v7.AppCompat.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll 56 | 57 | 58 | ..\packages\Xamarin.Android.Support.v7.RecyclerView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll 59 | 60 | 61 | ..\packages\Xamarin.Android.Support.Design.23.3.0\lib\MonoAndroid43\Xamarin.Android.Support.Design.dll 62 | 63 | 64 | ..\packages\Xamarin.Android.Support.v7.CardView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll 65 | 66 | 67 | ..\packages\Xamarin.Android.Support.v7.MediaRouter.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll 68 | 69 | 70 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\FormsViewGroup.dll 71 | 72 | 73 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Core.dll 74 | 75 | 76 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll 77 | 78 | 79 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Platform.dll 80 | 81 | 82 | ..\packages\Xamarin.Forms.2.3.3.175\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll 83 | 84 | 85 | 86 | 87 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35} 88 | XtcGuide 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /XtcGuide/Droid/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /XtcGuide/UITests/AppInitializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using Xamarin.UITest; 5 | using Xamarin.UITest.Queries; 6 | 7 | namespace XtcGuide.UITests 8 | { 9 | public class AppInitializer 10 | { 11 | public static IApp StartApp(Platform platform) 12 | { 13 | if (platform == Platform.Android) 14 | { 15 | return ConfigureApp.Android.StartApp(); 16 | } 17 | 18 | return ConfigureApp.iOS.StartApp(); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /XtcGuide/UITests/Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using NUnit.Framework; 5 | using Xamarin.UITest; 6 | using Xamarin.UITest.Queries; 7 | 8 | namespace XtcGuide.UITests 9 | { 10 | [TestFixture(Platform.Android)] 11 | [TestFixture(Platform.iOS)] 12 | public class Tests 13 | { 14 | IApp app; 15 | Platform platform; 16 | 17 | public Tests(Platform platform) 18 | { 19 | this.platform = platform; 20 | } 21 | 22 | [SetUp] 23 | public void BeforeEachTest() 24 | { 25 | app = AppInitializer.StartApp(platform); 26 | } 27 | 28 | [Test] 29 | public void Repl() 30 | { 31 | app.Repl(); 32 | } 33 | 34 | [Test] 35 | public void WelcomeTextIsDisplayed() 36 | { 37 | AppResult[] results = app.WaitForElement(c => c.Marked("Welcome to Xamarin Forms!")); 38 | app.Screenshot("Welcome screen."); 39 | 40 | Assert.IsTrue(results.Any()); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /XtcGuide/UITests/XtcGuide.UITests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D} 7 | Library 8 | XtcGuide.UITests 9 | XtcGuide.UITests 10 | v4.5 11 | 12 | 13 | true 14 | full 15 | false 16 | bin\Debug 17 | DEBUG; 18 | prompt 19 | 4 20 | 21 | 22 | true 23 | bin\Release 24 | prompt 25 | 4 26 | 27 | 28 | 29 | 30 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll 31 | 32 | 33 | ..\packages\Xamarin.UITest.2.0.5\lib\Xamarin.UITest.dll 34 | 35 | 36 | 37 | 38 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB} 39 | XtcGuide.iOS 40 | False 41 | False 42 | 43 | 44 | {C2A66189-3E04-426E-8190-42B085B68BBF} 45 | XtcGuide.Droid 46 | False 47 | False 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /XtcGuide/UITests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /XtcGuide/XtcGuide.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide", "XtcGuide\XtcGuide.csproj", "{A4C97C3E-B114-44EA-9995-DF4A95D24D35}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.iOS", "iOS\XtcGuide.iOS.csproj", "{4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.Droid", "Droid\XtcGuide.Droid.csproj", "{C2A66189-3E04-426E-8190-42B085B68BBF}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtcGuide.UITests", "UITests\XtcGuide.UITests.csproj", "{0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | Debug|iPhoneSimulator = Debug|iPhoneSimulator 17 | Release|iPhone = Release|iPhone 18 | Release|iPhoneSimulator = Release|iPhoneSimulator 19 | Debug|iPhone = Debug|iPhone 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU 27 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU 28 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhone.ActiveCfg = Release|Any CPU 29 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhone.Build.0 = Release|Any CPU 30 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU 31 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Release|iPhoneSimulator.Build.0 = Release|Any CPU 32 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhone.ActiveCfg = Debug|Any CPU 33 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35}.Debug|iPhone.Build.0 = Debug|Any CPU 34 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator 35 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator 36 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|Any CPU.ActiveCfg = Release|iPhone 37 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|Any CPU.Build.0 = Release|iPhone 38 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator 39 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator 40 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhone.ActiveCfg = Release|iPhone 41 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhone.Build.0 = Release|iPhone 42 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator 43 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator 44 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhone.ActiveCfg = Debug|iPhone 45 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB}.Debug|iPhone.Build.0 = Debug|iPhone 46 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 47 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|Any CPU.Build.0 = Debug|Any CPU 48 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|Any CPU.ActiveCfg = Release|Any CPU 49 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|Any CPU.Build.0 = Release|Any CPU 50 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU 51 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU 52 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhone.ActiveCfg = Release|Any CPU 53 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhone.Build.0 = Release|Any CPU 54 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU 55 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU 56 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU 57 | {C2A66189-3E04-426E-8190-42B085B68BBF}.Debug|iPhone.Build.0 = Debug|Any CPU 58 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU 63 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU 64 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhone.ActiveCfg = Release|Any CPU 65 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhone.Build.0 = Release|Any CPU 66 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU 67 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU 68 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhone.ActiveCfg = Debug|Any CPU 69 | {0B5E9423-9CE1-4E8B-8008-4A4E1B82382D}.Debug|iPhone.Build.0 = Debug|Any CPU 70 | EndGlobalSection 71 | EndGlobal 72 | -------------------------------------------------------------------------------- /XtcGuide/XtcGuide/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | 4 | // Information about this assembly is defined by the following attributes. 5 | // Change them to the values specific to your project. 6 | 7 | [assembly: AssemblyTitle("XtcGuide")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("michaelw")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". 17 | // The form "{Major}.{Minor}.*" will automatically update the build and revision, 18 | // and "{Major}.{Minor}.{Build}.*" will update just the revision. 19 | 20 | [assembly: AssemblyVersion("1.0.*")] 21 | 22 | // The following attributes are used to specify the signing key for the assembly, 23 | // if desired. See the Mono documentation for more information about signing. 24 | 25 | //[assembly: AssemblyDelaySign(false)] 26 | //[assembly: AssemblyKeyFile("")] 27 | -------------------------------------------------------------------------------- /XtcGuide/XtcGuide/XtcGuide.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Xamarin.Forms; 4 | 5 | namespace XtcGuide 6 | { 7 | public class App : Application 8 | { 9 | public App() 10 | { 11 | // The root page of your application 12 | var content = new ContentPage 13 | { 14 | Title = "XtcGuide", 15 | Content = new StackLayout 16 | { 17 | Children = { 18 | new Label { 19 | HorizontalTextAlignment = TextAlignment.Center, 20 | Text = "Welcome to Xamarin Forms!" 21 | }, 22 | new WebView { AutomationId = "MyWebView", Source = "https://www.google.com/",WidthRequest = 300, HeightRequest = 300 } 23 | } 24 | } 25 | }; 26 | 27 | content.ToolbarItems.Add(new ToolbarItem { AutomationId = "OneButton", Text = "One", Icon = "icon.png" }); 28 | content.ToolbarItems.Add(new ToolbarItem { AutomationId = "TwoButton", Text = "Two", Icon = "icon.png" }); 29 | 30 | MainPage = new NavigationPage(content); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /XtcGuide/XtcGuide/XtcGuide.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35} 7 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | true 9 | Library 10 | XtcGuide 11 | XtcGuide 12 | v4.5 13 | Profile259 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug 20 | DEBUG; 21 | prompt 22 | 4 23 | 24 | 25 | true 26 | bin\Release 27 | prompt 28 | 4 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Core.dll 37 | 38 | 39 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Platform.dll 40 | 41 | 42 | ..\packages\Xamarin.Forms.2.3.3.175\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Xaml.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /XtcGuide/XtcGuide/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /XtcGuide/iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Foundation; 6 | using UIKit; 7 | 8 | namespace XtcGuide.iOS 9 | { 10 | [Register("AppDelegate")] 11 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate 12 | { 13 | public override bool FinishedLaunching(UIApplication app, NSDictionary options) 14 | { 15 | global::Xamarin.Forms.Forms.Init(); 16 | 17 | // Code for starting up the Xamarin Test Cloud Agent 18 | #if ENABLE_TEST_CLOUD 19 | Xamarin.Calabash.Start(); 20 | #endif 21 | 22 | LoadApplication(new App()); 23 | 24 | return base.FinishedLaunching(app, options); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /XtcGuide/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "iphone", 5 | "size": "29x29", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "iphone", 10 | "size": "29x29", 11 | "scale": "2x" 12 | }, 13 | { 14 | "idiom": "iphone", 15 | "size": "29x29", 16 | "scale": "3x" 17 | }, 18 | { 19 | "idiom": "iphone", 20 | "size": "40x40", 21 | "scale": "2x" 22 | }, 23 | { 24 | "idiom": "iphone", 25 | "size": "40x40", 26 | "scale": "3x" 27 | }, 28 | { 29 | "idiom": "iphone", 30 | "size": "57x57", 31 | "scale": "1x" 32 | }, 33 | { 34 | "idiom": "iphone", 35 | "size": "57x57", 36 | "scale": "2x" 37 | }, 38 | { 39 | "idiom": "iphone", 40 | "size": "60x60", 41 | "scale": "2x" 42 | }, 43 | { 44 | "idiom": "iphone", 45 | "size": "60x60", 46 | "scale": "3x" 47 | }, 48 | { 49 | "idiom": "ipad", 50 | "size": "29x29", 51 | "scale": "1x" 52 | }, 53 | { 54 | "idiom": "ipad", 55 | "size": "29x29", 56 | "scale": "2x" 57 | }, 58 | { 59 | "idiom": "ipad", 60 | "size": "40x40", 61 | "scale": "1x" 62 | }, 63 | { 64 | "idiom": "ipad", 65 | "size": "40x40", 66 | "scale": "2x" 67 | }, 68 | { 69 | "idiom": "ipad", 70 | "size": "50x50", 71 | "scale": "1x" 72 | }, 73 | { 74 | "idiom": "ipad", 75 | "size": "50x50", 76 | "scale": "2x" 77 | }, 78 | { 79 | "idiom": "ipad", 80 | "size": "72x72", 81 | "scale": "1x" 82 | }, 83 | { 84 | "idiom": "ipad", 85 | "size": "72x72", 86 | "scale": "2x" 87 | }, 88 | { 89 | "idiom": "ipad", 90 | "size": "76x76", 91 | "scale": "1x" 92 | }, 93 | { 94 | "idiom": "ipad", 95 | "size": "76x76", 96 | "scale": "2x" 97 | }, 98 | { 99 | "size": "24x24", 100 | "idiom": "watch", 101 | "scale": "2x", 102 | "role": "notificationCenter", 103 | "subtype": "38mm" 104 | }, 105 | { 106 | "size": "27.5x27.5", 107 | "idiom": "watch", 108 | "scale": "2x", 109 | "role": "notificationCenter", 110 | "subtype": "42mm" 111 | }, 112 | { 113 | "size": "29x29", 114 | "idiom": "watch", 115 | "role": "companionSettings", 116 | "scale": "2x" 117 | }, 118 | { 119 | "size": "29x29", 120 | "idiom": "watch", 121 | "role": "companionSettings", 122 | "scale": "3x" 123 | }, 124 | { 125 | "size": "40x40", 126 | "idiom": "watch", 127 | "scale": "2x", 128 | "role": "appLauncher", 129 | "subtype": "38mm" 130 | }, 131 | { 132 | "size": "44x44", 133 | "idiom": "watch", 134 | "scale": "2x", 135 | "role": "longLook", 136 | "subtype": "42mm" 137 | }, 138 | { 139 | "size": "86x86", 140 | "idiom": "watch", 141 | "scale": "2x", 142 | "role": "quickLook", 143 | "subtype": "38mm" 144 | }, 145 | { 146 | "size": "98x98", 147 | "idiom": "watch", 148 | "scale": "2x", 149 | "role": "quickLook", 150 | "subtype": "42mm" 151 | } 152 | ], 153 | "info": { 154 | "version": 1, 155 | "author": "xcode" 156 | } 157 | } -------------------------------------------------------------------------------- /XtcGuide/iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /XtcGuide/iOS/Entitlements.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /XtcGuide/iOS/Info.plist: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | CFBundleDisplayName 6 | XtcGuide 7 | CFBundleName 8 | XtcGuide 9 | CFBundleIdentifier 10 | com.michaelwatson.xtcguide 11 | CFBundleShortVersionString 12 | 1.0 13 | CFBundleVersion 14 | 1.0 15 | LSRequiresIPhoneOS 16 | 17 | MinimumOSVersion 18 | 8.0 19 | UIDeviceFamily 20 | 21 | 1 22 | 2 23 | 24 | UILaunchStoryboardName 25 | LaunchScreen 26 | UIRequiredDeviceCapabilities 27 | 28 | armv7 29 | 30 | UISupportedInterfaceOrientations 31 | 32 | UIInterfaceOrientationPortrait 33 | UIInterfaceOrientationLandscapeLeft 34 | UIInterfaceOrientationLandscapeRight 35 | 36 | UISupportedInterfaceOrientations~ipad 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationPortraitUpsideDown 40 | UIInterfaceOrientationLandscapeLeft 41 | UIInterfaceOrientationLandscapeRight 42 | 43 | XSAppIconAssets 44 | Assets.xcassets/AppIcon.appiconset 45 | 46 | 47 | -------------------------------------------------------------------------------- /XtcGuide/iOS/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /XtcGuide/iOS/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | using Foundation; 6 | using UIKit; 7 | 8 | namespace XtcGuide.iOS 9 | { 10 | public class Application 11 | { 12 | // This is the main entry point of the application. 13 | static void Main(string[] args) 14 | { 15 | // if you want to use a different Application Delegate class from "AppDelegate" 16 | // you can specify it here. 17 | UIApplication.Main(args, null, "AppDelegate"); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /XtcGuide/iOS/Resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/XtcGuide/iOS/Resources/icon.png -------------------------------------------------------------------------------- /XtcGuide/iOS/XtcGuide.iOS.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | iPhoneSimulator 6 | {4EEFC877-FF74-4BD8-B693-C5FD2AD912FB} 7 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 8 | Exe 9 | XtcGuide.iOS 10 | XtcGuide.iOS 11 | Resources 12 | 13 | 14 | true 15 | full 16 | false 17 | bin\iPhoneSimulator\Debug 18 | DEBUG;ENABLE_TEST_CLOUD; 19 | prompt 20 | 4 21 | iPhone Developer 22 | true 23 | true 24 | true 25 | true 26 | true 27 | 29091 28 | None 29 | x86_64 30 | HttpClientHandler 31 | Default 32 | x86 33 | 34 | 35 | pdbonly 36 | true 37 | bin\iPhone\Release 38 | prompt 39 | 4 40 | iPhone Developer 41 | true 42 | true 43 | true 44 | Entitlements.plist 45 | SdkOnly 46 | ARMv7, ARM64 47 | HttpClientHandler 48 | Default 49 | x86 50 | 51 | 52 | pdbonly 53 | true 54 | bin\iPhoneSimulator\Release 55 | prompt 56 | 4 57 | iPhone Developer 58 | true 59 | true 60 | None 61 | x86_64 62 | HttpClientHandler 63 | Default 64 | x86 65 | 66 | 67 | true 68 | full 69 | false 70 | bin\iPhone\Debug 71 | DEBUG;ENABLE_TEST_CLOUD; 72 | prompt 73 | 4 74 | iPhone Developer 75 | true 76 | true 77 | true 78 | true 79 | true 80 | true 81 | true 82 | Entitlements.plist 83 | SdkOnly 84 | ARMv7, ARM64 85 | HttpClientHandler 86 | Default 87 | x86 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll 96 | 97 | 98 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll 99 | 100 | 101 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll 102 | 103 | 104 | ..\packages\Xamarin.Forms.2.3.3.175\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll 105 | 106 | 107 | ..\packages\Xamarin.TestCloud.Agent.0.19.0\lib\Xamarin.iOS10\Calabash.dll 108 | 109 | 110 | 111 | 112 | {A4C97C3E-B114-44EA-9995-DF4A95D24D35} 113 | XtcGuide 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /XtcGuide/iOS/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /images/ActivityIndicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/ActivityIndicator.png -------------------------------------------------------------------------------- /images/BoxView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/BoxView.png -------------------------------------------------------------------------------- /images/Button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Button.png -------------------------------------------------------------------------------- /images/DatePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/DatePicker.png -------------------------------------------------------------------------------- /images/Editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Editor.png -------------------------------------------------------------------------------- /images/Entry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Entry.png -------------------------------------------------------------------------------- /images/Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Image.png -------------------------------------------------------------------------------- /images/Label.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Label.png -------------------------------------------------------------------------------- /images/ListView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/ListView.png -------------------------------------------------------------------------------- /images/OpenGL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/OpenGL.png -------------------------------------------------------------------------------- /images/ProgressBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/ProgressBar.png -------------------------------------------------------------------------------- /images/SearchBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/SearchBar.png -------------------------------------------------------------------------------- /images/Stepper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Stepper.png -------------------------------------------------------------------------------- /images/Switch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/Switch.png -------------------------------------------------------------------------------- /images/TableViewNewest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/TableViewNewest.png -------------------------------------------------------------------------------- /images/TimePicker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/TimePicker.png -------------------------------------------------------------------------------- /images/WebView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-watson/forms-xtc-guide/cba960a83f097cd1318d8c850f15f339268ea134/images/WebView.png --------------------------------------------------------------------------------