Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: clipboard get/set contentType #478

Merged
merged 11 commits into from
Aug 14, 2019
Merged

Conversation

KazuCocoa
Copy link
Member

Below error happens against [debug] [WD Proxy] Proxying [POST /wd/hub/session/50c33b86-8579-4d8a-911b-b175996978b6/appium/device/set_clipboard] to [POST http://localhost:8200/session/24fe3836-7a6c-4a01-a57c-be0c4a6e327e/appium/device/set_clipboard] with body: {"contentType":"plaintext","content":"aGFwcHkgdGVzdGluZw==","label":"Note"} since the contentType was lower case. Not sure from when, but recent espresso driver can work for PLAINTEXT case even if previosly it accepts plaintext.

Selenium::WebDriver::Error::InvalidArgumentError: io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter contentType
        at io.appium.espressoserver.lib.handlers.SetClipboard.handleInternal(SetClipboard.kt:42)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handleInternal(SetClipboard.kt:32)
        at io.appium.espressoserver.lib.handlers.RequestHandler$DefaultImpls.handle(RequestHandler.kt:28)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handle(SetClipboard.kt:32)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handle(SetClipboard.kt:32)
        at io.appium.espressoserver.lib.http.Router.route(Router.kt:216)
        at io.appium.espressoserver.lib.http.Server.serve(Server.kt:53)
        at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:945)
        at fi.iki.elonen.NanoHTTPD$ClientHandler.run(NanoHTTPD.java:192)
        at java.lang.Thread.run(Thread.java:764)
Caused by: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter contentType
        at io.appium.espressoserver.lib.handlers.SetClipboard$SetClipboardRunnable.<init>(Unknown Source:2)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handleInternal(SetClipboard.kt:39)
        ... 9 more
from InvalidArgumentError: io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException: java.lang.IllegalArgumentException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter contentType

In this PR, I changed to accept such lower case, too. Uppercase and lowercase are enough so far.
contentType can be null, so I've added ?.

Copy link
Contributor

@imurchie imurchie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small typo in comment. Otherwise great!

@@ -33,6 +33,13 @@ class GetClipboard : RequestHandler<GetClipboardParams, String?> {

@Throws(AppiumException::class)
override fun handleInternal(params: GetClipboardParams): String? {
// Can be null if contentType was no plaintext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'not plaintext'?

@@ -35,6 +34,14 @@ class SetClipboard : RequestHandler<SetClipboardParams, Void?> {
@Throws(AppiumException::class)
override fun handleInternal(params: SetClipboardParams): Void? {
params.content ?: throw InvalidArgumentException("The 'content' argument is mandatory")

// Can be null if contentType was no plaintext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same?

// Can be null if contentType was no plaintext
if (params.contentType == null
|| !ClipboardDataType.supportedDataTypes().contains(params.contentType.toString().toLowerCase())) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the empty line is redundant

@@ -33,6 +33,13 @@ class GetClipboard : RequestHandler<GetClipboardParams, String?> {

@Throws(AppiumException::class)
override fun handleInternal(params: GetClipboardParams): String? {
// Can be null if contentType was no plaintext
if (params.contentType == null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that it should be set to 'plaintext' be default if nothing else was set

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I also assumed so, but debugger showed here was null for {"contentType":"plaintext","content":"aGFwcHkgdGVzdGluZw==","label":"Note"}
Maybe, something was wrong in Gson mapping.
(would like to dig further as after this fix)

@@ -35,6 +34,13 @@ class SetClipboard : RequestHandler<SetClipboardParams, Void?> {
@Throws(AppiumException::class)
override fun handleInternal(params: SetClipboardParams): Void? {
params.content ?: throw InvalidArgumentException("The 'content' argument is mandatory")

// FIXME: Can be null while contentType should be ClipboardDataType.PLAINTEXT by default
if (params.contentType == null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so it cannot be null anymore, or it still can?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still can if a request had no 'plaintext' or 'PLAINTEXT' like 'image' in content Type attribute

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is weird..., perhaps we just don't know how GSON works

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah...
When I used Gson, non-null did not work. I remember such discussion..

Copy link
Member Author

@KazuCocoa KazuCocoa Aug 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found some articles about GSON such as:
https://proandroiddev.com/most-elegant-way-of-using-gson-kotlin-with-default-values-and-null-safety-b6216ac5328c

I also found a Japanese article decoding the generated code into Java.
According to them, we cannot handle properly for non-null (default) value in some case in Kotlin.
So, we should do like https://github.com/appium/appium-espresso-driver/pull/478/files#diff-88e41c77db8f06054ff5887d7d6e3031R27

It worked fine.

error example:

Selenium::WebDriver::Error::InvalidArgumentError: io.appium.espressoserver.lib.handlers.exceptions.InvalidArgumentException: Only [plaintext] content types are supported. 'image' is given instead
        at io.appium.espressoserver.lib.model.ClipboardDataType$Companion.invalidClipboardDataType(ClipboardDataType.kt:14)
        at io.appium.espressoserver.lib.model.SetClipboardParams.getContentType(SetClipboardParams.kt:33)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handleInternal(SetClipboard.kt:40)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handleInternal(SetClipboard.kt:31)
        at io.appium.espressoserver.lib.handlers.RequestHandler$DefaultImpls.handle(RequestHandler.kt:28)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handle(SetClipboard.kt:31)
        at io.appium.espressoserver.lib.handlers.SetClipboard.handle(SetClipboard.kt:31)
        at io.appium.espressoserver.lib.http.Router.route(Router.kt:216)
        at io.appium.espressoserver.lib.http.Server.serve(Server.kt:53)
        at fi.iki.elonen.NanoHTTPD$HTTPSession.execute(NanoHTTPD.java:945)
        at fi.iki.elonen.NanoHTTPD$ClientHandler.run(NanoHTTPD.java:192)
        at java.lang.Thread.run(Thread.java:764)
from InvalidArgumentError: io.appium.espressoserver.lib.han

@mykola-mokhnach
Copy link
Contributor

The test now fails :(

it('should set and get clipboard', async function () {
await driver.setClipboard(new Buffer.from('Hello').toString('base64'), 'plaintext');
await driver.getClipboard().should.eventually.eql('Hello');
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note.
Expects 'SGVsbG8=' instead of Hello

@KazuCocoa
Copy link
Member Author

Yes. Will fix it later

await driver.setClipboard(new Buffer.from('Hello').toString('base64'), 'plaintext');
// 'SGVsbG8=' is 'Hello' in base 64 encoding with a new line.
const text = await driver.getClipboard('PLAINTEXT');
text.should.eql('SGVsbG8=\n');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This behaviour, '\n', does not change from UIA2

data class SetClipboardParams(
val contentType: ClipboardDataType = ClipboardDataType.PLAINTEXT,
@SerializedName("contentType")
private val _contentType: String?,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what the point in having the underscore in the property name?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid to conflict with val contentType : ClipboardDataType in line 26

) : AppiumParams() {
val contentType : ClipboardDataType
get() {
if (_contentType == null) return ClipboardDataType.PLAINTEXT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move the getter to a shared method to avoid duplication?

@KazuCocoa KazuCocoa merged commit 7d1e981 into appium:master Aug 14, 2019
@KazuCocoa KazuCocoa deleted the km/fix-clipboard branch August 14, 2019 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants