itunes_store_transporter 0.0.1

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.
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe ITunes::Store::Transporter::TransporterMessage do
4
+ subject { ITunes::Store::Transporter::TransporterMessage.new("some message", 1) }
5
+ its(:code) { should == 1 }
6
+ its(:message) { should == "some message" }
7
+
8
+ describe "#to_s" do
9
+ it "includes the code and message" do
10
+ subject.to_s.should == "some message (1)"
11
+ end
12
+ end
13
+
14
+ describe "error predicate methods" do
15
+ method_codes = {
16
+ :bad_data? => [3000, 3999],
17
+ :invalid_data? => [4000, 4999],
18
+ :missing_data? => [5000, 5999],
19
+ :unsupported_feature? => [6000, 6999],
20
+ :schema_error? => [8000, 8999],
21
+ :asset_error? => [9000, 9999]
22
+ }
23
+
24
+ method_codes.each do |method, codes|
25
+ [codes.first, codes.last].each do |code|
26
+
27
+ context "code #{code}" do
28
+ subject { described_class.new("", code) }
29
+ its(method) { should be_true }
30
+ its(:validation_error?) { should be_true }
31
+
32
+ (method_codes.keys - [method]).each do |other|
33
+ its(other) { should be_false }
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe ITunes::Store::Transporter::ExecutionError do
42
+ subject { described_class.new(messages, 1) }
43
+ let(:messages) { 2.times.inject([]) { |err, i| err << ITunes::Store::Transporter::TransporterMessage.new("message #{i}", i) } }
44
+ its(:exitstatus) { should == 1 }
45
+ its(:errors) { should == messages }
46
+
47
+ describe "#to_s" do
48
+ it "includes each messages and its code" do
49
+ subject.to_s.should == "message 0 (0), message 1 (1)"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,71 @@
1
+ require "spec_helper"
2
+
3
+ describe ITunes::Store::Transporter::OutputParser do
4
+ describe "parsing errors" do
5
+ # TODO: test various error message/code formats handled by the parser
6
+
7
+ context "without an error code" do
8
+ before(:all) { @parser = described_class.new(fixture("errors_and_warnings.no_error_number")) }
9
+
10
+ subject { @parser }
11
+ its(:warnings) { should be_empty }
12
+ its(:errors) { should have(2).items }
13
+
14
+ describe "the first error" do
15
+ subject { @parser.errors.first }
16
+ its(:code) { should be_nil }
17
+ its(:message) { should == "An error occurred while doing fun stuff" }
18
+ end
19
+
20
+ describe "the second error" do
21
+ subject { @parser.errors.last }
22
+ its(:code) { should be_nil }
23
+ its(:message) { should == "An exception has occurred: network timeout" }
24
+ end
25
+ end
26
+
27
+ context "with an error code" do
28
+ before(:all) { @parser = described_class.new(fixture("errors_and_warnings.with_error_number")) }
29
+
30
+ subject { @parser }
31
+ its(:warnings) { should be_empty }
32
+ its(:errors) { should have(2).items }
33
+
34
+
35
+ describe "the first error" do
36
+ subject { @parser.errors.first }
37
+ its(:code) { should == 4000 }
38
+ its(:message) { should == "This is error 4000" }
39
+ end
40
+
41
+ describe "the second error" do
42
+ subject { @parser.errors.last }
43
+ its(:code) { should == 5000 }
44
+ its(:message) { should == "This is error 5000" }
45
+ end
46
+ end
47
+
48
+ context "with duplicate messages" do
49
+ before(:all) { @parser = described_class.new(fixture("errors_and_warnings.duplicate_errors")) }
50
+
51
+ it "does not include duplicates" do
52
+ errors = @parser.errors.map { |e| e.message }
53
+ errors.should == ["Error 1", "Error 2", "Error 3"]
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "parsing warnings" do
59
+ before(:all) { @parser = described_class.new(fixture("errors_and_warnings.single_warning")) }
60
+
61
+ subject { @parser }
62
+ its(:errors) { should be_empty }
63
+ its(:warnings) { should have(1).item }
64
+
65
+ describe "the warning" do
66
+ subject { @parser.warnings.first }
67
+ its(:code) { should == 4010 }
68
+ its(:message) { should == "You've been warned!" }
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+ require "rbconfig"
3
+
4
+ describe ITunes::Store::Transporter::Shell do
5
+ it "yields stdout and stderr as they become available" do
6
+ ruby = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
7
+ temp = Tempfile.new ""
8
+ # sleep else poll() (select) can favor the 1st FD in the read array, causing the
9
+ # test to fail on some platforms
10
+ temp.write(<<-CODE)
11
+ $stdout.puts "OUT 1"
12
+ $stdout.flush
13
+ sleep 1
14
+ $stderr.puts "ERR 1"
15
+ $stderr.flush
16
+ sleep 1
17
+ $stdout.puts "OUT 2"
18
+ $stdout.flush
19
+ sleep 1
20
+ $stderr.puts "ERR 2"
21
+ CODE
22
+
23
+ temp.flush
24
+
25
+ output = []
26
+ expect = [ [ :stdout, "OUT 1" ],
27
+ [ :stderr, "ERR 1" ],
28
+ [ :stdout, "OUT 2" ],
29
+ [ :stderr, "ERR 2" ] ]
30
+
31
+ described_class.new(ruby).exec([temp.path]) do |line, stream|
32
+ output << [ stream, line.chomp! ]
33
+ end
34
+
35
+ output.should == expect
36
+ end
37
+
38
+ context "when on Windows" do
39
+ before(:all) { ENV["PROGRAMFILES"] = "C:\\" }
40
+ it "selects the Windows executable" do
41
+ described_class.stub(:windows? => true)
42
+ described_class.new.path.should match /#{described_class::WINDOWS_EXE}\Z/
43
+ end
44
+ end
45
+
46
+ context "when on anything but Windows" do
47
+ it "selects the right executable" do
48
+ described_class.stub(:windows? => false)
49
+ described_class.new.path.should match /#{described_class::EXE_NAME}\Z/
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,75 @@
1
+ require "rspec"
2
+ require "yaml"
3
+ require "tempfile"
4
+ require "fileutils"
5
+ require "itunes/store/transporter"
6
+
7
+ module SpecHelper
8
+ def create_options(options = {})
9
+ { :username => "uzer",
10
+ :password => "_Gcod3" }.merge(options)
11
+ end
12
+
13
+ # TODO: options for package contents?
14
+ def create_package(options = {})
15
+ Dir.mktmpdir ["",".itmsp"]
16
+ end
17
+
18
+ def expect_shell_args(*expected)
19
+ ITunes::Store::Transporter::Shell.any_instance.stub(:exec) { |*arg| arg.first.should include(*expected) }
20
+ end
21
+
22
+ def fixture(path)
23
+ Fixture.for(path)
24
+ end
25
+
26
+ # Set up output streams and exit code
27
+ def mock_output(options = {})
28
+ outputs = []
29
+ exitcode = options[:exit] || 0
30
+
31
+ # Load a fixture for the given stream
32
+ [:stderr, :stdout].each do |fd|
33
+ fixture = options[fd]
34
+ next unless fixture
35
+ lines = Array === fixture ? fixture : Fixture.for(fixture)
36
+ outputs << [ lines, fd ]
37
+ end
38
+
39
+ ITunes::Store::Transporter::Shell.any_instance.stub(:exec) do |*options|
40
+ block = options.pop
41
+ outputs.each do |lines, fd|
42
+ lines.each { |line| block.call(line, fd) }
43
+ end
44
+ exitcode
45
+ end
46
+ end
47
+
48
+ module Fixture
49
+ class << self
50
+ def for(path)
51
+ type, name = path.split ".", 2
52
+ raise "Unknown fixture '#{path}'" unless fixtures[type].include?(name)
53
+ fixtures[type][name].split("\n")
54
+ end
55
+
56
+ private
57
+ def fixtures
58
+ @fixtures ||= load_fixtures
59
+ end
60
+
61
+ def load_fixtures
62
+ init = Hash.new { |h, k| h[k] = {} }
63
+ Dir[File.join(File.expand_path(File.dirname(__FILE__)), "fixtures", "*.yml")].inject(init) do |fixtures, path|
64
+ name = File.basename(path, ".yml")
65
+ fixtures[name] = YAML.load_file(path)
66
+ fixtures
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ RSpec.configure do |config|
74
+ config.include(SpecHelper)
75
+ end
@@ -0,0 +1,106 @@
1
+ require "spec_helper"
2
+ require "itunes/store/transporter"
3
+
4
+ shared_examples_for "a transporter method" do
5
+ it "uses the default options" do
6
+ defaults = create_options
7
+ config = {
8
+ :path => "/",
9
+ :print_stderr => true,
10
+ :print_stdout => true
11
+ }
12
+
13
+ s = stub(command)
14
+ s.should_receive(:run)
15
+
16
+ klass = ITunes::Store::Transporter::Command.const_get(command)
17
+ klass.should_receive(:new).with(config, defaults).and_return(s)
18
+
19
+ described_class.new(config.merge(defaults)).send(method, options)
20
+ end
21
+ end
22
+
23
+ shared_examples_for "a transporter method without a package argument" do
24
+ it_behaves_like "a transporter method"
25
+
26
+ it "executes the underlying command" do
27
+ ITunes::Store::Transporter::Command.const_get(command).any_instance.should_receive(:run).with(options)
28
+ subject.send(method, options)
29
+ end
30
+ end
31
+
32
+ shared_examples_for "a transporter method with a package argument" do
33
+ it_behaves_like "a transporter method"
34
+
35
+ it "executes the underlying command" do
36
+ ITunes::Store::Transporter::Command.const_get(command).any_instance.should_receive(:run).with(:package => "package.itmsp")
37
+ subject.send(method, "package.itmsp")
38
+ end
39
+ end
40
+
41
+
42
+ describe ITunes::Store::Transporter do
43
+ let(:options) { {} }
44
+
45
+ describe "#new" do
46
+ context "when the options are not a Hash or nil" do
47
+ it "raises an ArgumentError" do
48
+ lambda { described_class.new(123) }.should raise_exception(ArgumentError, /must be/)
49
+ end
50
+ end
51
+ end
52
+
53
+ describe "#lookup" do
54
+ let(:method) { :lookup }
55
+ let(:command) { "Lookup" }
56
+
57
+ it_behaves_like "a transporter method without a package argument"
58
+
59
+ it "executes the underlying command" do
60
+ ITunes::Store::Transporter::Command::Lookup.any_instance.should_receive(:run)
61
+ subject.lookup
62
+ end
63
+ end
64
+
65
+ describe "#providers" do
66
+ let(:method) { :providers }
67
+ let(:command) { "Providers" }
68
+
69
+ it_behaves_like "a transporter method without a package argument"
70
+ end
71
+
72
+ describe "#schema" do
73
+ let(:method) { :schema }
74
+ let(:command) { "Schema" }
75
+
76
+ it_behaves_like "a transporter method without a package argument"
77
+ end
78
+
79
+ describe "#status" do
80
+ let(:method) { :status }
81
+ let(:command) { "Status" }
82
+
83
+ it_behaves_like "a transporter method without a package argument"
84
+ end
85
+
86
+ describe "#upload" do
87
+ let(:method) { :upload }
88
+ let(:command) { "Upload" }
89
+
90
+ it_behaves_like "a transporter method with a package argument"
91
+ end
92
+
93
+ describe "#verify" do
94
+ let(:method) { :verify }
95
+ let(:command) { "Verify" }
96
+
97
+ it_behaves_like "a transporter method with a package argument"
98
+ end
99
+
100
+ describe "#version" do
101
+ let(:method) { :version }
102
+ let(:command) { "Version" }
103
+
104
+ it_behaves_like "a transporter method without a package argument"
105
+ end
106
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itunes_store_transporter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Skye Shaw
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-10 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: childprocess
16
+ requirement: &70193863731280 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70193863731280
25
+ - !ruby/object:Gem::Dependency
26
+ name: optout
27
+ requirement: &70193863730780 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.0.2
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70193863730780
36
+ - !ruby/object:Gem::Dependency
37
+ name: rake
38
+ requirement: &70193863730320 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.2
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70193863730320
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &70193863729860 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 2.8.0
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70193863729860
58
+ description: ! " iTunes::Store::Transporter is a wrapper around Apple's iTMSTransporter
59
+ program. It allows you to upload packages to the \n Apple Store, validate them,
60
+ retrieve status information, lookup metadata, and more!\n"
61
+ email: sshaw@lucas.cis.temple.edu
62
+ executables:
63
+ - itms
64
+ extensions: []
65
+ extra_rdoc_files:
66
+ - README.rdoc
67
+ files:
68
+ - lib/itunes/store/transporter/command/lookup.rb
69
+ - lib/itunes/store/transporter/command/option.rb
70
+ - lib/itunes/store/transporter/command/providers.rb
71
+ - lib/itunes/store/transporter/command/schema.rb
72
+ - lib/itunes/store/transporter/command/status.rb
73
+ - lib/itunes/store/transporter/command/upload.rb
74
+ - lib/itunes/store/transporter/command/verify.rb
75
+ - lib/itunes/store/transporter/command/version.rb
76
+ - lib/itunes/store/transporter/command.rb
77
+ - lib/itunes/store/transporter/errors.rb
78
+ - lib/itunes/store/transporter/output_parser.rb
79
+ - lib/itunes/store/transporter/shell.rb
80
+ - lib/itunes/store/transporter/version.rb
81
+ - lib/itunes/store/transporter.rb
82
+ - README.rdoc
83
+ - spec/command_spec.rb
84
+ - spec/errors_spec.rb
85
+ - spec/output_parser_spec.rb
86
+ - spec/shell_spec.rb
87
+ - spec/spec_helper.rb
88
+ - spec/transporter_spec.rb
89
+ - bin/itms
90
+ homepage: http://github.com/sshaw/itunes_store_transporter
91
+ licenses:
92
+ - MIT
93
+ post_install_message:
94
+ rdoc_options: []
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 1.8.10
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: Upload and manage your assets in the iTunes Store using the iTunes Store's
115
+ Transporter (iTMSTransporter).
116
+ test_files:
117
+ - spec/command_spec.rb
118
+ - spec/errors_spec.rb
119
+ - spec/output_parser_spec.rb
120
+ - spec/shell_spec.rb
121
+ - spec/spec_helper.rb
122
+ - spec/transporter_spec.rb
123
+ has_rdoc: