def test_separator(): hsep = teek.Separator(teek.Window()) vsep = teek.Separator(teek.Window(), orient='vertical') assert hsep.config['orient'] == 'horizontal' assert vsep.config['orient'] == 'vertical' assert repr(hsep) == "<teek.Separator widget: orient='horizontal'>" assert repr(vsep) == "<teek.Separator widget: orient='vertical'>"
def test_checkbutton(): assert teek.Checkbutton(teek.Window()).config['text'] == '' assert teek.Checkbutton(teek.Window(), 'asd').config['text'] == 'asd' asd = [] checkbutton = teek.Checkbutton(teek.Window(), 'asd', asd.append) checkbutton.config['command'].connect(asd.append) checkbutton.invoke() assert checkbutton.config['variable'].get() is True checkbutton.invoke() assert checkbutton.config['variable'].get() is False assert asd == [True, True, False, False] asd.clear() checkbutton = teek.Checkbutton(teek.Window(), 'asd', asd.append, onvalue=False, offvalue=True) checkbutton.config['command'].connect(asd.append) checkbutton.invoke() assert checkbutton.config['variable'].get() is False checkbutton.invoke() assert checkbutton.config['variable'].get() is True assert asd == [False, False, True, True] asd.clear()
def test_get_tab_by_widget_error(): notebook = teek.Notebook(teek.Window()) with pytest.raises(ValueError) as error: notebook.get_tab_by_widget(teek.Label(teek.Window(), text='lol')) assert str( error.value) == ("expected a widget with the notebook as its parent, " "got <teek.Label widget: text='lol'>")
def test_transient(): window1 = teek.Window() window2 = teek.Window() toplevel = teek.Toplevel() window1.transient = window2 assert window1.transient is window2.toplevel window1.transient = toplevel assert window1.transient is toplevel
def test_notebooktab_init_errors(): notebook = teek.Notebook(teek.Window()) label = teek.Label(notebook) lel_widget = teek.Window() with pytest.raises(ValueError) as error: teek.NotebookTab(lel_widget) assert ('widgets of NotebookTabs must be child widgets of a Notebook' in str(error.value)) teek.NotebookTab(label) with pytest.raises(RuntimeError) as error: teek.NotebookTab(label) assert 'there is already a NotebookTab' in str(error.value)
def test_tag_bind(): # i can't think of a better way to test this tag = teek.Text(teek.Window()).get_tag('asd') tag.bind('<Button-1>', print, event=True) tag.bindings['<1>'].disconnect(print) with pytest.raises(ValueError): tag.bindings['<1>'].disconnect(print)
def test_config_types(check_config_types): notebook = teek.Notebook(teek.Window()) check_config_types(notebook.config, 'Notebook') tab = teek.NotebookTab(teek.Label(notebook, "asd")) notebook.append(tab) check_config_types(tab.config, 'NotebookTab')
def test_move(): notebook = teek.Notebook(teek.Window()) tab1 = teek.NotebookTab(teek.Label(notebook, text="one")) tab2 = teek.NotebookTab(teek.Label(notebook, text="two")) notebook.extend([tab1, tab2]) notebook.move(tab2, 0) assert list(notebook) == [tab2, tab1] notebook.move(tab2, 0) assert list(notebook) == [tab2, tab1] notebook.move(tab1, 0) assert list(notebook) == [tab1, tab2] notebook.move(tab1, 1) assert list(notebook) == [tab2, tab1] notebook.move(tab1, -1) # some_list[-1] is last item assert list(notebook) == [tab2, tab1] notebook.move(tab1, -2) assert list(notebook) == [tab1, tab2] with pytest.raises(IndexError): notebook.move(tab1, 2) with pytest.raises(IndexError): notebook.move(tab1, -3) tab3 = teek.NotebookTab(teek.Label(notebook, text="three")) with pytest.raises(ValueError): notebook.move(tab3, 0)
def test_grid_row_and_column_objects(check_config_types): window = teek.Window() assert window.grid_rows == [] assert window.grid_columns == [] # a new list is created every time assert window.grid_rows is not window.grid_rows assert window.grid_rows == window.grid_rows label = teek.Label(window) label.grid() for rows_columns in [window.grid_rows, window.grid_columns]: assert isinstance(rows_columns, list) assert len(rows_columns) == 1 row_column = rows_columns[0] assert row_column.get_slaves() == [label] check_config_types(row_column.config, 'grid row or column object') row_column.config['weight'] = 4 assert isinstance(row_column.config['weight'], float) assert row_column.config['weight'] == 4.0 assert row_column == row_column assert row_column != 'toot' assert {row_column: 'woot'}[row_column] == 'woot'
def test_scrolling(): text = teek.Text(teek.Window()) asd = [] def callback(x, y): asd.extend([x, y]) text.config['yscrollcommand'].connect(callback) text.insert(text.end, 'toot\ntoot\n' * text.config['height']) # scroll to end, and make sure everything is visible text.yview('moveto', 1) text.pack() teek.update() # this fails consistently in travis for some reason, but if i run this # locally in xvfb-run, it works fine 0_o if 'CI' not in os.environ: assert round(asd[-2], 1) == 0.5 assert asd[-1] == 1.0 # yview return type checks assert text.yview('moveto', 1) is None pair = text.yview() assert isinstance(pair, tuple) and len(pair) == 2 assert all(isinstance(item, float) for item in pair)
def test_bind(handy_callback): widget = teek.Window() assert not widget.bindings.keys() @handy_callback def tcl_call_bound_callback(): pass @handy_callback def teek_bound_callback(): pass command = teek.create_command(tcl_call_bound_callback) teek.tcl_call(None, 'bind', widget, '<<Asd>>', command) assert widget.bindings.keys() == {'<<Asd>>'} widget.bind('<<Asd>>', teek_bound_callback) teek.update() teek.tcl_call(None, 'event', 'generate', widget, '<<Asd>>') teek.delete_command(command) assert tcl_call_bound_callback.ran_once() # tests binding with + assert teek_bound_callback.ran_once() # some binding strings are equivalent assert widget.bindings['<Button-3>'] is widget.bindings['<Button-3>'] assert widget.bindings['<3>'] is widget.bindings['<Button-3>'] assert repr(widget.bindings) == '<a bindings object, behaves like a dict>'
def test_options(): window = teek.Window() for widget in [teek.Button(window), teek.Label(window)]: assert 'behaves like a dict' in repr(widget.config) assert len(widget.config) == len(list(widget.config)) # abbreviations aren't allowed, it simplifies the implementation # and people aren't aware of abbreviating things in tk anyway assert 'text' in widget.config assert 'tex' not in widget.config with pytest.raises(KeyError): widget.config['tex'] with pytest.raises(TypeError): widget.config.pop('text') # buttons are tested below, this makes sure that windows and # labels don't do something weird when they get an option that # they shouldn't support if not isinstance(widget, teek.Button): with pytest.raises(KeyError): widget.config['command'] = print widget1 = teek.Label(window, 'lol') widget1.config.update({'text': 'asd'}) widget2 = teek.Label(window, text='asd') assert widget1.config == widget2.config widget2.config['text'] = 'tootie' assert widget1.config != widget2.config
def test_place_special_error(): label = teek.Label(teek.Window()) with pytest.raises(TypeError) as error: label.place() assert str(error.value).startswith( "cannot call widget.place() without any arguments, do e.g. ")
def test_destroy_with_widget_not_created_in_teek(): window = teek.Window() label_name = window.to_tcl() + '.asd' teek.tcl_call(None, 'label', label_name) assert teek.tcl_call(bool, 'winfo', 'exists', label_name) window.destroy() # should also destroy the label assert not teek.tcl_call(bool, 'winfo', 'exists', label_name)
def test_open_file(fake_dialog_command): window = teek.Window() def check(func, python_return, tcl_command, tcl_return, tcl_options=None): tcl_options = {} if tcl_options is None else tcl_options.copy() with fake_dialog_command(tcl_command, tcl_options, tcl_return): assert func() == python_return tcl_options['-parent'] = window.toplevel.to_tcl() with fake_dialog_command(tcl_command, tcl_options, tcl_return): assert func(parent=window) == python_return # aa = absolute a aa = os.path.abspath('a') ab = os.path.abspath('b') check(teek.dialog.open_file, None, 'tk_getOpenFile', '') check(teek.dialog.open_file, aa, 'tk_getOpenFile', 'a') check(teek.dialog.open_multiple_files, [], 'tk_getOpenFile', '', {'-multiple': '1'}) check(teek.dialog.open_multiple_files, [aa, ab], 'tk_getOpenFile', ['a', 'b'], {'-multiple': '1'}) check(teek.dialog.save_file, None, 'tk_getSaveFile', '') check(teek.dialog.save_file, aa, 'tk_getSaveFile', 'a') check(teek.dialog.directory, None, 'tk_chooseDirectory', '') check(teek.dialog.directory, aa, 'tk_chooseDirectory', 'a') with pytest.raises(TypeError) as error: teek.dialog.open_file(multiple=True) assert 'open_multiple_files()' in str(error.value)
def test_bind_tab_key(): what_happened = [] def callback1(shifted): what_happened.append((1, shifted)) def callback2(shifted, event): assert event == 'fake event' what_happened.append((2, shifted)) widget = teek.Window() cross_platform.bind_tab_key(widget, callback1) cross_platform.bind_tab_key(widget, callback2, event=True) # might be nice to trigger a warning when attempting to use <Shift-Tab> # on x11 widget.bindings['<Tab>'].run('fake event') if teek.windowingsystem() == 'x11': widget.bindings['<ISO_Left_Tab>'].run('fake event') else: widget.bindings['<Shift-Tab>'].run('fake event') assert what_happened == [ (1, False), (2, False), (1, True), (2, True), ]
def test_destroy(): window = teek.Window() label = teek.Label(window) frame = teek.Frame(window) button = teek.Button(frame) widgets = [window, label, button] command = teek.create_command(print, str) label.command_list.append(command) assert teek.tcl_call([str], 'info', 'commands', command) == [command] assert window.winfo_children() == [label, frame] assert frame.winfo_children() == [button] for widget in widgets: assert widget.winfo_exists() window.destroy() for widget in widgets: assert not widget.winfo_exists() assert repr(widget).startswith('<destroyed ') assert teek.tcl_call([str], 'info', 'commands', command) == [] with pytest.raises(RuntimeError) as error: label.config['text'] = 'lel' assert str(error.value) == 'the widget has been destroyed'
def test_button_invoke(): button = teek.Button(teek.Window()) stuff = [] button.config['command'].connect(stuff.append, args=[1]) button.config['command'].connect(stuff.append, args=[2]) button.invoke() assert stuff == [1, 2]
def test_tags(): canvas = teek.Canvas(teek.Window()) rect = canvas.create_rectangle(100, 100, 200, 200) oval = canvas.create_oval(150, 150, 250, 250) assert list(rect.tags) == [] assert list(oval.tags) == [] rect.tags.add('a') assert list(rect.tags) == ['a'] assert list(oval.tags) == [] rect.tags.add('a') assert list(rect.tags) == ['a'] assert list(oval.tags) == [] rect.tags.add('b') assert list(rect.tags) == ['a', 'b'] assert list(oval.tags) == [] rect.tags.discard('b') assert list(rect.tags) == ['a'] assert list(oval.tags) == [] rect.tags.discard('b') assert list(rect.tags) == ['a'] assert list(oval.tags) == [] assert 'a' in rect.tags assert 'b' not in rect.tags
def test_state(): assert teek.Menu().state is None assert teek.Toplevel().state is None state = teek.Button(teek.Window()).state assert state is not None assert isinstance(state, collections.abc.Set) assert isinstance(state, collections.abc.MutableSet) assert 'disabled' not in state state.add('disabled') assert 'disabled' in state state.add('disabled') assert 'disabled' in state state.discard('disabled') assert 'disabled' not in state state.discard('disabled') assert 'disabled' not in state state.add('disabled') state.remove('disabled') assert 'disabled' not in state with pytest.raises(KeyError): state.remove('disabled') assert not state assert repr(state) == "<state set: []>" state.add('disabled') assert state assert repr(state) == "<state set: ['disabled']>"
def test_winfo_id(): window = teek.Window() frame1 = teek.Frame(window) frame2 = teek.Frame(window) assert isinstance(frame1.winfo_id(), int) assert frame1.winfo_id() == frame1.winfo_id() assert frame1.winfo_id() != frame2.winfo_id()
def test_insert_with_different_indexes(): notebook = teek.Notebook(teek.Window()) notebook.insert(0, teek.NotebookTab(teek.Label(notebook, "1"))) notebook.insert(1, teek.NotebookTab(teek.Label(notebook, "2"))) notebook.insert(10, teek.NotebookTab(teek.Label(notebook, "3"))) notebook.insert(-10, teek.NotebookTab(teek.Label(notebook, "0"))) assert [tab.widget.config['text'] for tab in notebook] == list('0123')
def test_tab_added_with_tcl_call_so_notebooktab_object_is_created_automagic(): notebook = teek.Notebook(teek.Window()) label = teek.Label(notebook) teek.tcl_call(None, notebook, 'add', label) # looking up notebook[0] should create a new NotebookTab object assert isinstance(notebook[0], teek.NotebookTab) assert notebook[0] is notebook[0] # and it should be "cached" now
def test_coords(): canvas = teek.Canvas(teek.Window()) oval = canvas.create_oval(150, 150, 250, 250) assert oval.coords == (150, 150, 250, 250) oval.coords = (50, 50, 100, 100.123) assert oval.coords == (50, 50, 100, 100.123) assert repr(oval) == '<oval canvas item at (50.0, 50.0, 100.0, 100.123)>'
def test_item_config_usage(): canvas = teek.Canvas(teek.Window()) rect = canvas.create_rectangle(100, 100, 200, 200, dash='-') assert rect.config['dash'] == '-' assert rect.config['fill'] is None rect.config['fill'] = 'blue' assert rect.config['fill'] == teek.Color('blue')
def create_souped_widget(html, **kwargs): widget = teek.Text(teek.Window()) souper = SoupViewer(widget, **kwargs) souper.create_tags() for element in bs4.BeautifulSoup(html, 'lxml').body: souper.add_soup(element) return (souper, widget)
def test_ask_integer(handy_callback, monkeypatch): with pytest.raises(ValueError): more_dialogs.ask_integer('a', 'b', range(10, 1, -1)) real_entrydialog = more_dialogs._EntryDialog @handy_callback def fake_entrydialog(*args): a, b, creator, validator, initial_value, parent = args assert a == 'a' assert b == 'b' assert callable(creator) assert callable(validator) assert initial_value == initial assert parent is None or isinstance(parent, WmMixin) entrydialog = real_entrydialog(*args) entrydialog.run = lambda: 123 [spinbox] = [widget for widget in entrydialog.window.winfo_children() if isinstance(widget, teek.Spinbox)] assert spinbox.text == str(initial) assert entrydialog.result == initial spinbox.text = 'asd' assert entrydialog.result is None spinbox.text = '12345678' assert entrydialog.result is None spinbox.text = str(initial) assert entrydialog.result == initial for item in spinbox_config.items(): assert item in list(spinbox.config.items()) return entrydialog monkeypatch.setattr(more_dialogs, '_EntryDialog', fake_entrydialog) assert fake_entrydialog.ran == 0 spinbox_config = {'from': 10, 'to': 30, 'increment': 5} initial = 10 assert more_dialogs.ask_integer('a', 'b', range(10, 33, 5)) == 123 assert fake_entrydialog.ran == 1 # the spinbox's config contains strings because spinboxes can be used for # non-integer things too spinbox_config = {'values': ['1', '4', '3']} initial = 1 assert more_dialogs.ask_integer('a', 'b', [1, 4, 3]) == 123 assert fake_entrydialog.ran == 2 initial = 4 assert more_dialogs.ask_integer('a', 'b', [1, 4, 3], initial_value=4, parent=teek.Window()) == 123 assert fake_entrydialog.ran == 3 with pytest.raises(ValueError): more_dialogs.ask_integer('a', 'b', [1, 4, 3], initial_value=666)
def test_ask_string(handy_callback, monkeypatch): def validator(string): if string not in ('asd', 'wat'): raise ValueError return string.upper() real_run = more_dialogs._EntryDialog.run @handy_callback def fake_run(entrydialog): @handy_callback def fake_wait_window(): [label] = [widget for widget in entrydialog.window.winfo_children() if isinstance(widget, teek.Label)] [entry] = [widget for widget in entrydialog.window.winfo_children() if isinstance(widget, teek.Entry)] assert entrydialog.window.toplevel.title == 'A' assert label.config['text'] == 'B' def get_stuff(): assert entry.text == entrydialog.var.get() return (entry.text, entrydialog.ok_button.config['state'], entrydialog.result) assert get_stuff() == ('boo', 'disabled', None) entry.text = 'a' assert get_stuff() == ('a', 'disabled', None) entry.text = 'asd' assert get_stuff() == ('asd', 'normal', 'ASD') entry.text = 'b' assert get_stuff() == ('b', 'disabled', None) entry.text = 'wat' assert get_stuff() == ('wat', 'normal', 'WAT') entry.text = 'c' assert get_stuff() == ('c', 'disabled', None) # the button is disabled now, so on_ok must do nothing entrydialog.on_ok() assert get_stuff() == ('c', 'disabled', None) assert entrydialog.window.winfo_exists() entry.text = 'wat' assert get_stuff() == ('wat', 'normal', 'WAT') entrydialog.on_ok() assert not entrydialog.window.winfo_exists() entrydialog.window.wait_window = fake_wait_window result = real_run(entrydialog) assert fake_wait_window.ran_once() return result monkeypatch.setattr(more_dialogs._EntryDialog, 'run', fake_run) assert more_dialogs.ask_string( 'A', 'B', validator=validator, initial_value='boo', parent=teek.Window()) == 'WAT' assert fake_run.ran_once()
def setUp(self): self.bus = EventBus() self.window = teek.Window("Testing Window") self.window.geometry(800, 600) ui = POEForge(self.window, self.bus) self.mouse = Mouse(self.bus) self.keyboard = Keyboard(self.bus) self.preset = Preset("test", self.bus, xy_1=(0, 1), xy_2=(1, 2))
def test_bind_deletes_tcl_commands(handy_callback): widget = teek.Window() widget.bind('<Button-1>', print) tcl_codes = teek.tcl_call(str, 'bind', widget, '<Button-1>') command_string = re.search(r'teek_command_\d+', tcl_codes).group(0) assert command_string in teek.tcl_call([str], 'info', 'commands') widget.destroy() assert command_string not in teek.tcl_call([str], 'info', 'commands')