playwright-java
playwright-java copied to clipboard
[Feature]: Add Gradle examples to documentation
Feature request
Is it possible to add Gradle examples to the Playwright documentation along the current Maven ones?
It'd be nice to have one! If anyone who uses Gradle is willing to contribute such an example we'd appreciate that.
I am using gradle so I could try to reproduce all the examples, and then contribute them.
It turns out that Gradle doesn't have a direct equivalent of Maven's exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project's build.gradle
which then can be executed.
Because that requires a bit more description instead of just a "run this line" instruction, how would you like to integrate the gradle instructions into the doc?
Example of a task that needs to be added to build.gradle
:
task runPlaywrightCli(type: JavaExec) {
mainClass = 'com.microsoft.playwright.CLI'
classpath sourceSets.main.runtimeClasspath
args 'open'
}
Which can then be run with ./gradlew runPlaywrightCli
Also, gradle files can be written in Groovy (the original way) or in Kotlin (newer way which is pretty popular for new projects I think). How do you want to deal with this? I have only a Groovy setup, so couldn't easily test the Kotlin code.
args
above can also be set dynamically from the CLI, so the minimum would be to define one "generic" Playwright task, and then I think all the Maven examples can be translated into Gradle commands that run this task with a set of arguments.
I thought you were originally talking about just gradle config for adding playwright deps but now I see that you are talking about all the cli examples. In that case I believe we'll need something like TypeScript/JavaScript tabs (see e.g. this page) but for the two build systems Maven/Gradle. As for the task definition I'd like the command line to be as close as possible to the node.js one. For example if it's
npx playwright open --device="iPhone 11" wikipedia.org
in nodejs it'd be nice to map it to something as concise as
./gradlew playwright open --device="iPhone 11" wikipedia.org
in a Gradle project. Would that be possible? As for the syntax preference we could provide the snippet in both Groovy and Kotlin similar to how Gradle docs do it. If not, I'd stay with more conservative option of Groovy as I'd expect clients that write their scripts in Kotlin to know how to translate Groovy to Kotlin.
You probably know this already but just in case, our docs live in the upstream repo and then we roll it periodically to playwright.dev to update it so these changes would need to go the playwright repo.
Also, gradle files can be written in Groovy (the original way) or in Kotlin (newer way which is pretty popular for new projects I think). How do you want to deal with this? I have only a Groovy setup, so couldn't easily test the Kotlin code.
There are some neat setups on Gradle website that toggle between Groovy and Kotlin formats. Could that be implemented?
It turns out that Gradle doesn't have a direct equivalent of Maven's
exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project'sbuild.gradle
which then can be executed.
I think maybe you can get away with including the application
plugin and setting the mainClass in the gradle(kotlin) build file:
plugins {
application
kotlin("jvm") version "1.5.0"
}
application {
mainClass.set("com.microsoft.playwright.CLI")
}
...and then running this, but I could be wrong:
./gradlew run --args="install" // you can specify the browser here as well
./gradlew run --args="install-deps"
update:
Just tried both and then work along with browsing a page:
./gradlew run --args="open google.com"
@jhyot and @yury-s - I think both an example gradle in both groovy and kotlin, along with these commands could be super useful in the docs! 😄
There are some neat setups on Gradle website that toggle between Groovy and Kotlin formats. Could that be implemented?
Should be possible and I think this is the way to go.
I think maybe you can get away with including the
application
plugin and setting the mainClass in the gradle(kotlin) build file:
I like how concise the command line is in that case, but I'm concerned that it may get in conflict with the actual "application" in the project. Perhaps it's not an issue (I'm not familiar enough with Gradle)?
@yury-s I am able to run tests locally using Playwright with a similar gradle setup. What would be the best way to test this?
I like how concise the command line is in that case, but I'm concerned that it may get in conflict with the actual "application" in the project. Perhaps it's not an issue (I'm not familiar enough with Gradle)?
Yeah I would not use the application
method as the main official way to use Playwright, because as you noted there can be only one application, and this might already be used by a project.
The best that I could come up with would be called something like this example command:
./gradlew playwright -Pargs="open --device='iPhone 11' wikipedia.org"
and this is the setup:
task playwright(type: JavaExec) {
mainClass = 'com.microsoft.playwright.CLI'
classpath sourceSets.main.runtimeClasspath
if (project.hasProperty('args')) {
args project.getProperty('args')
}
}
Yeah I would not use the
application
method as the main official way to use Playwright, because as you noted there can be only one application, and this might already be used by a project.
The application is actually the framework the user is wrapping around Playwright, and as I mentioned, this does not conflict. I was able to use exactly what I said locally in my own project. So I don't see the issue, but whatever is the best for the general user is going to be the right one, and that may not be mine 😆
Yeah I would not use the
application
method as the main official way to use Playwright, because as you noted there can be only one application, and this might already be used by a project.The application is actually the framework the user is wrapping around Playwright, and as I mentioned, this does not conflict. I was able to use exactly what I said locally in my own project. So I don't see the issue, but whatever is the best for the general user is going to be the right one, and that may not be mine 😆
Not sure if we are maybe misunderstanding each other. I thought (but haven't actually checked) that if a project already uses the application plugin for its own purpose, you can't add another application for playwright.
If your project doesn't use the application, then sure it will work.
It turns out that Gradle doesn't have a direct equivalent of Maven's
exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project'sbuild.gradle
which then can be executed.I think maybe you can get away with including the
application
plugin and setting the mainClass in the gradle(kotlin) build file:plugins { application kotlin("jvm") version "1.5.0" } application { mainClass.set("com.microsoft.playwright.CLI") }
...and then running this, but I could be wrong:
./gradlew run --args="install" // you can specify the browser here as well
./gradlew run --args="install-deps"
update: Just tried both and then work along with browsing a page:
./gradlew run --args="open google.com"
This approach is working well!
It turns out that Gradle doesn't have a direct equivalent of Maven's
exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project'sbuild.gradle
which then can be executed.I think maybe you can get away with including the
application
plugin and setting the mainClass in the gradle(kotlin) build file:plugins { application kotlin("jvm") version "1.5.0" } application { mainClass.set("com.microsoft.playwright.CLI") }
...and then running this, but I could be wrong:
./gradlew run --args="install" // you can specify the browser here as well
./gradlew run --args="install-deps"
update: Just tried both and then work along with browsing a page:./gradlew run --args="open google.com"
This approach is working well!
Glad it is working for you.
@yury-s @jhyot would it be worth it to add this approach as an alternative much like the suggestion at the end of the linked #864 ?
@jhyot I am not sure what you mean. Basically your local framwork is an application that is leveraging the playwright CLI is what is happening if I am not mistaken.
@yury-s @jhyot would it be worth it to add this approach as an alternative much like the suggestion at the end of the linked #864 ?
Yes, we can add a guide providing some tips on how to use gradle + cli. Would you like to send a PR for that (the docs source is here)?
@jhyot I am not sure what you mean. Basically your local framwork is an application that is leveraging the playwright CLI is what is happening if I am not mistaken.
@ddaypunk
For example, if you have a single gradle module for your application (i.e. everything about the main application and all tests etc. is defined in the one gradle build file), and your application is already leveraging the application { }
block for its own purposes (running the app in CLI); then you cannot add another application { }
block just for Playwright. They would conflict.
For that reason, I don't recommend documenting the application { }
method as the only or the main way to use Playwright CLI with gradle. The other way using a task (https://github.com/microsoft/playwright-java/issues/571#issuecomment-920660451) is more generic, because it works in any case.
I believe that many people just copy&paste the build file additions blindly (because most developers are not interested in the details of the build system), so displaying the application { }
method as the first or only way would lead to breaking of some peoples' builds, which I consider bad.
I don't mind if the application { }
method is described additionally as well, because it is convenient. As long as users know the alternatives.
But also, I would guess that because of the types of applications that are most interested in using Playwright (web apps), by far the majority of apps don't use the application
block. So it is in the end of course a judgement call. I just wanted to make the implications clear.
@jhyot If I can get to it, I would love to. Some interesting developments at work today, so I may not get to it for a bit.
So i was looking to add this to the documentation, but the given example in the comment seems to only work with single-word commands? Can anyone reproduce this? (using gradle 7.4)
./gradlew playwright -Pargs="open --device='iPhone 11' wikipedia.org"
task playwright(type: JavaExec) { mainClass = 'com.microsoft.playwright.CLI' classpath sourceSets.main.runtimeClasspath if (project.hasProperty('args')) { args project.getProperty('args') } }
Actually, as I found out, the JavaExec
task type supports the --args
command line parameter (even without application
plugin).
So this should work:
task playwright(type: JavaExec) {
mainClass = 'com.microsoft.playwright.CLI'
classpath sourceSets.main.runtimeClasspath // or possibly sourceSets.test if Playwright is a test dependency only
}
And run like this:
./gradlew playwright --args="open --device='iPhone 11' wikipedia.org"
That should also fix the multiple-args problem as noticed by @eneller.
It turns out that Gradle doesn't have a direct equivalent of Maven's
exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project'sbuild.gradle
which then can be executed.I think maybe you can get away with including the
application
plugin and setting the mainClass in the gradle(kotlin) build file:plugins { application kotlin("jvm") version "1.5.0" } application { mainClass.set("com.microsoft.playwright.CLI") }
...and then running this, but I could be wrong:
./gradlew run --args="install" // you can specify the browser here as well
./gradlew run --args="install-deps"
update: Just tried both and then work along with browsing a page:
./gradlew run --args="open google.com"
Hey @ddaypunk , this works. Can you share an example on how it can be converted to a Gradle kotlin DSL task so that we can run the codegen when we do say ./gradlew codegen --args="open google.com" ? Essentially say we do not want to modify the main application run cli option , as We want the application to execute when We do gradlew run ,We would instead like to add a new task for trigger codegen.
FYI Kotlin is now the default for Gradle build files.
https://blog.gradle.org/kotlin-dsl-is-now-the-default-for-new-gradle-builds
It turns out that Gradle doesn't have a direct equivalent of Maven's
exec:java
goal. So the CLI commands cannot be translated 1:1 into Gradle. Instead, a new task or multiple tasks have to be defined in the project'sbuild.gradle
which then can be executed.I think maybe you can get away with including the
application
plugin and setting the mainClass in the gradle(kotlin) build file:plugins { application kotlin("jvm") version "1.5.0" } application { mainClass.set("com.microsoft.playwright.CLI") }
...and then running this, but I could be wrong:
./gradlew run --args="install" // you can specify the browser here as well
./gradlew run --args="install-deps"
update: Just tried both and then work along with browsing a page:./gradlew run --args="open google.com"
Hey @ddaypunk , this works. Can you share an example on how it can be converted to a Gradle kotlin DSL task so that we can run the codegen when we do say ./gradlew codegen --args="open google.com" ? Essentially say we do not want to modify the main application run cli option , as We want the application to execute when We do gradlew run ,We would instead like to add a new task for trigger codegen.
If I am not mistaken, they are trying to avoid using the application plugin? A few previous comments shows using a task which is already in Kotlin DSL.
Hey @ddaypunk , this works. Can you share an example on how it can be converted to a Gradle kotlin DSL task so that we can run the codegen when we do say ./gradlew codegen --args="open google.com" ? Essentially say we do not want to modify the main application run cli option , as We want the application to execute when We do gradlew run ,We would instead like to add a new task for trigger codegen.
@parthasarma87 check my comment: https://github.com/microsoft/playwright-java/issues/571#issuecomment-1559794309
It is in Groovy, but I think you can find out what the syntax in Kotlin is (I don't know). The key is to create the new task as type JavaExec
. Then the --args
also works for that task automatically, without needing to modify the main application.
First things first. I've made a branch with the changes suggested on the intro page for install
https://github.com/jfgreffier/playwright/tree/feat/gradle-docs
Shall we add Kotlin ? Kotlin only ?
Next step will be to add the alternatives to Playwright commands. For example : ./gradlew playwright --args="codegen demo.playwright.dev/todomvc"
First things first. I've made a branch with the changes suggested on the intro page for install https://github.com/jfgreffier/playwright/tree/feat/gradle-docs
Shall we add Kotlin ? Kotlin only ?
Thanks for getting this started @jfgreffier. I would support adding Kotlin as well, Groovy is so common that I think having both would be useful.
Here is the Kotlin code I have used for a project. Feel free to include it in your commit, or I can add one later if you choose not to add it.
// build.gradle.kts
// Usage: gradle playwright --args="help"
tasks.register<JavaExec>("playwright") {
classpath(sourceSets["test"].runtimeClasspath)
mainClass.set("com.microsoft.playwright.CLI")
}
Thanks @ardetrick I've updated my branch accordingly and created a PR.
I only documented CLI usage with Gradle in the installation page; I feel it's very redondant to add it next to each Maven example. I'm opened to suggestions or co-authoring the PR
I don't have much context on the rest of the example, but the gradle kotlin task looks good to me. thanks for adding it!