audio-feed-manager 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +27 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Guardfile +17 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +86 -0
  8. data/Rakefile +2 -0
  9. data/audio-feed-manager.gemspec +32 -0
  10. data/bin/afm +5 -0
  11. data/lib/audio-feed-manager.rb +1 -0
  12. data/lib/audio_feed_manager/application.rb +39 -0
  13. data/lib/audio_feed_manager/audio_file.rb +9 -0
  14. data/lib/audio_feed_manager/audio_file_adder.rb +14 -0
  15. data/lib/audio_feed_manager/audio_file_repository.rb +42 -0
  16. data/lib/audio_feed_manager/cli/add_audio_file.rb +39 -0
  17. data/lib/audio_feed_manager/cli/add_feed.rb +20 -0
  18. data/lib/audio_feed_manager/cli/arguments.rb +27 -0
  19. data/lib/audio_feed_manager/cli/arguments_parser.rb +67 -0
  20. data/lib/audio_feed_manager/cli/arguments_specification.rb +103 -0
  21. data/lib/audio_feed_manager/cli/command.rb +23 -0
  22. data/lib/audio_feed_manager/cli/commands_list.rb +120 -0
  23. data/lib/audio_feed_manager/cli/get_feed_url.rb +20 -0
  24. data/lib/audio_feed_manager/cli/initialize_project.rb +44 -0
  25. data/lib/audio_feed_manager/cli/list_feeds.rb +38 -0
  26. data/lib/audio_feed_manager/cli/publish.rb +21 -0
  27. data/lib/audio_feed_manager/cli/show_feed.rb +44 -0
  28. data/lib/audio_feed_manager/cli/update_feed_rss.rb +19 -0
  29. data/lib/audio_feed_manager/cli.rb +19 -0
  30. data/lib/audio_feed_manager/config.rb +5 -0
  31. data/lib/audio_feed_manager/config_repository.rb +14 -0
  32. data/lib/audio_feed_manager/console.rb +28 -0
  33. data/lib/audio_feed_manager/directory_lister.rb +9 -0
  34. data/lib/audio_feed_manager/error.rb +4 -0
  35. data/lib/audio_feed_manager/feed.rb +9 -0
  36. data/lib/audio_feed_manager/feed_items_repository.rb +30 -0
  37. data/lib/audio_feed_manager/feed_repository.rb +32 -0
  38. data/lib/audio_feed_manager/feed_syncer.rb +20 -0
  39. data/lib/audio_feed_manager/file_storage.rb +20 -0
  40. data/lib/audio_feed_manager/id3_tags.rb +14 -0
  41. data/lib/audio_feed_manager/new_model_creator.rb +15 -0
  42. data/lib/audio_feed_manager/rss_generator.rb +10 -0
  43. data/lib/audio_feed_manager/rss_repository.rb +36 -0
  44. data/lib/audio_feed_manager/s3_gateway.rb +39 -0
  45. data/lib/audio_feed_manager/secret_token_generator.rb +9 -0
  46. data/lib/audio_feed_manager/stop_application.rb +4 -0
  47. data/lib/audio_feed_manager/support/getter_setter_method.rb +18 -0
  48. data/lib/audio_feed_manager/support/hash_constructor.rb +9 -0
  49. data/lib/audio_feed_manager/tags.rb +9 -0
  50. data/lib/audio_feed_manager/unique_id_generator.rb +19 -0
  51. data/lib/audio_feed_manager/url_maker.rb +13 -0
  52. data/lib/audio_feed_manager/version.rb +3 -0
  53. data/lib/audio_feed_manager.rb +57 -0
  54. data/spec/audio_feed_manager/audio_file_adder_spec.rb +49 -0
  55. data/spec/audio_feed_manager/audio_file_repository_spec.rb +58 -0
  56. data/spec/audio_feed_manager/cli/add_audio_file_spec.rb +44 -0
  57. data/spec/audio_feed_manager/cli/add_feed_spec.rb +27 -0
  58. data/spec/audio_feed_manager/cli/arguments_parser_spec.rb +85 -0
  59. data/spec/audio_feed_manager/cli/arguments_specification_spec.rb +51 -0
  60. data/spec/audio_feed_manager/cli/commands_list_spec.rb +91 -0
  61. data/spec/audio_feed_manager/cli/get_feed_url_spec.rb +26 -0
  62. data/spec/audio_feed_manager/cli/initialize_project_spec.rb +47 -0
  63. data/spec/audio_feed_manager/cli/list_feeds_spec.rb +27 -0
  64. data/spec/audio_feed_manager/cli/show_feed_spec.rb +41 -0
  65. data/spec/audio_feed_manager/cli/update_feed_rss_spec.rb +26 -0
  66. data/spec/audio_feed_manager/cli_spec.rb +42 -0
  67. data/spec/audio_feed_manager/directory_lister_spec.rb +23 -0
  68. data/spec/audio_feed_manager/feed_items_repository_spec.rb +34 -0
  69. data/spec/audio_feed_manager/feeds_repository_spec.rb +40 -0
  70. data/spec/audio_feed_manager/file_storage_spec.rb +22 -0
  71. data/spec/audio_feed_manager/id3_tags_spec.rb +26 -0
  72. data/spec/audio_feed_manager/new_model_creator_spec.rb +44 -0
  73. data/spec/audio_feed_manager/rss_repository_spec.rb +34 -0
  74. data/spec/audio_feed_manager/s3_gateway_spec.rb +51 -0
  75. data/spec/audio_feed_manager/secret_token_generator_spec.rb +13 -0
  76. data/spec/audio_feed_manager/support/getter_setter_method_spec.rb +77 -0
  77. data/spec/audio_feed_manager/unique_id_generator_spec.rb +23 -0
  78. data/spec/fixtures/test.mp3 +0 -0
  79. data/spec/fixtures/test.txt +1 -0
  80. data/spec/help_spec.rb +64 -0
  81. data/spec/initializing_spec.rb +12 -0
  82. data/spec/managing_audio_files_spec.rb +21 -0
  83. data/spec/managing_feeds_spec.rb +51 -0
  84. data/spec/publishing_spec.rb +24 -0
  85. data/spec/s3_credentials.yml.sample +5 -0
  86. data/spec/spec_helper.rb +17 -0
  87. data/spec/support/builders.rb +26 -0
  88. data/spec/support/fake_console.rb +13 -0
  89. data/spec/support/fakes.rb +5 -0
  90. data/spec/support/integration_helpers.rb +38 -0
  91. metadata +297 -0
@@ -0,0 +1,26 @@
1
+ module AudioFeedManager
2
+ describe UpdateFeedRss do
3
+ fake(:feed_repository)
4
+ fake(:rss_generator)
5
+ let(:console) { FakeConsole.new }
6
+
7
+ let(:update_feed_rss) { isolate(UpdateFeedRss) }
8
+
9
+ it "generates the feed RSS" do
10
+ feed = build_feed
11
+ stub(feed_repository).fetch("feeds/foo") { feed }
12
+
13
+ update_feed_rss.run(feed: "feeds/foo")
14
+
15
+ expect(rss_generator).to have_received.generate(feed)
16
+ end
17
+
18
+ it "prints an error message when feed not found" do
19
+ stub(feed_repository).fetch("feeds/foo") { raise FeedNotFound.for_id("feeds/foo") }
20
+
21
+ update_feed_rss.run(feed: "feeds/foo")
22
+
23
+ expect(console.out).to include("not found")
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module AudioFeedManager
2
+ describe CLI do
3
+ fake(:command, arguments: ArgumentsSpecification.new, name: "init") { InitializeProject }
4
+ fake(:commands_list)
5
+ fake(:arguments_parser)
6
+ fake(:help)
7
+ fake(:console)
8
+ let(:arguments) { Arguments.from_hash(project_dir: "my-project-name") }
9
+
10
+ let(:cli) { isolate(CLI) }
11
+
12
+ it "runs the specified command" do
13
+ stub(commands_list).get(["init", "my-project-name"]) { [command, ["my-project-name"]]}
14
+ stub(arguments_parser).parse(command.arguments, ["my-project-name"]) { arguments }
15
+
16
+ cli.run(["init", "my-project-name"])
17
+
18
+ expect(command).to have_received.run(project_dir: "my-project-name")
19
+ end
20
+
21
+ it "prints command usage if command arguments are invalid and stops the application" do
22
+ stub(commands_list).get(["init"]) { [command, []]}
23
+ stub(arguments_parser).parse(command.arguments, []) { raise InvalidArguments }
24
+
25
+ expect {
26
+ cli.run(["init"])
27
+ }.to raise_error(StopApplication)
28
+
29
+ expect(help).to have_received.print_command_usage("init")
30
+ end
31
+
32
+ it "prints usage if command is invalid and stops the application" do
33
+ stub(commands_list).get(["foo"]) { raise UnknownCommand }
34
+
35
+ expect {
36
+ cli.run(["foo"])
37
+ }.to raise_error(StopApplication)
38
+
39
+ expect(help).to have_received.print_usage
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ module AudioFeedManager
2
+ describe DirectoryLister do
3
+ let(:directory_lister) { isolate(DirectoryLister) }
4
+
5
+ it "returns an empty array for non-existent directories" do
6
+ files = directory_lister.list("/tmp/asdfasdfasdfasdfasdfasdf")
7
+
8
+ expect(files).to eq([])
9
+ end
10
+
11
+ it "returns a list of all the files in a given directory, sorted by name" do
12
+ FileUtils.rm_rf("/tmp/foobar")
13
+ FileUtils.mkdir_p("/tmp/foobar")
14
+ FileUtils.touch("/tmp/foobar/foo.txt")
15
+ FileUtils.touch("/tmp/foobar/bar.txt")
16
+ FileUtils.touch("/tmp/foobar/baz.txt")
17
+
18
+ files = directory_lister.list("/tmp/foobar")
19
+
20
+ expect(files).to eq(["bar.txt", "baz.txt", "foo.txt"])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ module AudioFeedManager
2
+ describe FeedItemsRepository do
3
+ let(:items_directory) { Pathname.new("/tmp/foo") }
4
+ let(:feed_items_repository) { isolate(FeedItemsRepository) }
5
+ fake(:audio_file_repository)
6
+
7
+ before do
8
+ FileUtils.rm_rf(items_directory)
9
+ FileUtils.mkdir_p(items_directory)
10
+ end
11
+
12
+ it "returns an empty array for a feed with no items" do
13
+ feed = build_feed
14
+
15
+ expect(feed_items_repository.list(feed)).to eq([])
16
+ end
17
+
18
+ it "returns a list of audio files added for a feed, latest first" do
19
+ feed = build_feed(id: "feeds/abc")
20
+ other_feed = build_feed(id: "feeds/def")
21
+ foo = AudioFile.new(id: "audio_files/foo")
22
+ bar = AudioFile.new(id: "audio_files/bar")
23
+ baz = AudioFile.new(id: "audio_files/baz")
24
+ stub(audio_file_repository).fetch("audio_files/foo") { foo }
25
+ stub(audio_file_repository).fetch("audio_files/bar") { bar }
26
+ stub(audio_file_repository).fetch("audio_files/baz") { baz }
27
+ feed_items_repository.add(feed, foo)
28
+ feed_items_repository.add(feed, bar)
29
+ feed_items_repository.add(other_feed, baz)
30
+
31
+ expect(feed_items_repository.list(feed)).to eq([bar, foo])
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ module AudioFeedManager
4
+ describe FeedRepository do
5
+ let(:feed_repository) { isolate(FeedRepository) }
6
+ let(:feeds_directory) { Pathname.new("/tmp/foo/feeds") }
7
+ let(:feeds_prefix) { "feeds" }
8
+ fake(:new_model_creator)
9
+ fake(:storage)
10
+ fake(:directory_lister)
11
+
12
+ it "stores new feeds" do
13
+ saved_feed = Feed.new(id: "feeds/foo")
14
+ feed = Feed.new(title: "Hello World!")
15
+ mock(new_model_creator).create(feed, directory: feeds_directory,
16
+ prefix: feeds_prefix) { saved_feed }
17
+
18
+ feed = feed_repository.add(feed)
19
+ end
20
+
21
+ it "fetches the stored feeds" do
22
+ stub(storage).read("feeds/hello-world") { {id: "feeds/hello-world", title: "Hello World"} }
23
+
24
+ expect(feed_repository.fetch("feeds/hello-world")).to eq(Feed.new(id: "feeds/hello-world", title: "Hello World"))
25
+ end
26
+
27
+ it "raises FeedNotFound when a feed by given id does not exist" do
28
+ stub(storage).read("feeds/hello-world") { raise FileNotFound }
29
+
30
+ expect{feed_repository.fetch("feeds/hello-world")}.to raise_error(FeedNotFound)
31
+ end
32
+
33
+ it "lists the feeds" do
34
+ stub(directory_lister).list(feeds_directory) { ["hello-world"] }
35
+ stub(storage).read("feeds/hello-world") { {id: "feeds/hello-world", title: "Hello World"} }
36
+
37
+ expect(feed_repository.list).to include(Feed.new(id: "feeds/hello-world", title: "Hello World"))
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,22 @@
1
+ module AudioFeedManager
2
+ describe FileStorage do
3
+ let(:directory) { Pathname.new("/tmp/foo") }
4
+
5
+ let(:storage) { isolate(FileStorage) }
6
+
7
+ before do
8
+ FileUtils.rm_rf(directory)
9
+ FileUtils.mkdir_p(directory.join("feeds"))
10
+ end
11
+
12
+ it "stores the contents in a specified file" do
13
+ storage.store("feeds/hello", {id: 1, title: "hello!"})
14
+
15
+ expect(storage.read("feeds/hello")).to eq(id: 1, title: "hello!")
16
+ end
17
+
18
+ it "raises an error, when the given file does not exist" do
19
+ expect{ storage.read("feeds/hello") }.to raise_error(FileNotFound)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module AudioFeedManager
2
+ describe Id3Tags do
3
+ let(:id3tags) { isolate(Id3Tags) }
4
+
5
+ it "reads ID3 tags from an mp3 file" do
6
+ tags = id3tags.read(fixture_file("test.mp3"))
7
+
8
+ expect(tags.title).to eq("My first audio file")
9
+ expect(tags.artist).to eq("Adam Pohorecki")
10
+ end
11
+
12
+ it "returns empty tags for a file that does not exist" do
13
+ tags = id3tags.read(Pathname.new("/tmp/file-which-does-not-exist"))
14
+
15
+ expect(tags.title).to eq(nil)
16
+ expect(tags.artist).to eq(nil)
17
+ end
18
+
19
+ it "returns empty tags for a file that is not an mp3 file" do
20
+ tags = id3tags.read(fixture_file("test.txt"))
21
+
22
+ expect(tags.title).to eq(nil)
23
+ expect(tags.artist).to eq(nil)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module AudioFeedManager
2
+ describe NewModelCreator do
3
+ class SampleModel < Struct.new(:id, :title, :secret_token, :foo)
4
+ include HashConstructor
5
+ end
6
+
7
+ let(:new_model_creator) { isolate(NewModelCreator) }
8
+ let(:directory) { Pathname.new("/tmp/foo/feeds") }
9
+ let(:prefix) { "feeds" }
10
+ fake(:unique_id_generator, generate: "hello-world")
11
+ fake(:secret_token_generator, generate: "secret-token")
12
+ fake(:storage)
13
+
14
+ it "sets the id for the added model" do
15
+ stub(unique_id_generator).generate("Hello World!", directory) { "hello-world" }
16
+ model = SampleModel.new(title: "Hello World!")
17
+
18
+ new_model_creator.create(model, prefix: prefix, directory: directory)
19
+
20
+ expect(model.id).to eq("feeds/hello-world")
21
+ end
22
+
23
+ it "stores the added model" do
24
+ model = SampleModel.new(title: "Hello World!", foo: "hello there")
25
+
26
+ new_model_creator.create(model, prefix: prefix, directory: directory)
27
+
28
+ expect(storage).to have_received.store(
29
+ "feeds/hello-world",
30
+ id: "feeds/hello-world",
31
+ title: "Hello World!",
32
+ secret_token: "secret-token",
33
+ foo: "hello there",
34
+ )
35
+ end
36
+
37
+ it "assigns a secret token to the created model" do
38
+ model = new_model_creator.create(SampleModel.new(title: "Hello World!"), prefix: prefix, directory: directory)
39
+
40
+ expect(model.secret_token).to eq("secret-token")
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ module AudioFeedManager
2
+ describe RSSRepository do
3
+ fake(:url_maker, feed_url: "http://example.com/feed.xml", audio_file_url: "http://example.com/audio/foo.mp3")
4
+ let(:rss_files_directory) { Pathname.new("/tmp/my-project/rss") }
5
+
6
+ before do
7
+ FileUtils.rm_rf(rss_files_directory)
8
+ FileUtils.mkdir_p(rss_files_directory)
9
+ end
10
+
11
+ it "stores an RSS feed under rss/:secret_token.xml" do
12
+ feed = build_feed(id: "feeds/hello",
13
+ title: "My First Feed",
14
+ description: "some description",
15
+ secret_token: "abcdefgh")
16
+ audio_file = build_audio_file(secret_token: "foobar",
17
+ extension: ".mp3",
18
+ title: "Some audio file",
19
+ author: "Audio file author")
20
+ rss_repository = isolate(RSSRepository)
21
+
22
+ rss_repository.store(feed, [audio_file])
23
+
24
+ feed_content = File.read("/tmp/my-project/rss/abcdefgh.xml")
25
+ expect(feed_content).to include("<?xml")
26
+ expect(feed_content).to include("My First Feed")
27
+ expect(feed_content).to include("some description")
28
+ expect(feed_content).not_to include("feeds/hello")
29
+ expect(feed_content).to include("Some audio file")
30
+ expect(feed_content).to include("Audio file author")
31
+ expect(feed_content).to include("http://example.com/audio/foo.mp3")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ require 'net/http'
2
+
3
+ module AudioFeedManager
4
+ describe S3Gateway, :slow do
5
+ let(:config) { Config.new(s3_bucket: s3_config["bucket"],
6
+ s3_access_key: s3_config["access_key"],
7
+ s3_secret: s3_config["secret_key"],
8
+ s3_region: s3_config["region"]) }
9
+
10
+ let(:s3_gateway) { isolate(S3Gateway) }
11
+
12
+ it "syncs files to S3" do
13
+ unique_key = "test/#{SecureRandom.hex}"
14
+ file_name = :not_called
15
+
16
+ s3_gateway.sync(unique_key, fixture_file("test.mp3")) { |f| file_name = f }
17
+
18
+ expect(file_name).to eq(unique_key)
19
+ end
20
+
21
+ it "does not sync the same file twice" do
22
+ unique_key = "test/#{SecureRandom.hex}"
23
+ file_name = :not_called
24
+
25
+ s3_gateway.sync(unique_key, fixture_file("test.mp3"))
26
+ s3_gateway.sync(unique_key, fixture_file("test.mp3")) { |f| file_name = f }
27
+
28
+ expect(file_name).to eq(:not_called)
29
+ end
30
+
31
+ it "syncs the same file twice if the contents change" do
32
+ unique_key = "test/#{SecureRandom.hex}"
33
+ file_name = :not_called
34
+
35
+ s3_gateway.sync(unique_key, fixture_file("test.mp3"))
36
+ s3_gateway.sync(unique_key, fixture_file("test.txt")) { |f| file_name = f }
37
+
38
+ expect(file_name).to eq(unique_key)
39
+ end
40
+
41
+ it "makes the file publicly accessible" do
42
+ unique_key = "test/#{SecureRandom.hex}"
43
+
44
+ s3_gateway.sync(unique_key, fixture_file("test.txt"))
45
+
46
+ url = URI.parse(s3_gateway.url(unique_key))
47
+ content = File.read(fixture_file("test.txt"))
48
+ expect(Net::HTTP.get(url)).to eq(content)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,13 @@
1
+ module AudioFeedManager
2
+ describe SecretTokenGenerator do
3
+ let(:generator) { isolate(SecretTokenGenerator) }
4
+
5
+ it "generates 16-character strings" do
6
+ expect(generator.generate.size).to eq(16)
7
+ end
8
+
9
+ it "generates unique strings" do
10
+ expect(generator.generate).not_to eq(generator.generate)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,77 @@
1
+ module AudioFeedManager
2
+ describe GetterSetterMethod do
3
+ context "without a default value" do
4
+ klass = Class.new do
5
+ extend GetterSetterMethod
6
+
7
+ get_set :foo
8
+ get_set :bar
9
+ end
10
+
11
+ it "returns nil by default" do
12
+ instance = klass.new
13
+
14
+ expect(instance.foo).to be_nil
15
+ expect(instance.bar).to be_nil
16
+ end
17
+
18
+ it "sets the value when value given" do
19
+ instance = klass.new
20
+
21
+ instance.foo "bar"
22
+
23
+ expect(instance.foo).to eq("bar")
24
+ end
25
+
26
+ it "does not overwrite other values when setting one property" do
27
+ instance = klass.new
28
+
29
+ instance.foo "bar"
30
+
31
+ expect(instance.bar).to be_nil
32
+ end
33
+ end
34
+
35
+ context "with a default value" do
36
+ klass = Class.new do
37
+ extend GetterSetterMethod
38
+
39
+ get_set(:foo) { bar }
40
+ get_set :bar
41
+ get_set(:baz) { "hello" }
42
+ end
43
+
44
+ it "returns the default value" do
45
+ instance = klass.new
46
+
47
+ expect(instance.baz).to eq("hello")
48
+ end
49
+
50
+ it "overwrites the value when value given" do
51
+ instance = klass.new
52
+
53
+ instance.baz "aaa"
54
+
55
+ expect(instance.baz).to eq("aaa")
56
+ end
57
+
58
+ it "evaluates the default block lazily" do
59
+ instance = klass.new
60
+
61
+ instance.bar "aaa"
62
+
63
+ expect(instance.foo).to eq("aaa")
64
+ end
65
+
66
+ it "caches the value once set" do
67
+ instance = klass.new
68
+
69
+ instance.bar "aaa"
70
+ instance.foo
71
+ instance.bar "bbb"
72
+
73
+ expect(instance.foo).to eq("aaa")
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,23 @@
1
+ module AudioFeedManager
2
+ describe UniqueIdGenerator do
3
+ fake(:directory_lister)
4
+
5
+ let(:generator) { isolate(UniqueIdGenerator) }
6
+
7
+ it "generates ids based on the given name" do
8
+ stub(directory_lister).list("/foo") { [] }
9
+
10
+ id = generator.generate("Hello World!", "/foo")
11
+
12
+ expect(id).to eq("hello-world")
13
+ end
14
+
15
+ it "suffixes the id with a number if the name is not unique" do
16
+ stub(directory_lister).list("/foo") { ["hello-world", "foo-bar"] }
17
+
18
+ id = generator.generate("Hello World!", "/foo")
19
+
20
+ expect(id).to eq("hello-world-1")
21
+ end
22
+ end
23
+ end
Binary file
@@ -0,0 +1 @@
1
+ Hello!
data/spec/help_spec.rb ADDED
@@ -0,0 +1,64 @@
1
+ require 'stringio'
2
+
3
+ describe "help commands" do
4
+ let(:stdin) { StringIO.new }
5
+ let(:stderr) { StringIO.new }
6
+
7
+ it "prints help when no arguments given" do
8
+ AudioFeedManager.run(
9
+ argv: [],
10
+ stdin: stdin,
11
+ stderr: stderr,
12
+ )
13
+
14
+ expect(stderr.string).to include("Usage:")
15
+ expect(stderr.string).to include("init")
16
+ end
17
+
18
+ it "prints help with the help command" do
19
+ AudioFeedManager.run(
20
+ argv: ["help"],
21
+ stdin: stdin,
22
+ stderr: stderr,
23
+ )
24
+
25
+ expect(stderr.string).to include("Usage:")
26
+ expect(stderr.string).to include("init")
27
+ end
28
+
29
+ it "prints help with an unknown command" do
30
+ AudioFeedManager.run(
31
+ argv: ["asdfasdfa"],
32
+ stdin: stdin,
33
+ stderr: stderr,
34
+ exit: ->(out) {}
35
+ )
36
+
37
+ expect(stderr.string).to include("Usage:")
38
+ expect(stderr.string).to include("init")
39
+ end
40
+
41
+ it "prints help for specific commands" do
42
+ AudioFeedManager.run(
43
+ argv: ["help", "init"],
44
+ stdin: stdin,
45
+ stderr: stderr,
46
+ )
47
+
48
+ expect(stderr.string).to include("Usage:")
49
+ expect(stderr.string).to include("init")
50
+ expect(stderr.string).to include("<PROJECT_DIR>")
51
+ end
52
+
53
+ it "prints help for multi-word commands" do
54
+ AudioFeedManager.run(
55
+ argv: ["help", "feeds", "add"],
56
+ stdin: stdin,
57
+ stderr: stderr,
58
+ )
59
+
60
+ expect(stderr.string).to include("Usage:")
61
+ expect(stderr.string).to include("feeds add")
62
+ expect(stderr.string).to include("<TITLE>")
63
+ end
64
+ end
@@ -0,0 +1,12 @@
1
+ describe "Initializing project" do
2
+ it "creates the project directory and some support files/directories" do
3
+ FileUtils.rm_rf("/tmp/my-test-project")
4
+
5
+ init_project("/tmp/my-test-project")
6
+
7
+ expect(File.exists?("/tmp/my-test-project")).to be(true)
8
+ expect(File.exists?("/tmp/my-test-project/feeds")).to be(true)
9
+ expect(File.exists?("/tmp/my-test-project/audio_files")).to be(true)
10
+ expect(File.exists?("/tmp/my-test-project/config.yml")).to be(true)
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ describe "Managing audio files" do
2
+ it "adds audio files to feeds" do
3
+ dir = init_project
4
+ feed = add_feed(dir)
5
+
6
+ AudioFeedManager.run(
7
+ pwd: dir,
8
+ stdout: StringIO.new,
9
+ argv: ["audio", "add", feed.id, fixture_file("test.mp3")]
10
+ )
11
+
12
+ out = StringIO.new
13
+ AudioFeedManager.run(
14
+ pwd: dir,
15
+ stdout: out,
16
+ argv: ["feeds", "show", feed.id]
17
+ )
18
+
19
+ expect(out.string).to include("My first audio file")
20
+ end
21
+ end
@@ -0,0 +1,51 @@
1
+ describe "Managing Feeds" do
2
+ it "adds feeds using afm feeds add" do
3
+ dir = init_project
4
+
5
+ AudioFeedManager.run(
6
+ pwd: dir,
7
+ stdin: StringIO.new("some description"),
8
+ stdout: StringIO.new,
9
+ argv: ["feeds", "add", "Hello World!"]
10
+ )
11
+
12
+ stdout = StringIO.new
13
+ AudioFeedManager.run(
14
+ pwd: dir,
15
+ argv: ["feeds", "list"],
16
+ stdout: stdout,
17
+ )
18
+
19
+ expect(stdout.string).to include("Hello World!")
20
+ end
21
+
22
+ it "allows getting the feed url" do
23
+ dir = init_project
24
+ feed = add_feed(dir)
25
+
26
+ out = StringIO.new
27
+ AudioFeedManager.run(
28
+ pwd: dir,
29
+ stdout: out,
30
+ argv: ["feeds", "get-url", feed.id]
31
+ )
32
+
33
+ expect(out.string).to include("http")
34
+ end
35
+
36
+ it "allows regenerating feed rss" do
37
+ dir = init_project
38
+ feed = add_feed(dir)
39
+
40
+ rss_files = File.join(dir, "rss/*.xml")
41
+ Dir[rss_files].each{|f| FileUtils.rm_rf(f)}
42
+
43
+ AudioFeedManager.run(
44
+ pwd: dir,
45
+ stdout: StringIO.new,
46
+ argv: ["feeds", "update-rss", feed.id]
47
+ )
48
+
49
+ expect(Dir[rss_files]).not_to eq([])
50
+ end
51
+ end
@@ -0,0 +1,24 @@
1
+ require 'net/http'
2
+
3
+ describe "Publishing content to S3", :slow do
4
+ it "publishes the RSS and data files" do
5
+ dir = init_project
6
+ feed = add_feed(dir)
7
+ add_audio_file(dir, feed)
8
+
9
+ AudioFeedManager.run(
10
+ pwd: dir,
11
+ stdout: StringIO.new,
12
+ argv: ["publish"]
13
+ )
14
+
15
+ AudioFeedManager.run(
16
+ pwd: dir,
17
+ stdout: out = StringIO.new,
18
+ argv: ["feeds", "get-url", feed.id]
19
+ )
20
+ feed_url = out.string.chomp
21
+
22
+ expect(Net::HTTP.get(URI.parse(feed_url))).to include("Hello World!")
23
+ end
24
+ end
@@ -0,0 +1,5 @@
1
+ ---
2
+ secret_key: "SECRET"
3
+ access_key: "ACCESS"
4
+ bucket: "BUCKET"
5
+ region: "us-west-2"
@@ -0,0 +1,17 @@
1
+ require 'audio-feed-manager'
2
+ require 'bogus/rspec'
3
+ require 'dependor/rspec'
4
+ require "fileutils"
5
+
6
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each do |file|
7
+ require file
8
+ end
9
+
10
+ Bogus.configure do |config|
11
+ config.search_modules = [AudioFeedManager]
12
+ end
13
+
14
+ RSpec.configure do |config|
15
+ config.include IntegrationHelpers
16
+ config.include Builders
17
+ end