Ticket Wizard
or the perils of ticket creation
by @gnz
Don't panic
It's the new wizard
Now 100% voodoo-free.
Features
The basic two are obvious:
- Ticket creation
- Ticket edition
- ..but many use cases
Vision
- It should be a
platform
on top of which controls can be built.
- It should
provide services
to the control, such as API to interact with other fields, prefilling & chaining, etc.
- Implementing a new control types should be piece of cake.
How does it work?
- The structure is defined in XML in the creation pipe.
- The creation pipe is loaded into configuration classes.
- Using them, the wizard controller (UI) instantiates composite controls that recursively instantiate their childs all the way up to the fields/controls.
Defining structure
The creation pipe
- There's an XSD!
- Used by the check page to validate
- Should be added in the designer on Save
-
There's a set of classes for loading
- ...and saving too!
Configuration classes
BusinessInterfaces\TicketWizard\Configuration
BusinessEntities\TicketWizard\Configuration
- They are in charge of loading the creation pipe.
- Split the work into logical parts (Page, Section, Control, etc)
- Mapped 1-to-1 to the valid XML defined in XSD .
- Bi-directional: can load and also SAVE it back.
- Not used currently in the wizard designer, but should.
- XCM hooks onto these ones to transport wizards.
Control implementations
-
Controls types are MEF plug-ins
- Implement IWizardField
- Inherit from WizardField
- Implemented interfaces define capabilities:
- IChainableControl, IChangeHandler, IChangeNotifierControl, ISaveableControl, INameBoundPrefillProvider .
Control implementations
Currently still located on TxpEnterprise but should be moved into its own project.
Composed my MEF.
See?
[WizardFieldDescriptor("CheckBox", typeof(WizardCheckBox))]
public class WizardCheckBox : WizardField { }
The FAQing control
-
How do I add a new property to a control?
Simply create a C# property and attribute it with [WizardFieldProperty] -
Need to do something special on save?
Implement ISaveableControl -
Need to implement some common prefilling?
Override the OnPreFill() method and access the Items[0] - Need to implement a list-like control?
Inherit from WizardListControl base class. -
Need to implement prefills "a la DB query"?
Implement INameBoundPrefillProvider (more to come...) -
Need special styling on your control?
The wizard adds quite some CSS classes already!
Prefill & chaining
Some definitions:
- Chaining is when one control has a parent control, which, on update cascades the update to the child.
- Prefilling is an overloaded term:
- Provide a default static value before creation, e.g. "client computer name". Easy case, handled automatically by the ticket wizard manager in the creation pipe level.
- Propagation of a field's value (or related values) into other fields. Hard case.
PREFILL & CHAINING
Think about them in terms of direction:
- Chaining = child points to parent. E.g. CI List control.
-
Prefilling = parent provides results and children receive them. E.g. DB Query control, Web service controls.
To solve the hard case, we have infrastructure now:
- Implement INameBoundPrefillProvider
- It takes care of most of the propagation issues
- First implemented in the new chainable DB controls
Client side wizard
-
The wizard has a client-side API.
- Really, it does!
- Defined in WizardController.js
- ...and populated with data emitted on WizardPage.cs
- Provides a unified API surface to access and set all fields, and more:
TicketWizard.Fields[]; TicketWizard.Pages[]; TicketWizard.Validate*(); //etc.
Testing the wizard
Everyone said it couldn't be done!
- Based on CasperJS & PhantomJS
- Isolates the wizard:
- ...just enough to be able to inject configuration
- ...but leave pieces that work (i.e. don't mock the world)
- Relies on the "static manager + ChangeImplementation()" approach by HKO for isolation
Testing the wizard
- What is in a test?
- A creation pipe file and .
-
(+ some additional configuration, rights, etc)
- How to kick in one individual test?
- Copy the testable assembly to BIN
-
Pass the absolute path of the test creation pipe via query string
- How to write tests?
- Write a test creation pipe
- Write some simple JS code
TESTING THE WIZARD
-
We created the concept of wizard strategy.
- The default strategy does the expected.
- But there's a testable strategy that allows testing.
- Needs to be copied manually into \bin, then run:
-
Isonet.TxpEnterprise.WebUiAutomation\run.bat
-
The testable strategy does a few things:
- Makes sure managers are replaced.
- Renders a few special Javascript in the wizard to allow testing for the results of saving.
- Currently only works for creation, not edit test cases!
Here be dragons
- There's still some legacy code around:
- LogicalCreationPipe? Crap
- Any direct XML manipulation? Crap
- Checking the field type directly? Crap
- Code duplication: some, but is not that bad.
- Chaining and prefilling are TWO different things!
- Chaining is always complex: many use cases!
- SetDefaultValue feature? Not finished, not tested.
The future
- Controls should be moved into a separate project:
- True MEF composition
- No references
- No type checking cheats
- Keep working on the testing infrastructure
- Clean up the web service control implementations
Ticket wizard
By Gonzalo Casas
Ticket wizard
- 1,794