client_for_poslynx 0.2.4 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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