1WAComponent subclass: WAAllTests [
2    | navigation |
3
4    <comment: 'If you want to see these examples:
5
6/seaside/config app:
7- add a new application named "tests"
8- choose WAAllTests as the root component
9'>
10    <category: 'Seaside-Tests-Functional'>
11
12    WAAllTests class >> canBeRoot [
13	<category: 'testing'>
14	^true
15    ]
16
17    WAAllTests class >> description [
18	<category: 'accessing'>
19	^'Functional Seaside Test Suite'
20    ]
21
22    WAAllTests class >> initialize [
23	<category: 'initialization'>
24	(self registerAsApplication: 'tests/alltests') preferenceAt: #sessionClass
25	    put: WAExpirySession
26    ]
27
28    children [
29	<category: 'accessing'>
30	^Array with: navigation
31    ]
32
33    initialize [
34	<category: 'initialize-release'>
35	| components |
36	super initialize.
37	components := SortedCollection
38		    sortBlock: [:a :b | a label caseInsensitiveLessOrEqual: b label].
39	WAFunctionalTest allSubclassesDo: [:each | components add: each new].
40	WAFunctionalTaskTest allSubclassesDo: [:each | components add: each new].
41	components add: (WAParentTest new parent: self).
42	navigation := WASimpleNavigation new.
43	components do: [:each | navigation add: each label: each label]
44    ]
45
46    renderContentOn: html [
47	<category: 'rendering'>
48	(html div)
49	    id: 'all-tests';
50	    with:
51		    [html heading: 'Functional Seaside Test Suite'.
52		    html render: navigation]
53    ]
54]
55
56
57
58WAComponent subclass: WAFunctionalTest [
59
60    <comment: nil>
61    <category: 'Seaside-Tests-Functional'>
62
63    label [
64	<category: 'accessing'>
65	self subclassResponsibility
66    ]
67]
68
69
70
71WAFunctionalTest subclass: WABatchTest [
72    | batcher |
73
74    <comment: nil>
75    <category: 'Seaside-Tests-Functional'>
76
77    children [
78	<category: 'accessing'>
79	^Array with: batcher
80    ]
81
82    initialize [
83	<category: 'initialization'>
84	super initialize.
85	batcher := WAAlphabeticBatchedList new items: Collection allSubclasses
86    ]
87
88    label [
89	<category: 'accessing'>
90	^'Batch'
91    ]
92
93    renderContentOn: html [
94	<category: 'rendering'>
95	html render: batcher.
96	html unorderedList list: batcher batch
97    ]
98]
99
100
101
102WAFunctionalTest subclass: WAButtonTest [
103    | input |
104
105    <comment: nil>
106    <category: 'Seaside-Tests-Functional'>
107
108    initialize [
109	<category: 'initialize-release'>
110	super initialize.
111	self input: 'a text'
112    ]
113
114    input [
115	<category: 'accessing'>
116	^input
117    ]
118
119    input: aString [
120	<category: 'accessing'>
121	input := aString
122    ]
123
124    label [
125	<category: 'accessing'>
126	^'Button'
127    ]
128
129    renderContentOn: html [
130	<category: 'rendering'>
131	html form:
132		[html div:
133			[self renderInputOn: html.
134			self renderSubmitOn: html.
135			self renderResetOn: html.
136			self renderPushOn: html]]
137    ]
138
139    renderInputOn: html [
140	<category: 'rendering'>
141	html table:
142		[html tableRow:
143			[html tableHeading: 'Value:'.
144			html tableData: self input].
145		html tableRow:
146			[html tableHeading: 'Input:'.
147			html tableData: [html textInput on: #input of: self]]]
148    ]
149
150    renderPushOn: html [
151	<category: 'rendering'>
152	html heading level2 with: 'Push'.
153	html paragraph: 'Clicking the button should not do anything.'.
154	(html button)
155	    bePush;
156	    with: 'Push'
157    ]
158
159    renderResetOn: html [
160	<category: 'rendering'>
161	html heading level2 with: 'Reset'.
162	html
163	    paragraph: 'Clicking the button should not submit the form reset the value in "Input"'.
164	(html button)
165	    beReset;
166	    with: 'Reset'
167    ]
168
169    renderSubmitOn: html [
170	<category: 'rendering'>
171	html heading level2 with: 'Submit'.
172	html
173	    paragraph: 'Clicking the button should submit the form and update the value in "Value:" with the value in "Input"'.
174	html button with: 'Submit'
175    ]
176]
177
178
179
180WAFunctionalTest subclass: WACacheTest [
181
182    <comment: nil>
183    <category: 'Seaside-Tests-Functional'>
184
185    label [
186	<category: 'accessing'>
187	^'Cache'
188    ]
189
190    renderActionsOn: html [
191	<category: 'rendering'>
192	html paragraph:
193		[(html anchor)
194		    callback: [self inform: 'answer'];
195		    with: 'call'.
196		html text: ' (answer: +1, escape: +1)'.
197		html break.
198		(html anchor)
199		    callback: [self call: self class new];
200		    with: 'keep calling'.
201		html text: ' (answer: +1, escape: +1)'.
202		html break.
203		(html anchor)
204		    callback: [self session redirect];
205		    with: 'redirect'.
206		html text: ' (response: +1, escape: +1)']
207    ]
208
209    renderContentOn: html [
210	<category: 'rendering'>
211	Smalltalk garbageCollect.
212	self renderStatisticsOn: html.
213	self renderActionsOn: html
214    ]
215
216    renderStatisticsOn: html [
217	<category: 'rendering'>
218	html paragraph:
219		[html
220		    strong: 'Response Continuations: ';
221		    text: ResponseContinuation allInstances size;
222		    break.
223		html
224		    strong: 'Answer Continuations: ';
225		    text: AnswerContinuation allInstances size;
226		    break.
227		html
228		    strong: 'Escape Continuations: ';
229		    text: EscapeContinuation allInstances size;
230		    break]
231    ]
232]
233
234
235
236WAFunctionalTest subclass: WACallbackTest [
237    | transcript counter |
238
239    <comment: nil>
240    <category: 'Seaside-Tests-Functional'>
241
242    children [
243	<category: 'accessing'>
244	^Array with: counter
245    ]
246
247    initialize [
248	<category: 'initialization'>
249	super initialize.
250	transcript := String new writeStream.
251	counter := WACounter new
252    ]
253
254    label [
255	<category: 'accessing'>
256	^'Callback'
257    ]
258
259    renderContentOn: html [
260	<category: 'rendering'>
261	(html anchor)
262	    callback: [];
263	    with: 'Idempotent'.
264	html space.
265	(html anchor)
266	    callback: [];
267	    with: 'Side Effect'.
268	(html form)
269	    defaultAction:
270		    [transcript
271			cr;
272			nextPutAll: 'default action'];
273	    with:
274		    [html textInput callback:
275			    [:v |
276			    transcript
277				cr;
278				nextPutAll: 'text: ';
279				nextPutAll: v printString].
280		    html textInput callback:
281			    [:v |
282			    transcript
283				cr;
284				nextPutAll: 'text2: ';
285				nextPutAll: v printString].
286		    html break.
287		    html submitButton.
288		    html space.
289		    (html submitButton)
290			callback:
291				[transcript
292				    cr;
293				    nextPutAll: 'go'];
294			text: 'Go'.
295		    html space.
296		    (html cancelButton)
297			callback:
298				[transcript
299				    cr;
300				    nextPutAll: 'cancel'];
301			text: 'Cancel'].
302	html preformatted: transcript contents.
303	html horizontalRule.
304	html render: counter
305    ]
306]
307
308
309
310WAFunctionalTest subclass: WACanvasTableTest [
311
312    <comment: nil>
313    <category: 'Seaside-Tests-Functional'>
314
315    entities [
316	<category: 'samples'>
317	^#(#('non-breaking space' #('&nbsp;' '&#160;' '&#xA0;')) #('ampersand' #('&amp;' '&#38;' '&#x26;')) #('less than sign' #('&lt;' '&#60;' '&#x3C;')) #('greater than sign' #('&gt;' '&#62;' '&#x3E;')) #('euro sign' #('&euro;' '&#8364;' '&#x20AC;')))
318    ]
319
320    exchangeRates [
321	<category: 'samples'>
322	^#(#('EUR' 1.7) #('USD' 1.3) #('DKK' 23.36) #('SEK' 19.32))
323    ]
324
325    label [
326	<category: 'accessing'>
327	^'Table'
328    ]
329
330    renderContentOn: html [
331	<category: 'rendering'>
332	(html div)
333	    class: 'wacanvastabletest';
334	    with:
335		    [self renderEntityTableOn: html.
336		    self renderCurrencyTableOn: html]
337    ]
338
339    renderCurrencyTableBodyOn: html [
340	<category: 'rendering'>
341	(html tableBody)
342	    title: 'Table body';
343	    with:
344		    [self exchangeRates do:
345			    [:each |
346			    html tableRow:
347				    [html tableHeading: each first.
348				    (html tableData)
349					align: 'char';
350					character: $.;
351					with: each second]]]
352    ]
353
354    renderCurrencyTableHeadOn: html [
355	<category: 'rendering'>
356	(html tableHead)
357	    title: 'Table header';
358	    with:
359		    [html tableRow:
360			    [html tableHeading: 'Currency'.
361			    html tableHeading: 'Rate']]
362    ]
363
364    renderCurrencyTableOn: html [
365	<category: 'rendering'>
366	(html table)
367	    summary: 'This table shows exchange rates against the Swiss Franc';
368	    with:
369		    [html tableCaption: 'Currencies against Swiss Franc (CHF)'.
370		    html tableColumnGroup.
371		    (html tableColumnGroup)
372			width: '100px';
373			align: 'char';
374			character: $..
375		    self renderCurrencyTableHeadOn: html.
376		    self renderCurrencyTableBodyOn: html]
377    ]
378
379    renderEntityTableBodyOn: html [
380	<category: 'rendering'>
381	html tableBody:
382		[self entities do:
383			[:eachEntity |
384			html tableRow:
385				[(html tableData)
386				    scope: 'row';
387				    with: eachEntity first.
388				eachEntity second do: [:each | html tableData: each].
389				eachEntity second do:
390					[:each |
391					(html tableData)
392					    align: 'center';
393					    with: [html html: each]]]]]
394    ]
395
396    renderEntityTableColumnGroupsOn: html [
397	<category: 'rendering'>
398	html tableColumnGroup.
399	html tableColumnGroup span: 3.
400	(html tableColumnGroup)
401	    span: 3;
402	    align: 'center'
403    ]
404
405    renderEntityTableFootOn: html [
406	<category: 'rendering'>
407	html tableFoot:
408		[html tableRow:
409			[(html tableData)
410			    align: 'center';
411			    colSpan: 7;
412			    with: '5 entities shown']]
413    ]
414
415    renderEntityTableHeadOn: html [
416	<category: 'rendering'>
417	html tableHead:
418		[html tableRow:
419			[#('Character' 'Entity' 'Decimal' 'Hex') do:
420				[:each |
421				(html tableHeading)
422				    scope: 'col';
423				    rowSpan: 2;
424				    with: each].
425			(html tableHeading)
426			    scope: 'colgroup';
427			    colSpan: 3;
428			    with: 'Rendering in Your Browser'].
429		html tableRow:
430			[#('Entity' 'Decimal' 'Hex') do:
431				[:each |
432				(html tableHeading)
433				    scope: 'col';
434				    with: each]]]
435    ]
436
437    renderEntityTableOn: html [
438	<category: 'rendering'>
439	(html table)
440	    summary: 'This table gives the character entity reference,
441                decimal character reference, and hexadecimal character
442                reference for 8-bit Latin-1 characters, as well as the
443                rendering of each in your browser.';
444	    with:
445		    [html tableCaption: 'HTML 4.0 entities'.
446		    self renderEntityTableColumnGroupsOn: html.
447		    self renderEntityTableHeadOn: html.
448		    self renderEntityTableFootOn: html.
449		    self renderEntityTableBodyOn: html]
450    ]
451
452    style [
453	<category: 'rendering'>
454	^'
455.wacanvastabletest table {
456	border-collapse: collapse;
457	border:1px solid black;
458	margin:0px auto; /* center */
459}
460
461.wacanvastabletest caption {
462	margin:0px auto; /* center */
463}
464.wacanvastabletest caption {
465	font-weight: bold;
466	padding: 0.5em 0 1em 0;
467}
468.wacanvastabletest td, .wacanvastabletest th {
469	padding: 3px;
470	border:1px solid black;
471}
472'
473    ]
474]
475
476
477
478WAFunctionalTest subclass: WAClosureTest [
479
480    <comment: nil>
481    <category: 'Seaside-Tests-Functional'>
482
483    ensure [
484	<category: 'actions'>
485	[self go] ensure: [self inform: 'ensure']
486    ]
487
488    go [
489	<category: 'actions'>
490	#(#a #b #c)
491	    keysAndValuesDo: [:a :b | self inform: a seasideString , ' ' , b seasideString]
492    ]
493
494    label [
495	<category: 'accessing'>
496	^'Closure'
497    ]
498
499    renderContentOn: html [
500	<category: 'rendering'>
501	(html anchor)
502	    callback: [self go];
503	    with: 'go'.
504	html space.
505	(html anchor)
506	    callback: [self ensure];
507	    with: 'go with ensure'
508    ]
509]
510
511
512
513WAFunctionalTest subclass: WACookieTest [
514    | key value |
515
516    <comment: nil>
517    <category: 'Seaside-Tests-Functional'>
518
519    add [
520	<category: 'actions'>
521	| response |
522	self session respond:
523		[:url |
524		response := self session redirectResponseFor: url.
525		response addCookie: (WACookie key: key value: value).
526		response].
527	key := value := nil
528    ]
529
530    cookies [
531	<category: 'accessing'>
532	^self session currentRequest cookies
533    ]
534
535    label [
536	<category: 'accessing'>
537	^'Cookies'
538    ]
539
540    remove: aKey [
541	<category: 'actions'>
542	| response |
543	self session respond:
544		[:url |
545		response := self session redirectResponseFor: url.
546		response deleteCookieAt: aKey.
547		response]
548    ]
549
550    renderContentOn: html [
551	<category: 'rendering'>
552	html form:
553		[html table:
554			[html tableRow:
555				[html tableHeading: 'Key'.
556				html tableHeading: 'Value'.
557				html tableHeading].
558			self cookies keysAndValuesDo:
559				[:k :v |
560				html tableRow:
561					[html tableData: k.
562					html tableData: v.
563					html tableData:
564						[(html submitButton)
565						    callback: [self remove: k];
566						    text: 'remove']]].
567			html tableRow:
568				[html tableData:
569					[(html textInput)
570					    value: key;
571					    callback: [:v | key := v]].
572				html tableData:
573					[(html textInput)
574					    value: value;
575					    callback: [:v | value := v]].
576				html tableData: [html submitButton on: #add of: self]]]]
577    ]
578]
579
580
581
582WAFunctionalTest subclass: WADateSelectorTest [
583    | beginDate endDate beginTime endTime beginDAT endDAT |
584
585    <comment: nil>
586    <category: 'Seaside-Tests-Functional'>
587
588    WADateSelectorTest class >> example [
589	<category: 'examples'>
590	^self new
591    ]
592
593    WADateSelectorTest class >> initialize [
594	<category: 'class initialization'>
595	self registerAsApplication: 'tests/dateselector'
596    ]
597
598    children [
599	<category: 'accessing'>
600	^(OrderedCollection new)
601	    add: beginDate;
602	    add: endDate;
603	    add: beginTime;
604	    add: endTime;
605	    add: beginDAT;
606	    add: endDAT;
607	    yourself
608    ]
609
610    computeDuration [
611	<category: 'actions'>
612	| dateDiff |
613	dateDiff := (endDAT dateAndTime asDate - beginDAT dateAndTime asDate) days.
614	dateDiff isZero
615	    ifFalse: [self inform: dateDiff seasideString , ' day(s)']
616	    ifTrue:
617		[self
618		    inform: (endDAT dateAndTime asTime
619			    subtractTime: beginDAT dateAndTime asTime) asSeconds
620			    seasideString , ' second(s)']
621    ]
622
623    initialize [
624	<category: 'initialization'>
625	super initialize.
626	beginDate := WADateSelector new.
627	endDate := WADateSelector new.
628	endDate date: (Date today addDays: 1).
629	beginTime := WATimeSelector new.
630	beginTime time: Time now.
631	endTime := WATimeSelector new.
632	endTime time: (beginTime time addSeconds: 3600).
633	beginDAT := WADateTimeSelector new.
634	endDAT := WADateTimeSelector new.
635	endDAT dateAndTime: beginDAT dateAndTime + 1 day + 1 hour
636    ]
637
638    label [
639	<category: 'accessing'>
640	^'Date Selector'
641    ]
642
643    renderContentOn: html [
644	<category: 'rendering'>
645	self renderDateSelectorsOn: html.
646	html horizontalRule.
647	self renderTimeSelectorsOn: html.
648	html horizontalRule.
649	self renderDateTimeSelectorsOn: html
650    ]
651
652    renderDateSelectorsOn: html [
653	<category: 'rendering'>
654	(html heading)
655	    level3;
656	    with: 'Dates'.
657	html form:
658		[html table:
659			[html tableRow:
660				[html
661				    tableData: 'From';
662				    tableData: beginDate].
663			html tableRow:
664				[html
665				    tableData: 'To';
666				    tableData: endDate]].
667		(html submitButton)
668		    callback:
669			    [self inform: (endDate date - beginDate date) days seasideString , ' day(s)'];
670		    text: 'Compute duration']
671    ]
672
673    renderDateTimeSelectorsOn: html [
674	<category: 'rendering'>
675	(html heading)
676	    level3;
677	    with: 'Dates and Times'.
678	html form:
679		[html table:
680			[html tableRow:
681				[html
682				    tableData: 'From';
683				    tableData: beginDAT].
684			html tableRow:
685				[html
686				    tableData: 'To';
687				    tableData: endDAT]].
688		(html submitButton)
689		    callback: [self computeDuration];
690		    text: 'Compute duration']
691    ]
692
693    renderTimeSelectorsOn: html [
694	<category: 'rendering'>
695	(html heading)
696	    level3;
697	    with: 'Times'.
698	html form:
699		[html table:
700			[html tableRow:
701				[html
702				    tableData: 'From';
703				    tableData: beginTime].
704			html tableRow:
705				[html
706				    tableData: 'To';
707				    tableData: endTime]].
708		(html submitButton)
709		    callback:
710			    [self
711				inform: (endTime time subtractTime: beginTime time) asSeconds seasideString
712					, ' seconds(s)'];
713		    text: 'Compute duration']
714    ]
715]
716
717
718
719WAFunctionalTest subclass: WADateTimeTest [
720    | data numericData date time data1 data2 message |
721
722    <comment: nil>
723    <category: 'Seaside-Tests-Functional'>
724
725    data1 [
726	<category: 'accessing'>
727	^data1
728    ]
729
730    data1: aString [
731	<category: 'accessing'>
732	data1 := aString
733    ]
734
735    data2 [
736	<category: 'accessing'>
737	^data2
738    ]
739
740    data2: aString [
741	<category: 'accessing'>
742	data2 := aString
743    ]
744
745    date [
746	<category: 'accessing'>
747	^date
748    ]
749
750    date: aDate [
751	<category: 'accessing'>
752	date := aDate
753    ]
754
755    initialize [
756	<category: 'initialize-release'>
757	super initialize.
758	data1 := 'Harry'.
759	data2 := 'Covert'.
760	data := String new.
761	message := String new.
762	numericData := 12
763    ]
764
765    label [
766	<category: 'accessing'>
767	^'Date and Time Selector'
768    ]
769
770    numericData [
771	<category: 'accessing'>
772	^numericData
773    ]
774
775    numericData: aString [
776	<category: 'accessing'>
777	numericData := aString
778    ]
779
780    renderContentOn: html [
781	<category: 'rendering'>
782	self renderSubmitFormOn: html.
783	self renderDateTimeOn: html.
784	self renderDeadDateTimeOn: html
785    ]
786
787    renderDateTimeOn: html [
788	<category: 'rendering'>
789	(html heading)
790	    level3;
791	    with: 'Form with #dateInput and #timeInput'.
792	(html form)
793	    defaultAction:
794		    [message := 'Default action: ' , date seasideString , ' ' , time seasideString];
795	    with:
796		    [html div:
797			    [html dateInput on: #date of: self.
798			    html space: 10.
799			    (html timeInput)
800				withSeconds;
801				on: #time of: self.
802			    html break.
803			    html text: message.
804			    html break.
805			    html submitButton
806				callback: [message := 'Button action: ' , date seasideString , ' ' , time seasideString]]]
807    ]
808
809    renderDeadDateTimeOn: html [
810	<category: 'rendering'>
811	(html heading)
812	    level: 3;
813	    with: 'Div with #dateInput and #timeInput, no callback'.
814	html form:
815		[html div:
816			[html dateInput value: Date today.
817			html space: 10.
818			(html timeInput)
819			    withSeconds;
820			    value: Time now.
821			html break.
822			html
823			    withLineBreaks: 'The year portion of the date should be visible.
824				The seconds portion of the time should be visible']]
825    ]
826
827    renderSubmitFormOn: html [
828	<category: 'rendering'>
829	(html heading)
830	    level3;
831	    with: 'Form with #submitFormNamed:'.
832	(html form)
833	    id: 'submitForm';
834	    defaultAction:
835		    [data := 'Default action : ' , data1 seasideString , ' ' , data2 seasideString , ' '
836				, numericData seasideString];
837	    with:
838		    [html div:
839			    [html textInput on: #data1 of: self.
840			    html textInput on: #data2 of: self.
841			    html textInput on: #numericData of: self.
842			    html break.
843			    html text: data.
844			    html break.
845			    (html anchor)
846				callback:
847					[data := 'Anchor action : ' , data1 seasideString , ' ' , data2 seasideString , ' '
848						    , numericData seasideString];
849				submitFormNamed: 'submitForm';
850				with: 'Click to submit']]
851    ]
852
853    time [
854	<category: 'accessing'>
855	^time
856    ]
857
858    time: aTime [
859	<category: 'accessing'>
860	time := aTime
861    ]
862]
863
864
865
866WAFunctionalTest subclass: WADefaultFormTest [
867    | value |
868
869    <comment: nil>
870    <category: 'Seaside-Tests-Functional'>
871
872    label [
873	<category: 'accessing'>
874	^'Default Form'
875    ]
876
877    renderContentOn: html [
878	<category: 'rendering'>
879	(html form)
880	    defaultAction: [self inform: 'Default: ' , value seasideString];
881	    with:
882		    [html div:
883			    [(html submitButton)
884				callback: [self inform: 'Before: ' , value seasideString];
885				text: 'Before'.
886			    html break.
887			    (html textInput)
888				value: '';
889				callback: [:v | value := v].
890			    (html submitButton)
891				callback: [self inform: 'Go: ' , value seasideString];
892				text: 'Go'.
893			    html break.
894			    (html submitButton)
895				callback: [self inform: 'After: ' , value seasideString];
896				text: 'After']]
897    ]
898]
899
900
901
902WAFunctionalTest subclass: WADelayTest [
903
904    <comment: nil>
905    <category: 'Seaside-Tests-Functional'>
906
907    go [
908	<category: 'actions'>
909	self call: ((WAComponent new)
910		    addMessage: '3 seconds';
911		    addDecoration: (WADelayedAnswerDecoration new delay: 3);
912		    yourself)
913    ]
914
915    label [
916	<category: 'accessing'>
917	^'Delay'
918    ]
919
920    renderContentOn: html [
921	<category: 'rendering'>
922	html
923	    paragraph: 'Clicking the following anchor should replace it with the message "3 seconds" for 3 seconds and then restore it.'.
924	html paragraph:
925		[(html anchor)
926		    callback: [self go];
927		    with: 'Start']
928    ]
929]
930
931
932
933WAFunctionalTest subclass: WAEncodingTest [
934    | urlencoded multipart |
935
936    <comment: 'A WAEncodingTest test whether Seaside correctly handles non-ASCII strings. Unfortunately due to differences in server setup and source code encodings this test requires manual interaction.
937'>
938    <category: 'Seaside-Tests-Functional'>
939
940    initialize [
941	<category: 'initialize-release'>
942	super initialize.
943	self urlencoded: 'urlencoded'.
944	self multipart: 'multipart'
945    ]
946
947    label [
948	<category: 'accessing'>
949	^'Encoding'
950    ]
951
952    multipart [
953	<category: 'accessing'>
954	^multipart
955    ]
956
957    multipart: aString [
958	<category: 'accessing'>
959	multipart := aString
960    ]
961
962    renderClassName: aString on: html [
963	<category: 'rendering'>
964	aString isNil
965	    ifFalse:
966		[html strong: 'Class: '.
967		html text: aString class name]
968    ]
969
970    renderContentOn: html [
971	<category: 'rendering'>
972	self renderExplanationOn: html.
973	self renderUrlencodedOn: html.
974	self renderMultipartOn: html
975    ]
976
977    renderExplanationOn: html [
978	<category: 'rendering'>
979	html paragraph:
980		[html unorderedList:
981			[html listItem:
982				[html text: 'Go to the '.
983				(html anchor)
984				    url: 'http://www.columbia.edu/kermit/utf8.html';
985				    with: 'UTF-8 Sampler'.
986				html text: ' and select some "foreign" text.'].
987			html
988			    listItem: 'Copy and paste it into the urlencoded text field below and click the submit button.'.
989			html
990			    listItem: 'The heading, textfield and submitt button should all display the text without any error.'.
991			html
992			    listItem: 'Submit again without changing anything, again everything should display normally.'.
993			html
994			    listItem: 'Repeat this process for the multipart field. Make sure to pick at least every of these languages: German, Czech, Korean.']]
995    ]
996
997    renderMultipartOn: html [
998	<category: 'rendering'>
999	(html heading)
1000	    level2;
1001	    with: 'Multipart'.
1002	(html heading)
1003	    level3;
1004	    with: self multipart.
1005	(html form)
1006	    multipart;
1007	    with:
1008		    [html textInput on: #multipart of: self.
1009		    html submitButton text: self multipart].
1010	self renderClassName: self multipart on: html
1011    ]
1012
1013    renderUrlencodedOn: html [
1014	<category: 'rendering'>
1015	(html heading)
1016	    level2;
1017	    with: 'Urlencoded'.
1018	(html heading)
1019	    level3;
1020	    with: self urlencoded.
1021	html form:
1022		[html textInput on: #urlencoded of: self.
1023		html submitButton text: self urlencoded].
1024	self renderClassName: self urlencoded on: html
1025    ]
1026
1027    urlencoded [
1028	<category: 'accessing'>
1029	^urlencoded
1030    ]
1031
1032    urlencoded: aString [
1033	<category: 'accessing'>
1034	urlencoded := aString
1035    ]
1036]
1037
1038
1039
1040WAFunctionalTest subclass: WAErrorTest [
1041
1042    <comment: nil>
1043    <category: 'Seaside-Tests-Functional'>
1044
1045    label [
1046	<category: 'accessing'>
1047	^'Error'
1048    ]
1049
1050    renderContentOn: html [
1051	<category: 'rendering'>
1052	(html div)
1053	    class: 'errorTest';
1054	    with:
1055		    [self renderHaltOn: html.
1056		    self renderErrorOn: html.
1057		    self renderResumableErrorOn: html.
1058		    self renderWarningOn: html.
1059		    self renderDeprecatedOn: html]
1060    ]
1061
1062    renderDeprecatedOn: html [
1063	<category: 'rendering'>
1064	html heading: 'Deprecated'.
1065	html
1066	    paragraph: 'The link should display a deprecated warning in the toolbar and display an information message.'.
1067	(html anchor)
1068	    callback:
1069		    [self
1070			deprecatedApi: 'Test Deprecation';
1071			inform: 'To be displayed'];
1072	    with: 'Raise deprecated'
1073    ]
1074
1075    renderErrorOn: html [
1076	<category: 'rendering'>
1077	html heading: 'Error'.
1078	html
1079	    paragraph: 'The link should display an error walkback. Opening a debugger should work. Closing the debugger window should not lock the session.'.
1080	(html anchor)
1081	    callback:
1082		    [self
1083			error: 'Test Error';
1084			inform: 'Not to be displayed'];
1085	    with: 'Raise error'
1086    ]
1087
1088    renderHaltOn: html [
1089	<category: 'rendering'>
1090	html heading: 'Halt'.
1091	html
1092	    paragraph: 'The link should open a debugger in the image. Clicking on proceed should display the information message "To be displayed".'.
1093	(html anchor)
1094	    callback:
1095		    [self
1096			halt;
1097			inform: 'To be displayed'];
1098	    with: 'Halt execution'
1099    ]
1100
1101    renderResumableErrorOn: html [
1102	<category: 'rendering'>
1103	html heading: 'Resumable error'.
1104	html
1105	    paragraph: 'The link should display a zero divide walkback. Clicking on proceed should display the message "To be displayed". Clicking on debug should open a debugger in the image.'.
1106	(html anchor)
1107	    callback:
1108		    [1 / 0.
1109		    self inform: 'To be displayed'];
1110	    with: 'Raise zero divide'
1111    ]
1112
1113    renderWarningOn: html [
1114	<category: 'rendering'>
1115	html heading: 'Warning'.
1116	html
1117	    paragraph: 'In Squeak the warning test works the same as the resumable error test.'.
1118	html
1119	    paragraph: 'In VisualWorks the warning test works the same as the halt test.'.
1120	(html anchor)
1121	    callback:
1122		    [self
1123			notify: 'Test Warning';
1124			inform: 'To be displayed'];
1125	    with: 'Raise warning'
1126    ]
1127]
1128
1129
1130
1131WAFunctionalTest subclass: WAExpiryTest [
1132
1133    <comment: nil>
1134    <category: 'Seaside-Tests-Functional'>
1135
1136    label [
1137	<category: 'accessing'>
1138	^'Expiry'
1139    ]
1140
1141    renderActionsOn: html [
1142	<category: 'rendering'>
1143	(html anchor)
1144	    url: self session newSessionUrl;
1145	    with: 'New Session'.
1146	html break.
1147	(html anchor)
1148	    callback: [self session expire];
1149	    with: 'Expire'.
1150	html break.
1151	(html anchor)
1152	    callback: [WAExpirySession resetCounters];
1153	    with: 'Reset Counters'.
1154	html break.
1155	(html anchor)
1156	    callback: [Smalltalk garbageCollect];
1157	    with: 'Garbage Collect'.
1158	html break.
1159	(html anchor)
1160	    callback:
1161		    [self session application clearHandlers.
1162		    Smalltalk garbageCollect];
1163	    with: 'Clear Handlers'.
1164	html break.
1165	(html anchor)
1166	    callback:
1167		    [self session application clearHandlers.
1168		    WAExpirySession resetCounters.
1169		    Smalltalk garbageCollect];
1170	    with: 'Reset All'.
1171	html form:
1172		[html text: 'Expiry seconds:'.
1173		(html textInput)
1174		    value: self session application sessionExpirySeconds;
1175		    callback: [:value | self session timeoutSeconds: value asInteger].
1176		html space.
1177		html submitButton text: 'Change']
1178    ]
1179
1180    renderContentOn: html [
1181	<category: 'rendering'>
1182	self renderStatsOn: html.
1183	self renderActionsOn: html
1184    ]
1185
1186    renderStatsOn: html [
1187	<category: 'rendering'>
1188	html table:
1189		[html tableRow:
1190			[html tableHeading: 'Total session instances'.
1191			html tableData: WAExpirySession allInstances size].
1192		html tableRow:
1193			[html tableHeading: 'Active session instances'.
1194			html
1195			    tableData: (WAExpirySession allInstances count: [:each | each isActive])].
1196		html tableRow:
1197			[html tableHeading: 'Total component instances'.
1198			html tableData: self class allInstances size].
1199		html tableRow:
1200			[html tableHeading: 'Sessions created'.
1201			html tableData: WAExpirySession created].
1202		html tableRow:
1203			[html tableHeading: 'Sessions unregistered'.
1204			html tableData: WAExpirySession unregistered]]
1205    ]
1206]
1207
1208
1209
1210WAFunctionalTest subclass: WAFileLibraryHtmlTest [
1211
1212    <comment: nil>
1213    <category: 'Seaside-Tests-Functional'>
1214
1215    basePath [
1216	<category: 'accessing'>
1217	^WADispatcher default basePath
1218    ]
1219
1220    label [
1221	<category: 'accessing'>
1222	^'File Library'
1223    ]
1224
1225    renderContentOn: html [
1226	<category: 'rendering'>
1227	(html div)
1228	    class: 'desc';
1229	    with:
1230		    [(html heading)
1231			level3;
1232			with: 'This page has'.
1233		    html unorderedList:
1234			    [html listItem: 'a static stylesheet (main.css)'.
1235			    html
1236				listItem: 'a static background image (main.jpg) named in a dynamic stylesheet'.
1237			    html listItem: 'an image']].
1238	html image url: WAFileLibraryDemo / #mainJpg
1239    ]
1240
1241    style [
1242	<category: 'accessing'>
1243	^'
1244
1245body {
1246	background: url(' , self basePath
1247	    , '/files/WAFileLibraryDemo/main.jpg);
1248}
1249div.desc {
1250	padding: 2em;
1251}
1252'
1253    ]
1254
1255    updateRoot: anHtmlRoot [
1256	<category: 'path'>
1257	super updateRoot: anHtmlRoot.
1258	anHtmlRoot stylesheet url: WAFileLibraryDemo / #mainCss
1259    ]
1260]
1261
1262
1263
1264WAFunctionalTest subclass: WAFlowTest [
1265
1266    <comment: nil>
1267    <category: 'Seaside-Tests-Functional'>
1268
1269    depth: aContext [
1270	<category: 'private'>
1271	| depth current |
1272	depth := 0.
1273	current := aContext.
1274	[current isNil] whileFalse:
1275		[current := current parentContext.
1276		depth := depth + 1].
1277	^depth
1278    ]
1279
1280    goAnchors [
1281	<category: 'actions'>
1282	| component |
1283	1 to: 5
1284	    do:
1285		[:each |
1286		component := WAComponent new.
1287		component addMessage:
1288			[:html |
1289			(html anchor)
1290			    callback: [component answer];
1291			    with: each seasideString , ': ' , (self depth: thisContext) seasideString].
1292		self call: component]
1293    ]
1294
1295    goButtons [
1296	<category: 'actions'>
1297	1 to: 5
1298	    do: [:each | self inform: each seasideString , ': ' , (self depth: thisContext) seasideString]
1299    ]
1300
1301    label [
1302	<category: 'accessing'>
1303	^'Flow'
1304    ]
1305
1306    renderContentOn: html [
1307	<category: 'rendering'>
1308	html
1309	    paragraph: 'The following two anchors should trigger flows with 5 steps each. The stack should neither grow nor shrink. Backtracking and spawning of windows should properly work.'.
1310	html paragraph:
1311		[(html anchor)
1312		    callback: [self goAnchors];
1313		    with: 'go anchors'.
1314		html break.
1315		(html anchor)
1316		    callback: [self goButtons];
1317		    with: 'go buttons']
1318    ]
1319]
1320
1321
1322
1323WAFunctionalTest subclass: WAHomeTest [
1324    | main |
1325
1326    <comment: nil>
1327    <category: 'Seaside-Tests-Functional'>
1328
1329    children [
1330	<category: 'accessing'>
1331	^Array with: main
1332    ]
1333
1334    initialize [
1335	<category: 'initialize-release'>
1336	super initialize.
1337	main := WATaskTest new
1338    ]
1339
1340    label [
1341	<category: 'accessing'>
1342	^'Home'
1343    ]
1344
1345    renderContentOn: html [
1346	<category: 'rendering'>
1347	(html anchor)
1348	    callback: [main home];
1349	    with: 'Home'.
1350	html break.
1351	html render: main
1352    ]
1353]
1354
1355
1356
1357WAFunctionalTest subclass: WAHtmlTest [
1358    | booleanList message number |
1359
1360    <comment: nil>
1361    <category: 'Seaside-Tests-Functional'>
1362
1363    allSelectors [
1364	<category: 'accessing'>
1365	^(self class selectors asSortedCollection
1366	    select: [:s | s startsWith: 'render'])
1367	    remove: #renderContentOn:;
1368	    yourself
1369    ]
1370
1371    initialMessage [
1372	<category: 'accessing'>
1373	^'Hello world!'
1374    ]
1375
1376    initialize [
1377	<category: 'initialize-release'>
1378	super initialize.
1379	message := self initialMessage.
1380	booleanList := #(#a #b #c #d)
1381		    collect: [:key | key -> (Array with: true with: false) atRandom].
1382	number := 10 atRandom
1383    ]
1384
1385    label [
1386	<category: 'accessing'>
1387	^'Form Elements'
1388    ]
1389
1390    message [
1391	<category: 'accessing'>
1392	^message
1393    ]
1394
1395    message: aString [
1396	<category: 'accessing'>
1397	message := aString
1398    ]
1399
1400    number [
1401	<category: 'accessing'>
1402	^number
1403    ]
1404
1405    number: anInteger [
1406	<category: 'accessing'>
1407	number := anInteger
1408    ]
1409
1410    renderCheckboxesOn: html [
1411	<category: 'rendering'>
1412	html text: booleanList.
1413	html paragraph.
1414	html form:
1415		[booleanList do:
1416			[:association |
1417			html
1418			    text: association key;
1419			    space.
1420			(html checkbox)
1421			    addShortcut: 'Ctrl-' , association key asUppercase;
1422			    on: #value of: association.
1423			(html span)
1424			    class: 'indented';
1425			    class: 'hint';
1426			    with: 'Shortcuts: ' , 'Ctrl-' , association key asUppercase.
1427			html break].
1428		html submitButton]
1429    ]
1430
1431    renderContentOn: html [
1432	"don't use pairsDo:, doesn't work for JPMorgan"
1433
1434	<category: 'rendering'>
1435	| selectors indices |
1436	selectors := self allSelectors.
1437	indices := (1 to: selectors size) select: [:each | each odd].
1438	indices do:
1439		[:index |
1440		(html div)
1441		    class: 'row';
1442		    with:
1443			    [(html div)
1444				class: 'left';
1445				with: [self perform: (selectors at: index) with: html].
1446			    index < selectors size
1447				ifTrue:
1448				    [(html div)
1449					class: 'left';
1450					with: [self perform: (selectors at: index + 1) with: html]]]]
1451    ]
1452
1453    renderRadioButtonsOn: html [
1454	<category: 'rendering'>
1455	html text: booleanList.
1456	html paragraph.
1457	html form:
1458		[booleanList do:
1459			[:association |
1460			| group |
1461			group := html radioGroup.
1462			html
1463			    text: association key;
1464			    space.
1465			(group radioButton)
1466			    addShortcut: 'Ctrl-' , association key;
1467			    selected: association value;
1468			    callback: [association value: true].
1469			(group radioButton)
1470			    addShortcut: 'Alt-' , association key;
1471			    selected: association value not;
1472			    callback: [association value: false].
1473			(html span)
1474			    class: 'indented';
1475			    class: 'hint';
1476			    with: 'Shortcuts: ' , 'Ctrl-' , association key , ' Alt-' , association key.
1477			html break].
1478		html submitButton]
1479    ]
1480
1481    renderSelectsOn: html [
1482	<category: 'rendering'>
1483	html text: number.
1484	html paragraph.
1485	html form:
1486		[(html select)
1487		    list: (1 to: 10);
1488		    on: #number of: self.
1489		html submitButton]
1490    ]
1491
1492    renderSubmitButtonsOn: html [
1493	<category: 'rendering'>
1494	html text: number.
1495	html paragraph.
1496	html form:
1497		[1 to: 10
1498		    do:
1499			[:index |
1500			(html submitButton)
1501			    addShortcut: 'F' , index seasideString;
1502			    callback: [number := index];
1503			    text: index.
1504			html space]].
1505	(html span)
1506	    class: 'hint';
1507	    with: 'Above, you may be able to use F1 .. F10 as shortcuts, if the browser allows you.'
1508    ]
1509
1510    renderTextAreaOn: html [
1511	<category: 'rendering'>
1512	| position |
1513	position := message = self initialMessage ifTrue: [6] ifFalse: ['End'].
1514	html form:
1515		[html text: message.
1516		(html paragraph)
1517		    class: 'hint';
1518		    with: 'The text area below should have the focus and be wholly selected, unless it has its initial value, '
1519				, self initialMessage printString
1520				    , ', in which case you should see the cursor right after the "o" of "Hello".'.
1521		(html textArea)
1522		    setCursorPosition: position;
1523		    on: #message of: self.
1524		html break.
1525		html submitButton]
1526    ]
1527
1528    renderTextInputOn: html [
1529	<category: 'rendering'>
1530	html form:
1531		[html text: message.
1532		html paragraph.
1533		html textInput on: #message of: self.
1534		html submitButton]
1535    ]
1536
1537    renderVFieldSetOn: html [
1538	<category: 'rendering'>
1539	(html fieldSet)
1540	    legend: 'Various text rendering in a fieldset';
1541	    with:
1542		    [html
1543			strong: 'Strong';
1544			break;
1545			emphasis: 'Emphasis';
1546			break.
1547		    (html acronym)
1548			title: 'United States of America';
1549			with: 'USA'.
1550		    html
1551			break;
1552			emphasis: 'Emphasis';
1553			break.
1554		    (html div)
1555			style: 'color: red';
1556			style: 'background-color: lightgreen';
1557			style: 'padding: 1em';
1558			style: 'border: solid 2px black';
1559			style: 'font-weight: bold';
1560			style: 'font-size: 150%';
1561			style: 'height: 3em';
1562			style: 'text-align: center';
1563			with: 'Large bold red in a green div'.
1564		    html break]
1565    ]
1566
1567    renderZFieldSetOn: html [
1568	<category: 'rendering'>
1569	| url |
1570	url := html context
1571		    urlForDocument: WAStandardFiles default inspectorPng
1572		    mimeType: 'image/png'
1573		    fileName: 'Debug.jpg'.
1574	(html fieldSet)
1575	    legend: 'Various images in a fieldset';
1576	    with:
1577		    [(html image)
1578			url: url;
1579			altText: 'Halo-Debug'.
1580		    html space.
1581		    html break.
1582		    (html image)
1583			url: WAHandlerEditorFiles / #logoPng;
1584			width: '80%';
1585			altText: 'Seaside'.
1586		    html break.
1587		    (html image)
1588			url: WAHandlerEditorFiles / #logoPng;
1589			height: '50px';
1590			altText: 'Seaside'.
1591		    html break.
1592		    (html image)
1593			url: WAHandlerEditorFiles / #logoPng;
1594			width: '250px';
1595			height: '60px';
1596			altText: 'Seaside']
1597    ]
1598
1599    style [
1600	<category: 'rendering'>
1601	^'
1602div.row {
1603	clear: both
1604}
1605
1606div.left {
1607	float: left;
1608	width: 45%;
1609	margin: 1%
1610}
1611
1612.indented {
1613	margin-left: 2em;
1614}
1615
1616.hint {
1617	font-family: Tahoma, Arial;
1618	font-size: small;
1619}
1620'
1621    ]
1622]
1623
1624
1625
1626WAFunctionalTest subclass: WAIframeTest [
1627    | counter |
1628
1629    <comment: nil>
1630    <category: 'Seaside-Tests-Functional'>
1631
1632    children [
1633	<category: 'accessing'>
1634	^Array with: counter
1635    ]
1636
1637    initialize [
1638	<category: 'initialization'>
1639	super initialize.
1640	counter := WACounter new
1641    ]
1642
1643    label [
1644	<category: 'accessing'>
1645	^'Iframe'
1646    ]
1647
1648    renderContentOn: html [
1649	<category: 'rendering'>
1650	html iframe contents: counter.
1651	html
1652	    break;
1653	    break.
1654	html iframe
1655	    url: (WADispatcher default entryPointAt: WACounter entryPointName) basePath.
1656	html
1657	    break;
1658	    break.
1659	html iframe document: WAHandlerEditorFiles default logoPng
1660	    mimeType: 'image/jpeg'
1661    ]
1662
1663    style [
1664	<category: 'rendering'>
1665	^'iframe {
1666	border: 1px solid gray;
1667	width: 100%;
1668}'
1669    ]
1670]
1671
1672
1673
1674WAFunctionalTest subclass: WAImageMapTest [
1675
1676    <comment: nil>
1677    <category: 'Seaside-Tests-Functional'>
1678
1679    clickedAt: aPoint id: aString [
1680	<category: 'actions'>
1681	self inform: 'Clicked at ' , aPoint seasideString , ' on ' , aString seasideString
1682    ]
1683
1684    label [
1685	<category: 'accessing'>
1686	^'Image map (ismap)'
1687    ]
1688
1689    renderContentOn: html [
1690	<category: 'rendering'>
1691	(html heading)
1692	    level: 3;
1693	    with: 'A byte array with server side map (ismap)'.
1694	(html map)
1695	    title: 'Click anywhere on the Seaside logo';
1696	    id: #map1;
1697	    callback: [:aPoint | self clickedAt: aPoint id: 'the Seaside logo'];
1698	    with:
1699		    [(html image)
1700			altText: 'Seaside logo';
1701			width: '40%';
1702			document: WAHandlerEditorFiles new logoPng
1703			    mimeType: 'image/jpg'
1704			    fileName: 'seasideLogo.jpg']
1705    ]
1706]
1707
1708
1709
1710WAFunctionalTest subclass: WAInputTest [
1711    | inputElements |
1712
1713    <comment: nil>
1714    <category: 'Seaside-Tests-Functional'>
1715
1716    WAInputTest class >> description [
1717	<category: 'accessing'>
1718	^'Various XHTML form input elements'
1719    ]
1720
1721    WAInputTest class >> example [
1722	<category: 'accessing'>
1723	^self new
1724    ]
1725
1726    children [
1727	<category: 'accessing'>
1728	^Array with: inputElements
1729    ]
1730
1731    initialize [
1732	<category: 'initialization'>
1733	super initialize.
1734	inputElements := WAInputElementContainer new
1735    ]
1736
1737    label [
1738	<category: 'accessing'>
1739	^'Input'
1740    ]
1741
1742    renderContentOn: html [
1743	<category: 'rendering'>
1744	html form:
1745		[html table: inputElements.
1746		html submitButton]
1747    ]
1748]
1749
1750
1751
1752WAFunctionalTest subclass: WALinkSubmitTest [
1753    | count |
1754
1755    <comment: nil>
1756    <category: 'Seaside-Tests-Functional'>
1757
1758    count [
1759	<category: 'accessing'>
1760	^count
1761    ]
1762
1763    count: anIntegerOrString [
1764	<category: 'accessing'>
1765	count := anIntegerOrString asInteger
1766    ]
1767
1768    initialize [
1769	<category: 'initialize-release'>
1770	super initialize.
1771	count := 0
1772    ]
1773
1774    label [
1775	<category: 'accessing'>
1776	^'Submit'
1777    ]
1778
1779    renderContentOn: html [
1780	<category: 'rendering'>
1781	| formId |
1782	formId := #myform.
1783	(html form)
1784	    id: formId;
1785	    with:
1786		    [html textInput on: #count of: self.
1787		    html break.
1788		    (html anchor)
1789			id: #decreaseLink;
1790			addShortcut: 'Ctrl-Down';
1791			callback: [count := count - 1];
1792			submitFormNamed: formId;
1793			with: '--'.
1794		    html space.
1795		    (html anchor)
1796			id: #increaseLink;
1797			addShortcut: 'Ctrl-Up';
1798			callback: [count := count + 1];
1799			submitFormNamed: formId;
1800			with: '++'.
1801		    html
1802			break;
1803			break.
1804		    count = 0
1805			ifFalse:
1806			    [(html checkbox)
1807				addShortcut: 'Ctrl-Z';
1808				addShortcut: 'Ctrl-z';
1809				value: count = 0;
1810				callback: [:value | value ifTrue: [count := 0]];
1811				submitFormNamed: formId.
1812			    html space.
1813			    html text: 'Reset']].
1814	html emphasis: 'Handy shortcuts : Ctrl-Up, Ctrl-Down and Ctrl-Z'
1815    ]
1816]
1817
1818
1819
1820WAFunctionalTest subclass: WALotsaLinksTest [
1821
1822    <comment: nil>
1823    <category: 'Seaside-Tests-Functional'>
1824
1825    label [
1826	<category: 'accessing'>
1827	^'Links'
1828    ]
1829
1830    renderContentOn: html [
1831	<category: 'rendering'>
1832	html unorderedList:
1833		[1 to: 5000
1834		    do:
1835			[:each |
1836			html listItem:
1837				[(html anchor)
1838				    callback: [self inform: each];
1839				    with: each]]]
1840    ]
1841]
1842
1843
1844
1845WAFunctionalTest subclass: WAMiniCalendarTest [
1846    | calendar |
1847
1848    <comment: nil>
1849    <category: 'Seaside-Tests-Functional'>
1850
1851    children [
1852	<category: 'accessing'>
1853	^Array with: calendar
1854    ]
1855
1856    initialize [
1857	<category: 'initialize-release'>
1858	super initialize.
1859	calendar := WAMiniCalendar new
1860    ]
1861
1862    label [
1863	<category: 'accessing'>
1864	^'Mini Calendar'
1865    ]
1866
1867    renderContentOn: html [
1868	<category: 'rendering'>
1869	html render: calendar.
1870	html strong: 'selected:'.
1871	html space.
1872	html render: calendar date
1873    ]
1874]
1875
1876
1877
1878WAFunctionalTest subclass: WAModelTest [
1879    | state user pass test |
1880
1881    <comment: nil>
1882    <category: 'Seaside-Tests-Functional'>
1883
1884    label [
1885	<category: 'accessing'>
1886	^'Model'
1887    ]
1888
1889    logoff [
1890	<category: 'actions'>
1891	state := #OFF.
1892	test ifTrue: [self inform: 'Logged off']
1893    ]
1894
1895    logon [
1896	<category: 'actions'>
1897	user isEmptyOrNil
1898	    ifTrue: [self inform: 'Nope !']
1899	    ifFalse:
1900		[state := #ON.
1901		test ifTrue: [self inform: 'Logged on']]
1902    ]
1903
1904    pass [
1905	"Answer the value of pass"
1906
1907	<category: 'accessing'>
1908	^pass
1909    ]
1910
1911    pass: anObject [
1912	"Set the value of pass"
1913
1914	<category: 'accessing'>
1915	pass := anObject
1916    ]
1917
1918    renderButtonOn: html [
1919	<category: 'rendering'>
1920	| action |
1921	action := state == #ON ifTrue: [#logoff] ifFalse: [#logon].
1922	html submitButton on: action of: self
1923    ]
1924
1925    renderContentOn: html [
1926	<category: 'rendering'>
1927	(html form)
1928	    id: 'myform';
1929	    with:
1930		    [html table:
1931			    [self renderUsernameOn: html.
1932			    self renderPasswordOn: html.
1933			    self renderFeedbackOn: html].
1934		    self renderButtonOn: html]
1935    ]
1936
1937    renderFeedbackOn: html [
1938	<category: 'rendering'>
1939	html tableRow:
1940		[html tableData:
1941			[(html label)
1942			    for: #withFeedback;
1943			    with: 'With Feedback:'].
1944		html tableData:
1945			[(html checkbox)
1946			    id: #withFeedback;
1947			    on: #test of: self]]
1948    ]
1949
1950    renderPasswordOn: html [
1951	<category: 'rendering'>
1952	html tableRow:
1953		[html tableData:
1954			[(html label)
1955			    for: #pass;
1956			    with: 'Password:'].
1957		html tableData:
1958			[(html passwordInput)
1959			    id: #pass;
1960			    on: #pass of: self]]
1961    ]
1962
1963    renderUsernameOn: html [
1964	<category: 'rendering'>
1965	html tableRow:
1966		[html tableData:
1967			[(html label)
1968			    for: #userid;
1969			    with: 'Username:'].
1970		html tableData:
1971			[(html textInput)
1972			    id: #userid;
1973			    on: #user of: self]]
1974    ]
1975
1976    test [
1977	"Answer the value of test"
1978
1979	<category: 'accessing'>
1980	^test
1981    ]
1982
1983    test: anObject [
1984	"Set the value of test"
1985
1986	<category: 'accessing'>
1987	test := anObject
1988    ]
1989
1990    user [
1991	"Answer the value of user"
1992
1993	<category: 'accessing'>
1994	^user
1995    ]
1996
1997    user: anObject [
1998	"Set the value of user"
1999
2000	<category: 'accessing'>
2001	user := anObject
2002    ]
2003]
2004
2005
2006
2007WAFunctionalTest subclass: WAMultipartInputTest [
2008    | inputElements |
2009
2010    <comment: nil>
2011    <category: 'Seaside-Tests-Functional'>
2012
2013    WAMultipartInputTest class >> description [
2014	<category: 'accessing'>
2015	^'Various XHTML form input elements'
2016    ]
2017
2018    WAMultipartInputTest class >> example [
2019	<category: 'accessing'>
2020	^self new
2021    ]
2022
2023    children [
2024	<category: 'accessing'>
2025	^Array with: inputElements
2026    ]
2027
2028    initialize [
2029	<category: 'initialization'>
2030	super initialize.
2031	inputElements := WAInputElementContainer new
2032    ]
2033
2034    label [
2035	<category: 'accessing'>
2036	^'Multipart Input'
2037    ]
2038
2039    renderContentOn: html [
2040	<category: 'rendering'>
2041	(html form)
2042	    multipart;
2043	    with:
2044		    [html table: inputElements.
2045		    html submitButton]
2046    ]
2047]
2048
2049
2050
2051WAFunctionalTest subclass: WAPathTest [
2052    | counter |
2053
2054    <comment: nil>
2055    <category: 'Seaside-Tests-Functional'>
2056
2057    children [
2058	<category: 'accessing'>
2059	^Array with: counter
2060    ]
2061
2062    initialize [
2063	<category: 'initialize-release'>
2064	super initialize.
2065	counter := WACounter new
2066    ]
2067
2068    label [
2069	<category: 'accessing'>
2070	^'Path'
2071    ]
2072
2073    renderContentOn: html [
2074	<category: 'rendering'>
2075	html anchor name: counter count.
2076	html render: counter
2077    ]
2078
2079    updateUrl: aUrl [
2080	<category: 'path'>
2081	super updateUrl: aUrl.
2082	aUrl addToPath: counter count seasideString.
2083	aUrl fragment: counter count seasideString
2084    ]
2085]
2086
2087
2088
2089WAFunctionalTest subclass: WAPhraseElementsTest [
2090
2091    <comment: nil>
2092    <category: 'Seaside-Tests-Functional'>
2093
2094    label [
2095	<category: 'accessing'>
2096	^'Phrase'
2097    ]
2098
2099    renderAbbreviatedOn: html [
2100	<category: 'rendering'>
2101	(html heading)
2102	    level2;
2103	    with: '<abbr>'.
2104	(html abbreviated)
2105	    title: 'World Wide Web';
2106	    with: 'WWW'
2107    ]
2108
2109    renderAcronymOn: html [
2110	<category: 'rendering'>
2111	(html heading)
2112	    level2;
2113	    with: '<acronym>'.
2114	(html acronym)
2115	    title: 'Federal Bureau of Investigation';
2116	    with: 'F.B.I.'
2117    ]
2118
2119    renderAddressOn: html [
2120	<category: 'rendering'>
2121	(html heading)
2122	    level2;
2123	    with: '<address>'.
2124	html address:
2125		[#('Newsletter editor' 'J.R. Brown' 'JimquickPost News, Jimquick, CT 01234' 'Tel (123) 456 7890')
2126		    do: [:each | html text: each]
2127		    separatedBy: [html break]]
2128    ]
2129
2130    renderCodeOn: html [
2131	<category: 'rendering'>
2132	(html heading)
2133	    level2;
2134	    with: '<code>'.
2135	html text: 'Expressions like '.
2136	html code: 'a[i++] + b[i++]'.
2137	html text: ' should not be used, since they cause undefined behavior'
2138    ]
2139
2140    renderContentOn: html [
2141	<category: 'rendering'>
2142	self renderHarryOn: html.
2143	self renderAbbreviatedOn: html.
2144	self renderAcronymOn: html.
2145	self renderKeyboardInputOn: html.
2146	self renderVariableOn: html.
2147	self renderCodeOn: html.
2148	self renderDefinitionOn: html.
2149	self renderSampleOn: html.
2150	self renderAddressOn: html.
2151	self renderModificationOn: html
2152    ]
2153
2154    renderDefinitionOn: html [
2155	<category: 'rendering'>
2156	(html heading)
2157	    level2;
2158	    with: '<dfn>'.
2159	html definition: 'Ichthyology'.
2160	html text: ' is the branch of natural science which
2161studies fish.'
2162    ]
2163
2164    renderHarryOn: html [
2165	<category: 'rendering'>
2166	(html heading)
2167	    level2;
2168	    with: '<cite>, <q>, <strong>'.
2169	html text: 'As '.
2170	html citation: 'Harry S. Truman'.
2171	html text: ' said, '.
2172	html quote: 'The buck stops here.'.
2173	html break.
2174	html text: 'More information can be found in '.
2175	html citation: '[ISO-0000]'.
2176	html text: '.'.
2177	html break.
2178	html
2179	    text: 'Please refer to the following reference number in future correspondence: '.
2180	html strong: '1-234-55'
2181    ]
2182
2183    renderKeyboardInputOn: html [
2184	<category: 'rendering'>
2185	(html heading)
2186	    level2;
2187	    with: '<kbd>'.
2188	html text: 'Finally, type '.
2189	html keyboard: 'logout'.
2190	html text: ' and press the return key.'
2191    ]
2192
2193    renderModificationOn: html [
2194	<category: 'rendering'>
2195	(html heading)
2196	    level2;
2197	    with: '<ins>, <del>'.
2198	html paragraph:
2199		[html text: 'A Sheriff can employ '.
2200		(html deleted)
2201		    title: 'Changed as a result of the SECURE bill.';
2202		    cite: 'http://www.w3.org/TR/html401/struct/text.html#edef-del';
2203		    datetime: '1994-11-05T08:15:30-05:00';
2204		    with: 3.
2205		(html inserted)
2206		    title: 'Changed as a result of the SECURE bill.';
2207		    cite: 'http://www.w3.org/TR/html401/struct/text.html#edef-del';
2208		    datetime: '1994-11-05T08:15:30-05:00';
2209		    with: 5.
2210		html text: ' deputies.']
2211    ]
2212
2213    renderSampleOn: html [
2214	<category: 'rendering'>
2215	(html heading)
2216	    level2;
2217	    with: '<samp>'.
2218	html
2219	    text: 'If you select the ''champion'' option, you will receive the message '.
2220	html sample: 'The monkey is not a caterpillar'.
2221	html text: '.'
2222    ]
2223
2224    renderVariableOn: html [
2225	<category: 'rendering'>
2226	(html heading)
2227	    level2;
2228	    with: '<var>'.
2229	html
2230	    text: 'In the simplest case, the command for deleting a file in Unix is'.
2231	html break.
2232	html keyboard: 'rm'.
2233	html space.
2234	html variable: 'filename'
2235    ]
2236]
2237
2238
2239
2240WAFunctionalTest subclass: WAPopupTest [
2241
2242    <comment: nil>
2243    <category: 'Seaside-Tests-Functional'>
2244
2245    counterLoop [
2246	<category: 'actions'>
2247	WARenderLoop new call: WACounter new
2248    ]
2249
2250    label [
2251	<category: 'accessing'>
2252	^'Popup'
2253    ]
2254
2255    renderContentOn: html [
2256	<category: 'rendering'>
2257	(html popupAnchor)
2258	    callback: [self counterLoop];
2259	    with: 'popup'.
2260	html break.
2261	(html popupAnchor)
2262	    extent: 100 @ 100;
2263	    callback: [self counterLoop];
2264	    with: 'popup with extent'.
2265	html break.
2266	(html popupAnchor)
2267	    position: 100 @ 100;
2268	    callback: [self counterLoop];
2269	    with: 'popup with position'.
2270	html break.
2271	(html popupAnchor)
2272	    location: true;
2273	    callback: [self counterLoop];
2274	    with: 'popup with location'.
2275	html break.
2276	(html popupAnchor)
2277	    resizable: false;
2278	    callback: [self counterLoop];
2279	    with: 'popup not resizable'
2280    ]
2281]
2282
2283
2284
2285WAFunctionalTest subclass: WARubyTest [
2286
2287    <comment: 'Examples taken directly from spec:
2288http://www.w3.org/TR/2001/REC-ruby-20010531/
2289'>
2290    <category: 'Seaside-Tests-Functional'>
2291
2292    label [
2293	<category: 'accessing'>
2294	^'Ruby'
2295    ]
2296
2297    renderComplexOn: html [
2298	<category: 'rendering'>
2299	(html heading)
2300	    level2;
2301	    with: 'Complex ruby markup'.
2302	html ruby:
2303		[html rubyBaseContainer:
2304			[html rubyBase: 10.
2305			html rubyBase: 31.
2306			html rubyBase: 2002].
2307		html rubyTextContainer:
2308			[html rubyText: 'Month'.
2309			html rubyText: 'Day'.
2310			html rubyText: 'Year'].
2311		html rubyTextContainer:
2312			[(html rubyText)
2313			    span: 3;
2314			    with: 'Expiration Date']]
2315    ]
2316
2317    renderContentOn: html [
2318	<category: 'rendering'>
2319	self renderSimpleOn: html.
2320	self renderSimpleParenthesesOn: html.
2321	self renderComplexOn: html
2322    ]
2323
2324    renderSimpleOn: html [
2325	<category: 'rendering'>
2326	(html heading)
2327	    level2;
2328	    with: 'Simple ruby markup'.
2329	html ruby:
2330		[html rubyBase: 'WWW'.
2331		html rubyText: 'World Wide Web']
2332    ]
2333
2334    renderSimpleParenthesesOn: html [
2335	<category: 'rendering'>
2336	(html heading)
2337	    level2;
2338	    with: 'Simple ruby markup with parentheses'.
2339	html ruby:
2340		[html rubyBase: 'WWW'.
2341		html rubyParentheses: '('.
2342		html rubyText: 'World Wide Web'.
2343		html rubyParentheses: ')']
2344    ]
2345]
2346
2347
2348
2349WAFunctionalTest subclass: WASvgTest [
2350
2351    <comment: nil>
2352    <category: 'Seaside-Tests-Functional'>
2353
2354    label [
2355	<category: 'accessing'>
2356	^'<object>'
2357    ]
2358
2359    renderContentOn: html [
2360	<category: 'rendering'>
2361	(html object)
2362	    type: 'image/svg+xml' toMimeType;
2363	    width: 600;
2364	    height: 800;
2365	    standby: 'loading tiger';
2366	    classId: 'http://www.adobe.com/svg/viewer/install/main.html';
2367	    url: 'http://croczilla.com/svg/samples/tiger/tiger.svg';
2368	    with: 'Your browser doesn''t support SVG'
2369    ]
2370]
2371
2372
2373
2374WAFunctionalTest subclass: WATableReportTest [
2375    | report |
2376
2377    <comment: nil>
2378    <category: 'Seaside-Tests-Functional'>
2379
2380    WATableReportTest class >> example [
2381	<category: 'accessing'>
2382	^self new
2383    ]
2384
2385    children [
2386	<category: 'accessing'>
2387	^Array with: report
2388    ]
2389
2390    initialize [
2391	<category: 'initialization'>
2392	super initialize.
2393	report := (WATableReport new)
2394		    rows: WAComponent allSubclasses asArray;
2395		    columns: ((OrderedCollection new)
2396				add: (WAReportColumn
2397					    selector: #fullName
2398					    title: 'Name'
2399					    onClick: [:each | self inform: each description]);
2400				add: ((WAReportColumn selector: #canBeRoot title: 'Can Be Root')
2401					    sortBlock: [:a :b | a]);
2402				add: (WAReportColumn
2403					    renderBlock: [:each :html | html emphasis: each description]
2404					    title: 'Description');
2405				yourself);
2406		    rowColors: #(#lightblue #lightyellow);
2407		    rowPeriod: 1;
2408		    yourself
2409    ]
2410
2411    label [
2412	<category: 'accessing'>
2413	^'Table Report'
2414    ]
2415]
2416
2417
2418
2419WAFunctionalTest subclass: WATransactionTest [
2420    | nestedTransation |
2421
2422    <comment: 'A WATransactionTest runs a WANestedTransaction with a description'>
2423    <category: 'Seaside-Tests-Functional'>
2424
2425    children [
2426	<category: 'accessing'>
2427	^Array with: nestedTransation
2428    ]
2429
2430    initialize [
2431	<category: 'initialize-release'>
2432	super initialize.
2433	nestedTransation := WANestedTransaction new
2434    ]
2435
2436    label [
2437	<category: 'accessing'>
2438	^'Transaction'
2439    ]
2440
2441    renderContentOn: html [
2442	<category: 'rendering'>
2443	self renderExplanationOn: html.
2444	html render: nestedTransation
2445    ]
2446
2447    renderExplanationOn: html [
2448	<category: 'rendering'>
2449	html paragraph:
2450		[html
2451		    text: 'This checks if nested #isolate: block work. It has the following nested transactions:'.
2452		html orderedList:
2453			[html listItem: 'Inside parent txn'.
2454			html listItem:
2455				[html orderedList: [html listItem: 'Inside child txn'].
2456				html listItem: 'Outside child txn']].
2457		html
2458		    text: 'if you leave the child transaction and enter it with the back button you should end up in the parent transaction. If you leave the parent transaction with the back button and enter either it or the child transaction with the back button you should end up outside the parent transaction.']
2459    ]
2460]
2461
2462
2463
2464WAFunctionalTest subclass: WAUploadTest [
2465    | file |
2466
2467    <comment: nil>
2468    <category: 'Seaside-Tests-Functional'>
2469
2470    label [
2471	<category: 'accessing'>
2472	^'Upload'
2473    ]
2474
2475    renderContentOn: html [
2476	<category: 'rendering'>
2477	html heading: 'Upload File'.
2478	(html form)
2479	    multipart;
2480	    with:
2481		    [html fileUpload callback: [:f | file := f].
2482		    html submitButton text: 'Load'].
2483	file ifNotNil:
2484		[:foo |
2485		(html anchor)
2486		    document: file contents
2487			mimeType: file contentType
2488			fileName: file fileName;
2489		    with: file fileName , ' (' , file contentType seasideString , ')'.
2490		html break.
2491		(html anchor)
2492		    document: file contents;
2493		    with: file fileName.
2494		html preformatted: file contents]
2495    ]
2496]
2497
2498
2499
2500WAComponent subclass: WAInputElementContainer [
2501    | textInput textInputExample textArea textAreaExample singleSelection singleSelectionOptional multiSelection nestedSelection |
2502
2503    <comment: nil>
2504    <category: 'Seaside-Tests-Functional'>
2505
2506    elements [
2507	<category: 'accessing'>
2508	^#(#Quito #Dakar #Sydney #Bamako)
2509    ]
2510
2511    exampleText [
2512	<category: 'accessing'>
2513	^'Example Text'
2514    ]
2515
2516    initialize [
2517	<category: 'initialization'>
2518	super initialize.
2519	textInput := textArea := 'Some Text'
2520    ]
2521
2522    nestedElements [
2523	<category: 'accessing'>
2524	^#(#('Functional' #('Haskell ' 'Lisp' 'ML')) #('Dataflow' #('Hartmann pipelines' 'G' 'Max' 'Prograph')) #('Fourth-generation' #('Today' 'Ubercode' 'Uniface')))
2525    ]
2526
2527    renderContentOn: html [
2528	<category: 'rendering'>
2529	self renderHeadingOn: html.
2530	self renderTextInputOn: html.
2531	self renderTextInputExampleOn: html.
2532	self renderTextAreaOn: html.
2533	self renderTextAreaExampleOn: html.
2534	self renderSingleSelectionOn: html.
2535	self renderSingleSelectionOptionalOn: html.
2536	self renderSingleSelectionWithoutCallbackOn: html.
2537	self renderMultiSelectionOn: html.
2538	self renderNestedSelectionOn: html
2539    ]
2540
2541    renderHeadingOn: html [
2542	<category: 'rendering-elements'>
2543	html tableRow:
2544		[html tableData.
2545		html tableHeading: 'Control'.
2546		html tableHeading: 'Print String']
2547    ]
2548
2549    renderLabel: aString input: anInputBlock output: anOutputBlock on: html [
2550	<category: 'rendering'>
2551	html tableRow:
2552		[html tableHeading: aString.
2553		html tableData: anInputBlock.
2554		html tableData: anOutputBlock]
2555    ]
2556
2557    renderMultiSelectionOn: html [
2558	<category: 'rendering-elements'>
2559	self
2560	    renderLabel: 'Multi Selection'
2561	    input:
2562		[(html multiSelect)
2563		    list: self elements;
2564		    selected: multiSelection;
2565		    callback: [:value | multiSelection := value]]
2566	    output: [html unorderedList list: multiSelection]
2567	    on: html
2568    ]
2569
2570    renderNestedSelectionOn: html [
2571	<category: 'rendering-elements'>
2572	self
2573	    renderLabel: 'Nested Selection'
2574	    input:
2575		[html select:
2576			[self nestedElements do:
2577				[:list |
2578				(html optionGroup)
2579				    label: list first;
2580				    with:
2581					    [list second do:
2582						    [:each |
2583						    (html option)
2584							selected: nestedSelection = each;
2585							callback: [nestedSelection := each];
2586							with: each]]]]]
2587	    output: nestedSelection printString
2588	    on: html
2589    ]
2590
2591    renderSingleSelectionOn: html [
2592	<category: 'rendering-elements'>
2593	self
2594	    renderLabel: 'Single Selection'
2595	    input:
2596		[(html select)
2597		    list: self elements;
2598		    selected: singleSelection;
2599		    callback: [:value | singleSelection := value]]
2600	    output: singleSelection printString
2601	    on: html
2602    ]
2603
2604    renderSingleSelectionOptionalOn: html [
2605	<category: 'rendering-elements'>
2606	self
2607	    renderLabel: 'Single Selection (Optional)'
2608	    input:
2609		[(html select)
2610		    beOptional;
2611		    list: self elements;
2612		    optionalLabel: '(none)';
2613		    selected: singleSelectionOptional;
2614		    callback: [:value | singleSelectionOptional := value]]
2615	    output: singleSelectionOptional printString
2616	    on: html
2617    ]
2618
2619    renderSingleSelectionWithoutCallbackOn: html [
2620	<category: 'rendering-elements'>
2621	self
2622	    renderLabel: 'Single Selection (Without Callback)'
2623	    input: [html select list: self elements]
2624	    output: nil
2625	    on: html
2626    ]
2627
2628    renderTextAreaExampleOn: html [
2629	<category: 'rendering-elements'>
2630	self
2631	    renderLabel: 'Text Area (Example)'
2632	    input:
2633		[(html textArea)
2634		    value: textAreaExample;
2635		    exampleText: self exampleText;
2636		    callback: [:value | textAreaExample := value]]
2637	    output: textAreaExample printString
2638	    on: html
2639    ]
2640
2641    renderTextAreaOn: html [
2642	<category: 'rendering-elements'>
2643	self
2644	    renderLabel: 'Text Area'
2645	    input:
2646		[(html textArea)
2647		    value: textArea;
2648		    callback: [:value | textArea := value]]
2649	    output: textArea printString
2650	    on: html
2651    ]
2652
2653    renderTextInputExampleOn: html [
2654	<category: 'rendering-elements'>
2655	self
2656	    renderLabel: 'Text Input (Example)'
2657	    input:
2658		[(html textInput)
2659		    value: textInputExample;
2660		    exampleText: self exampleText;
2661		    callback: [:value | textInputExample := value]]
2662	    output: textInputExample printString
2663	    on: html
2664    ]
2665
2666    renderTextInputOn: html [
2667	<category: 'rendering-elements'>
2668	self
2669	    renderLabel: 'Text Input'
2670	    input:
2671		[(html textInput)
2672		    setFocus;
2673		    value: textInput;
2674		    callback: [:value | textInput := value]]
2675	    output: textInput printString
2676	    on: html
2677    ]
2678]
2679
2680
2681
2682WAComponent subclass: WAParentTest [
2683    | parent |
2684
2685    <comment: nil>
2686    <category: 'Seaside-Tests-Functional'>
2687
2688    go [
2689	<category: 'actions'>
2690	parent inform: 'Test green!'
2691    ]
2692
2693    label [
2694	<category: 'accessing'>
2695	^'Parent'
2696    ]
2697
2698    parent: aComponent [
2699	<category: 'accessing'>
2700	parent := aComponent
2701    ]
2702
2703    renderContentOn: html [
2704	<category: 'rendering'>
2705	self renderExplanationOn: html.
2706	self renderSwapParentOn: html
2707    ]
2708
2709    renderExplanationOn: html [
2710	<category: 'rendering'>
2711	html
2712	    paragraph: 'This regression tests checks if #call: on the parent component works. If you click "swap parent" "Test green!" should appear without a tab panel.'
2713    ]
2714
2715    renderSwapParentOn: html [
2716	<category: 'rendering'>
2717	(html anchor)
2718	    callback: [self go];
2719	    with: 'swap parent'
2720    ]
2721]
2722
2723
2724
2725WAComponent subclass: WATaskTest [
2726
2727    <comment: nil>
2728    <category: 'Seaside-Tests-Functional'>
2729
2730    renderContentOn: html [
2731	<category: 'rendering'>
2732	(html anchor)
2733	    callback: [self call: WAExceptionTest new];
2734	    with: 'go'
2735    ]
2736]
2737
2738
2739
2740WASession subclass: WAExpirySession [
2741
2742    <comment: nil>
2743    <category: 'Seaside-Tests-Functional'>
2744
2745    Created := nil.
2746    Unregistered := nil.
2747
2748    WAExpirySession class >> created [
2749	<category: 'accessing'>
2750	^Created
2751    ]
2752
2753    WAExpirySession class >> initialize [
2754	<category: 'class initialization'>
2755	self resetCounters
2756    ]
2757
2758    WAExpirySession class >> resetCounters [
2759	<category: 'actions'>
2760	Unregistered := 0.
2761	Created := 0
2762    ]
2763
2764    WAExpirySession class >> unregistered [
2765	<category: 'accessing'>
2766	^Unregistered
2767    ]
2768
2769    initialize [
2770	<category: 'initialize-release'>
2771	super initialize.
2772	Created := Created + 1
2773    ]
2774
2775    unregistered [
2776	<category: 'subclass responsibilities'>
2777	super unregistered.
2778	Unregistered := Unregistered + 1
2779    ]
2780]
2781
2782
2783
2784WATask subclass: WAFunctionalTaskTest [
2785
2786    <comment: nil>
2787    <category: 'Seaside-Tests-Functional'>
2788
2789    label [
2790	<category: 'accessing'>
2791	self subclassResponsibility
2792    ]
2793]
2794
2795
2796
2797WAFunctionalTaskTest subclass: WAConvenienceTest [
2798    | cheese |
2799
2800    <comment: nil>
2801    <category: 'Seaside-Tests-Functional'>
2802
2803    chooseCheese [
2804	<category: 'controlling'>
2805	cheese := self chooseFrom: #('Greyerzer' 'Tilsiter' 'Sbrinz')
2806		    caption: 'What''s your favorite Cheese?'.
2807	cheese isNil ifTrue: [self chooseCheese]
2808    ]
2809
2810    confirmCheese [
2811	<category: 'controlling'>
2812	^self confirm: 'Is ' , cheese , ' your favorite cheese?'
2813    ]
2814
2815    go [
2816	<category: 'controlling'>
2817
2818	[self chooseCheese.
2819	self confirmCheese] whileFalse.
2820	self informCheese
2821    ]
2822
2823    informCheese [
2824	<category: 'controlling'>
2825	self inform: 'Your favorite cheese is ' , cheese , '.'
2826    ]
2827
2828    label [
2829	<category: 'accessing'>
2830	^'Convenience'
2831    ]
2832]
2833
2834
2835
2836WAFunctionalTaskTest subclass: WAExceptionTest [
2837
2838    <comment: nil>
2839    <category: 'Seaside-Tests-Functional'>
2840
2841    go [
2842	<category: 'processing'>
2843	[(self confirm: 'Raise an exception?') ifTrue: [self error: 'foo']]
2844	    on: Error
2845	    do: [:error | self inform: 'Caught: ' , error description]
2846    ]
2847
2848    label [
2849	<category: 'accessing'>
2850	^'Exception'
2851    ]
2852]
2853
2854
2855
2856WATask subclass: WANestedTransaction [
2857
2858    <comment: 'A WANestedTransaction is a test that uses two nested #isolate: blocks'>
2859    <category: 'Seaside-Tests-Functional'>
2860
2861    go [
2862	<category: 'processing'>
2863	self inform: 'Before parent txn'.
2864	self isolate:
2865		[self inform: 'Inside parent txn'.
2866		self isolate: [self inform: 'Inside child txn'].
2867		self inform: 'Outside child txn'].
2868	self inform: 'Outside parent txn'
2869    ]
2870]
2871
2872
2873Eval [
2874    WAAllTests initialize.
2875    WADateSelectorTest initialize.
2876    WAExpirySession initialize
2877]
2878
2879