summaryrefslogtreecommitdiffstats
path: root/tests/ttk/validate.test
blob: e687a15a59cccc043b093722ff51507de739fbbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
#
# Entry widget validation tests
# Derived from core test suite entry-19.1 through entry-19.20
#

#
# TESTFILE INITIALIZATION
#

package require tcltest 2.2; # needed in mode -singleproc 0

# Load the main script main.tcl, which takes care of:
# - setup for the application and the root window
# - importing commands from the tcltest namespace
# - loading of the testutils mechanism along with its utility procs
# - loading of Tk specific test constraints (additionally to constraints
#   provided by the package tcltest)
source [file join [file dirname [tcltest::configure -testdir]] main.tcl]

# Ensure a pristine initial window state
resetWindows

# Import utility procs for specific functional areas
testutils import entry

#
# LOCAL TEST CONSTRAINTS
#

testConstraint ttkEntry 1
testConstraint coreEntry [expr {![testConstraint ttkEntry]}]
testConstraint NA 0

#
# COMMON TEST SETUP
#

foreach i {1 2 3 4} {
    set validateCmd$i [list validateCommand$i %W %d %i %P %s %S %v %V]
}

#
# TESTS
#

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 textVar}
    unset -nocomplain validationData; # not necessary
    entry .e -validate all \
	    -validatecommand $validateCmd1 \
	    -invalidcommand bell \
	    -textvariable textVar \
	    ;
    pack .e
}

# 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 validationData
} -result {.e 1 0 a {} a all key}

test validate-1.2 {entry widget validation - insert} -body {
    .e insert 1 b
    set validationData
} -result {.e 1 1 ab a b all key}

test validate-1.3 {entry widget validation - insert} -body {
    .e insert end c
    set validationData
} -result {.e 1 2 abc ab c all key}

test validate-1.4 {entry widget validation - insert} -body {
    .e insert 1 123
    list $validationData $textVar
} -result {{.e 1 1 a123bc abc 123 all key} a123bc}

test validate-1.5 {entry widget validation - delete} -body {
    .e delete 2
    set validationData
} -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 validationData
} -result {.e 0 1 abc a13bc 13 key key}

test validate-1.7 {entry widget validation - vmode focus} -body {
    set validationData {}
    .e configure -validate focus
    .e insert end d
    set validationData
} -result {}

test validate-1.8 {entry widget validation - vmode focus} -body {
    set validationData {}
    set timer [after 300 validationData lappend timeout]
    focus -force .e
    vwait validationData
    after cancel $timer
    set validationData
} -result {.e -1 -1 abcd abcd {} focus focusin}

test validate-1.9 {entry widget validation - vmode focus} -body {
    set validationData {}
    set timer [after 300 validationData lappend timeout]
    focus -force .
    vwait validationData
    after cancel $timer
    set validationData
} -result {.e -1 -1 abcd abcd {} focus focusout}

#
# COMMON TEST SETUP
#

.e configure -validate all

test validate-1.10 {entry widget validation - vmode all} -body {
    set validationData {}
    set timer [after 300 validationData lappend timeout]
    focus -force .e
    vwait validationData
    after cancel $timer
    set validationData
} -result {.e -1 -1 abcd abcd {} all focusin}

test validate-1.11 {entry widget validation} -body {
    set validationData {}
    set timer [after 300 validationData lappend timeout]
    focus -force .
    vwait validationData
    after cancel $timer
    set validationData
} -result {.e -1 -1 abcd abcd {} all focusout}

#
# COMMON TEST SETUP
#

.e configure -validate focusin

test validate-1.12 {entry widget validation} -body {
    set validationData {}
    set timer [after 300 validationData lappend timeout]
    focus -force .e
    vwait validationData
    after cancel $timer
    set validationData
} -result {.e -1 -1 abcd abcd {} focusin focusin}

test validate-1.13 {entry widget validation} -body {
    set validationData {}
    focus -force .
    update
    set validationData
} -result {}

#
# COMMON TEST SETUP
#

.e configure -validate focuso

test validate-1.14 {entry widget validation} -body {
    set validationData {}
    focus -force .e
    update
    set validationData
} -result {}

test validate-1.15 {entry widget validation} -body {
    focus -force .
    # update necessary to process FocusOut event
    update
    set validationData
} -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] $validationData
} -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 textVar newdata
    list [.e cget -validate] $validationData
} -result {all {.e -1 -1 newdata abcd {} all forced}}

test validate-1.18 {entry widget validation} -constraints coreEntry -body {
    .e configure -validate all -validatecommand $validateCmd3
    set textVar nextdata
    list [.e cget -validate] $validationData
} -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

## 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 -validatecommand $validateCmd2
    .e validate
    list [.e cget -validate] [.e get] $validationData
} -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 -validatecommand $validateCmd2
    set textVar testdata
    list [.e cget -validate] [.e get] $textVar $validationData
} -result {all testdata mydata {.e -1 -1 testdata mydata {} all forced}}

test validate-2.1 "Validation script changes value" -body {
    .e configure -validate none -validatecommand $validateCmd4
    set textVar testdata
    .e configure -validate all
    .e validate
    list [.e get] $textVar $validationData
} -result {dovaldata dovaldata {.e -1 -1 testdata testdata {} all forced}}
# DIFFERENCE: core entry disables validation, ttk entry does not.

#
# COMMON TEST CLEANUP
#

destroy .e
catch {unset textVar}

# 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}]

# 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 }

#
# TESTFILE CLEANUP
#

foreach i {1 2 3 4} {
    unset validateCmd$i
}
unset i
testutils forget entry
tcltest::cleanupTests