1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
library(testit)
op = options(device = function(file = NULL, ...) {
pdf(file, ...)
dev.control('enable') # important! otherwise plots get discarded
})
evaluate = evaluate::evaluate
classes = function(x) vapply(x, function(x) class(x)[1], character(1))
# remove the blank plot
assert('blank plots are removed', {
res = evaluate('layout(t(1:2))')
(identical(classes(res), 'source'))
})
assert('plots generated by par(), palette() or layout() are removed', {
res = evaluate('par(mfrow = c(1, 2))\npie(islands)\nbarplot(islands)')
(identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1))))
res = evaluate('layout(t(1:2))\npie(islands)\nbarplot(islands)')
(identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1))))
res = evaluate('pie(islands)\nbarplot(islands)\npar(mfrow = c(1, 2))')
res = merge_low_plot(res)
(identical(classes(res), rep(c('source', 'recordedplot'), length = 5)))
res = evaluate('pie(islands)\npar(cex.main=1.2)\nbarplot(islands)')
res = merge_low_plot(res)
(identical(classes(res), c('source', 'recordedplot')[c(1, 2, 1, 1, 2)]))
res = evaluate('par(cex.main=1.2)\npalette(c("red","black"))\nbarplot(islands)')
(identical(classes(res), rep(c('source', 'recordedplot'), c(3, 1))))
})
assert('merge low-level changes', {
res = evaluate('plot(1)\npoints(1.1, 1.1)')
(classes(res) %==% rep(c('source', 'recordedplot'), 2))
(classes(merge_low_plot(res)) %==% rep(c('source', 'recordedplot'), c(2, 1)))
})
assert('captures grid graphics', {
res = evaluate('library(grid)
grid.newpage()
grid.rect(gp=gpar(fill="grey"))
grid.rect(gp=gpar(fill="red"))')
(classes(res) %==% c('source', 'recordedplot')[c(1, 1, 1, 2, 1, 2)])
res = merge_low_plot(res)
(identical(classes(res), rep(c('source', 'recordedplot'), c(4, 1))))
})
options(op)
# rmarkdown sets dev.args = list(pdf = list(useDingbats = FALSE)) when dev = 'pdf'
if (!has_error({png(); dev.off()})) {
assert('chunk_device() correctly opens the png device with dev.args', {
chunk_device(opts_chunk$merge(list(
dev = 'png', dev.args = list(pdf = list(useDingbats = FALSE))
)))
plot(1:10)
dev.off()
TRUE
})
}
if (requireNamespace("ragg", quietly = TRUE) &&
!has_error({ragg::agg_png(); dev.off()})) {
assert(
'chunk_device() correctly opens the ragg::agg_png device with dev.args',
{
chunk_device(opts_chunk$merge(list(
dev = 'ragg_png', dev.args = list(pdf = list(useDingbats = FALSE))
)))
plot(1:10)
dev.off()
TRUE
}
)
assert(
'ragg_png_dev correctly handles bg dev.arg into background arg',
{
chunk_device(opts_chunk$merge(list(
dev = 'ragg_png', dev.args = list(bg = "grey")
)))
plot(1:10)
dev.off()
TRUE
}
)
}
# should not error (find `pdf` correctly in grDevices, instead of the one
# defined below)
pdf = function() {}
do.call(pdf_null, list(7, 7))
dev.off()
gen_source = function(x) structure(x, class = 'source')
gen_plotrc = function(x) structure(factor(x), class = c('factor', 'recordedplot'))
assert('fig_before_code() moves plots before code blocks', {
res = list(
gen_source(1), gen_plotrc('a'), gen_plotrc('b'), gen_source(2), gen_source(3),
gen_plotrc('c'), gen_source(4), gen_plotrc('d')
)
(fig_before_code(res) %==% res[c(2, 3, 1, 4, 6, 5, 8, 7)])
})
assert('plots are rearrange based on fig.keep & fig.show options', {
res = list(gen_source(1), gen_source(2))
(rearrange_figs(res, 'high', NULL, 'asis') %==% res)
# only one plot to keep
res = c(evaluate('plot(1)'), list(gen_source(1)))
(rearrange_figs(res, 'high', NULL, 'asis') %==% res)
(rearrange_figs(res, 'all', NULL, 'asis') %==% res)
(rearrange_figs(res, 'last', NULL, 'asis') %==% res)
(rearrange_figs(res, 'first', NULL, 'asis') %==% res)
(rearrange_figs(res, 'index', 2, 'asis') %==% res)
# several plots
res = c(list(gen_source(1)), evaluate('plot(1)\npoints(1.1, 1.1)'),
list(gen_plotrc('b'), gen_source(2)))
(rearrange_figs(res, 'high', NULL, 'asis') %==% res[-3])
(rearrange_figs(res, 'all', NULL, 'asis') %==% res)
(rearrange_figs(res, 'all', NULL, 'hold') %==% res[c(1:2, 4, 7, 3, 5, 6)])
(rearrange_figs(res, 'last', NULL, 'asis') %==% res[c(-3, -5)])
(rearrange_figs(res, 'first', NULL, 'asis') %==% res[c(-5, -6)])
(rearrange_figs(res, 'none', NULL, 'asis') %==% res[c(-3, -5, -6)])
# correspond to options$fig.keep with numeric vector
(rearrange_figs(res, 'index', 1, 'asis') %==% res[c(-5, -6)])
(rearrange_figs(res, 'index', c(2, 3), 'asis') %==% res[c(-3)])
(rearrange_figs(res, 'index', c(2, 3), 'hold') %==% res[c(1:2, 4, 7, 5, 6)])
(rearrange_figs(res, 'index', c(1, 2, 3), 'asis') %==% res)
})
# should not error when a plot label contains special characters and sanitize=TRUE
if (xfun::loadable('tikzDevice') && Sys.which('pdflatex') != '' &&
(!is.na(Sys.getenv('CI', NA)) || Sys.getenv('USER') == 'yihui' || !xfun::is_macos())) {
knit('knit-tikzDevice.Rnw', quiet = TRUE)
unlink(c('*-tikzDictionary', 'figure', 'knit-tikzDevice.tex'), recursive = TRUE)
}
# https://github.com/yihui/knitr/issues/1166
knit(text = "\\Sexpr{include_graphics('myfigure.pdf', error = FALSE)}", quiet = TRUE)
assert('include_graphics() expands ~', {
path1 = "~/test.png"
(!has_warning(include_graphics("img/test.png", error = FALSE)))
(unclass(suppressWarnings(include_graphics(path1, error = FALSE))) %==% path.expand(path1))
})
with_par = function(expr, ...) {
# set par
op = graphics::par(...)
# reset on exit
on.exit(graphics::par(op))
# save changed state
global.pars = par(no.readonly = TRUE)
# reset par
graphics::par(op)
# simulate what happens when global.par = TRUE by restoring pars
par2(global.pars)
# evaluate in this state
force(expr)
}
assert("par2 correctly handles specific pars", {
(par2(NULL) %==% NULL)
# correctly changed
(with_par(par("col") %==% "red", col = "red"))
(with_par(par("cex") %==% 2, cex = 2))
# unchanged
old = par("fig")
(with_par(par("fig") %==% old, fig = old / 2))
old = par("fin")
(with_par(par("fin") %==% old, fin = old / 2))
old = par("pin")
(with_par(par("pin") %==% old, pin = old / 2))
old = par("usr")
(with_par(par("usr") %==% old, usr = old / 2))
old = par("ask")
(with_par(par("ask") %==% old, ask = !old))
# Does not work - something else is changing plt when setting everything
# old = par("plt")
# (with_par(par("plt") %==% old, plt = old / 2))
})
|