ruby-sslyze 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -4
  3. data/.travis.yml +15 -7
  4. data/ChangeLog.md +29 -12
  5. data/Gemfile +3 -2
  6. data/LICENSE.txt +1 -1
  7. data/README.md +5 -5
  8. data/Rakefile +1 -1
  9. data/lib/sslyze/cipher_suites.rb +176 -0
  10. data/lib/sslyze/program.rb +8 -8
  11. data/lib/sslyze/task.rb +40 -33
  12. data/lib/sslyze/version.rb +1 -1
  13. data/lib/sslyze/{certificate/domain_name.rb → x509/domain.rb} +5 -3
  14. data/lib/sslyze/x509/extension.rb +15 -0
  15. data/lib/sslyze/x509/extension_set.rb +140 -0
  16. data/lib/sslyze/x509/extensions.rb +6 -0
  17. data/lib/sslyze/x509/extensions/basic_constraints.rb +41 -0
  18. data/lib/sslyze/x509/extensions/certificate_policies.rb +108 -0
  19. data/lib/sslyze/x509/extensions/crl_distribution_points.rb +47 -0
  20. data/lib/sslyze/x509/extensions/extended_key_usage.rb +58 -0
  21. data/lib/sslyze/x509/extensions/key_usage.rb +66 -0
  22. data/lib/sslyze/x509/extensions/subject_alt_name.rb +144 -0
  23. data/lib/sslyze/x509/name.rb +194 -0
  24. data/lib/sslyze/x509/public_key.rb +53 -0
  25. data/lib/sslyze/xml.rb +26 -37
  26. data/lib/sslyze/xml/attributes.rb +5 -0
  27. data/lib/sslyze/xml/attributes/error.rb +30 -0
  28. data/lib/sslyze/xml/attributes/exception.rb +30 -0
  29. data/lib/sslyze/xml/attributes/is_supported.rb +29 -0
  30. data/lib/sslyze/xml/attributes/is_vulnerable.rb +29 -0
  31. data/lib/sslyze/xml/attributes/title.rb +31 -0
  32. data/lib/sslyze/xml/certinfo.rb +67 -0
  33. data/lib/sslyze/xml/certinfo/certificate.rb +202 -0
  34. data/lib/sslyze/xml/certinfo/certificate_validation.rb +69 -0
  35. data/lib/sslyze/xml/certinfo/certificate_validation/hostname_validation.rb +54 -0
  36. data/lib/sslyze/xml/certinfo/certificate_validation/path_validation.rb +84 -0
  37. data/lib/sslyze/xml/certinfo/certificate_validation/verified_certificate_chain.rb +41 -0
  38. data/lib/sslyze/xml/certinfo/has_certificates.rb +102 -0
  39. data/lib/sslyze/xml/certinfo/ocsp_stapling.rb +45 -0
  40. data/lib/sslyze/xml/certinfo/ocsp_stapling/ocsp_response.rb +87 -0
  41. data/lib/sslyze/xml/certinfo/received_certificate_chain.rb +48 -0
  42. data/lib/sslyze/xml/compression.rb +33 -0
  43. data/lib/sslyze/xml/compression/compression_method.rb +38 -0
  44. data/lib/sslyze/xml/fallback.rb +34 -0
  45. data/lib/sslyze/xml/fallback/tls_fallback_scsv.rb +27 -0
  46. data/lib/sslyze/xml/heartbleed.rb +38 -0
  47. data/lib/sslyze/xml/heartbleed/openssl_heartbleed.rb +29 -0
  48. data/lib/sslyze/xml/http_headers.rb +42 -0
  49. data/lib/sslyze/xml/http_headers/http_public_key_pinning.rb +121 -0
  50. data/lib/sslyze/xml/http_headers/http_strict_transport_security.rb +59 -0
  51. data/lib/sslyze/xml/invalid_target.rb +33 -0
  52. data/lib/sslyze/xml/openssl_ccs.rb +34 -0
  53. data/lib/sslyze/xml/openssl_ccs/openssl_ccs_injection.rb +26 -0
  54. data/lib/sslyze/xml/plugin.rb +27 -0
  55. data/lib/sslyze/xml/protocol.rb +143 -0
  56. data/lib/sslyze/xml/protocol/cipher_suite.rb +93 -0
  57. data/lib/sslyze/xml/protocol/cipher_suite/key_exchange.rb +127 -0
  58. data/lib/sslyze/xml/reneg.rb +28 -0
  59. data/lib/sslyze/xml/reneg/session_renegotiation.rb +51 -0
  60. data/lib/sslyze/xml/resum.rb +42 -0
  61. data/lib/sslyze/xml/resum/session_resumption_with_session_ids.rb +94 -0
  62. data/lib/sslyze/xml/resum/session_resumption_with_tls_tickets.rb +69 -0
  63. data/lib/sslyze/xml/resum_rate.rb +30 -0
  64. data/lib/sslyze/xml/target.rb +371 -0
  65. data/lib/sslyze/xml/types.rb +19 -0
  66. data/ruby-sslyze.gemspec +3 -3
  67. data/spec/spec_helper.rb +2 -4
  68. data/spec/sslyze.xml +2356 -2580
  69. data/spec/x509/domain_spec.rb +125 -0
  70. data/spec/x509/extension_set_spec.rb +208 -0
  71. data/spec/x509/extension_spec.rb +58 -0
  72. data/spec/x509/extensions/basic_constraints_spec.rb +41 -0
  73. data/spec/x509/extensions/certificate_policies_spec.rb +38 -0
  74. data/spec/x509/extensions/crl_distribution_points_spec.rb +38 -0
  75. data/spec/x509/extensions/extended_key_usage_spec.rb +58 -0
  76. data/spec/x509/extensions/key_usage_spec.rb +84 -0
  77. data/spec/x509/extensions/subject_alt_name_spec.rb +146 -0
  78. data/spec/x509/name_spec.rb +85 -0
  79. data/spec/x509/public_key_spec.rb +113 -0
  80. data/spec/xml/certinfo/certificate_spec.rb +166 -0
  81. data/spec/xml/certinfo/certificate_validation/hostname_validation_spec.rb +23 -0
  82. data/spec/xml/certinfo/certificate_validation/path_validation_spec.rb +107 -0
  83. data/spec/xml/certinfo/certificate_validation/verified_certificate_chain_spec.rb +163 -0
  84. data/spec/xml/certinfo/certificate_validation_spec.rb +40 -0
  85. data/spec/xml/certinfo/ocsp_stapling/ocsp_response_spec.rb +61 -0
  86. data/spec/xml/certinfo/ocsp_stapling_spec.rb +31 -0
  87. data/spec/xml/certinfo/received_certificate_chain_spec.rb +165 -0
  88. data/spec/xml/certinfo_spec.rb +45 -0
  89. data/spec/xml/compression/compression_method_spec.rb +23 -0
  90. data/spec/xml/compression_spec.rb +23 -0
  91. data/spec/xml/heartbleed/openssl_heartbleed_spec.rb +17 -0
  92. data/spec/xml/heartbleed_spec.rb +37 -0
  93. data/spec/xml/http_headers/http_public_key_pinning_spec.rb +73 -0
  94. data/spec/xml/http_headers/http_strict_transport_security_spec.rb +107 -0
  95. data/spec/xml/http_headers_spec.rb +63 -0
  96. data/spec/xml/invalid_target_spec.rb +23 -0
  97. data/spec/xml/plugin_examples.rb +14 -0
  98. data/spec/{key_exchange_spec.rb → xml/protocol/cipher_suite/key_exchange_spec.rb} +9 -3
  99. data/spec/xml/protocol/cipher_suite_spec.rb +66 -0
  100. data/spec/xml/protocol_spec.rb +115 -0
  101. data/spec/xml/reneg/session_renegotiation_spec.rb +23 -0
  102. data/spec/xml/reneg_spec.rb +35 -0
  103. data/spec/xml/resum/session_resumption_with_session_ids_spec.rb +103 -0
  104. data/spec/xml/resum/session_resumption_with_tls_tickets_spec.rb +121 -0
  105. data/spec/xml/resum_rate_spec.rb +30 -0
  106. data/spec/xml/resum_spec.rb +47 -0
  107. data/spec/{target_spec.rb → xml/target_spec.rb} +73 -27
  108. data/spec/xml_spec.rb +13 -21
  109. metadata +138 -61
  110. data/lib/sslyze/cert_info.rb +0 -57
  111. data/lib/sslyze/certificate.rb +0 -139
  112. data/lib/sslyze/certificate/extensions.rb +0 -127
  113. data/lib/sslyze/certificate/extensions/authority_information_access.rb +0 -38
  114. data/lib/sslyze/certificate/extensions/extension.rb +0 -26
  115. data/lib/sslyze/certificate/extensions/x509v3_basic_constraints.rb +0 -60
  116. data/lib/sslyze/certificate/extensions/x509v3_certificate_policies.rb +0 -50
  117. data/lib/sslyze/certificate/extensions/x509v3_crl_distribution_points.rb +0 -32
  118. data/lib/sslyze/certificate/extensions/x509v3_extended_key_usage.rb +0 -32
  119. data/lib/sslyze/certificate/extensions/x509v3_key_usage.rb +0 -50
  120. data/lib/sslyze/certificate/extensions/x509v3_subject_alternative_name.rb +0 -71
  121. data/lib/sslyze/certificate/issuer.rb +0 -56
  122. data/lib/sslyze/certificate/public_key.rb +0 -9
  123. data/lib/sslyze/certificate/subject.rb +0 -117
  124. data/lib/sslyze/certificate/subject_public_key_info.rb +0 -53
  125. data/lib/sslyze/certificate/validity.rb +0 -9
  126. data/lib/sslyze/certificate_chain.rb +0 -89
  127. data/lib/sslyze/certificate_validation.rb +0 -70
  128. data/lib/sslyze/cipher_suite.rb +0 -237
  129. data/lib/sslyze/invalid_target.rb +0 -35
  130. data/lib/sslyze/key_exchange.rb +0 -106
  131. data/lib/sslyze/ocsp_response.rb +0 -87
  132. data/lib/sslyze/protocol.rb +0 -133
  133. data/lib/sslyze/target.rb +0 -312
  134. data/lib/sslyze/types.rb +0 -17
  135. data/spec/cert_info_spec.rb +0 -29
  136. data/spec/certificate/subject_name_spec.rb +0 -72
  137. data/spec/certificate_chain_spec.rb +0 -61
  138. data/spec/certificate_spec.rb +0 -330
  139. data/spec/certificate_validation_spec.rb +0 -39
  140. data/spec/cipher_suite_spec.rb +0 -50
  141. data/spec/invalid_target_spec.rb +0 -21
  142. data/spec/issuer_spec.rb +0 -33
  143. data/spec/ocsp_response_spec.rb +0 -59
  144. data/spec/protocol_spec.rb +0 -99
  145. data/spec/subject_public_key_info_spec.rb +0 -35
  146. data/spec/subject_spec.rb +0 -69
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/certificate_validation'
4
-
5
- describe SSLyze::CertificateValidation do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/certinfo/certificateValidation')) }
9
-
10
- describe "#hostname?" do
11
- it "should query hostnameValidation/@certificateMatchesServerHostname" do
12
- expect(subject.hostname?).to be true
13
- end
14
- end
15
-
16
- describe "#results" do
17
- it "should parse the pathValidation elements into a Hash" do
18
- expect(subject.results).to be == {
19
- 'Mozilla NSS' => 'ok',
20
- 'Microsoft' => 'ok',
21
- 'Apple' => 'ok',
22
- 'Java 6' => 'ok',
23
- 'Google' => 'ok'
24
- }
25
- end
26
- end
27
-
28
- describe "#path" do
29
- it "should check if each pathValidation/@validationResult is 'ok'" do
30
- expect(subject.path).to be == {
31
- 'Mozilla NSS' => true,
32
- 'Microsoft' => true,
33
- 'Apple' => true,
34
- 'Java 6' => true,
35
- 'Google' => true
36
- }
37
- end
38
- end
39
- end
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/cipher_suite'
4
-
5
- describe SSLyze::CipherSuite do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/tlsv1_2/acceptedCipherSuites/cipherSuite')) }
9
-
10
- describe "#name" do
11
- it "should parse the name attribute" do
12
- expect(subject.name).to be == 'AES128-GCM-SHA256'
13
- end
14
- end
15
-
16
- describe "#rfc_name" do
17
- it "should map the openssl name back to the RFC name" do
18
- expect(subject.rfc_name).to be == 'TLS_RSA_WITH_AES_128_GCM_SHA256'
19
- end
20
- end
21
-
22
- describe "#connection_status" do
23
- it "should parse the connectionStatus attribute" do
24
- expect(subject.connection_status).to be == 'HTTP 200 OK'
25
- end
26
- end
27
-
28
- describe "#anonymous?" do
29
- it "should query the anonymous attribute" do
30
- expect(subject.anonymous?).to be false
31
- end
32
- end
33
-
34
- describe "#key_exchange" do
35
- context "when the keyExchange child is present" do
36
- subject { described_class.new(xml.at('/document/results/target/tlsv1_2/acceptedCipherSuites/cipherSuite[keyExchange]')) }
37
-
38
- it "should return a KeyExchange object" do
39
- expect(subject.key_exchange).to be_kind_of(KeyExchange)
40
- end
41
- end
42
-
43
- context "when the keyExchange object is missing" do
44
- it "should return nil" do
45
- expect(subject.key_exchange).to be nil
46
- end
47
- end
48
- end
49
-
50
- end
@@ -1,21 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/invalid_target'
4
-
5
- describe SSLyze::InvalidTarget do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/invalidTargets/invalidTarget')) }
9
-
10
- describe "#host" do
11
- it "must parse the host attribute" do
12
- expect(subject.host).to be == '10.10.10.1:443'
13
- end
14
- end
15
-
16
- describe "#error" do
17
- it "must parse the ip attribute" do
18
- expect(subject.error).to be == 'Could not connect (timeout)'
19
- end
20
- end
21
- end
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/certificate'
4
-
5
- describe SSLyze::Certificate::Issuer do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/certinfo/certificateChain/certificate/issuer')) }
9
-
10
- describe "#country_name" do
11
- it "should parse the countryName" do
12
- expect(subject.country_name).to be == 'US'
13
- end
14
- end
15
-
16
- describe "#common_name" do
17
- it "should parse the commonName element" do
18
- expect(subject.common_name).to be == 'DigiCert SHA2 Extended Validation Server CA'
19
- end
20
- end
21
-
22
- describe "#organizational_unit_name" do
23
- it "should parse the organizationalUnitName element" do
24
- expect(subject.organizational_unit_name).to be == 'www.digicert.com'
25
- end
26
- end
27
-
28
- describe "#organization_name" do
29
- it "should parse the organizationName element" do
30
- expect(subject.organization_name).to be == 'DigiCert Inc'
31
- end
32
- end
33
- end
@@ -1,59 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/ocsp_response'
4
-
5
- describe SSLyze::OCSPResponse do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/certinfo/ocspStapling/ocspResponse')) }
9
-
10
- describe "#trusted?" do
11
- it "should query @isTrustedByMozillaCAStore" do
12
- expect(subject.trusted?).to be true
13
- end
14
- end
15
-
16
- describe "#type" do
17
- it "should query responseType" do
18
- expect(subject.type).to be == 'Basic OCSP Response'
19
- end
20
- end
21
-
22
- describe "#responder_id" do
23
- it "should query responderID" do
24
- expect(subject.responder_id).to be == '0E7DB19F96176475CE3E5D98725AF4ACADA03FAF'
25
- end
26
- end
27
-
28
- describe "#version" do
29
- it "should query version" do
30
- expect(subject.version).to be 1
31
- end
32
- end
33
-
34
- describe "#status" do
35
- it "should query responseStatus" do
36
- expect(subject.status).to be == :successful
37
- end
38
- end
39
-
40
- describe "#successful?" do
41
- context "when status is :successful" do
42
- before { expect(subject).to receive(:status).and_return(:successful) }
43
-
44
- specify { expect(subject.successful?).to be true }
45
- end
46
-
47
- context "when status is not :successful" do
48
- before { expect(subject).to receive(:status).and_return(:failure) }
49
-
50
- specify { expect(subject.successful?).to be false }
51
- end
52
- end
53
-
54
- describe "#produced_at" do
55
- it "should query producedAt and return a Time object" do
56
- expect(subject.produced_at).to be == Time.parse('Sep 24 22:58:23 2015 GMT')
57
- end
58
- end
59
- end
@@ -1,99 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/protocol'
4
-
5
- describe SSLyze::Protocol do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/tlsv1_2')) }
9
-
10
- describe "#name" do
11
- it "should return the protocol name" do
12
- expect(subject.name).to be == :tlsv1_2
13
- end
14
- end
15
-
16
- describe "#title" do
17
- it "must parse the title attribute" do
18
- expect(subject.title).to be == 'TLSV1_2 Cipher Suites'
19
- end
20
- end
21
-
22
- describe "#each_error" do
23
- pending "need data"
24
- end
25
-
26
- describe "#each_rejected_cipher_suite" do
27
- it "should yield CipherSuite objects" do
28
- expect { |b|
29
- subject.each_rejected_cipher_suite(&b)
30
- }
31
- end
32
-
33
- context "when given no block" do
34
- specify do
35
- expect(subject.each_rejected_cipher_suite).to be_an(Enumerator)
36
- end
37
- end
38
- end
39
-
40
- describe "#rejected_cipher_suites" do
41
- specify do
42
- expect(subject.rejected_cipher_suites).to be_an(Array).and(
43
- all(be_a(CipherSuite))
44
- )
45
- end
46
- end
47
-
48
- describe "#each_accepted_cipher_suite" do
49
- it "should yield CipherSuite objects" do
50
- expect { |b|
51
- subject.each_accepted_cipher_suite(&b)
52
- }
53
- end
54
-
55
- context "when given no block" do
56
- specify do
57
- expect(subject.each_accepted_cipher_suite).to be_an(Enumerator)
58
- end
59
- end
60
- end
61
-
62
- describe "#accepted_cipher_suites" do
63
- specify do
64
- expect(subject.accepted_cipher_suites).to be_an(Array).and(
65
- all(be_a(CipherSuite))
66
- )
67
- end
68
- end
69
-
70
- describe "#each_preferred_cipher_suite" do
71
- it "should yield CipherSuite objects" do
72
- expect { |b|
73
- subject.each_preferred_cipher_suite(&b)
74
- }
75
- end
76
-
77
- context "when given no block" do
78
- specify do
79
- expect(subject.each_preferred_cipher_suite).to be_an(Enumerator)
80
- end
81
- end
82
- end
83
-
84
- describe "#preferred_cipher_suites" do
85
- specify do
86
- expect(subject.preferred_cipher_suites).to be_an(Array).and(
87
- all(be_a(CipherSuite))
88
- )
89
- end
90
- end
91
-
92
- describe "#supported?" do
93
- context "when there are preferred cipher suites" do
94
- it "should return true" do
95
- expect(subject.supported?).to be(true)
96
- end
97
- end
98
- end
99
- end
@@ -1,35 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/certificate'
4
-
5
- describe SSLyze::Certificate::SubjectPublicKeyInfo do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/certinfo/certificateChain/certificate/subjectPublicKeyInfo')) }
9
-
10
- describe "#public_key" do
11
- it "should return a PublicKey object" do
12
- expect(subject.public_key).to be_a(Certificate::PublicKey)
13
- end
14
-
15
- it "should parse the publicKey/modulus element" do
16
- expect(subject.public_key.modulus).to be == %{00:b1:d4:dc:3c:af:fd:f3:4e:ed:c1:67:ad:e6:cb:22:e8:b7:e2:ab:28:f2:f7:dc:62:70:08:d1:0c:af:d6:16:6a:21:b0:36:4b:17:0d:36:63:04:ae:bf:ea:20:51:95:65:66:f2:bf:b9:4d:a4:0c:29:eb:f5:15:b1:e8:35:b3:70:10:94:d5:1b:59:b4:26:0f:d6:83:57:59:9d:e1:7c:09:dd:e0:13:ca:4d:6f:43:9b:cd:cf:87:3a:15:a7:85:dd:66:83:ed:93:0c:fe:2b:6d:38:1c:79:88:90:cf:ad:58:18:2d:51:d1:c2:a3:f2:47:8c:6f:38:09:b9:b8:ef:4c:93:0b:cb:83:94:87:ea:e0:a3:b5:d9:7b:9b:6b:0f:43:f9:ca:ee:80:0d:28:a7:76:f1:25:f4:c1:35:3c:f6:74:ad:de:6a:33:82:7b:dc:fd:4b:76:a7:c2:ee:f2:6a:bf:a9:24:a6:5f:e7:2e:7c:0e:db:c3:74:73:fa:7e:c6:d8:cf:60:eb:36:56:21:b6:c1:8a:b8:24:82:4d:78:24:ba:e9:1d:a1:8a:a7:87:be:66:25:69:bf:be:3b:72:6e:4f:e0:e4:85:25:08:b1:91:89:b8:d6:74:65:76:9b:2c:4f:62:1f:a1:fa:3a:be:9c:24:bf:9f:ca:b0:c5:c0:67:8d}
17
- end
18
-
19
- it "should parse the publicKey/exponent element" do
20
- expect(subject.public_key.exponent).to be == 65537
21
- end
22
- end
23
-
24
- describe "#public_key_algorithm" do
25
- it "should parse the publicKeyAlgorithm element" do
26
- expect(subject.public_key_algorithm).to be == 'rsaEncryption'
27
- end
28
- end
29
-
30
- describe "#public_key_size" do
31
- it "should parse the publicKeySize element" do
32
- expect(subject.public_key_size).to be == 2048
33
- end
34
- end
35
- end
@@ -1,69 +0,0 @@
1
- require 'spec_helper'
2
- require 'xml_examples'
3
- require 'sslyze/certificate'
4
-
5
- describe SSLyze::Certificate::Subject do
6
- include_examples "XML specs"
7
-
8
- subject { described_class.new(xml.at('/document/results/target/certinfo/certificateChain/certificate/subject')) }
9
-
10
- describe "#organizational_unit_name" do
11
- it "should parse the organizationUnitName element" do
12
- expect(subject.organizational_unit_name).to be == 'Information Security'
13
- end
14
- end
15
-
16
- describe "#organization_name" do
17
- it "should parse the organizationName element" do
18
- expect(subject.organization_name).to be == 'GitHub, Inc.'
19
- end
20
- end
21
-
22
- describe "#business_category" do
23
- it "should parse the businessCategory element" do
24
- expect(subject.business_category).to be == 'Private Organization'
25
- end
26
- end
27
-
28
- describe "#serial_number" do
29
- it "should parse the serialNumber element" do
30
- expect(subject.serial_number).to be == 5157550
31
- end
32
- end
33
-
34
- describe "#common_name" do
35
- it "should parse the commonName element" do
36
- expect(subject.common_name.name).to be == 'github.com'
37
- end
38
- end
39
-
40
- describe "#state_or_province_name" do
41
- it "should parse the stateOrProvinceName element" do
42
- expect(subject.state_or_province_name).to be == 'California'
43
- end
44
- end
45
-
46
- describe "#country_name" do
47
- it "should parse the countryName element" do
48
- expect(subject.country_name).to be == 'US'
49
- end
50
- end
51
-
52
- describe "#street_address" do
53
- it "should parse the streetAddress element" do
54
- expect(subject.street_address).to be == '548 4th Street'
55
- end
56
- end
57
-
58
- describe "#locality_name" do
59
- it "should parse the localityName element" do
60
- expect(subject.locality_name).to be == 'San Francisco'
61
- end
62
- end
63
-
64
- describe "#postal_code" do
65
- it "should parse the postalCode element" do
66
- expect(subject.postal_code).to be == '94107'
67
- end
68
- end
69
- end