Permalink
Browse files

simulator bugfixes

  • Loading branch information...
1 parent a9f7869 commit 90cd47ccb5835fef680557765afebcf14ef21549 @sinisterchipmunk committed Apr 4, 2012

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,20 @@
+(function() {
+ var Document, Literal;
+
+ Document = require('nodes/document').Document;
+
+ Literal = require('nodes/literal').Literal;
+
+ Document.preprocessor('check_card', function(builder) {
+ var screen;
+ screen = builder.root.current_screen().extend();
+ screen.b('tform', function(tform) {
+ return tform.b('card', {
+ parser: 'mag',
+ parser_params: 'risk_mgmt'
+ });
+ });
+ return this.create(Literal, "");
+ });
+
+}).call(this);
@@ -20,4 +20,6 @@
require('ext/builtin');
+ require('ext/check_card');
+
}).call(this);

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -125,20 +125,20 @@ describe "Builder", ->
it "should insert preamble by default", ->
expect(builder.toString()).toEqual("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<tml />")
- it "should build root tag with children", ->
+ it "should build root tag without children", ->
expect(builder.toString(false)).toEqual('<tml />')
it "should build root tag with children", ->
builder.b 'screen'
- expect(builder.toString(false)).toEqual("<tml>\n <screen />\n</tml>")
+ expect(builder.toString(false)).toMatch /<tml>[\s\n]*?<screen/
it "should change attributes on root tag", ->
builder.attrs['one'] = 1
expect(builder.toString(false)).toEqual('<tml one="1" />')
it "should set attributes on children", ->
builder.b 'screen', id: 'idle'
- expect(builder.toString(false)).toEqual("<tml>\n <screen id=\"idle\" />\n</tml>")
+ expect(builder.toString(false)).toMatch /<tml>[\s\n]*?<screen id="idle"/
it "should build children with attributes with callbacks", ->
builder.b 'screen', id: 'idle', (b) -> b.b 'display'
@@ -0,0 +1,23 @@
+require 'spec_helper'
+
+describe "check_card", ->
+ it "should fill in card scheme for correct pans", ->
+ sim = simulate dom "card.pan = '5454545454545454'; check_card()"
+ sim.start()
+ expect(sim.state.variables['card.scheme'].value).toEqual 'MASTERCARD'
+
+ it "should complain if pan does not match one on file", ->
+ sim = simulate dom "card.pan = '54'; check_card()"
+ expect(-> sim.start()).toThrow("Card PAN does not match any registered card data")
+
+ it "should set card.parser.verdict to online", ->
+ sim = simulate dom "card.pan = '5454545454545454'; check_card()"
+ sim.start()
+ expect(sim.state.variables['card.parser.verdict'].value).toEqual 'online'
+
+ it "should not choke on card sipes", ->
+ sim = simulate dom "read_card('mag'); check_card()"
+ sim.start()
+ sim.swipe_card 'visa'
+ expect(sim.state.variables['card.parser.verdict'].value).toEqual 'online'
+
@@ -23,7 +23,7 @@ describe "keypad input", ->
# console.log sim.state.flow[sim.state.flow.length-1]
expect(sim.state.variables.result.value).toEqual 2
expect(sim.state.display.trim()).toEqual ""
-
+
it "should not treat cardswipe as keypress '0'", ->
doc = dom """
result = 0
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+# These specs aren't necessarily intuitive, but they describe how
+# the terminal behaves, and therefore they describe how the simulator
+# should behave.
+
+describe "Simulator", ->
+ doc = sim = null
+ beforeEach -> doc = build('tml', xmlns: 'http://www.ingenico.co.uk/tml')
+
+ it "should raise an error when 'cancel' is listed as a key variant", ->
+ doc = dom ""
+ scr = doc.first 'screen'
+ scr.b 'next', uri: '#__main__', (n) -> n.b 'variant', uri: "#__main__", key: 'cancel'
+ expect(-> simulate(doc).start()).toThrow "'cancel' is not allowed as a variant key"
@@ -3,7 +3,7 @@ require 'spec_helper'
describe "Simulator", ->
doc = sim = null
beforeEach -> doc = build('tml', xmlns: 'http://www.ingenico.co.uk/tml')
-
+
it "should handle text entry", ->
doc = dom "result = ''\nswitch getch '1'\n when '1' then result += 'A'\ndisplay '\\n<input type=\"text\" name=\"result\" />'"
sim = simulate doc
@@ -125,7 +125,7 @@ exports.Builder = class Builder
front = "<#{@name} "
front += "#{k}=\"#{v}\" " for k, v of @attrs
- if @tags.length > 0
+ if @tags.length > 0 or @force_endtag
@tabs() + front.trim() + ">\n" +
(tag.toString(false) + "\n" for tag in @tags).join("") +
@tabs() + "</#{@name}>"
@@ -0,0 +1,9 @@
+{Document} = require 'nodes/document'
+{Literal} = require 'nodes/literal'
+
+Document.preprocessor 'check_card',
+ (builder) ->
+ screen = builder.root.current_screen().extend()
+ screen.b 'tform', (tform) ->
+ tform.b 'card', parser: 'mag', parser_params: 'risk_mgmt'
+ @create Literal, ""
@@ -7,4 +7,5 @@ require 'ext/link_to'
require 'ext/post'
require 'ext/read_card'
require 'ext/require'
-require 'ext/builtin'
+require 'ext/builtin'
+require 'ext/check_card'
@@ -64,6 +64,7 @@ exports.Simulator = class Simulator
@state.flow.push ["Switched to screen", screen.attrs.id]
@state.screen.id = screen.attrs.id
@state.screen.element = screen
+ @validate_screen_variants()
@process_variable_assignments()
@state.key = "" # reset input key for processing at next screen
@state.card = null # reset input card for processing at next screen
@@ -76,6 +77,26 @@ exports.Simulator = class Simulator
if print = @state.screen.element.first 'print'
@state.flow.push ["Printed output", print.toString(false)]
@state.print += @process_output_element print
+ # if it's a risk management screen, perform risk management.
+ if tform = @state.screen.element.first 'tform'
+ if parser = tform.first('card', parser: 'mag', parser_params: 'risk_mgmt')
+ @perform_risk_management()
+
+ validate_screen_variants: ->
+ variants = @state.screen.element.search 'variant'
+ for variant in variants
+ if key = variant.attrs.key
+ throw new Error "Variant key '#{key}' is not valid" unless key in KEYS
+ throw new Error "'cancel' is not allowed as a variant key" if key in ['cancel']
+
+ perform_risk_management: ->
+ pan = @find_variable('card.pan').value
+ for name, data of CARDS
+ if data.pan == pan
+ @find_variable('card.scheme').value = data.scheme
+ @find_variable('card.parser.verdict').value = 'online'
+ return
+ throw new Error "Card PAN does not match any registered card data"
process_output_element: (e) ->
str = "" + (sub.toString(false) for sub in e.all())
@@ -169,6 +190,10 @@ exports.Simulator = class Simulator
candidates = []
next = @state.screen.element.first('next')
+ # check cancel button, which is not a variant
+ if @state.key == 'cancel' and @state.screen.element.attrs.cancel
+ return [@state.screen.element.attrs.cancel]
+
# check for matching conditions
if next
for variant in next.all("variant")
@@ -310,3 +335,12 @@ Simulator.register_card "visa",
issuer_name: "N/A"
pan: "4111111111111111"
scheme: "VISA"
+
+Simulator.register_card "mastercard",
+ cardholder_name: "John Smith"
+ effective_date: "01/01/2001"
+ expiry_date: "01/01/2111"
+ issue_number: "N/A"
+ issuer_name: "N/A"
+ pan: "5454545454545454"
+ scheme: "MASTERCARD"
@@ -77,7 +77,10 @@ Builder.screen = class Screen extends Builder
new_screen_id = @root.name_registry.increment base_id
new_screen_uri = uri_for new_screen_id
operation.uri = new_screen_uri
- next.b 'variant', operation
+ if operation.key and operation.key in ['cancel']
+ @attrs.cancel = operation.uri
+ else
+ next.b 'variant', operation
scr = @root.screen new_screen_id, next: next.attrs.uri
scr._branched_from = this
scr.merge_to = @merge_to

0 comments on commit 90cd47c

Please sign in to comment.