mingle_events 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -0
- data/LICENSE.txt +202 -0
- data/README.textile +117 -0
- data/lib/mingle_events.rb +26 -0
- data/lib/mingle_events/feed.rb +5 -0
- data/lib/mingle_events/feed/author.rb +28 -0
- data/lib/mingle_events/feed/category.rb +75 -0
- data/lib/mingle_events/feed/element_support.rb +19 -0
- data/lib/mingle_events/feed/entry.rb +96 -0
- data/lib/mingle_events/feed/page.rb +61 -0
- data/lib/mingle_events/http_error.rb +26 -0
- data/lib/mingle_events/mingle_basic_auth_access.rb +71 -0
- data/lib/mingle_events/mingle_oauth_access.rb +40 -0
- data/lib/mingle_events/poller.rb +32 -0
- data/lib/mingle_events/processors.rb +10 -0
- data/lib/mingle_events/processors/author_filter.rb +62 -0
- data/lib/mingle_events/processors/card_data.rb +102 -0
- data/lib/mingle_events/processors/card_type_filter.rb +28 -0
- data/lib/mingle_events/processors/category_filter.rb +19 -0
- data/lib/mingle_events/processors/custom_property_filter.rb +30 -0
- data/lib/mingle_events/processors/http_post_publisher.rb +20 -0
- data/lib/mingle_events/processors/pipeline.rb +20 -0
- data/lib/mingle_events/processors/puts_publisher.rb +17 -0
- data/lib/mingle_events/project_custom_properties.rb +33 -0
- data/lib/mingle_events/project_event_fetcher.rb +96 -0
- data/test/mingle_events/feed/author_test.rb +39 -0
- data/test/mingle_events/feed/category_test.rb +20 -0
- data/test/mingle_events/feed/entry_test.rb +140 -0
- data/test/mingle_events/feed/page_test.rb +82 -0
- data/test/mingle_events/poller_test.rb +47 -0
- data/test/mingle_events/processors/author_filter_test.rb +80 -0
- data/test/mingle_events/processors/card_data_test.rb +210 -0
- data/test/mingle_events/processors/card_type_filter_test.rb +51 -0
- data/test/mingle_events/processors/category_filter_test.rb +27 -0
- data/test/mingle_events/processors/custom_property_filter_test.rb +51 -0
- data/test/mingle_events/processors/pipeline_test.rb +32 -0
- data/test/mingle_events/project_custom_properties_test.rb +39 -0
- data/test/mingle_events/project_event_fetcher_test.rb +122 -0
- data/test/test_helper.rb +163 -0
- data/test/web_hook_server/web_hook_server.rb +6 -0
- metadata +140 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
|
2
|
+
|
3
|
+
module MingleEvents
|
4
|
+
module Processors
|
5
|
+
class CategoryFilterTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_removes_events_without_matching_categories
|
8
|
+
event_1 = stub_event(1, [Feed::Category::CARD, Feed::Category::COMMENT_ADDITION])
|
9
|
+
event_2 = stub_event(2, [Feed::Category::CARD, Feed::Category::PROPERTY_CHANGE])
|
10
|
+
event_3 = stub_event(3, [Feed::Category::REVISION_COMMIT])
|
11
|
+
event_4 = stub_event(4, [Feed::Category::CARD, Feed::Category::PROPERTY_CHANGE])
|
12
|
+
event_5 = stub_event(5, [])
|
13
|
+
events = [event_1, event_2, event_3, event_4, event_5]
|
14
|
+
|
15
|
+
filter = CategoryFilter.new([Feed::Category::CARD, Feed::Category::PROPERTY_CHANGE])
|
16
|
+
assert_equal([event_2, event_4], filter.process_events(events))
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def stub_event(id, categories)
|
22
|
+
OpenStruct.new(:entry_id => id, :categories => categories)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
|
2
|
+
|
3
|
+
module MingleEvents
|
4
|
+
module Processors
|
5
|
+
|
6
|
+
class CustomPropertyFilterTest < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_filters_events_on_custom_property
|
9
|
+
event_1 = stub_event(true)
|
10
|
+
event_2 = stub_event(false)
|
11
|
+
event_3 = stub_event(true)
|
12
|
+
event_4 = stub_event(true)
|
13
|
+
event_5 = stub_event(true)
|
14
|
+
|
15
|
+
card_data = {
|
16
|
+
event_1 => {:custom_properties => {'Priority' => 'High'}},
|
17
|
+
event_3 => {:custom_properties => {'Priority' => 'Low'}},
|
18
|
+
event_4 => {:custom_properties => {'Priority' => 'High'}},
|
19
|
+
event_5 => {:custom_properties => {'Severity' => 'High'}}
|
20
|
+
}
|
21
|
+
def card_data.for_card_event(card_event)
|
22
|
+
self[card_event]
|
23
|
+
end
|
24
|
+
|
25
|
+
filter = CustomPropertyFilter.new('Priority', 'High', card_data)
|
26
|
+
filtered_events = filter.process_events([event_1, event_2, event_3, event_4, event_5])
|
27
|
+
assert_equal([event_1, event_4], filtered_events)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_drops_events_for_deleted_cards
|
31
|
+
event_1 = stub_event(true)
|
32
|
+
|
33
|
+
card_data = {}
|
34
|
+
def card_data.for_card_event(card_event)
|
35
|
+
self[card_event]
|
36
|
+
end
|
37
|
+
|
38
|
+
filter = CustomPropertyFilter.new('Priority', 'High', card_data)
|
39
|
+
filtered_events = filter.process_events([event_1])
|
40
|
+
assert_equal([], filtered_events)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def stub_event(is_card)
|
46
|
+
OpenStruct.new(:card? => is_card)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'test_helper'))
|
2
|
+
|
3
|
+
module MingleEvents
|
4
|
+
module Processors
|
5
|
+
class PipelineTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_chains_all_processors
|
8
|
+
events = [stub_event(100), stub_event(101), stub_event(102)]
|
9
|
+
pipeline = Pipeline.new([DeleteLastProcessor.new, ReversingProcessor.new])
|
10
|
+
processed_events = pipeline.process_events(events)
|
11
|
+
assert_equal([101, 100], processed_events.map(&:entry_id))
|
12
|
+
end
|
13
|
+
|
14
|
+
def stub_event(id)
|
15
|
+
OpenStruct.new(:entry_id => id)
|
16
|
+
end
|
17
|
+
|
18
|
+
class ReversingProcessor
|
19
|
+
def process_events(events)
|
20
|
+
events.reverse
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class DeleteLastProcessor
|
25
|
+
def process_events(events)
|
26
|
+
events[0..-2]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
module MingleEvents
|
4
|
+
|
5
|
+
class ProjectCustomPropertiesTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_can_lookup_property_name_by_column_name
|
8
|
+
property_definitions_xml = %{
|
9
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
10
|
+
<property_definitions type="array">
|
11
|
+
<property_definition>
|
12
|
+
<name>Account</name>
|
13
|
+
<data_type>string</data_type>
|
14
|
+
<is_numeric type="boolean">false</is_numeric>
|
15
|
+
<column_name>cp_account</column_name>
|
16
|
+
</property_definition>
|
17
|
+
<property_definition>
|
18
|
+
<name>Account ID</name>
|
19
|
+
<data_type>string</data_type>
|
20
|
+
<is_numeric type="boolean">false</is_numeric>
|
21
|
+
<column_name>cp_account_id</column_name>
|
22
|
+
</property_definition>
|
23
|
+
</property_definitions>
|
24
|
+
}
|
25
|
+
|
26
|
+
dummy_mingle_access = StubMingleAccess.new
|
27
|
+
dummy_mingle_access.register_page_content(
|
28
|
+
URI.escape('/api/v2/projects/atlas/property_definitions.xml'),
|
29
|
+
property_definitions_xml
|
30
|
+
)
|
31
|
+
|
32
|
+
project_custom_properties = ProjectCustomProperties.new(dummy_mingle_access, "atlas")
|
33
|
+
assert_equal("Account ID", project_custom_properties.property_name_for_column("cp_account_id"))
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'test_helper'))
|
2
|
+
|
3
|
+
module MingleEvents
|
4
|
+
class ProjectEventFetcherTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_can_fetch_all_entries_and_write_to_disk_when_no_initial_state
|
7
|
+
state_dir = temp_dir
|
8
|
+
fetcher = ProjectEventFetcher.new('atlas', stub_mingle_access, state_dir)
|
9
|
+
|
10
|
+
file_for_first_new_entry = fetcher.fetch_latest
|
11
|
+
|
12
|
+
expected_entry_ids = [
|
13
|
+
'https://mingle.example.com/projects/atlas/events/index/23',
|
14
|
+
'https://mingle.example.com/projects/atlas/events/index/97',
|
15
|
+
'https://mingle.example.com/projects/atlas/events/index/98',
|
16
|
+
'https://mingle.example.com/projects/atlas/events/index/99',
|
17
|
+
'https://mingle.example.com/projects/atlas/events/index/100',
|
18
|
+
'https://mingle.example.com/projects/atlas/events/index/101',
|
19
|
+
'https://mingle.example.com/projects/atlas/events/index/103'
|
20
|
+
]
|
21
|
+
|
22
|
+
assert_expected_entry_chain_written_to_disk(expected_entry_ids, file_for_first_new_entry, fetcher)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_can_fetch_all_entries_and_write_to_disk_when_existing_state
|
26
|
+
state_dir = temp_dir
|
27
|
+
fetcher = ProjectEventFetcher.new('atlas', stub_mingle_access, state_dir)
|
28
|
+
setup_current_state(%{
|
29
|
+
<entry>
|
30
|
+
<id>https://mingle.example.com/projects/atlas/events/index/97</id>
|
31
|
+
<title>entry 97</title>
|
32
|
+
<updated>2011-02-03T01:10:52Z</updated>
|
33
|
+
<author><name>Harry</name></author>
|
34
|
+
</entry>}, fetcher)
|
35
|
+
|
36
|
+
file_for_first_new_entry = fetcher.fetch_latest
|
37
|
+
|
38
|
+
expected_entry_ids = [
|
39
|
+
'https://mingle.example.com/projects/atlas/events/index/98',
|
40
|
+
'https://mingle.example.com/projects/atlas/events/index/99',
|
41
|
+
'https://mingle.example.com/projects/atlas/events/index/100',
|
42
|
+
'https://mingle.example.com/projects/atlas/events/index/101',
|
43
|
+
'https://mingle.example.com/projects/atlas/events/index/103'
|
44
|
+
]
|
45
|
+
|
46
|
+
assert_expected_entry_chain_written_to_disk(expected_entry_ids, file_for_first_new_entry, fetcher)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_no_new_entries_with_current_state
|
50
|
+
state_dir = temp_dir
|
51
|
+
fetcher = ProjectEventFetcher.new('atlas', stub_mingle_access, state_dir)
|
52
|
+
setup_current_state(%{
|
53
|
+
<entry>
|
54
|
+
<id>https://mingle.example.com/projects/atlas/events/index/103</id>
|
55
|
+
<title>entry 103</title>
|
56
|
+
<updated>2011-02-03T01:10:52Z</updated>
|
57
|
+
<author><name>Harry</name></author>
|
58
|
+
</entry>}, fetcher)
|
59
|
+
|
60
|
+
assert_nil fetcher.fetch_latest
|
61
|
+
|
62
|
+
current_state = YAML.load(File.new(File.join(state_dir, 'current_state.yml')))
|
63
|
+
assert_equal(@last_fetched_entry_info_file, current_state[:last_fetched_entry_info_file])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_no_new_entries_with_no_current_state
|
67
|
+
state_dir = temp_dir
|
68
|
+
mingle_access = StubMingleAccess.new
|
69
|
+
mingle_access.register_page_content('/api/v2/projects/atlas/feeds/events.xml',%{
|
70
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
71
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:mingle="http://www.thoughtworks-studios.com/ns/mingle">
|
72
|
+
<title>Mingle Events: Blank Project</title>
|
73
|
+
<id>https://mingle.example.com/api/v2/projects/blank_project/feeds/events.xml</id>
|
74
|
+
<link href="https://mingle.example.com/api/v2/projects/blank_project/feeds/events.xml" rel="current"/>
|
75
|
+
<link href="https://mingle.example.com/api/v2/projects/blank_project/feeds/events.xml" rel="self"/>
|
76
|
+
<updated>2011-08-04T19:42:04Z</updated>
|
77
|
+
</feed>})
|
78
|
+
fetcher = ProjectEventFetcher.new('atlas', mingle_access, state_dir)
|
79
|
+
|
80
|
+
assert_nil fetcher.fetch_latest
|
81
|
+
assert !File.exist?(File.join(state_dir, 'current_state.yml'))
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def setup_current_state(last_fetched_entry_xml, fetcher)
|
87
|
+
last_fetched_entry_info = {
|
88
|
+
:entry_xml => last_fetched_entry_xml,
|
89
|
+
:next_entry_file_path => nil
|
90
|
+
}
|
91
|
+
@last_fetched_entry_info_file = fetcher.file_for_entry(Feed::Entry.new(Nokogiri::XML(last_fetched_entry_xml).at('/entry')))
|
92
|
+
FileUtils.mkdir_p(File.dirname(@last_fetched_entry_info_file))
|
93
|
+
File.open(@last_fetched_entry_info_file, 'w') do |out|
|
94
|
+
YAML.dump(last_fetched_entry_info, out)
|
95
|
+
end
|
96
|
+
current_state = {:last_fetched_entry_info_file => @last_fetched_entry_info_file}
|
97
|
+
File.open(fetcher.current_state_file, 'w') do |out|
|
98
|
+
YAML.dump(current_state, out)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
def assert_expected_entry_chain_written_to_disk(expected_entry_ids, file_for_first_new_entry, fetcher)
|
104
|
+
|
105
|
+
file_for_new_entry = file_for_first_new_entry
|
106
|
+
file_for_last_inspected_entry = nil
|
107
|
+
expected_entry_ids.each_with_index do |expected_entry_id, index|
|
108
|
+
file_for_last_inspected_entry = file_for_new_entry
|
109
|
+
new_entry_info = YAML.load(File.new(file_for_new_entry))
|
110
|
+
new_entry = Feed::Entry.new(Nokogiri::XML(new_entry_info[:entry_xml]).at('/entry'))
|
111
|
+
assert_equal(expected_entry_id, new_entry.entry_id)
|
112
|
+
file_for_new_entry = new_entry_info[:next_entry_file_path]
|
113
|
+
end
|
114
|
+
|
115
|
+
current_state = YAML.load(File.new(fetcher.current_state_file))
|
116
|
+
assert_equal(file_for_last_inspected_entry, current_state[:last_fetched_entry_info_file])
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'active_support'
|
8
|
+
|
9
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'mingle_events'))
|
10
|
+
|
11
|
+
MingleEvents.log.level = Logger::WARN
|
12
|
+
|
13
|
+
class Test::Unit::TestCase
|
14
|
+
|
15
|
+
# page 3
|
16
|
+
LATEST_PAGE_CONTENT = %{
|
17
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:mingle="http://www.thoughtworks-studios.com/ns/mingle">
|
18
|
+
|
19
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml" rel="current"/>
|
20
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml" rel="self"/>
|
21
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=2" rel="next"/>
|
22
|
+
|
23
|
+
<entry>
|
24
|
+
<id>https://mingle.example.com/projects/atlas/events/index/103</id>
|
25
|
+
<title>entry 103</title>
|
26
|
+
<updated>2011-02-03T08:12:42Z</updated>
|
27
|
+
<author><name>Bob</name></author>
|
28
|
+
</entry>
|
29
|
+
<entry>
|
30
|
+
<id>https://mingle.example.com/projects/atlas/events/index/101</id>
|
31
|
+
<title>entry 101</title>
|
32
|
+
<updated>2011-02-03T02:09:16Z</updated>
|
33
|
+
<author><name>Bob</name></author>
|
34
|
+
</entry>
|
35
|
+
<entry>
|
36
|
+
<id>https://mingle.example.com/projects/atlas/events/index/100</id>
|
37
|
+
<title>entry 100</title>
|
38
|
+
<updated>2011-02-03T01:58:02Z</updated>
|
39
|
+
<author><name>Mary</name></author>
|
40
|
+
</entry>
|
41
|
+
</feed>
|
42
|
+
}
|
43
|
+
|
44
|
+
# page 2
|
45
|
+
PAGE_2_CONTENT = %{
|
46
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:mingle="http://www.thoughtworks-studios.com/ns/mingle">
|
47
|
+
|
48
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml" rel="current"/>
|
49
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=2" rel="self"/>
|
50
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=1" rel="next"/>
|
51
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=3" rel="previous"/>
|
52
|
+
|
53
|
+
<entry>
|
54
|
+
<id>https://mingle.example.com/projects/atlas/events/index/99</id>
|
55
|
+
<title>entry 99</title>
|
56
|
+
<updated>2011-02-03T01:30:52Z</updated>
|
57
|
+
<author><name>Harry</name></author>
|
58
|
+
</entry>
|
59
|
+
|
60
|
+
<entry>
|
61
|
+
<id>https://mingle.example.com/projects/atlas/events/index/98</id>
|
62
|
+
<title>entry 98</title>
|
63
|
+
<updated>2011-02-03T01:20:52Z</updated>
|
64
|
+
<author><name>Harry</name></author>
|
65
|
+
</entry>
|
66
|
+
|
67
|
+
<entry>
|
68
|
+
<id>https://mingle.example.com/projects/atlas/events/index/97</id>
|
69
|
+
<title>entry 97</title>
|
70
|
+
<updated>2011-02-03T01:10:52Z</updated>
|
71
|
+
<author><name>Harry</name></author>
|
72
|
+
</entry>
|
73
|
+
</feed>
|
74
|
+
}
|
75
|
+
|
76
|
+
# page 1
|
77
|
+
PAGE_1_CONTENT = %{
|
78
|
+
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:mingle="http://www.thoughtworks-studios.com/ns/mingle">
|
79
|
+
|
80
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml" rel="current"/>
|
81
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=1" rel="self"/>
|
82
|
+
<link href="https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=2" rel="previous"/>
|
83
|
+
|
84
|
+
<entry>
|
85
|
+
<id>https://mingle.example.com/projects/atlas/events/index/23</id>
|
86
|
+
<title>entry 23</title>
|
87
|
+
<updated>2011-02-01T01:00:52Z</updated>
|
88
|
+
<author><name>Bob</name></author>
|
89
|
+
</entry>
|
90
|
+
</feed>
|
91
|
+
}
|
92
|
+
|
93
|
+
def stub_mingle_access
|
94
|
+
stub = StubMingleAccess.new
|
95
|
+
stub.register_page_content('https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml', LATEST_PAGE_CONTENT)
|
96
|
+
stub.register_page_content('https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=2', PAGE_2_CONTENT)
|
97
|
+
stub.register_page_content('https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=1', PAGE_1_CONTENT)
|
98
|
+
stub.register_page_content('https://mingle.example.com/api/v2/projects/atlas/feeds/events.xml?page=3', LATEST_PAGE_CONTENT)
|
99
|
+
stub.register_page_content('/api/v2/projects/atlas/feeds/events.xml', LATEST_PAGE_CONTENT)
|
100
|
+
stub.register_page_content('/api/v2/projects/atlas/feeds/events.xml?page=2', PAGE_2_CONTENT)
|
101
|
+
stub.register_page_content('/api/v2/projects/atlas/feeds/events.xml?page=1', PAGE_1_CONTENT)
|
102
|
+
stub.register_page_content('/api/v2/projects/atlas/feeds/events.xml?page=3', LATEST_PAGE_CONTENT)
|
103
|
+
|
104
|
+
stub
|
105
|
+
end
|
106
|
+
|
107
|
+
def temp_dir
|
108
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), 'tmp', ActiveSupport::SecureRandom.hex(16)))
|
109
|
+
FileUtils.mkdir_p(path)
|
110
|
+
path
|
111
|
+
end
|
112
|
+
|
113
|
+
def temp_file
|
114
|
+
File.join(temp_dir, ActiveSupport::SecureRandom.hex(16))
|
115
|
+
end
|
116
|
+
|
117
|
+
class StubMingleAccess
|
118
|
+
|
119
|
+
def initialize
|
120
|
+
@pages_by_path = {}
|
121
|
+
@not_found_pages = []
|
122
|
+
end
|
123
|
+
|
124
|
+
def base_url
|
125
|
+
'http://example.com/mingle'
|
126
|
+
end
|
127
|
+
|
128
|
+
def register_page_content(path, content)
|
129
|
+
@pages_by_path[path] = content
|
130
|
+
end
|
131
|
+
|
132
|
+
def register_page_not_found(path)
|
133
|
+
@not_found_pages << path
|
134
|
+
end
|
135
|
+
|
136
|
+
def fetch_page(path)
|
137
|
+
if @not_found_pages.include?(path)
|
138
|
+
rsp = Net::HTTPNotFound.new(nil, '404', 'Page not found!')
|
139
|
+
def rsp.body
|
140
|
+
"404!!!!!"
|
141
|
+
end
|
142
|
+
raise MingleEvents::HttpError.new(rsp, path)
|
143
|
+
end
|
144
|
+
|
145
|
+
raise "Attempting to fetch page at #{path}, but your test has not registered content for this path! Registered paths: #{@pages_by_path.keys.inspect}" unless @pages_by_path.key?(path)
|
146
|
+
@pages_by_path[path]
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
class StubProjectCustomProperties
|
152
|
+
|
153
|
+
def initialize(property_names_by_column_names)
|
154
|
+
@property_names_by_column_names = property_names_by_column_names
|
155
|
+
end
|
156
|
+
|
157
|
+
def property_name_for_column(column_name)
|
158
|
+
@property_names_by_column_names[column_name]
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|