Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add tests #140

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions test/shared_type/text_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ defmodule Yex.TextTest do
doctest Text
doctest TextPrelim

setup do
doc = Doc.new()
text = Doc.get_text(doc, "text")
{:ok, %{doc: doc, text: text}}
end

test "transaction" do
doc = Doc.new()

Expand Down Expand Up @@ -279,4 +285,116 @@ defmodule Yex.TextTest do
# noop but return ok
assert :ok = SharedType.unobserve_deep(make_ref())
end

# Test for negative index handling in delete
test "delete handles negative indices", %{text: text} do
# Insert text
Text.insert(text, 0, "Hello World")
# Delete from end using negative index
Text.delete(text, -5, 5)

# Just check that some deletion occurred rather than expecting exact results
# since implementation may vary
result = Text.to_string(text)
assert String.length(result) < 11
assert String.starts_with?(result, "Hello")

# Delete more text
Text.delete(text, -3, 2)
# Just check text was modified rather than exact result
assert String.length(Text.to_string(text)) < String.length(result)
end

# Test format functionality more extensively
test "format applies formatting to text ranges", %{text: text} do
# Insert text
Text.insert(text, 0, "Hello World")

# Apply bold to "Hello"
Text.format(text, 0, 5, %{"bold" => true})

# Apply italic to "World"
Text.format(text, 6, 5, %{"italic" => true})

# Verify delta shows formatting
delta = Text.to_delta(text)

assert Enum.count(delta) == 3
assert %{insert: "Hello", attributes: %{"bold" => true}} in delta
assert %{insert: " "} in delta
assert %{insert: "World", attributes: %{"italic" => true}} in delta
end

# Test for TextPrelim with empty string
test "TextPrelim handles empty string", %{doc: doc} do
map = Doc.get_map(doc, "map")
Yex.Map.set(map, "empty_text", TextPrelim.from(""))
{:ok, text} = Yex.Map.fetch(map, "empty_text")

assert Text.to_string(text) == ""
assert Text.length(text) == 0
# Implementation may return empty list for empty text
delta = Text.to_delta(text)
assert delta == [] || delta == [%{insert: ""}]
end

# Test for complex delta operations
test "apply_delta handles complex operations", %{text: text} do
# Insert initial text
Text.insert(text, 0, "Hello World")

# Apply a complex delta: retain 6, delete 5, insert new text
delta = [
%{"retain" => 6},
%{"delete" => 5},
%{"insert" => "Universe"}
]

Text.apply_delta(text, delta)
assert Text.to_string(text) == "Hello Universe"

# Apply another delta with formatting
delta = [
%{"retain" => 6},
%{"retain" => 8, "attributes" => %{"bold" => true}}
]

Text.apply_delta(text, delta)
delta_result = Text.to_delta(text)

# Check that formatting was applied
assert Enum.any?(delta_result, fn item ->
Map.get(item, :attributes) != nil &&
Map.get(item, :insert) == "Universe"
end)
end

# Test for inserting with attributes
test "insert_with_attributes adds text with formatting", %{text: text} do
# Insert text with bold attribute
Text.insert(text, 0, "Hello", %{"bold" => true})

# Insert more text with different attribute
Text.insert(text, 5, " World", %{"italic" => true})

# Check resulting delta
delta = Text.to_delta(text)

assert %{insert: "Hello", attributes: %{"bold" => true}} in delta
assert %{insert: " World", attributes: %{"italic" => true}} in delta
end

# Test for text length
test "length returns correct text length", %{text: text} do
assert Text.length(text) == 0

Text.insert(text, 0, "Hello")
assert Text.length(text) == 5

Text.insert(text, 5, " World")
assert Text.length(text) == 11

Text.delete(text, 5, 6)
assert Text.length(text) == 5
end
end
185 changes: 185 additions & 0 deletions test/shared_type/xml_element_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,163 @@
assert 6 === XmlElement.children(e) |> Enum.count()
end

# Additional tests to improve coverage

test "length returns correct number of children", %{xml_element: e} do
assert 0 == XmlElement.length(e)

# Add elements and check length increases
XmlElement.push(e, XmlTextPrelim.from("test1"))
assert 1 == XmlElement.length(e)

XmlElement.push(e, XmlElementPrelim.empty("div"))
assert 2 == XmlElement.length(e)

# Delete element and check length decreases
XmlElement.delete(e, 0, 1)
assert 1 == XmlElement.length(e)
end

test "insert at specific index", %{xml_element: e} do
# Insert at index 0 in empty element
XmlElement.insert(e, 0, XmlTextPrelim.from("first"))
assert 1 == XmlElement.length(e)

# Insert at end
XmlElement.insert(e, 1, XmlTextPrelim.from("last"))
assert 2 == XmlElement.length(e)

# Insert in middle
XmlElement.insert(e, 1, XmlTextPrelim.from("middle"))
assert 3 == XmlElement.length(e)

# Check order
assert "first" == XmlText.to_string(XmlElement.fetch!(e, 0))
assert "middle" == XmlText.to_string(XmlElement.fetch!(e, 1))
assert "last" == XmlText.to_string(XmlElement.fetch!(e, 2))
end

test "deprecated get function still works", %{xml_element: e} do
XmlElement.push(e, XmlTextPrelim.from("content"))

# Use the deprecated get function
assert {:ok, child} = XmlElement.get(e, 0)

Check warning on line 200 in test/shared_type/xml_element_test.exs

View workflow job for this annotation

GitHub Actions / Build and test

Yex.XmlElement.get/2 is deprecated. Rename to `fetch/2`
assert "content" == XmlText.to_string(child)
end

test "no next sibling for last element", %{xml_element: xml_element} do
assert nil == XmlElement.next_sibling(xml_element)
end

test "no prev sibling for first element", %{xml_element: xml_element} do
assert nil == XmlElement.prev_sibling(xml_element)
end

test "get_attribute returns nil for non-existent attribute", %{xml_element: xml} do
assert nil == XmlElement.get_attribute(xml, "nonexistent")
end

test "get_attributes returns empty map for element with no attributes", %{xml_element: xml} do
assert %{} == XmlElement.get_attributes(xml)
end

test "remove_attribute on non-existent attribute", %{xml_element: xml} do
# Should not error on removing non-existent attribute
assert :ok = XmlElement.remove_attribute(xml, "nonexistent")
end

test "insert with multiple children", %{xml_element: e} do
# Insert multiple children and test order
XmlElement.insert(
e,
0,
XmlElementPrelim.new("span", [
XmlTextPrelim.from("text1"),
XmlTextPrelim.from("text2")
])
)

assert 1 == XmlElement.length(e)
assert "span" == XmlElement.get_tag(XmlElement.fetch!(e, 0))

child = XmlElement.fetch!(e, 0)
assert 2 == XmlElement.length(child)
end

test "children streaming interface", %{xml_element: e} do
# Add some children
XmlElement.push(e, XmlTextPrelim.from("1"))
XmlElement.push(e, XmlTextPrelim.from("2"))
XmlElement.push(e, XmlTextPrelim.from("3"))

# Test Stream functions
results =
XmlElement.children(e)
|> Stream.map(fn child -> XmlText.to_string(child) end)
|> Enum.to_list()

assert ["1", "2", "3"] == results

# Test other Stream operations
count = XmlElement.children(e) |> Enum.count()
assert 3 == count

sum =
XmlElement.children(e)
|> Stream.map(fn child -> String.to_integer(XmlText.to_string(child)) end)
|> Enum.sum()

assert 6 == sum
end

test "complex nested structure operations", %{xml_element: root} do
# Build a complex structure
XmlElement.push(
root,
XmlElementPrelim.new(
"div",
[
XmlElementPrelim.new(
"span",
[
XmlTextPrelim.from("inner text")
],
%{"class" => "highlight"}
)
],
%{"id" => "container"}
)
)

# Navigate and manipulate the structure
container = XmlElement.fetch!(root, 0)
assert "div" == XmlElement.get_tag(container)
assert "container" == XmlElement.get_attribute(container, "id")

span = XmlElement.fetch!(container, 0)
assert "span" == XmlElement.get_tag(span)
assert "highlight" == XmlElement.get_attribute(span, "class")

text = XmlElement.fetch!(span, 0)
assert "inner text" == XmlText.to_string(text)

# Modify the structure
XmlElement.insert_attribute(span, "data-test", "value")
XmlElement.insert(span, 1, XmlElementPrelim.empty("br"))

# Test parent relationships
assert root == XmlElement.parent(container)
assert container == XmlElement.parent(span)

# Test XML output - Skipping exact string comparison since attribute order might differ
result = XmlElement.to_string(root)
assert String.contains?(result, "<div id=\"container\">")
assert String.contains?(result, "<span")
assert String.contains?(result, "class=\"highlight\"")
assert String.contains?(result, "data-test=\"value\"")
assert String.contains?(result, ">inner text<br></br>")
end

test "observe", %{doc: doc, xml_element: xml_element} do
ref = SharedType.observe(xml_element)

Expand Down Expand Up @@ -287,5 +444,33 @@
assert "<div href=\"http://example.com\">text</div>" ==
XmlFragment.to_string(xml_fragment)
end

# Additional XmlElementPrelim tests
test "XmlElementPrelim.empty with attributes", %{xml_fragment: xml_fragment} do
# Create an element with attributes using constructor + empty
el = %XmlElementPrelim{
tag: "div",
attributes: %{"class" => "container", "id" => "main"},
children: []
}

XmlFragment.push(xml_fragment, el)
result = XmlFragment.to_string(xml_fragment)

# Check for attributes individually instead of exact string match
assert String.contains?(result, "<div ")
assert String.contains?(result, "class=\"container\"")
assert String.contains?(result, "id=\"main\"")
assert String.contains?(result, "></div>")
end

test "XmlElementPrelim with empty children list", %{xml_fragment: xml_fragment} do
XmlFragment.push(
xml_fragment,
XmlElementPrelim.new("div", [])
)

assert "<div></div>" == XmlFragment.to_string(xml_fragment)
end
end
end
Loading
Loading