From a1b23ba4ce7bb92221f97a2be1c2f8280165a663 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 10:38:52 +0200 Subject: [PATCH 01/14] Move regression spec to its own directory --- spec/{features => regressions}/ignay_spec.rb | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/{features => regressions}/ignay_spec.rb (100%) diff --git a/spec/features/ignay_spec.rb b/spec/regressions/ignay_spec.rb similarity index 100% rename from spec/features/ignay_spec.rb rename to spec/regressions/ignay_spec.rb From c7c73872d27af1f267cf6c5b284ee50530738392 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 10:48:15 +0200 Subject: [PATCH 02/14] Stub test classes in regression spec --- spec/regressions/ignay_spec.rb | 56 +++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/spec/regressions/ignay_spec.rb b/spec/regressions/ignay_spec.rb index cf390b6..2a33a8e 100644 --- a/spec/regressions/ignay_spec.rb +++ b/spec/regressions/ignay_spec.rb @@ -2,43 +2,49 @@ require "spec_helper" -class CatalogTree - include HappyMapper +RSpec.describe "parsing a VOD catalog" do + before do + catalog_tree = Class.new do + include HappyMapper - tag "CatalogTree" - register_namespace "xmlns", "urn:eventis:prodis:onlineapi:1.0" - register_namespace "xsi", "http://www.w3.org/2001/XMLSchema-instance" - register_namespace "xsd", "http://www.w3.org/2001/XMLSchema" + tag "CatalogTree" + register_namespace "xmlns", "urn:eventis:prodis:onlineapi:1.0" + register_namespace "xsi", "http://www.w3.org/2001/XMLSchema-instance" + register_namespace "xsd", "http://www.w3.org/2001/XMLSchema" - attribute :code, String + attribute :code, String - has_many :nodes, "CatalogNode", tag: "Node", xpath: "." -end + has_many :nodes, "CatalogNode", tag: "Node", xpath: "." + end + stub_const "CatalogTree", catalog_tree -class CatalogNode - include HappyMapper + catalog_node = Class.new do + include HappyMapper - tag "Node" + tag "Node" - attribute :back_office_id, String, tag: "vodBackOfficeId" + attribute :back_office_id, String, tag: "vodBackOfficeId" - has_one :name, String, tag: "Name" - # other important fields + has_one :name, String, tag: "Name" + # other important fields - has_many :translations, "CatalogNode::Translations", tag: "Translation", xpath: "child::*" + has_many :translations, "CatalogNode::Translations", tag: "Translation", + xpath: "child::*" - class Translations - include HappyMapper - tag "Translation" + has_many :nodes, self, tag: "Node", xpath: "child::*" + end + stub_const "CatalogNode", catalog_node - attribute :language, String, tag: "Language" - has_one :name, String, tag: "Name" - end + translations = Class.new do + include HappyMapper + tag "Translation" - has_many :nodes, CatalogNode, tag: "Node", xpath: "child::*" -end + attribute :language, String, tag: "Language" + has_one :name, String, tag: "Name" + end + stub_const "CatalogNode::Translations", translations + end -RSpec.describe "parsing a VOD catalog" do let(:catalog_tree) { CatalogTree.parse(fixture_file("inagy.xml"), single: true) } it "is not nil" do From 6af492a5784e646342b603f08b5786f36e4cce83 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 10:50:22 +0200 Subject: [PATCH 03/14] Give regression spec a clearer name --- spec/regressions/{ignay_spec.rb => vod_catalog_spec.rb} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename spec/regressions/{ignay_spec.rb => vod_catalog_spec.rb} (100%) diff --git a/spec/regressions/ignay_spec.rb b/spec/regressions/vod_catalog_spec.rb similarity index 100% rename from spec/regressions/ignay_spec.rb rename to spec/regressions/vod_catalog_spec.rb From 3b59a1c7823facfb65fc433b30d595f30de5d260 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 10:52:49 +0200 Subject: [PATCH 04/14] Disable RSpec/DescribeClass for regression specs These specs do not describe classes or modules. --- .rubocop.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.rubocop.yml b/.rubocop.yml index 763aab8..725d370 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -49,6 +49,11 @@ Naming/PredicateName: - 'has_many' - 'has_xml_content' +# regression specs do not describe classes +RSpec/DescribeClass: + Exclude: + - 'spec/regressions/*.rb' + # Disabled because RSpec/SpecFilePathFormat is automatically enabled as a new cop RSpec/FilePath: Enabled: false From f2732728363035222a178a42a4aed512cc0a9e08 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 11:39:02 +0200 Subject: [PATCH 05/14] Extract feature spec showing handling of optional attributes --- spec/features/optional_attributes_spec.rb | 27 +++++++++++++++++++++++ spec/happymapper_spec.rb | 23 ------------------- 2 files changed, 27 insertions(+), 23 deletions(-) create mode 100644 spec/features/optional_attributes_spec.rb diff --git a/spec/features/optional_attributes_spec.rb b/spec/features/optional_attributes_spec.rb new file mode 100644 index 0000000..b246832 --- /dev/null +++ b/spec/features/optional_attributes_spec.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +RSpec.describe "Parsing optional attributes" do + before do + klass = Class.new do + include HappyMapper + tag "address" + + attribute :street, String + end + stub_const "OptionalAttribute", klass + end + + let(:parsed_result) { OptionalAttribute.parse(fixture_file("optional_attributes.xml")) } + + it "parses an empty String as empty" do + expect(parsed_result[0].street).to eq("") + end + + it "parses a String with value" do + expect(parsed_result[1].street).to eq("Milchstrasse") + end + + it "parses an element with no value for the attribute" do + expect(parsed_result[2].street).to be_nil + end +end diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index e0909ba..d97422b 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -527,13 +527,6 @@ class Video element :publish_options, PublishOptions, tag: "publishOptions", namespace: "video" end -class OptionalAttribute - include HappyMapper - tag "address" - - attribute :street, String -end - class DefaultNamespaceCombi include HappyMapper @@ -1030,22 +1023,6 @@ class Thing expect(l.first.latitude).to eq("51.53469") end - describe "Parse optional attributes" do - let(:parsed_result) { OptionalAttribute.parse(fixture_file("optional_attributes.xml")) } - - it "parses an empty String as empty" do - expect(parsed_result[0].street).to eq("") - end - - it "parses a String with value" do - expect(parsed_result[1].street).to eq("Milchstrasse") - end - - it "parses an element with no value for the attribute" do - expect(parsed_result[2].street).to be_nil - end - end - describe "Default namespace combi" do let(:file_contents) { fixture_file("default_namespace_combi.xml") } let(:book) { DefaultNamespaceCombi.parse(file_contents, single: true) } From bae334459b04d9e34a3cf336c6aa80d4f79617b9 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 11:42:55 +0200 Subject: [PATCH 06/14] Extract regression spec for lastfm namespace handling --- spec/happymapper_spec.rb | 13 ------------- spec/regressions/lastfm_spec.rb | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 spec/regressions/lastfm_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index d97422b..d84c042 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -398,14 +398,6 @@ class Artist element :name, String end -class Location - include HappyMapper - - tag "point" - namespace "geo" - element :latitude, String, tag: "lat" -end - # Testing the XmlContent type module Dictionary class Variant @@ -1018,11 +1010,6 @@ class Thing end end - it "parses lastfm namespaces" do - l = Location.parse(fixture_file("lastfm.xml")) - expect(l.first.latitude).to eq("51.53469") - end - describe "Default namespace combi" do let(:file_contents) { fixture_file("default_namespace_combi.xml") } let(:book) { DefaultNamespaceCombi.parse(file_contents, single: true) } diff --git a/spec/regressions/lastfm_spec.rb b/spec/regressions/lastfm_spec.rb new file mode 100644 index 0000000..8275e3b --- /dev/null +++ b/spec/regressions/lastfm_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +RSpec.describe "parsing lastfm xml" do + before do + klass = Class.new do + include HappyMapper + + tag "point" + namespace "geo" + element :latitude, String, tag: "lat" + end + stub_const "Location", klass + end + + it "maps namespaces correctly" do + l = Location.parse(fixture_file("lastfm.xml")) + expect(l.first.latitude).to eq("51.53469") + end +end From b8df33ac3ce2dda3844c3d636a987eed4bde7f36 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 13:10:32 +0200 Subject: [PATCH 07/14] Extract regression spec for google analytics xml parsing --- spec/happymapper_spec.rb | 95 -------------------- spec/regressions/google_analytics_spec.rb | 101 ++++++++++++++++++++++ 2 files changed, 101 insertions(+), 95 deletions(-) create mode 100644 spec/regressions/google_analytics_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index d84c042..80e904b 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -3,72 +3,6 @@ require "spec_helper" require "uri" -module Analytics - class Property - include HappyMapper - - tag "property" - namespace "dxp" - attribute :name, String - attribute :value, String - end - - class Goal - include HappyMapper - - # Google Analytics does a dirtry trick where a user with no goals - # returns a profile without any goals data or the declared namespace - # which means Nokogiri does not pick up the namespace automatically. - # To fix this, we manually register the namespace to avoid bad XPath - # expression. Dirty, but works. - - register_namespace "ga", "http://schemas.google.com/ga/2009" - namespace "ga" - - tag "goal" - attribute :active, Boolean - attribute :name, String - attribute :number, Integer - attribute :value, Float - - def clean_name - name.gsub("ga:", "") - end - end - - class Profile - include HappyMapper - - tag "entry" - element :title, String - element :tableId, String, namespace: "dxp" - - has_many :properties, Property - has_many :goals, Goal - end - - class Entry - include HappyMapper - - tag "entry" - element :id, String - element :updated, DateTime - element :title, String - element :table_id, String, namespace: "dxp", tag: "tableId" - has_many :properties, Property - end - - class Feed - include HappyMapper - - tag "feed" - element :id, String - element :updated, DateTime - element :title, String - has_many :entries, Entry - end -end - module Atom class Feed include HappyMapper @@ -949,35 +883,6 @@ class Thing end end - it "is able to parse google analytics api xml" do - data = Analytics::Feed.parse(fixture_file("analytics.xml")) - - aggregate_failures do - expect(data.id).to eq("http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com") - expect(data.entries.size).to eq(4) - - entry = data.entries[0] - expect(entry.title).to eq("addictedtonew.com") - expect(entry.properties.size).to eq(4) - - property = entry.properties[0] - expect(property.name).to eq("ga:accountId") - expect(property.value).to eq("85301") - end - end - - it "is able to parse google analytics profile xml with manually declared namespace" do - data = Analytics::Profile.parse(fixture_file("analytics_profile.xml")) - - aggregate_failures do - expect(data.entries.size).to eq(6) - entry = data.entries[0] - expect(entry.title).to eq("www.homedepot.com") - expect(entry.properties.size).to eq(6) - expect(entry.goals.size).to eq(0) - end - end - it "allows speficying child element class with a string" do bar = StringFoo::Bar.parse "" diff --git a/spec/regressions/google_analytics_spec.rb b/spec/regressions/google_analytics_spec.rb new file mode 100644 index 0000000..c382663 --- /dev/null +++ b/spec/regressions/google_analytics_spec.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing Google Analytics XML" do + before do + property_klass = Class.new do + include HappyMapper + + tag "property" + namespace "dxp" + attribute :name, String + attribute :value, String + end + stub_const "Property", property_klass + + goal_klass = Class.new do + include HappyMapper + + # Google Analytics does a dirtry trick where a user with no goals + # returns a profile without any goals data or the declared namespace + # which means Nokogiri does not pick up the namespace automatically. + # To fix this, we manually register the namespace to avoid bad XPath + # expression. Dirty, but works. + + register_namespace "ga", "http://schemas.google.com/ga/2009" + namespace "ga" + + tag "goal" + attribute :active, HappyMapper::Boolean + attribute :name, String + attribute :number, Integer + attribute :value, Float + end + stub_const "Goal", goal_klass + + profile_klass = Class.new do + include HappyMapper + + tag "entry" + element :title, String + element :tableId, String, namespace: "dxp" + + has_many :properties, Property + has_many :goals, Goal + end + stub_const "Profile", profile_klass + + entry_klass = Class.new do + include HappyMapper + + tag "entry" + element :id, String + element :updated, DateTime + element :title, String + element :table_id, String, namespace: "dxp", tag: "tableId" + has_many :properties, Property + end + stub_const "Entry", entry_klass + + feed_klass = Class.new do + include HappyMapper + + tag "feed" + element :id, String + element :updated, DateTime + element :title, String + has_many :entries, Entry + end + stub_const "Feed", feed_klass + end + + it "is able to parse google analytics api xml" do + data = Feed.parse(fixture_file("analytics.xml")) + + aggregate_failures do + expect(data.id).to eq("http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com") + expect(data.entries.size).to eq(4) + + entry = data.entries[0] + expect(entry.title).to eq("addictedtonew.com") + expect(entry.properties.size).to eq(4) + + property = entry.properties[0] + expect(property.name).to eq("ga:accountId") + expect(property.value).to eq("85301") + end + end + + it "is able to parse google analytics profile xml with manually declared namespace" do + data = Profile.parse(fixture_file("analytics_profile.xml")) + + aggregate_failures do + expect(data.entries.size).to eq(6) + entry = data.entries[0] + expect(entry.title).to eq("www.homedepot.com") + expect(entry.properties.size).to eq(6) + expect(entry.goals.size).to eq(0) + end + end +end From 5d0f176f286a72099c74714267d47251bb1ee6ae Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 13:26:40 +0200 Subject: [PATCH 08/14] Extract regression spec for familysearch xml parsing --- spec/happymapper_spec.rb | 56 ----------------------- spec/regressions/familysearch_spec.rb | 66 +++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 56 deletions(-) create mode 100644 spec/regressions/familysearch_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index 80e904b..c597e3b 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -71,45 +71,6 @@ class Rate include HappyMapper end -module FamilySearch - class AlternateIds - include HappyMapper - - tag "alternateIds" - has_many :ids, String, tag: "id" - end - - class Information - include HappyMapper - - has_one :alternateIds, AlternateIds - end - - class Person - include HappyMapper - - attribute :version, String - attribute :modified, Time - attribute :id, String - has_one :information, Information - end - - class Persons - include HappyMapper - has_many :person, Person - end - - class FamilyTree - include HappyMapper - - tag "familytree" - attribute :version, String - attribute :status_message, String, tag: "statusMessage" - attribute :status_code, String, tag: "statusCode" - has_one :persons, Persons - end -end - module FedEx class Address include HappyMapper @@ -889,23 +850,6 @@ class Thing expect(bar.things).to contain_exactly(StringFoo::Thing) end - it "parses family search xml" do - tree = FamilySearch::FamilyTree.parse(fixture_file("family_tree.xml")) - - aggregate_failures do - expect(tree.version).to eq("1.0.20071213.942") - expect(tree.status_message).to eq("OK") - expect(tree.status_code).to eq("200") - expect(tree.persons.person.size).to eq(1) - expect(tree.persons.person.first.version).to eq("1199378491000") - expect(tree.persons.person.first.modified) - .to eq(Time.utc(2008, 1, 3, 16, 41, 31)) # 2008-01-03T09:41:31-07:00 - expect(tree.persons.person.first.id).to eq("KWQS-BBQ") - expect(tree.persons.person.first.information.alternateIds.ids).not_to be_a(String) - expect(tree.persons.person.first.information.alternateIds.ids.size).to eq(8) - end - end - it "parses multiple images" do artist = Artist.parse(fixture_file("multiple_primitives.xml")) diff --git a/spec/regressions/familysearch_spec.rb b/spec/regressions/familysearch_spec.rb new file mode 100644 index 0000000..9dae8be --- /dev/null +++ b/spec/regressions/familysearch_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing a familysearch family tree" do + before do + alternateids_klass = Class.new do + include HappyMapper + + tag "alternateIds" + has_many :ids, String, tag: "id" + end + stub_const "AlternateIds", alternateids_klass + + information_klass = Class.new do + include HappyMapper + + has_one :alternateIds, AlternateIds + end + stub_const "Information", information_klass + + person_klass = Class.new do + include HappyMapper + + attribute :version, String + attribute :modified, Time + attribute :id, String + has_one :information, Information + end + stub_const "Person", person_klass + + persons_klass = Class.new do + include HappyMapper + has_many :person, Person + end + stub_const "Persons", persons_klass + + familytree_klass = Class.new do + include HappyMapper + + tag "familytree" + attribute :version, String + attribute :status_message, String, tag: "statusMessage" + attribute :status_code, String, tag: "statusCode" + has_one :persons, Persons + end + stub_const "FamilyTree", familytree_klass + end + + it "parses family search xml correctly" do + tree = FamilyTree.parse(fixture_file("family_tree.xml")) + + aggregate_failures do + expect(tree.version).to eq("1.0.20071213.942") + expect(tree.status_message).to eq("OK") + expect(tree.status_code).to eq("200") + expect(tree.persons.person.size).to eq(1) + expect(tree.persons.person.first.version).to eq("1199378491000") + expect(tree.persons.person.first.modified) + .to eq(Time.utc(2008, 1, 3, 16, 41, 31)) # 2008-01-03T09:41:31-07:00 + expect(tree.persons.person.first.id).to eq("KWQS-BBQ") + expect(tree.persons.person.first.information.alternateIds.ids).not_to be_a(String) + expect(tree.persons.person.first.information.alternateIds.ids.size).to eq(8) + end + end +end From 72834e55c0ba9db5d5c3460c23159ff7570efcad Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 13:35:44 +0200 Subject: [PATCH 09/14] Extract regression spec for github xml parsing --- spec/happymapper_spec.rb | 25 ------------------------- spec/regressions/github_spec.rb | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 25 deletions(-) create mode 100644 spec/regressions/github_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index c597e3b..2cf3c6c 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -241,19 +241,6 @@ class Items end end -module GitHub - class Commit - include HappyMapper - - tag "commit" - element :url, String - element :tree, String - element :message, String - element :id, String - element :"committed-date", Date - end -end - module QuarterTest class Quarter include HappyMapper @@ -751,18 +738,6 @@ class Thing end end - it "parses xml that has elements with dashes" do - commit = GitHub::Commit.parse(fixture_file("commit.xml")) - - aggregate_failures do - expect(commit.message).to eq("move commands.rb and helpers.rb into commands/ dir") - expect(commit.url).to eq("http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b") - expect(commit.id).to eq("c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b") - expect(commit.committed_date).to eq(Date.parse("2008-03-02T16:45:41-08:00")) - expect(commit.tree).to eq("28a1a1ca3e663d35ba8bf07d3f1781af71359b76") - end - end - it "parses xml with no namespace" do product = Product.parse(fixture_file("product_no_namespace.xml"), single: true) diff --git a/spec/regressions/github_spec.rb b/spec/regressions/github_spec.rb new file mode 100644 index 0000000..f49dc81 --- /dev/null +++ b/spec/regressions/github_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing github commit xml" do + before do + commit_klass = Class.new do + include HappyMapper + + tag "commit" + element :url, String + element :tree, String + element :message, String + element :id, String + element :"committed-date", Date + end + stub_const "Commit", commit_klass + end + + it "parses xml that has elements with dashes" do + commit = Commit.parse(fixture_file("commit.xml")) + + aggregate_failures do + expect(commit.message).to eq("move commands.rb and helpers.rb into commands/ dir") + expect(commit.url).to eq("http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b") + expect(commit.id).to eq("c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b") + expect(commit.committed_date).to eq(Date.parse("2008-03-02T16:45:41-08:00")) + expect(commit.tree).to eq("28a1a1ca3e663d35ba8bf07d3f1781af71359b76") + end + end +end From df759df09364efb3694d47d35e03d9ba033685de Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 13:43:06 +0200 Subject: [PATCH 10/14] Extrect regression spec for fedex xml parsing --- spec/happymapper_spec.rb | 126 ------------------------------ spec/regressions/fedex_spec.rb | 138 +++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 126 deletions(-) create mode 100644 spec/regressions/fedex_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index 2cf3c6c..bb2b2a3 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -71,87 +71,6 @@ class Rate include HappyMapper end -module FedEx - class Address - include HappyMapper - - tag "Address" - namespace "v2" - element :city, String, tag: "City" - element :state, String, tag: "StateOrProvinceCode" - element :zip, String, tag: "PostalCode" - element :countrycode, String, tag: "CountryCode" - element :residential, Boolean, tag: "Residential" - end - - class Event - include HappyMapper - - tag "Events" - namespace "v2" - element :timestamp, String, tag: "Timestamp" - element :eventtype, String, tag: "EventType" - element :eventdescription, String, tag: "EventDescription" - has_one :address, Address - end - - class PackageWeight - include HappyMapper - - tag "PackageWeight" - namespace "v2" - element :units, String, tag: "Units" - element :value, Integer, tag: "Value" - end - - class TrackDetails - include HappyMapper - - tag "TrackDetails" - namespace "v2" - element :tracking_number, String, tag: "TrackingNumber" - element :status_code, String, tag: "StatusCode" - element :status_desc, String, tag: "StatusDescription" - element :carrier_code, String, tag: "CarrierCode" - element :service_info, String, tag: "ServiceInfo" - has_one :weight, PackageWeight, tag: "PackageWeight" - element :est_delivery, String, tag: "EstimatedDeliveryTimestamp" - has_many :events, Event - end - - class Notification - include HappyMapper - - tag "Notifications" - namespace "v2" - element :severity, String, tag: "Severity" - element :source, String, tag: "Source" - element :code, Integer, tag: "Code" - element :message, String, tag: "Message" - element :localized_message, String, tag: "LocalizedMessage" - end - - class TransactionDetail - include HappyMapper - - tag "TransactionDetail" - namespace "v2" - element :cust_tran_id, String, tag: "CustomerTransactionId" - end - - class TrackReply - include HappyMapper - - tag "TrackReply" - namespace "v2" - element :highest_severity, String, tag: "HighestSeverity" - element :more_data, Boolean, tag: "MoreData" - has_many :notifications, Notification, tag: "Notifications" - has_many :trackdetails, TrackDetails, tag: "TrackDetails" - has_one :tran_detail, TransactionDetail, tab: "TransactionDetail" - end -end - class Place include HappyMapper element :name, String @@ -774,51 +693,6 @@ class Thing end end - it "parses xml with multiple namespaces" do - track = FedEx::TrackReply.parse(fixture_file("multiple_namespaces.xml")) - - aggregate_failures do - expect(track.highest_severity).to eq("SUCCESS") - expect(track.more_data).to be_falsey - notification = track.notifications.first - expect(notification.code).to eq(0) - expect(notification.localized_message).to eq("Request was successfully processed.") - expect(notification.message).to eq("Request was successfully processed.") - expect(notification.severity).to eq("SUCCESS") - expect(notification.source).to eq("trck") - detail = track.trackdetails.first - expect(detail.carrier_code).to eq("FDXG") - expect(detail.est_delivery).to eq("2009-01-02T00:00:00") - expect(detail.service_info).to eq("Ground-Package Returns Program-Domestic") - expect(detail.status_code).to eq("OD") - expect(detail.status_desc).to eq("On FedEx vehicle for delivery") - expect(detail.tracking_number).to eq("9611018034267800045212") - expect(detail.weight.units).to eq("LB") - expect(detail.weight.value).to eq(2) - events = detail.events - expect(events.size).to eq(10) - first_event = events[0] - expect(first_event.eventdescription).to eq("On FedEx vehicle for delivery") - expect(first_event.eventtype).to eq("OD") - expect(first_event.timestamp).to eq("2009-01-02T06:00:00") - expect(first_event.address.city).to eq("WICHITA") - expect(first_event.address.countrycode).to eq("US") - expect(first_event.address.residential).to be_falsey - expect(first_event.address.state).to eq("KS") - expect(first_event.address.zip).to eq("67226") - last_event = events[-1] - expect(last_event.eventdescription).to eq("In FedEx possession") - expect(last_event.eventtype).to eq("IP") - expect(last_event.timestamp).to eq("2008-12-27T09:40:00") - expect(last_event.address.city).to eq("LONGWOOD") - expect(last_event.address.countrycode).to eq("US") - expect(last_event.address.residential).to be_falsey - expect(last_event.address.state).to eq("FL") - expect(last_event.address.zip).to eq("327506398") - expect(track.tran_detail.cust_tran_id).to eq("20090102-111321") - end - end - it "allows speficying child element class with a string" do bar = StringFoo::Bar.parse "" diff --git a/spec/regressions/fedex_spec.rb b/spec/regressions/fedex_spec.rb new file mode 100644 index 0000000..19d5474 --- /dev/null +++ b/spec/regressions/fedex_spec.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing FedEx xml" do + before do + address_klass = Class.new do + include HappyMapper + + tag "Address" + namespace "v2" + element :city, String, tag: "City" + element :state, String, tag: "StateOrProvinceCode" + element :zip, String, tag: "PostalCode" + element :countrycode, String, tag: "CountryCode" + element :residential, HappyMapper::Boolean, tag: "Residential" + end + stub_const "Address", address_klass + + event_klass = Class.new do + include HappyMapper + + tag "Events" + namespace "v2" + element :timestamp, String, tag: "Timestamp" + element :eventtype, String, tag: "EventType" + element :eventdescription, String, tag: "EventDescription" + has_one :address, Address + end + stub_const "Event", event_klass + + packageweight_klass = Class.new do + include HappyMapper + + tag "PackageWeight" + namespace "v2" + element :units, String, tag: "Units" + element :value, Integer, tag: "Value" + end + stub_const "PackageWeight", packageweight_klass + + trackdetails_klass = Class.new do + include HappyMapper + + tag "TrackDetails" + namespace "v2" + element :tracking_number, String, tag: "TrackingNumber" + element :status_code, String, tag: "StatusCode" + element :status_desc, String, tag: "StatusDescription" + element :carrier_code, String, tag: "CarrierCode" + element :service_info, String, tag: "ServiceInfo" + has_one :weight, PackageWeight, tag: "PackageWeight" + element :est_delivery, String, tag: "EstimatedDeliveryTimestamp" + has_many :events, Event + end + stub_const "TrackDetails", trackdetails_klass + + notification_klass = Class.new do + include HappyMapper + + tag "Notifications" + namespace "v2" + element :severity, String, tag: "Severity" + element :source, String, tag: "Source" + element :code, Integer, tag: "Code" + element :message, String, tag: "Message" + element :localized_message, String, tag: "LocalizedMessage" + end + stub_const "Notification", notification_klass + + transactiondetail_klass = Class.new do + include HappyMapper + + tag "TransactionDetail" + namespace "v2" + element :cust_tran_id, String, tag: "CustomerTransactionId" + end + stub_const "TransactionDetail", transactiondetail_klass + + trackreply_klass = Class.new do + include HappyMapper + + tag "TrackReply" + namespace "v2" + element :highest_severity, String, tag: "HighestSeverity" + element :more_data, HappyMapper::Boolean, tag: "MoreData" + has_many :notifications, Notification, tag: "Notifications" + has_many :trackdetails, TrackDetails, tag: "TrackDetails" + has_one :tran_detail, TransactionDetail, tab: "TransactionDetail" + end + stub_const "TrackReply", trackreply_klass + end + + it "parses xml with multiple namespaces" do + track = TrackReply.parse(fixture_file("multiple_namespaces.xml")) + + aggregate_failures do + expect(track.highest_severity).to eq("SUCCESS") + expect(track.more_data).to be_falsey + notification = track.notifications.first + expect(notification.code).to eq(0) + expect(notification.localized_message).to eq("Request was successfully processed.") + expect(notification.message).to eq("Request was successfully processed.") + expect(notification.severity).to eq("SUCCESS") + expect(notification.source).to eq("trck") + detail = track.trackdetails.first + expect(detail.carrier_code).to eq("FDXG") + expect(detail.est_delivery).to eq("2009-01-02T00:00:00") + expect(detail.service_info).to eq("Ground-Package Returns Program-Domestic") + expect(detail.status_code).to eq("OD") + expect(detail.status_desc).to eq("On FedEx vehicle for delivery") + expect(detail.tracking_number).to eq("9611018034267800045212") + expect(detail.weight.units).to eq("LB") + expect(detail.weight.value).to eq(2) + events = detail.events + expect(events.size).to eq(10) + first_event = events[0] + expect(first_event.eventdescription).to eq("On FedEx vehicle for delivery") + expect(first_event.eventtype).to eq("OD") + expect(first_event.timestamp).to eq("2009-01-02T06:00:00") + expect(first_event.address.city).to eq("WICHITA") + expect(first_event.address.countrycode).to eq("US") + expect(first_event.address.residential).to be_falsey + expect(first_event.address.state).to eq("KS") + expect(first_event.address.zip).to eq("67226") + last_event = events[-1] + expect(last_event.eventdescription).to eq("In FedEx possession") + expect(last_event.eventtype).to eq("IP") + expect(last_event.timestamp).to eq("2008-12-27T09:40:00") + expect(last_event.address.city).to eq("LONGWOOD") + expect(last_event.address.countrycode).to eq("US") + expect(last_event.address.residential).to be_falsey + expect(last_event.address.state).to eq("FL") + expect(last_event.address.zip).to eq("327506398") + expect(track.tran_detail.cust_tran_id).to eq("20090102-111321") + end + end +end From b05758d247657591cb96e8165adc0c56222e524b Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 15:36:37 +0200 Subject: [PATCH 11/14] Extract regression spec for amazon xml parsing --- spec/happymapper_spec.rb | 51 ---------------- .../amazon_search_response_spec.rb | 59 +++++++++++++++++++ 2 files changed, 59 insertions(+), 51 deletions(-) create mode 100644 spec/regressions/amazon_search_response_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index bb2b2a3..be495fd 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "spec_helper" -require "uri" module Atom class Feed @@ -134,32 +133,6 @@ class CurrentWeather element :current_condition, String, tag: "current-condition", attributes: { icon: String } end -# for type coercion -class ProductGroup < String; end - -module PITA - class Item - include HappyMapper - - tag "Item" # if you put class in module you need tag - element :asin, String, tag: "ASIN" - element :detail_page_url, URI, tag: "DetailPageURL", parser: :parse - element :manufacturer, String, tag: "Manufacturer", deep: true - element :point, String, tag: "point", namespace: "georss" - element :product_group, ProductGroup, tag: "ProductGroup", deep: true, - parser: :new, raw: true - end - - class Items - include HappyMapper - - tag "Items" # if you put class in module you need tag - element :total_results, Integer, tag: "TotalResults" - element :total_pages, Integer, tag: "TotalPages" - has_many :items, Item - end -end - module QuarterTest class Quarter include HappyMapper @@ -569,30 +542,6 @@ class Thing expect(address.class).to eq(Address) end - it "parses xml with default namespace (amazon)" do - file_contents = fixture_file("pita.xml") - items = PITA::Items.parse(file_contents, single: true) - - aggregate_failures do - expect(items.total_results).to eq(22) - expect(items.total_pages).to eq(3) - - first = items.items[0] - - expect(first.asin).to eq("0321480791") - expect(first.point).to eq("38.5351715088 -121.7948684692") - expect(first.detail_page_url).to be_a(URI) - expect(first.detail_page_url.to_s).to eq("http://www.amazon.com/gp/redirect.html%3FASIN=0321480791%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321480791%253FSubscriptionId=dontbeaswoosh") - expect(first.manufacturer).to eq("Addison-Wesley Professional") - expect(first.product_group).to eq("Book") - - second = items.items[1] - - expect(second.asin).to eq("047022388X") - expect(second.manufacturer).to eq("Wrox") - end - end - it "parses xml that has attributes of elements" do items = CurrentWeather.parse(fixture_file("current_weather.xml")) first = items[0] diff --git a/spec/regressions/amazon_search_response_spec.rb b/spec/regressions/amazon_search_response_spec.rb new file mode 100644 index 0000000..764851b --- /dev/null +++ b/spec/regressions/amazon_search_response_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" +require "uri" + +RSpec.describe "parsing an amazon search result" do + before do + # for type coercion + productgroup_klass = Class.new(String) + stub_const "ProductGroup", productgroup_klass + + item_klass = Class.new do + include HappyMapper + + tag "Item" + element :asin, String, tag: "ASIN" + element :detail_page_url, URI, tag: "DetailPageURL", parser: :parse + element :manufacturer, String, tag: "Manufacturer", deep: true + element :point, String, tag: "point", namespace: "georss" + element :product_group, ProductGroup, tag: "ProductGroup", deep: true, + parser: :new, raw: true + end + stub_const "Item", item_klass + + items_klass = Class.new do + include HappyMapper + + tag "Items" + element :total_results, Integer, tag: "TotalResults" + element :total_pages, Integer, tag: "TotalPages" + has_many :items, Item + end + stub_const "Items", items_klass + end + + it "parses xml with default and other namespace and various custom parsing" do + file_contents = fixture_file("pita.xml") + items = Items.parse(file_contents, single: true) + + aggregate_failures do + expect(items.total_results).to eq(22) + expect(items.total_pages).to eq(3) + + first = items.items[0] + + expect(first.asin).to eq("0321480791") + expect(first.point).to eq("38.5351715088 -121.7948684692") + expect(first.detail_page_url).to be_a(URI) + expect(first.detail_page_url.to_s).to eq("http://www.amazon.com/gp/redirect.html%3FASIN=0321480791%26tag=ws%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/0321480791%253FSubscriptionId=dontbeaswoosh") + expect(first.manufacturer).to eq("Addison-Wesley Professional") + expect(first.product_group).to eq("Book") + + second = items.items[1] + + expect(second.asin).to eq("047022388X") + expect(second.manufacturer).to eq("Wrox") + end + end +end From f5f21488c98a9f45e3e43a09ef298f6ff776bb45 Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 16:00:36 +0200 Subject: [PATCH 12/14] Extract regression spec for yahoo posts xml parsing --- spec/happymapper_spec.rb | 69 +++++++++++++--------------- spec/regressions/yahoo_posts_spec.rb | 41 +++++++++++++++++ 2 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 spec/regressions/yahoo_posts_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index be495fd..4721b58 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -80,18 +80,6 @@ class Radar has_many :places, Place, tag: :place end -class Post - include HappyMapper - - attribute :href, String - attribute :hash, String - attribute :description, String - attribute :tag, String - attribute :time, Time - attribute :others, Integer - attribute :extended, String -end - class User include HappyMapper @@ -425,10 +413,29 @@ class Thing end describe "#attributes" do + let(:foo_klass) do + Class.new do + include HappyMapper + + attribute :foo, String + attribute :bar, String + end + end + let(:bar_klass) do + Class.new do + include HappyMapper + + attribute :baz1, String + attribute :baz2, String + attribute :baz3, String + attribute :baz4, String + end + end + it "returns only attributes for the current class" do aggregate_failures do - expect(Post.attributes.size).to eq(7) - expect(Status.attributes.size).to eq(0) + expect(foo_klass.attributes.size).to eq 2 + expect(bar_klass.attributes.size).to eq 4 end end end @@ -436,7 +443,7 @@ class Thing describe "#elements" do it "returns only elements for the current class" do aggregate_failures do - expect(Post.elements.size).to eq(0) + expect(User.elements.size).to eq(9) expect(Status.elements.size).to eq(10) end end @@ -467,27 +474,6 @@ class Thing end end - it "parses xml attributes into ruby objects" do - posts = Post.parse(fixture_file("posts.xml")) - - aggregate_failures do - expect(posts.size).to eq(20) - first = posts.first - expect(first.href).to eq("http://roxml.rubyforge.org/") - expect(first.hash).to eq("19bba2ab667be03a19f67fb67dc56917") - expect(first.description).to eq("ROXML - Ruby Object to XML Mapping Library") - expect(first.tag).to eq("ruby xml gems mapping") - expect(first.time).to eq(Time.utc(2008, 8, 9, 5, 24, 20)) - expect(first.others).to eq(56) - expect(first.extended) - .to eq("ROXML is a Ruby library designed to make it easier for Ruby" \ - " developers to work with XML. Using simple annotations, it enables" \ - " Ruby classes to be custom-mapped to XML. ROXML takes care of the" \ - " marshalling and unmarshalling of mapped attributes so that developers" \ - " can focus on building first-class Ruby classes.") - end - end - it "parses xml elements to ruby objcts" do statuses = Status.parse(fixture_file("statuses.xml")) @@ -739,9 +725,16 @@ class Thing end describe "with limit option" do + let(:post_klass) do + Class.new do + include HappyMapper + tag "post" + end + end + it "returns results with limited size: 6" do sizes = [] - Post.parse(fixture_file("posts.xml"), in_groups_of: 6) do |a| + post_klass.parse(fixture_file("posts.xml"), in_groups_of: 6) do |a| sizes << a.size end expect(sizes).to eq([6, 6, 6, 2]) @@ -749,7 +742,7 @@ class Thing it "returns results with limited size: 10" do sizes = [] - Post.parse(fixture_file("posts.xml"), in_groups_of: 10) do |a| + post_klass.parse(fixture_file("posts.xml"), in_groups_of: 10) do |a| sizes << a.size end expect(sizes).to eq([10, 10]) diff --git a/spec/regressions/yahoo_posts_spec.rb b/spec/regressions/yahoo_posts_spec.rb new file mode 100644 index 0000000..af93367 --- /dev/null +++ b/spec/regressions/yahoo_posts_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing a yahoo posts xml" do + before do + post_klass = Class.new do + include HappyMapper + + attribute :href, String + attribute :hash, String + attribute :description, String + attribute :tag, String + attribute :time, Time + attribute :others, Integer + attribute :extended, String + end + stub_const "Post", post_klass + end + + it "parses xml attributes into ruby objects" do + posts = Post.parse(fixture_file("posts.xml")) + + aggregate_failures do + expect(posts.size).to eq(20) + first = posts.first + expect(first.href).to eq("http://roxml.rubyforge.org/") + expect(first.hash).to eq("19bba2ab667be03a19f67fb67dc56917") + expect(first.description).to eq("ROXML - Ruby Object to XML Mapping Library") + expect(first.tag).to eq("ruby xml gems mapping") + expect(first.time).to eq(Time.utc(2008, 8, 9, 5, 24, 20)) + expect(first.others).to eq(56) + expect(first.extended) + .to eq("ROXML is a Ruby library designed to make it easier for Ruby" \ + " developers to work with XML. Using simple annotations, it enables" \ + " Ruby classes to be custom-mapped to XML. ROXML takes care of the" \ + " marshalling and unmarshalling of mapped attributes so that developers" \ + " can focus on building first-class Ruby classes.") + end + end +end From 949d1e204cf918fc41190f0f77ff92211459e33f Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 16:32:01 +0200 Subject: [PATCH 13/14] Extract regression spec for twitter status xml parsing --- spec/happymapper_spec.rb | 93 +++++++---------------- spec/regressions/twitter_statuses_spec.rb | 67 ++++++++++++++++ 2 files changed, 93 insertions(+), 67 deletions(-) create mode 100644 spec/regressions/twitter_statuses_spec.rb diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index 4721b58..8822ebf 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -80,37 +80,6 @@ class Radar has_many :places, Place, tag: :place end -class User - include HappyMapper - - element :id, Integer - element :name, String - element :screen_name, String - element :location, String - element :description, String - element :profile_image_url, String - element :url, String - element :protected, Boolean - element :followers_count, Integer -end - -class Status - include HappyMapper - - register_namespace "fake", "faka:namespace" - - element :id, Integer - element :text, String - element :created_at, Time - element :source, String - element :truncated, Boolean - element :in_reply_to_status_id, Integer - element :in_reply_to_user_id, Integer - element :favorited, Boolean - element :non_existent, String, tag: "dummy", namespace: "fake" - has_one :user, User -end - class CurrentWeather include HappyMapper @@ -310,9 +279,10 @@ class Thing describe HappyMapper do describe "being included into another class" do let(:klass) do - Class.new do - include HappyMapper - end + Class.new { include HappyMapper } + end + let(:nested_klass) do + Class.new { include HappyMapper } end it "sets attributes to an array" do @@ -358,23 +328,23 @@ class Thing end it "allows has one association" do - klass.has_one(:user, User) + klass.has_one(:user, nested_klass) element = klass.elements.first aggregate_failures do expect(element.name).to eq("user") - expect(element.type).to eq(User) + expect(element.type).to eq(nested_klass) expect(element.options[:single]).to be(true) end end it "allows has many association" do - klass.has_many(:users, User) + klass.has_many(:users, nested_klass) element = klass.elements.first aggregate_failures do expect(element.name).to eq("users") - expect(element.type).to eq(User) + expect(element.type).to eq(nested_klass) expect(element.options[:single]).to be(false) end end @@ -441,10 +411,26 @@ class Thing end describe "#elements" do + let(:foo_klass) do + Class.new do + include HappyMapper + + element :foo, String + end + end + let(:bar_klass) do + Class.new do + include HappyMapper + + element :baz1, String + element :baz2, String + end + end + it "returns only elements for the current class" do aggregate_failures do - expect(User.elements.size).to eq(9) - expect(Status.elements.size).to eq(10) + expect(foo_klass.elements.size).to eq 1 + expect(bar_klass.elements.size).to eq 2 end end end @@ -474,33 +460,6 @@ class Thing end end - it "parses xml elements to ruby objcts" do - statuses = Status.parse(fixture_file("statuses.xml")) - - aggregate_failures do - expect(statuses.size).to eq(20) - first = statuses.first - expect(first.id).to eq(882_281_424) - expect(first.created_at).to eq(Time.utc(2008, 8, 9, 5, 38, 12)) - expect(first.source).to eq("web") - expect(first.truncated).to be_falsey - expect(first.in_reply_to_status_id).to eq(1234) - expect(first.in_reply_to_user_id).to eq(12_345) - expect(first.favorited).to be_falsey - expect(first.user.id).to eq(4243) - expect(first.user.name).to eq("John Nunemaker") - expect(first.user.screen_name).to eq("jnunemaker") - expect(first.user.location).to eq("Mishawaka, IN, US") - expect(first.user.description) - .to eq "Loves his wife, ruby, notre dame football and iu basketball" - expect(first.user.profile_image_url) - .to eq("http://s3.amazonaws.com/twitter_production/profile_images/53781608/Photo_75_normal.jpg") - expect(first.user.url).to eq("http://addictedtonew.com") - expect(first.user.protected).to be_falsey - expect(first.user.followers_count).to eq(486) - end - end - it "parses xml containing the desired element as root node" do address = Address.parse(fixture_file("address.xml"), single: true) diff --git a/spec/regressions/twitter_statuses_spec.rb b/spec/regressions/twitter_statuses_spec.rb new file mode 100644 index 0000000..580c138 --- /dev/null +++ b/spec/regressions/twitter_statuses_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "parsing twitter statuses" do + before do + user_klass = Class.new do + include HappyMapper + + element :id, Integer + element :name, String + element :screen_name, String + element :location, String + element :description, String + element :profile_image_url, String + element :url, String + element :protected, HappyMapper::Boolean + element :followers_count, Integer + end + stub_const "User", user_klass + + status_klass = Class.new do + include HappyMapper + + register_namespace "fake", "faka:namespace" + + element :id, Integer + element :text, String + element :created_at, Time + element :source, String + element :truncated, HappyMapper::Boolean + element :in_reply_to_status_id, Integer + element :in_reply_to_user_id, Integer + element :favorited, HappyMapper::Boolean + element :non_existent, String, tag: "dummy", namespace: "fake" + has_one :user, User + end + stub_const "Status", status_klass + end + + it "parses xml elements to ruby objects" do + statuses = Status.parse(fixture_file("statuses.xml")) + + aggregate_failures do + expect(statuses.size).to eq(20) + first = statuses.first + expect(first.id).to eq(882_281_424) + expect(first.created_at).to eq(Time.utc(2008, 8, 9, 5, 38, 12)) + expect(first.source).to eq("web") + expect(first.truncated).to be_falsey + expect(first.in_reply_to_status_id).to eq(1234) + expect(first.in_reply_to_user_id).to eq(12_345) + expect(first.favorited).to be_falsey + expect(first.user.id).to eq(4243) + expect(first.user.name).to eq("John Nunemaker") + expect(first.user.screen_name).to eq("jnunemaker") + expect(first.user.location).to eq("Mishawaka, IN, US") + expect(first.user.description) + .to eq "Loves his wife, ruby, notre dame football and iu basketball" + expect(first.user.profile_image_url) + .to eq("http://s3.amazonaws.com/twitter_production/profile_images/53781608/Photo_75_normal.jpg") + expect(first.user.url).to eq("http://addictedtonew.com") + expect(first.user.protected).to be_falsey + expect(first.user.followers_count).to eq(486) + end + end +end From 80655c03c1c939092bfd2d00c141fef7660f784c Mon Sep 17 00:00:00 2001 From: Matijs van Zuijlen Date: Sun, 12 May 2024 17:49:50 +0200 Subject: [PATCH 14/14] Extract feature specs for inline element attribute specification --- .../inline_element_attributes_spec.rb | 62 +++++++++++++++++++ spec/happymapper_spec.rb | 55 ---------------- 2 files changed, 62 insertions(+), 55 deletions(-) create mode 100644 spec/features/inline_element_attributes_spec.rb diff --git a/spec/features/inline_element_attributes_spec.rb b/spec/features/inline_element_attributes_spec.rb new file mode 100644 index 0000000..142bc8d --- /dev/null +++ b/spec/features/inline_element_attributes_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "specifying element attributes inline" do + let(:currentweather_klass) do + Class.new do + include HappyMapper + + tag "ob" + namespace "aws" + element :temperature, Integer, tag: "temp" + element :feels_like, Integer, tag: "feels-like" + element :current_condition, String, tag: "current-condition", + attributes: { icon: String } + end + end + + let(:atomfeed_klass) do + Class.new do + include HappyMapper + tag "feed" + + attribute :xmlns, String, single: true + element :id, String, single: true + element :title, String, single: true + element :updated, DateTime, single: true + element :link, String, single: false, attributes: { + rel: String, + type: String, + href: String + } + end + end + + it "adds the values of the attributes to the element" do + items = currentweather_klass.parse(fixture_file("current_weather.xml")) + first = items[0] + + aggregate_failures do + expect(first.temperature).to eq(51) + expect(first.feels_like).to eq(51) + expect(first.current_condition).to eq("Sunny") + expect(first.current_condition.icon).to eq("http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif") + end + end + + it "parses xml when the element with embedded attributes is not present in the xml" do + expect do + currentweather_klass.parse(fixture_file("current_weather_missing_elements.xml")) + end.not_to raise_error + end + + it "parses xml with attributes of elements that aren't :single => true" do + feed = atomfeed_klass.parse(fixture_file("atom.xml")) + + aggregate_failures do + expect(feed.link.first.href).to eq("http://www.example.com") + expect(feed.link.last.href).to eq("http://www.example.com/tv_shows.atom") + end + end +end diff --git a/spec/happymapper_spec.rb b/spec/happymapper_spec.rb index 8822ebf..36bc384 100644 --- a/spec/happymapper_spec.rb +++ b/spec/happymapper_spec.rb @@ -2,24 +2,6 @@ require "spec_helper" -module Atom - class Feed - include HappyMapper - tag "feed" - - attribute :xmlns, String, single: true - element :id, String, single: true - element :title, String, single: true - element :updated, DateTime, single: true - element :link, String, single: false, attributes: { - rel: String, - type: String, - href: String - } - # has_many :entries, Entry # nothing interesting in the entries - end -end - class Country include HappyMapper @@ -80,16 +62,6 @@ class Radar has_many :places, Place, tag: :place end -class CurrentWeather - include HappyMapper - - tag "ob" - namespace "aws" - element :temperature, Integer, tag: "temp" - element :feels_like, Integer, tag: "feels-like" - element :current_condition, String, tag: "current-condition", attributes: { icon: String } -end - module QuarterTest class Quarter include HappyMapper @@ -487,33 +459,6 @@ class Thing expect(address.class).to eq(Address) end - it "parses xml that has attributes of elements" do - items = CurrentWeather.parse(fixture_file("current_weather.xml")) - first = items[0] - - aggregate_failures do - expect(first.temperature).to eq(51) - expect(first.feels_like).to eq(51) - expect(first.current_condition).to eq("Sunny") - expect(first.current_condition.icon).to eq("http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif") - end - end - - it "parses xml with attributes of elements that aren't :single => true" do - feed = Atom::Feed.parse(fixture_file("atom.xml")) - - aggregate_failures do - expect(feed.link.first.href).to eq("http://www.example.com") - expect(feed.link.last.href).to eq("http://www.example.com/tv_shows.atom") - end - end - - it "parses xml with optional elements with embedded attributes" do - expect do - CurrentWeather.parse(fixture_file("current_weather_missing_elements.xml")) - end.not_to raise_error - end - it "returns nil rather than empty array for absent values when :single => true" do address = Address.parse('', single: true) expect(address).to be_nil