positron icon indicating copy to clipboard operation
positron copied to clipboard

Create test for hyperlinks

Open jonvanausdeln opened this issue 1 year ago • 3 comments

We should look to add a tests to cover some scenarios using & following hyperlinks, similar to this discussion

https://github.com/posit-dev/positron/discussions/4968#discussion-7296959

jonvanausdeln avatar Oct 10 '24 16:10 jonvanausdeln

After reading a little closer, I don't think we need this test for now.

jonvanausdeln avatar Oct 10 '24 16:10 jonvanausdeln

When we get to doing this, @jennybc might have some input/suggestions on what is needed to test.

jonvanausdeln avatar Oct 10 '24 18:10 jonvanausdeln

Short version which we can flesh out later: we should test that ANSI based hyperlinks "work" (for various definitions of "work") in the R console. The cli package (https://cli.r-lib.org/index.html) is the main producer of such links. But what I'm suggesting is probably not to explicitly test cli usage, but rather to explicitly test hard-wired well-formed hyperlinks (and leave it to cli to test that it's producing such hyperlinks).

Best cli doc for an inventory of links we expect to see often in R: https://cli.r-lib.org/reference/links.html

jennybc avatar Oct 10 '24 19:10 jennybc

Attach cli to play with the code below.

library(cli)

Accessing R help

The first case is a basic clickable link to open help for an R function.

txt <- "Help for a function: {.fun utils::available.packages}"
cli_text(txt)
#> Help for a function: `utils::available.packages()`

In interactive use in the Positron Console, you should be able to click on utils::available.packages() and view that help in HELP.

It's also worth knowing about cli::format_inline() to get your hands on the string that cli is emitting, i.e. the string that contains the OSC 8 hyperlink.

format_inline(txt)
#> [1] "Help for a function: `\033]8;;x-r-help:utils::available.packages\autils::available.packages\033]8;;\a()`"

If you want the Positron tests to not depend on and exercise cli, you could generate these strings with cli::format_inline(), hardcode them in the tests, and just cat() them.

txt_formatted <- "Help for a function: `\033]8;;x-r-help:utils::available.packages\autils::available.packages\033]8;;\a()`"
cat(txt_formatted)

Arguably this separates concerns, i.e. cli is responsible for testing that it emits the intended OSC 8 hyperlinks and Positron tests that it handles them as intended. But it would also be fine to test that Positron "handles cli hyperlinks", because that is what we really care about.

There are a few more help variants we should tickle.

Help with custom link text:

txt <- "Help for a function with custom text: {.help [CLICK HERE](utils::sessionInfo)}"
cli_text(txt)
#> Help for a function with custom text: CLICK HERE (`?utils::sessionInfo()`)
format_inline(txt)
#> [1] "Help for a function with custom text: \033]8;;x-r-help:utils::sessionInfo\aCLICK HERE\033]8;;\a"

Help for a topic that is not a function:

txt <- "Help for a non-function topic: {.topic utils::BATCH}"
cli_text(txt)
#> Help for a non-function topic: `?utils::BATCH`
format_inline(txt)
#> [1] "Help for a non-function topic: \033]8;;x-r-help:utils::BATCH\autils::BATCH\033]8;;\a"

An external webpage

txt <- "A webpage: {.url https://posit.co}"
cli_text(txt)
#> A webpage: <https://posit.co>
format_inline(txt)
#> [1] "A webpage: <\033]8;;https://posit.co\ahttps://posit.co\033]8;;\a>"

Accessing a vignette

Unfortunately, no base or recommended package has an html vignette. So we have to test this with some other R package. I chose dplyr, because it seems likely it will always be required by other Positron tests.

txt <- "A vignette: {.vignette dplyr::dplyr}"
cli_text(txt)
#> A vignette: `vignette(dplyr::dplyr)`
format_inline(txt)
#> [1] "A vignette: \033]8;;x-r-vignette:dplyr::dplyr\adplyr::dplyr\033]8;;\a"

In the Positron Console, you should be able to click on dplyr::dplyr and view "Introduction to dplyr" in HELP.

Runnable code

Hyperlinks for runnable code only work for a very short list of blessed packages. rlang is one of them and will presumably be dragged in by several other packages used in Positron tests.

txt <- "Is rlang installed? Run this to find out: {.run rlang::is_installed('rlang')}"
cli_text(txt)
#> Is rlang installed? Run this to find out: `rlang::is_installed('rlang')`
format_inline(txt)
#> [1] "Is rlang installed? Run this to find out: \033]8;;x-r-run:rlang::is_installed('rlang')\arlang::is_installed('rlang')\033]8;;\a"

In the Positron console, clicking on the hyperlink should look like this:

#> Is rlang installed? Run this to find out: rlang::is_installed('rlang')
rlang::is_installed('rlang')
#> [1] TRUE

The core packages base, stats, and utils are specially disallowed.

txt <- "You can't click to run {.run utils::sessionInfo()}"
cli_text(txt)
#> You can't click to run `utils::sessionInfo()`
format_inline(txt)
#> [1] "You can't click to run \033]8;;x-r-run:utils::sessionInfo()\autils::sessionInfo()\033]8;;\a"

If you click on utils::sessionInfo(), you should get an information message ("Code hyperlink not recognized ...") and no code execution.

For other packages, if and only if the package is attached, you should get clickable code execution.

library(stringr)

txt <- "This should work: {.run stringr::str_c('hello, ', 'world')}"
cli_text(txt)
#> This should work: `stringr::str_c('hello, ', 'world')`

In the Positron console, clicking on the hyperlink should look like this:

#> This should work: stringr::str_c('hello, ', 'world')
stringr::str_c('hello, ', 'world')
#> [1] "hello, world"

File hyperlinks

I'm assuming this test is running in the workspace corresponding to qa-example-content/workspaces/r_testing/, which has a DESCRIPTION file. The important thing is linking to a file that exists.

txt <- "Let's open a file {.file DESCRIPTION}"
cli_text(txt)
#> Let's open a file 'DESCRIPTION'
format_inline(txt)
#> [1] "Let's open a file '\033]8;;positron://file/Users/jenny/rrr/qa-example-content/workspaces/r_testing/DESCRIPTION\aDESCRIPTION\033]8;;\a'"

Clicking on DESCRIPTION should open that file in the editor.

You should also be able to open at a specific line or specific line and column.

cli_text("Let's open a file {.file DESCRIPTION:15}")
#> Let's open a file 'DESCRIPTION:15'
cli_text("Let's open a file {.file DESCRIPTION:15:20}")
#> Let's open a file 'DESCRIPTION:15:20'

jennybc avatar Apr 11 '25 02:04 jennybc

Automated tests have been added

testlabauto avatar Apr 15 '25 19:04 testlabauto