tests/testthat/GatingHierarchy-testSuite.R

context("---- gh")

test_that(".isCompensated",
    {
      expect_true(flowWorkspace:::.isCompensated(gh))
    })

test_that("getNodeInd ",{
      
      #invalid numeric indexing
      expect_error(flowWorkspace:::.getNodeInd(gh, 2), "string", class = "Rcpp::not_compatible")
      
      #invalid node name
      expect_error(flowWorkspace:::.getNodeInd(gh, "singlet"), "singlet not found", class = "std::domain_error")
      
      #valid unique node name
      expect_equal(flowWorkspace:::.getNodeInd(gh, "singlets"), 3)
      
      expect_equal(flowWorkspace:::.getNodeInd(gh, "root"), 1)
      
      expect_equal(flowWorkspace:::.getNodeInd(gh, "CD3+"), 4)
      
      #full path indexing
      expect_equal(flowWorkspace:::.getNodeInd(gh, "/not debris/singlets/CD3+/CD4/38- DR+"), 6)
      expect_equal(flowWorkspace:::.getNodeInd(gh, "/not debris/singlets/CD3+/CD8/38- DR+"), 15)
      
      #partial path 
      expect_equal(flowWorkspace:::.getNodeInd(gh, "CD4/38- DR+"), 6)
      expect_equal(flowWorkspace:::.getNodeInd(gh, "CD8/38- DR+"), 15)
      
      #non-unqiue partial path
      expect_error(flowWorkspace:::.getNodeInd(gh, "/38- DR+"), "not found", class = "std::domain_error")
      
      #non-unique node name indexing
      expect_error(flowWorkspace:::.getNodeInd(gh, "38- DR+"), "is ambiguous within the gating tree", class = "std::domain_error")
      
      #dealing with root
      expect_equal(flowWorkspace:::.getNodeInd(gh, "/not debris"), 2)
      expect_equal(flowWorkspace:::.getNodeInd(gh, "not debris"), 2)
      expect_equal(flowWorkspace:::.getNodeInd(gh, "/root/not debris"), 2)
      expect_equal(flowWorkspace:::.getNodeInd(gh, "root/not debris"), 2)
      
    })


test_that("gh_pop_get_indices ",{
      
      thisRes <- gh_pop_get_indices(gh, "singlets")
      expectRes <- readRDS(file.path(resultDir, "getIndice_singlet_gh.rds"))
      expect_equal(thisRes,expectRes)
      
    })

test_that("gh_pop_set_indices ",{
  node <- "singlets"
  idx <- gh_pop_get_indices(gh, node)
  idx1 <- idx
  idx1[c(1,3,5)] <- F
  gh_pop_set_indices(gh, node, idx1)
  expect_equal(gh_pop_get_indices(gh, node), idx1)
  #restore  
  gh_pop_set_indices(gh, node, idx)
  expect_equal(gh_pop_get_indices(gh, node), idx)
})

test_that("gh_get_compensations ",{
      
      thisRes <- gh_get_compensations(gh)
      expectRes <- readRDS(file.path(resultDir, "getCompensationMatrices_gh.rds"))
      expect_equal(thisRes,expectRes, tolerance = 2e-08)
      
    })

test_that("gh_pop_is_bool_gate ",{
      expect_false(gh_pop_is_bool_gate(gh, "singlets"))
      
      bf <- booleanFilter(`CD4/38- DR+|CD4/CCR7- 45RA+`, filterId = "myBoolFilter")
      suppressWarnings(id <- pop_add(bf, gh))
      expect_true(gh_pop_is_bool_gate(gh, "myBoolFilter"))
      invisible(gh_pop_remove(gh, "myBoolFilter"))
    })


test_that("gh_pop_get_data ",{
      
      fr <- gh_pop_get_data(gh)
      expect_is(fr, "cytoframe");
      expect_equal(nrow(fr), 119531)
      
      fr <- gh_pop_get_data(gh, "CD8")
      expect_equal(nrow(fr), 14564)
      
      cf <- gh_pop_get_data(gh, use.exprs = FALSE)
      fr <- cytoframe_to_flowFrame(cf)
      expect_equal(nrow(fr), 0)
    })



test_that("sampleNames",{
      
      sn <- sampleNames(gh)
      expect_equal(sn, "CytoTrol_CytoTrol_1.fcs")
      
    })

test_that("gs_get_pop_paths & gh_pop_set_visibility",{

      expectRes <- readRDS(file.path(resultDir, "getNodes_gh.rds"))

      #full path
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]])
      expect_equal(gs_get_pop_paths(gh, path = "full"), expectRes[["full_path"]])
      
            
      expect_equal(gs_get_pop_paths(gh, path = 1), expectRes[["terminal"]])
      
      #fixed partial path
      expect_equal(gs_get_pop_paths(gh, path = 2), expectRes[["path_two"]])
      expect_equal(gs_get_pop_paths(gh, path = 3), expectRes[["path_three"]])
      
      #auto partial path
      expect_equal(gs_get_pop_paths(gh, path = "auto"), expectRes[["path_auto"]])
      
      #full path (bfs)
      expect_equal(gs_get_pop_paths(gh, order = "bfs"), expectRes[["full_path_bfs"]])
      expect_equal(gs_get_pop_paths(gh, order = "tsort"), expectRes[["full_path_tsort"]])
      
      #change node name
      invisible(gh_pop_set_name(gh, "singlets", "S"))
      expect_equal(gs_get_pop_paths(gh), gsub("singlets", "S", expectRes[["full_path"]]))
      invisible(gh_pop_set_name(gh, "S", "singlets"))
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]])
      
      #hide node(terminal)
      invisible(gh_pop_set_visibility(gh, "DNT", FALSE))
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]][-23])
      invisible(gh_pop_set_visibility(gh, "DNT", TRUE))
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]])
      
      #hide node(non-terminal)
      invisible(gh_pop_set_visibility(gh, "singlets", FALSE))
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]][-3])
      invisible(gh_pop_set_visibility(gh, "singlets", TRUE))
      expect_equal(gs_get_pop_paths(gh), expectRes[["full_path"]])
    })

test_that("gh_pop_set_gate", {
      
      gate_cd4 <- gh_pop_get_gate(gh, "CD4")
      gate_cd8 <- gh_pop_get_gate(gh, "CD8")
      invisible(gh_pop_set_gate(gh, "CD4", gate_cd8))
      expect_equal(gh_pop_get_gate(gh, "CD4")@cov, gate_cd8@cov)
      suppressMessages(recompute(gh, "CD4"))
      expect_equal(gh_pop_get_stats(gh, "CD4")[[2]], gh_pop_get_stats(gh, "CD8")[[2]])
      
      #restore the gate
      invisible(gh_pop_set_gate(gh, "CD4", gate_cd4))
      suppressMessages(recompute(gh, "CD4"))
    })    

test_that(".getAllDescendants",{
      nodelist <- new.env(parent=emptyenv())
      allNodes <- gs_get_pop_paths(gh, showHidden = TRUE)
      nodelist$v <-integer()
      flowWorkspace:::.getAllDescendants(gh, "CD3+", nodelist)
      thisRes <- nodelist$v
      expectRes <- readRDS(file.path(resultDir, "getAllDescendants_cd3_gh.rds"))
      expect_equal(allNodes[thisRes], expectRes)
      
      nodelist$v <-integer()
      flowWorkspace:::.getAllDescendants(gh, "CD4", nodelist)
      thisRes <- nodelist$v
      expectRes <- readRDS(file.path(resultDir, "getAllDescendants_cd4_gh.rds"))
      expect_equal(allNodes[thisRes], expectRes)
      
      nodelist$v <-integer()
      flowWorkspace:::.getAllDescendants(gh, "CD8", nodelist)
      thisRes <- nodelist$v
      expectRes <- readRDS(file.path(resultDir, "getAllDescendants_cd8_gh.rds"))
      expect_equal(allNodes[thisRes], expectRes)
      
    })

test_that("show ",{
      
      thisRes <- paste(capture.output(show(gh)), collapse = "")
      expectRes <- "Sample:  CytoTrol_CytoTrol_1.fcs GatingHierarchy with  24  gates"
      expect_equal(thisRes, expectRes)
            
    })

test_that("keyword",{
      thisRes <- keyword(gh)
      expectRes <- readRDS(file.path(resultDir, "kw_gh.rds"))
      kw_fn <- "CytoTrol_CytoTrol_1.fcs"
      
      expect_true(grepl(kw_fn, thisRes$FILENAME))
      expect_true(grepl(kw_fn, expectRes$FILENAME))
      expectRes$FILENAME <- NULL
      thisRes$FILENAME <- NULL
      #skip flowCore_R keys due to the historical archived results do not have this info up to date
      thisRes <- thisRes[!grepl("(flowCore_\\$P)|(transformation)",names(thisRes))]
      colnames(thisRes[["SPILL"]]) <- gsub("<|>", "", colnames(thisRes[["SPILL"]]))
      
      expectRes <- expectRes[!grepl("(flowCore_\\$P)|(transformation)",names(expectRes))]
      #fix legacy result
      expectRes[paste0("$P",5:11, "N")] <- paste0("<", expectRes[paste0("$P",5:11, "N")], ">")
      expectRes <- lapply(expectRes, function(i){
                                      if(is.character(i))
                                        trimws(i)
                                      else
                                        i
                                         })
      expectRes[["$BEGINDATA"]] <- NULL
      expectRes[["$ENDDATA"]] <- NULL
      expectRes[["GUID"]] <- "CytoTrol_CytoTrol_1.fcs"
      expect_equal(thisRes[names(expectRes)], expectRes, tol = 6e-6)
      expect_equal(keyword(gh, 'P11DISPLAY'), "LOG")
      
      expect_equal(keyword(gh, '$P8N'), "<V450-A>")
    })

test_that("gs_pop_get_parent",{
      
      
      expect_equal(gs_pop_get_parent(gh, "singlets"), "/not debris")
      
      expect_equal(gs_pop_get_parent(gh, "not debris/singlets"), "/not debris")
      
      expect_error(gs_pop_get_parent(gh, "singlet"), "singlet not found", class = "std::domain_error")
      
      expect_error(gs_pop_get_parent(gh, "root"), "0 :parent not found!", class = "std::domain_error")
      
    })

test_that("gs_pop_get_children",{
      
      
      expect_equal(gs_pop_get_children(gh, "not debris/singlets"), "/not debris/singlets/CD3+")
      
      expect_equal(gs_pop_get_children(gh, "singlets"), "/not debris/singlets/CD3+")
      
      
      expect_error(gs_pop_get_children(gh, "singlet"), "singlet not found", class = "std::domain_error")
      
      expect_error(gs_pop_get_children(gh, "38- DR+"), "ambiguous", class = "std::domain_error")
      
      expect_equal(gs_pop_get_children(gh, "CD4/38- DR+"), character(0))
      
      expect_equal(gs_pop_get_children(gh, "CD3+"), c("/not debris/singlets/CD3+/CD4"
                                              , "/not debris/singlets/CD3+/CD8"
                                              , "/not debris/singlets/CD3+/DNT"
                                              , "/not debris/singlets/CD3+/DPT")
                                      )
      
    })

test_that(".getPopStat",{
      
      expect_error(flowWorkspace:::.getPopStat(gh, 3), "string", class = "Rcpp::not_compatible")
      
      expect_error(flowWorkspace:::.getPopStat(gh, "singlet"), "not found", class = "std::domain_error")
      
      expect_equal(flowWorkspace:::.getPopStat(gh, "singlets"), list(openCyto = c(percent = 9.487789e-01, count = 8.702200e+04)
                                            , xml = c(percent = 9.488988e-01, count = 8.703300e+04)
                                            )
                      , tol = 1e-7 )
      
      
      
      expect_equal(flowWorkspace:::.getPopStat(gh, "root"), list(openCyto = c(percent = 1, count = 119531)
                                            , xml = c(percent = 1, count = 119531)
                                        )
                                )
    })      


test_that("gh_pop_get_proportion",{
      
      expect_equal(gh_pop_get_proportion(gh, "singlets"), 0.9487789)
      
      expect_equal(gh_pop_get_proportion(gh, "singlets", xml = FALSE), 0.9487789)
      
      expect_equal(gh_pop_get_proportion(gh, "singlets", xml = TRUE), 0.9488988, tol = 1e-7)
      
      expect_error(gh_pop_get_proportion(gh, "singlet"), "singlet not found", class = "std::domain_error")
    })      

test_that("gh_pop_get_count",{
      
      expect_equal(gh_pop_get_stats(gh, "singlets")[[2]], 87022)
      
      expect_equal(gh_pop_get_stats(gh, "singlets", xml = FALSE)[[2]], 87022)
      
      expect_equal(gh_pop_get_stats(gh, "singlets", xml = TRUE)[[2]], 87033)
      
      expect_error(gh_pop_get_stats(gh, "singlet"), "singlet not found", class = "std::domain_error")
    })      


test_that("gh_pop_compare_stats",{
      
      
      thisRes <- gh_pop_compare_stats(gh, path = "full")
      expect_is(thisRes, "data.table")
     
      expectRes <- fread(file.path(resultDir, "getPopStats_gh.csv"))
      expectRes[, node := V1]
      expectRes[, V1 := NULL]
      expect_equal(rownames(thisRes),expectRes[["node"]])#check rownames 
      expect_equal(thisRes[, xml.freq], thisRes[, openCyto.freq], tol = 3e-3) 
    })

test_that("compute CV from gh",{
      
      thisRes <- flowWorkspace:::.computeCV_gh(gh)
      expect_is(thisRes, "matrix")
      
      expectRes <- readRDS(file.path(resultDir, "cv_gh.rds"))
      rownames(thisRes) <- basename(rownames(thisRes))
      expect_equal(thisRes, expectRes, tol = 3e-3)
      
    })

test_that("gh_pop_get_gate",{
      
      thisRes <- gh_pop_get_gate(gh, "singlets")
      expect_is(thisRes, "polygonGate")
      
      #add a rectangleGate to test 
      rg <- rectangleGate(filterId="myRectGate", list("FSC-A"=c(200, 600),"SSC-A"=c(0, 400)))      
      id <- pop_add(rg, gh)
      thisRes <- gh_pop_get_gate(gh, "myRectGate")
      expect_is(thisRes, "rectangleGate")
      expect_equal(thisRes@min, rg@min)
      expect_equal(thisRes@max, rg@max)
      expect_equivalent(parameters(thisRes), parameters(rg))
      invisible(gh_pop_remove(gh, "myRectGate"))
      
      #add a bool gate to test
      bf <- booleanFilter(`CD4/38- DR+|CD4/CCR7- 45RA+`, filterId = "myBoolFilter")
      suppressWarnings(id <- pop_add(bf, gh))
      thisRes <- gh_pop_get_gate(gh, "myBoolFilter")
      expect_is(thisRes, "booleanFilter")
      
      expect_equal(as.character(thisRes@expr), as.character(bf@expr))
      invisible(gh_pop_remove(gh, "myBoolFilter"))
     
      ##TODO: test rangeGate (no R API to add it, have to parse it from xml )
      
    })

test_that(".mergeGates",{
      nodes <- gs_get_pop_paths(gh, path = "auto")
      #with customized x,y (incorrect prj)
      projections <- list("singlets" = c("FSC-H", "FSC-A")
                        , "CD3+" = c("CD3", "FSC-A")
                        , "CD4" = c("CD4", "CD3")
                        , "CD4/38- DR-" = c("SSC-A", "<V545-A>")
                    )
                          
      expect_error(flowWorkspace:::.mergeGates(gh, i = nodes[6:9], bool = FALSE, merge = TRUE, projections = projections)
                  , "Given projection")

      #swapped x,y (we don't really allow to change the dimensions for 2D gate yet, only the order can be changed)
      projections[["CD4/38- DR-"]] <- c("<R660-A>", "<V545-A>")                     
      thisRes <- flowWorkspace:::.mergeGates(gh, i = nodes[6:9], bool = FALSE, merge = TRUE, projections = projections)
      expectRes <- list(`CD4/38- DR+` = list(popIds = nodes[6:9]
                                  , parentId = nodes[5])
                          )      
      expect_equal(thisRes, expectRes)
      
      
      #merge 4 quadrants
      thisRes <- flowWorkspace:::.mergeGates(gh, i = nodes[6:9], bool = FALSE, merge = TRUE)
      
      expect_equal(thisRes, expectRes)
      
            
      # 4 quadrants + 1 pop
      thisRes <- flowWorkspace:::.mergeGates(gh, i = nodes[5:9], bool = FALSE, merge = TRUE)
      expectRes <- c(`CD4` = "CD4", expectRes) 
      expect_equal(thisRes, expectRes)
      
      thisRes <- flowWorkspace:::.mergeGates(gh, i = nodes[6:12], bool = FALSE, merge = TRUE)
      expectRes <- list(`CD4/38- DR+` = list(popIds = nodes[6:9]
                                  , parentId = "CD4")
                        ,`CD4/CCR7- 45RA+` = list(popIds = nodes[10:12]
                              , parentId = "CD4")
                          )
      
      expect_equal(thisRes, expectRes)
      
      #4 quadrants without merge
      thisRes <- flowWorkspace:::.mergeGates(gh, i = nodes[6:9], bool = FALSE, merge = FALSE)
      expectRes <- list(`CD4/38- DR+` = "CD4/38- DR+"
                        , `CD4/38+ DR+` = "CD4/38+ DR+"
                        , `CD4/38+ DR-` = "CD4/38+ DR-"
                        , `CD4/38- DR-` = "CD4/38- DR-")
      expect_equal(thisRes, expectRes)
      
    })

test_that("pretty10exp",{
      
      thisRes <- flowWorkspace:::pretty10exp(c(1, 10, 100, 1000), drop.1 = TRUE)
      expectRes <- expression(10^0, 10^1, 10^2, 10^3)
      expect_equal(thisRes, expectRes)
      
      thisRes <- flowWorkspace:::pretty10exp(c(1, 10, 100, 1000), drop.1 = FALSE)
      expectRes <- expression(1 %*% 10^0, 1 %*% 10^1, 1 %*% 10^2, 1 %*% 10^3)
      expect_equal(thisRes, expectRes)      
    })


if(!isCpStaticGate)
{
  test_that("gh_pop_get_indices_mat for COMPASS",{
    
    thisRes <- gh_pop_get_indices_mat(gh, "CD8/38- DR+|CD8/CCR7- 45RA+")
    expectRes <- readRDS(file.path(resultDir, "getIndiceMat_gh.rds"))
    expect_equal(thisRes,expectRes)
    
    
  })
  
}

test_that("getPopChnlMapping",{
      
      fr <- gh_pop_get_data(gh, use.exprs = FALSE) 
      this_pd <- pData(parameters(fr))
      
      #'make up ICS markers
      this_pd[8:12, "desc"] <- c("IL2", "IL4", "IL22", "TNFa", "CD154")
      
      #'no mapping provided 
      
      #we don't parse + signs since they could be part of pop names
      nodes <- c("CD4/IL2+","CD4/IL22+")
      expect_error(flowWorkspace:::.getPopChnlMapping(this_pd, nodes), "Marker not found: IL2+")
      
      #remove + from pop names
      nodes <- c("CD4/IL2","CD4/IL22")
      expectRes <- data.frame(name = c("<V450-A>", "<G560-A>")
          , desc = c("IL2", "IL22")
          , stringsAsFactors = F
          , pop = nodes
      )
      expect_equivalent(flowWorkspace:::.getPopChnlMapping(this_pd, nodes), expectRes)
      
      #partial match for IL22
      nodes <- c("CD4/IL2","CD4/22")
      expectRes[["pop"]] <- nodes 
      expect_equivalent(flowWorkspace:::.getPopChnlMapping(this_pd, nodes), expectRes)
      
      #'mapping provided
      
      # but without the proper names
      nodes <- c("CD4/IL2+","CD4/IL22+")
      mapping <- list("IL2", "IL22")
      expect_error(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), "Marker not found: IL2+")
      # add names
      names(mapping) <- nodes
      expectRes[["pop"]] <- nodes
      expect_equivalent(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), expectRes)
      
      
      #incorrect mapping
      mapping <- list("IL2", "IL3")
      names(mapping) <- nodes
      expect_error(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), "Marker not found: IL3")
      
      #ambiguous mapping
      mapping <- list("IL2", "2")
      names(mapping) <- nodes
      expect_error(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), "2  paritally matched to multiple markers but failed to exactly matched to any of them")
      
      
      #correct mappping with extra items (ignored during the matching)
      mapping <- list("IL2", "IL22")
      names(mapping) <- nodes
      mapping[["extra"]] <- "marker1"
      expect_equivalent(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), expectRes)                     
      
      #correct partial mapping
      mapping <- list("IL2", "154")
      names(mapping) <- nodes                          
      expectRes[2,"name"] <- "Time"
      expectRes[2,"desc"] <- "CD154"
      expect_equivalent(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), expectRes)
      
      #case sensitive at the moment
      mapping <- list("IL2", "cd154")
      names(mapping) <- nodes                          
      expect_error(flowWorkspace:::.getPopChnlMapping(this_pd, nodes, mapping), "Marker not found: cd154")
      
      
    })


test_that("keyword setters", {
  gs_copy <- gs_clone(gs)
  gh1 <- gs_copy[[1]]
  #add new
  gh_keyword_insert(gh1, "k1", 2)
  expect_error(gh_keyword_insert(gh1, "k1", 2), "exist")
  #rename
  gh_keyword_rename(gh1, "k1", "k2")
  expect_error(gh_keyword_rename(gh1, "k1", "k2"), "not found")
  expect_equal(keyword(gh1)[["k2"]], "2")
  #set (subset)
  gh_keyword_set(gh1, "k2", 5)
  expect_equal(keyword(gh1)[["k2"]], "5")
  #delete
  gh_keyword_delete(gh1, "k2")
  expect_error(gh_keyword_delete(gh1, "k2"), "not found")
  
  # Testing vectorized operations
  gs_copy <- gs_clone(gs)
  gh1 <- gs_copy[[1]]
  #add new
  gh_keyword_insert(gh1, c("k1", "k2", "k3"), c("red", 5, 1.23))
  # If any is already present, the call should fail
  expect_error(gh_keyword_insert(gh1, c("k1", "k2"), c("blue", 6)), "exist")
  #rename
  gh_keyword_rename(gh1, c("k1", "k2"), c("key1", "key2"))
  expect_error(gh_keyword_rename(gh1, c("k1", "k2"), c("key1", "key2")), "not found")
  expected <- list(key1="red", key2="5")
  expect_equal(keyword(gh1)[c("key1", "key2")], expected)
  #set (subset) -- overwrite two and add one
  gh_keyword_set(gh1, c("key1", "key2", "key4"), c("green", 7, "newval"))
  expected <- list(key1="green", key2="7", k3="1.23", key4="newval")
  expect_equal(keyword(gh1)[c("key1", "key2", "k3", "key4")], expected)
  #delete
  gh_keyword_delete(gh1, c("key2", "key4"))
  # If any are not longer present, the call should fail
  expect_error(gh_keyword_delete(gh1, c("key2", "k3")), "not found")
  
  # Testing vectorized operations with named vectors
  gs_copy <- gs_clone(gs)
  gh1 <- gs_copy[[1]]
  #add new
  gh_keyword_insert(gh1, c(k1="red", k2=5, k3=1.23))
  # If any is already present, the call should fail
  expect_error(gh_keyword_insert(gh1, c(k1="blue", k2=6)), "exist")
  #rename
  gh_keyword_rename(gh1, c(k1="key1", k2="key2"))
  expect_error(gh_keyword_rename(gh1, c(k1="key1", k2="key2")), "not found")
  expected <- list(key1="red", key2="5")
  expect_equal(keyword(gh1)[c("key1", "key2")], expected)
  #set (subset) -- overwrite two and add one
  gh_keyword_set(gh1, c("key1", "key2", "key4"), c("green", 7, "newval"))
  expected <- list(key1="green", key2="7", k3="1.23", key4="newval")
  expect_equal(keyword(gh1)[c("key1", "key2", "k3", "key4")], expected)
  #delete
  gh_keyword_delete(gh1, c("key2", "key4"))
  # If any are not longer present, the call should fail
  expect_error(gh_keyword_delete(gh1, c("key2", "k3")), "not found")
})

Try the flowWorkspace package in your browser

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

flowWorkspace documentation built on Nov. 8, 2020, 8:08 p.m.