From 591c7d9a07f4e27da1f16bd7832de8a86142cdf0 Mon Sep 17 00:00:00 2001 From: Vincent Guyader Date: Tue, 12 May 2026 09:38:26 +0200 Subject: [PATCH 01/10] feat(random_ggplot): add 'ts' / 'timeseries' type (#4) - new type 'ts' (alias 'timeseries') with 3 Date-axis variants (economics unemploy/psavert, AirPassengers) - fix geom_line(size=) -> linewidth deprecation warning (#13) - add coverage for random_ggplotly() - TDD: tests/testthat/test-ggplot-ts.R written first (red), then implementation --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/Plot.R | 44 +++++++++++++++++++++++++++++---- dev/SUIVI_AUTONOME.md | 30 ++++++++++++++++++++++ man/random_ggplot.Rd | 4 +-- man/shinipsum-package.Rd | 3 +-- tests/testthat/test-ggplot-ts.R | 25 +++++++++++++++++++ tests/testthat/test-ggplot.R | 8 ++++++ 8 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 dev/SUIVI_AUTONOME.md create mode 100644 tests/testthat/test-ggplot-ts.R diff --git a/DESCRIPTION b/DESCRIPTION index af6527b..b1faa67 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -36,4 +36,4 @@ Suggests: Encoding: UTF-8 LazyData: true Roxygen: list(markdown = TRUE) -RoxygenNote: 7.1.1 +RoxygenNote: 7.3.3 diff --git a/NAMESPACE b/NAMESPACE index 69040ae..6caa4d5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -17,6 +17,7 @@ importFrom(dygraphs,dygraph) importFrom(ggplot2,aes) importFrom(ggplot2,coord_flip) importFrom(ggplot2,facet_grid) +importFrom(ggplot2,geom_area) importFrom(ggplot2,geom_bar) importFrom(ggplot2,geom_bin2d) importFrom(ggplot2,geom_boxplot) diff --git a/R/Plot.R b/R/Plot.R index 217f78e..9a3f9f5 100644 --- a/R/Plot.R +++ b/R/Plot.R @@ -2,9 +2,9 @@ #' #' This function returns a ggplot object, which can be passed to `renderPlot` and `plotOutput` #' -#' @param type type of the geom. Can be any of "random", "point", "bar", "boxplot","col", "tile", "line", "bin2d", "contour", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", "ribbon", "raster", "tile", "violin" and defines the geom of the ggplot. Default is "random", and chooses a random geom for you. +#' @param type type of the geom. Can be any of "random", "point", "bar", "boxplot","col", "tile", "line", "bin2d", "contour", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", "ribbon", "raster", "tile", "violin", "ts" (alias "timeseries") and defines the geom of the ggplot. Default is "random", and chooses a random geom for you. The "ts" type returns a time-series oriented plot, with a `Date` on the x axis. #' -#' @importFrom ggplot2 ggplot aes geom_point geom_bar scale_color_viridis_d theme_minimal geom_boxplot labs coord_flip geom_tile geom_line facet_grid geom_col scale_fill_viridis_c +#' @importFrom ggplot2 ggplot aes geom_point geom_bar scale_color_viridis_d theme_minimal geom_boxplot labs coord_flip geom_tile geom_line geom_area facet_grid geom_col scale_fill_viridis_c #' @importFrom ggplot2 xlim ylim geom_bin2d geom_contour geom_density geom_density_2d geom_dotplot #' @importFrom ggplot2 geom_hex geom_freqpoly stat geom_histogram geom_ribbon geom_raster geom_violin #' @@ -18,7 +18,10 @@ random_ggplot <- function(type = c("random", "point", "bar", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", "ribbon", "raster", "tile", - "violin")) { + "violin", "ts")) { + if (length(type) == 1L && identical(type, "timeseries")) { + type <- "ts" + } type_matched <- match.arg(type) if (type_matched == "random") { @@ -46,7 +49,8 @@ random_ggplot <- function(type = c("random", "point", "bar", "ribbon" = sample(140:141, 1), "raster" = sample(150:151, 1), "tile" = sample(160:161, 1), - "violin" = sample(170:171, 1) + "violin" = sample(170:171, 1), + "ts" = sample(180:182, 1) ) res <- switch(as.character(r), @@ -144,7 +148,7 @@ random_ggplot <- function(type = c("random", "point", "bar", "50" = list( ggplot(datasets::women) + aes(height, weight) + - geom_line(size = 2) + + geom_line(linewidth = 2) + theme_minimal() ), "51" = list( @@ -299,6 +303,36 @@ random_ggplot <- function(type = c("random", "point", "bar", ggplot(datasets::iris, aes(Species, Sepal.Length)) + geom_violin() + theme_minimal() + ), + "180" = list( + ggplot(ggplot2::economics) + + aes(date, unemploy) + + geom_line() + + labs(x = "date", y = "unemployment") + + theme_minimal() + ), + "181" = list( + ggplot( + data.frame( + date = seq( + as.Date("1949-01-01"), + by = "month", + length.out = length(datasets::AirPassengers) + ), + passengers = as.numeric(datasets::AirPassengers) + ) + ) + + aes(date, passengers) + + geom_line() + + geom_point(size = 0.8) + + theme_minimal() + ), + "182" = list( + ggplot(ggplot2::economics) + + aes(date, psavert) + + geom_area(fill = "#440154FF", alpha = 0.7) + + labs(x = "date", y = "personal savings rate") + + theme_minimal() ) ) res[[1]] diff --git a/dev/SUIVI_AUTONOME.md b/dev/SUIVI_AUTONOME.md new file mode 100644 index 0000000..769cc5e --- /dev/null +++ b/dev/SUIVI_AUTONOME.md @@ -0,0 +1,30 @@ +# Suivi - session autonome (issues shinipsum) + +Branche : `feat/text-variants-and-ts-plot` +Base : `master` (commit de départ : voir `git merge-base`) +Méthode : TDD strict (red d'abord, fix ensuite), couverture maintenue, `pr-reviewer` lancé à intervalles. + +## Contexte + +PR #15 (`fix/multiple-issues`, déjà ouverte, CI verte) couvre déjà les issues **#13**, **#9**, **#5**. +Cette branche s'attaque aux issues restantes. + +## Plan + +| # | Titre | Statut | +|---|-------|--------| +| #4 | option série temporelle pour `random_ggplot()` | fait | +| #1 | `mock_frame()` : zoning de blocs UI Shiny | à faire | +| #3 | variantes de texte pour `random_text()` | à faire (si temps) | + +## Journal + +### #4 - random_ggplot("ts") / "timeseries" - FAIT +- Red : `tests/testthat/test-ggplot-ts.R` (ggplot avec `date` de classe `Date`, alias `timeseries`, présence dans le pool aléatoire) -> 3 FAIL sur `match.arg`. +- Green : ajout du type `"ts"` (alias `"timeseries"`) dans `R/Plot.R`, 3 variantes (codes 180-182) : + - 180 : `economics$unemploy` en `geom_line` + - 181 : `AirPassengers` (data.frame avec colonne `date` mensuelle) en `geom_line` + `geom_point` + - 182 : `economics$psavert` en `geom_area` +- Bonus : `geom_line(size = 2)` -> `geom_line(linewidth = 2)` (déprécation ggplot 3.4, issue #13 - aussi traitée par la PR #15 ; trivial à réconcilier). +- Bonus : test pour `random_ggplotly()` (lignes jusque-là non couvertes). +- Couverture paquet : 98.07% -> 98.55%. Suite : 3359 PASS / 0 FAIL / 0 WARN. diff --git a/man/random_ggplot.Rd b/man/random_ggplot.Rd index 07a25c6..ae641c0 100644 --- a/man/random_ggplot.Rd +++ b/man/random_ggplot.Rd @@ -7,11 +7,11 @@ random_ggplot( type = c("random", "point", "bar", "boxplot", "col", "tile", "line", "bin2d", "contour", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", - "ribbon", "raster", "tile", "violin") + "ribbon", "raster", "tile", "violin", "ts") ) } \arguments{ -\item{type}{type of the geom. Can be any of "random", "point", "bar", "boxplot","col", "tile", "line", "bin2d", "contour", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", "ribbon", "raster", "tile", "violin" and defines the geom of the ggplot. Default is "random", and chooses a random geom for you.} +\item{type}{type of the geom. Can be any of "random", "point", "bar", "boxplot","col", "tile", "line", "bin2d", "contour", "density", "density_2d", "dotplot", "hex", "freqpoly", "histogram", "ribbon", "raster", "tile", "violin", "ts" (alias "timeseries") and defines the geom of the ggplot. Default is "random", and chooses a random geom for you. The "ts" type returns a time-series oriented plot, with a \code{Date} on the x axis.} } \value{ a ggplot diff --git a/man/shinipsum-package.Rd b/man/shinipsum-package.Rd index b0b0ca3..0fa84ce 100644 --- a/man/shinipsum-package.Rd +++ b/man/shinipsum-package.Rd @@ -6,8 +6,7 @@ \alias{shinipsum-package} \title{shinipsum: Lorem-Ipsum-like Helpers for fast Shiny Prototyping} \description{ -Prototype your shiny apps quickly with these - Lorem-Ipsum-like Helpers. +Prototype your shiny apps quickly with these Lorem-Ipsum-like Helpers. } \seealso{ Useful links: diff --git a/tests/testthat/test-ggplot-ts.R b/tests/testthat/test-ggplot-ts.R new file mode 100644 index 0000000..4c02c54 --- /dev/null +++ b/tests/testthat/test-ggplot-ts.R @@ -0,0 +1,25 @@ +context("test-ggplot-ts.R") + +test_that("random_ggplot('ts') returns a time-series ggplot with a Date x", { + lapply( + 1:50, function(x){ + a <- random_ggplot("ts") + expect_is(a, "ggplot") + expect_true("date" %in% names(a$data)) + expect_is(a$data$date, "Date") + # building must not error nor warn (e.g. deprecated aesthetics) + expect_warning(ggplot2::ggplot_build(a), regexp = NA) + } + ) +}) + +test_that("'timeseries' is an alias of 'ts'", { + a <- random_ggplot("timeseries") + expect_is(a, "ggplot") + expect_true("date" %in% names(a$data)) + expect_is(a$data$date, "Date") +}) + +test_that("'ts' is part of the random pool", { + expect_true("ts" %in% eval(formals(random_ggplot)$type)) +}) diff --git a/tests/testthat/test-ggplot.R b/tests/testthat/test-ggplot.R index 06baf4b..0fc274d 100644 --- a/tests/testthat/test-ggplot.R +++ b/tests/testthat/test-ggplot.R @@ -10,3 +10,11 @@ test_that("ggplot creation works", { ) }) + +test_that("ggplotly creation works", { + a <- random_ggplotly() + expect_is(a, "plotly") + expect_is(a, "htmlwidget") + b <- random_ggplotly("ts") + expect_is(b, "plotly") +}) From c9f6ef7ef8dc269118f9605ab39cbef8df64691f Mon Sep 17 00:00:00 2001 From: Vincent Guyader Date: Tue, 12 May 2026 09:54:24 +0200 Subject: [PATCH 02/10] feat(random_mock): add mock UI layout helper (#1) - random_mock(widths, heights, labels) returns a htmltools::tagList of bordered bootstrap columns to sketch a Shiny UI zoning - new Imports: htmltools - declare psavert/passengers globals, ignore dev/ in build - TDD: tests/testthat/test-mock.R written first (red), then implementation --- .Rbuildignore | 1 + DESCRIPTION | 1 + NAMESPACE | 5 +++ R/Mock.R | 88 ++++++++++++++++++++++++++++++++++++++ R/globals.R | 2 +- dev/SUIVI_AUTONOME.md | 15 ++++++- man/random_mock.Rd | 35 +++++++++++++++ tests/testthat/test-mock.R | 43 +++++++++++++++++++ 8 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 R/Mock.R create mode 100644 man/random_mock.Rd create mode 100644 tests/testthat/test-mock.R diff --git a/.Rbuildignore b/.Rbuildignore index 2735ea3..968819f 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -12,4 +12,5 @@ ^LICENSE\.md$ ^README\.Rmd$ ^data-raw$ +^dev$ ^\.github$ diff --git a/DESCRIPTION b/DESCRIPTION index b1faa67..5bc40b1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -27,6 +27,7 @@ Imports: DT, dygraphs, ggplot2 (>= 3.0.0), + htmltools, magrittr, plotly, stats, diff --git a/NAMESPACE b/NAMESPACE index 6caa4d5..524c5e2 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,11 +8,13 @@ export(random_ggplot) export(random_ggplotly) export(random_image) export(random_lm) +export(random_mock) export(random_print) export(random_table) export(random_text) importFrom(DT,datatable) importFrom(attempt,stop_if_all) +importFrom(attempt,stop_if_not) importFrom(dygraphs,dygraph) importFrom(ggplot2,aes) importFrom(ggplot2,coord_flip) @@ -43,6 +45,9 @@ importFrom(ggplot2,stat) importFrom(ggplot2,theme_minimal) importFrom(ggplot2,xlim) importFrom(ggplot2,ylim) +importFrom(htmltools,HTML) +importFrom(htmltools,tagList) +importFrom(htmltools,tags) importFrom(magrittr,"%>%") importFrom(plotly,ggplotly) importFrom(stats,HoltWinters) diff --git a/R/Mock.R b/R/Mock.R new file mode 100644 index 0000000..027a796 --- /dev/null +++ b/R/Mock.R @@ -0,0 +1,88 @@ +#' A Mock UI Layout +#' +#' Build a quick "zoning" of a Shiny UI: a row of bootstrap columns, each one +#' drawn as an empty bordered box with a centered label. Handy to sketch the +#' layout of an app before any real content exists. +#' +#' The returned object is a [htmltools::tagList()] (a self-contained CSS `