network_executive 0.0.4 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +53 -24
- data/app/assets/fonts/network_executive/league_gothic.css +13 -0
- data/app/assets/fonts/network_executive/league_gothic.svg +148 -0
- data/app/assets/fonts/network_executive/league_gothic.ttf +0 -0
- data/app/assets/fonts/network_executive/league_gothic.woff +0 -0
- data/app/assets/javascripts/network_executive/components/iframe_notifier.coffee +14 -0
- data/app/assets/javascripts/network_executive/components/namespace.coffee +1 -0
- data/app/assets/javascripts/network_executive/components/osd.coffee +65 -0
- data/app/assets/javascripts/network_executive/components/photo_player.coffee +55 -0
- data/app/assets/javascripts/network_executive/components/postman.coffee +23 -0
- data/app/assets/javascripts/network_executive/components/set_top_box.coffee +81 -0
- data/app/assets/javascripts/network_executive/components/tweet_player.coffee +95 -0
- data/app/assets/javascripts/network_executive/components/you_tube_player.coffee +85 -0
- data/app/assets/javascripts/network_executive/slideshow.coffee +6 -0
- data/app/assets/javascripts/network_executive/twitter.coffee +7 -0
- data/app/assets/javascripts/network_executive/you_tube.coffee +8 -0
- data/app/assets/javascripts/network_executive.coffee +10 -0
- data/app/assets/stylesheets/network_executive/{gui_components.css → components/gui_components.css} +0 -0
- data/app/assets/stylesheets/network_executive/{normalize.css → components/normalize.css} +0 -0
- data/app/assets/stylesheets/network_executive/{osd.css → components/osd.css} +6 -34
- data/app/assets/stylesheets/network_executive/components/osd_guide.css +43 -0
- data/app/assets/stylesheets/network_executive/components/photo_player.css +61 -0
- data/app/assets/stylesheets/network_executive/{smpte.css → components/smpte.css} +0 -0
- data/app/assets/stylesheets/network_executive/components/tweet_player.css +60 -0
- data/app/assets/stylesheets/network_executive/components/you_tube_player.css +12 -0
- data/app/assets/stylesheets/network_executive/off_air.css +5 -0
- data/app/assets/stylesheets/network_executive/slideshow.css +4 -0
- data/app/assets/stylesheets/network_executive/twitter.css +5 -0
- data/app/assets/stylesheets/network_executive/you_tube.css +3 -0
- data/app/assets/stylesheets/{network_executive/application.css → network_executive.css} +5 -5
- data/app/controllers/network_executive/components_controller.rb +4 -0
- data/app/controllers/network_executive/guide_controller.rb +41 -0
- data/app/controllers/network_executive/programs_controller.rb +9 -0
- data/app/helpers/network_executive/network_helper.rb +6 -0
- data/app/models/network_executive/channel.rb +15 -14
- data/app/models/network_executive/guide.rb +65 -0
- data/app/models/network_executive/program.rb +69 -5
- data/app/models/network_executive/viewer.rb +4 -0
- data/app/programs/network_executive/off_air.rb +18 -0
- data/app/views/network_executive/components/slideshow.html.erb +20 -0
- data/app/views/network_executive/components/twitter.html.erb +16 -0
- data/app/views/network_executive/components/you_tube.html.erb +13 -0
- data/app/views/network_executive/guide/index.html.erb +30 -0
- data/app/views/network_executive/network/index.html.erb +3 -3
- data/app/views/network_executive/programs/off_air.html.erb +13 -0
- data/config/routes.rb +7 -1
- data/lib/network_executive/channel_schedule.rb +65 -0
- data/lib/network_executive/components/photo_player.rb +48 -0
- data/lib/network_executive/components/tweet_player.rb +48 -0
- data/lib/network_executive/components/you_tube_player.rb +15 -0
- data/lib/network_executive/components.rb +3 -0
- data/lib/network_executive/engine.rb +29 -3
- data/lib/network_executive/off_air_schedule.rb +18 -0
- data/lib/network_executive/producer.rb +3 -3
- data/lib/network_executive/program_schedule.rb +96 -0
- data/lib/network_executive/program_schedule_proxy.rb +55 -0
- data/lib/network_executive/scheduled_program.rb +26 -0
- data/lib/network_executive/scheduling.rb +15 -21
- data/lib/network_executive/time_calculations.rb +10 -0
- data/lib/network_executive/version.rb +1 -1
- data/lib/network_executive.rb +2 -1
- data/network_executive.gemspec +5 -0
- data/spec/models/channel_spec.rb +30 -12
- data/spec/models/{lineup_spec.rb → guide_spec.rb} +28 -6
- data/spec/models/program_spec.rb +46 -3
- data/spec/models/viewer_spec.rb +9 -1
- data/spec/programs/off_air_spec.rb +9 -0
- data/spec/spec_helper.rb +3 -2
- data/spec/unit/channel_schedule_spec.rb +67 -0
- data/spec/unit/components/photo_player_spec.rb +76 -0
- data/spec/unit/components/tweet_player_spec.rb +68 -0
- data/spec/unit/components/you_tube_player_spec.rb +17 -0
- data/spec/unit/off_air_schedule_spec.rb +28 -0
- data/spec/unit/producer_spec.rb +2 -4
- data/spec/unit/program_schedule_proxy_spec.rb +102 -0
- data/spec/unit/program_schedule_spec.rb +191 -0
- data/spec/unit/scheduled_program_spec.rb +57 -0
- data/spec/unit/scheduling_spec.rb +61 -72
- data/vendor/assets/javascripts/bigtext.js +264 -0
- metadata +185 -44
- data/app/assets/javascripts/application.js +0 -13
- data/app/assets/javascripts/network_executive/osd.js +0 -62
- data/app/assets/javascripts/network_executive/set_top_box.js +0 -45
- data/app/controllers/network_executive/lineup_controller.rb +0 -11
- data/app/models/network_executive/channel_schedule.rb +0 -13
- data/app/models/network_executive/lineup.rb +0 -74
- data/app/models/network_executive/lineup_range.rb +0 -34
- data/app/models/network_executive/program_schedule.rb +0 -148
- data/app/views/network_executive/lineup/index.html.erb +0 -26
- data/spec/models/channel_schedule_spec.rb +0 -29
- data/spec/models/lineup_range_spec.rb +0 -65
- data/spec/models/program_schedule_spec.rb +0 -399
data/lib/network_executive.rb
CHANGED
data/network_executive.gemspec
CHANGED
@@ -19,9 +19,14 @@ Gem::Specification.new do |gem|
|
|
19
19
|
|
20
20
|
gem.add_dependency 'activesupport', '~> 3.2.0'
|
21
21
|
gem.add_dependency 'faye-websocket', '~> 0.4.6'
|
22
|
+
gem.add_dependency 'ice_cube', '~> 0.8.1'
|
22
23
|
|
24
|
+
gem.add_dependency 'twitter', '~> 4.0.0'
|
25
|
+
|
26
|
+
# TODO: Where should these live?
|
23
27
|
gem.add_runtime_dependency 'sass-rails'
|
24
28
|
gem.add_runtime_dependency 'uglifier'
|
29
|
+
gem.add_runtime_dependency 'coffee-rails'
|
25
30
|
|
26
31
|
gem.add_development_dependency 'awesome_print'
|
27
32
|
gem.add_development_dependency 'rails', '~> 3.2.8'
|
data/spec/models/channel_spec.rb
CHANGED
@@ -11,29 +11,47 @@ describe NetworkExecutive::Channel do
|
|
11
11
|
subject { MyChannel.new }
|
12
12
|
|
13
13
|
its(:name) { should == 'my_channel' }
|
14
|
+
its(:to_s) { should == 'my_channel' }
|
14
15
|
its(:display_name) { should == 'my channel' }
|
15
|
-
its(:to_s) { should == 'my channel' }
|
16
16
|
|
17
|
-
describe '#
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
describe '#play' do
|
18
|
+
let(:program_double) { double('program', occurs_at?: starting ) }
|
19
|
+
|
20
|
+
context 'at a programs start time' do
|
21
|
+
let(:starting) { true }
|
21
22
|
|
22
23
|
it 'should play the program' do
|
23
|
-
|
24
|
+
program_double.should_receive( :play ).and_yield( {} )
|
24
25
|
|
25
|
-
program_double.should_receive :play
|
26
26
|
described_class.any_instance.should_receive :push
|
27
27
|
|
28
|
-
subject.
|
28
|
+
subject.play program_double
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
context '
|
33
|
-
|
34
|
-
|
32
|
+
context 'after a programs start time' do
|
33
|
+
let(:starting) { false }
|
34
|
+
|
35
|
+
it 'should update the program' do
|
36
|
+
program_double.should_receive( :update ).and_yield( {} )
|
37
|
+
|
38
|
+
described_class.any_instance.should_receive :push
|
39
|
+
|
40
|
+
subject.play program_double
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#play_whats_on' do
|
46
|
+
let(:program) { double('program') }
|
47
|
+
|
48
|
+
it 'should ask what is on and play the program' do
|
49
|
+
described_class.any_instance.should_receive( :whats_on? ).and_return program
|
50
|
+
|
51
|
+
program.should_receive( :play ).and_yield( {} )
|
35
52
|
|
36
|
-
|
53
|
+
subject.play_whats_on do |m|
|
54
|
+
m.should == {}
|
37
55
|
end
|
38
56
|
end
|
39
57
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
describe NetworkExecutive::
|
1
|
+
describe NetworkExecutive::Guide do
|
2
2
|
|
3
3
|
let(:show) do
|
4
4
|
show = double('show', program_name:'show 1')
|
@@ -7,7 +7,7 @@ describe NetworkExecutive::Lineup do
|
|
7
7
|
let(:channel) do
|
8
8
|
channel = double('channel', display_name:'channel a').as_null_object
|
9
9
|
|
10
|
-
channel.stub(:
|
10
|
+
channel.stub(:whats_on_between?).and_return [ show ]
|
11
11
|
|
12
12
|
channel
|
13
13
|
end
|
@@ -25,6 +25,8 @@ describe NetworkExecutive::Lineup do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#start_time' do
|
28
|
+
before { described_class.any_instance.stub(:generate) }
|
29
|
+
|
28
30
|
context 'the default value' do
|
29
31
|
subject { described_class.new.start_time }
|
30
32
|
|
@@ -45,6 +47,8 @@ describe NetworkExecutive::Lineup do
|
|
45
47
|
end
|
46
48
|
|
47
49
|
describe '#stop_time' do
|
50
|
+
before { described_class.any_instance.stub(:generate) }
|
51
|
+
|
48
52
|
context 'the default value' do
|
49
53
|
subject { described_class.new.stop_time }
|
50
54
|
|
@@ -64,6 +68,20 @@ describe NetworkExecutive::Lineup do
|
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
71
|
+
describe '#times' do
|
72
|
+
it 'should start with the start time' do
|
73
|
+
subject.times.first.should eq Time.now
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should contain 15 minute intervals' do
|
77
|
+
subject.times.size.should eq 6
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should end with 1.5 hours after start time' do
|
81
|
+
subject.times.last.should eq Time.now + 1.5.hours - 15.minutes
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
67
85
|
describe '#channels' do
|
68
86
|
subject { described_class.new[:channels] }
|
69
87
|
|
@@ -73,14 +91,18 @@ describe NetworkExecutive::Lineup do
|
|
73
91
|
subject.first[:channel].should == channel
|
74
92
|
end
|
75
93
|
|
76
|
-
it 'should contain
|
77
|
-
subject.first[:
|
94
|
+
it 'should contain a collection of programs' do
|
95
|
+
subject.first[:programs].should be_an Array
|
78
96
|
end
|
79
97
|
|
80
98
|
it 'should ask the channel what is on' do
|
81
|
-
args = [
|
99
|
+
args = [
|
100
|
+
Time.now,
|
101
|
+
(Time.now + 1.5.hours),
|
102
|
+
15.minutes
|
103
|
+
]
|
82
104
|
|
83
|
-
channels.first.should_receive(:
|
105
|
+
channels.first.should_receive(:whats_on_between?).with( *args )
|
84
106
|
|
85
107
|
subject
|
86
108
|
end
|
data/spec/models/program_spec.rb
CHANGED
@@ -11,14 +11,57 @@ describe NetworkExecutive::Program do
|
|
11
11
|
subject { MyProgram.new }
|
12
12
|
|
13
13
|
its(:name) { should == 'my_program' }
|
14
|
+
its(:display_name) { should == 'My Program' }
|
14
15
|
its(:url) { should == '' }
|
15
|
-
its(:
|
16
|
+
its(:refresh) { should == :auto }
|
17
|
+
its(:onload) { should == {} }
|
18
|
+
its(:onupdate) { should == {} }
|
16
19
|
|
17
|
-
describe '#
|
18
|
-
|
20
|
+
describe '#play' do
|
21
|
+
before { EM.stub( :defer ).and_yield }
|
22
|
+
|
23
|
+
it 'should return an EventSource payload' do
|
24
|
+
msg = nil
|
25
|
+
|
26
|
+
subject.play { |m| msg = m }
|
27
|
+
|
28
|
+
msg.should == %q[{"name":"my_program","url":"","onLoad":{},"refresh":"auto","event":"show:program"}]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#onshow' do
|
33
|
+
subject { MyProgram.new.onshow }
|
19
34
|
|
20
35
|
it { should include( name:'my_program' ) }
|
21
36
|
it { should include( url: '' ) }
|
37
|
+
it { should include( onLoad: {} ) }
|
38
|
+
it { should include( refresh: :auto ) }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#update' do
|
42
|
+
context 'when #refresh is set to :auto' do
|
43
|
+
it 'should play the program' do
|
44
|
+
subject.stub(:refresh).and_return :auto
|
45
|
+
|
46
|
+
subject.should_receive( :play )
|
47
|
+
|
48
|
+
subject.update
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when #refresh is NOT set to :auto' do
|
53
|
+
before { EM.stub(:defer).and_yield }
|
54
|
+
|
55
|
+
it 'should return the contents of #onupdate' do
|
56
|
+
subject.stub(:refresh).and_return 'zomg'
|
57
|
+
|
58
|
+
msg = nil
|
59
|
+
|
60
|
+
subject.update { |m| msg = m }
|
61
|
+
|
62
|
+
msg.should == %q[{"event":"update:program"}]
|
63
|
+
end
|
64
|
+
end
|
22
65
|
end
|
23
66
|
|
24
67
|
describe '.find_by_name' do
|
data/spec/models/viewer_spec.rb
CHANGED
@@ -69,7 +69,7 @@ describe NetworkExecutive::Viewer do
|
|
69
69
|
end
|
70
70
|
|
71
71
|
describe '#tune_in' do
|
72
|
-
let(:channel) { double('channel')
|
72
|
+
let(:channel) { double('channel', subscribe:true, play_whats_on:true) }
|
73
73
|
let(:stream) { double('stream').as_null_object }
|
74
74
|
|
75
75
|
before do
|
@@ -91,6 +91,14 @@ describe NetworkExecutive::Viewer do
|
|
91
91
|
|
92
92
|
stream.onclose.should_not be_nil
|
93
93
|
end
|
94
|
+
|
95
|
+
it 'should immediately play whatever is currently scheduled' do
|
96
|
+
channel.should_receive( :play_whats_on ).and_yield( {} )
|
97
|
+
|
98
|
+
stream.should_receive( :send ).with kind_of(Hash)
|
99
|
+
|
100
|
+
subject
|
101
|
+
end
|
94
102
|
end
|
95
103
|
|
96
104
|
describe '#tune_out' do
|
data/spec/spec_helper.rb
CHANGED
@@ -31,7 +31,8 @@ RSpec.configure do |config|
|
|
31
31
|
|
32
32
|
Timecop.return
|
33
33
|
|
34
|
-
|
35
|
-
NetworkExecutive::Network.
|
34
|
+
# Clear out any non-built-in instances
|
35
|
+
NetworkExecutive::Network.channels.reject! { |c| c.class.name.deconstantize != 'NetworkExecutive' }
|
36
|
+
NetworkExecutive::Network.programming.reject! { |p| p.class.name.deconstantize != 'NetworkExecutive' }
|
36
37
|
end
|
37
38
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
describe NetworkExecutive::ChannelSchedule do
|
2
|
+
|
3
|
+
let(:time) { Time.now.change(min:45, sec:0) }
|
4
|
+
let(:interval) { 15.minutes }
|
5
|
+
let(:schedule) { described_class.new }
|
6
|
+
|
7
|
+
let(:program_schedule) do
|
8
|
+
occ = double('occurrence').tap do |o|
|
9
|
+
o.stub(:start_time).and_return time + interval
|
10
|
+
o.stub(:duration).and_return 20.minutes
|
11
|
+
o.stub(:end_time).and_return time + interval + 20.minutes - 1
|
12
|
+
end
|
13
|
+
|
14
|
+
double('program_schedule').tap do |ps|
|
15
|
+
ps.stub(:occurring_at?).and_return false
|
16
|
+
ps.stub(:occurring_at?).with( time + 15.minutes).and_return true
|
17
|
+
ps.stub(:duration).and_return 20.minutes
|
18
|
+
ps.stub(:occurrence_at).and_return occ
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#add' do
|
23
|
+
subject do
|
24
|
+
schedule.add( 'foo', foo:'bar' )
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should prepend a ProgramSchedule' do
|
28
|
+
NetworkExecutive::ProgramSchedule
|
29
|
+
.should_receive( :new )
|
30
|
+
.with( 'foo', { foo:'bar' } )
|
31
|
+
.and_return( program_schedule )
|
32
|
+
|
33
|
+
described_class.any_instance.should_receive( :unshift ).with program_schedule
|
34
|
+
|
35
|
+
subject
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#whats_on_between?' do
|
40
|
+
let(:start) { time }
|
41
|
+
let(:stop) { start + 1.hour }
|
42
|
+
|
43
|
+
before do
|
44
|
+
schedule.unshift program_schedule
|
45
|
+
end
|
46
|
+
|
47
|
+
subject do
|
48
|
+
schedule.whats_on_between? start, stop, interval
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should start with 15-minutes of Off Air time' do
|
52
|
+
subject.first.program.should be_a NetworkExecutive::OffAirSchedule
|
53
|
+
subject.first.remainder.should == 15.minutes - 1
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'should contain a scheduled program at the apporiate time' do
|
57
|
+
subject[1].program.should eq program_schedule
|
58
|
+
subject[1].remainder.should eq 20.minutes - 1
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should fill the remaining time slots of Off Air time' do
|
62
|
+
subject.last.program.should be_a NetworkExecutive::OffAirSchedule
|
63
|
+
subject.last.remainder.should == 25.minutes
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
describe NetworkExecutive::Components::PhotoPlayer do
|
2
|
+
|
3
|
+
let(:klass) do
|
4
|
+
Class.new.send :include, described_class
|
5
|
+
end
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_const 'MyProgram', klass
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { MyProgram.new }
|
12
|
+
|
13
|
+
its(:url) { should == '/slideshow' }
|
14
|
+
its(:refresh) { should be_false }
|
15
|
+
its(:onload) { should include(photos:[]) }
|
16
|
+
its(:photos) { should be_empty }
|
17
|
+
|
18
|
+
describe '#feed_url' do
|
19
|
+
it 'should raise' do
|
20
|
+
expect { subject.feed_url }.to raise_error NotImplementedError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#feed' do
|
25
|
+
let(:request) { double('request').as_null_object }
|
26
|
+
let(:response) { double('response', body:'{}') }
|
27
|
+
|
28
|
+
before do
|
29
|
+
Net::HTTP::Get.stub(:new).and_return request
|
30
|
+
Net::HTTP.any_instance.stub(:request).and_return response
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'with a HTTP feed URL' do
|
34
|
+
before do
|
35
|
+
subject.class.send(:define_method, :feed_url) do
|
36
|
+
'http://example.org'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should not use SSL' do
|
41
|
+
Net::HTTP.any_instance.should_receive(:use_ssl=).with( true ).never
|
42
|
+
|
43
|
+
subject.feed
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'should parse JSON' do
|
47
|
+
subject.feed.should == {}
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with a HTTPS feed URL' do
|
52
|
+
before do
|
53
|
+
subject.class.send(:define_method, :feed_url) do
|
54
|
+
'https://example.org'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should use SSL' do
|
59
|
+
Net::HTTP.any_instance.should_receive(:use_ssl=).with true
|
60
|
+
|
61
|
+
subject.feed
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should not verify the certificate' do
|
65
|
+
Net::HTTP.any_instance.should_receive(:verify_mode=).with 0
|
66
|
+
|
67
|
+
subject.feed
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should parse JSON' do
|
71
|
+
subject.feed.should == {}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
describe NetworkExecutive::Components::TweetPlayer do
|
2
|
+
|
3
|
+
let(:klass) do
|
4
|
+
Class.new do
|
5
|
+
def name; 'foo'; end
|
6
|
+
end.send :include, described_class
|
7
|
+
end
|
8
|
+
|
9
|
+
before do
|
10
|
+
stub_const 'MyProgram', klass
|
11
|
+
end
|
12
|
+
|
13
|
+
subject { MyProgram.new }
|
14
|
+
|
15
|
+
its(:url) { should == '/twitter' }
|
16
|
+
|
17
|
+
its(:refresh) { should be_false }
|
18
|
+
|
19
|
+
describe '#onload' do
|
20
|
+
it 'should include the Twitter search results' do
|
21
|
+
subject.class.should_receive( :tweets ).and_return( statuses: [] )
|
22
|
+
|
23
|
+
subject.onload.should include(:tweets)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '.tweets' do
|
28
|
+
it 'should delegate to the class' do
|
29
|
+
described_class.should_receive :tweets
|
30
|
+
|
31
|
+
described_class.tweets
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.client' do
|
36
|
+
it 'should be a Twitter Client' do
|
37
|
+
subject.class.client.should be_a Twitter::Client
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.configure' do
|
42
|
+
it 'should yield the client' do
|
43
|
+
arg = nil
|
44
|
+
|
45
|
+
subject.class.configure { |c| arg = c }
|
46
|
+
|
47
|
+
arg.should eq subject.class.client
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe '.search' do
|
52
|
+
it 'should configure the search query' do
|
53
|
+
subject.class.search 'search term', count: 4
|
54
|
+
|
55
|
+
subject.class.query.should eq [ 'search term', { count: 4 }]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.tweets' do
|
60
|
+
it 'should search with the client instance' do
|
61
|
+
subject.class.search 'foo'
|
62
|
+
|
63
|
+
Twitter::Client.any_instance.should_receive( :search ).with 'foo'
|
64
|
+
|
65
|
+
subject.class.tweets
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
describe NetworkExecutive::Components::YouTubePlayer do
|
2
|
+
|
3
|
+
let(:klass) do
|
4
|
+
Class.new.send :include, described_class
|
5
|
+
end
|
6
|
+
|
7
|
+
before do
|
8
|
+
stub_const 'MyProgram', klass
|
9
|
+
end
|
10
|
+
|
11
|
+
subject { MyProgram.new }
|
12
|
+
|
13
|
+
its(:url) { should == '/you_tube' }
|
14
|
+
|
15
|
+
its(:refresh) { should be_false }
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
describe NetworkExecutive::OffAirSchedule do
|
2
|
+
|
3
|
+
its(:program) { should be_a NetworkExecutive::OffAir }
|
4
|
+
its(:duration) { should == 59.seconds }
|
5
|
+
|
6
|
+
it 'should be subclass ProgramSchedule' do
|
7
|
+
subject.is_a? NetworkExecutive::ProgramSchedule
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#occurrence_at' do
|
11
|
+
let(:time) { Time.now.change(min:0, sec:0) }
|
12
|
+
|
13
|
+
subject { described_class.new.occurrence_at time }
|
14
|
+
|
15
|
+
it 'return build a ProgramSchedule Occurrence' do
|
16
|
+
args = [
|
17
|
+
time,
|
18
|
+
59.seconds,
|
19
|
+
time + 59.seconds
|
20
|
+
]
|
21
|
+
|
22
|
+
NetworkExecutive::ProgramSchedule::Occurrence.should_receive(:new).with( *args )
|
23
|
+
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/spec/unit/producer_spec.rb
CHANGED
@@ -41,17 +41,15 @@ describe NetworkExecutive::Producer do
|
|
41
41
|
|
42
42
|
describe '.run_scheduled_programming' do
|
43
43
|
let(:scheduled) { double('channel', whats_on?: true) }
|
44
|
-
let(:unscheduled) { double('channel', whats_on?: nil) }
|
45
44
|
|
46
45
|
before do
|
47
|
-
NetworkExecutive::Network.stub(:channels).and_return [ scheduled
|
46
|
+
NetworkExecutive::Network.stub(:channels).and_return [ scheduled ]
|
48
47
|
end
|
49
48
|
|
50
49
|
subject { described_class.run_scheduled_programming }
|
51
50
|
|
52
51
|
it 'should show all scheduled programming' do
|
53
|
-
scheduled.should_receive :
|
54
|
-
unscheduled.should_receive( :show ).never
|
52
|
+
scheduled.should_receive :play
|
55
53
|
|
56
54
|
subject
|
57
55
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
describe NetworkExecutive::ProgramScheduleProxy do
|
2
|
+
|
3
|
+
describe '#initialize' do
|
4
|
+
|
5
|
+
context 'start time' do
|
6
|
+
context 'when specified' do
|
7
|
+
let(:time) { 1.hour.ago }
|
8
|
+
|
9
|
+
subject { described_class.new( time ) }
|
10
|
+
|
11
|
+
it 'should be the specified time' do
|
12
|
+
subject.start_time.should == time
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when unspecified' do
|
17
|
+
it 'should default to the beginning of the day' do
|
18
|
+
subject.start_time.should == Time.now.beginning_of_day
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'duration' do
|
24
|
+
context 'when set' do
|
25
|
+
subject do
|
26
|
+
described_class.new( nil, 15.minutes ).duration
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should have the specified duration' do
|
30
|
+
subject.should == 15.minutes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when not set' do
|
35
|
+
subject do
|
36
|
+
described_class.new.duration
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should default to a full day' do
|
40
|
+
subject.should == 24.hours
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'block evaluation' do
|
46
|
+
it 'should evaluate the block' do
|
47
|
+
evald = false
|
48
|
+
|
49
|
+
described_class.new { evald = true }
|
50
|
+
|
51
|
+
evald.should be_true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#to_schedule' do
|
57
|
+
it 'should return the internal IceCube::Schedule instance' do
|
58
|
+
subject.to_schedule.should be_a IceCube::Schedule
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#respond_to_missing?' do
|
63
|
+
context 'when parsing a schedule block' do
|
64
|
+
# TODO: Not the best test setup in the world...
|
65
|
+
before { subject.instance_variable_set('@parsing_schedule', true) }
|
66
|
+
|
67
|
+
it 'should respond to anything that IceCube::Rule does' do
|
68
|
+
subject.respond_to_missing?( :minutely ).should be_true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when outside a schedule parsing block' do
|
73
|
+
it 'should respond to anything that IceCube::Rule does' do
|
74
|
+
subject.respond_to_missing?( :all_occurrences ).should be_true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#method_missing' do
|
80
|
+
context 'when parsing a schedule block' do
|
81
|
+
it 'should add a recurrence rule' do
|
82
|
+
IceCube::Schedule.any_instance.should_receive( :add_recurrence_rule )
|
83
|
+
.twice
|
84
|
+
.with kind_of( IceCube::Rule )
|
85
|
+
|
86
|
+
described_class.new do
|
87
|
+
minutely 30
|
88
|
+
minutely 45
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when outside a schedule parsing block' do
|
94
|
+
it 'should attempt to forward to the schedule' do
|
95
|
+
IceCube::Schedule.any_instance.should_receive( :all_occurrences )
|
96
|
+
|
97
|
+
described_class.new.all_occurrences
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|