summaryrefslogtreecommitdiff
path: root/cli/tools/test_runner.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/test_runner.rs')
-rw-r--r--cli/tools/test_runner.rs256
1 files changed, 172 insertions, 84 deletions
diff --git a/cli/tools/test_runner.rs b/cli/tools/test_runner.rs
index e74fad1f8..a9610015e 100644
--- a/cli/tools/test_runner.rs
+++ b/cli/tools/test_runner.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
use crate::ast;
+use crate::ast::Location;
use crate::colors;
use crate::create_main_worker;
use crate::file_fetcher::File;
@@ -346,6 +347,172 @@ pub async fn run_test_file(
Ok(())
}
+fn extract_files_from_regex_blocks(
+ location: &Location,
+ source: &str,
+ media_type: &MediaType,
+ blocks_regex: &Regex,
+ lines_regex: &Regex,
+) -> Result<Vec<File>, AnyError> {
+ let files = blocks_regex
+ .captures_iter(&source)
+ .filter_map(|block| {
+ let maybe_attributes = block
+ .get(1)
+ .map(|attributes| attributes.as_str().split(' '));
+
+ let file_media_type = if let Some(mut attributes) = maybe_attributes {
+ match attributes.next() {
+ Some("js") => MediaType::JavaScript,
+ Some("jsx") => MediaType::Jsx,
+ Some("ts") => MediaType::TypeScript,
+ Some("tsx") => MediaType::Tsx,
+ Some("") => *media_type,
+ _ => MediaType::Unknown,
+ }
+ } else {
+ *media_type
+ };
+
+ if file_media_type == MediaType::Unknown {
+ return None;
+ }
+
+ let line_offset = source[0..block.get(0).unwrap().start()]
+ .chars()
+ .filter(|c| *c == '\n')
+ .count();
+
+ let line_count = block.get(0).unwrap().as_str().split('\n').count();
+
+ let body = block.get(2).unwrap();
+ let text = body.as_str();
+
+ // TODO(caspervonb) generate an inline source map
+ let mut file_source = String::new();
+ for line in lines_regex.captures_iter(&text) {
+ let text = line.get(1).unwrap();
+ file_source.push_str(&format!("{}\n", text.as_str()));
+ }
+
+ file_source.push_str("export {};");
+
+ let file_specifier = deno_core::resolve_url_or_path(&format!(
+ "{}${}-{}{}",
+ location.filename,
+ location.line + line_offset,
+ location.line + line_offset + line_count,
+ file_media_type.as_ts_extension(),
+ ))
+ .unwrap();
+
+ Some(File {
+ local: file_specifier.to_file_path().unwrap(),
+ maybe_types: None,
+ media_type: file_media_type,
+ source: file_source,
+ specifier: file_specifier,
+ })
+ })
+ .collect();
+
+ Ok(files)
+}
+
+fn extract_files_from_source_comments(
+ specifier: &ModuleSpecifier,
+ source: &str,
+ media_type: &MediaType,
+) -> Result<Vec<File>, AnyError> {
+ let parsed_module = ast::parse(&specifier.as_str(), &source, &media_type)?;
+ let mut comments = parsed_module.get_comments();
+ comments
+ .sort_by_key(|comment| parsed_module.get_location(&comment.span).line);
+
+ let blocks_regex = Regex::new(r"```([^\n]*)\n([\S\s]*?)```")?;
+ let lines_regex = Regex::new(r"(?:\* ?)(?:\# ?)?(.*)")?;
+
+ let files = comments
+ .iter()
+ .filter(|comment| {
+ if comment.kind != CommentKind::Block || !comment.text.starts_with('*') {
+ return false;
+ }
+
+ true
+ })
+ .flat_map(|comment| {
+ let location = parsed_module.get_location(&comment.span);
+
+ extract_files_from_regex_blocks(
+ &location,
+ &comment.text,
+ &media_type,
+ &blocks_regex,
+ &lines_regex,
+ )
+ })
+ .flatten()
+ .collect();
+
+ Ok(files)
+}
+
+fn extract_files_from_fenced_blocks(
+ specifier: &ModuleSpecifier,
+ source: &str,
+ media_type: &MediaType,
+) -> Result<Vec<File>, AnyError> {
+ let location = Location {
+ filename: specifier.to_string(),
+ line: 1,
+ col: 0,
+ };
+
+ let blocks_regex = Regex::new(r"```([^\n]*)\n([\S\s]*?)```")?;
+ let lines_regex = Regex::new(r"(?:\# ?)?(.*)")?;
+
+ extract_files_from_regex_blocks(
+ &location,
+ &source,
+ &media_type,
+ &blocks_regex,
+ &lines_regex,
+ )
+}
+
+async fn fetch_inline_files(
+ program_state: Arc<ProgramState>,
+ specifiers: Vec<ModuleSpecifier>,
+) -> Result<Vec<File>, AnyError> {
+ let mut files = Vec::new();
+ for specifier in specifiers {
+ let mut fetch_permissions = Permissions::allow_all();
+ let file = program_state
+ .file_fetcher
+ .fetch(&specifier, &mut fetch_permissions)
+ .await?;
+
+ let inline_files = if file.media_type == MediaType::Unknown {
+ extract_files_from_fenced_blocks(
+ &file.specifier,
+ &file.source,
+ &file.media_type,
+ )
+ } else {
+ extract_files_from_source_comments(
+ &file.specifier,
+ &file.source,
+ &file.media_type,
+ )
+ };
+
+ files.extend(inline_files?);
+ }
+
+ Ok(files)
+}
+
/// Runs tests.
///
#[allow(clippy::too_many_arguments)]
@@ -378,95 +545,16 @@ pub async fn run_tests(
};
if !doc_modules.is_empty() {
- let mut test_programs = Vec::new();
-
- let blocks_regex = Regex::new(r"```([^\n]*)\n([\S\s]*?)```")?;
- let lines_regex = Regex::new(r"(?:\* ?)(?:\# ?)?(.*)")?;
-
- for specifier in &doc_modules {
- let mut fetch_permissions = Permissions::allow_all();
- let file = program_state
- .file_fetcher
- .fetch(&specifier, &mut fetch_permissions)
- .await?;
+ let files = fetch_inline_files(program_state.clone(), doc_modules).await?;
+ let specifiers = files.iter().map(|file| file.specifier.clone()).collect();
- let parsed_module =
- ast::parse(&file.specifier.as_str(), &file.source, &file.media_type)?;
-
- let mut comments = parsed_module.get_comments();
- comments.sort_by_key(|comment| {
- let location = parsed_module.get_location(&comment.span);
- location.line
- });
-
- for comment in comments {
- if comment.kind != CommentKind::Block || !comment.text.starts_with('*')
- {
- continue;
- }
-
- for block in blocks_regex.captures_iter(&comment.text) {
- let maybe_attributes = block.get(1).map(|m| m.as_str().split(' '));
- let media_type = if let Some(mut attributes) = maybe_attributes {
- match attributes.next() {
- Some("js") => MediaType::JavaScript,
- Some("jsx") => MediaType::Jsx,
- Some("ts") => MediaType::TypeScript,
- Some("tsx") => MediaType::Tsx,
- Some("") => file.media_type,
- _ => MediaType::Unknown,
- }
- } else {
- file.media_type
- };
-
- if media_type == MediaType::Unknown {
- continue;
- }
-
- let body = block.get(2).unwrap();
- let text = body.as_str();
-
- // TODO(caspervonb) generate an inline source map
- let mut source = String::new();
- for line in lines_regex.captures_iter(&text) {
- let text = line.get(1).unwrap();
- source.push_str(&format!("{}\n", text.as_str()));
- }
-
- source.push_str("export {};");
-
- let element = block.get(0).unwrap();
- let span = comment
- .span
- .from_inner_byte_pos(element.start(), element.end());
- let location = parsed_module.get_location(&span);
-
- let specifier = deno_core::resolve_url_or_path(&format!(
- "{}${}-{}{}",
- location.filename,
- location.line,
- location.line + element.as_str().split('\n').count(),
- media_type.as_ts_extension(),
- ))?;
-
- let file = File {
- local: specifier.to_file_path().unwrap(),
- maybe_types: None,
- media_type,
- source: source.clone(),
- specifier: specifier.clone(),
- };
-
- program_state.file_fetcher.insert_cached(file.clone());
- test_programs.push(file.specifier.clone());
- }
- }
+ for file in files {
+ program_state.file_fetcher.insert_cached(file);
}
program_state
.prepare_module_graph(
- test_programs.clone(),
+ specifiers,
lib.clone(),
Permissions::allow_all(),
permissions.clone(),