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

Interact with DT datatable fields #4

Closed
sybrohee opened this issue Oct 31, 2023 · 4 comments
Closed

Interact with DT datatable fields #4

sybrohee opened this issue Oct 31, 2023 · 4 comments

Comments

@sybrohee
Copy link

Thank you for this really nice and useful library with which I wish I will be able to use R instead of selenium and python for my shiny applications production tests.
Indeed, as shiny is in R, I would find it more logical to make use of tests that are written in pure R. I have not been convinced by RSelenium which I found way to heavy or by cypress which I found too complicated.

I wanted to use shinytest2 but unfortunately it does not seem to be compatible with applications rendered via shinyproxy .

With selenider, I have been able without (too much) struggling to connect and to display my shiny application.

However, when I wanted to change the number of displayed lines by selecting the field on top of the table (classical DT field), I have not been able to make it change.

image

Having a look at the code, it seems that this selector should be available through something like

find_element(mySeleniderSession, xpath = '//*[@id="myTable"]') |> find_element(xpath = '//*[@class="dataTables_length"]') |> find_element(css = "label:nth-child(1)") |> find_element(css = "select:nth-child(1)") |> find_element(css = "option:nth-child(5)") |> elem_click()

This is what I was doing with Selenium but in this case, the "click" simply does not take place.

Would you have any insight of what I am missing.

Thank you again for this really good library.

Regards

@ashbythorpe
Copy link
Owner

ashbythorpe commented Nov 1, 2023

This issue is universal with all select elements, and is most likely an issue with chromote, which I've reported here:
rstudio/chromote#131

For now, you can use elem_set_value() on the select input, e.g:

library(selenider)

session <- minimal_selenider_session("
<select name='select'>
  <option value='1'>One</option>
  <option value='2'>Two</option>
</select>
", view = TRUE)

s("select") |>
  elem_set_value("Two")

This works quite nicely, although for some reason it highlights the select element.

I guess in your case it would be something like:

find_element(mySeleniderSession, "#myTable") |>
  find_element(".dataTables_length") |>
  find_element("select") |>
  elem_set_value("100")

In the future, I might create an elem_select() function to interact with select elements more easily.

@sybrohee
Copy link
Author

sybrohee commented Nov 2, 2023

Hi @ashbythorpe,

Thanks a lof for your fast answer. It is working now and in combination with rvest (as described in your documentation), I could extract a data.table from my DT:datatable in my shiny app.

However, I would really like that chromote could allow any type of click. For example, I am not sure that the issue I raised a while ago about airDatePicker would be working (I should test it, though).

Again, many thanks for your help and good luck with the new library

@sybrohee sybrohee closed this as completed Nov 2, 2023
@ashbythorpe
Copy link
Owner

ashbythorpe commented Nov 2, 2023

Thanks @sybrohee,

Since the issue is specific to <select> elements, and airDatePicker elements use custom <div> elements instead of <select> elements, chromote should work fine with airDatePicker elements.

I tested this out with the following code:

library(selenider)
library(callr)

start_app <- function() {
  library(shiny)
  library(shinyWidgets)

  ui <- fluidPage(
    airDatepickerInput("date")
  )

  server <- function(input, output, session) {}

  runApp(shinyApp(ui, server), host = "127.0.0.1", port = 4566L)
}

process <- callr::r_bg(start_app)

Sys.sleep(5) # Wait for the server to start

session <- selenider_session(view = TRUE)

open_url("http://127.0.0.1:4566")

# Focus the input element, opening the Calander.
s("#date") |>
  elem_click()

s(".air-datepicker-nav--title") |>
  elem_click() |> # This moves from days to months
  elem_click() # This moves from months to years

# Select the year 2021
s(".air-datepicker-body.-years-") |>
  find_element("div[data-year='2021']") |>
  elem_click()

# Select the month April
s(".air-datepicker-body.-months-") |>
  find_elements(".air-datepicker-cell") |>
  elem_find(has_text("Apr")) |>
  elem_click()

# Select the 26th day
s(".air-datepicker-body.-days-") |>
  find_element("div[data-date='26']:not(.-other-month-)") |> # Make sure the day is not from another month
  elem_click()

# Stop focusing the input
elem_send_keys(NULL, keys$esc)

# Make sure the value is as expected
execute_js_fn("x => x.value", s("#date"))
#> [1] "2021-04-26"

process$finalize()
process$kill()

This selects a date using only clicks.

@sybrohee
Copy link
Author

sybrohee commented Nov 3, 2023

Hello @ashbythorpe ,

With this little piece of code ... you made my day!

Long live Selenider :-) ... chromote was really difficult to understand (to me) as soon as the actions we wanted to achieve were not straightforward and with Selenider you really made evertything easier.

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

No branches or pull requests

2 participants