Skip to content

Commit

Permalink
Tests for eachline and chop
Browse files Browse the repository at this point in the history
  • Loading branch information
mariocesar committed Jan 23, 2018
1 parent 23144b9 commit d290e05
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 15 deletions.
53 changes: 39 additions & 14 deletions quilldelta/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self, ops: Union[List[OperationType], Dict, TypeVar('Delta')] = Non
self.ops.append(op)

def __repr__(self):
return f'<Delta length={self.length()} at {id(self)}>'
return f'<Delta {self.ops}>'

def __eq__(self, other):
return self.ops == other.ops
Expand Down Expand Up @@ -73,13 +73,10 @@ def push(self, new_op: OperationType):
self.ops.insert(0, new_op)
return self

if isinstance(new_op, (Insert, Retain)) and isinstance(last_op, (Insert, Retain)):
if all(map(lambda op: isinstance(op, (Insert, Retain)), [new_op, last_op])):
if isinstance(new_op, type(last_op)):
if new_op.attributes == last_op.attributes:
if isinstance(new_op.value, str) and isinstance(last_op.value, str):
self.ops[index - 1] = last_op + new_op
return self
elif isinstance(new_op.value, int) and isinstance(last_op.value, int):
if type(new_op.value) == type(last_op.value):
self.ops[index - 1] = last_op + new_op
return self

Expand Down Expand Up @@ -144,7 +141,7 @@ def partition(self, func):

return passed, failed

def reduce(self, func, initial):
def reduce(self, func, initial=0):
return reduce(func, self.ops, initial=initial)

def change_length(self):
Expand All @@ -156,18 +153,17 @@ def reducer(length, op):
else:
return length

return self.reduce(reducer, initial=0)
return self.reduce(reducer, 0)

def length(self):
return self.reduce(self.map(lambda op: op.length), initial=0)
return reduce(lambda length, op: op.length + length, self.ops, 0)

def compose(self, other: TypeVar('Delta')):
delta = Delta()
self_iter = Iterator(self.ops)
other_iter = Iterator(other.ops)
delta = Delta()

while self_iter.has_next() or other_iter.has_next():

if other_iter.peek_type() == Insert:
delta.push(other_iter.next())
elif self_iter.peek_type() == Delete:
Expand Down Expand Up @@ -226,12 +222,41 @@ def concat(self, other):
def diff(self, other, index):
raise NotImplementedError

def each_line(self, func, newline):
raise NotImplementedError
def each_line(self, func, newline='\n'):
cursor = Iterator(self.ops)
line = Delta()
i = 0

while cursor.has_next():
if cursor.peek_type() != Insert:
return

self_op = cursor.peek()
start = self_op.length - cursor.peek_length()

if isinstance(self_op, Insert) and isinstance(self_op.value, str):
try:
index = self_op.value.index(newline, start) - start
except ValueError:
index = -1
else:
index = -1

if index < 0:
line.push(cursor.next())
elif index > 0:
line.push(cursor.next(index))
else:
if not func(line, cursor.next(1).attributes, i):
return
i += 1
line = Delta()

if line.length() > 0:
func(line, {}, i)

def transform(self, other, priority):
raise NotImplementedError

def transform_position(self, index, priority):
raise NotImplementedError

8 changes: 7 additions & 1 deletion tests/test_compose.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from quilldelta import Delta


class TestCompose:
def test_insert_insert(self):
a = Delta().insert('A')
Expand Down Expand Up @@ -64,3 +63,10 @@ def test_retain_delete(self):
expected = Delta().delete(1)
delta = a.compose(b)
assert delta == expected, [delta.ops, expected.ops]

def test_insert_in_middle_of_text(self):
a = Delta().insert('Hello')
b = Delta().retain(3).insert('X')
expected = Delta().insert('HelXlo')

assert a.compose(b).ops == expected.ops
68 changes: 68 additions & 0 deletions tests/test_helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from unittest import mock

from quilldelta import Delta


class TestConcat:
def test_empty_delta(self):
delta = Delta().insert('Test')
concat = Delta()
expected = Delta().insert('Test')
assert delta.concat(concat).ops == expected.ops

assert concat.concat(delta).ops == expected.ops

def test_unmergeable(self):
delta = Delta().insert('Test')
original = Delta().insert('Test')
concat = Delta().insert('!', {'bold': True})
expected = Delta().insert('Test').insert('!', {'bold': True})

assert delta.concat(concat).ops == expected.ops
assert delta.ops == original.ops

def test_mergeable(self):
delta = Delta().insert('Test', {'bold': True})
original = Delta().insert('Test', {'bold': True})
concat = Delta().insert('!', {'bold': True}).insert('\n')
expected = Delta().insert('Test!', {'bold': True}).insert('\n')

assert delta.concat(concat).ops == expected.ops
assert delta.ops == original.ops


class TestChop:
def test_retain(self):
delta = Delta().insert('Test').retain(4)
expected = Delta().insert('Test')

assert delta.chop().ops == expected.ops

def test_insert(self):
delta = Delta().insert('Test')
expected = Delta().insert('Test')

assert delta.chop().ops == expected.ops

def test_formatted_retain(self):
delta = Delta().insert('Test').retain(4, {'bold': True})
expected = Delta().insert('Test').retain(4, {'bold': True})

assert delta.chop().ops == expected.ops


class TestEachLine:
def test_expected(self):
delta = (Delta().insert('Hello\n\n')
.insert('World', {'bold': True})
.insert({'image': 'octocat.png'})
.insert('\n', {'align': 'right'})
.insert('!'))

predicate = mock.Mock()
delta.each_line(predicate)

assert predicate.call_count == 4
call_args = predicate.call_args_list

assert call_args[0] == (Delta().insert('Hello'), {}, 0)

0 comments on commit d290e05

Please sign in to comment.