mr_video 1.0.1 → 1.0.2

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 CHANGED
@@ -49,6 +49,7 @@ Mount it in your `config/routes.rb`.
49
49
  MyApp::Application.routes.draw do
50
50
 
51
51
  if Rails.env.development?
52
+ require 'mr_video'
52
53
  mount MrVideo::Engine => '/mr_video'
53
54
  end
54
55
 
@@ -3,19 +3,10 @@ module MrVideo
3
3
  class EpisodesController < MrVideoController
4
4
 
5
5
  def show
6
- cassette = Cassette.find(params[:cassette_id])
7
- episode = cassette.find_episode_by_id(params[:id])
8
- episode_content = episode.content
9
-
10
- unless params[:fix_relative_links] == 'false'
11
- episode_content.gsub!(/href="\//, "href=\"#{episode.website_url}/")
12
- episode_content.gsub!(/href="(?<foo>[a-zA-z0-9_])/, 'href="' + episode.website_url + '/\k<foo>')
13
- episode_content.gsub!(/src="\//, "src=\"#{episode.website_url}/")
14
- episode_content.gsub!(/@import url\("/, "@import url(\"#{episode.website_url}/")
15
- end
6
+ show_presenter = Episodes::ShowPresenter.new(self)
16
7
 
17
8
  # TODO: Add method for sending decompressed content
18
- send_data episode_content, type: episode.content_type, disposition: 'inline'
9
+ send_data show_presenter.content, type: show_presenter.content_type, disposition: 'inline'
19
10
  end
20
11
 
21
12
  def destroy
@@ -23,7 +23,7 @@ module MrVideo
23
23
  end
24
24
 
25
25
  def updated_at
26
- Time.zone.parse(File.mtime(cassette_path).to_s).to_datetime
26
+ @updated_at ||= episodes.map(&:recorded_at).max
27
27
  end
28
28
 
29
29
 
@@ -0,0 +1,80 @@
1
+ module MrVideo
2
+
3
+ module Episodes
4
+
5
+ class ShowPresenter
6
+
7
+ def initialize(context)
8
+ @context = context
9
+ end
10
+
11
+ def content
12
+ if fix_relative_links?
13
+ content_with_relative_links_fixed
14
+ else
15
+ raw_content
16
+ end
17
+ end
18
+
19
+ def content_type
20
+ episode.content_type
21
+ end
22
+
23
+ private
24
+
25
+ def content_with_relative_links_fixed
26
+ content = raw_content
27
+ [
28
+ /href=["']([^'" >]+)["']/,
29
+ /src=["']([^'" >]+)["']/,
30
+ /@import url\(([^'" >]+)\)/
31
+ ].each do |pattern|
32
+ content.gsub!(pattern) do |match|
33
+ url = $1
34
+ match.gsub(url, URI.join(base_url, url).to_s)
35
+ end
36
+ end
37
+ content
38
+ end
39
+
40
+ def base_url
41
+ episode.website_url
42
+ end
43
+
44
+ def raw_content
45
+ episode.content
46
+ end
47
+
48
+ def fix_relative_links?
49
+ params[:fix_relative_links] != 'false'
50
+ end
51
+
52
+ def episode
53
+ @episode ||= cassette.find_episode_by_id(id)
54
+ end
55
+
56
+ def cassette
57
+ @cassette ||= Cassette.find(cassette_id)
58
+ end
59
+
60
+ def cassette_id
61
+ params[:cassette_id]
62
+ end
63
+
64
+ def id
65
+ params[:id]
66
+ end
67
+
68
+ def params
69
+ context.params
70
+ end
71
+
72
+ def context
73
+ @context
74
+ end
75
+
76
+ end # ShowPresenter class
77
+
78
+ end # Episodes module
79
+
80
+ end # MrVideo module
@@ -9,7 +9,7 @@
9
9
  <%= stylesheet_link_tag 'mr_video/application', media: 'all' %>
10
10
  </head>
11
11
  <body>
12
- <nav class="navbar navbar-default navbar-fixed-top" role="navigation">
12
+ <nav class="navbar navbar-default navbar-fixed-top navbar-inverse" role="navigation">
13
13
  <div class="container">
14
14
  <!-- Brand and toggle get grouped for better mobile display -->
15
15
  <div class="navbar-header">
@@ -19,7 +19,7 @@
19
19
  <span class="icon-bar"></span>
20
20
  <span class="icon-bar"></span>
21
21
  </button>
22
- <a class="navbar-brand" href="<%= root_path %>">Mr. Video</a>
22
+ <a class="navbar-brand" style="color: white;" href="<%= root_path %>">Mr. Video</a>
23
23
  </div><!-- /.navbar-header -->
24
24
  <div class="navbar-collapse collapse" id="navbar-main">
25
25
  <ul class="nav navbar-nav">
@@ -33,7 +33,7 @@
33
33
  <div class="container">
34
34
  <%= yield %>
35
35
  </div>
36
- <div class="navbar navbar-fixed-bottom navbar-inverse">
36
+ <!--div class="navbar navbar-fixed-bottom navbar-inverse">
37
37
  <div class="navbar-inner">
38
38
  <div class="container">
39
39
  <ul class="nav navbar-nav">
@@ -49,7 +49,7 @@
49
49
  </ul>
50
50
  </div>
51
51
  </div>
52
- </div>
52
+ </div-->
53
53
  <%= javascript_include_tag 'mr_video/application' %>
54
54
  </body>
55
55
  </html>
@@ -10,7 +10,7 @@
10
10
  <th>Url</th>
11
11
  <th>Method</th>
12
12
  <th>Content Type</th>
13
- <th>Last Recorded</th>
13
+ <th>Recorded</th>
14
14
  <th>Action</th>
15
15
  </tr>
16
16
  </thead>
@@ -18,7 +18,7 @@
18
18
  <% @cassette.episodes.each_with_index do |episode, index| %>
19
19
  <tr id="episode_<%= episode.id %>_row">
20
20
  <td><%= index + 1 %></td>
21
- <td><%= link_to(episode.url, cassette_episode_path(@cassette, episode), html_options = { target: '_blank' }) %></td>
21
+ <td><%= link_to(episode.url, cassette_episode_path(@cassette, episode, fix_relative_links: true), html_options = { target: '_blank' }) %></td>
22
22
  <td><%= episode.request_method.upcase %></td>
23
23
  <td><%= episode.content_type %></td>
24
24
  <td title="<%= episode.recorded_at %>"><%= time_ago_in_words(episode.recorded_at) %> ago</td>
@@ -1,5 +1,5 @@
1
1
  module MrVideo
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  URL = 'https://github.com/quidproquo/mr_video'
4
4
  NAME = 'Mr. Video'
5
5
  end
@@ -0,0 +1,96 @@
1
+ require 'rails_helper'
2
+
3
+ describe MrVideo::EpisodesController do
4
+ routes { MrVideo::Engine.routes }
5
+
6
+ render_views
7
+
8
+ describe '#show' do
9
+ let(:cassette_id) { 'bell_house' }
10
+ let(:id) { 1234 }
11
+ let(:fix_relative_links) { 'false' }
12
+ let(:cassette) { double(:cassette, id: cassette_id) }
13
+ let(:episode) { double(:episode, id: id) }
14
+ let(:content) { '<html><body></body></html>' }
15
+ let(:website_url) { 'http://www.mrvideo.com' }
16
+ let(:content_type) { 'text/html' }
17
+ let(:params) { {
18
+ cassette_id: cassette_id,
19
+ id: id,
20
+ fix_relative_links: fix_relative_links
21
+ } }
22
+ let(:show) { get(:show, params) }
23
+
24
+ subject { show }
25
+
26
+ before do
27
+ expect(MrVideo::Cassette).to receive(:find).with(cassette_id) { cassette }
28
+ expect(cassette).to receive(:find_episode_by_id).with(id.to_s) { episode }
29
+ expect(episode).to receive(:content) { content }
30
+ allow(episode).to receive(:website_url) { website_url }
31
+ expect(episode).to receive(:content_type) { 'text/html' }
32
+ show
33
+ end
34
+
35
+ it { should be_success }
36
+
37
+ context 'fix relative links is true' do
38
+ let(:fix_relative_links) { 'true' }
39
+ let(:content) { raise NotImplementedError }
40
+ let(:body) { show.body }
41
+
42
+ subject { body }
43
+
44
+ context 'when href contains href="/' do
45
+ let(:content) { '<a href="/videos/video_1234" class="interesting">click here</a>' }
46
+ it 'should have correctly replaced the href' do
47
+ expect(body).to match(/href="http:\/\/www\.mrvideo\.com\/videos\/video_1234"/)
48
+ end
49
+ end
50
+
51
+ context 'when img contains src="/' do
52
+ let(:content) { '<img src="/videos/video_1234.png" />' }
53
+ it 'should have correctly replaced the src' do
54
+ expect(body).to match(/src="http:\/\/www\.mrvideo\.com\/videos\/video_1234.png"/)
55
+ end
56
+ end
57
+
58
+ context 'when @import is relative' do
59
+ let(:content) { '<style>@import url(fun.css);<style/>' }
60
+ it 'should have correctly replaced the url' do
61
+ expect(body).to match(/@import url\(http:\/\/www\.mrvideo\.com\/fun\.css\)/)
62
+ end
63
+ end
64
+
65
+ end # fix relative links
66
+
67
+ end # show
68
+
69
+ describe '#destroy' do
70
+ let(:cassette_id) { 'bell_house' }
71
+ let(:id) { 0 }
72
+ let(:params) { {
73
+ cassette_id: cassette_id,
74
+ id: id
75
+ } }
76
+ let(:cassette) { double(:cassette) }
77
+ let(:episode) { double(:episode, id: id) }
78
+ let(:destroy) { xhr(:post, :destroy, params) }
79
+
80
+ subject { destroy }
81
+
82
+ before do
83
+ expect(MrVideo::Cassette).to receive(:find).with(cassette_id) { cassette }
84
+ expect(cassette).to receive(:find_episode_by_id).with(id.to_s) { episode }
85
+ allow(episode).to receive(:destroy)
86
+ destroy
87
+ end
88
+
89
+ it { should be_success }
90
+
91
+ it 'should destroy the episode' do
92
+ expect(episode).to have_received(:destroy)
93
+ end
94
+ end # #destroy
95
+
96
+ end # MrVideo::EpisodesController