diff options
Diffstat (limited to 'tests/ttk')
-rw-r--r-- | tests/ttk/all.tcl | 15 | ||||
-rw-r--r-- | tests/ttk/bwidget.test | 101 | ||||
-rw-r--r-- | tests/ttk/combobox.test | 48 | ||||
-rw-r--r-- | tests/ttk/entry.test | 262 | ||||
-rw-r--r-- | tests/ttk/image.test | 44 | ||||
-rw-r--r-- | tests/ttk/labelframe.test | 134 | ||||
-rw-r--r-- | tests/ttk/layout.test | 29 | ||||
-rw-r--r-- | tests/ttk/misc.test | 33 | ||||
-rw-r--r-- | tests/ttk/notebook.test | 387 | ||||
-rw-r--r-- | tests/ttk/panedwindow.test | 201 | ||||
-rw-r--r-- | tests/ttk/progressbar.test | 89 | ||||
-rw-r--r-- | tests/ttk/scrollbar.test | 42 | ||||
-rw-r--r-- | tests/ttk/treetags.test | 77 | ||||
-rw-r--r-- | tests/ttk/treeview.test | 494 | ||||
-rw-r--r-- | tests/ttk/ttk.test | 594 | ||||
-rw-r--r-- | tests/ttk/validate.test | 277 |
16 files changed, 2827 insertions, 0 deletions
diff --git a/tests/ttk/all.tcl b/tests/ttk/all.tcl new file mode 100644 index 0000000..75aa035 --- /dev/null +++ b/tests/ttk/all.tcl @@ -0,0 +1,15 @@ +# +# source all tests. +# +package require tcltest 2.1 + +package require Tk 8.5 ;# This is the Tk test suite; fail early if no Tk! + +tcltest::configure -testdir [file join [pwd] [file dirname [info script]]] + +eval tcltest::configure $::argv +tcltest::runAllTests + +if {![catch { package present Tk }]} { + destroy . +} diff --git a/tests/ttk/bwidget.test b/tests/ttk/bwidget.test new file mode 100644 index 0000000..f371daf --- /dev/null +++ b/tests/ttk/bwidget.test @@ -0,0 +1,101 @@ +# +# Test BWidget / Ttk compatibility. +# +# NOTE: This part of the test suite is no longer operative: +# [namespace import -force ttk::*] is not expected or intended to work. +# +# Keeping the file around for now since it contains some historical +# information about how ttk *tried* to make it work, and what +# sort of things went wrong. +# + +package require Tk 8.5 +package require tcltest +tcltest::cleanupTests ; return + +loadTestedCommands + +set have_compat 0 +if {![catch {ttk::pkgconfig get compat} compat]} {set have_compat $compat} +testConstraint bwidget [expr {$have_compat && ![catch {package require BWidget}]}] + +test bwidget-1.0 "Setup for BWidget test" -constraints bwidget -body { + namespace import -force ttk::* + puts "Loaded BWidget version [package provide BWidget]" +} + +test bwidget-1.1 "Make Label widget" -constraints bwidget -body { + pack [Label .w] +} -cleanup {destroy .w} + +test bwidget-1.2 "Make ScrolledWindow widget" -constraints bwidget -body { + pack [ScrolledWindow .w -auto both -scrollbar vertical] +} -cleanup {destroy .w} + +test bwidget-1.3 "Make PagesManager widget" -constraints bwidget -body { + pack [PagesManager .w] +} -cleanup {destroy .w} + +# +# ProgressBar: this one fails with 'unknown color name "xxx"', +# where "xxx" is the default value of some other option +# (variously, "4m", "100", something else). +# +# Update: fixed now. Source of problem: widgets were using "unused" +# as the resource database name for compatibility options; +# BWidgets keys off the db name instead of the option name. +# +test bwidget-1.4 "Make ProgressBar widget" -constraints bwidget -body { + pack [ProgressBar .w] +} -cleanup {destroy .w} + +# @@@ TODO: full BWidget coverage, +# @@@ not just the ones people have reported problems with. + + +# +# <<NOTE-NULLOPTIONS>>: +# +# TK_OPTION_NULL_OK doesn't work for TK_OPTION_INT (among others); +# see Bug #967209. +# +# This means that [.l configure -width [.l cget -width]] -- which is +# essentially what BWidgets does -- will raise an error if -width has +# a NULL default. +# +# Temporary workaround: declare -width, etc. as TK_OPTION_STRING instead. +# This disables typechecking in the 'configure' method, but it seems +# to be the best way to avoid the BWidget incompatibility for now. +# +test nulloptions-1.1 "Test null options" -body { + ttk::label .tl + .tl configure -width [.tl cget -width] +} -cleanup { destroy .tl } + +# +# <<NOTE-NULLOPTIONS-2>> This also means we have to (partially) disable +# the widget option / element option consistency checks. +# +test nulloptions-1.2 "Ensure workaround doesn't break -width" -body { + ttk::label .tl -text "x" -width 0 + set w1 [winfo reqwidth .tl] + .tl configure -width 10 + set w2 [winfo reqwidth .tl] + expr {$w2 > $w1} +} -result 1 -cleanup { destroy .tl } + +test nulloptions-1.3 "Exhaustive test" -body { + set readonlyOpts [list -class] + foreach widget $::ttk::widgets { + #puts "$widget" + ttk::$widget .w + foreach configspec [.w configure] { + set option [lindex $configspec 0] + if {[lsearch -exact $readonlyOpts $option] >= 0} { continue } + .w configure $option [.w cget $option] + } + destroy .w + } +} + +tcltest::cleanupTests diff --git a/tests/ttk/combobox.test b/tests/ttk/combobox.test new file mode 100644 index 0000000..3c20bd3 --- /dev/null +++ b/tests/ttk/combobox.test @@ -0,0 +1,48 @@ +# +# Tile package: combobox widget tests +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test combobox-1.0 "Combobox tests -- setup" -body { + ttk::combobox .cb +} -result .cb + +test combobox-1.1 "Bad -values list" -body { + .cb configure -values "bad \{list" +} -result "unmatched open brace in list" -returnCodes 1 + +test combobox-1.end "Combobox tests -- cleanup" -body { + destroy .cb +} + +test combobox-2.0 "current command" -body { + ttk::combobox .cb -values [list a b c d e a] + .cb current +} -result -1 + +test combobox-2.1 "current -- set index" -body { + .cb current 5 + .cb get +} -result a + +test combobox-2.2 "current -- change -values" -body { + .cb configure -values [list c b a d e] + .cb current +} -result 2 + +test combobox-2.3 "current -- change value" -body { + .cb set "b" + .cb current +} -result 1 + +test combobox-2.4 "current -- value not in list" -body { + .cb set "z" + .cb current +} -result -1 + +test combobox-end "Cleanup" -body { destroy .cb } + +tcltest::cleanupTests diff --git a/tests/ttk/entry.test b/tests/ttk/entry.test new file mode 100644 index 0000000..0e7acd2 --- /dev/null +++ b/tests/ttk/entry.test @@ -0,0 +1,262 @@ +# +# Tile package: entry widget tests +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +variable scrollInfo +proc scroll args { + global scrollInfo + set scrollInfo $args +} + +# Some of the tests raise background errors; +# override default bgerror to catch them. +# +variable bgerror "" +proc bgerror {error} { + variable bgerror $error + variable bgerrorInfo $::errorInfo + variable bgerrorCode $::errorCode +} + +# +test entry-1.1 "Create entry widget" -body { + ttk::entry .e +} -result .e + +test entry-1.2 "Insert" -body { + .e insert end abcde + .e get +} -result abcde + +test entry-1.3 "Selection" -body { + .e selection range 1 3 + selection get +} -result bc + +test entry-1.4 "Delete" -body { + .e delete 1 3 + .e get +} -result ade + +test entry-1.5 "Deletion - insert cursor" -body { + .e insert end abcde + .e icursor 0 + .e delete 0 end + .e index insert +} -result 0 + +test entry-1.6 "Deletion - insert cursor at end" -body { + .e insert end abcde + .e icursor end + .e delete 0 end + .e index insert +} -result 0 + +test entry-1.7 "Deletion - insert cursor in the middle " -body { + .e insert end abcde + .e icursor 3 + .e delete 0 end + .e index insert +} -result 0 + +test entry-1.done "Cleanup" -body { destroy .e } + +# Scrollbar tests. + +test entry-2.1 "Create entry before scrollbar" -body { + pack [ttk::entry .te -xscrollcommand [list .tsb set]] \ + -expand true -fill both + pack [ttk::scrollbar .tsb -orient horizontal -command [list .te xview]] \ + -expand false -fill x +} -cleanup {destroy .te .tsb} + +test entry-2.2 "Initial scroll position" -body { + ttk::entry .e -font fixed -width 5 -xscrollcommand scroll + .e insert end "0123456789" + pack .e; update idletasks + set scrollInfo +} -result {0 0.5} -cleanup { destroy .e } +# NOTE: result can vary depending on font. + +# Bounding box / scrolling tests. +test entry-3.0 "Series 3 setup" -body { + ttk::style theme use default + variable fixed fixed + variable cw [font measure $fixed a] + variable ch [font metrics $fixed -linespace] + variable bd 2 ;# border + padding + variable ux [font measure $fixed \u4e4e] + + pack [ttk::entry .e -font $fixed -width 20] + update +} + +test entry-3.1 "bbox widget command" -body { + .e delete 0 end + .e bbox 0 +} -result [list $bd $bd 0 $ch] + +test entry-3.2 "xview" -body { + .e delete 0 end; + .e insert end [string repeat "M" 40] + update idletasks + set result [.e xview] +} -result {0 0.5} + +test entry-3.last "Series 3 cleanup" -body { + destroy .e +} + +# Selection tests: + +test entry-4.0 "Selection test - setup" -body { + ttk::entry .e + .e insert end asdfasdf + .e selection range 0 end +} + +test entry-4.1 "Selection test" -body { + selection get +} -result asdfasdf + +test entry-4.2 "Disable -exportselection" -body { + .e configure -exportselection false + selection get +} -returnCodes error -result "PRIMARY selection doesn't exist*" -match glob + +test entry-4.3 "Reenable -exportselection" -body { + .e configure -exportselection true + selection get +} -result asdfasdf + +test entry-4.4 "Force selection loss" -body { + selection own . + .e index sel.first +} -returnCodes error -result "selection isn't in widget .e" + +test entry-4.5 "Allow selection changes if readonly" -body { + .e delete 0 end + .e insert end 0123456789 + .e selection range 0 end + .e configure -state readonly + .e selection range 2 4 + .e configure -state normal + list [.e index sel.first] [.e index sel.last] +} -result {2 4} + +test entry-4.6 "Disallow selection changes if disabled" -body { + .e delete 0 end + .e insert end 0123456789 + .e selection range 0 end + .e configure -state disabled + .e selection range 2 4 + .e configure -state normal + list [.e index sel.first] [.e index sel.last] +} -result {0 10} + +test entry-4.7 {sel.first and sel.last gravity} -body { + set result [list] + .e delete 0 end + .e insert 0 0123456789 + .e select range 2 6 + .e insert 2 XXX + lappend result [.e index sel.first] [.e index sel.last] + .e insert 6 YYY + lappend result [.e index sel.first] [.e index sel.last] [.e get] +} -result {5 9 5 12 01XXX2YYY3456789} + +# Self-destruct tests. + +test entry-5.1 {widget deletion while active} -body { + destroy .e + pack [ttk::entry .e] + update + .e config -xscrollcommand { destroy .e } + update idletasks + winfo exists .e +} -result 0 + +# TODO: test killing .e in -validatecommand, -invalidcommand, variable trace; + + +# -textvariable tests. + +test entry-6.1 {Update linked variable in write trace} -body { + proc override args { + global x + set x "Overridden!" + } + catch {destroy .e} + set x "" + trace variable x w override + ttk::entry .e -textvariable x + .e insert 0 "Some text" + set result [list $x [.e get]] + set result +} -result {Overridden! Overridden!} -cleanup { + unset x + rename override {} + destroy .e +} + +test entry-6.2 {-textvariable tests} -body { + set result [list] + ttk::entry .e -textvariable x + set x "text" + lappend result [.e get] + unset x + lappend result [.e get] + .e insert end "newtext" + lappend result [.e get] [set x] +} -result [list "text" "" "newtext" "newtext"] -cleanup { + destroy .e + unset -nocomplain x +} + +test entry-7.1 {Bad style options} -body { + ttk::style theme create entry-7.1 -settings { + ttk::style configure TEntry -foreground BadColor + ttk::style map TEntry -foreground {readonly AnotherBadColor} + ttk::style map TEntry -font {readonly ABadFont} + ttk::style map TEntry \ + -selectbackground {{} BadColor} \ + -selectforeground {{} BadColor} \ + -insertcolor {{} BadColor} + } + pack [ttk::entry .e -text "Don't crash"] + ttk::style theme use entry-7.1 + update + .e selection range 0 end + update + .e state readonly; + update +} -cleanup { destroy .e ; ttk::style theme use default } + +test entry-8.1 "Unset linked variable" -body { + variable foo "bar" + pack [ttk::entry .e -textvariable foo] + unset foo + .e insert end "baz" + list [.e cget -textvariable] [.e get] [set foo] +} -result [list foo "baz" "baz"] -cleanup { destroy .e } + +test entry-8.2 "Unset linked variable by deleting namespace" -body { + namespace eval ::test { variable foo "bar" } + pack [ttk::entry .e -textvariable ::test::foo] + namespace delete ::test + .e insert end "baz" ;# <== error here + list [.e cget -textvariable] [.e get] [set foo] +} -returnCodes error -result "*parent namespace doesn't exist*" -match glob +# '-result [list ::test::foo "baz" "baz"]' would also be sensible, +# but Tcl namespaces don't work that way. + +test entry-8.2a "Followup to test 8.2" -body { + .e cget -textvariable +} -result ::test::foo -cleanup { destroy .e } +# For 8.2a, -result {} would also be sensible. + +tcltest::cleanupTests diff --git a/tests/ttk/image.test b/tests/ttk/image.test new file mode 100644 index 0000000..b1f66bd --- /dev/null +++ b/tests/ttk/image.test @@ -0,0 +1,44 @@ +# +# $Id: image.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +# catch background errors: +# +if {[info procs bgerror] == "bgerror"} { rename bgerror {} } +array set BGerror { caught 0 message {} } +proc bgerror {message} { + variable BGerror + set BGerror(caught) 1 + set BGerror(message) $message +} +proc caughtbgerror {} { + variable BGerror + if {!$BGerror(caught)} { + error "No bgerror caught" + } + set BGerror(caught) 0 + return $BGerror(message) +} + +test image-1.1 "Bad image element" -body { + ttk::style element create BadImage image badimage + ttk::style layout BadImage { BadImage } + ttk::label .l -style BadImage + pack .l ; update + destroy .l + caughtbgerror +} -result {image "badimage" doesn't exist} + +test image-1.2 "Duplicate element" -setup { + image create photo test.element -width 10 -height 10 + ttk::style element create testElement image test.element +} -body { + ttk::style element create testElement image test.element +} -returnCodes 1 -result "Duplicate element testElement" + +# +tcltest::cleanupTests diff --git a/tests/ttk/labelframe.test b/tests/ttk/labelframe.test new file mode 100644 index 0000000..1dd5573 --- /dev/null +++ b/tests/ttk/labelframe.test @@ -0,0 +1,134 @@ +# +# $Id: labelframe.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test labelframe-1.0 "Setup" -body { + pack [ttk::labelframe .lf] -expand true -fill both +} + +test labelframe-2.1 "Can't use indirect descendant as labelwidget" -body { + ttk::frame .lf.t + ttk::checkbutton .lf.t.cb + .lf configure -labelwidget .lf.t.cb +} -returnCodes 1 -result "can't *" -match glob \ + -cleanup { destroy .lf.t } ; + +test labelframe-2.2 "Can't use toplevel as labelwidget" -body { + toplevel .lf.t + .lf configure -labelwidget .lf.t +} -returnCodes 1 -result "can't *" -match glob \ + -cleanup { destroy .lf.t } ; + +test labelframe-2.3 "Can't use non-windows as -labelwidget" -body { + .lf configure -labelwidget BogusWindowName +} -returnCodes 1 -result {bad window path name "BogusWindowName"} + +test labelframe-2.4 "Can't use nonexistent-windows as -labelwidget" -body { + .lf configure -labelwidget .nosuchwindow +} -returnCodes 1 -result {bad window path name ".nosuchwindow"} + + +### +# See also series labelframe-4.x +# +test labelframe-3.1 "Add child slave" -body { + checkbutton .lf.cb -text "abcde" + .lf configure -labelwidget .lf.cb + list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] +} -result [list 1 labelframe] + +test labelframe-3.2 "Remove child slave" -body { + .lf configure -labelwidget {} + list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] +} -result [list 0 {}] + +test labelframe-3.3 "Re-add child slave" -body { + .lf configure -labelwidget .lf.cb + list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] +} -result [list 1 labelframe] + +test labelframe-3.4 "Re-manage child slave" -body { + pack .lf.cb -side right + list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] [.lf cget -labelwidget] +} -result [list 1 pack {}] + +test labelframe-3.5 "Re-add child slave" -body { + .lf configure -labelwidget .lf.cb + list [update; winfo viewable .lf.cb] [winfo manager .lf.cb] +} -result [list 1 labelframe] + +test labelframe-3.6 "Destroy child slave" -body { + destroy .lf.cb + .lf cget -labelwidget +} -result {} + +### +# Re-run series labelframe-3.x with nonchild slaves. +# +# @@@ ODDITY, 14 Nov 2005: +# @@@ labelframe-4.1 fails if .cb is a [checkbutton], +# @@@ but seems to succeed if it's some other widget class. +# @@@ I suspect a race condition; unable to track it down ATM. +# +# @@@ FOLLOWUP: This *may* have been caused by a bug in ManagerIdleProc +# @@@ (see manager.c r1.11). There's still probably a race condition in here. +# +test labelframe-4.1 "Add nonchild slave" -body { + checkbutton .cb -text "abcde" + .lf configure -labelwidget .cb + update + list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb] + +} -result [list 1 1 labelframe] + +test labelframe-4.2 "Remove nonchild slave" -body { + .lf configure -labelwidget {} + update; + list [winfo ismapped .cb] [winfo viewable .cb] [winfo manager .cb] +} -result [list 0 0 {}] + +test labelframe-4.3 "Re-add nonchild slave" -body { + .lf configure -labelwidget .cb + list [update; winfo viewable .cb] [winfo manager .cb] +} -result [list 1 labelframe] + +test labelframe-4.4 "Re-manage nonchild slave" -body { + pack .cb -side right + list [update; winfo viewable .cb] \ + [winfo manager .cb] \ + [.lf cget -labelwidget] +} -result [list 1 pack {}] + +test labelframe-4.5 "Re-add nonchild slave" -body { + .lf configure -labelwidget .cb + list [update; winfo viewable .cb] \ + [winfo manager .cb] \ + [.lf cget -labelwidget] +} -result [list 1 labelframe .cb] + +test labelframe-4.6 "Destroy nonchild slave" -body { + destroy .cb + .lf cget -labelwidget +} -result {} + +test labelframe-5.0 "Cleanup" -body { + destroy .lf +} + +# 1342876 -- labelframe should raise sibling -labelwidget above self. +# +test labelframe-6.1 "Stacking order" -body { + toplevel .t + pack [ttk::checkbutton .t.x1] + pack [ttk::labelframe .t.lf -labelwidget [ttk::label .t.lb]] + pack [ttk::checkbutton .t.x2] + winfo children .t +} -cleanup { + destroy .t +} -result [list .t.x1 .t.lf .t.lb .t.x2] + +tcltest::cleanupTests diff --git a/tests/ttk/layout.test b/tests/ttk/layout.test new file mode 100644 index 0000000..4b69b3c --- /dev/null +++ b/tests/ttk/layout.test @@ -0,0 +1,29 @@ +# +# $Id: layout.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test layout-1.1 "Size computations for mixed-orientation layouts" -body { + ttk::style theme use default + + set block [image create photo -width 10 -height 10] + ttk::style element create block image $block + ttk::style layout Blocks { + border -children { block } -side left + border -children { block } -side top + border -children { block } -side bottom + } + ttk::style configure Blocks -borderwidth 1 -relief raised + ttk::button .b -style Blocks + + pack .b -expand true -fill both + + list [winfo reqwidth .b] [winfo reqheight .b] + +} -cleanup { destroy .b } -result [list 24 24] + + +tcltest::cleanupTests diff --git a/tests/ttk/misc.test b/tests/ttk/misc.test new file mode 100644 index 0000000..27b87d6 --- /dev/null +++ b/tests/ttk/misc.test @@ -0,0 +1,33 @@ +# +# $Id: misc.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test misc-1.0 "#1551500 -parent option in ttk::dialog doesn't work" -body { + ttk::dialog .dialog -parent . -type ok \ + -message "Something to say" -title "Let's see" + wm transient .dialog +} -result . -cleanup { destroy .dialog } + +test misc-1.1 "ttk::dialog w/no -parent option" -body { + toplevel .t + ttk::dialog .t.dialog -type ok + wm transient .t.dialog +} -result .t -cleanup { destroy .t } + +test misc-1.2 "Explicitly specify -parent" -body { + toplevel .t + ttk::dialog .t.dialog -type ok -parent . + wm transient .t.dialog +} -result . -cleanup { destroy .t } + +test misc-1.3 "Nontransient dialog" -body { + toplevel .t + ttk::dialog .t.dialog -type ok -parent "" + wm transient .t.dialog +} -result "" -cleanup { destroy .t } + +tcltest::cleanupTests diff --git a/tests/ttk/notebook.test b/tests/ttk/notebook.test new file mode 100644 index 0000000..ecb614a --- /dev/null +++ b/tests/ttk/notebook.test @@ -0,0 +1,387 @@ +# +# $Id: notebook.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test notebook-1.0 "Setup" -body { + ttk::notebook .nb +} -result .nb + +# +# Error handling tests: +# +test notebook-1.1 "Cannot add ancestor" -body { + .nb add . +} -returnCodes error -result "*" -match glob + +proc inoperative {args} {} + +inoperative test notebook-1.2 "Cannot add siblings" -body { + # This is legal now + .nb add [frame .sibling] +} -returnCodes error -result "*" -match glob + +test notebook-1.3 "Cannot add toplevel" -body { + .nb add [toplevel .nb.t] +} -cleanup { + destroy .t.nb +} -returnCodes 1 -match glob -result "can't add .nb.t*" + +test notebook-1.4 "Try to select bad tab" -body { + .nb select @6000,6000 +} -returnCodes 1 -match glob -result "* not found" + +# +# Now add stuff: +# +test notebook-2.0 "Add children" -body { + pack .nb -expand true -fill both + .nb add [frame .nb.foo] -text "Foo" + pack [label .nb.foo.l -text "Foo"] + + .nb add [frame .nb.bar -relief raised -borderwidth 2] -text "Bar" + pack [label .nb.bar.l -text "Bar"] + + .nb tabs +} -result [list .nb.foo .nb.bar] + +test notebook-2.1 "select pane" -body { + .nb select .nb.foo + update + list [winfo viewable .nb.foo] [winfo viewable .nb.bar] [.nb index current] +} -result [list 1 0 0] + +test notebook-2.2 "select another pane" -body { + .nb select 1 + update + list [winfo viewable .nb.foo] [winfo viewable .nb.bar] [.nb index current] +} -result [list 0 1 1] + +test notebook-2.3 "tab - get value" -body { + .nb tab .nb.foo -text +} -result "Foo" + +test notebook-2.4 "tab - set value" -body { + .nb tab .nb.foo -text "Changed Foo" + .nb tab .nb.foo -text +} -result "Changed Foo" + +test notebook-2.5 "tab - get all options" -body { + .nb tab .nb.foo +} -result [list \ + -padding 0 -sticky nsew \ + -state normal -text "Changed Foo" -image "" -compound none -underline -1] + +test notebook-4.1 "Test .nb index end" -body { + .nb index end +} -result 2 + +test notebook-4.2 "'end' is not a selectable index" -body { + .nb select end +} -returnCodes error -result "*" -match glob + +test notebook-4.3 "Select index out of range" -body { + .nb select 2 +} -returnCodes error -result "*" -match glob + +test notebook-4.4 "-padding option" -body { + .nb configure -padding "5 5 5 5" +} + +test notebook-4.end "Cleanup test suite 1-4.*" -body { destroy .nb } + +test notebook-5.1 "Virtual events" -body { + toplevel .t + set ::events [list] + bind .t <<NotebookTabChanged>> { lappend events changed %W } + + pack [set nb [ttk::notebook .t.nb]] -expand true -fill both; update + $nb add [frame $nb.f1] + $nb add [frame $nb.f2] + $nb add [frame $nb.f3] + + $nb select $nb.f1 + update; set events +} -result [list changed .t.nb] + +test notebook-5.2 "Virtual events, continued" -body { + set events [list] + $nb select $nb.f3 + update ; set events +} -result [list changed .t.nb] +# OR: [list deselected .t.nb.f1 selected .t.nb.f3 changed .t.nb] + +test notebook-5.3 "Disabled tabs" -body { + set events [list] + $nb tab $nb.f2 -state disabled + $nb select $nb.f2 + update + list $events [$nb index current] +} -result [list [list] 2] + +test notebook-5.4 "Reenable tab" -body { + set events [list] + $nb tab $nb.f2 -state normal + $nb select $nb.f2 + update + list $events [$nb index current] +} -result [list [list changed .t.nb] 1] + +test notebook-5.end "Virtual events, cleanup" -body { destroy .t } + +test notebook-6.0 "Select hidden tab" -setup { + set nb [ttk::notebook .nb] + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + $nb tab $nb.f1 -state hidden + lappend result [$nb tab $nb.f1 -state] + $nb select $nb.f1 + lappend result [$nb tab $nb.f1 -state] +} -result [list hidden normal] + +test notebook-6.1 "Hide selected tab" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb tab $nb.f2 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 2 0] + +# See 1370833 +test notebook-6.2 "Forget selected tab" -setup { + ttk::notebook .n + pack .n + label .n.l -text abc + .n add .n.l +} -body { + update + after 100 + .n forget .n.l + update ;# Yowch! +} -cleanup { + destroy .n +} -result {} + +test notebook-6.3 "Hide first tab when it's the current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f1 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f1] + $nb tab $nb.f1 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f1] +} -result [list 0 1 1 0] + +test notebook-6.4 "Forget first tab when it's the current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f1 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f1] + $nb forget $nb.f1 + lappend result [$nb index current] [winfo ismapped $nb.f1] +} -result [list 0 1 0 0] + +test notebook-6.5 "Hide last tab when it's the current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f3 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f3] + $nb tab $nb.f3 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f3] +} -result [list 2 1 1 0] + +test notebook-6.6 "Forget a middle tab when it's the current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb forget $nb.f2 + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 1 0] + +test notebook-6.7 "Hide a middle tab when it's the current" -setup { + pack [set nb [ttk::notebook .nb]]; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb tab $nb.f2 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 2 0] + +test notebook-6.8 "Forget a non-current tab < current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb forget $nb.f1 + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 0 1] + +test notebook-6.9 "Hide a non-current tab < current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb tab $nb.f1 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 1 1] + +test notebook-6.10 "Forget a non-current tab > current" -setup { + pack [set nb [ttk::notebook .nb]] ; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb forget $nb.f3 + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 1 1] + +test notebook-6.11 "Hide a non-current tab > current" -setup { + pack [set nb [ttk::notebook .nb]]; update + $nb add [ttk::frame $nb.f1] + $nb add [ttk::frame $nb.f2] + $nb add [ttk::frame $nb.f3] + $nb select $nb.f2 +} -cleanup { + destroy $nb +} -body { + set result [list] + lappend result [$nb index current] [winfo ismapped $nb.f2] + $nb tab $nb.f3 -state hidden + lappend result [$nb index current] [winfo ismapped $nb.f2] +} -result [list 1 1 1 1] + + +# +# Insert: +# +unset nb +test notebook-7.0 "insert - setup" -body { + pack [ttk::notebook .nb] + for {set i 0} {$i < 5} {incr i} { + .nb add [ttk::frame .nb.f$i] -text "$i" + } + .nb select .nb.f1 + list [.nb index current] [.nb tabs] +} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]] + +test notebook-7.1 "insert - move backwards" -body { + .nb insert 1 3 + list [.nb index current] [.nb tabs] +} -result [list 2 [list .nb.f0 .nb.f3 .nb.f1 .nb.f2 .nb.f4]] + +test notebook-7.2 "insert - move backwards again" -body { + .nb insert 1 3 + list [.nb index current] [.nb tabs] +} -result [list 3 [list .nb.f0 .nb.f2 .nb.f3 .nb.f1 .nb.f4]] + +test notebook-7.3 "insert - move backwards again" -body { + .nb insert 1 3 + list [.nb index current] [.nb tabs] +} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]] + +test notebook-7.4 "insert - move forwards" -body { + .nb insert 3 1 + list [.nb index current] [.nb tabs] +} -result [list 3 [list .nb.f0 .nb.f2 .nb.f3 .nb.f1 .nb.f4]] + +test notebook-7.5 "insert - move forwards again" -body { + .nb insert 3 1 + list [.nb index current] [.nb tabs] +} -result [list 2 [list .nb.f0 .nb.f3 .nb.f1 .nb.f2 .nb.f4]] + +test notebook-7.6 "insert - move forwards again" -body { + .nb insert 3 1 + list [.nb index current] [.nb tabs] +} -result [list 1 [list .nb.f0 .nb.f1 .nb.f2 .nb.f3 .nb.f4]] + +test notebook-7.7a "insert - current tab undisturbed" -body { + .nb select 0 + .nb insert 3 1 + .nb index current +} -result 0 + +test notebook-7.7b "insert - current tab undisturbed" -body { + .nb select 0 + .nb insert 1 3 + .nb index current +} -result 0 + +test notebook-7.7c "insert - current tab undisturbed" -body { + .nb select 4 + .nb insert 3 1 + .nb index current +} -result 4 + +test notebook-7.7d "insert - current tab undisturbed" -body { + .nb select 4 + .nb insert 1 3 + .nb index current +} -result 4 + +test notebook-7.end "insert - cleanup" -body { + destroy .nb +} + +tcltest::cleanupTests diff --git a/tests/ttk/panedwindow.test b/tests/ttk/panedwindow.test new file mode 100644 index 0000000..13a7e85 --- /dev/null +++ b/tests/ttk/panedwindow.test @@ -0,0 +1,201 @@ +# +# $Id: panedwindow.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + + +# Basic sanity checks: +# +test panedwindow-1.0 "Setup" -body { + ttk::panedwindow .pw +} -result .pw + +test panedwindow-1.1 "Make sure empty panedwindow doesn't crash" -body { + pack .pw -expand true -fill both + update +} + +test panedwindow-1.2 "Add a pane" -body { + .pw add [ttk::frame .pw.f1] + winfo manager .pw.f1 +} -result "paned" + +test panedwindow-1.3 "Steal pane" -body { + pack .pw.f1 -side bottom + winfo manager .pw.f1 +} -result "pack" + +test panedwindow-1.4 "Make sure empty panedwindow still doesn't crash" -body { + update +} + +test panedwindow-1.5 "Remanage pane" -body { + #XXX .pw insert 0 .pw.f1 + .pw add .pw.f1 + winfo manager .pw.f1 +} -result "paned" + +test panedwindow-1.6 "Forget pane" -body { + .pw forget .pw.f1 + winfo manager .pw.f1 +} -result "" + +test panedwindow-1.7 "Make sure empty panedwindow still still doesn't crash" -body { + update +} + +test panedwindow-1.8 "Re-forget pane" -body { + .pw forget .pw.f1 +} -returnCodes 1 -result ".pw.f1 is not managed by .pw" + +test panedwindow-1.end "Cleanup" -body { + destroy .pw +} + +# Resize behavior: +# +test panedwindow-2.1 "..." -body { + ttk::panedwindow .pw -orient horizontal + + .pw add [listbox .pw.l1] + .pw add [listbox .pw.l2] + .pw add [listbox .pw.l3] + .pw add [listbox .pw.l4] + + pack .pw -expand true -fill both + update + set w1 [winfo width .] + + # This should make the window shrink: + destroy .pw.l2 + + update + set w2 [winfo width .] + + expr {$w2 < $w1} +} -result 1 + +test panedwindow-2.2 "..., cont'd" -body { + + # This should keep the window from shrinking: + wm geometry . [wm geometry .] + + set rw2 [winfo reqwidth .pw] + + destroy .pw.l1 + update + + set w3 [winfo width .] + set rw3 [winfo reqwidth .pw] + + expr {$w3 == $w2 && $rw3 < $rw2} + # problem: [winfo reqwidth] shrinks, but sashes haven't moved + # since we haven't gotten a ConfigureNotify. + # How to (a) check for this, and (b) fix it? +} -result 1 + +test panedwindow-2.3 "..., cont'd" -body { + + .pw add [listbox .pw.l5] + update + set rw4 [winfo reqwidth .pw] + + expr {$rw4 > $rw3} +} -result 1 + +test panedwindow-2.end "Cleanup" -body { destroy .pw } + +# +# ... +# +test panedwindow-3.0 "configure pane" -body { + ttk::panedwindow .pw + .pw add [listbox .pw.lb1] + .pw add [listbox .pw.lb2] + .pw pane 1 -weight 2 + .pw pane 1 -weight +} -result 2 + +test panedwindow-3.1 "configure pane -- errors" -body { + .pw pane 1 -weight -4 +} -returnCodes 1 -match glob -result "-weight must be nonnegative" + +test panedwindow-3.2 "add pane -- errors" -body { + .pw add [ttk::label .pw.l] -weight -1 +} -returnCodes 1 -match glob -result "-weight must be nonnegative" + + +test panedwindow-3.end "cleanup" -body { destroy .pw } + + +test panedwindow-4.1 "forget" -body { + pack [ttk::panedwindow .pw -orient vertical] -expand true -fill both + .pw add [label .pw.l1 -text "L1"] + .pw add [label .pw.l2 -text "L2"] + .pw add [label .pw.l3 -text "L3"] + .pw add [label .pw.l4 -text "L4"] + + update + + .pw forget .pw.l1 + .pw forget .pw.l2 + .pw forget .pw.l3 + .pw forget .pw.l4 + update +} + +test panedwindow-4.2 "forget forgotten" -body { + .pw forget .pw.l1 +} -returnCodes 1 -result ".pw.l1 is not managed by .pw" + +# checkorder $winlist -- +# Ensure that Y coordinates windows in $winlist are strictly increasing. +# +proc checkorder {winlist} { + set pos -1 + foreach win $winlist { + set nextpos [winfo y $win] + if {$nextpos <= $pos} { + error "window $win out of order" + } + set pos $nextpos + } +} + +test panedwindow-4.3 "insert command" -body { + .pw insert end .pw.l1 + .pw insert end .pw.l3 + .pw insert 1 .pw.l2 + .pw insert end .pw.l4 + + update; + checkorder {.pw.l1 .pw.l2 .pw.l3 .pw.l4} +} + +test panedwindow-4.END "cleanup" -body { + destroy .pw +} + +# See #1292219 + +test panedwindow-5.1 "Propage Map/Unmap state to children" -body { + set result [list] + pack [ttk::panedwindow .pw] + .pw add [ttk::button .pw.b] + update + + lappend result [winfo ismapped .pw] [winfo ismapped .pw.b] + + pack forget .pw + update + lappend result [winfo ismapped .pw] [winfo ismapped .pw.b] + + set result +} -result [list 1 1 0 0] -cleanup { + destroy .pw +} + +tcltest::cleanupTests diff --git a/tests/ttk/progressbar.test b/tests/ttk/progressbar.test new file mode 100644 index 0000000..ead15f6 --- /dev/null +++ b/tests/ttk/progressbar.test @@ -0,0 +1,89 @@ +# +# $Id: progressbar.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + + +test progressbar-1.1 "Setup" -body { + ttk::progressbar .pb +} -result .pb + +test progressbar-1.2 "Linked variable" -body { + set PB 50 + .pb configure -variable PB + .pb cget -value +} -result 50 + +test progressbar-1.3 "Change linked variable" -body { + set PB 80 + .pb cget -value +} -result 80 + +test progressbar-1.4 "Set linked variable to bad value" -body { + set PB "bogus" + .pb instate invalid +} -result 1 + +test progressbar-1.4.1 "Set linked variable back to a good value" -body { + set PB 80 + .pb instate invalid +} -result 0 + +test progressbar-1.5 "Set -variable to illegal variable" -body { + set BAD "bogus" + .pb configure -variable BAD + .pb instate invalid +} -result 1 + +test progressbar-1.6 "Unset -variable" -body { + unset -nocomplain UNSET + .pb configure -variable UNSET + .pb instate disabled +} -result 1 + +test progressbar-2.0 "step command" -body { + .pb configure -variable {} ;# @@@ + .pb configure -value 5 -maximum 10 -mode determinate + .pb step + .pb cget -value +} -result 6.0 + +test progressbar-2.1 "step command, with stepamount" -body { + .pb step 3 + .pb cget -value +} -result 9.0 + +test progressbar-2.2 "step wraps at -maximum in determinate mode" -body { + .pb step + .pb cget -value +} -result 0.0 + +test progressbar-2.3 "step doesn't wrap in indeterminate mode" -body { + .pb configure -value 8 -maximum 10 -mode indeterminate + .pb step + .pb step + .pb step + .pb cget -value +} -result 11.0 + +test progressbar-2.4 "step with linked variable" -body { + .pb configure -variable PB ;# @@@ + set PB 5 + .pb step + set PB +} -result 6.0 + +test progressbar-2.5 "error in write trace" -body { + trace variable PB w { error "YIPES!" ;# } + .pb step + set PB ;# NOTREACHED +} -cleanup { unset PB } -returnCodes 1 -match glob -result "*YIPES!" + +test progressbar-end "Cleanup" -body { + destroy .pb +} + +tcltest::cleanupTests diff --git a/tests/ttk/scrollbar.test b/tests/ttk/scrollbar.test new file mode 100644 index 0000000..f91659a --- /dev/null +++ b/tests/ttk/scrollbar.test @@ -0,0 +1,42 @@ +# +# $Id: scrollbar.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +test scrollbar-1.0 "Setup" -body { + ttk::scrollbar .tsb +} -result .tsb + +test scrollbar-1.1 "Set method" -body { + .tsb set 0.2 0.4 + .tsb get +} -result [list 0.2 0.4] + +test scrollbar-1.2 "Set orientation" -body { + .tsb configure -orient vertical + set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb] + expr {$h > $w} +} -result 1 + +test scrollbar-1.3 "Change orientation" -body { + .tsb configure -orient horizontal + set w [winfo reqwidth .tsb] ; set h [winfo reqheight .tsb] + expr {$h < $w} +} -result 1 + +# +# Scale tests: +# + +test scale-1.0 "Self-destruction" -body { + trace variable v w { destroy .s ;# } + ttk::scale .s -variable v + pack .s ; update + .s set 1 ; update +} -returnCodes 1 -match glob -result "*" + +tcltest::cleanupTests + diff --git a/tests/ttk/treetags.test b/tests/ttk/treetags.test new file mode 100644 index 0000000..2161395 --- /dev/null +++ b/tests/ttk/treetags.test @@ -0,0 +1,77 @@ +# +# $Id: treetags.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +testConstraint treeview [llength [info commands ttk::treeview]] +testConstraint nyi 0 + +test treetags-1.0 "Setup" -constraints treeview -body { + set tv [ttk::treeview .tv] + .tv insert {} end -id item1 -text "Item 1" + pack .tv +} + +test treetags-1.1 "Bad tag list" -constraints treeview -body { + $tv item item1 -tags {bad {list}here bad} +} -returnCodes error -result "list element in braces *" -match glob + +test treetags-1.2 "Good tag list" -constraints treeview -body { + $tv item item1 -tags tag1 + $tv item item1 -tags +} -result [list tag1] + +test treetags-1.3 "Bad events" -constraints treeview -body { + $tv tag bind bad <Enter> { puts "Entered!" } +} -returnCodes 1 -result "unsupported event <Enter>*" -match glob + +test treetags-2.0 "tag bind" -constraints treeview -body { + $tv tag bind tag1 <KeyPress> {set ::KEY %A} + $tv tag bind tag1 <KeyPress> +} -result {set ::KEY %A} + +test treetags-2.1 "Events delivered to tags" -constraints treeview -body { + focus -force $tv ; update ;# needed so [event generate] delivers KeyPress + $tv focus item1 + event generate .tv <KeyPress-a> + set ::KEY +} -result a + +test treetags-2.2 "Events delivered to correct tags" -constraints treeview -body { + $tv insert {} end -id item2 -tags tag2 + $tv tag bind tag2 <KeyPress> [list set ::KEY2 %A] + + $tv focus item1 + event generate $tv <KeyPress-b> + $tv focus item2 + event generate $tv <KeyPress-c> + + list $::KEY $::KEY2 +} -result [list b c] + +test treetags-2.3 "Virtual events delivered to focus item" -constraints treeview -body { + set ::bong 0 + $tv tag bind tag2 <<Bing>> { incr bong } + $tv focus item2 + event generate $tv <<Bing>> + $tv focus item1 + event generate $tv <<Bing>> + set bong +} -result 1 + + +test treetags-3.0 "tag configure" -constraints treeview -body { + $tv tag configure tag1 -foreground blue -background red +} -result {} + +test treetags-3.1 "tag configure" -constraints treeview -body { + $tv tag configure tag1 -foreground +} -result [list blue] + + +test treetags-end "Cleanup" -constraints treeview -body { destroy .tv } + +tcltest::cleanupTests diff --git a/tests/ttk/treeview.test b/tests/ttk/treeview.test new file mode 100644 index 0000000..ac0778c --- /dev/null +++ b/tests/ttk/treeview.test @@ -0,0 +1,494 @@ +# +# $Id: treeview.test,v 1.1 2006/10/31 01:42:27 hobbs Exp $ +# +# [7Jun2005] TO CHECK: [$tv see {}] -- shouldn't work (at least, shouldn't do +# what it currently does) +# + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +testConstraint treeview [llength [info commands ttk::treeview]] + +# consistencyCheck -- +# Traverse the tree to make sure the item data structures +# are properly linked. +# +# Since [$tv children] follows ->next links and [$tv index] +# follows ->prev links, this should cover all invariants. +# +proc consistencyCheck {tv {item {}}} { + if {![llength [info commands ttk::treeview]]} { return } + set i 0; + foreach child [$tv children $item] { + assert {[$tv parent $child] == $item} "parent $child = $item" + assert {[$tv index $child] == $i} "index $child [$tv index $child]=$i" + incr i + consistencyCheck $tv $child + } +} + +proc assert {expr {message ""}} { + if {![uplevel 1 [list expr $expr]]} { + set error "PANIC! PANIC! PANIC: $message ($expr failed)" + puts stderr $error + error $error + } +} + +test treeview-0 "treeview test - setup" -constraints treeview -body { + ttk::treeview .tv -columns {a b c} + pack .tv -expand true -fill both + update +} + +test treeview-1.1 "columns" -constraints treeview -body { + .tv configure -columns {a b c} +} + +test treeview-1.2 "Bad columns" -constraints treeview -body { + #.tv configure -columns {illegal "list"value} + ttk::treeview .badtv -columns {illegal "list"value} +} -returnCodes 1 -result "list element in quotes followed by*" -match glob + +test treeview-1.3 "bad displaycolumns" -constraints treeview -body { + .tv configure -displaycolumns {a b d} +} -returnCodes 1 -result "Invalid column index d" + +test treeview-1.4 "more bad displaycolumns" -constraints treeview -body { + .tv configure -displaycolumns {1 2 3} +} -returnCodes 1 -result "Column index 3 out of bounds" + +test treeview-1.5 "Don't forget to check negative numbers" -constraints treeview -body { + .tv configure -displaycolumns {1 -2 3} +} -returnCodes 1 -result "Column index -2 out of bounds" + +# Item creation. +# +test treeview-2.1 "insert -- not enough args" -constraints treeview -body { + .tv insert +} -returnCodes 1 -result "wrong # args: *" -match glob + +test treeview-2.3 "insert -- bad integer index" -constraints treeview -body { + .tv insert {} badindex +} -returnCodes 1 -result "expected integer *" -match glob + +test treeview-2.4 "insert -- bad parent node" -constraints treeview -body { + .tv insert badparent end +} -returnCodes 1 -result "Item badparent not found" -match glob + +test treeview-2.5 "insert -- finaly insert a node" -constraints treeview -body { + .tv insert {} end -id newnode -text "New node" +} -result newnode + +test treeview-2.6 "insert -- make sure node was inserted" -constraints treeview -body { + .tv children {} +} -result [list newnode] + +test treeview-2.7 "insert -- prevent duplicate node names" -constraints treeview -body { + .tv insert {} end -id newnode +} -returnCodes 1 -result "Item newnode already exists" + +test treeview-2.8 "insert -- new node at end" -constraints treeview -body { + .tv insert {} end -id lastnode + consistencyCheck .tv + .tv children {} +} -result [list newnode lastnode] + +consistencyCheck .tv + +test treeview-2.9 "insert -- new node at beginning" -constraints treeview -body { + .tv insert {} 0 -id firstnode + consistencyCheck .tv + .tv children {} +} -result [list firstnode newnode lastnode] + +test treeview-2.10 "insert -- one more node" -constraints treeview -body { + .tv insert {} 2 -id onemore + consistencyCheck .tv + .tv children {} +} -result [list firstnode newnode onemore lastnode] + +test treeview-2.11 "insert -- and another one" -constraints treeview -body { + .tv insert {} 2 -id anotherone + consistencyCheck .tv + .tv children {} +} -result [list firstnode newnode anotherone onemore lastnode] + +test treeview-2.12 "insert -- one more at end" -constraints treeview -body { + .tv insert {} end -id newlastone + consistencyCheck .tv + .tv children {} +} -result [list firstnode newnode anotherone onemore lastnode newlastone] + +test treeview-2.13 "insert -- one more at beginning" -constraints treeview -body { + .tv insert {} 0 -id newfirstone + consistencyCheck .tv + .tv children {} +} -result [list newfirstone firstnode newnode anotherone onemore lastnode newlastone] + +test treeview-2.14 "insert -- bad options" -constraints treeview -body { + .tv insert {} end -badoption foo +} -returnCodes 1 -result {unknown option "-badoption"} + +test treeview-2.15 "insert -- at position 0 w/no children" -constraints treeview -body { + .tv insert newnode 0 -id newnode.n2 -text "Foo" + .tv children newnode +} -result newnode.n2 ;# don't crash + +test treeview-2.16 "insert -- insert way past end" -constraints treeview -body { + .tv insert newnode 99 -id newnode.n3 -text "Foo" + consistencyCheck .tv + .tv children newnode +} -result [list newnode.n2 newnode.n3] + +test treeview-2.17 "insert -- insert before beginning" -constraints treeview -body { + .tv insert newnode -1 -id newnode.n1 -text "Foo" + consistencyCheck .tv + .tv children newnode +} -result [list newnode.n1 newnode.n2 newnode.n3] + +### +# +test treeview-3.1 "parent" -constraints treeview -body { + .tv parent newnode.n1 +} -result newnode +test treeview-3.2 "parent - top-level node" -constraints treeview -body { + .tv parent newnode +} -result {} +test treeview-3.3 "parent - root node" -constraints treeview -body { + .tv parent {} +} -result {} +test treeview-3.4 "index" -constraints treeview -body { + list [.tv index newnode.n3] [.tv index newnode.n2] [.tv index newnode.n1] +} -result [list 2 1 0] +test treeview-3.5 "index - exhaustive test" -constraints treeview -body { + set result [list] + foreach item [.tv children {}] { + lappend result [.tv index $item] + } + set result +} -result [list 0 1 2 3 4 5 6] + +test treeview-3.6 "detach" -constraints treeview -body { + .tv detach newnode + consistencyCheck .tv + .tv children {} +} -result [list newfirstone firstnode anotherone onemore lastnode newlastone] +# XREF: treeview-2.13 + +test treeview-3.7 "detach didn't screw up internal links" -constraints treeview -body { + consistencyCheck .tv + set result [list] + foreach item [.tv children {}] { + lappend result [.tv index $item] + } + set result +} -result [list 0 1 2 3 4 5] + +test treeview-3.8 "detached node has no parent, index 0" -constraints treeview -body { + list [.tv parent newnode] [.tv index newnode] +} -result [list {} 0] +# @@@ Can't distinguish detached nodes from first root node + +test treeview-3.9 "detached node's children undisturbed" -constraints treeview -body { + .tv children newnode +} -result [list newnode.n1 newnode.n2 newnode.n3] + +test treeview-3.10 "detach is idempotent" -constraints treeview -body { + .tv detach newnode + consistencyCheck .tv + .tv children {} +} -result [list newfirstone firstnode anotherone onemore lastnode newlastone] + +test treeview-3.11 "Can't detach root item" -constraints treeview -body { + .tv detach [list {}] + update + consistencyCheck .tv +} -returnCodes 1 -result "Cannot detach root item" +consistencyCheck .tv + +test treeview-3.12 "Reattach" -constraints treeview -body { + .tv move newnode {} end + consistencyCheck .tv + .tv children {} +} -result [list newfirstone firstnode anotherone onemore lastnode newlastone newnode] + +# Bug # ????? +test treeview-3.13 "Re-reattach" -constraints treeview -body { + .tv move newnode {} end + consistencyCheck .tv + .tv children {} +} -result [list newfirstone firstnode anotherone onemore lastnode newlastone newnode] + +catch { + .tv insert newfirstone end -id x1 + .tv insert newfirstone end -id x2 + .tv insert newfirstone end -id x3 +} + +test treeview-3.14 "Duplicated entry in children list" -constraints treeview -body { + .tv children newfirstone [list x3 x1 x2 x3] + # ??? Maybe this should raise an error? + consistencyCheck .tv + .tv children newfirstone +} -result [list x3 x1 x2] + +test treeview-3.14.1 "Duplicated entry in children list" -constraints treeview -body { + .tv children newfirstone [list x1 x2 x3 x3 x2 x1] + consistencyCheck .tv + .tv children newfirstone +} -result [list x1 x2 x3] + +test treeview-3.15 "Consecutive duplicate entries in children list" -constraints treeview -body { + .tv children newfirstone [list x1 x2 x2 x3] + consistencyCheck .tv + .tv children newfirstone +} -result [list x1 x2 x3] + +test treeview-3.16 "Insert child after self" -constraints treeview -body { + .tv move x2 newfirstone 1 + consistencyCheck .tv + .tv children newfirstone +} -result [list x1 x2 x3] + +test treeview-3.17 "Insert last child after self" -constraints treeview -body { + .tv move x3 newfirstone 2 + consistencyCheck .tv + .tv children newfirstone +} -result [list x1 x2 x3] + +test treeview-3.18 "Insert last child after end" -constraints treeview -body { + .tv move x3 newfirstone 3 + consistencyCheck .tv + .tv children newfirstone +} -result [list x1 x2 x3] + + +test treeview-4.1 "opened - initial state" -constraints treeview -body { + .tv item newnode -open +} -result 0 +test treeview-4.2 "opened - open node" -constraints treeview -body { + .tv item newnode -open 1 + .tv item newnode -open +} -result 1 +test treeview-4.3 "opened - closed node" -constraints treeview -body { + .tv item newnode -open 0 + .tv item newnode -open +} -result 0 + +test treeview-5.1 "item -- error checks" -constraints treeview -body { + .tv item newnode -text "Bad values" -values "{bad}list" +} -returnCodes 1 -result "list element in braces followed by*" -match glob + +test treeview-5.2 "item -- error leaves options unchanged " -constraints treeview -body { + .tv item newnode -text +} -result "New node" + +test treeview-5.3 "Heading" -constraints treeview -body { + .tv heading #0 -text "Heading" +} + +test treeview-5.4 "get cell" -constraints treeview -body { + set l [list a b c] + .tv item newnode -values $l + .tv set newnode 1 +} -result b + +test treeview-5.5 "set cell" -constraints treeview -body { + .tv set newnode 1 XXX + .tv item newnode -values +} -result [list a XXX c] + +test treeview-5.6 "set illegal cell" -constraints treeview -body { + .tv set newnode #0 YYY +} -returnCodes 1 -result "Display column #0 cannot be set" + +test treeview-5.7 "set illegal cell" -constraints treeview -body { + .tv set newnode 3 YY ;# 3 == current #columns +} -returnCodes 1 -result "Column index 3 out of bounds" + +test treeview-5.8 "set display columns" -constraints treeview -body { + .tv configure -displaycolumns [list 2 1 0] + .tv set newnode #1 X + .tv set newnode #2 Y + .tv set newnode #3 Z + .tv item newnode -values +} -result [list Z Y X] + +test treeview-5.9 "display columns part 2" -constraints treeview -body { + list [.tv column #1 -id] [.tv column #2 -id] [.tv column #3 -id] +} -result [list c b a] + +test treeview-5.10 "cannot set column -id" -constraints treeview -body { + .tv column #1 -id X +} -returnCodes 1 -result "Attempt to change read-only option" + +test treeview-5.11 "get" -constraints treeview -body { + .tv set newnode #1 +} -result X + +test treeview-5.12 "get dictionary" -constraints treeview -body { + .tv set newnode +} -result [list a Z b Y c X] + +test treeview-5.13 "get, no value" -constraints treeview -body { + set newitem [.tv insert {} end] + set result [.tv set $newitem #1] + .tv delete $newitem + set result +} -result {} + + +test treeview-6.1 "deletion - setup" -constraints treeview -body { + .tv insert {} end -id dtest + foreach id [list a b c d e] { + .tv insert dtest end -id $id + } + .tv children dtest +} -result [list a b c d e] + +test treeview-6.1 "delete" -constraints treeview -body { + .tv delete b + consistencyCheck .tv + list [.tv exists b] [.tv children dtest] +} -result [list 0 [list a c d e]] + +consistencyCheck .tv + +test treeview-6.2 "delete - duplicate items in list" -constraints treeview -body { + .tv delete [list a e a e] + consistencyCheck .tv + .tv children dtest +} -result [list c d] + +test treeview-6.3 "delete - descendants removed" -constraints treeview -body { + .tv insert c end -id c1 + .tv insert c end -id c2 + .tv insert c1 end -id c11 + consistencyCheck .tv + .tv delete c + consistencyCheck .tv + list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11] +} -result [list 0 0 0 0] + +test treeview-6.4 "delete - delete parent and descendants" -constraints treeview -body { + .tv insert dtest end -id c + .tv insert c end -id c1 + .tv insert c end -id c2 + .tv insert c1 end -id c11 + consistencyCheck .tv + .tv delete [list c c1 c2 c11] + consistencyCheck .tv + list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11] +} -result [list 0 0 0 0] + +test treeview-6.5 "delete - delete descendants and parent" -constraints treeview -body { + .tv insert dtest end -id c + .tv insert c end -id c1 + .tv insert c end -id c2 + .tv insert c1 end -id c11 + consistencyCheck .tv + .tv delete [list c11 c1 c2 c] + consistencyCheck .tv + list [.tv exists c] [.tv exists c1] [.tv exists c2] [.tv exists c11] +} -result [list 0 0 0 0] + +test treeview-6.6 "delete - end" -constraints treeview -body { + consistencyCheck .tv + .tv children dtest +} -result [list d] + +test treeview-7.1 "move" -constraints treeview -body { + .tv insert d end -id d1 + .tv insert d end -id d2 + .tv insert d end -id d3 + .tv move d3 d 0 + consistencyCheck .tv + .tv children d +} -result [list d3 d1 d2] + +test treeview-7.2 "illegal move" -constraints treeview -body { + .tv move d d2 end +} -returnCodes 1 -result "Cannot insert d as a descendant of d2" + +test treeview-7.3 "illegal move has no effect" -constraints treeview -body { + consistencyCheck .tv + .tv children d +} -result [list d3 d1 d2] + +test treeview-7.4 "Replace children" -constraints treeview -body { + .tv children d [list d3 d2 d1] + consistencyCheck .tv + .tv children d +} -result [list d3 d2 d1] + +test treeview-7.5 "replace children - precondition" -constraints treeview -body { + # Just check to make sure the test suite so far has left + # us in the state we expect to be in: + list [.tv parent newnode] [.tv children newnode] +} -result [list {} [list newnode.n1 newnode.n2 newnode.n3]] + +test treeview-7.6 "Replace children - illegal move" -constraints treeview -body { + .tv children newnode.n1 [list newnode.n1 newnode.n2 newnode.n3] +} -returnCodes 1 -result "Cannot insert newnode.n1 as a descendant of newnode.n1" + +consistencyCheck .tv + +test treeview-8.0 "Selection set" -constraints treeview -body { + .tv selection set [list newnode.n1 newnode.n3 newnode.n2] + .tv selection +} -result [list newnode.n1 newnode.n2 newnode.n3] + +test treeview-8.1 "Selection add" -constraints treeview -body { + .tv selection add [list newnode] + .tv selection +} -result [list newnode newnode.n1 newnode.n2 newnode.n3] + +test treeview-8.2 "Selection toggle" -constraints treeview -body { + .tv selection toggle [list newnode.n2 d3] + .tv selection +} -result [list newnode newnode.n1 newnode.n3 d3] + +test treeview-8.3 "Selection remove" -constraints treeview -body { + .tv selection remove [list newnode.n2 d3] + .tv selection +} -result [list newnode newnode.n1 newnode.n3] + +test treeview-8.4 "Selection - clear" -constraints treeview -body { + .tv selection set {} + .tv selection +} -result {} + +test treeview-8.5 "Selection - bad operation" -constraints treeview -body { + .tv selection badop foo +} -returnCodes 1 -match glob -result {bad selection operation "badop": must be *} + +### NEED: more tests for see/yview/scrolling + +proc scrollcallback {args} { + set ::scrolldata $args +} +test treeview-9.0 "scroll callback - empty tree" -constraints treeview -body { + .tv configure -yscrollcommand scrollcallback + .tv delete [.tv children {}] + update + set ::scrolldata +} -result [list 0 1] + +### NEED: tests for focus item, selection + + +### Misc. tests: + +destroy .tv +test treeview-10.1 "Root node properly initialized (#1541739)" -setup { + ttk::treeview .tv + .tv insert {} end -id a + .tv see a +} -cleanup { + destroy .tv +} -constraints treeview + +tcltest::cleanupTests diff --git a/tests/ttk/ttk.test b/tests/ttk/ttk.test new file mode 100644 index 0000000..1532a24 --- /dev/null +++ b/tests/ttk/ttk.test @@ -0,0 +1,594 @@ + +package require Tk 8.5 +package require tcltest ; namespace import -force tcltest::* +loadTestedCommands + +proc skip args {} +proc ok {} { return } + +proc bgerror {error} { + variable bgerror $error + variable bgerrorInfo $::errorInfo + variable bgerrorCode $::errorCode +} + +# Self-destruct tests. +# Do these early, so any memory corruption has a longer time to cause a crash. +# +proc selfdestruct {w args} { + destroy $w +} +test ttk-6.1 "Self-destructing checkbutton" -body { + pack [ttk::checkbutton .sd -text "Self-destruction" -variable ::sd] + trace variable sd w [list selfdestruct .sd] + update + .sd invoke +} -returnCodes 1 +test ttk-6.2 "Checkbutton self-destructed" -body { + winfo exists .sd +} -result 0 + +test ttk-6.3 "Test package cleanup" -body { + interp create foo + foo eval { if {[catch {package require Tk}]} { load {} Tk } } + foo eval { destroy . } + interp delete foo +} + +test ttk-6.4 "Defeat evil intentions" -body { + trace variable OUCH r { kill.b } + proc kill.b {args} { destroy .b } + pack [ttk::checkbutton .b] + .b configure -variable OUCH + # At this point, .b should be gone. + .b invoke + list [set OUCH] [winfo exists .b] + # Mostly we just care that we haven't crashed the interpreter. + # +} -returnCodes error -match glob -result "*" + +test ttk-6.5 "Clean up -textvariable traces" -body { + foreach class {ttk::button ttk::checkbutton ttk::radiobutton} { + $class .b1 -textvariable V + set V "asdf" + destroy .b1 + set V "" + } +} + +test ttk-6.6 "Bad color spec in styles" -body { + pack [ttk::button .b1 -text Hi!] + ttk::style configure TButton -foreground badColor + event generate .b1 <Expose> + update + ttk::style configure TButton -foreground black + destroy .b1 + set ::bgerror +} -result {unknown color name "badColor"} + +# This should move to be a standard test per widget test file +test ttk-6.7 "Basic destruction test" -body { + foreach widget { + button checkbutton radiobutton sizegrip separator notebook + progressbar panedwindow scrollbar + } { + ttk::$widget .w + pack .w + destroy .w + } +} + +test ttk-6.8 "Button command removes itself" -body { + ttk::button .b -command ".b configure -command {}; set ::A {it worked}" + .b invoke + destroy .b + set ::A +} -result {it worked} + +# +# + +test ttk-6.9 "Bad font spec in styles" -setup { + ttk::style theme create badfont -settings { + ttk::style configure . -font {Helvetica 12 Bogus} + } + ttk::style theme use badfont +} -cleanup { + ttk::style theme use default +} -body { + pack [ttk::label .l -text Hi!] + event generate .l <Expose> + update + destroy .l + set ::bgerror +} -result {unknown font style "Bogus"} + +# +# Basic tests. +# + +test ttk-1.1 "Create button" -body { + pack [ttk::button .t] -expand true -fill both + update +} + +test ttk-1.2 "Check style" -body { + .t cget -style +} -result {} + + +test ttk-1.4 "Restore default style" -body { + .t cget -style +} -result "" + +proc checkstate {w} { + foreach statespec { + {!active !disabled} + {!active disabled} + {active !disabled} + {active disabled} + active + disabled + } { + lappend result [$w instate $statespec] + } + set result +} + +# NB: this will fail if the top-level window pops up underneath the cursor +test ttk-2.0 "Check state" -body { + checkstate .t +} -result [list 1 0 0 0 0 0] + +test ttk-2.1 "Change state" -body { + .t state active +} -result !active + +test ttk-2.2 "Check state again" -body { + checkstate .t +} -result [list 0 0 1 0 1 0] + +test ttk-2.3 "Change state again" -body { + .t state {!active disabled} +} -result {active !disabled} + +test ttk-2.4 "Check state again" -body { + checkstate .t +} -result [list 0 1 0 0 0 1] + +test ttk-2.5 "Change state again" -body { + .t state !disabled +} -result {disabled} + +test ttk-2.6 "instate scripts, false" -body { + set x 0 + .t instate disabled { set x 1 } + set x +} -result 0 + +test ttk-2.7 "instate scripts, true" -body { + set x 0 + .t instate !disabled { set x 1 } + set x +} -result 1 + + +# misc. error detection +test ttk-3.0 "Bad option" -body { + ttk::button .bad -badoption foo +} -returnCodes 1 -result {unknown option "-badoption"} -match glob + +test ttk-3.1 "Make sure widget command not created" -body { + .bad state disabled +} -returnCodes 1 -result {invalid command name ".bad"} -match glob + +test ttk-3.2 "Propagate errors from variable traces" -body { + set A 0 + trace add variable A write {error "failure" ;# } + ttk::checkbutton .cb -variable A + .cb invoke +} -cleanup { + unset ::A ; destroy .cb +} -returnCodes error -result {can't set "A": failure} + +# Test resource allocation +# (@@@ "-font" is a compatibility option now, so tests 4.1-4.3 +# don't really test anything useful at the moment.) +# + +test ttk-4.0 "Setup" -body { + catch { destroy .t } + pack [ttk::label .t -text "Button 1"] + testConstraint fontOption [expr ![catch { set prevFont [.t cget -font] }]] + ok +} + +test ttk-4.1 "Change font" -constraints fontOption -body { + .t configure -font "Helvetica 18 bold" +} +test ttk-4.2 "Check font" -constraints fontOption -body { + .t cget -font +} -result "Helvetica 18 bold" + +test ttk-4.3 "Restore font" -constraints fontOption -body { + .t configure -font $prevFont +} + +test ttk-4.4 "Bad resource specifications" -body { + ttk::style theme settings alt { + ttk::style configure TButton -font {Bad font} + # @@@ it would be best to raise an error at this point, + # @@@ but that's not really feasible in the current framework. + } + pack [ttk::button .tb1 -text "Ouch"] + ttk::style theme use alt + update; + # As long as we haven't crashed, everything's OK + ttk::style theme settings alt { + ttk::style configure TButton -font TkDefaultFont + } + ttk::style theme use default + destroy .tb1 +} + +# +# checkbutton tests +# +test ttk-5.1 "Checkbutton check" -body { + pack [ttk::checkbutton .cb -text "TCheckbutton" -variable cb] +} +test ttk-5.2 "Checkbutton invoke" -body { + .cb invoke + list [set ::cb] [.cb instate selected] +} -result [list 1 1] +test ttk-5.3 "Checkbutton reinvoke" -body { + .cb invoke + list [set ::cb] [.cb instate selected] +} -result [list 0 0] + +test ttk-5.4 "Checkbutton variable" -body { + set result [] + set ::cb 1 + lappend result [.cb instate selected] + set ::cb 0 + lappend result [.cb instate selected] +} -result {1 0} + +test ttk-5.5 "Unset checkbutton variable" -body { + set result [] + unset ::cb + lappend result [.cb instate alternate] [info exists ::cb] + set ::cb 1 + lappend result [.cb instate alternate] [info exists ::cb] +} -result {1 0 0 1} + +# See #1257319 +test ttk-5.6 "Checkbutton default variable" -body { + destroy .cb ; unset -nocomplain {} ; set result [list] + ttk::checkbutton .cb -onvalue on -offvalue off + lappend result [.cb cget -variable] [info exists .cb] [.cb state] + .cb invoke + lappend result [info exists .cb] [set .cb] [.cb state] + .cb invoke + lappend result [info exists .cb] [set .cb] [.cb state] +} -result [list .cb 0 alternate 1 on selected 1 off {}] + +# +# radiobutton tests +# +test ttk-7.1 "Radiobutton check" -body { + pack \ + [ttk::radiobutton .rb1 -text "One" -variable choice -value 1] \ + [ttk::radiobutton .rb2 -text "Two" -variable choice -value 2] \ + [ttk::radiobutton .rb3 -text "Three" -variable choice -value 3] \ + ; +} +test ttk-7.2 "Radiobutton invoke" -body { + .rb1 invoke + set ::choice +} -result 1 + +test ttk-7.3 "Radiobutton state" -body { + .rb1 instate selected +} -result 1 + +test ttk-7.4 "Other radiobutton invoke" -body { + .rb2 invoke + set ::choice +} -result 2 + +test ttk-7.5 "Other radiobutton state" -body { + .rb2 instate selected +} -result 1 + +test ttk-7.6 "First radiobutton state" -body { + .rb1 instate selected +} -result 0 + +test ttk-7.6 "Unset radiobutton variable" -body { + unset ::choice + list [info exists ::choice] [.rb1 instate alternate] [.rb2 instate alternate] +} -result {0 1 1} + +test ttk-7.6 "Reset radiobutton variable" -body { + set ::choice 2 + list [info exists ::choice] [.rb1 instate alternate] [.rb2 instate alternate] +} -result {1 0 0} + +# +# -compound tests: +# +variable iconData \ +{R0lGODlhIAAgAKIAANnZ2YQAAP8AAISEhP///////////////yH5BAEAAAAALAAAAAAgACAA +AAP/CLoMGLqKoMvtGIqiqxEYCLrcioGiyxwIusyBgaLLLRiBoMsQKLrcjYGgu4Giy+2CAkFX +A0WX2wXFIOgGii7trkCEohsDCACBoktEKLpKhISiGwAIECiqSKooukiqKKoxgACBooukKiIo +SKooujGDECi6iqQqsopEV2MQAkV3kXQZRXdjEAJFl5F0FUWXY3ACRZcFSRdFlyVwJlB0WZB0 +UXRZAmcCRZeRdBVFl2NwAkV3kXQZRXdjcAJFV5FURVaR6GoMDgSKLpKqiKAgqaLoxgwOBIoq +kiqKLpIqimrM4ECg6BIRiq4SIaHoxgyCBoou7a5AhKIbMzgAAIGiy+2CTWJmBhAAAkWX2wXF +zCDoBooud2PMDIKuRqDocgtGzMwg6O4Eii5z4Kgi6DIMhqLoagQGjiqCLvPgYOgqji6CLrfi +6DIj6HI7jq4i6DIkADs=} + +variable compoundStrings {text image center top bottom left right none} + +if {0} { + proc now {} { set ::now [clock clicks -milliseconds] } + proc tick {} { puts -nonewline stderr "+" ; flush stderr } + proc tock {} { + set then $::now; set ::now [clock clicks -milliseconds] + puts stderr " [expr {$::now - $then}] ms" + } +} else { + proc now {} {} ; proc tick {} {} ; proc tock {} {} +} + +now ; tick +test ttk-8.0 "Setup for 8.X" -body { + ttk::button .ctb + image create photo icon -data $::iconData; + pack .ctb +} +tock + +now +test ttk-8.1 "Test -compound options" -body { + # Exhaustively test each combination. + # Main goal is to make sure no code paths crash. + foreach image {icon ""} { + foreach text {"Hi!" ""} { + foreach compound $::compoundStrings { + .ctb configure -image $image -text $text -compound $compound + update; tick + } + } + } +} +tock + +test ttk-8.2 "Test -compound options with regular button" -body { + button .rtb + pack .rtb + + foreach image {"" icon} { + foreach text {"Hi!" ""} { + foreach compound [lrange $::compoundStrings 2 end] { + .rtb configure -image $image -text $text -compound $compound + update; tick + } + } + } +} +tock + +test ttk-8.3 "Rerun test 8.1" -body { + foreach image {icon ""} { + foreach text {"Hi!" ""} { + foreach compound $::compoundStrings { + .ctb configure -image $image -text $text -compound $compound + update; tick + } + } + } +} +tock + +test ttk-8.4 "ImageChanged" -body { + ttk::button .b -image icon + icon blank +} -cleanup { destroy .b } + +#------------------------------------------------------------------------ + +test ttk-9.1 "Traces on nonexistant namespaces" -body { + ttk::checkbutton .tcb -variable foo::bar +} -returnCodes 1 -result "*parent namespace doesn't exist*" -match glob + +test ttk-9.2 "Traces on nonexistant namespaces II" -body { + ttk::checkbutton .tcb -variable X + .tcb configure -variable foo::bar +} -returnCodes 1 -result "*parent namespace doesn't exist*" -match glob + +test ttk-9.3 "Restore saved options on configure error" -body { + .tcb cget -variable +} -result X + +test ttk-9.4 "Textvariable tests" -body { + set tcbLabel "Testing..." + .tcb configure -textvariable tcbLabel + .tcb cget -text +} -result "Testing..." + +# Changing -text has no effect if there is a linked -textvariable. +# Compatible with core widget. +test ttk-9.5 "Change -text" -body { + .tcb configure -text "Changed -text" + .tcb cget -text +} -result "Testing..." + +# Unset -textvariable clears the text. +# NOTE: this is different from core widgets, which automagically reinitalize +# the -textvariable to the last value of -text. +# +test ttk-9.6 "Unset -textvariable" -body { + unset tcbLabel + list [info exists tcbLabel] [.tcb cget -text] +} -result [list 0 ""] + +test ttk-9.7 "Unset textvariable, comparison" -body { +# +# NB: the ttk label behaves differently from the standard label here; +# NB: this is on purpose: I believe the standard behaviour is the Wrong Thing +# + unset -nocomplain V1 V2 + label .l -text Foo ; ttk::label .tl -text Foo + + .l configure -textvariable V1 ; .tl configure -textvariable V2 + list [set V1] [info exists V2] +} -cleanup { destroy .l .tl } -result [list Foo 0] + +test ttk-9.8 "-textvariable overrides -text" -body { + ttk::label .tl -textvariable TV + set TV Foo + .tl configure -text Bar + .tl cget -text +} -cleanup { destroy .tl } -result "Foo" + +# +# Frame widget tests: +# + +test ttk-10.1 "ttk::frame -class resource" -body { + ttk::frame .f -class Foo +} -result .f + +test ttk-10.2 "Check widget class" -body { + winfo class .f +} -result Foo + +test ttk-10.3 "Check class resource" -body { + .f cget -class +} -result Foo + +test ttk-10.4 "Try to modify class resource" -body { + .f configure -class Bar +} -returnCodes 1 -match glob -result "*read-only option*" + +test ttk-10.5 "Check class resource again" -body { + .f cget -class +} -result Foo + +test ttk-11.1 "-state test, setup" -body { + ttk::button .b + .b instate disabled +} -result 0 + +test ttk-11.2 "-state test, disable" -body { + .b configure -state disabled + .b instate disabled +} -result 1 + +test ttk-11.3 "-state test, reenable" -body { + .b configure -state normal + .b instate disabled +} -result 0 + +test ttk-11.4 "-state test, unrecognized -state value" -body { + .b configure -state bogus + .b state +} -result [list] + +test ttk-11.5 "-state test, 'active'" -body { + .b configure -state active + .b state +} -result [list active] -cleanup { .b state !active } + +test ttk-11.6 "-state test, 'readonly'" -body { + .b configure -state readonly + .b state +} -result [list readonly] -cleanup { .b state !readonly } + +test ttk-11.7 "-state test, cleanup" -body { + destroy .b +} + +test ttk-12.1 "-cursor option" -body { + ttk::button .b + .b cget -cursor +} -result {} + +test ttk-12.2 "-cursor option" -body { + .b configure -cursor arrow + .b cget -cursor +} -result arrow + +test ttk-12.3 "-borderwidth frame option" -body { + destroy .t + toplevel .t + raise .t + pack [set t [ttk::frame .t.f]] -expand true -fill x ; + pack [ttk::label $t.l -text "ASDF QWERTY"] -expand true -fill both + foreach theme {default alt} { + ttk::style theme use $theme + foreach relief {flat raised sunken ridge groove solid} { + $t configure -relief $relief + for {set i 5} {$i >= 0} {incr i -1} { + $t configure -borderwidth $i + update + } + } + } +} + +test ttk-12.4 "-borderwidth frame option" -body { + .t.f configure -relief raised + .t.f configure -borderwidth 1 + ttk::style theme use alt + update +} + + +test ttk-13.1 "Custom styles -- bad -style option" -body { + ttk::button .tb1 -style badstyle +} -returnCodes 1 -result "*badstyle not found*" -match glob + +test ttk-13.4 "Custom styles -- bad -style option" -body { + ttk::button .tb1 + .tb1 configure -style badstyle +} -cleanup { + destroy .tb1 +} -returnCodes 1 -result "*badstyle not found*" -match glob + +test ttk-13.5 "Custom layouts -- missing element definition" -body { + ttk::style layout badstyle { + NoSuchElement + } + ttk::button .tb1 -style badstyle +} -cleanup { + destroy .tb1 +} -result .tb1 +# @@@ Should: signal an error, possibly a background error. + +# +# See #793909 +# + +test ttk-14.1 "-variable in nonexistant namespace" -body { + ttk::checkbutton .tw -variable ::nsn::foo +} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \ + -match glob -cleanup { destroy .tw } + +test ttk-14.2 "-textvariable in nonexistant namespace" -body { + ttk::label .tw -textvariable ::nsn::foo +} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \ + -match glob -cleanup { destroy .tw } + +test ttk-14.3 "-textvariable in nonexistant namespace" -body { + ttk::entry .tw -textvariable ::nsn::foo +} -returnCodes 1 -result {can't trace *: parent namespace doesn't exist} \ + -match glob -cleanup { destroy .tw } + + +eval destroy [winfo children .] + +tcltest::cleanupTests + +#*EOF* diff --git a/tests/ttk/validate.test b/tests/ttk/validate.test new file mode 100644 index 0000000..417deac --- /dev/null +++ b/tests/ttk/validate.test @@ -0,0 +1,277 @@ +## +## Entry widget validation tests +## Derived from core test suite entry-19.1 through entry-19.20 +## + +package require Tk 8.5 +package require tcltest 2.1 +namespace import -force tcltest::* + +loadTestedCommands + +testConstraint ttkEntry 1 +testConstraint coreEntry [expr {![testConstraint ttkEntry]}] + +eval tcltest::configure $argv + +test validate-0.0 "Setup" -constraints ttkEntry -body { + rename entry {} + interp alias {} entry {} ttk::entry + return; +} + +test validate-0.1 "More setup" -body { + destroy .e + catch {unset ::e} + catch {unset ::vVals} + entry .e -validate all \ + -validatecommand [list doval %W %d %i %P %s %S %v %V] \ + -invalidcommand bell \ + -textvariable ::e \ + ; + pack .e + proc doval {W d i P s S v V} { + set ::vVals [list $W $d $i $P $s $S $v $V] + return 1 + } +} + +# The validation tests build each one upon the previous, so cascading +# failures aren't good +# +test validate-1.1 {entry widget validation - insert} -body { + .e insert 0 a + set ::vVals +} -result {.e 1 0 a {} a all key} + +test validate-1.2 {entry widget validation - insert} -body { + .e insert 1 b + set ::vVals +} -result {.e 1 1 ab a b all key} + +test validate-1.3 {entry widget validation - insert} -body { + .e insert end c + set ::vVals +} -result {.e 1 2 abc ab c all key} + +test validate-1.4 {entry widget validation - insert} -body { + .e insert 1 123 + list $::vVals $::e +} -result {{.e 1 1 a123bc abc 123 all key} a123bc} + +test validate-1.5 {entry widget validation - delete} -body { + .e delete 2 + set ::vVals +} -result {.e 0 2 a13bc a123bc 2 all key} + +test validate-1.6 {entry widget validation - delete} -body { + .e configure -validate key + .e delete 1 3 + set ::vVals +} -result {.e 0 1 abc a13bc 13 key key} + +test validate-1.7 {entry widget validation - vmode focus} -body { + set ::vVals {} + .e configure -validate focus + .e insert end d + set ::vVals +} -result {} + +test validate-1.8 {entry widget validation - vmode focus} -body { + focus -force .e + # update necessary to process FocusIn event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} focus focusin} + +test validate-1.9 {entry widget validation - vmode focus} -body { + focus -force . + # update necessary to process FocusOut event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} focus focusout} + +.e configure -validate all +test validate-1.10 {entry widget validation - vmode all} -body { + focus -force .e + # update necessary to process FocusIn event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} all focusin} + +test validate-1.11 {entry widget validation} -body { + focus -force . + # update necessary to process FocusOut event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} all focusout} +.e configure -validate focusin + +test validate-1.12 {entry widget validation} -body { + focus -force .e + # update necessary to process FocusIn event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} focusin focusin} + +test validate-1.13 {entry widget validation} -body { + set ::vVals {} + focus -force . + # update necessary to process FocusOut event + update + set ::vVals +} -result {} +.e configure -validate focuso + +test validate-1.14 {entry widget validation} -body { + focus -force .e + # update necessary to process FocusIn event + update + set ::vVals +} -result {} + +test validate-1.15 {entry widget validation} -body { + focus -force . + # update necessary to process FocusOut event + update + set ::vVals +} -result {.e -1 -1 abcd abcd {} focusout focusout} + +# DIFFERENCE: core entry temporarily sets "-validate all", ttk::entry doesn't. +test validate-1.16 {entry widget validation} -body { + .e configure -validate all + list [.e validate] $::vVals +} -result {1 {.e -1 -1 abcd abcd {} all forced}} + +# DIFFERENCE: ttk::entry does not perform validation when setting the -variable +test validate-1.17 {entry widget validation} -constraints coreEntry -body { + .e configure -validate all + set ::e newdata + list [.e cget -validate] $::vVals +} -result {all {.e -1 -1 newdata abcd {} all forced}} + +proc doval {W d i P s S v V} { + set ::vVals [list $W $d $i $P $s $S $v $V] + return 0 +} + +test validate-1.18 {entry widget validation} -constraints coreEntry -body { + .e configure -validate all + set ::e nextdata + list [.e cget -validate] $::vVals +} -result {none {.e -1 -1 nextdata newdata {} all forced}} +# DIFFERENCE: ttk::entry doesn't validate when setting linked -variable +# DIFFERENCE: ttk::entry doesn't disable validation + +proc doval {W d i P s S v V} { + set ::vVals [list $W $d $i $P $s $S $v $V] + set ::e mydata + return 1 +} + +## This sets validate to none because it shows that we prevent a possible +## loop condition in the validation, when the entry textvar is also set +test validate-1.19 {entry widget validation} -constraints coreEntry -body { + .e configure -validate all + .e validate + list [.e cget -validate] [.e get] $::vVals +} -result {none mydata {.e -1 -1 nextdata nextdata {} all forced}} + +## This leaves validate alone because we trigger validation through the +## textvar (a write trace), and the write during validation triggers +## nothing (by definition of avoiding loops on var traces). This is +## one of those "dangerous" conditions where the user will have a +## different value in the entry widget shown as is in the textvar. + +# DIFFERENCE: ttk entry doesn't get out of sync w/textvar +test validate-1.20 {entry widget validation} -constraints coreEntry -body { + .e configure -validate all + set ::e testdata + list [.e cget -validate] [.e get] $::e $::vVals +} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}} + +# +# New tests, -JE: +# +proc doval {W d i P s S v V} { + set ::vVals [list $W $d $i $P $s $S $v $V] + .e delete 0 end; + .e insert end dovaldata + return 0 +} +test validate-2.1 "Validation script changes value" -body { + .e configure -validate none + set ::e testdata + .e configure -validate all + .e validate + list [.e get] $::e $::vVals +} -result {dovaldata dovaldata {.e -1 -1 testdata testdata {} all forced}} +# DIFFERENCE: core entry disables validation, ttk entry does not. + +destroy .e +catch {unset ::e ::vVals} + +# See bug #1236979 + +test validate-2.2 "configure in -validatecommand" -body { + proc validate-2.2 {win str} { + $win configure -foreground black + return 1 + } + ttk::entry .e -textvariable var -validatecommand {validate-2.2 %W %P} + .e validate +} -result 1 -cleanup { destroy .e } + + +### invalid state behavior +# + +test validate-3.0 "Setup" -body { + set ::E "123" + ttk::entry .e \ + -validatecommand {string is integer -strict %P} \ + -validate all \ + -textvariable ::E \ + ; + return [list [.e get] [.e state]] +} -result [list 123 {}] + +test validate-3.1 "insert - valid" -body { + .e insert end "4" + return [list [.e get] [.e state]] +} -result [list 1234 {}] + +test validate-3.2 "insert - invalid" -body { + .e insert end "X" + return [list [.e get] [.e state]] +} -result [list 1234 {}] + +test validate-3.3 "force invalid value" -body { + append ::E "XY" + return [list [.e get] [.e state]] +} -result [list 1234XY {}] + +test validate-3.4 "revalidate" -body { + return [list [.e validate] [.e get] [.e state]] +} -result [list 0 1234XY {invalid}] + +testConstraint NA 0 +# the next two tests (used to) exercise validation lockout protection -- +# if the widget is currently invalid, all edits are allowed. +# This behavior is currently disabled. +# +test validate-3.5 "all edits allowed while invalid" -constraints NA -body { + .e delete 4 + return [list [.e get] [.e state]] +} -result [list 1234Y {invalid}] + +test validate-3.6 "...until the value becomes valid" -constraints NA -body { + .e delete 4 + return [list [.e get] [.e state]] +} -result [list 1234 {}] + +test validate-3.last "Cleanup" -body { destroy .e } + + +### +tcltest::cleanupTests |