Skip to content

Commit

Permalink
Merge fc14198 into bebd9b7
Browse files Browse the repository at this point in the history
  • Loading branch information
mshriver committed Jul 12, 2018
2 parents bebd9b7 + fc14198 commit b008946
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 29 deletions.
47 changes: 31 additions & 16 deletions src/widgetastic/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,7 @@ class TableRow(Widget, ClickableMixin):

def __init__(self, parent, index, logger=None):
Widget.__init__(self, parent, logger=logger)
self.index = index
self.index = index + 1 if parent._is_header_in_body else index or 1

@property
def table(self):
Expand All @@ -1332,7 +1332,7 @@ def __repr__(self):
return '{}({!r}, {!r})'.format(type(self).__name__, self.parent, self.index)

def __locator__(self):
loc = self.parent.ROW_AT_INDEX.format(self.index + 1)
loc = self.parent.ROW_AT_INDEX.format(self.index)
return self.browser.element(loc, parent=self.parent)

def position_to_column_name(self, position):
Expand Down Expand Up @@ -1514,12 +1514,19 @@ def __repr__(self):
self.rows_ignore_top, self.rows_ignore_bottom)

def _process_negative_index(self, nindex):
"""The semantics is pretty much the same like for ordinary list."""
rc = self.row_count
if (- nindex) > rc:
"""The semantics is pretty much the same like for ordinary list.
There's some funky off-by-1 math here because the index is 1-based and we're replicating
list negative index access
Args:
nindex: negative index
"""
max_index = self.row_count
if (- nindex) > max_index:
raise ValueError(
'Negative index {} wanted but we only have {} rows'.format(nindex, rc))
return rc + nindex
'Negative index {} wanted but we only have {} rows'.format(nindex, max_index))
return max_index + nindex + 1

def clear_cache(self):
"""Clear all cached properties."""
Expand Down Expand Up @@ -1629,14 +1636,17 @@ def _get_number_preceeding_rows(self, row_el):
How simple.
"""
return self.browser.execute_script(
row_count = self.browser.execute_script(
jsmin("""\
var p = []; var e = arguments[0];
while (e.previousElementSibling)
p.push(e = e.previousElementSibling);
return p.length;
"""), row_el, silent=True)

# the JS gobbles up the in-tbody header row when counting
return row_count

def map_column(self, column):
"""Return column position. Can accept int, normal name, attributized name."""
if isinstance(column, int):
Expand All @@ -1653,7 +1663,8 @@ def map_column(self, column):
@cached_property
def _is_header_in_body(self):
"""Checks whether the header is erroneously specified in the body of table."""
return len(self.browser.elements(self.HEADER_IN_ROWS, parent=self)) > 0
header_rows = len(self.browser.elements(self.HEADER_IN_ROWS, parent=self))
return header_rows > 0

def rows(self, *extra_filters, **filters):
if not (filters or extra_filters):
Expand All @@ -1662,8 +1673,8 @@ def rows(self, *extra_filters, **filters):
return self._filtered_rows(*extra_filters, **filters)

def _all_rows(self):
for row_pos in range(len(self.browser.elements(self.ROWS, parent=self))):
row_pos = row_pos if not self._is_header_in_body else row_pos + 1
# passing index to TableRow, should not be <1 but want to adjust for headers within TableRow
for row_pos in range(1, len(self.browser.elements(self.ROWS, parent=self)) + 1):
yield self.Row(self, row_pos, logger=create_item_logger(self.logger, row_pos))

def _filtered_rows(self, *extra_filters, **filters):
Expand Down Expand Up @@ -1774,8 +1785,10 @@ def _filtered_rows(self, *extra_filters, **filters):
rows = []
for row_element in self.browser.elements(query, parent=self):
row_pos = self._get_number_preceeding_rows(row_element)
row_pos = row_pos if not self._is_header_in_body else row_pos + 1
rows.append(self.Row(self, row_pos, logger=create_item_logger(self.logger, row_pos)))
row_pos = row_pos if self._is_header_in_body else row_pos + 1
# get_number_prceeding_rows
rows.append(self.Row(self, row_pos,
logger=create_item_logger(self.logger, row_pos)))

for row in rows:
if regexp_filters:
Expand Down Expand Up @@ -1805,11 +1818,13 @@ def row_by_cell_or_widget_value(self, column, key):
except RowNotFound:
for row in self.rows():
if row[column].widget is None:
continue
continue # the column has a widget...
if not row[column].widget.is_displayed:
continue
continue # the column widget is displayed...
if row[column].widget.read() == key:
return row
return row # And the value matches, we're done
else:
continue # continue loop, not the row we want
else:
raise RowNotFound('Row not found by {!r}/{!r}'.format(column, key))

Expand Down
77 changes: 65 additions & 12 deletions testing/test_basic_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,6 @@ class Nested2(View):
def test_table(browser):
class TestForm(View):
table = Table('#with-thead')
other_table = Table('#untypical_header')

view = TestForm(browser)
assert view.table.headers == (None, 'Column 1', 'Column 2', 'Column 3', 'Column 4')
Expand All @@ -150,12 +149,12 @@ class TestForm(View):
assert len(list(view.table.rows(_row__attr_endswith=('data-test', '345')))) == 2
assert len(list(view.table.rows(_row__attr_contains=('data-test', '3')))) == 3
assert len(list(view.table.rows(
_row__attr_contains=('data-test', '3'), _row__attr_startswith=('data-test', 'abc')))) == 2
_row__attr_contains=('data-test', '3'), _row__attr_startswith=('data-test', 'abc')))) == 2

assert len(list(view.table.rows(_row__attr=('data-test', 'abc-345'), column_1='qwer'))) == 0

with pytest.raises(ValueError):
list(view.table.rows(_row__papalala=('foo', 'bar')))
list(view.table.rows(_row__papalala=('foo', 'bar')))

with pytest.raises(ValueError):
list(view.table.rows(_row__attr_papalala=('foo', 'bar')))
Expand Down Expand Up @@ -183,17 +182,24 @@ class TestForm(View):
column_3__endswith='_x')
assert row[0].text == 'foo_x'

# attributized columns for a table with thead
row = view.table.row(column_1='bar_x')
assert row[0].text == 'foo_x'
assert row['Column 1'].text == 'bar_x'
assert row.column_1.text == 'bar_x'

assert [(header, column.text) for header, column in row] == [
(None, 'foo_x'),
('Column 1', 'bar_x'),
('Column 2', 'baz_x'),
('Column 3', 'bat_x'),
('Column 4', '')]
assert row.read() == {0: 'foo_x',
'Column 1': 'bar_x',
'Column 2': 'baz_x',
'Column 3': 'bat_x',
'Column 4': ''}

unpacking_fake_read = [(header, column.text) for header, column in row]
assert unpacking_fake_read == [(None, 'foo_x'),
('Column 1', 'bar_x'),
('Column 2', 'baz_x'),
('Column 3', 'bat_x'),
('Column 4', '')]

assert view.table[0].column_2.text == 'yxcv'

Expand All @@ -203,13 +209,60 @@ class TestForm(View):
with pytest.raises(TypeError):
view.table['boom!']

row = next(view.table.rows())
assert row.column_1.text == 'qwer'


def test_table_no_header(browser):
class TestForm(View):
nohead_table = Table('#without_thead')

view = TestForm(browser)
# attributized columns for a table withOUT thead
row = view.nohead_table.row(event='Some Event')
assert row[0].text == '27.02.2017, 12:19:30'
assert row['Event'].text == 'Some Event'
assert row.event.text == 'Some Event'

assert row.read() == {'Date': '27.02.2017, 12:19:30',
'Event': 'Some Event'}
# headers are read correctly when those aren't in thead
assert len(view.other_table.headers) == 2
assert len(view.nohead_table.headers) == 2

row = next(view.other_table.rows())
row = next(view.nohead_table.rows())
assert row.event.text == 'Some Event'


def test_table_negative_row_index(browser):
class TestForm(View):
table = Table('#with-thead')

view = TestForm(browser)
assert view.table[-1].read() == {0: 'foo_y',
'Column 1': 'bar_y',
'Column 2': 'baz_y',
'Column 3': 'bat_y',
'Column 4': ''}
assert view.table[-2].read() == {0: 'foo_x',
'Column 1': 'bar_x',
'Column 2': 'baz_x',
'Column 3': 'bat_x',
'Column 4': ''}
assert view.table[-3].read() == {0: 'asdf',
'Column 1': 'qwer',
'Column 2': 'yxcv',
'Column 3': 'uiop',
'Column 4': ''}
assert view.table[0].read() == {0: 'asdf',
'Column 1': 'qwer',
'Column 2': 'yxcv',
'Column 3': 'uiop',
'Column 4': ''}

with pytest.raises(ValueError):
view.table[-4].read()


def test_table_with_widgets(browser):
class TestForm(View):
table = Table('#withwidgets', column_widgets={
Expand Down Expand Up @@ -372,7 +425,7 @@ def test_table_dynamic_add_assoc(browser):
class MyTable(Table):
def row_add(self):
self.browser.click('//button[@id="dynamicadd"]')
return -1
return -1 # testing negative index when we expect row to be added to end of table

class MyView(View):
table = MyTable(
Expand Down
5 changes: 4 additions & 1 deletion testing/testing_page.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ <h3>test test</h3>
<input name="input1" type="text" />
<input id="input2" type="checkbox" />
</form>
<hr/>
<table id="with-thead">
<thead>
<tr>
Expand Down Expand Up @@ -68,7 +69,8 @@ <h3>test test</h3>

</tbody>
</table>
<table id="untypical_header">
<hr/>
<table id="without_thead">
<thead></thead>
<tbody>
<tr>
Expand All @@ -81,6 +83,7 @@ <h3>test test</h3>
</tr>
</tbody>
</table>
<hr/>
<select name="testselect1">
<option value="foo">Foo</option>
<option value="bar"> Bar </option>
Expand Down

0 comments on commit b008946

Please sign in to comment.