dropcaster 0.0.8 → 1.0.0
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.
- checksums.yaml +5 -5
- data/.rubocop.yml +174 -0
- data/.ruby-version +1 -1
- data/.travis.yml +14 -4
- data/Gemfile.lock +244 -135
- data/Guardfile +8 -6
- data/Rakefile +7 -4
- data/Vagrantfile +2 -0
- data/bin/dropcaster +60 -58
- data/bin/lstags +28 -25
- data/dropcaster.gemspec +14 -12
- data/lib/dropcaster/channel.rb +53 -42
- data/lib/dropcaster/channel_file_locator.rb +8 -5
- data/lib/dropcaster/contributors.rb +32 -5
- data/lib/dropcaster/errors.rb +6 -4
- data/lib/dropcaster/item.rb +19 -13
- data/lib/dropcaster/log_formatter.rb +10 -0
- data/lib/dropcaster/logging.rb +13 -0
- data/lib/dropcaster/version.rb +3 -1
- data/lib/dropcaster.rb +2 -15
- data/templates/channel.html.erb +1 -1
- data/templates/channel.rss.erb +1 -1
- data/test/Vagrantfile +3 -1
- data/test/bin/vagrant-status +36 -30
- data/test/extensions/windows.rb +3 -1
- data/test/fixtures/extension.MP3 +0 -0
- data/test/fixtures/special &.mp3 +0 -0
- data/test/helper.rb +4 -1
- data/test/unit/test_app.rb +29 -24
- data/test/unit/test_channel.rb +9 -5
- data/test/unit/test_channel_locator.rb +8 -5
- data/test/unit/test_channel_xml.rb +29 -9
- data/test/unit/{test_item.rb → test_itunes_item.rb} +4 -2
- metadata +39 -19
data/lib/dropcaster/errors.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Dropcaster
|
2
4
|
class ConfigurationError < StandardError
|
3
5
|
def initialize(msg)
|
@@ -6,14 +8,14 @@ module Dropcaster
|
|
6
8
|
end
|
7
9
|
|
8
10
|
class MissingAttributeError < ConfigurationError
|
9
|
-
def initialize(
|
10
|
-
super("#{
|
11
|
+
def initialize(missing_attribute)
|
12
|
+
super("#{missing_attribute} is a mandatory channel attribute, but it is missing.")
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
16
|
class AmbiguousSourcesError < ConfigurationError
|
15
|
-
def initialize(
|
16
|
-
super("The list of sources is ambiguous. Can't derive common directory from these: #{
|
17
|
+
def initialize(ambiguous_sources)
|
18
|
+
super("The list of sources is ambiguous. Can't derive common directory from these: #{ambiguous_sources.inspect}")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
data/lib/dropcaster/item.rb
CHANGED
@@ -1,31 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
1
4
|
require 'mp3info'
|
2
5
|
require 'digest/sha1'
|
6
|
+
require 'dropcaster/logging'
|
3
7
|
|
4
8
|
module Dropcaster
|
5
9
|
class Item
|
6
|
-
|
10
|
+
include Logging
|
11
|
+
|
12
|
+
attr_reader :file_path, :tag, :tag2, :duration, :file_size, :uuid, :pub_date, :lyrics
|
7
13
|
attr_accessor :artist, :image_url, :url, :keywords
|
8
14
|
|
9
|
-
def initialize(file_path, options
|
10
|
-
Mp3Info.open(file_path){|mp3info|
|
11
|
-
@
|
15
|
+
def initialize(file_path, options=nil)
|
16
|
+
Mp3Info.open(file_path) { |mp3info|
|
17
|
+
@file_path = Pathname.new(File.expand_path(file_path)).relative_path_from(Pathname.new(Dir.pwd)).cleanpath
|
12
18
|
@tag = mp3info.tag
|
13
19
|
@tag2 = mp3info.tag2
|
14
20
|
@duration = mp3info.length
|
15
|
-
if @tag2[
|
16
|
-
@lyrics = {}
|
17
|
-
@tag2[
|
21
|
+
if @tag2['ULT']
|
22
|
+
@lyrics = {}
|
23
|
+
@tag2['ULT'].split(/\x00/).drop(1).each_slice(2) { |k, v| @lyrics[k] = v }
|
18
24
|
end
|
19
25
|
}
|
20
26
|
|
21
|
-
@file_size = File.new(
|
22
|
-
@uuid = Digest::SHA1.hexdigest(File.read(
|
27
|
+
@file_size = File.new(file_path).stat.size
|
28
|
+
@uuid = Digest::SHA1.hexdigest(File.read(file_path))
|
23
29
|
|
24
|
-
|
25
|
-
|
30
|
+
if tag2.TDR.blank?
|
31
|
+
logger.info("#{file_path} has no pub date set, using the file's modification time")
|
32
|
+
@pub_date = Time.parse(File.new(file_path).mtime.to_s)
|
26
33
|
else
|
27
|
-
|
28
|
-
@pub_date = DateTime.parse(File.new(file_name).mtime.to_s)
|
34
|
+
@pub_date = Time.parse(tag2.TDR)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
end
|
@@ -1,6 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
2
4
|
|
3
5
|
module Dropcaster
|
6
|
+
module Logging
|
7
|
+
attr_writer :logger
|
8
|
+
|
9
|
+
def logger
|
10
|
+
@logger ||= NullLogger.new
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
class LogFormatter < Logger::Formatter
|
5
15
|
def call(severity, time, program_name, message)
|
6
16
|
"#{severity}: #{message}\n"
|
data/lib/dropcaster/version.rb
CHANGED
data/lib/dropcaster.rb
CHANGED
@@ -1,17 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
require 'bundler/setup'
|
3
|
+
$LOAD_PATH.unshift File.dirname(__FILE__)
|
5
4
|
|
6
5
|
require 'yaml'
|
7
6
|
require 'active_support/core_ext/date_time/conversions'
|
8
7
|
require 'active_support/core_ext/object/blank'
|
9
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
10
|
-
|
11
|
-
require 'logger'
|
12
8
|
|
13
9
|
require 'dropcaster/errors'
|
14
|
-
require 'dropcaster/log_formatter'
|
15
10
|
require 'dropcaster/channel'
|
16
11
|
require 'dropcaster/item'
|
17
12
|
require 'dropcaster/channel_file_locator'
|
@@ -19,12 +14,4 @@ require 'dropcaster/version'
|
|
19
14
|
|
20
15
|
module Dropcaster
|
21
16
|
CHANNEL_YML = 'channel.yml'
|
22
|
-
|
23
|
-
mattr_accessor :logger
|
24
|
-
|
25
|
-
unless @@logger
|
26
|
-
@@logger = Logger.new(STDERR)
|
27
|
-
@@logger.level = Logger::WARN
|
28
|
-
@@logger.formatter = LogFormatter.new
|
29
|
-
end
|
30
17
|
end
|
data/templates/channel.html.erb
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
<h1>Episodes</h1>
|
27
27
|
<% items.each{|item| %>
|
28
28
|
<div class="item" id="<%= h(item.uuid) %>">
|
29
|
-
<h1><%= item.tag.title || item.tag2.TIT2%></h1>
|
29
|
+
<h1><%= h(item.tag.title || item.tag2.TIT2 || item.file_path.to_s) %></h1>
|
30
30
|
<% unless item.tag2.SUBTITLE.blank? %>
|
31
31
|
<h2><%= h(item.tag2.SUBTITLE) %></h2>
|
32
32
|
<% end %>
|
data/templates/channel.rss.erb
CHANGED
@@ -45,7 +45,7 @@
|
|
45
45
|
<% end %>
|
46
46
|
<% items.each{|item| %>
|
47
47
|
<item>
|
48
|
-
<title><%= item.tag.title || item.tag2.TIT2 || item.
|
48
|
+
<title><%= h(item.tag.title || item.tag2.TIT2 || item.file_path.to_s) %></title>
|
49
49
|
<itunes:author><%= h(item.tag2.TP1 || item.tag2.TPE1) %></itunes:author>
|
50
50
|
<% unless item.tag2.TT3.blank? %>
|
51
51
|
<itunes:subtitle><%= h(truncate(item.tag2.TT3, 50)) %></itunes:subtitle>
|
data/test/Vagrantfile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# -*- mode: ruby -*-
|
2
4
|
# vi: set ft=ruby :
|
3
5
|
|
@@ -9,7 +11,7 @@ Vagrant.configure(2) do |config|
|
|
9
11
|
vb.memory = '256'
|
10
12
|
end
|
11
13
|
|
12
|
-
%w
|
14
|
+
%w[1.9.1 2.0 2.1 2.2].each do |version|
|
13
15
|
ruby = "ruby#{version}"
|
14
16
|
name = "ruby-#{version.tr('.', '-')}"
|
15
17
|
|
data/test/bin/vagrant-status
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
3
4
|
require 'csv'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
'
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
HEADERS = [
|
7
|
+
# Unix timestamp in UTC of when the message was printed.
|
8
|
+
'timestamp',
|
9
|
+
# is the target of the following output. This is empty if the message is related to Vagrant globally. Otherwise, this is generally a machine name so you can relate output to a
|
10
|
+
# specific machine when multi-VM is in use.
|
11
|
+
'target',
|
12
|
+
# is the type of machine-readable message being outputted. There are a set of standard types which are covered later.
|
13
|
+
'type',
|
14
|
+
# is zero or more comma-separated values associated with the prior type. The exact amount and meaning of this data is
|
15
|
+
# type-dependent, so you must read the documentation associated with the type to understand fully.
|
16
|
+
'data'
|
17
|
+
].freeze
|
11
18
|
|
12
|
-
|
19
|
+
TYPES = [
|
13
20
|
'box-name', # Name of a box installed into Vagrant.
|
14
21
|
'box-provider', # Provider for an installed box.
|
15
22
|
'cli-command', # A subcommand of vagrant that is available.
|
@@ -18,7 +25,7 @@ types = [
|
|
18
25
|
'state', # The state ID of the target machine. targeted
|
19
26
|
'state-human-long', # Human-readable description of the state of the machine. This is the long version, and may be a paragraph or longer. targeted
|
20
27
|
'state-human-short', # Human-readable description of the state of the machine. This is the short version, limited to at most a sentence. targeted
|
21
|
-
]
|
28
|
+
].freeze
|
22
29
|
|
23
30
|
module Vagrant
|
24
31
|
Box = Struct.new(:name, :provider)
|
@@ -40,31 +47,30 @@ virtual_machines = Hash.new do |vms, target|
|
|
40
47
|
vms[target] = Vagrant::VM.new(target)
|
41
48
|
end
|
42
49
|
|
43
|
-
CSV.new(ARGF, headers:
|
50
|
+
CSV.new(ARGF, headers: HEADERS).each do |message|
|
44
51
|
vm = virtual_machines[message['target']]
|
45
52
|
data = message['data'].split('%!(VAGRANT_COMMA)')
|
46
53
|
|
47
54
|
case message['type']
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
55
|
+
when 'box-name'
|
56
|
+
vm.box.name = data
|
57
|
+
when 'box-provider'
|
58
|
+
vm.box.provider = data
|
59
|
+
when 'state'
|
60
|
+
vm.state.id = data
|
61
|
+
when 'state-human-long'
|
62
|
+
vm.state.long = data
|
63
|
+
when 'state-human-short'
|
64
|
+
vm.state.short = data
|
65
|
+
when 'cli-command'
|
66
|
+
vm.command = data
|
67
|
+
when 'error-exit'
|
68
|
+
vm.error = Vagrant::Error.new(data[0], data[1])
|
69
|
+
when 'provider-name'
|
70
|
+
vm.provider = data
|
71
|
+
else
|
72
|
+
raise "Unknown type: #{message['type']}"
|
66
73
|
end
|
67
74
|
end
|
68
75
|
|
69
|
-
puts
|
70
|
-
#puts virtual_machines.map{|name, vm| "#{name}: #{vm.state.short}"}
|
76
|
+
puts(virtual_machines.map { |name, _| name })
|
data/test/extensions/windows.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Returns true if we run on a windows platform
|
2
4
|
#
|
3
5
|
# Sample:
|
@@ -7,6 +9,6 @@
|
|
7
9
|
# http://snippets.dzone.com/posts/show/2112
|
8
10
|
#
|
9
11
|
def Kernel.is_windows?
|
10
|
-
|
12
|
+
_, platform, _ = RUBY_PLATFORM.split('-')
|
11
13
|
platform == 'mingw32'
|
12
14
|
end
|
Binary file
|
Binary file
|
data/test/helper.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
gem 'minitest'
|
2
4
|
require 'minitest/autorun'
|
3
5
|
require 'dropcaster'
|
@@ -7,5 +9,6 @@ require_relative 'extensions/windows'
|
|
7
9
|
module DropcasterTest
|
8
10
|
FIXTURES_DIR = File.join(File.dirname(__FILE__), 'fixtures')
|
9
11
|
FIXTURE_ITUNES_MP3 = File.join(FIXTURES_DIR, 'iTunes.mp3')
|
10
|
-
|
12
|
+
NUMBER_OF_MP3_FILES = 3
|
13
|
+
NS_ITUNES = 'itunes:http://www.itunes.com/dtds/podcast-1.0.dtd'
|
11
14
|
end
|
data/test/unit/test_app.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
require 'open3'
|
3
5
|
require 'uri'
|
@@ -14,24 +16,24 @@ class TestApp < TestChannelXML
|
|
14
16
|
APP_SCRIPT = 'ruby bin/dropcaster'
|
15
17
|
|
16
18
|
def channel_rss
|
17
|
-
|
19
|
+
`#{APP_SCRIPT} #{FIXTURES_DIR}`
|
18
20
|
end
|
19
21
|
|
20
22
|
def test_overwrite_title
|
21
23
|
test_title = 'Alice and Bob in Wonderland'
|
22
|
-
channel = channel_node(
|
24
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --title '#{test_title}'`)
|
23
25
|
assert_equal(test_title, channel.find('title').first.content)
|
24
26
|
end
|
25
27
|
|
26
28
|
def test_overwrite_subtitle
|
27
29
|
test_subtitle = 'Tales from another world that is upside down'
|
28
|
-
channel = channel_node(
|
30
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --subtitle '#{test_subtitle}'`)
|
29
31
|
assert_equal(test_subtitle, channel.find('itunes:subtitle').first.content)
|
30
32
|
end
|
31
33
|
|
32
34
|
def test_overwrite_link
|
33
35
|
test_link = 'http://www.example.com/foo/bar'
|
34
|
-
channel = channel_node(
|
36
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --url '#{test_link}'`)
|
35
37
|
assert_equal(test_link, channel.find('link').first.content)
|
36
38
|
end
|
37
39
|
|
@@ -39,14 +41,14 @@ class TestApp < TestChannelXML
|
|
39
41
|
test_link_base = 'http://www.dropbox.com/foo/bar/'
|
40
42
|
test_link_file = 'index.html'
|
41
43
|
test_link = "#{test_link_base}#{test_link_file}"
|
42
|
-
channel = channel_node(
|
44
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --url '#{test_link}'`)
|
43
45
|
assert_equal(test_link, channel.find('link').first.content)
|
44
46
|
|
45
47
|
options = YAML.load_file(File.join(FIXTURES_DIR, Dropcaster::CHANNEL_YML))
|
46
48
|
assert_equal(URI.join(test_link_base, options[:image_url]).to_s, channel.find('itunes:image').first['href'])
|
47
49
|
|
48
50
|
# check that the item URLs are correct, too
|
49
|
-
item = channel.find(
|
51
|
+
item = channel.find('item').first
|
50
52
|
assert(item)
|
51
53
|
|
52
54
|
# enclosure
|
@@ -59,42 +61,43 @@ class TestApp < TestChannelXML
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def test_dir_only
|
62
|
-
channel
|
63
|
-
assert_equal(1, channel.find('item').size)
|
64
|
+
assert_equal(NUMBER_OF_MP3_FILES, @channel.find('item').size)
|
64
65
|
end
|
65
66
|
|
66
67
|
def test_overwrite_enclosures_url
|
67
68
|
test_enclosures_url = 'http://www.example.com/foo/bar/episodes/'
|
68
|
-
channel = channel_node(
|
69
|
-
item = channel.find(
|
69
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --enclosures '#{test_enclosures_url}'`)
|
70
|
+
item = channel.find('item').first
|
70
71
|
assert(item)
|
71
72
|
enclosure = item.find('enclosure').first
|
72
73
|
assert(enclosure)
|
73
|
-
assert_equal(URI.join(test_enclosures_url,'test/fixtures/iTunes.mp3').to_s, enclosure['url'])
|
74
|
+
assert_equal(URI.join(test_enclosures_url, 'test/fixtures/iTunes.mp3').to_s, enclosure['url'])
|
74
75
|
end
|
75
76
|
|
76
77
|
def test_overwrite_image_url
|
77
78
|
test_image_url = 'http://www.example.com/foo/bar/override.gif'
|
78
|
-
channel = channel_node(
|
79
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --image '#{test_image_url}'`)
|
79
80
|
assert_equal(test_image_url, channel.find('itunes:image').first['href'])
|
80
81
|
|
81
82
|
# Make sure the items pick up this URL, too
|
82
|
-
item = channel.find(
|
83
|
+
item = channel.find('item').first
|
83
84
|
assert(item)
|
84
85
|
assert_equal(test_image_url, item.find('itunes:image').first['href'])
|
85
86
|
end
|
86
87
|
|
87
88
|
def test_overwrite_description
|
88
89
|
test_description = 'Testing commandline apps is not that hard.'
|
89
|
-
channel = channel_node(
|
90
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --description '#{test_description}'`)
|
90
91
|
assert_equal(test_description, channel.find('description').first.content)
|
91
92
|
assert_equal(test_description, channel.find('itunes:summary', NS_ITUNES).first.content)
|
92
93
|
end
|
93
94
|
|
94
95
|
def test_no_channel_file
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
unless Kernel.is_windows?
|
97
|
+
Open3.popen3(APP_SCRIPT) { |stdin, stdout, stderr|
|
98
|
+
assert_match(/ERROR: No channel file found/, stderr.read)
|
99
|
+
}
|
100
|
+
end
|
98
101
|
end
|
99
102
|
|
100
103
|
def test_overwrite_all
|
@@ -102,7 +105,7 @@ class TestApp < TestChannelXML
|
|
102
105
|
test_link = 'http://www.example.com/bar/foot'
|
103
106
|
test_description = 'Testing commandline apps is really not that hard.'
|
104
107
|
|
105
|
-
channel = channel_node(
|
108
|
+
channel = channel_node(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --title '#{test_title}' --url '#{test_link}' --description '#{test_description}'`)
|
106
109
|
|
107
110
|
assert_equal(test_title, channel.find('title').first.content)
|
108
111
|
assert_equal(test_link, channel.find('link').first.content)
|
@@ -111,9 +114,11 @@ class TestApp < TestChannelXML
|
|
111
114
|
end
|
112
115
|
|
113
116
|
def test_channel_template_not_found
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
+
unless Kernel.is_windows?
|
118
|
+
Open3.popen3("#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --channel-template foo/bar/42") { |stdin, stdout, stderr|
|
119
|
+
assert_match(/Unable to load template file/, stderr.read)
|
120
|
+
}
|
121
|
+
end
|
117
122
|
end
|
118
123
|
|
119
124
|
#
|
@@ -121,9 +126,9 @@ class TestApp < TestChannelXML
|
|
121
126
|
#
|
122
127
|
def test_overwrite_channel_template
|
123
128
|
channel_template = File.join(FIXTURES_DIR, 'test_template.json.erb')
|
124
|
-
channel = JSON.parse(
|
125
|
-
assert_equal(
|
129
|
+
channel = JSON.parse(`#{APP_SCRIPT} #{FIXTURE_ITUNES_MP3} --channel-template #{channel_template}`)
|
130
|
+
assert_equal('All About Everything', channel['channel']['title'])
|
126
131
|
end
|
127
132
|
|
128
|
-
# TODO --channel
|
133
|
+
# TODO: --channel
|
129
134
|
end
|
data/test/unit/test_channel.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
5
|
class TestChannel < MiniTest::Test
|
@@ -9,7 +11,7 @@ class TestChannel < MiniTest::Test
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def test_item_count
|
12
|
-
assert_equal(
|
14
|
+
assert_equal(NUMBER_OF_MP3_FILES, @channel.items.size)
|
13
15
|
end
|
14
16
|
|
15
17
|
def test_channel
|
@@ -47,7 +49,9 @@ class TestChannel < MiniTest::Test
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def test_channel_explicit_nil
|
50
|
-
|
52
|
+
@options[:explicit] = nil
|
53
|
+
channel = Dropcaster::Channel.new(FIXTURES_DIR, @options)
|
54
|
+
assert_nil(channel.explicit)
|
51
55
|
end
|
52
56
|
|
53
57
|
def test_channel_explicit_clean
|
@@ -62,19 +66,19 @@ class TestChannel < MiniTest::Test
|
|
62
66
|
|
63
67
|
def test_raise_on_missing_title
|
64
68
|
assert_raises Dropcaster::MissingAttributeError do
|
65
|
-
Dropcaster::Channel.new(FIXTURES_DIR, {:
|
69
|
+
Dropcaster::Channel.new(FIXTURES_DIR, { url: 'bar', description: 'foobar' })
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
69
73
|
def test_raise_on_missing_url
|
70
74
|
assert_raises Dropcaster::MissingAttributeError do
|
71
|
-
Dropcaster::Channel.new(FIXTURES_DIR, {:
|
75
|
+
Dropcaster::Channel.new(FIXTURES_DIR, { title: 'foo', description: 'foobar' })
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
75
79
|
def test_raise_on_missing_description
|
76
80
|
assert_raises Dropcaster::MissingAttributeError do
|
77
|
-
Dropcaster::Channel.new(FIXTURES_DIR, {:
|
81
|
+
Dropcaster::Channel.new(FIXTURES_DIR, { title: 'foo', url: 'bar' })
|
78
82
|
end
|
79
83
|
end
|
80
84
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
require 'tmpdir'
|
3
5
|
require 'pry'
|
@@ -8,6 +10,7 @@ class TestChannelLocator < MiniTest::Test
|
|
8
10
|
def setup
|
9
11
|
@temp_dir = Dir.mktmpdir
|
10
12
|
end
|
13
|
+
|
11
14
|
def teardown
|
12
15
|
FileUtils.remove_entry_secure(@temp_dir)
|
13
16
|
end
|
@@ -30,7 +33,7 @@ class TestChannelLocator < MiniTest::Test
|
|
30
33
|
end
|
31
34
|
|
32
35
|
def test_array_of_files_same_dir
|
33
|
-
sources =
|
36
|
+
sources = []
|
34
37
|
sources << File.join(@temp_dir, 'file1.mp3')
|
35
38
|
sources << File.join(@temp_dir, 'file2.mp3')
|
36
39
|
sources << File.join(@temp_dir, 'file3.mp3')
|
@@ -39,7 +42,7 @@ class TestChannelLocator < MiniTest::Test
|
|
39
42
|
end
|
40
43
|
|
41
44
|
def test_array_of_files_different_dir
|
42
|
-
sources =
|
45
|
+
sources = []
|
43
46
|
sources << File.join(@temp_dir, 'foo', 'file1.mp3')
|
44
47
|
sources << File.join(@temp_dir, 'bar', 'file1.mp3')
|
45
48
|
sources << File.join(@temp_dir, 'baz', 'file1.mp3')
|
@@ -54,9 +57,9 @@ class TestChannelLocator < MiniTest::Test
|
|
54
57
|
end
|
55
58
|
|
56
59
|
def test_array_with_more_than_a_single_directory
|
57
|
-
Dir.mktmpdir{|tmp_dir1|
|
58
|
-
Dir.mktmpdir{|tmp_dir2|
|
59
|
-
sources =
|
60
|
+
Dir.mktmpdir { |tmp_dir1|
|
61
|
+
Dir.mktmpdir { |tmp_dir2|
|
62
|
+
sources = []
|
60
63
|
sources << File.join(tmp_dir1, 'another_dir')
|
61
64
|
sources << File.join(tmp_dir2, 'another_dir')
|
62
65
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
require 'xml/libxml'
|
3
5
|
require 'pry'
|
@@ -14,7 +16,7 @@ class TestChannelXML < MiniTest::Test
|
|
14
16
|
# Returnes the XML node for the channel passed as XML string
|
15
17
|
#
|
16
18
|
def channel_node(rss)
|
17
|
-
XML::Document.string(rss).find(
|
19
|
+
XML::Document.string(rss).find('//rss/channel').first
|
18
20
|
end
|
19
21
|
|
20
22
|
#
|
@@ -27,11 +29,10 @@ class TestChannelXML < MiniTest::Test
|
|
27
29
|
Dropcaster::Channel.new(FIXTURES_DIR, @options.dup).to_rss
|
28
30
|
end
|
29
31
|
|
30
|
-
def
|
31
|
-
item = @channel.find(
|
32
|
+
def test_itunes_item
|
33
|
+
item = @channel.find('item[title = "iTunes Name"]').first
|
32
34
|
assert(item)
|
33
35
|
|
34
|
-
assert_equal('iTunes Name', item.find('title').first.content)
|
35
36
|
assert_equal('iTunes Artist', item.find('itunes:author', NS_ITUNES).first.content)
|
36
37
|
assert_equal('iTunes Description (Video Pane)', item.find('itunes:summary', NS_ITUNES).first.content)
|
37
38
|
assert_equal('http://www.example.com/podcasts/everything/AllAboutEverything.jpg', item.find('itunes:image', NS_ITUNES).first['href'])
|
@@ -51,12 +52,31 @@ class TestChannelXML < MiniTest::Test
|
|
51
52
|
assert_equal('3', item.find('itunes:duration', NS_ITUNES).first.content)
|
52
53
|
end
|
53
54
|
|
55
|
+
def test_special_ampersand_item
|
56
|
+
# in the actual XML, this is "special &.mp3", but it gets interpreted by XML::Document
|
57
|
+
# if it was just "special &.mp3", it would be invalid XML and we wouldn't get this far
|
58
|
+
item = @channel.find('item[title = "test/fixtures/special &.mp3"]').first
|
59
|
+
assert(item)
|
60
|
+
|
61
|
+
enclosure = item.find('enclosure').first
|
62
|
+
assert(enclosure)
|
63
|
+
assert_equal('http://www.example.com/podcasts/everything/test/fixtures/special%20%26.mp3', enclosure['url'])
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_uppercase_extension_item
|
67
|
+
item = @channel.find('item[title = "test/fixtures/extension.MP3"]').first
|
68
|
+
assert(item)
|
69
|
+
|
70
|
+
enclosure = item.find('enclosure').first
|
71
|
+
assert(enclosure)
|
72
|
+
assert_equal('http://www.example.com/podcasts/everything/test/fixtures/extension.MP3', enclosure['url'])
|
73
|
+
end
|
74
|
+
|
54
75
|
def test_attributes_mandatory
|
55
|
-
options = {:
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
}
|
76
|
+
options = { title: 'Test Channel',
|
77
|
+
url: 'http://www.example.com/',
|
78
|
+
description: 'A test channel',
|
79
|
+
enclosures_url: 'http://www.example.com/foo/bar' }
|
60
80
|
|
61
81
|
channel = channel_node(Dropcaster::Channel.new(FIXTURES_DIR, options).to_rss)
|
62
82
|
assert_equal('Test Channel', channel.find('title').first.content)
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'helper'
|
2
4
|
|
3
|
-
class
|
5
|
+
class TestItunesItem < MiniTest::Test
|
4
6
|
include DropcasterTest
|
5
7
|
|
6
8
|
def setup
|
@@ -12,7 +14,7 @@ class TestItem < MiniTest::Test
|
|
12
14
|
assert_equal(58119, @item.file_size)
|
13
15
|
assert_equal('77bf84447c0f69ce4a33a18b0ae1e030b82010de', @item.uuid)
|
14
16
|
assert_equal(File.mtime(FIXTURE_ITUNES_MP3).to_i, @item.pub_date.to_i)
|
15
|
-
assert_equal('test/fixtures/iTunes.mp3', @item.
|
17
|
+
assert_equal('test/fixtures/iTunes.mp3', @item.file_path.to_s)
|
16
18
|
end
|
17
19
|
|
18
20
|
def test_tag
|