Using scripter to test the user interfaces
BlScripter
Object << #BlScripter
traits: {TBlDevScripterActionStep + TBlDevScripterCheckStepCreation};
slots: { #element . #space . #events . #rootStep . #eventHandler . #maxPulseElapsedTime };
tag: 'Scripter';
package: 'Bloc-Scripter'
is the framework for scripting and verifying UI interactions in Glamorous Toolkit. It lets users create reproducible scenarios that simulate user actions (clicks, typing, keyboard shortcuts, scrolling) and assert UI state.
The main entry point is BlScripter
Object << #BlScripter
traits: {TBlDevScripterActionStep + TBlDevScripterCheckStepCreation};
slots: { #element . #space . #events . #rootStep . #eventHandler . #maxPulseElapsedTime };
tag: 'Scripter';
package: 'Bloc-Scripter'
. Steps are the building blocks: they model actions or assertions. The scripter manages a BlSpace
Object << #BlSpace
traits: {TBlEventTarget + TBlSpaceProperties + TBlDebug};
slots: {
#id .
#host .
#hostSpace .
#extent .
#position .
#root .
#resizable .
#borderless .
#dirtyAreas .
#eventDispatcher .
#eventListener .
#eventRecorder .
#mouseProcessor .
#focusProcessor .
#keyboardProcessor .
#focusChain .
#dragboard .
#nextPulseRequested .
#currentCursor .
#session .
#focused .
#title .
#fullscreen .
#fullsize .
#layoutError .
#tasks .
#time .
#touchProcessor .
#frame .
#gestureProcessor .
#elementsNeedingPaint .
#elementsNeedingLayout .
#telemetry .
#reference .
#elementsNeedingStyle .
#elementsNeedingPropertiesComputation .
#iconStencil };
sharedVariables: { #UniqueIdGenerator . #UserFontScaleFactor . #UserScaleFactor };
tag: 'Space';
package: 'Bloc'
internally — the UI is live and pulsed between steps to let layout, animations, and tasks settle.
Every scripter example follows this structure:
1. Create a scripter instance
newScripter
<gtExample>
<return: #BlScripter>
^ BlScripter new
2. Set the root UI element
scripterWithElement
<gtExample>
<return: #BlScripter>
| aScripter |
aScripter := self newScripter.
aScripter element: self containerWithRectangle.
^ aScripter
3. Add action steps (simulating user interactions)
clickOnButton
"Demonstrates clicking a button by element ID.
Uses clickStep: which auto-plays the step."
<gtExample>
| aScripter |
aScripter := self scripterWithButton.
aScripter clickStep:
[:s |
s
label: 'Click the test button';
id: #testButton].
^aScripter
4. Add assertion/check steps (verifying UI state)
clickOnButtonAndAssert
"Demonstrates clicking and then asserting the UI changed.
Shows the pattern: action step followed by assertion step."
<gtExample>
| aScripter |
aScripter := self clickOnButton.
aScripter assertStep:
[:s |
s
label: 'Assert button still exists';
exists;
id: #testButton].
^aScripter
5. (Optional) Set a model on the scripter, accessible from steps via #selector
onModel
self target: (BlDevScripterModelTarget new)
scripterWithModel
"Demonstrates setting a model on scripter and asserting on it."
<gtExample>
<return: #BlScripter>
| aScripter |
aScripter := self newScripter.
aScripter model: 42.
aScripter element: self containerWithRectangle.
aScripter assertStep: [ :s |
s
label: 'Assert model is 42';
value: [ :aModel | aModel ] equals: [ 42 ];
onModel ].
^ aScripter
6. Return the scripter (for composition by other examples)
Overall, BlScripterExamples>>#exampleClickButton
exampleClickButton
"Demonstrates the full scripter pattern: create, set element, act, assert."
<gtExample>
| aScripter |
aScripter := BlScripter new.
aScripter element: (BrFrame new
matchParent;
addChild: (BlElement new
id: #myButton;
size: 50 @ 50;
addEventHandlerOn: BlClickEvent do: [ :e |
e currentTarget background: Color green ])).
aScripter clickStep: [ :s | s id: #myButton ].
aScripter assertStep: [ :s |
s
label: 'Assert background is green';
satisfies: [ :el | el background paint color = Color green ];
id: #myButton ].
^ aScripter
shows all these steps using the raw API (without the TBlDevScripterExamples
Trait << #TBlDevScripterExamples
tag: 'Scripter';
package: 'Bloc-Scripter'
trait, to show the minimal setup).
exampleClickButton
"Demonstrates the full scripter pattern: create, set element, act, assert."
<gtExample>
| aScripter |
aScripter := BlScripter new.
aScripter element: (BrFrame new
matchParent;
addChild: (BlElement new
id: #myButton;
size: 50 @ 50;
addEventHandlerOn: BlClickEvent do: [ :e |
e currentTarget background: Color green ])).
aScripter clickStep: [ :s | s id: #myButton ].
aScripter assertStep: [ :s |
s
label: 'Assert background is green';
satisfies: [ :el | el background paint color = Color green ];
id: #myButton ].
^ aScripter
A step (subclass of BlDevScripterStep
Object << #BlDevScripterStep
slots: { #scripter . #state . #label . #properties . #maxPulseElapsedTime };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
) is the fundamental unit of work in a scripter script.
Every step holds a target specification (built via TBlDevScripterTarget
Trait << #TBlDevScripterTarget
tag: 'Scripter';
package: 'Bloc-Scripter'
) that locates the element to act upon or assert against, and implements BlDevScripterStep>>#playOn:
playOn: aScripter
to execute its logic against the scripter.
Steps are composed into trees: composite steps (BlDevScripterCompositeStep
BlDevScripterStep << #BlDevScripterCompositeStep
traits: {TBlDevScripterCompositeStepTarget + TBlDevScripterTarget};
slots: { #steps };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
) group child steps into logical sequences, while leaf steps represent individual atomic interactions or assertions.
When played, a step fires events through the space's simulation API, then the scripter pulses the space so that event handling, layout, and rendering settle before the next step executes.
There are several types of steps like:
- BlDevScripterInteractionStep
BlDevScripterTargetedStep << #BlDevScripterInteractionStep
slots: {};
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: high-level UI interactions (click, double-click, type text, fire events, request focus, shortcuts, wait) defined by subclasses
- BlDevScripterKeyboardStep
BlDevScripterStep << #BlDevScripterKeyboardStep
slots: { #key . #modifiers };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: low-level keyboard events (key down, key up, key press) defined by subclasses
- BlDevScripterMouseStep
BlDevScripterStep << #BlDevScripterMouseStep
slots: { #modifiers };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: low-level mouse events (mouse down, mouse up, mouse move) defined by subclasses
- BlDevScripterToolActionStep
BlDevScripterMultipleActionStep << #BlDevScripterToolActionStep
slots: { #target };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: domain-specific composite steps for GT tools (coder, inspector, pager, filter, etc.) defined by subclasses
- BlDevScripterSetStep
BlDevScripterTargetedStep << #BlDevScripterSetStep
slots: { #storage };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: stores values into the scripter's state during step execution (see BlScripterSetStepUsageExamples
BlScripterStepUsageExamples << #BlScripterSetStepUsageExamples
slots: {};
tag: 'Examples';
package: 'Bloc-Scripter'
)
- BlDevScripterActionStep
BlDevScripterTargetedStep << #BlDevScripterActionStep
slots: { #block };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: executes an arbitrary block during scripter playback (see BlScripterActionStepUsageExamples
BlScripterStepUsageExamples << #BlScripterActionStepUsageExamples
slots: {};
tag: 'Examples';
package: 'Bloc-Scripter'
)
- BlDevScripterCheckStep
BlDevScripterTargetedStep << #BlDevScripterCheckStep
slots: {};
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
: conditions about the current element state defined by subclasses
Steps should be used though an internal DSL not directly by instantiating step class.
The step-creation DSL is defined in the trait TBlDevScripterActionStep
Trait << #TBlDevScripterActionStep
tag: 'Scripter';
package: 'Bloc-Scripter'
. This trait provides factory methods like #selector
click
"Simulates a click event on a target element"
<scripterActionStep>
^ self addStep: (BlDevScripterClickStep new referenceSender)
, #selector
doubleClick
"Simulates a double click event on a target element"
<scripterActionStep>
^ self addStep: (BlDevScripterDoubleClickStep new referenceSender)
, #selector
type: aString
^ self type text: aString; referenceSender
, #selector
shortcut
"Simulates a keyboard shortcut event on a target element. If no target
element is provided, the shortcut is sent to the scripted element."
<scripterActionStep>
^ self addStep: BlDevScripterShortcutStep new referenceSender
, #selector
keyPress: aBlKeyboardKey
"Simulates a keyboard key click event sent to the focused element"
^ self keyPress key: aBlKeyboardKey; referenceSender
, #selector
mouseDown
"Simulates a mouse down event at the current cursor position"
<scripterActionStep>
^ self addStep: (BlDevScripterMouseDownStep new referenceSender)
, #selector
do
"Performs a block closure with a target element as an argument"
<scripterActionStep>
^ self addStep: BlDevScripterActionStep new referenceSender
, #selector
set
"Assigns various optional variables in the scripter such as model or key:value pairs"
<scripterActionStep>
^ self addStep: BlDevScripterSetStep new referenceSender
, #selector
wait
^ self addStep: BlDevScripterWaitStep new referenceSender
, and more. Explore its methods to see all available step creators.
For assertions, the trait TBlDevScripterCheckStepCreation
Trait << #TBlDevScripterCheckStepCreation
tag: 'Scripter';
package: 'Bloc-Scripter'
provides #selector
check
^ (BlDevScripterFutureCheckStep new parent: self) referenceSender
and #selector
assert
"Builds a step to assert the state of the graphical scene"
<scripterActionStep>
^ (BlDevScripterFutureCheckStep new parent: self) referenceSender
steps which return a BlDevScripterFutureCheckStep
BlDevScripterCheckStep << #BlDevScripterFutureCheckStep
traits: {TBlDevScripterCheckStep + TBlDevScripterCheckStepCreation + TBlDevScripterCompositeStepTarget};
slots: { #parent . #hasCustomTarget . #realStep };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
builder supporting: #selector
satisfies: anOneArgBlock
"Given block evaluated with the current target returns true."
<scripterAssert>
^ self addStep: (BlDevScripterCheckElementStep new block: anOneArgBlock; referenceSender)
, #selector
value: anOneArgBlock equals: anEqualsBlock
"Computed value equals to the provided one."
<scripterAssert>
^ self addStep: (BlDevScripterCheckElementValueStep new
valueBlock: anOneArgBlock;
equalsBlock: anEqualsBlock;
referenceSender)
, #selector
exists
"Target element (or other specified object) exists."
<scripterAssert>
^ self addStep: (BlDevScripterCheckElementExistsStep new referenceSender)
, #selector
notExists
"Target element (or other specified object) doesn't exist."
<scripterAssert>
^ self addStep: (BlDevScripterCheckElementNotExistsStep new referenceSender)
, #selector
childrenCount: aNumber
^ self addStep: (BlDevScripterCheckChildrenCountStep new
childrenCount: aNumber;
referenceSender)
, #selector
hasFocus
^ self
addStep: (BlDevScripterCheckElementStep new
label: 'Assert element has focus';
block: [ :anElement | anElement hasFocus ];
description: [ :anElement |
'{1} element must have focus' format: {anElement} ];
referenceSender)
, and more.
To discover available steps, browse its class hierarchy.
- Steps with the Step: suffix (e.g., #selector
clickStep: aBlock
| step |
step := self click.
step referenceSender.
aBlock value: step.
step play
, #selector
assertStep: aBlock
| step |
step := self assert.
aBlock value: step.
step play
, #selector
doStep: aBlock
| step |
step := self do.
step referenceSender.
aBlock value: step.
step play
) that take a block to create the step auto-play immediately; no need to call BlScripter>>#play
play
rootStep play
/BlDevScripterStep>>#play
play
self
assert: [ self scripter notNil ]
description: [ 'Can not play without scripter' ].
self playNoPulse.
self privatePulseUntilReady
.
clickOnButtonAndAssertWithImplicitPlay
"Demonstrates clicking and then asserting the UI changed.
Shows the pattern: action step followed by assertion step
with implicit play actions in the step creation method"
<gtExample>
| aScripter |
aScripter := self scripterWithButton.
aScripter clickStep:
[:s |
s
label: 'Click the test button';
id: #testButton].
aScripter assertStep:
[:s |
s
label: 'Assert button still exists';
exists;
id: #testButton].
^aScripter
- Steps without the suffix (e.g., #selector
click
"Simulates a click event on a target element"
<scripterActionStep>
^ self addStep: (BlDevScripterClickStep new referenceSender)
, #selector
assert
"Builds a step to assert the state of the graphical scene"
<scripterActionStep>
^ (BlDevScripterFutureCheckStep new parent: self) referenceSender
) require explicit play at the end (BlScripter>>#play
play
rootStep play
/BlDevScripterStep>>#play
play
self
assert: [ self scripter notNil ]
description: [ 'Can not play without scripter' ].
self playNoPulse.
self privatePulseUntilReady
.). In case a step has the version that does the auto-play imediately favour that one.
clickOnButtonAndAssertWithExplicitPlay
"Demonstrates clicking and then asserting the UI changed.
Shows the pattern: action step followed by assertion step
with explicit play actions"
<gtExample>
| aScripter |
aScripter := self scripterWithButton.
aScripter click
label: 'Click the test button';
id: #testButton;
play.
aScripter assert
label: 'Assert button still exists';
exists;
id: #testButton;
play.
^aScripter
- Use #selector
substep: aLabel do: anOneArgBlock
^ self substeps: aLabel do: anOneArgBlock
to group related steps logically with a label
mouseDownAndUp
"Demonstrates low-level mouse events: mouseDown followed by mouseUp.
These are the building blocks of click but give more control over timing and position."
<gtExample>
| aScripter container element |
element := (BlElement new)
id: #testElement;
size: 100 @ 100;
background: Color blue.
container := (BrFrame new)
matchParent;
addChild: element.
aScripter := self scripter.
aScripter element: container.
aScripter substep: 'Mouse down then up'
do:
[:aStep |
(aStep mouseDown)
label: 'Press mouse button';
play.
(aStep mouseUp)
label: 'Release mouse button';
play].
^aScripter
- The trait TBlDevScripterExamples
Trait << #TBlDevScripterExamples
tag: 'Scripter';
package: 'Bloc-Scripter'
provides factory methods (#selector
scripter
<gtExample>
<return: #BlScripter>
| aScripter |
aScripter := BlScripter new.
self assert: aScripter events isEmpty.
^ aScripter
, #selector
scripterWithElement: anElementBlock
<gtExample>
^ self
scripter: self scripter
withModel: [ nil ]
element: anElementBlock
, #selector
scripterWithModel: aModelBlock element: anElementBlock
<gtExample>
^ self
scripter: self scripter
withModel: aModelBlock
element: anElementBlock
) — use it in example classes
Steps locate elements using a fluent DSL defined in the trait TBlDevScripterTarget
Trait << #TBlDevScripterTarget
tag: 'Scripter';
package: 'Bloc-Scripter'
(mixed into BlDevScripterCompositeStep
BlDevScripterStep << #BlDevScripterCompositeStep
traits: {TBlDevScripterCompositeStepTarget + TBlDevScripterTarget};
slots: { #steps };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
and BlDevScripterTargetedStep
BlDevScripterStep << #BlDevScripterTargetedStep
traits: {TBlDevScripterTarget};
slots: { #target };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
).
Examples of generic methods for controling the scripter target:
- #selector
id: aBlElementId
"Find an element with a given index (depth first)"
<scripterStepTarget>
self updateTarget: (BlDevScripterElementIdEventTarget new elementId: aBlElementId)
— find by element ID
- #selector
// aBlElementQueryByPropertySelector
"Selects among all children (depth first) based on a given selector such as id or class"
<scripterStepTarget>
self updateTarget: (BlDevScripterOneElementQueryEventTarget new // aBlElementQueryByPropertySelector)
— descendant search (like CSS descendant selector)
- #selector
onChildAt: aNumber
"Select the Nth direct child of the current target"
<scripterStepTarget>
self updateTarget: (BlDevScripterIndexedChildEventTarget new index: aNumber)
— nth child (1-based)
- #selector
onBreadthFirstChildOfClass: aClass
self updateTarget: (BlDevScripterDeepChildOfClassEventTarget new elementClass: aClass)
— breadth-first search by class
- #selector
@ aBlElementQueryByPredicate
"Filters the result of the previous selection based on a predicate (such as index)"
<scripterStepTarget>
self updateTarget: (BlDevScripterOneElementQueryEventTarget new @ aBlElementQueryByPredicate)
— filter by block predicate
- #selector
onModel
self target: (BlDevScripterModelTarget new)
— target the scripter's model instead of an element
- #selector
onSelf
self target: BlDevScripterSelfEventTarget new
— target the current element
- #selector
onSpace
self target: (BlDevScripterSpaceTarget new)
/ #selector
onSpaceRoot
self target: BlDevScripterSpaceRootTarget new
— target the space
A part from generic targeting methods, tools can add using extension metods other methods to TBlDevScripterTarget
Trait << #TBlDevScripterTarget
tag: 'Scripter';
package: 'Bloc-Scripter'
that provide domain-specific ways to identify elements, like TBlDevScripterTarget>>#onPagerPaneWithIndex:
onPagerPaneWithIndex: anInteger
GtPagerSettings isTreePager
ifFalse: [ self // (GtPagerPageElementId indexed: anInteger) ]
ifTrue: [ (self // GtTreePagerPaneElement)
@ [ :eachPaneElement |
eachPaneElement constraints horizontalTreeFlow depth = anInteger
and: [ eachPaneElement constraints horizontalTreeFlow row = 1 ] ] ]
providing a way to select within a navigation session the page at a given index.
inspectorInPagerClickInspectSpawnsPane
"Demonstrates clicking the inspect button in an inspector within a pager.
Verifies that a second pane is spawned with the same inspected object."
<gtExample>
| aScripter |
aScripter := self scripter.
aScripter element: (GtPagerSettings usedPager
createWrappedOn: (GtInspectorTool forObject: 42)).
aScripter inspectorStep
label: 'Click on the inspect button';
clickOnInspectButton;
play.
aScripter inspectorStep
label: 'Check the object in the second pane';
onPagerPaneWithIndex: 2;
assertInspectedObjectOfType: SmallInteger;
play.
^ aScripter
All these can be chained for nested navigation (illustrative):
"Chained targeting example:"
aScripter assertStep: [ :aStep |
aStep
// GtPhlowColumnedListId;
id: #scrollable;
// GtPhlowCellElement;
@ [ :aCellElement | aCellElement content text asString = 'target' ];
satisfies: [ :el | el isNotNil ] ].
For testing GT tools, higher-level step APIs exist as subclasses of BlDevScripterToolActionStep
BlDevScripterMultipleActionStep << #BlDevScripterToolActionStep
slots: { #target };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
. These provide fluent DSLs tailored to their domain. To find them, browse the subclasses of BlDevScripterToolActionStep
BlDevScripterMultipleActionStep << #BlDevScripterToolActionStep
slots: { #target };
tag: 'Scripter-Steps';
package: 'Bloc-Scripter'
.
Each tool step is accessed via a method on BlScripter
Object << #BlScripter
traits: {TBlDevScripterActionStep + TBlDevScripterCheckStepCreation};
slots: { #element . #space . #events . #rootStep . #eventHandler . #maxPulseElapsedTime };
tag: 'Scripter';
package: 'Bloc-Scripter'
(e.g., #selector
multipleViewsToolStep
<scripterActionStep>
^ self
addStep: (GtPhlowMultipleViewsToolStep new
label: 'Multiple Views Tool';
referenceSender;
onParentStepTarget: self)
, #selector
phlowCompositeToolStep
<scripterActionStep>
^ self
addStep: (GtPhlowCompositeToolStep new
label: 'Phlow Composite Tool';
referenceSender;
onParentStepTarget: self)
, #selector
inspectorStep
<scripterActionStep>
^ self
addStep: (GtInspectorStep new
label: 'Inspector';
referenceSender;
onParentStepTarget: self)
, #selector
methodsCoder
<scripterActionStep>
^ self
addStep: (GtPharoMethodsCoderStep new
label: 'Pharo methods coder';
referenceSender)
). Look at senders of these methods for usage patterns.
Examples of tool step classes:
- GtPhlowViewsBasedToolStep
BlDevScripterToolActionStep << #GtPhlowViewsBasedToolStep
slots: {};
tag: 'Scripter';
package: 'GToolkit-Phlow'
— assert tab names, click tabs, check tool objects
- GtPhlowCompositeToolStep
BlDevScripterToolActionStep << #GtPhlowCompositeToolStep
slots: {};
tag: 'Scripter';
package: 'GToolkit-Phlow'
— assert composite tool structure and labels
- GtPagerStep
BlDevScripterToolActionStep << #GtPagerStep
slots: {};
tag: 'Scripter';
package: 'GToolkit-Pager'
/ GtTreePagerStep
BlDevScripterToolActionStep << #GtTreePagerStep
slots: {};
tag: 'Examples';
package: 'GToolkit-TreePager'
— navigate pager panes
- GtPharoMethodCoderStep
BlDevScripterToolActionStep << #GtPharoMethodCoderStep
slots: {};
tag: 'Scripter';
package: 'GToolkit-Pharo-Coder-Method-Examples'
— expand/focus methods, browse implementors
- BrEditorStep
BlDevScripterToolActionStep << #BrEditorStep
slots: {};
tag: 'Scripter';
package: 'Brick-Editor-Examples'
— editor-specific assertions and interactions
- GtFilterStep
BlDevScripterToolActionStep << #GtFilterStep
slots: {};
tag: 'Filters - Widgets';
package: 'GToolkit-Coder-UI'
— filter-related steps
To find how a specific step is used in practice:
1. Browse subclasses of BlScripterStepUsageExamples
Object << #BlScripterStepUsageExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Examples';
package: 'Bloc-Scripter'
— each demonstrates a specific step type with canonical patterns
2. Search for classes with "Scripter" and "Examples" in their name — there are many such classes across all layers
3. Look at senders of the step's factory method (e.g., senders of #selector
clickStep: aBlock
| step |
step := self click.
step referenceSender.
aBlock value: step.
step play
, #selector
shortcut
"Simulates a keyboard shortcut event on a target element. If no target
element is provided, the shortcut is sent to the scripted element."
<scripterActionStep>
^ self addStep: BlDevScripterShortcutStep new referenceSender
, #selector
typeStep: aBlock
| step |
step := self type.
step referenceSender.
aBlock value: step.
step play
) to see real-world usage
4. Use the trait TBlDevScripterExamples
Trait << #TBlDevScripterExamples
tag: 'Scripter';
package: 'Bloc-Scripter'
as starting point — it provides the standard scripter factory
Key example classes by layer:
- Bloc (low-level): BlScripterExamples
Object << #BlScripterExamples
slots: { #elementExamples };
tag: 'Examples';
package: 'Bloc-Scripter'
, BlElementBoundsByScripterExamples
Object << #BlElementBoundsByScripterExamples
slots: {};
tag: 'Basic';
package: 'Bloc-Examples'
- Brick (widgets): BrSimpleListByScripterExamples
Object << #BrSimpleListByScripterExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'List';
package: 'Brick-Examples'
, BrTabGroupByScripterExamples
Object << #BrTabGroupByScripterExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Tab';
package: 'Brick-Examples'
, BrMenuWithScripterExamples
Object << #BrMenuWithScripterExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Menu';
package: 'Brick-Examples'
, BrEditorWithScripterExamples
Object << #BrEditorWithScripterExamples
slots: {};
tag: 'Editor';
package: 'Brick-Examples'
- GToolkit (tools): GtBehaviorCoderByScripterExamples
Object << #GtBehaviorCoderByScripterExamples
traits: {TCoderByScripterExamples};
slots: { #environment };
tag: 'Coders';
package: 'GToolkit-Pharo-Coder-Examples'
, GtWorldByScripterExamples
Object << #GtWorldByScripterExamples
traits: {TBlDevScripterExamples + TGtScripterDebuggerExamples};
slots: {};
tag: 'Examples';
package: 'GToolkit-World'
, GtInspectorScripterExamples
Object << #GtInspectorScripterExamples
slots: {};
tag: 'Examples';
package: 'GToolkit-Demo-MoldableDevelopment'
, GtSpotterByScripterExamples
Object << #GtSpotterByScripterExamples
slots: {};
tag: 'Examples';
package: 'GToolkit-Spotter-Examples'
- Lepiter: LeDatabaseByScripterExamples
Object << #LeDatabaseByScripterExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Examples';
package: 'Lepiter-UI'
, LePharoSnippetByScripterExamples
Object << #LePharoSnippetByScripterExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Examples';
package: 'Lepiter-Pharo'
Use labels — label: 'descriptive text' on every step aids debugging when a step fails.
Use substep:do: for grouping related steps logically.
Target precisely — identify the element on a which a step should be appplied
Check TBlDevScripterActionStepTrait << #TBlDevScripterActionStep
tag: 'Scripter';
package: 'Bloc-Scripter' methods for all available actions before inventing custom approaches.
Browse BlScripterStepUsageExamplesObject << #BlScripterStepUsageExamples
traits: {TBlDevScripterExamples};
slots: {};
tag: 'Examples';
package: 'Bloc-Scripter' subclasses for canonical usage patterns of each step type.
Use the trait TBlDevScripterExamples
Trait << #TBlDevScripterExamples
tag: 'Scripter';
package: 'Bloc-Scripter'
in your example classes for standard scripter factories.
Steps auto-pulse — no need to manually pulse the space; the scripter does this after each step; unless explicitly needed also no need to manually wait for steps to complete.
Compose examples — build on prior examples via self priorExample to get a scripter in a known state, then add more steps.