use super::*;
use crate::test_utils::index::index_models_with_properties;
#[test]
fn test_method_docstring_basic() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'test.model'
def test_method(self, arg):
"""Test docstring"""
pass
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let entry = index.models.get(&_I("test.model")).unwrap();
let methods = entry.methods.as_ref().unwrap();
let method = methods.get(&_I("test_method")).unwrap();
let doc = index.method_docstring("test_method", method, Some("str"));
println!("method doc: {doc}");
assert!(doc.contains("test_method"));
}
#[test]
fn test_completion_resolve_method() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'test.model'
def test_method(self, arg):
"""Test docstring"""
pass
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let mut item = CompletionItem {
label: "test_method".to_string(),
data: Some(serde_json::json!({ "model": "test.model" })),
..Default::default()
};
let result = index.completion_resolve_method(&mut item);
assert!(result.is_some());
if let Some(Documentation::MarkupContent(MarkupContent { value, .. })) = &item.documentation {
assert!(value.contains("def test_method"));
} else {
panic!("Expected documentation to be set");
}
}
#[test]
fn test_field_docstring_signature() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'foo.model'
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let entry = index.models.get(&_I("foo.model")).unwrap();
let fields = entry.fields.as_ref().unwrap();
let field = fields.get(&_I("foo_field")).unwrap();
let doc = index.field_docstring(field, true);
assert!(doc.contains("(field) Char("));
}
#[test]
fn test_completion_resolve_field() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'foo.model'
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let mut item = CompletionItem {
label: "foo_field".to_string(),
data: Some(serde_json::json!({ "model": "foo.model" })),
..Default::default()
};
let result = index.completion_resolve_field(&mut item);
assert!(result.is_some());
if let Some(Documentation::MarkupContent(MarkupContent { value, .. })) = &item.documentation {
println!("field doc: {value}");
assert!(value.is_empty() || !value.is_empty());
} else {
panic!("Expected documentation to be set");
}
}
#[test]
fn test_hover_property_name_field() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'foo.model'
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let result = index.hover_property_name("foo_field", "foo.model", None);
assert!(result.unwrap().is_some());
}
#[test]
fn test_hover_property_name_method() {
let py: &'static str = r#"
class Foo(models.Model):
_name = 'bar.model'
def bar_method(self, arg):
"""Docstring"""
pass
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let result = index.hover_property_name("bar_method", "bar.model", None);
assert!(result.unwrap().is_some());
}
#[test]
fn test_model_docstring() {
let py = r#"
class Foo(models.Model):
_name = 'foo.model'
"""Foo docstring"""
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let entry = index.models.get(&_I("foo.model")).unwrap();
let doc = index.model_docstring(&entry, Some("foo.model"), Some("Foo"));
println!("model doc: {doc}");
assert!(doc.contains("foo.model"));
}
#[test]
fn test_method_references() {
let py = r#"
class Foo(models.Model):
_name = 'foo.model'
def bar(self):
pass
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let refs = index.method_references("bar", "foo.model").unwrap();
assert!(refs.is_some());
let refs = refs.unwrap();
assert!(!refs.is_empty());
}
#[test]
fn test_jump_def_property_name_field() {
let py = r#"
class Foo(models.Model):
_name = 'foo.model'
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let loc = index.jump_def_property_name("foo_field", "foo.model").unwrap();
assert!(loc.is_some());
}
#[test]
fn test_hover_model() {
let py = r#"
class Foo(models.Model):
_name = 'foo.model'
"""Foo docstring"""
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let hover = index.hover_model("foo.model", None, true, Some("Foo")).unwrap();
assert!(hover.is_some());
let hover = hover.unwrap();
if let HoverContents::Markup(MarkupContent { value, .. }) = hover.contents {
assert!(value.contains("foo.model"));
} else {
panic!("Expected markup content");
}
}
#[test]
fn test_jump_def_model() {
let py = r#"
class Foo(models.Model):
_name = 'foo.model'
foo_field = fields.Char()
"#;
let mut index = Index::default();
index_models_with_properties(&mut index, Some(py), None, None);
let loc = index.jump_def_model("foo.model").unwrap();
assert!(loc.is_some());
}
#[test]
fn test_hover_component() {
let index = Index::default();
let name = _I("TestComponent");
let minloc = crate::utils::MinLoc {
path: crate::index::PathSymbol::empty(),
range: Default::default(),
};
let component = crate::component::Component {
location: Some(minloc.clone()),
..Default::default()
};
index.components.insert(name.into(), component);
let hover = index.hover_component("TestComponent", None);
assert!(hover.is_some());
let hover = hover.unwrap();
if let HoverContents::Scalar(MarkedString::String(value)) = hover.contents {
assert!(value.contains("TestComponent"));
} else {
panic!("Expected scalar string");
}
}
#[test]
fn test_complete_widget() {
let index = Index::default();
let minloc = crate::utils::MinLoc {
path: crate::index::PathSymbol::empty(),
range: Default::default(),
};
index.widgets.insert("WidgetA".into(), minloc);
let rope = ropey::Rope::from_str("");
let mut items = crate::utils::MaxVec::new(10);
let range = crate::prelude::ByteRange::default();
index.complete_widget(range, rope.slice(..), &mut items).unwrap();
assert!(items.iter().any(|item| item.label == "WidgetA"));
}
#[test]
fn test_damage_zone() {
use crate::backend::Text;
use ropey::Rope;
let rope = Rope::from_str("hello world");
let delta = Text::Delta(vec![TextDocumentContentChangeEvent {
range: Some(Range {
start: Position { line: 0, character: 0 },
end: Position { line: 0, character: 5 },
}),
text: String::from(""),
range_length: None,
}]);
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_some());
}
#[test]
fn test_damage_zone_cases() {
use crate::backend::Text;
use ropey::Rope;
let rope = Rope::from_str("abcdefghij");
let delta = Text::Delta(vec![TextDocumentContentChangeEvent {
range: Some(Range {
start: Position { line: 0, character: 2 },
end: Position { line: 0, character: 5 },
}),
text: String::from(""),
range_length: None,
}]);
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_some(), "Single delta should produce a zone");
let delta = Text::Delta(vec![
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position { line: 0, character: 1 },
end: Position { line: 0, character: 3 },
}),
text: String::from(""),
range_length: None,
},
TextDocumentContentChangeEvent {
range: Some(Range {
start: Position { line: 0, character: 6 },
end: Position { line: 0, character: 8 },
}),
text: String::from(""),
range_length: None,
},
]);
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_some(), "Multiple deltas should produce a zone");
let delta = Text::Full("abcdefghij".to_string());
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_none(), "Full variant should return None");
let delta = Text::Delta(vec![TextDocumentContentChangeEvent {
range: None,
text: String::from(""),
range_length: None,
}]);
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_none(), "Delta with None range should return None");
let delta = Text::Delta(vec![TextDocumentContentChangeEvent {
range: Some(Range {
start: Position { line: 0, character: 4 },
end: Position { line: 0, character: 6 },
}),
text: String::from(""),
range_length: None,
}]);
let seed = Some(2..5); let zone = delta.damage_zone(rope.slice(..), seed.map(|r| r.map_unit(crate::utils::ByteOffset)));
assert!(zone.is_some(), "Delta with seed should produce a zone");
let delta = Text::Delta(vec![]);
let zone = delta.damage_zone(rope.slice(..), None);
assert!(zone.is_none(), "Empty deltas should return None");
}