network_executive 0.0.4 → 0.0.7
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/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
|