I am effectively using geb-spock for our web application. I am new to geb spock appium and struggling with PageObject mechanism in Appium as I have comfortably achieved that for web application.
I am successfully able to launch the App and able to perform some actions on app with below code.
#Stepwise
class TC_001_DictionaryApp_Spec extends GebReportingSpec {
def "Step 1:Go to the login page of the WU"() {
when: "User is on Dictionary App"
// at AppHomePage
and: " User enters the value in Searh box"
/*page.textboxSearch.value("Obsess")*/
driver.findElement(By.id("com.dictionary.mr:id/input_text_view")).sendKeys("Obsess")
and: "Press the Enter"
then: "Word should be searched"
}
}
However if I try to use at or to block then its getting failed. (If you un-comment the code in the above test case it's not working) Below is my page object class
class AppHomePage extends Page {
static at = {}
static content ={
textboxSearch (wait:true) { driver.findElement(By.id("com.dictionary.mr:id/input_text_view")) }
}
}
Can you please guide me how I can achieve the page object mechanism with geb spock appium.
Thanks!
You haven't added an assertion in your "at" block so it will fail.
class AppHomePage extends Page {
static at = { title == "my title assertion"}
static content ={
textboxSearch (wait:true) { driver.findElement(By.id("com.dictionary.mr:id/input_text_view")) }
}
}
Related
I'm trying to create a custom Debug Tree class to get the same result as the following:
I have followed this Stackoverflow answer:
Log method name and line number in Timber
But using that answer gives me two problems:
Implementing the custom Debug Tree class does not log anything when I use more than one method.
public class MyDebugTree extends Timber.DebugTree {
#Override
protected String createStackElementTag(StackTraceElement element) {
return String.format("(%s:%s)#%s",
element.getFileName(),
element.getLineNumber(),
element.getMethodName());
}
}
public class BaseApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
Timber.plant(new MyDebugTree);
}
}
}
The above causes it to not log at all.
If I use only return element.getFileName(); it successfully logs that one error.
The second problem I'm having is that using a custom DebugTree class does not give me the same results as using err.getStackTrace()[0].getLineNumber().
}, err -> {
Timber.e("Method name: " + err);
Timber.e("Method name: " + err.getStackTrace()[0].getMethodName());
}
The custom Debug Tree class does not display the name of the method I'm trying to log.
Why is it not logging when I use all three methods?
Also how can I get it to log like it would using
err.getStackTrace()[0].getMethodName()?
I'm using 'com.jakewharton.timber:timber:4.7.1'
You seem to be doing it right. I recreated your code in kotlin (programming language should not matter) and i was able to show my logs.
MyDebugTree.kt
class QueenlyDebugTree : Timber.DebugTree() {
override fun createStackElementTag(element: StackTraceElement): String {
return "(${element.fileName}:${element.lineNumber})#${element.methodName}"
}
}
force log using an actual exception:
try {
throw RuntimeException("Hello World")
} catch (e: Exception) {
Timber.e(e)
}
i got a log:
So, from what i saw from your code, its most probably because you have a compact logcat view. To update your logcat view, follow these steps:
1. Make sure you have standard view selected
2. Configure standard view
3. Make sure Show tags is selected and tag column is at max(35)
I recently started learning Xamarin and was following through some tutorials that show how to use Xamarin.Firebase.Auth nuget package to handle authentication. I was able to login and get the Id Token at that point without a problem.
I also want to use an api that I have built that uses the token for it's JWT. I've used Firebase before and know that their id tokens expire after one hour. So I looked around for a tutorial on how to setup my code to handle the token changes, but couldn't find anything. I started going through the code and the only thing I could find was a method to add an Id Token Listener. So, I put together a Listener class.
public class IdTokenListener : Java.Lang.Object, FirebaseAuth.IIdTokenListener
{
public EventHandler<TokenChangedEventArgs> IdTokenChanged;
public class TokenChangedEventArgs: EventArgs
{
public string Token { get; set; }
}
public void OnIdTokenChanged(FirebaseAuth auth)
{
auth.CurrentUser.GetIdToken(false).AsAsync<GetTokenResult>().ContinueWith((task) =>
{
IdTokenChanged?.Invoke(this, new TokenChangedEventArgs { Token = task.Result.Token });
});
}
}
Then in the MainActivity.cs file of the Android project (haven't worked on the iOS project yet), I created a class level variable to hold an instance of the listener. I also called the AddIdTokenListener method as well as adding an event handler within the OnCreate method:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
IdTokenListener idTokenListener = new IdTokenListener();
protected override void OnCreate(Bundle savedInstanceState)
{
// Other code removed for space
FirebaseAuth.Instance.AddIdTokenListener(idTokenListener);
idTokenListener.IdTokenChanged += OnIdTokenChanged;
LoadApplication(new App());
}
private void OnIdTokenChanged(object sender, IdTokenListener.TokenChangedEventArgs e)
{
Console.WriteLine("Main Activity - OnIdTokenChanged: " + e.Token);
}
}
When the app loads or I use the login page, the token listener is called and I get the expected results. However, if I leave the app running, the token listener is never called again. I even left it running overnight just to make sure it wasn't a timing issue. Is there something else I need to do in order to get this to work?
I am developing an APP with wechat login feature. After getting approval from wechat it will call a custom activity of my NativeScript APP. I am getting response correctly but how can I move to another page instated of the home page after doing some verification. I am using NativeScript + Angular.
Sample code
getJSON("https://api.weixin.qq.com/sns/oauth2/access_token?appid=ID&secret=SECRET&code=" + res.code + "&grant_type=authorization_code").then((res) => {
console.dir(res);
// ===> here I want navigation
}, err => {
console.dir(err);
})
I tried like this:
frame.topmost().navigate("src/app/login/login.component");
but getting error:
JS: Unhandled Promise rejection: Cannot set property '_moduleName' of undefined ; Zone: ; Task: Promise.then ; Value: TypeError: Cannot set property '_moduleName' of undefined TypeError: Cannot set property '_moduleName' of undefined
Please give me some suggestions. Thanks in advance :)
Fire an event from the Activity callback, something like
import { android } from "tns-core-modules/application";
...
public onResp(res: com.tencent.mm.opensdk.modelbase.BaseResp) {
console.log("onResp");
console.dir(res);
androidApp.notify(<AndroidActivityEventData>{ eventName: 'wxapiresponse', object: android, activity: this });
}
In app component, listen to the event
export class AppComponent implements OnInit {
constructor(private ngZone: NgZone, private routerExtensions: RouterExtensions) {}
ngOnInit() {
application.android.on('wxapiresponse', this.wxApiResponse, this);
}
wxApiResponse() {
// making sure the event callback runs inside Angular zone
this.ngZone.run(() => {
this.routerExtensions.navigate(...);
});
}
}
A similar problem cost me an entire Weekend, without knowing how the companion controller .js or .ts files look like I can only recommend you go to the basics / source:
https://docs.nativescript.org/core-concepts/navigation#frame
it helped me find the problem in my code.
If you wrote a custom Page that does not start from a template chances are you wrote the controller too and it's easy to overlook some line that is present in the samples - even thou it looks like you don't need it.
If you paste your controller JS we could understand your context.
For instance, here is piece of code you should definitely include to help you debug:
in your page-you-navigate-to.xml
<Page loaded="onPageLoaded" class="page">
...
</Page>
in your page-you-navigate-to.ts
import { EventData } from "tns-core-modules/data/observable";
import { Page } from "tns-core-modules/ui/page";
export function onPageLoaded(args: EventData): void {
const page = <Page>args.object;
var context = page.navigationContext;
page.bindingContext = context;
console.log("Target page Loaded.");
}
Start your debugger, and step through see where you have null values and read up on those method calls and their parameters.
I'm trying to send data back and forth from Flutter to my native platform (in this case Android).
In order to keep some model consistency, I have generated the models for all platforms by using Protocol-Buffers.
When I try to pass data from Android to Flutter I'm not finding any way to do it without shenanigans like serializing to a handcrafted JSON.
There must be a way to use protobuf in order to do so, isn't it?
In order to give context, I have made a minimal app to try to solve this problem:
My Protocol Buffer
syntax = "proto3";
option java_package = "com.test.protobuf_test";
option java_outer_classname = "ProtoModel";
message SimplePerson {
int32 id= 1;
string name= 2;
}
From which I generate my model using:
protoc --java_out and protoc --dart_out
In Dart I get my class
class SimplePerson extends $pb.GeneratedMessage {...}
And in Java
public final class ProtoModel {
...
public static final class SimplePerson extends
com.google.protobuf.GeneratedMessageV3 implements
SimplePersonOrBuilder {...}
}
From Android inside my method channel, I am trying to pass one or many ProtoModel.SimplePerson objects back to Dart.
No success so far.
How would you actually do it?
I'd expect it to be something like
In Java:
ProtoModel.SimplePerson person = ProtoModel.SimplePerson.newBuilder().setId(3).setName("Person Name").build();
result(person);
And in Dart:
var result = await platform.invokeMethod("generatePerson");
if(result is SimplePerson) {
print("Success!");
} else {
print("Failure!");
}
So far I'm only getting Failures or Exceptions.
Thanks!
your very close your using result but i have it working with result.success
when (call.method) {
"getPlatformVersion" -> result.success(getPlatformVersion().toByteArray())
}
private fun getPlatformVersion(): Models.Version {
return Models.Version.newBuilder().setVersionName("Android ${android.os.Build.VERSION.RELEASE}").build()
}
great example here https://www.freecodecamp.org/news/flutter-platform-channels-with-protobuf-e895e533dfb7/
EDIT didnt see how old this post was
I have to use this as Pigeon is sill early access, and although pigeon was generally harder to set up i do prefer it
My android app communicate with backend service through REST API . I want to mock out this API to quickly develop the front end.
I am using android volley as client side networking library.
You can use the dependency injection design pattern for this.
Basically you specify an interface that defines a set of methods corresponding to the queries you have in your REST backend, e.g.:
interface DataSupplier {
// Lookup user by ID
User getUser(int id);
// Get all blog posts posted by a specific user.
List<BlogPost> getUsersBlogPosts(int userId);
}
Now in the class where you need to query the backend, you specify an injector. This can be done in multiple ways (e.g. constructor injection, setter injection - see the wiki article for more details). An injector lets you inject an implementation of the dependency into the class that depends on it. Let us assume you use constructor injection. Your class that uses the backend would look like this:
public class DependentClass {
private final DataSupplier mSupplier;
public DependentClass(DataSupplier dataSupplier) {
mSupplier = dataSupplier;
}
// Now you simply call mSupplier whenever you need to query the mock
// (or - later in development - the real) REST service, e.g.:
public void printUserName() {
System.out.println("User name: " + mSupplier.getUser(42).getName());
}
}
Then you create a mock implementation of DataSupplier:
public class MockRestService implements DataSupplier {
#Override
public User getUser(int id) {
// Return a dummy user that matches the given ID
// with 'Alice' as the username.
return new User(id, "Alice");
}
#Override
public List<BlogPost> getUsersBlogPosts(int userId) {
List<BlogPost> result = new ArrayList<BlogPost>();
result.add(new BlogPost("Some Title", "Some body text"));
result.add(new BlogPost("Another Title", "Another body text"));
result.add(new BlogPost("A Third Title", "A third body text"));
return result;
}
}
and use that to instantiate your dependent class:
DepedentClass restClient = new DepedentClass(new MockRestService());
Now you can use restClient as if it was connected to your actual backend. It will simply return dummy objects that you can use to develop your front end.
When you are done with your front end and ready to implement your backend, you do so by creating another implementation of DataSupplier that sets up a connection to your REST backend and queries it for real objects. Let us say you name this implementation RestService. Now you can simply replace the constructor creating the MockRestService with your RestService constructor like so:
DepedentClass restClient = new DepedentClass(new RestService());
And there you have it: by swapping a single constructor call, you can change your front end code from using dummy objects to using real REST-delivered objects.
You could even have a debug flag and create the restClient according to the state of your application (debug or release):
boolean debug = true;
DependentClass restClient = null;
if (debug) {
restClient = new DepedentClass(new MockRestService());
} else {
restClient = new DepedentClass(new RestService());
}
I've recently created RESTMock. It is a library for Mocking REST API's in android tests. It can be used during development though. You would need to set it up following the README on github and create a basic Android Instrumentation test that would start your app and do nothing. This way the app is started with the Mock Server in background.
Example test:
public class SmokeTest {
#Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<MainActivity>(
SplashActivity.class,
true,
false);
#Test
public void smokeTest() throws InterruptedException {
rule.launchActivity(null);
Thread.sleep(10000000);
}
}