client_for_poslynx 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +6 -0
  3. data/README.md +3 -0
  4. data/foo.svg +20 -0
  5. data/lib/client_for_poslynx/bit_sequence.rb +139 -0
  6. data/lib/client_for_poslynx/data/requests/can_visit.rb +1 -0
  7. data/lib/client_for_poslynx/data/requests/credit_card_sale.rb +1 -0
  8. data/lib/client_for_poslynx/data/requests/pin_pad_get_signature.rb +17 -0
  9. data/lib/client_for_poslynx/data/requests.rb +1 -0
  10. data/lib/client_for_poslynx/data/responses/credit_card_sale.rb +1 -0
  11. data/lib/client_for_poslynx/data/responses/pin_pad_get_signature.rb +18 -0
  12. data/lib/client_for_poslynx/data/responses.rb +1 -0
  13. data/lib/client_for_poslynx/experimental.rb +16 -0
  14. data/lib/client_for_poslynx/has_client_console_support.rb +7 -1
  15. data/lib/client_for_poslynx/message_handling/xml_extractor.rb +3 -2
  16. data/lib/client_for_poslynx/signature_image/draw.rb +43 -0
  17. data/lib/client_for_poslynx/signature_image/move.rb +43 -0
  18. data/lib/client_for_poslynx/signature_image/to_svg_converter.rb +99 -0
  19. data/lib/client_for_poslynx/signature_image.rb +97 -0
  20. data/lib/client_for_poslynx/version.rb +1 -1
  21. data/spec/client_for_poslynx/bit_sequence_spec.rb +147 -0
  22. data/spec/client_for_poslynx/data/requests/credit_card_sale_spec.rb +15 -11
  23. data/spec/client_for_poslynx/data/requests/pin_pad_get_signature_spec.rb +72 -0
  24. data/spec/client_for_poslynx/data/responses/credit_card_sale_spec.rb +4 -0
  25. data/spec/client_for_poslynx/data/responses/pin_pad_display_message_spec.rb +14 -18
  26. data/spec/client_for_poslynx/signature_image/to_svg_converter_spec.rb +114 -0
  27. data/spec/client_for_poslynx/signature_image_spec.rb +91 -0
  28. data/spec/spec_helper.rb +1 -0
  29. metadata +19 -2
@@ -0,0 +1,147 @@
1
+ # coding: binary
2
+ # Note that "binary" coding is important for this file
3
+ # since that allows us to write packed binary string
4
+ # literals.
5
+
6
+ require 'spec_helper'
7
+ require 'stringio'
8
+
9
+ module ClientForPoslynx
10
+
11
+ describe BitSequence do
12
+ subject{ klass ^ "Do" }
13
+ let( :klass ) { described_class }
14
+
15
+ specify "is unequal to another instance based on different packed bits" do
16
+ other_instance = klass ^ "Re"
17
+ expect( subject ).not_to eq( other_instance )
18
+ end
19
+
20
+ specify "is equal to another instance based on same packed bits" do
21
+ other_instance = klass ^ "Do"
22
+ expect( subject ).to eq( other_instance )
23
+ end
24
+
25
+ specify "is unequal to another instance based on a non-equivalent binary digit sequence" do
26
+ other_instance = klass / "1010101010101010"
27
+ expect( subject ).not_to eq( other_instance )
28
+ end
29
+
30
+ specify "is equal to another instance based on an equivalent binary digit sequence" do
31
+ other_instance = klass / "0100010001101111"
32
+ expect( subject ).to eq( other_instance )
33
+ end
34
+
35
+ it "sets extra bits in final byte to zeros when packing bits" do
36
+ instance = klass / "01110000111"
37
+ expect( instance.to_packed_bits ).to eq( "\x70\xE0" )
38
+ end
39
+
40
+ it "correctly reports how many bits long it is" do
41
+ expect( klass.new_empty .length ).to eq( 0 )
42
+ expect( ( klass / '0' ).length ).to eq( 1 )
43
+ expect( ( klass / '10' ).length ).to eq( 2 )
44
+ expect( ( klass / ('01' * 9) ).length ).to eq( 18 )
45
+ end
46
+
47
+ it "correctly reports what its first bit-digit is" do
48
+ expect( ( klass / '101' ).first_bit_digit ).to eq( '1' )
49
+ expect( ( klass / '1101' ).first_bit_digit ).to eq( '1' )
50
+ expect( ( klass / '001' ).first_bit_digit ).to eq( '0' )
51
+ expect( ( klass / '0101' ).first_bit_digit ).to eq( '0' )
52
+ end
53
+
54
+ it "can have another bit sequence pushed onto its end" do
55
+ actual = klass / '10101'
56
+ actual << klass / '001100'
57
+ expected = klass / '10101001100'
58
+ expect( actual ).to eq( expected )
59
+ end
60
+
61
+ it "can have a bit sequence shifted off of its front" do
62
+ bit_source = klass / '111000111000111000'
63
+ taken = bit_source.shift(9)
64
+
65
+ expected_remaining = klass / '000111000'
66
+ expected_taken = klass / '111000111'
67
+
68
+ expect( bit_source ).to eq( expected_remaining )
69
+ expect( taken ).to eq( expected_taken )
70
+ end
71
+
72
+ it "can have another bit sequence unshifted onto its fron" do
73
+ bit_target = klass / '000111000'
74
+ bit_target.unshift klass / '111000111'
75
+
76
+ expected_resulting = klass / '111000111000111000'
77
+
78
+ expect( bit_target ).to eq( expected_resulting )
79
+ end
80
+
81
+ it "can be (big-endian) interpreted as an unsigned integer" do
82
+ expect( ( klass / '111000011110000' ).as_unsigned ).to eq( 0x70F0 )
83
+ expect( ( klass / ( '11110000' * 8 ) ).as_unsigned ).to eq( 0xF0F0F0F0F0F0F0F0 )
84
+ end
85
+
86
+ it "fails to be interpreted as unsigned if longer than 64 bits" do
87
+ bit_seq = klass / ( '11110000' * 8 + '1' )
88
+ expect{ bit_seq.as_unsigned }.to \
89
+ raise_exception( klass::TooManyBitsLong, /\b64\b/ )
90
+ end
91
+
92
+ it "can be (big-endian) interpreted as the sign-bit and magnitude of an integer" do
93
+ expect( ( klass / '000' ).as_sign_and_magnitude ).to eq( 0 )
94
+ expect( ( klass / '0111000011110000' ).as_sign_and_magnitude ).to eq( 0x70F0 )
95
+ expect( ( klass / '1111000011110000' ).as_sign_and_magnitude ).to eq( - 0x70F0 )
96
+ expect( ( klass / ('1' + '11110000' * 8) ).as_sign_and_magnitude ).to eq( - 0xF0F0F0F0F0F0F0F0 )
97
+ end
98
+
99
+ it "fails to be interpreted as sign-bit and magnitude if longer than 65 bits" do
100
+ bit_seq = klass / ( '0' + '11110000' * 8 + '1' )
101
+ expect{ bit_seq.as_sign_and_magnitude }.
102
+ to raise_exception( klass::TooManyBitsLong, /\b65\b/ )
103
+ end
104
+
105
+ it "can be constructed as the big-endian representation of an unsigned integer" do
106
+ expect( klass.from_unsigned( 0, 9 ) ).to eq( klass / ( '0' * 9 ) )
107
+ expect( klass.from_unsigned( 0x23, 7 ) ).to eq( klass / ( '0100011' ) )
108
+ expect( klass.from_unsigned( (2 ** 64) - 1, 64 ) ).to eq( klass / ( '1' * 64 ) )
109
+ end
110
+
111
+ it "can be constructed as the sign-bit and big-endian magnitude representation of an integer" do
112
+ expect( klass.from_sign_and_magnitude_of( 0, 10 ) ).to eq( klass / ( '0' * 10 ) )
113
+ expect( klass.from_sign_and_magnitude_of( 0x23, 8 ) ).to eq( klass / ( '00100011' ) )
114
+ expect( klass.from_sign_and_magnitude_of( - 0x23, 8 ) ).to eq( klass / ( '10100011' ) )
115
+ expect( klass.from_sign_and_magnitude_of( -(2 ** 64) + 1, 65 ) ).to eq( klass / ( '1' * 65 ) )
116
+ end
117
+
118
+ it "fails to be constructed as a longer than 64-bit representation of an unsigned number" do
119
+ expect{ klass.from_unsigned(0x23, 65) }.
120
+ to raise_exception( klass::TooManyBitsLong, /\b64\b/ )
121
+ end
122
+
123
+ it "fails to be constructed as an unsigned representation a negative number" do
124
+ expect{ klass.from_unsigned(-1, 5) }.
125
+ to raise_exception( klass::NumberOutOfBounds )
126
+ end
127
+
128
+ it "fails to be constructed as an under-sized representation of an unsigned number" do
129
+ expect{ klass.from_unsigned(0x23, 5) }.
130
+ to raise_exception( klass::NumberOutOfBounds )
131
+ end
132
+
133
+ it "can be build by unpacking bits from a uuencoded string" do
134
+ actual = klass.from_uuencoded( "&,C(R,C(R\n" )
135
+ expected = klass ^ "\x32" * 6
136
+
137
+ expect( actual ).to eq( expected )
138
+ end
139
+
140
+ it "can be packed to a uuencoded string" do
141
+ bit_seq = klass ^ "\x32" * 6
142
+ expect( bit_seq.uuencode ).to eq( "&,C(R,C(R\n" )
143
+ end
144
+
145
+ end
146
+
147
+ end
@@ -27,6 +27,7 @@ module ClientForPoslynx
27
27
  subject.track_2 = 'the-two'
28
28
  subject.card_number = 'the-number'
29
29
  subject.expiry_date = 'the-expiration'
30
+ subject.capture_signature = 'the-capture-signature'
30
31
 
31
32
  expected_xml =
32
33
  "<PLRequest>" +
@@ -42,6 +43,7 @@ module ClientForPoslynx
42
43
  "<Track1>the-one</Track1>" +
43
44
  "<CardNumber>the-number</CardNumber>" +
44
45
  "<ExpiryDate>the-expiration</ExpiryDate>" +
46
+ "<ReqPPSigCapture>the-capture-signature</ReqPPSigCapture>" +
45
47
  "</PLRequest>\n"
46
48
 
47
49
  expect( subject.xml_serialize ).to eq( expected_xml )
@@ -75,22 +77,24 @@ module ClientForPoslynx
75
77
  <Track1>the-one</Track1>
76
78
  <CardNumber>the-number</CardNumber>
77
79
  <ExpiryDate>the-expiration</ExpiryDate>
80
+ <ReqPPSigCapture>the-capture-signature</ReqPPSigCapture>
78
81
  </PLRequest>
79
82
  XML
80
83
 
81
84
  actual_instance = described_class.xml_deserialize xml_input
82
85
 
83
- expect( actual_instance.client_mac ).to eq( 'the-MAC' )
84
- expect( actual_instance.merchant_supplied_id ).to eq( 'the-transaction' )
85
- expect( actual_instance.client_id ).to eq( 'the-client' )
86
- expect( actual_instance.tax_amount ).to eq( 'the-tax' )
87
- expect( actual_instance.customer_code ).to eq( 'the-code' )
88
- expect( actual_instance.amount ).to eq( 'the-amount' )
89
- expect( actual_instance.input_source ).to eq( 'the-source' )
90
- expect( actual_instance.track_1 ).to eq( 'the-one' )
91
- expect( actual_instance.track_2 ).to eq( 'the-two' )
92
- expect( actual_instance.card_number ).to eq( 'the-number' )
93
- expect( actual_instance.expiry_date ).to eq( 'the-expiration' )
86
+ expect( actual_instance.client_mac ).to eq( 'the-MAC' )
87
+ expect( actual_instance.merchant_supplied_id ).to eq( 'the-transaction' )
88
+ expect( actual_instance.client_id ).to eq( 'the-client' )
89
+ expect( actual_instance.tax_amount ).to eq( 'the-tax' )
90
+ expect( actual_instance.customer_code ).to eq( 'the-code' )
91
+ expect( actual_instance.amount ).to eq( 'the-amount' )
92
+ expect( actual_instance.input_source ).to eq( 'the-source' )
93
+ expect( actual_instance.track_1 ).to eq( 'the-one' )
94
+ expect( actual_instance.track_2 ).to eq( 'the-two' )
95
+ expect( actual_instance.card_number ).to eq( 'the-number' )
96
+ expect( actual_instance.expiry_date ).to eq( 'the-expiration' )
97
+ expect( actual_instance.capture_signature ).to eq( 'the-capture-signature' )
94
98
  end
95
99
 
96
100
  it "accepts a canonical visitor" do
@@ -0,0 +1,72 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module ClientForPoslynx
6
+
7
+ describe Data::Requests::PinPadGetSignature do
8
+
9
+ it_behaves_like "a data object"
10
+
11
+ it "Serializes to a PLRequest XML document for a PPGETSIGNATURE request" do
12
+ mac = Data::Requests::DEFAULT_CLIENT_MAC
13
+ expected_xml =
14
+ "<PLRequest><Command>PPGETSIGNATURE</Command><ClientMAC>#{mac}</ClientMAC></PLRequest>\n"
15
+
16
+ expect( subject.xml_serialize ).to eq( expected_xml )
17
+ end
18
+
19
+
20
+ it "Serializes all assigned members to appropriate elements" do
21
+ subject.client_mac = 'the-mac'
22
+
23
+ expected_xml =
24
+ "<PLRequest>" +
25
+ "<Command>PPGETSIGNATURE</Command>" +
26
+ "<ClientMAC>the-mac</ClientMAC>" +
27
+ "</PLRequest>\n"
28
+
29
+ expect( subject.xml_serialize ).to eq( expected_xml )
30
+ end
31
+
32
+
33
+ it "parses minimally acceptable XML data" do
34
+ xml_input = <<-XML
35
+ <PLRequest>
36
+ <Command>PPGETSIGNATURE</Command>
37
+ </PLRequest>
38
+ XML
39
+
40
+ actual_instance = described_class.xml_deserialize xml_input
41
+ end
42
+
43
+
44
+ it "parses XML data with all property elements supplied" do
45
+ xml_input = <<-XML
46
+ <PLRequest>
47
+ <Command>PPGETSIGNATURE</Command>
48
+ <ClientMAC>the-MAC</ClientMAC>
49
+ </PLRequest>
50
+ XML
51
+
52
+ actual_instance = described_class.xml_deserialize xml_input
53
+
54
+ expect( actual_instance.client_mac ).to eq( 'the-MAC' )
55
+ end
56
+
57
+
58
+ it "accepts a canonical visitor" do
59
+ visitor = Object.new
60
+ visitor.extend Data::Requests::CanVisit
61
+ expect{ subject.accept_visitor visitor }.not_to raise_exception
62
+ end
63
+
64
+ it "sends itself to an accepted visitor" do
65
+ visitor = double :visitor
66
+ expect( visitor ).to receive( :visit_PinPadGetSignature ).with( subject )
67
+ subject.accept_visitor visitor
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -30,6 +30,7 @@ module ClientForPoslynx
30
30
  subject.transaction_date = 'the-date'
31
31
  subject.transaction_time = 'the-time'
32
32
  subject.input_method = 'the-input-method'
33
+ subject.signature = 'the-signature'
33
34
  subject.receipt = [ 'Merchant Receipt', '...' ]
34
35
  subject.customer_receipt = [ 'Customer Receipt', '...' ]
35
36
 
@@ -52,6 +53,7 @@ module ClientForPoslynx
52
53
  "<TransactionDate>the-date</TransactionDate>" +
53
54
  "<TransactionTime>the-time</TransactionTime>" +
54
55
  "<InputMethod>the-input-method</InputMethod>" +
56
+ "<Signature>the-signature</Signature>" +
55
57
  "<Receipt>" +
56
58
  "<Receipt1>Merchant Receipt</Receipt1>" +
57
59
  "<Receipt2>...</Receipt2>" +
@@ -98,6 +100,7 @@ module ClientForPoslynx
98
100
  <TransactionDate>the-date</TransactionDate>
99
101
  <TransactionTime>the-time</TransactionTime>
100
102
  <InputMethod>the-input-method</InputMethod>
103
+ <Signature>the-signature</Signature>
101
104
  <Receipt>
102
105
  <Receipt1>Merchant Receipt</Receipt1>
103
106
  <Receipt2>...</Receipt2>
@@ -127,6 +130,7 @@ module ClientForPoslynx
127
130
  expect( actual_instance.transaction_date ).to eq( 'the-date' )
128
131
  expect( actual_instance.transaction_time ).to eq( 'the-time' )
129
132
  expect( actual_instance.input_method ).to eq( 'the-input-method' )
133
+ expect( actual_instance.signature ).to eq( 'the-signature' )
130
134
  expect( actual_instance.receipt ).to eq( ['Merchant Receipt', '...'] )
131
135
  expect( actual_instance.customer_receipt ).to eq( ['Customer Receipt', '...'] )
132
136
  end
@@ -2,29 +2,27 @@ require 'spec_helper'
2
2
 
3
3
  module ClientForPoslynx
4
4
 
5
- describe Data::Responses::PinPadDisplayMessage do
5
+ describe Data::Responses::PinPadGetSignature do
6
6
 
7
7
  it_behaves_like "a data object"
8
8
 
9
- it "Serializes to a PLResponse XML document for a PPDISPLAY response" do
10
- expected_xml = "<PLResponse><Command>PPDISPLAY</Command></PLResponse>\n"
9
+ it "Serializes to a PLResponse XML document for a PPGETSIGNATURE response" do
10
+ expected_xml = "<PLResponse><Command>PPGETSIGNATURE</Command></PLResponse>\n"
11
11
  expect( subject.xml_serialize ).to eq( expected_xml )
12
12
  end
13
13
 
14
14
 
15
15
  it "Serializes all assigned members to appropriate elements" do
16
- subject.result = 'the-result'
17
- subject.result_text = 'the-text'
18
- subject.error_code = 'the-code'
19
- subject.button_response = 'the-response'
16
+ subject.result = 'the-result'
17
+ subject.result_text = 'the-text'
18
+ subject.signature = 'the-signature'
20
19
 
21
20
  expected_xml =
22
21
  "<PLResponse>" +
23
- "<Command>PPDISPLAY</Command>" +
22
+ "<Command>PPGETSIGNATURE</Command>" +
24
23
  "<Result>the-result</Result>" +
25
24
  "<ResultText>the-text</ResultText>" +
26
- "<ErrorCode>the-code</ErrorCode>" +
27
- "<Response>the-response</Response>" +
25
+ "<Signature>the-signature</Signature>" +
28
26
  "</PLResponse>\n"
29
27
 
30
28
  expect( subject.xml_serialize ).to eq( expected_xml )
@@ -34,7 +32,7 @@ module ClientForPoslynx
34
32
  it "parses minimally acceptable XML data" do
35
33
  xml_input = <<-XML
36
34
  <PLResponse>
37
- <Command>PPDISPLAY</Command>
35
+ <Command>PPGETSIGNATURE</Command>
38
36
  </PLResponse>
39
37
  XML
40
38
 
@@ -46,20 +44,18 @@ module ClientForPoslynx
46
44
  it "parses XML data with all property elements supplied" do
47
45
  xml_input = <<-XML
48
46
  <PLResponse>
49
- <Command>PPDISPLAY</Command>
47
+ <Command>PPGETSIGNATURE</Command>
50
48
  <Result>the-result</Result>
51
49
  <ResultText>the-text</ResultText>
52
- <ErrorCode>the-code</ErrorCode>
53
- <Response>the-response</Response>
50
+ <Signature>the-signature</Signature>
54
51
  </PLResponse>
55
52
  XML
56
53
 
57
54
  actual_instance = described_class.xml_deserialize xml_input
58
55
 
59
- expect( actual_instance.result ).to eq( 'the-result' )
60
- expect( actual_instance.result_text ).to eq( 'the-text' )
61
- expect( actual_instance.error_code ).to eq( 'the-code' )
62
- expect( actual_instance.button_response ).to eq( 'the-response' )
56
+ expect( actual_instance.result ).to eq( 'the-result' )
57
+ expect( actual_instance.result_text ).to eq( 'the-text' )
58
+ expect( actual_instance.signature ).to eq( 'the-signature' )
63
59
  end
64
60
 
65
61
 
@@ -0,0 +1,114 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module ClientForPoslynx
6
+
7
+ describe SignatureImage::ToSvgConverter do
8
+ let( :svg_ns ) { 'http://www.w3.org/2000/svg' }
9
+ let( :signature_image ) { SignatureImage.new }
10
+ let( :svg_doc_content ) { described_class.convert( signature_image ) }
11
+ let( :svg_document ) {
12
+ Nokogiri::XML( svg_doc_content ) do |config|
13
+ config.options = Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET
14
+ end
15
+ }
16
+ let( :svg_doc_root ) { svg_document.root }
17
+
18
+ it "produces SVG document content" do
19
+ expect( svg_doc_root.name ).to eq( 'svg' )
20
+ expect( svg_doc_root.namespace.href ).to eq( svg_ns )
21
+ expect( svg_doc_root['version'] ).to eq( '1.1' )
22
+ end
23
+
24
+ it "specifies physical dimensions in millimeter units" do
25
+ expected = /^\d+([.]\d*)?mm?$/
26
+ expect( svg_doc_root['width' ] ).to match( expected )
27
+ expect( svg_doc_root['height'] ).to match( expected )
28
+ end
29
+
30
+ it "specifies integer logical units for view box start and size" do
31
+ expect( svg_doc_root['viewBox'] ).to match( /^(\d+\s+){3}\d+$/ )
32
+ end
33
+
34
+ it "treats logical units as fractions of physical dimensions, regardless of resulting pixel aspect ratio" do
35
+ expect( svg_doc_root['preserveAspectRatio'] ).to eq( 'none' )
36
+ end
37
+
38
+ it "includes a an SVG <path> element" do
39
+ expect( svg_document.xpath('//ns:svg/ns:path', 'ns' => svg_ns).length ).
40
+ to eq( 1 )
41
+ end
42
+
43
+ describe "<path> element" do
44
+ let( :svg_path_element ) {
45
+ svg_document.at_xpath('//ns:svg/ns:path', 'ns' => svg_ns)
46
+ }
47
+
48
+ it "has a black stroke color" do
49
+ expect( svg_path_element['stroke'] ).to eq( 'black' )
50
+ end
51
+
52
+ it "is explicitly not filled" do
53
+ expect( svg_path_element['fill'] ).to eq( 'none' )
54
+ end
55
+
56
+ it "has a stroke width in millimeter units" do
57
+ expected = /^\d+([.]\d*)?mm?$/
58
+ expect( svg_path_element['stroke-width'] ).to match( expected )
59
+ end
60
+
61
+ describe "path data" do
62
+ let( :svg_path_instruction_tokens ) {
63
+ path_data = svg_path_element['d']
64
+ path_instructions = path_data.split(/ (?=[Ml])/)
65
+ path_instructions.map { |pi|
66
+ instr_type = pi[0..0]
67
+ instr_values = pi[1..-1].strip.split(/[ ,]+/)
68
+ [ instr_type ] + instr_values
69
+ }
70
+ }
71
+
72
+ it "creates path data from signature data steps" do
73
+ signature_image.move 25, 20
74
+ signature_image.draw 30, 1
75
+
76
+ signature_image.move 10, 20
77
+ signature_image.draw 0, 30
78
+ signature_image.draw -1, 25
79
+
80
+ expect( svg_path_instruction_tokens ).to eq( [
81
+ %w[ M 25 20 ],
82
+ %w[ l 30 1 ],
83
+
84
+ %w[ M 10 20 ],
85
+ %w[ l 0 30
86
+ -1 25 ],
87
+ ] )
88
+ end
89
+
90
+ it "adds zero length line-to after a move without a draw" do
91
+ signature_image.move 25, 20
92
+ signature_image.draw 30, 1
93
+
94
+ signature_image.move 10, 20
95
+
96
+ signature_image.move 90, 30
97
+ signature_image.draw -1, 25
98
+
99
+ expect( svg_path_instruction_tokens ).to eq( [
100
+ %w[ M 25 20 ],
101
+ %w[ l 30 1 ],
102
+
103
+ %w[ M 10 20 ],
104
+ %w[ l 0 0 ],
105
+
106
+ %w[ M 90 30 ],
107
+ %w[ l -1 25 ],
108
+ ] )
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ end
@@ -0,0 +1,91 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ module ClientForPoslynx
6
+
7
+ describe SignatureImage do
8
+
9
+ def build_example_image
10
+ described_class.new.tap { |si|
11
+ si.move 10, 120
12
+ si.draw 0, -30
13
+ si.draw 0, -30
14
+ si.draw 0, -30
15
+ si.draw 0, -20
16
+ si.draw 30, 30
17
+ si.draw -25, 25
18
+ si.draw 0, -2
19
+ }
20
+ end
21
+
22
+ let( :bit_sequence ) {
23
+ BitSequence.from_bit_digits( bit_digit_sequence )
24
+ }
25
+
26
+ let( :bit_digit_sequence ) {
27
+ # TODO: Currently assuming that deltas for move are
28
+ # expressed as sign bit and magnitude, where sign bit
29
+ # of 1 means negative. Documentation is unclear about
30
+ # this though except to say that there is a sign bit,
31
+ # and that values can range from -31 to 31.
32
+ # Once I can connect to the virtual POSLynx again, I
33
+ # need to do a test, and find out whether this
34
+ # assumption is true or not.
35
+
36
+ '1' + '0000001010' + '1111000' + # move 10, 120
37
+ '0' + '000000' + '111110' + # draw 0, -30
38
+ '0' + '000000' + '111110' + # draw 0, -30
39
+ '0' + '000000' + '111110' + # draw 0, -30
40
+ '0' + '000000' + '110100' + # draw 0, -20
41
+ '0' + '011110' + '011110' + # draw 30, 30
42
+ '0' + '111001' + '011001' + # draw -25, 25
43
+ '0' + '000000' + '100010' + # draw 0, -2
44
+ '000' # remaining bits in last byte
45
+ }
46
+
47
+ it "is unequal to another instance with a different sequence of steps" do
48
+ subject = build_example_image
49
+
50
+ other_sig = described_class.new
51
+ other_sig.move 10, 120
52
+ other_sig.draw 0, -29
53
+
54
+ expect( subject ).not_to eq( other_sig )
55
+ end
56
+
57
+ it "is equal to another instance with the same sequence of steps" do
58
+ subject = build_example_image
59
+ other_sig = build_example_image
60
+
61
+ expect( subject ).to eq( other_sig )
62
+ end
63
+
64
+ context "serializing" do
65
+ subject{ build_example_image }
66
+
67
+ it "serializes data in legacy format" do
68
+ actual_serialized = subject.serialize_legacy
69
+ actual_bit_sequence = BitSequence.from_uuencoded( actual_serialized )
70
+
71
+ expect( actual_bit_sequence ).to eq( bit_sequence )
72
+ end
73
+ end
74
+
75
+ context "deserializing" do
76
+ subject{ described_class.new(serialized_data) }
77
+ let( :serialized_data ) {
78
+ bit_sequence.uuencode
79
+ }
80
+
81
+ it "deserializes data from legacy format" do
82
+ actual = described_class.deserialize( serialized_data )
83
+ expected = build_example_image
84
+
85
+ expect( actual ).to eq( expected )
86
+ end
87
+ end
88
+
89
+ end
90
+
91
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
4
4
  require 'client_for_poslynx'
5
+ require 'client_for_poslynx/experimental'
5
6
  Dir[File.join( File.dirname(__FILE__), 'support', '**', '*.rb')].each do |script|
6
7
  require script
7
8
  end