summaryrefslogtreecommitdiff
path: root/cli/lsp/testing/collectors.rs
diff options
context:
space:
mode:
authorNayeem Rahman <nayeemrmn99@gmail.com>2023-08-30 16:31:31 +0100
committerGitHub <noreply@github.com>2023-08-30 16:31:31 +0100
commitd28384c3deec1497d28f0f6bd16cf51de832e572 (patch)
treeb65eb37b3c066f95d69c5ae36798426d617a9119 /cli/lsp/testing/collectors.rs
parent329698cf73e98bd3347f5b03f5ecb562a6ce9925 (diff)
refactor(lsp): store test definitions in adjacency list (#20330)
Previously: ```rust pub struct TestDefinition { pub id: String, pub name: String, pub range: SourceRange, pub steps: Vec<TestDefinition>, } pub struct TestDefinitions { pub discovered: Vec<TestDefinition>, pub injected: Vec<lsp_custom::TestData>, pub script_version: String, } ``` Now: ```rust pub struct TestDefinition { pub id: String, pub name: String, pub range: Option<Range>, pub is_dynamic: bool, // True for 'injected' module, not statically detected but added at runtime. pub parent_id: Option<String>, pub step_ids: HashSet<String>, } pub struct TestModule { pub specifier: ModuleSpecifier, pub script_version: String, pub defs: HashMap<String, TestDefinition>, } ``` Storing the test tree as a literal tree diminishes the value of IDs, even though vscode stores them that way. This makes all data easily accessible from `TestModule`. It unifies the interface between 'discovered' and 'injected' tests. This unblocks some enhancements wrt syncing tests between the LSP and extension, such as this TODO: https://github.com/denoland/vscode_deno/blob/61f08d5a71536a0a5f7dce965955b09e6bd957e1/client/src/testing.ts#L251-L259 and https://github.com/denoland/vscode_deno/issues/900. We should also get more flexibility overall. `TestCollector` is cleaned up, now stores a `&mut TestModule` directly and registers tests as it comes across them with `TestModule::register()`. This method ensures sanity in the redundant data from having both of `TestDefinition::{parent_id,step_ids}`. All of the messy conversions between `TestDescription`, `LspTestDescription`, `TestDefinition`, `TestData` and `TestIdentifier` are cleaned up. They shouldn't have been using `impl From` and now the full list of tests is available to their implementations.
Diffstat (limited to 'cli/lsp/testing/collectors.rs')
-rw-r--r--cli/lsp/testing/collectors.rs883
1 files changed, 559 insertions, 324 deletions
diff --git a/cli/lsp/testing/collectors.rs b/cli/lsp/testing/collectors.rs
index 6976cffb9..f5f1ea0d1 100644
--- a/cli/lsp/testing/collectors.rs
+++ b/cli/lsp/testing/collectors.rs
@@ -1,51 +1,59 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use super::definitions::TestDefinition;
+use crate::lsp::analysis::source_range_to_lsp_range;
+
+use super::definitions::TestModule;
use deno_ast::swc::ast;
use deno_ast::swc::visit::Visit;
use deno_ast::swc::visit::VisitWith;
-use deno_ast::SourceRange;
use deno_ast::SourceRangedForSpanned;
use deno_ast::SourceTextInfo;
use deno_core::ModuleSpecifier;
+use lsp::Range;
use std::collections::HashMap;
use std::collections::HashSet;
+use tower_lsp::lsp_types as lsp;
/// Parse an arrow expression for any test steps and return them.
-fn arrow_to_steps(
- parent: &str,
+fn visit_arrow(
arrow_expr: &ast::ArrowExpr,
-) -> Vec<TestDefinition> {
+ parent_id: &str,
+ text_info: &SourceTextInfo,
+ test_module: &mut TestModule,
+) {
if let Some((maybe_test_context, maybe_step_var)) =
parse_test_context_param(arrow_expr.params.get(0))
{
let mut collector = TestStepCollector::new(
- parent.to_string(),
maybe_test_context,
maybe_step_var,
+ parent_id,
+ text_info,
+ test_module,
);
arrow_expr.body.visit_with(&mut collector);
- collector.take()
- } else {
- vec![]
}
}
/// Parse a function for any test steps and return them.
-fn fn_to_steps(parent: &str, function: &ast::Function) -> Vec<TestDefinition> {
+fn visit_fn(
+ function: &ast::Function,
+ parent_id: &str,
+ text_info: &SourceTextInfo,
+ test_module: &mut TestModule,
+) {
if let Some((maybe_test_context, maybe_step_var)) =
parse_test_context_param(function.params.get(0).map(|p| &p.pat))
{
let mut collector = TestStepCollector::new(
- parent.to_string(),
maybe_test_context,
maybe_step_var,
+ parent_id,
+ text_info,
+ test_module,
);
function.body.visit_with(&mut collector);
- collector.take()
- } else {
- vec![]
}
}
@@ -120,188 +128,223 @@ fn parse_test_context_param(
/// Check a call expression of a test or test step to determine the name of the
/// test or test step as well as any sub steps.
-fn check_call_expr(
- parent: &str,
+fn visit_call_expr(
node: &ast::CallExpr,
fns: Option<&HashMap<String, ast::Function>>,
- text_info: Option<&SourceTextInfo>,
-) -> Option<(String, Vec<TestDefinition>)> {
+ range: Range,
+ parent_id: Option<&str>,
+ text_info: &SourceTextInfo,
+ test_module: &mut TestModule,
+) {
if let Some(expr) = node.args.get(0).map(|es| es.expr.as_ref()) {
match expr {
ast::Expr::Object(obj_lit) => {
let mut maybe_name = None;
- let mut steps = vec![];
for prop in &obj_lit.props {
- if let ast::PropOrSpread::Prop(prop) = prop {
- match prop.as_ref() {
- ast::Prop::KeyValue(key_value_prop) => {
- if let ast::PropName::Ident(ast::Ident { sym, .. }) =
- &key_value_prop.key
- {
- match sym.to_string().as_str() {
- "name" => match key_value_prop.value.as_ref() {
- // matches string literals (e.g. "test name" or
- // 'test name')
- ast::Expr::Lit(ast::Lit::Str(lit_str)) => {
- maybe_name = Some(lit_str.value.to_string());
- }
- // matches template literals with only a single quasis
- // (e.g. `test name`)
- ast::Expr::Tpl(tpl) => {
- if tpl.quasis.len() == 1 {
- maybe_name = Some(tpl.quasis[0].raw.to_string());
- }
- }
- _ => (),
- },
- "fn" => match key_value_prop.value.as_ref() {
- ast::Expr::Arrow(arrow_expr) => {
- steps = arrow_to_steps(parent, arrow_expr);
- }
- ast::Expr::Fn(fn_expr) => {
- steps = fn_to_steps(parent, &fn_expr.function);
- }
- _ => (),
- },
- _ => (),
+ let ast::PropOrSpread::Prop(prop) = prop else {
+ continue;
+ };
+ let ast::Prop::KeyValue(key_value_prop) = prop.as_ref() else {
+ continue;
+ };
+ let ast::PropName::Ident(ast::Ident { sym, .. }) =
+ &key_value_prop.key
+ else {
+ continue;
+ };
+ if sym == "name" {
+ match key_value_prop.value.as_ref() {
+ // matches string literals (e.g. "test name" or
+ // 'test name')
+ ast::Expr::Lit(ast::Lit::Str(lit_str)) => {
+ maybe_name = Some(lit_str.value.to_string());
+ }
+ // matches template literals with only a single quasis
+ // (e.g. `test name`)
+ ast::Expr::Tpl(tpl) => {
+ if tpl.quasis.len() == 1 {
+ maybe_name = Some(tpl.quasis[0].raw.to_string());
+ }
+ }
+ _ => {}
+ }
+ break;
+ }
+ }
+ let name = match maybe_name {
+ Some(n) => n,
+ None => return,
+ };
+ let (id, _) = test_module.register(
+ name,
+ Some(range),
+ false,
+ parent_id.map(str::to_owned),
+ );
+ for prop in &obj_lit.props {
+ let ast::PropOrSpread::Prop(prop) = prop else {
+ continue;
+ };
+ match prop.as_ref() {
+ ast::Prop::KeyValue(key_value_prop) => {
+ let ast::PropName::Ident(ast::Ident { sym, .. }) =
+ &key_value_prop.key
+ else {
+ continue;
+ };
+ if sym == "fn" {
+ match key_value_prop.value.as_ref() {
+ ast::Expr::Arrow(arrow_expr) => {
+ visit_arrow(arrow_expr, &id, text_info, test_module);
}
+ ast::Expr::Fn(fn_expr) => {
+ visit_fn(&fn_expr.function, &id, text_info, test_module);
+ }
+ _ => {}
}
+ break;
}
- ast::Prop::Method(method_prop) => {
- steps = fn_to_steps(parent, &method_prop.function);
+ }
+ ast::Prop::Method(method_prop) => {
+ let ast::PropName::Ident(ast::Ident { sym, .. }) =
+ &method_prop.key
+ else {
+ continue;
+ };
+ if sym == "fn" {
+ visit_fn(&method_prop.function, &id, text_info, test_module);
+ break;
}
- _ => (),
}
+ _ => {}
}
}
- maybe_name.map(|name| (name, steps))
}
ast::Expr::Fn(fn_expr) => {
if let Some(ast::Ident { sym, .. }) = fn_expr.ident.as_ref() {
let name = sym.to_string();
- let steps = fn_to_steps(parent, &fn_expr.function);
- Some((name, steps))
- } else {
- None
+ let (id, _) = test_module.register(
+ name,
+ Some(range),
+ false,
+ parent_id.map(str::to_owned),
+ );
+ visit_fn(&fn_expr.function, &id, text_info, test_module);
}
}
ast::Expr::Lit(ast::Lit::Str(lit_str)) => {
let name = lit_str.value.to_string();
- let mut steps = vec![];
+ let (id, _) = test_module.register(
+ name,
+ Some(range),
+ false,
+ parent_id.map(str::to_owned),
+ );
match node.args.get(1).map(|es| es.expr.as_ref()) {
Some(ast::Expr::Fn(fn_expr)) => {
- steps = fn_to_steps(parent, &fn_expr.function);
+ visit_fn(&fn_expr.function, &id, text_info, test_module);
}
Some(ast::Expr::Arrow(arrow_expr)) => {
- steps = arrow_to_steps(parent, arrow_expr);
+ visit_arrow(arrow_expr, &id, text_info, test_module);
}
- _ => (),
+ _ => {}
}
- Some((name, steps))
}
ast::Expr::Tpl(tpl) => {
if tpl.quasis.len() == 1 {
- let mut steps = vec![];
+ let name = tpl.quasis[0].raw.to_string();
+ let (id, _) = test_module.register(
+ name,
+ Some(range),
+ false,
+ parent_id.map(str::to_owned),
+ );
match node.args.get(1).map(|es| es.expr.as_ref()) {
Some(ast::Expr::Fn(fn_expr)) => {
- steps = fn_to_steps(parent, &fn_expr.function);
+ visit_fn(&fn_expr.function, &id, text_info, test_module);
}
Some(ast::Expr::Arrow(arrow_expr)) => {
- steps = arrow_to_steps(parent, arrow_expr);
+ visit_arrow(arrow_expr, &id, text_info, test_module);
}
- _ => (),
+ _ => {}
}
-
- Some((tpl.quasis[0].raw.to_string(), steps))
- } else {
- None
}
}
ast::Expr::Ident(ident) => {
let name = ident.sym.to_string();
- fns.and_then(|fns| {
- fns
- .get(&name)
- .map(|fn_expr| (name, fn_to_steps(parent, fn_expr)))
- })
+ if let Some(fn_expr) = fns.and_then(|fns| fns.get(&name)) {
+ let (parent_id, _) = test_module.register(
+ name,
+ Some(range),
+ false,
+ parent_id.map(str::to_owned),
+ );
+ visit_fn(fn_expr, &parent_id, text_info, test_module);
+ }
}
_ => {
- if let Some(text_info) = text_info {
- let range = node.range();
- let indexes = text_info.line_and_column_display(range.start);
- Some((
+ if parent_id.is_none() {
+ let node_range = node.range();
+ let indexes = text_info.line_and_column_display(node_range.start);
+ test_module.register(
format!("Test {}:{}", indexes.line_number, indexes.column_number),
- vec![],
- ))
- } else {
- None
+ Some(range),
+ false,
+ None,
+ );
}
}
}
- } else {
- None
}
}
/// A structure which can be used to walk a branch of AST determining if the
/// branch contains any testing steps.
-struct TestStepCollector {
- steps: Vec<TestDefinition>,
- parent: String,
+struct TestStepCollector<'a> {
maybe_test_context: Option<String>,
vars: HashSet<String>,
+ parent_id: &'a str,
+ text_info: &'a SourceTextInfo,
+ test_module: &'a mut TestModule,
}
-impl TestStepCollector {
+impl<'a> TestStepCollector<'a> {
fn new(
- parent: String,
maybe_test_context: Option<String>,
maybe_step_var: Option<String>,
+ parent_id: &'a str,
+ text_info: &'a SourceTextInfo,
+ test_module: &'a mut TestModule,
) -> Self {
let mut vars = HashSet::new();
if let Some(var) = maybe_step_var {
vars.insert(var);
}
Self {
- steps: Vec::default(),
- parent,
maybe_test_context,
vars,
+ parent_id,
+ text_info,
+ test_module,
}
}
-
- fn add_step<N: AsRef<str>>(
- &mut self,
- name: N,
- range: SourceRange,
- steps: Vec<TestDefinition>,
- ) {
- let step =
- TestDefinition::new_step(name.as_ref().to_string(), range, steps);
- self.steps.push(step);
- }
-
- fn check_call_expr(&mut self, node: &ast::CallExpr, range: SourceRange) {
- if let Some((name, steps)) = check_call_expr(&self.parent, node, None, None)
- {
- self.add_step(name, range, steps);
- }
- }
-
- /// Move out the test definitions
- pub fn take(self) -> Vec<TestDefinition> {
- self.steps
- }
}
-impl Visit for TestStepCollector {
+impl Visit for TestStepCollector<'_> {
fn visit_call_expr(&mut self, node: &ast::CallExpr) {
if let ast::Callee::Expr(callee_expr) = &node.callee {
match callee_expr.as_ref() {
// Identify calls to identified variables
ast::Expr::Ident(ident) => {
if self.vars.contains(&ident.sym.to_string()) {
- self.check_call_expr(node, ident.range());
+ visit_call_expr(
+ node,
+ None,
+ source_range_to_lsp_range(&ident.range(), self.text_info),
+ Some(self.parent_id),
+ self.text_info,
+ self.test_module,
+ );
}
}
// Identify calls to `test.step()`
@@ -311,7 +354,17 @@ impl Visit for TestStepCollector {
if ns_prop_ident.sym.eq("step") {
if let ast::Expr::Ident(ident) = member_expr.obj.as_ref() {
if ident.sym == *test_context {
- self.check_call_expr(node, ns_prop_ident.range());
+ visit_call_expr(
+ node,
+ None,
+ source_range_to_lsp_range(
+ &ns_prop_ident.range(),
+ self.text_info,
+ ),
+ Some(self.parent_id),
+ self.text_info,
+ self.test_module,
+ );
}
}
}
@@ -382,53 +435,29 @@ impl Visit for TestStepCollector {
/// Walk an AST and determine if it contains any `Deno.test` tests.
pub struct TestCollector {
- definitions: Vec<TestDefinition>,
- specifier: ModuleSpecifier,
+ test_module: TestModule,
vars: HashSet<String>,
fns: HashMap<String, ast::Function>,
text_info: SourceTextInfo,
}
impl TestCollector {
- pub fn new(specifier: ModuleSpecifier, text_info: SourceTextInfo) -> Self {
+ pub fn new(
+ specifier: ModuleSpecifier,
+ script_version: String,
+ text_info: SourceTextInfo,
+ ) -> Self {
Self {
- definitions: Vec::new(),
- specifier,
+ test_module: TestModule::new(specifier, script_version),
vars: HashSet::new(),
fns: HashMap::new(),
text_info,
}
}
- fn add_definition<N: AsRef<str>>(
- &mut self,
- name: N,
- range: SourceRange,
- steps: Vec<TestDefinition>,
- ) {
- let definition = TestDefinition::new(
- &self.specifier,
- name.as_ref().to_string(),
- range,
- steps,
- );
- self.definitions.push(definition);
- }
-
- fn check_call_expr(&mut self, node: &ast::CallExpr, range: SourceRange) {
- if let Some((name, steps)) = check_call_expr(
- self.specifier.as_str(),
- node,
- Some(&self.fns),
- Some(&self.text_info),
- ) {
- self.add_definition(name, range, steps);
- }
- }
-
/// Move out the test definitions
- pub fn take(self) -> Vec<TestDefinition> {
- self.definitions
+ pub fn take(self) -> TestModule {
+ self.test_module
}
}
@@ -438,7 +467,14 @@ impl Visit for TestCollector {
match callee_expr.as_ref() {
ast::Expr::Ident(ident) => {
if self.vars.contains(&ident.sym.to_string()) {
- self.check_call_expr(node, ident.range());
+ visit_call_expr(
+ node,
+ Some(&self.fns),
+ source_range_to_lsp_range(&ident.range(), &self.text_info),
+ None,
+ &self.text_info,
+ &mut self.test_module,
+ );
}
}
ast::Expr::Member(member_expr) => {
@@ -446,7 +482,17 @@ impl Visit for TestCollector {
if ns_prop_ident.sym.to_string() == "test" {
if let ast::Expr::Ident(ident) = member_expr.obj.as_ref() {
if ident.sym.to_string() == "Deno" {
- self.check_call_expr(node, ns_prop_ident.range());
+ visit_call_expr(
+ node,
+ Some(&self.fns),
+ source_range_to_lsp_range(
+ &ns_prop_ident.range(),
+ &self.text_info,
+ ),
+ None,
+ &self.text_info,
+ &mut self.test_module,
+ );
}
}
}
@@ -519,18 +565,17 @@ impl Visit for TestCollector {
#[cfg(test)]
pub mod tests {
+ use crate::lsp::testing::definitions::TestDefinition;
+
use super::*;
- use deno_ast::StartSourcePos;
use deno_core::resolve_url;
+ use lsp::Position;
- pub fn new_range(start: usize, end: usize) -> SourceRange {
- SourceRange::new(
- StartSourcePos::START_SOURCE_POS + start,
- StartSourcePos::START_SOURCE_POS + end,
- )
+ pub fn new_range(l1: u32, c1: u32, l2: u32, c2: u32) -> Range {
+ Range::new(Position::new(l1, c1), Position::new(l2, c2))
}
- fn collect(source: &str) -> Vec<TestDefinition> {
+ fn collect(source: &str) -> TestModule {
let specifier = resolve_url("file:///a/example.ts").unwrap();
let parsed_module = deno_ast::parse_module(deno_ast::ParseParams {
@@ -543,54 +588,81 @@ pub mod tests {
})
.unwrap();
let text_info = parsed_module.text_info().clone();
- let mut collector = TestCollector::new(specifier, text_info);
+ let mut collector =
+ TestCollector::new(specifier, "1".to_string(), text_info);
parsed_module.module().visit_with(&mut collector);
collector.take()
}
#[test]
fn test_test_collector_test() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test("test", () => {});
"#,
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(12, 16),
- steps: vec![],
- },]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ TestDefinition {
+ id:
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_test_tpl() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test(`test`, () => {});
"#,
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(12, 16),
- steps: vec![],
- },]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ TestDefinition {
+ id:
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_a() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test({
name: "test",
@@ -607,34 +679,52 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(12, 16),
- steps: vec![TestDefinition {
- id:
- "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c"
- .to_string(),
- name: "step".to_string(),
- range: new_range(81, 85),
- steps: vec![TestDefinition {
- id:
- "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d"
- .to_string(),
- name: "sub step".to_string(),
- range: new_range(128, 132),
- steps: vec![],
- }]
- }],
- },]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![
+ (
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string(),
+ TestDefinition {
+ id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: vec!["704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string()].into_iter().collect(),
+ }
+ ),
+ (
+ "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string(),
+ TestDefinition {
+ id: "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string(),
+ name: "step".to_string(),
+ range: Some(new_range(4, 18, 4, 22)),
+ is_dynamic: false,
+ parent_id: Some("4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string()),
+ step_ids: vec!["0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string()].into_iter().collect(),
+ }
+ ),
+ (
+ "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string(),
+ TestDefinition {
+ id: "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string(),
+ name: "sub step".to_string(),
+ range: Some(new_range(5, 18, 5, 22)),
+ is_dynamic: false,
+ parent_id: Some("704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string()),
+ step_ids: Default::default(),
+ }
+ ),
+ ].into_iter().collect(),
+ }
);
}
#[test]
fn test_test_collector_a_tpl() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test({
name: `test`,
@@ -651,34 +741,52 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(12, 16),
- steps: vec![TestDefinition {
- id:
- "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c"
- .to_string(),
- name: "step".to_string(),
- range: new_range(81, 85),
- steps: vec![TestDefinition {
- id:
- "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d"
- .to_string(),
- name: "sub step".to_string(),
- range: new_range(128, 132),
- steps: vec![],
- }]
- }],
- },]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![
+ (
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string(),
+ TestDefinition {
+ id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: vec!["704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string()].into_iter().collect(),
+ }
+ ),
+ (
+ "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string(),
+ TestDefinition {
+ id: "704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string(),
+ name: "step".to_string(),
+ range: Some(new_range(4, 18, 4, 22)),
+ is_dynamic: false,
+ parent_id: Some("4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9".to_string()),
+ step_ids: vec!["0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string()].into_iter().collect(),
+ }
+ ),
+ (
+ "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string(),
+ TestDefinition {
+ id: "0d006a4ec0abaa9cc1d18256b1ccd2677a4c882ff5cb807123890f7528ab1e8d".to_string(),
+ name: "sub step".to_string(),
+ range: Some(new_range(5, 18, 5, 22)),
+ is_dynamic: false,
+ parent_id: Some("704d24083fd4a3e1bd204faa20827dc594334812245e5d45dda222b3edc60a0c".to_string()),
+ step_ids: Default::default(),
+ }
+ ),
+ ].into_iter().collect(),
+ }
);
}
#[test]
fn test_test_collector_destructure() {
- let res = collect(
+ let test_module = collect(
r#"
const { test } = Deno;
test("test", () => {});
@@ -686,20 +794,33 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(36, 40),
- steps: vec![],
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ TestDefinition {
+ id:
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(2, 6, 2, 10)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_destructure_rebind_step() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test(async function useFnName({ step: s }) {
await s("step", () => {});
@@ -708,27 +829,41 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "86b4c821900e38fc89f24bceb0e45193608ab3f9d2a6019c7b6a5aceff5d7df2"
- .to_string(),
- name: "useFnName".to_string(),
- range: new_range(12, 16),
- steps: vec![TestDefinition {
- id:
- "dac8a169b8f8c6babf11122557ea545de2733bfafed594d044b22bc6863a0856"
- .to_string(),
- name: "step".to_string(),
- range: new_range(71, 72),
- steps: vec![],
- }],
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![
+ (
+ "86b4c821900e38fc89f24bceb0e45193608ab3f9d2a6019c7b6a5aceff5d7df2".to_string(),
+ TestDefinition {
+ id: "86b4c821900e38fc89f24bceb0e45193608ab3f9d2a6019c7b6a5aceff5d7df2".to_string(),
+ name: "useFnName".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: vec!["dac8a169b8f8c6babf11122557ea545de2733bfafed594d044b22bc6863a0856".to_string()].into_iter().collect(),
+ }
+ ),
+ (
+ "dac8a169b8f8c6babf11122557ea545de2733bfafed594d044b22bc6863a0856".to_string(),
+ TestDefinition {
+ id: "dac8a169b8f8c6babf11122557ea545de2733bfafed594d044b22bc6863a0856".to_string(),
+ name: "step".to_string(),
+ range: Some(new_range(2, 14, 2, 15)),
+ is_dynamic: false,
+ parent_id: Some("86b4c821900e38fc89f24bceb0e45193608ab3f9d2a6019c7b6a5aceff5d7df2".to_string()),
+ step_ids: Default::default(),
+ }
+ ),
+ ].into_iter().collect(),
+ }
);
}
#[test]
fn test_test_collector_rebind() {
- let res = collect(
+ let test_module = collect(
r#"
const t = Deno.test;
t("test", () => {});
@@ -736,20 +871,33 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(34, 35),
- steps: vec![],
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ TestDefinition {
+ id:
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(2, 6, 2, 7)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_separate_test_function_with_string_name() {
- let res = collect(
+ let test_module = collect(
r#"
function someFunction() {}
Deno.test("test", someFunction);
@@ -757,40 +905,66 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
- .to_string(),
- name: "test".to_string(),
- range: new_range(45, 49),
- steps: vec![],
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ TestDefinition {
+ id:
+ "4ebb361c93f76a0f1bac300638675609f1cf481e6f3b9006c3c98604b3a184e9"
+ .to_string(),
+ name: "test".to_string(),
+ range: Some(new_range(2, 11, 2, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_function_only() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test(async function someFunction() {});
"#,
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
- .to_string(),
- name: "someFunction".to_string(),
- range: new_range(12, 16),
- steps: vec![]
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
+ .to_string(),
+ TestDefinition {
+ id:
+ "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
+ .to_string(),
+ name: "someFunction".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_separate_test_function() {
- let res = collect(
+ let test_module = collect(
r#"
async function someFunction() {}
Deno.test(someFunction);
@@ -798,20 +972,33 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
- .to_string(),
- name: "someFunction".to_string(),
- range: new_range(51, 55),
- steps: vec![]
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
+ .to_string(),
+ TestDefinition {
+ id:
+ "e0f6a73647b763f82176c98a019e54200b799a32007f9859fb782aaa9e308568"
+ .to_string(),
+ name: "someFunction".to_string(),
+ range: Some(new_range(2, 11, 2, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
#[test]
fn test_test_collector_unknown_test() {
- let res = collect(
+ let test_module = collect(
r#"
const someFunction = () => ({ name: "test", fn: () => {} });
Deno.test(someFunction());
@@ -819,21 +1006,34 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "6d05d6dc35548b86a1e70acaf24a5bc2dd35db686b35b685ad5931d201b4a918"
- .to_string(),
- name: "Test 3:7".to_string(),
- range: new_range(79, 83),
- steps: vec![]
- }]
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![(
+ "6d05d6dc35548b86a1e70acaf24a5bc2dd35db686b35b685ad5931d201b4a918"
+ .to_string(),
+ TestDefinition {
+ id:
+ "6d05d6dc35548b86a1e70acaf24a5bc2dd35db686b35b685ad5931d201b4a918"
+ .to_string(),
+ name: "Test 3:7".to_string(),
+ range: Some(new_range(2, 11, 2, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: Default::default(),
+ }
+ ),]
+ .into_iter()
+ .collect(),
+ }
);
}
// Regression test for https://github.com/denoland/vscode_deno/issues/656.
#[test]
fn test_test_collector_nested_steps_same_name_and_level() {
- let res = collect(
+ let test_module = collect(
r#"
Deno.test("1", async (t) => {
await t.step("step 1", async (t) => {
@@ -847,36 +1047,71 @@ pub mod tests {
);
assert_eq!(
- res,
- vec![TestDefinition {
- id: "3799fc549a32532145ffc8532b0cd943e025bbc19a02e2cde9be94f87bceb829".to_string(),
- name: "1".to_string(),
- range: new_range(12, 16),
- steps: vec![
- TestDefinition {
- id: "e714fc695c0895327bf7148a934c3303ad515af029a14906be46f80340c6d7e3".to_string(),
- name: "step 1".to_string(),
- range: new_range(53, 57),
- steps: vec![TestDefinition {
+ &test_module,
+ &TestModule {
+ specifier: test_module.specifier.clone(),
+ script_version: test_module.script_version.clone(),
+ defs: vec![
+ (
+ "3799fc549a32532145ffc8532b0cd943e025bbc19a02e2cde9be94f87bceb829".to_string(),
+ TestDefinition {
+ id: "3799fc549a32532145ffc8532b0cd943e025bbc19a02e2cde9be94f87bceb829".to_string(),
+ name: "1".to_string(),
+ range: Some(new_range(1, 11, 1, 15)),
+ is_dynamic: false,
+ parent_id: None,
+ step_ids: vec![
+ "e714fc695c0895327bf7148a934c3303ad515af029a14906be46f80340c6d7e3".to_string(),
+ "ec6b03d3dd3dde78d2d11ed981d3386083aeca701510cc049189d74bd79f8587".to_string(),
+ ].into_iter().collect()
+ }
+ ),
+ (
+ "e714fc695c0895327bf7148a934c3303ad515af029a14906be46f80340c6d7e3".to_string(),
+ TestDefinition {
+ id: "e714fc695c0895327bf7148a934c3303ad515af029a14906be46f80340c6d7e3".to_string(),
+ name: "step 1".to_string(),
+ range: Some(new_range(2, 16, 2, 20)),
+ is_dynamic: false,
+ parent_id: Some("3799fc549a32532145ffc8532b0cd943e025bbc19a02e2cde9be94f87bceb829".to_string()),
+ step_ids: vec!["d874949e18dfc297e15c52ff13f13b4e6ae911ec1818b2c761e3313bc018a3ab".to_string()].into_iter().collect()
+ }
+ ),
+ (
+ "d874949e18dfc297e15c52ff13f13b4e6ae911ec1818b2c761e3313bc018a3ab".to_string(),
+ TestDefinition {
id: "d874949e18dfc297e15c52ff13f13b4e6ae911ec1818b2c761e3313bc018a3ab".to_string(),
name: "nested step".to_string(),
- range: new_range(101, 105),
- steps: vec![],
- }],
- },
- TestDefinition {
- id: "ec6b03d3dd3dde78d2d11ed981d3386083aeca701510cc049189d74bd79f8587".to_string(),
- name: "step 2".to_string(),
- range: new_range(160, 164),
- steps: vec![TestDefinition {
+ range: Some(new_range(3, 18, 3, 22)),
+ is_dynamic: false,
+ parent_id: Some("e714fc695c0895327bf7148a934c3303ad515af029a14906be46f80340c6d7e3".to_string()),
+ step_ids: Default::default(),
+ }
+ ),
+ (
+ "ec6b03d3dd3dde78d2d11ed981d3386083aeca701510cc049189d74bd79f8587".to_string(),
+ TestDefinition {
+ id: "ec6b03d3dd3dde78d2d11ed981d3386083aeca701510cc049189d74bd79f8587".to_string(),
+ name: "step 2".to_string(),
+ range: Some(new_range(5, 16, 5, 20)),
+ is_dynamic: false,
+ parent_id: Some("3799fc549a32532145ffc8532b0cd943e025bbc19a02e2cde9be94f87bceb829".to_string()),
+ step_ids: vec!["96729f1f1608e50160b0bf11946719384b4021fd1d26b14eff7765034b3d2684".to_string()].into_iter().collect()
+ }
+ ),
+ (
+ "96729f1f1608e50160b0bf11946719384b4021fd1d26b14eff7765034b3d2684".to_string(),
+ TestDefinition {
id: "96729f1f1608e50160b0bf11946719384b4021fd1d26b14eff7765034b3d2684".to_string(),
name: "nested step".to_string(),
- range: new_range(208, 212),
- steps: vec![],
- }],
- },
- ]
- }]
+ range: Some(new_range(6, 18, 6, 22)),
+ is_dynamic: false,
+ parent_id: Some("ec6b03d3dd3dde78d2d11ed981d3386083aeca701510cc049189d74bd79f8587".to_string()),
+ step_ids: Default::default(),
+ }
+ ),
+ ].into_iter().collect(),
+ }
);
}
}