use indoc::indoc;
use liwe::model::config::{ActionDefinition, Configuration, Link, LinkType};
use crate::fixture::*;
#[test]
fn link_word_at_start_of_line() {
assert_linked(
indoc! {"
# test
word in paragraph
"},
2,
0,
indoc! {"
# test
[word](2) in paragraph
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_word_in_middle_of_line() {
assert_linked(
indoc! {"
# test
this is a word here
"},
2,
10, indoc! {"
# test
this is a [word](2) here
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_word_at_end_of_line() {
assert_linked(
indoc! {"
# test
this is a word
"},
2,
10, indoc! {"
# test
this is a [word](2)
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_word_with_cursor_in_middle() {
assert_linked(
indoc! {"
# test
important
"},
2,
5, indoc! {"
# test
[important](2)
"},
indoc! {"
# important
"},
);
}
#[test]
fn link_word_with_hyphen() {
assert_linked(
indoc! {"
# test
multi-word
"},
2,
3,
indoc! {"
# test
[multi-word](2)
"},
indoc! {"
# multi-word
"},
);
}
#[test]
fn link_word_with_underscore() {
assert_linked(
indoc! {"
# test
some_function
"},
2,
5,
indoc! {"
# test
[some_function](2)
"},
indoc! {"
# some_function
"},
);
}
#[test]
fn link_word_wiki_link() {
assert_linked_wiki(
indoc! {"
# test
word here
"},
2,
0,
indoc! {"
# test
[[2]] here
"},
indoc! {"
# word
"},
);
}
#[test]
fn no_action_on_multiline_selection() {
use lsp_types::{
CodeActionContext, CodeActionKind, CodeActionParams, PartialResultParams, Position, Range,
TextDocumentIdentifier, WorkDoneProgressParams,
};
let params = CodeActionParams {
text_document: TextDocumentIdentifier { uri: uri(1) },
range: Range::new(Position::new(2, 0), Position::new(3, 5)),
context: CodeActionContext {
only: Some(vec![CodeActionKind::from("custom.link".to_string())]),
..Default::default()
},
work_done_progress_params: WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: PartialResultParams {
partial_result_token: None,
},
};
Fixture::with_config(
indoc! {"
# test
first line
second line
"},
link_config(),
)
.no_code_action(params);
}
#[test]
fn no_action_on_empty_space() {
Fixture::with_config(
indoc! {"
# test
word word
"},
link_config(),
)
.no_code_action(uri(1).to_code_action_params_at_position(2, 6, "custom.link"));
}
#[test]
fn link_word_in_list_item() {
assert_linked(
indoc! {"
# test
- item with word
"},
2,
12, indoc! {"
# test
- item with [word](2)
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_word_in_header() {
assert_linked(
indoc! {"
# test
## section word here
"},
2,
11, indoc! {"
# test
## section [word](2) here
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_word_with_collision() {
let mut files = std::collections::HashMap::new();
files.insert(
"1".to_string(),
indoc! {"
# test
word here
"}
.to_string(),
);
files.insert("existing".to_string(), "# existing\n".to_string());
Fixture::with_options_and_client(files, create_link_config("existing", None), "", None).code_action(
uri(1).to_code_action_params(2, "custom.link"),
vec here\n"),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
#[test]
fn link_word_with_slug_template() {
Fixture::with_config(
indoc! {"
# test
Important Word
"},
create_link_config("{{slug}}", None),
)
.code_action(
uri(1).to_code_action_params(2, "custom.link"),
vec Word\n"),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
#[test]
fn link_word_with_title_template() {
Fixture::with_config(
indoc! {"
# test
MyWord
"},
create_link_config("{{title}}", None),
)
.code_action(
uri(1).to_code_action_params(2, "custom.link"),
vec\n"),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
#[test]
fn link_unicode_word() {
assert_linked(
indoc! {"
# test
test here
"},
2,
0,
indoc! {"
# test
[test](2) here
"},
indoc! {"
# test
"},
);
}
#[test]
fn link_word_with_multibyte_chars() {
assert_linked(
indoc! {"
# test
- λÎξη
"},
2,
3,
indoc! {"
# test
- [λÎξη](2)
"},
indoc! {"
# λÎξη
"},
);
}
#[test]
fn link_selected_text_with_multibyte_chars() {
assert_linked_with_range(
indoc! {"
# test
prefix λÎξη suffix
"},
2,
7,
11,
indoc! {"
# test
prefix [λÎξη](2) suffix
"},
indoc! {"
# λÎξη
"},
);
}
#[test]
fn link_selected_text_simple() {
assert_linked_with_range(
indoc! {"
# test
this is some text here
"},
2,
8, 12, indoc! {"
# test
this is [some](2) text here
"},
indoc! {"
# some
"},
);
}
#[test]
fn link_selected_text_with_spaces() {
assert_linked_with_range(
indoc! {"
# test
this is some text here
"},
2,
8, 17, indoc! {"
# test
this is [some text](2) here
"},
indoc! {"
# some text
"},
);
}
#[test]
fn link_selected_text_at_start() {
assert_linked_with_range(
indoc! {"
# test
word in paragraph
"},
2,
0, 4, indoc! {"
# test
[word](2) in paragraph
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_selected_text_at_end() {
assert_linked_with_range(
indoc! {"
# test
this is a word
"},
2,
10, 14, indoc! {"
# test
this is a [word](2)
"},
indoc! {"
# word
"},
);
}
#[test]
fn link_selected_text_multi_word_phrase() {
assert_linked_with_range(
indoc! {"
# test
this is a very important concept
"},
2,
10, 24, indoc! {"
# test
this is a [very important](2) concept
"},
indoc! {"
# very important
"},
);
}
#[test]
fn link_selected_text_with_punctuation() {
assert_linked_with_range(
indoc! {"
# test
this is important!
"},
2,
8, 17, indoc! {"
# test
this is [important](2)!
"},
indoc! {"
# important
"},
);
}
#[test]
fn link_selected_text_wiki_link() {
use lsp_types::{
CodeActionContext, CodeActionKind, CodeActionParams, PartialResultParams, Position, Range,
TextDocumentIdentifier, WorkDoneProgressParams,
};
let params = CodeActionParams {
text_document: TextDocumentIdentifier { uri: uri(1) },
range: Range::new(Position::new(2, 8), Position::new(2, 12)), context: CodeActionContext {
only: Some(vec![CodeActionKind::from("custom.link".to_string())]),
..Default::default()
},
work_done_progress_params: WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: PartialResultParams {
partial_result_token: None,
},
};
Fixture::with_config(
indoc! {"
# test
this is some text
"},
create_link_config("{{id}}", Some(LinkType::WikiLink)),
)
.code_action(
params,
vec![
uri(2).to_create_file(),
uri(2).to_edit("# some\n"),
uri(1).to_edit("# test\n\nthis is [[2]] text\n"),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
fn assert_linked_with_range(
source: &str,
line: u32,
start_char: u32,
end_char: u32,
target: &str,
extracted: &str,
) {
use lsp_types::{
CodeActionContext, CodeActionKind, CodeActionParams, PartialResultParams, Position, Range,
TextDocumentIdentifier, WorkDoneProgressParams,
};
let params = CodeActionParams {
text_document: TextDocumentIdentifier { uri: uri(1) },
range: Range::new(
Position::new(line, start_char),
Position::new(line, end_char),
),
context: CodeActionContext {
only: Some(vec![CodeActionKind::from("custom.link".to_string())]),
..Default::default()
},
work_done_progress_params: WorkDoneProgressParams {
work_done_token: None,
},
partial_result_params: PartialResultParams {
partial_result_token: None,
},
};
Fixture::with_config(source, link_config()).code_action(
params,
vec![
uri(2).to_create_file(),
uri(2).to_edit(extracted),
uri(1).to_edit(target),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
fn assert_linked(source: &str, line: u32, character: u32, target: &str, extracted: &str) {
Fixture::with_config(source, link_config()).code_action(
uri(1).to_code_action_params_at_position(line, character, "custom.link"),
vec![
uri(2).to_create_file(),
uri(2).to_edit(extracted),
uri(1).to_edit(target),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
fn assert_linked_wiki(source: &str, line: u32, character: u32, target: &str, extracted: &str) {
Fixture::with_config(
source,
create_link_config("{{id}}", Some(LinkType::WikiLink)),
)
.code_action(
uri(1).to_code_action_params_at_position(line, character, "custom.link"),
vec![
uri(2).to_create_file(),
uri(2).to_edit(extracted),
uri(1).to_edit(target),
]
.to_workspace_edit()
.to_code_action("Link word", "custom.link"),
);
}
fn create_link_config(key_template: &str, link_type: Option<LinkType>) -> Configuration {
let mut config = Configuration::default();
config.actions.insert(
"link".to_string(),
ActionDefinition::Link(Link {
title: "Link word".to_string(),
link_type,
key_template: key_template.to_string(),
}),
);
config
}
fn link_config() -> Configuration {
create_link_config("{{id}}", None)
}