tests/testthat/test-methods.R

test_that("as.data.frame flattens complete cff objects", {
  path <- system.file("examples/CITATION_complete.cff", package = "cffr")

  the_cff <- cff_read(path)

  # To df
  the_df <- as.data.frame(the_cff)

  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)

  # lengths
  allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))

  expect_length(unique(names(the_df)), ncol(the_df))

  # As vector
  df_as_v <- as.character(as.vector(the_df[1, ]))

  expect_identical(allf, df_as_v)
  expect_snapshot(names(the_df))
})

test_that("as.data.frame flattens partial cff objects", {
  path <- system.file("examples/CITATION_complete.cff", package = "cffr")

  the_cff <- cff_read(path)

  # To df authors only
  subcff <- the_cff$authors[[1]]
  the_df <- as.data.frame(subcff)
  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)
  # lengths
  allf <- unlist(subcff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))
  expect_length(unique(names(the_df)), ncol(the_df))

  # To df references only
  subcff <- the_cff$references[[1]]
  the_df <- as.data.frame(subcff)
  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)
  # lengths
  allf <- unlist(subcff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))
  expect_length(unique(names(the_df)), ncol(the_df))
})

test_that("as.data.frame converts preferred citations", {
  path <- system.file("examples/DESCRIPTION_many_persons", package = "cffr")
  a_cit <- as_bibentry(cff_create(path))

  the_cff <- as_cff(a_cit)

  # To df
  the_df <- as.data.frame(the_cff)

  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)

  # lengths
  allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))

  expect_length(unique(names(the_df)), ncol(the_df))

  # As vector
  df_as_v <- as.character(as.vector(the_df[1, ]))

  expect_identical(allf, df_as_v)
  expect_snapshot(names(the_df))
})


test_that("as.data.frame converts authors", {
  a_pers_lst <- as_cff_person(
    "A person and {A Entity inc.} and {One person} more"
  )

  the_cff <- a_pers_lst[[1]]

  # To df
  the_df <- as.data.frame(the_cff)

  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)

  # lengths
  allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))

  expect_length(unique(names(the_df)), ncol(the_df))

  # As vector
  df_as_v <- as.character(as.vector(the_df[1, ]))

  expect_identical(allf, df_as_v)
  expect_snapshot(names(the_df))
})

test_that("as.data.frame converts lists of authors", {
  path <- system.file("examples/CITATION_complete.cff", package = "cffr")

  the_cff <- cff_read(path)$authors

  # To df
  the_df <- as.data.frame(the_cff)

  expect_s3_class(the_df, "data.frame")
  expect_equal(nrow(the_df), 1)

  # lengths
  allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE)
  expect_length(allf, ncol(the_df))

  expect_length(unique(names(the_df)), ncol(the_df))

  # As vector
  df_as_v <- as.character(as.vector(the_df[1, ]))

  expect_identical(allf, df_as_v)
  expect_snapshot(names(the_df))
})


test_that("as.person converts cff person lists", {
  rvers <- getRversion()
  skip_if(!grepl("^4.6", rvers), "Snapshot created with R 4.6.*")
  skip_on_cran()
  path <- system.file("examples/CITATION_complete.cff", package = "cffr")

  the_cff <- cff_read(path)

  getref <- the_cff$references[[1]]

  # Single entity
  pub <- as.person(getref$publisher)
  expect_s3_class(pub, "person")

  expect_snapshot(dput(pub))
  expect_snapshot(format(
    pub,
    include = c("given", "family", "email", "role", "comment")
  ))

  # Single person
  aut <- as.person(getref$authors[[1]])
  expect_s3_class(aut, "person")
  expect_snapshot(dput(aut))
  expect_snapshot(format(
    aut,
    include = c("given", "family", "email", "role", "comment")
  ))

  # List of authors
  aut2 <- as.person(getref$authors)

  expect_s3_class(aut2, "person")
  expect_s3_class(aut2[1], "person")
  expect_s3_class(aut2[2], "person")
  expect_snapshot(dput(aut2))

  # Malformed
  malf <- getref$authors
  malf[[1]] <- list(a = "list")
  expect_s3_class(malf, "cff_pers_lst")

  expect_snapshot(end <- as.person(malf))
  expect_s3_class(end, "person")
  expect_length(end, 1)

  # Duplicates
  aa <- getref$authors
  aa[[3]] <- aa[[1]]
  expect_s3_class(aa, "cff_pers_lst")

  expect_snapshot(aa2 <- as.person(aa))
  expect_s3_class(aa2, "person")
  expect_length(aa2, 2)
})

test_that("as.person reports the number of malformed elements", {
  malformed <- structure(
    list(list(a = "first"), list(b = "second")),
    class = c("cff_pers_lst", "cff")
  )

  expect_snapshot(result <- as.person(malformed))
  expect_s3_class(result, "person")
  expect_length(result, 0)
})

test_that("as.person method names and particles", {
  skip_on_cran()
  str <- "von Wicksteed, III, P. H. and {The translator factory}"

  cf <- as_cff_person(str)
  expect_snapshot(cf)

  pers_bib <- toBibtex(as.person(cf))
  again <- as_cff_person(pers_bib)
  expect_identical(cf, again)
})

test_that("unsupported as.person methods report errors", {
  path <- system.file("examples/CITATION_complete.cff", package = "cffr")
  the_cff <- cff_read(path)
  expect_s3_class(the_cff, "cff", exact = TRUE)
  expect_snapshot(as.person(the_cff), error = TRUE)

  # identifiers
  key <- the_cff$identifiers
  expect_s3_class(key, c("cff_ref_lst", "cff"), exact = TRUE)
  expect_snapshot(as.person(key), error = TRUE)

  # preferred
  key <- the_cff$`preferred-citation`
  expect_s3_class(key, c("cff_ref", "cff"), exact = TRUE)
  expect_snapshot(as.person(key), error = TRUE)
})

test_that("head and tail preserve cff classes", {
  a_cff <- cff()
  expect_snapshot(a_cff)
  expect_snapshot(head(a_cff, 2))
  expect_s3_class(head(a_cff, 2), "cff")

  expect_snapshot(tail(a_cff, 2))
  expect_s3_class(tail(a_cff, 2), "cff")
})

test_that("toBibtex converts supported cff structures", {
  skip_on_cran()

  # Create several alternatives
  descobj <- cff_read_description(system.file(
    "examples/DESCRIPTION_basic",
    package = "cffr"
  ))

  citobj <- cff_read_citation(system.file(
    "examples/CITATION_basic",
    package = "cffr"
  ))
  newbib <- cff_read_bib(system.file("examples/example.bib", package = "cffr"))

  full_cff <- merge_desc_cit(descobj, c(newbib, citobj))
  full_cff <- new_cff(full_cff)
  expect_true(cff_validate(full_cff, verbose = FALSE))

  # A. validate extractions
  expect_snapshot(toBibtex(full_cff))
  expect_snapshot(toBibtex(full_cff, what = "references"))
  expect_snapshot(toBibtex(full_cff, what = "all"))

  # single entries
  single <- toBibtex(full_cff$`preferred-citation`)
  expect_s3_class(single, "Bibtex")
  expect_equal(sum(names(single) == "title"), 1)

  # Several entries
  several <- toBibtex(full_cff$references)
  expect_s3_class(several, "Bibtex")
  expect_equal(sum(names(several) == "title"), 3)

  # One entry
  oneent <- toBibtex(full_cff$references[[1]])
  expect_s3_class(oneent, "Bibtex")
  expect_equal(sum(names(oneent) == "title"), 1)

  fromfile <- toBibtex(newbib)
  expect_s3_class(fromfile, "Bibtex")
  expect_equal(sum(names(fromfile) == "title"), 2)

  # From lines
  string <- "@book{einstein1921,
    title        = {Relativity: The Special and the General Theory},
    author       = {Einstein, A.},
    year         = 1920,
    publisher    = {Henry Holt and Company},
    address      = {London, United Kingdom},
    isbn         = 9781587340925}"

  froml <- toBibtex(cff_read_bib_text(string))
  expect_equal(sum(names(froml) == "title"), 1)

  # Persons

  sev_auth <- as_cff_person(
    "{The Big Bopper} and Frank Sinatra and Dean Martin and Davis, Jr., Sammy"
  )

  comp <- c(
    person("The Big Bopper"),
    person("Frank", "Sinatra"),
    person("Dean", "Martin"),
    person("Sammy", "Davis, Jr.")
  )

  expect_length(sev_auth, 4)
  expect_s3_class(sev_auth, "cff_pers_lst")
  expect_identical(toBibtex(sev_auth), toBibtex(comp))

  # Single person
  single <- as_cff_person(person("A", "person", email = "a@b.d"))[[1]]
  expect_s3_class(single, "cff_pers")
  expect_identical(toBibtex(single), toBibtex(person("A", "person")))

  # Single entity
  single <- as_cff_person(person("{A and B co}", email = "a@b.d"))[[1]]
  expect_s3_class(single, "cff_pers")
  expect_identical(
    toBibtex(single),
    toBibtex(person("A and B co", email = "a@b.d"))
  )
})


test_that("as.list removes nested cff classes and supports round-trips", {
  f <- system.file("examples/CITATION_complete.cff", package = "cffr")

  full_cff <- cff_read_cff_citation(f)

  count_cff_classes <- function(x) {
    n <- as.integer("cff" %in% class(x))
    if (!is.list(x)) {
      return(n)
    }

    n + sum(vapply(x, count_cff_classes, integer(1)))
  }

  expect_gt(count_cff_classes(full_cff), 0)

  # Unlist
  unl <- as.list(full_cff)

  expect_identical(count_cff_classes(unl), 0L)

  # Reclass
  regen_cff <- as_cff(unl)

  expect_identical(full_cff, regen_cff)

  expect_true(cff_validate(regen_cff, verbose = FALSE))
})

Try the cffr package in your browser

Any scripts or data that you put into this service are public.

cffr documentation built on Aug. 24, 2026, 5:11 p.m.