nytimes-articles 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,120 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class TestNytimes::TestArticles::TestBase < Test::Unit::TestCase
4
+ include Nytimes::Articles
5
+ context "Base.build_request_url" do
6
+ should "call v1 of the API" do
7
+ assert_match %r{v1}, api_url_for
8
+ end
9
+
10
+ should "be of the form /svc/search/VERSION/article" do
11
+ assert_match %r{/svc/search/[^/]+/article}, api_url_for
12
+ end
13
+ end
14
+
15
+ context "Base.invoke" do
16
+ setup do
17
+ init_test_key
18
+ end
19
+
20
+ context "when the API key has not been set" do
21
+ setup do
22
+ Base.api_key = nil
23
+ end
24
+
25
+ should "raise an AuthenticationError" do
26
+ assert_raise(AuthenticationError) do
27
+ Base.invoke
28
+ end
29
+ end
30
+ end
31
+
32
+ context "when the Articles API returns a 403 forbidden error (API key issue)" do
33
+ setup do
34
+ FakeWeb.register_uri(api_url_for, :status => ["403", "Forbidden"])
35
+ end
36
+
37
+ should "raise an AuthenticationError" do
38
+ assert_raise(AuthenticationError) do
39
+ Base.invoke
40
+ end
41
+ end
42
+ end
43
+
44
+ context "when the Articles API returns a 400 bad request error" do
45
+ setup do
46
+ FakeWeb.register_uri(api_url_for, :status => ["400", "Bad Request"])
47
+ end
48
+
49
+ should "raise an BadRequestError" do
50
+ assert_raise(BadRequestError) do
51
+ Base.invoke
52
+ end
53
+ end
54
+ end
55
+
56
+ context "When calling the Articles API returns a 500 server error" do
57
+ setup do
58
+ FakeWeb.register_uri(api_url_for, :status => ["500", "Server Error"])
59
+ end
60
+
61
+ should "raise an ServerError" do
62
+ assert_raise(ServerError) do
63
+ Base.invoke
64
+ end
65
+ end
66
+ end
67
+
68
+ context "when the Articles API returns any other HTTP error" do
69
+ setup do
70
+ FakeWeb.register_uri(api_url_for, :status => ["502", "Random Error"])
71
+ end
72
+
73
+ should "raise an ConnectionError" do
74
+ assert_raise(ConnectionError) do
75
+ Base.invoke
76
+ end
77
+ end
78
+ end
79
+
80
+ context "When the Articles API returns JSON that can't be parsed" do
81
+ setup do
82
+ FakeWeb.register_uri(api_url_for, :text => "e2131421212121221 => 3i109sdfvinp;2 112")
83
+ end
84
+
85
+ should "raise an BadResponseError" do
86
+ assert_raise(BadResponseError) do
87
+ Base.invoke
88
+ end
89
+ end
90
+ end
91
+
92
+ context "when passing Integer for offset" do
93
+ # note Article.search requries integer for offset
94
+ setup do
95
+ FakeWeb.register_uri(api_url_for('offset' => '1'), :status => ['200', 'OK'], :string => '{}')
96
+ end
97
+
98
+ should "not raise NoMethodError" do
99
+ assert_nothing_raised(NoMethodError) { Base.invoke('offset' => 1) }
100
+ end
101
+ end
102
+ end
103
+
104
+ context "Base#text_field" do
105
+ context "when decode_html_entities == true" do
106
+ should "decode HTML entities in text fields" do
107
+ assert_equal "foó", Base.text_field("fo&oacute;")
108
+ end
109
+ end
110
+
111
+ context "when decode_html_entities == false" do
112
+ setup { Base.decode_html_entities = false }
113
+ teardown { Base.decode_html_entities = true }
114
+
115
+ should "not decode HTML entities in text fields" do
116
+ assert_equal "fo&oacute;", Base.text_field("fo&oacute;")
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,109 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class TestNytimes::TestArticles::TestFacet < Test::Unit::TestCase
4
+ include Nytimes::Articles
5
+
6
+ context "read-only attributes" do
7
+ setup do
8
+ @facet = Facet.new("facet_type", "term", 103)
9
+ end
10
+
11
+ %w(term count facet_type).each do |field|
12
+ should "have a #{field} attribute" do
13
+ assert @facet.respond_to?(field)
14
+ end
15
+
16
+ should "be read-only for the #{field} attribute" do
17
+ assert_raise(NoMethodError) do
18
+ @facet.send "#{field}=", "new value"
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ context "Facet.init_from_api" do
25
+ setup do
26
+ @hash = {"date" => [{"count" => 36 , "term" => "19960630"} , {"count" => 36 , "term" => "19990523"}]}
27
+ @facets = Facet.init_from_api(@hash)
28
+ end
29
+
30
+ should "return nil if reply from API has no facets section" do
31
+ assert_nil Facet.init_from_api(nil)
32
+ end
33
+
34
+ should "return a hash indexed by the facet name from the API" do
35
+ assert_kind_of(Hash, @facets)
36
+ assert_same_elements @hash.keys, @facets.keys
37
+ end
38
+
39
+ should "return an array of Facet objects as the value for a key" do
40
+ first_key = @facets.keys.first
41
+ assert_kind_of Array, @facets[first_key]
42
+ assert @facets[first_key].all? {|f| f.is_a? Facet }
43
+ assert @facets[first_key].all? {|f| f.facet_type == first_key }
44
+ end
45
+ end
46
+
47
+ context "Facet.symbol_name" do
48
+ [:geo, :geography].each do |sym|
49
+ should "return Facet::GEO for #{sym}" do
50
+ assert_equal Facet::GEO, Facet.symbol_name(sym)
51
+ end
52
+ end
53
+
54
+ [:org, :orgs, :organization, :organizations].each do |sym|
55
+ should "return Facet::ORGANIZATION for #{sym}" do
56
+ assert_equal Facet::ORGANIZATION, Facet.symbol_name(sym)
57
+ end
58
+ end
59
+
60
+ [:people, :person, :persons].each do |sym|
61
+ should "return Facet::PERSON for #{sym}" do
62
+ assert_equal Facet::PERSON, Facet.symbol_name(sym)
63
+ end
64
+ end
65
+
66
+ [:nytd_geo, :nytd_geography].each do |sym|
67
+ should "return Facet::NYTD_GEO for #{sym}" do
68
+ assert_equal Facet::NYTD_GEO, Facet.symbol_name(sym)
69
+ end
70
+ end
71
+
72
+ [:nytd_org, :nytd_orgs, :nytd_organization, :nytd_organizations].each do |sym|
73
+ should "return Facet::NYTD_ORGANIZATION for #{sym}" do
74
+ assert_equal Facet::NYTD_ORGANIZATION, Facet.symbol_name(sym)
75
+ end
76
+ end
77
+
78
+ [:nytd_people, :nytd_person, :nytd_persons].each do |sym|
79
+ should "return Facet::NYTD_PERSON for #{sym}" do
80
+ assert_equal Facet::NYTD_PERSON, Facet.symbol_name(sym)
81
+ end
82
+ end
83
+
84
+ should "look for a matching constant and use that value" do
85
+ assert_equal Facet::SOURCE, Facet.symbol_name(:source)
86
+ end
87
+
88
+ should "singularize the symbol when looking for a constant if no match for the plural form" do
89
+ assert_equal Facet::PAGE, Facet.symbol_name(:pages)
90
+ end
91
+
92
+ should "return the string passed in if passed a string" do
93
+ assert_equal "FOOBAR", Facet.symbol_name('FOOBAR')
94
+ end
95
+
96
+ should "return the facet's facet_type if passed a Facet object" do
97
+ f = Facet.new(Facet::ORGANIZATION, 'THE NEW YORK TIMES', nil)
98
+ assert_equal Facet::ORGANIZATION, Facet.symbol_name(f)
99
+ end
100
+
101
+ should "raise an ArgumentError if not passed a symbol" do
102
+ assert_raise(ArgumentError) { Facet.symbol_name(23) }
103
+ end
104
+
105
+ should "raise an ArgumentError if unable to find a matching Facet constant" do
106
+ assert_raise(ArgumentError) { Facet.symbol_name(:clown) }
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,89 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class TestNytimes::TestArticles::TestQuery < Test::Unit::TestCase
4
+ include Nytimes::Articles
5
+
6
+ def setup
7
+ Base.stubs(:invoke)
8
+ @query = Query.new
9
+ end
10
+
11
+ def assert_has_accessor(obj, name, value='foo')
12
+ assert_nothing_raised { obj.send("#{name}=", value) }
13
+ assert_equal value, obj.send(name)
14
+ end
15
+
16
+ def expect_search_with(hsh)
17
+ Article.expects(:search).with(has_entry(hsh))
18
+ end
19
+
20
+ def self.should_proxy_search_param(name, value)
21
+ should "provide accessor for :#{name}" do
22
+ assert_has_accessor(@query, name, value)
23
+ end
24
+
25
+ should "pass :#{name} to Article#search" do
26
+ @query.send("#{name}=", value)
27
+ expect_search_with name => value
28
+ @query.perform
29
+ end
30
+ end
31
+
32
+ context "proxying named parameters to Article.search" do
33
+ (Article::TEXT_FIELDS + [:query]).each do |name|
34
+ should_proxy_search_param name.to_sym, 'some text field'
35
+ end
36
+
37
+ [:only_facets, :except_facets].each do |name|
38
+ should_proxy_search_param name, {'geo_facet' => 'NEW YORK CITY'}
39
+ end
40
+
41
+ [:begin_date, :end_date, :since, :before].each do |name|
42
+ should_proxy_search_param name, Time.now
43
+ end
44
+
45
+ [:fee, :has_thumbnail].each do |name|
46
+ should_proxy_search_param name, true
47
+ end
48
+
49
+ should_proxy_search_param :facets, ['geo_facet', 'org_facet', 'per_facet']
50
+ should_proxy_search_param :fields, ['title', 'abstract']
51
+ should_proxy_search_param :offset, 99
52
+
53
+ should "not pass nil parameters" do
54
+ @query.query = 'foo'
55
+ Article.expects(:search).with(:query => 'foo')
56
+ @query.perform
57
+ end
58
+ end
59
+
60
+ context "generating hash" do
61
+ # not sure how one would test this exhaustively, going for coverage + non-regression...
62
+
63
+ should "produce the same hash for identical queries" do
64
+ q0 = Query.new
65
+ q0.query = 'foo bar baz'
66
+ q0.only_facets = {'geo_facet' => 'NEW YORK CITY'}
67
+
68
+ q1 = Query.new
69
+ q1.query = 'foo bar baz'
70
+ q1.only_facets = {'geo_facet' => 'NEW YORK CITY'}
71
+
72
+ assert_equal q0.hash, q1.hash
73
+ end
74
+
75
+ should "not produce the same hash for non-identical queries" do
76
+ q0 = Query.new; q0.query = 'foo'
77
+ q1 = Query.new; q1.query = 'bar'
78
+ assert_not_equal q0.hash, q1.hash
79
+
80
+ q0 = Query.new; q0.facets = {'geo_facet' => 'NEW YORK CITY'}
81
+ q1 = Query.new; q1.facets = {'geo_facet' => 'CALIFORNIA'}
82
+ assert_not_equal q0.hash, q1.hash
83
+
84
+ q0 = Query.new; q0.since = Date.parse('1/1/2009')
85
+ q1 = Query.new; q1.since = Date.parse('1/2/2009')
86
+ assert_not_equal q0.hash, q1.hash
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,62 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ RESULT_SET_HASH = {"results"=>[{"lead_paragraph"=>"", "classifiers_facet"=>["Top/News/Business", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/News/Business/Markets"], "title"=>"Wall Street on Even Keel After Sell-Off", "nytd_title"=>"Wall Street on Even Keel After Sell-Off", "byline"=>"By JACK HEALY and MATTHEW SALTMARSH", "body"=>"A day after fleeing stocks in a fierce sell-off, investors on Wall Street stayed mostly at bay on Wednesday. Shares on Wall Street were hovering slightly higher at midday Wednesday as investors tried to get a better grip on Washington&#8217;s newly announced plans to stabilize the shaky banking system with up to $2.5 trillion in public and private", "material_type_facet"=>["News"], "url"=>"http://www.nytimes.com/2009/02/12/business/12markets.html", "publication_month"=>"02", "date"=>"20090212", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Business", "publication_day"=>"12", "des_facet"=>["STOCKS AND BONDS"], "day_of_week_facet"=>"Thursday"}, {"page_facet"=>"8", "lead_paragraph"=>"", "classifiers_facet"=>["Top/News/Business", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/News/Business/Markets"], "title"=>"Wall St. Treads Water as It Waits on Washington", "nytd_title"=>"Wall St. Treads Water as It Waits on Washington", "byline"=>"By JACK HEALY", "body"=>"Wall Street held its breath on Monday as it awaited details on a banking bailout from Washington. Investors had expected to start the week with an announcement from the Treasury Department outlining its latest plans to stabilize the financial system. But the Obama administration delayed releasing the details until at least Tuesday to keep the focus", "material_type_facet"=>["News"], "url"=>"http://www.nytimes.com/2009/02/10/business/10markets.html", "publication_month"=>"02", "date"=>"20090210", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Business", "publication_day"=>"10", "des_facet"=>["STOCKS AND BONDS"], "day_of_week_facet"=>"Tuesday"}, {"lead_paragraph"=>"", "geo_facet"=>["WALL STREET (NYC)"], "classifiers_facet"=>["Top/Opinion/Opinion/Letters", "Top/Opinion", "Top/Opinion/Opinion", "Top/Features/Travel/Guides/Destinations/North America", "Top/Features/Travel/Guides/Destinations/North America/United States/New York", "Top/Features/Travel/Guides/Destinations/North America/United States"], "title"=>"LETTER; Wall Street Blues", "nytd_title"=>"Wall Street Blues", "body"=>"To the Editor: Re &#8220;Wall St., a Financial Epithet, Stirs Outrage and Punch Lines&#8221; (front page, Feb. 3): I have some news for the Wall Street worker who ponders working for a nonprofit from 8 to 4 instead of on Wall Street, where long hours are the norm. I was a college administrator and English teacher for 15 years. Every night and all", "material_type_facet"=>["Letter"], "url"=>"http://www.nytimes.com/2009/02/09/opinion/lweb09econ.html", "publication_month"=>"02", "date"=>"20090209", "column_facet"=>"Letter", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Opinion", "publication_day"=>"09", "des_facet"=>["NONPROFIT ORGANIZATIONS", "EXECUTIVE COMPENSATION"], "day_of_week_facet"=>"Monday"}, {"page_facet"=>"29", "lead_paragraph"=>"", "geo_facet"=>["WALL STREET (NYC)"], "small_image_width"=>"75", "classifiers_facet"=>["Top/News/New York and Region", "Top/Classifieds/Job Market/Job Categories/Education", "Top/Features/Travel/Guides/Destinations/North America", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/Features/Travel/Guides/Destinations/North America/United States/New York", "Top/Features/Travel/Guides/Destinations/North America/United States", "Top/News/Education"], "title"=>"OUR TOWNS; As Pipeline to Wall Street Narrows, Princeton Students Adjust Sights", "nytd_title"=>"As Pipeline to Wall Street Narrows, Princeton Students Adjust Sights", "byline"=>"By PETER APPLEBOME", "body"=>"Princeton, N.J. There must be a screenplay in the fabulous Schoppe twins, Christine and Jennifer, Princeton University juniors from Houston. They had the same G.P.A. and SATs in high school, where they became Gold Award Girl Scouts , sort of the female version of Eagle Scouts. They live together and take all the same courses, wear identical", "material_type_facet"=>["News"], "url"=>"http://www.nytimes.com/2009/02/08/nyregion/08towns.html", "publication_month"=>"02", "small_image_height"=>"75", "date"=>"20090208", "column_facet"=>"Our Towns", "small_image"=>"Y", "publication_year"=>"2009", "source_facet"=>"The New York Times", "org_facet"=>["PRINCETON UNIVERSITY"], "desk_facet"=>"New York Region", "publication_day"=>"08", "small_image_url"=>"http://graphics8.nytimes.com/images/2009/02/08/nyregion/08towns.751.jpg", "des_facet"=>["EDUCATION AND SCHOOLS", "BANKS AND BANKING"], "day_of_week_facet"=>"Sunday"}, {"page_facet"=>"1", "lead_paragraph"=>"", "geo_facet"=>["WALL STREET (NYC)"], "classifiers_facet"=>["Top/News/Business", "Top/News/Business/Markets", "Top/Features/Travel/Guides/Destinations/North America", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/Features/Travel/Guides/Destinations/North America/United States/New York", "Top/Features/Travel/Guides/Destinations/North America/United States"], "title"=>"Wall St. Pay Is Cyclical. Guess Where We Are Now.", "nytd_title"=>"Wall St. Pay Is Cyclical. Guess Where We Are Now.", "byline"=>"By STEVE LOHR", "body"=>"To most people, a salary cap of $500,000 would be anything but punishment. But in Wall Street&#8217;s executive suites, it amounts to a humbling pay cut &#151; and, just maybe, the beginning of a cultural shift. True, the rich always seem to find new ways to get richer. But in the sweep of history, high pay on Wall Street comes and goes through", "material_type_facet"=>["News"], "url"=>"http://www.nytimes.com/2009/02/05/business/05bonus.html", "publication_month"=>"02", "date"=>"20090205", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Business", "publication_day"=>"05", "des_facet"=>["BONUSES", "BANKS AND BANKING", "SUBPRIME MORTGAGE CRISIS", "EXECUTIVE COMPENSATION"], "day_of_week_facet"=>"Thursday"}, {"page_facet"=>"26", "lead_paragraph"=>"", "geo_facet"=>["WALL STREET (NYC)"], "small_image_width"=>"75", "classifiers_facet"=>["Top/Opinion/Opinion/Letters", "Top/Opinion", "Top/Opinion/Opinion", "Top/Features/Travel/Guides/Destinations/North America", "Top/Features/Travel/Guides/Destinations/North America/United States/New York", "Top/Features/Travel/Guides/Destinations/North America/United States"], "title"=>"LETTERS; Wall St. and the $500,000 Question", "nytd_title"=>"Wall St. and the $500,000 Question", "body"=>"To the Editor: Re &#8220;Amid Fury, U.S. Is Set to Curb Executives&#8217; Pay After Bailouts&#8221; (front page, Feb. 4): It may be that the $500,000 cap is a bit extreme, but America should celebrate that there is at last some mechanism to rein in top corporate compensation. Public outrage and shareholder revolts have not managed to do so, since", "material_type_facet"=>["Letter"], "url"=>"http://www.nytimes.com/2009/02/05/opinion/l05econ.html", "publication_month"=>"02", "small_image_height"=>"75", "date"=>"20090205", "column_facet"=>"Letters", "small_image"=>"Y", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Opinion", "publication_day"=>"05", "small_image_url"=>"http://graphics8.nytimes.com/images/2009/02/05/opinion/05letter.75.gif", "des_facet"=>["EMERGENCY ECONOMIC STABILIZATION ACT (2008)", "EXECUTIVES AND MANAGEMENT", "WAGES AND SALARIES", "SUBPRIME MORTGAGE CRISIS"], "day_of_week_facet"=>"Thursday"}, {"page_facet"=>"1", "lead_paragraph"=>"", "geo_facet"=>["UNITED STATES"], "classifiers_facet"=>["Top/News/World/Countries and Territories/United States", "Top/News/Business/Personal Finance", "Top/News/Front Page", "Top/Features/Travel/Guides/Destinations/North America", "Top/News/Business", "Top/News/Business/Markets", "Top/Classifieds/Job Market/Job Categories/Executive", "Top/News", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/Features/Travel/Guides/Destinations/North America/United States"], "title"=>"Wall St., a Financial Epithet, Stirs Outrage and Punch Lines", "nytd_title"=>"Wall St., a Financial Epithet, Stirs Outrage", "byline"=>"By DAVID SEGAL", "body"=>"Monday was the last day of Iris Chau's 11-year career at JPMorgan Chase and she says there's a lot she'll miss about the job, including her colleagues, her paycheck and her role managing a technical support team. But one thing she won't miss about JPMorgan: telling people that she works there. ''For a long time, it was kind of glamorous and I had", "material_type_facet"=>["News"], "word_count"=>"1472", "url"=>"http://www.nytimes.com/2009/02/03/business/03bankers.html", "publication_month"=>"02", "abstract"=>"Financial industry has become national pariah, as country fumes over billions spent on bailouts and bonuses; many workers feel they are unfairly singled out for blame for crisis that was created by numerous players; there has been huge loss of status and cultural cachet as industry has become target of rage, raw material for talk-show tirades and comedians; fall in stature has taken toll on those industry veterans who are even willing to discuss it and, when they do, they attribute much of financial crisis to others; photos (M)", "small_image_height"=>"75", "date"=>"20090203", "fee"=>"N", "small_image"=>"Y", "publication_year"=>"2009", "source_facet"=>"The New York Times", "nytd_lead_paragraph"=>"As investment bankers adjust to a new role as targets of scorn, they aren\342\200\231t expecting pity, or a sympathetic ear.", "desk_facet"=>"Business/Financial Desk", "publication_day"=>"03", "small_image_url"=>"http://graphics8.nytimes.com/images/2009/02/02/business/03bankers_75.jpg", "nytd_des_facet"=>["Executives and Management", "Investment Banking", "Personal Finances", "Layoffs and Job Reductions", "High Net Worth Individuals", "Bonuses", "Executive Compensation", "Banks and Banking"], "des_facet"=>["EXECUTIVES AND MANAGEMENT", "INVESTMENT BANKING", "PERSONAL FINANCES", "BANKS AND BANKING", "LAYOFFS AND JOB REDUCTIONS", "LABOR", "BONUSES", "STOCKS AND BONDS", "BUDGETS AND BUDGETING", "EXECUTIVE COMPENSATION", "HIGH NET WORTH INDIVIDUALS", "FINANCES"], "day_of_week_facet"=>"Tuesday"}, {"page_facet"=>"20", "lead_paragraph"=>"", "classifiers_facet"=>["Top/Opinion/Opinion/Letters", "Top/Opinion", "Top/Opinion/Opinion"], "title"=>"LETTERS; Wall St. Bonuses: Enough Is Enough", "body"=>"To the Editor: Re ''Money for Nothing,'' by Dave Krasne (Op-Ed, Jan. 27): In the discussion of regulating executive compensation, the question has been asked, ''Without the most significant of financial rewards, how will we attract the very best to occupy these lofty positions?'' The implicit assumption of this statement is that society's very best", "material_type_facet"=>["Letter"], "word_count"=>"760", "url"=>"http://query.nytimes.com/gst/fullpage.html?res=9401E3D91431F931A35751C0A96F9C8B63", "publication_month"=>"02", "date"=>"20090202", "column_facet"=>"LETTERS", "publication_year"=>"2009", "source_facet"=>"The New York Times", "desk_facet"=>"Editorial Desk", "publication_day"=>"02", "day_of_week_facet"=>"Monday"}, {"page_facet"=>"11", "lead_paragraph"=>"", "classifiers_facet"=>["Top/Opinion/Opinion/Editorials", "Top/Opinion", "Top/News/Washington/Campaign 2008/Candidates", "Top/News/Washington/Campaign 2008", "Top/Opinion/Opinion"], "title"=>"OP-ED COLUMNIST; Disgorge, Wall Street Fat Cats", "nytd_title"=>"Disgorge, Wall Street Fat Cats", "byline"=>"By MAUREEN DOWD", "body"=>"The president's disgust at Wall Street looters was good. But we need more. We need disgorgement. Disgorgement is when courts force wrongdoers to repay ill-gotten gains. And I'm ill at the gains gotten by scummy executives acting all Gordon Gekko while they're getting bailed out by us. With the equally laconic Tim Geithner beside him, Mr. Obama", "material_type_facet"=>["Editorial"], "word_count"=>"807", "url"=>"http://www.nytimes.com/2009/02/01/opinion/01dowd.html", "publication_month"=>"02", "date"=>"20090201", "column_facet"=>"OP-ED COLUMNIST", "fee"=>"N", "publication_year"=>"2009", "source_facet"=>"The New York Times", "nytd_lead_paragraph"=>"The president\342\200\231s disgust at Wall Street looters was good. But we need more. We need disgorgement. Disgorgement is when courts force wrongdoers to repay ill-gotten gains.", "desk_facet"=>"Editorial Desk", "publication_day"=>"01", "per_facet"=>["OBAMA, BARACK"], "nytd_des_facet"=>["United States Economy", "Executive Compensation", "Subprime Mortgage Crisis"], "des_facet"=>["UNITED STATES ECONOMY", "EXECUTIVE COMPENSATION", "SUBPRIME MORTGAGE CRISIS"], "day_of_week_facet"=>"Sunday"}, {"page_facet"=>"1", "lead_paragraph"=>"", "geo_facet"=>["WALL STREET (NYC)"], "classifiers_facet"=>["Top/News/Front Page", "Top/Features/Travel/Guides/Destinations/North America", "Top/News/Business", "Top/News/Business/Markets", "Top/News/Washington/Campaign 2008", "Top/News", "Top/Classifieds/Job Market/Job Categories/Banking, Finance and Insurance", "Top/News/Washington/Campaign 2008/Candidates", "Top/Features/Travel/Guides/Destinations/North America/United States/New York", "Top/Features/Travel/Guides/Destinations/North America/United States"], "title"=>"What Red Ink? Wall St. Paid Hefty Bonuses", "nytd_title"=>"What Red Ink? Wall Street Paid Hefty Bonuses", "byline"=>"By BEN WHITE; Paul J. Sullivan contributed reporting.", "body"=>"By almost any measure, 2008 was a complete disaster for Wall Street -- except, that is, when the bonuses arrived. Despite crippling losses, multibillion-dollar bailouts and the passing of some of the most prominent names in the business, employees at financial companies in New York, the now-diminished world capital of capital, collected an", "material_type_facet"=>["News"], "word_count"=>"992", "url"=>"http://www.nytimes.com/2009/01/29/business/29bonus.html", "publication_month"=>"01", "abstract"=>"Wall Street paid out estimated $18.4 billion in bonuses last year, despite crippling losses, multi-billion-dollar bailouts and veritable banishment of well-known heads of financial firms; New York State Comptroller Thomas DiNapoli reports that it is sixth largest amount on record, matching 2004 when Dow Jones industrial average was above 10,000; estimate is based on personal income-tax collections and excludes stock option awards that could push figure even higher; DiNapoli says it is unclear whether bailouts helped make bonuses possible and urges Obama administration to examine issue; graphs (M)", "date"=>"20090129", "fee"=>"N", "publication_year"=>"2009", "source_facet"=>"The New York Times", "nytd_lead_paragraph"=>"Despite crippling losses in 2008, financial employees in New York collected an estimated $18.4 billion in bonuses for the year.", "desk_facet"=>"Business/Financial Desk", "publication_day"=>"29", "nytd_geo_facet"=>["Wall Street (NYC)"], "per_facet"=>["OBAMA, BARACK", "DINAPOLI, THOMAS P"], "nytd_des_facet"=>["Executive Compensation", "High Net Worth Individuals", "Bonuses", "Subprime Mortgage Crisis", "Brokers and Brokerage Firms"], "des_facet"=>["STOCK OPTIONS AND PURCHASE PLANS", "SUBPRIME MORTGAGE CRISIS", "HIGH NET WORTH INDIVIDUALS", "BONUSES", "STOCKS AND BONDS", "WAGES AND SALARIES", "EXECUTIVE COMPENSATION", "ETHICS", "BROKERS AND BROKERAGE FIRMS"], "day_of_week_facet"=>"Thursday"}], "total"=>3292, "tokens"=>["title:wall", "street"], "offset"=>"0"}
4
+
5
+ class TestNytimes::TestArticles::TestResultSet < Test::Unit::TestCase
6
+ include Nytimes::Articles
7
+
8
+ context "ResultSet.init_from_api" do
9
+ setup do
10
+ @result_set = ResultSet.init_from_api(RESULT_SET_HASH)
11
+ end
12
+
13
+ should "read the offset from the results hash @offset field" do
14
+ assert_equal RESULT_SET_HASH["offset"].to_i, @result_set.offset
15
+ end
16
+
17
+ should "read the total_results from the results_hash total field" do
18
+ assert_equal RESULT_SET_HASH["total"].to_i, @result_set.total_results
19
+ end
20
+
21
+ should "return results as an array of Article objects" do
22
+ assert_kind_of(Array, @result_set.results)
23
+ assert @result_set.results.all? {|r| r.is_a? Article }
24
+ end
25
+ end
26
+
27
+ context "page_number" do
28
+ setup do
29
+ @result_set = ResultSet.init_from_api(RESULT_SET_HASH)
30
+ end
31
+
32
+ should "be offset + 1" do
33
+ assert_equal 1, @result_set.page_number
34
+ end
35
+
36
+ should "be 0 if total_results is 0" do
37
+ result_set = ResultSet.new(:total_results => 0)
38
+ assert_equal 0, result_set.page_number
39
+ end
40
+ end
41
+
42
+ context "total_pages" do
43
+ should "be 1 if less than BATCH_SIZE results" do
44
+ result_set = ResultSet.new(:total_results => 7)
45
+ assert_equal 1, result_set.total_pages
46
+ end
47
+
48
+ should "be 0 if 0 results returned" do
49
+ result_set = ResultSet.new(:total_results => 0)
50
+ assert_equal 0, result_set.total_pages
51
+ end
52
+
53
+ should "be ceil(total_results / batch_size)" do
54
+ result_set = ResultSet.new(:total_results => 23)
55
+ assert_equal 3, result_set.total_pages
56
+
57
+ result_set = ResultSet.new(:total_results => 20)
58
+ assert_equal 2, result_set.total_pages
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/../../test_helper.rb'
2
+
3
+ class TestNytimes::TestArticles::TestThumbnail < Test::Unit::TestCase
4
+ include Nytimes::Articles
5
+
6
+ context "read-only attributes" do
7
+ setup do
8
+ @thumbnail = Thumbnail.new("http://www.foo.com", 400, 600)
9
+ end
10
+
11
+ %w(url width height).each do |field|
12
+ should "have a #{field} attribute" do
13
+ assert @thumbnail.respond_to?(field)
14
+ end
15
+
16
+ should "be read-only for the #{field} attribute" do
17
+ assert_raise(NoMethodError) do
18
+ @thumbnail.send "#{field}=", "new value"
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ context "Facet.init_from_api" do
25
+ setup do
26
+ @hash = {"small_image_url" => "http://foo.com/", 'small_image_width' => '400', 'small_image_height' => '600'}
27
+ end
28
+
29
+ should "return nil if reply from API has no URL" do
30
+ assert_nil Thumbnail.init_from_api(nil)
31
+ assert_nil Thumbnail.init_from_api({})
32
+ end
33
+
34
+ %w(width height).each do |dimension|
35
+ should "set to nil if it is nil in the array" do
36
+ @hash["small_image_#{dimension}"] = nil
37
+ thumbnail = Thumbnail.init_from_api(@hash)
38
+ assert_nil thumbnail.send(dimension)
39
+ end
40
+
41
+ should "cast to an Integer value if passed a string" do
42
+ thumbnail = Thumbnail.init_from_api(@hash)
43
+ assert_equal @hash["small_image_#{dimension}"].to_i, thumbnail.send(dimension)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,31 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ gem 'chrisk-fakeweb'
6
+ require 'fake_web'
7
+
8
+ FakeWeb.allow_net_connect = false
9
+
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
11
+ require 'nytimes_articles'
12
+
13
+ API_KEY = '13e234323232222'
14
+
15
+ def init_test_key
16
+ Nytimes::Articles::Base.api_key = API_KEY
17
+ end
18
+
19
+ def api_url_for(params = {})
20
+ full_params = params.merge 'api-key' => API_KEY
21
+ Nytimes::Articles::Base.build_request_url(full_params).to_s
22
+ end
23
+
24
+ module TestNytimes
25
+ module TestArticles
26
+ end
27
+ end
28
+
29
+ class Test::Unit::TestCase
30
+ end
31
+