wordpress_client 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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.hound.yml +2 -0
- data/.rubocop.yml +1065 -0
- data/.ruby-version +1 -0
- data/Gemfile +11 -0
- data/Guardfile +29 -0
- data/LICENSE +21 -0
- data/README.md +63 -0
- data/Rakefile +1 -0
- data/circle.yml +3 -0
- data/lib/wordpress_client.rb +25 -0
- data/lib/wordpress_client/category.rb +4 -0
- data/lib/wordpress_client/client.rb +142 -0
- data/lib/wordpress_client/connection.rb +186 -0
- data/lib/wordpress_client/errors.rb +10 -0
- data/lib/wordpress_client/media.rb +37 -0
- data/lib/wordpress_client/media_parser.rb +48 -0
- data/lib/wordpress_client/paginated_collection.rb +53 -0
- data/lib/wordpress_client/post.rb +62 -0
- data/lib/wordpress_client/post_parser.rb +113 -0
- data/lib/wordpress_client/replace_metadata.rb +81 -0
- data/lib/wordpress_client/replace_terms.rb +62 -0
- data/lib/wordpress_client/rest_parser.rb +17 -0
- data/lib/wordpress_client/tag.rb +4 -0
- data/lib/wordpress_client/term.rb +34 -0
- data/lib/wordpress_client/version.rb +3 -0
- data/spec/category_spec.rb +8 -0
- data/spec/client_spec.rb +411 -0
- data/spec/connection_spec.rb +270 -0
- data/spec/docker/Dockerfile +40 -0
- data/spec/docker/README.md +37 -0
- data/spec/docker/dbdump.sql.gz +0 -0
- data/spec/docker/htaccess +10 -0
- data/spec/docker/restore-dbdump.sh +13 -0
- data/spec/fixtures/category.json +1 -0
- data/spec/fixtures/image-media.json +1 -0
- data/spec/fixtures/invalid-post-id.json +1 -0
- data/spec/fixtures/post-with-forbidden-metadata.json +1 -0
- data/spec/fixtures/post-with-metadata.json +1 -0
- data/spec/fixtures/simple-post.json +1 -0
- data/spec/fixtures/tag.json +1 -0
- data/spec/fixtures/thoughtful.jpg +0 -0
- data/spec/fixtures/validation-error.json +1 -0
- data/spec/integration/attachments_crud_spec.rb +51 -0
- data/spec/integration/categories_spec.rb +60 -0
- data/spec/integration/category_assignment_spec.rb +29 -0
- data/spec/integration/posts_crud_spec.rb +118 -0
- data/spec/integration/posts_finding_spec.rb +86 -0
- data/spec/integration/posts_metadata_spec.rb +27 -0
- data/spec/integration/posts_with_attachments_spec.rb +21 -0
- data/spec/integration/tag_assignment_spec.rb +29 -0
- data/spec/integration/tags_spec.rb +36 -0
- data/spec/media_spec.rb +63 -0
- data/spec/paginated_collection_spec.rb +64 -0
- data/spec/post_spec.rb +114 -0
- data/spec/replace_metadata_spec.rb +56 -0
- data/spec/replace_terms_spec.rb +51 -0
- data/spec/shared_examples/term_examples.rb +37 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/docker_runner.rb +49 -0
- data/spec/support/fixtures.rb +19 -0
- data/spec/support/integration_macros.rb +10 -0
- data/spec/support/wordpress_server.rb +103 -0
- data/spec/tag_spec.rb +8 -0
- data/wordpress_client.gemspec +27 -0
- metadata +219 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module WordpressClient
|
4
|
+
describe PaginatedCollection do
|
5
|
+
it "wraps an array" do
|
6
|
+
list = ["one"]
|
7
|
+
pagination = PaginatedCollection.new(list, total: 1, per_page: 1, current_page: 1)
|
8
|
+
|
9
|
+
expect(pagination.each.to_a).to eq list
|
10
|
+
expect(pagination.to_a).to eq list
|
11
|
+
expect(pagination.size).to eq 1
|
12
|
+
|
13
|
+
expect(pagination.total).to eq 1
|
14
|
+
expect(pagination.per_page).to eq 1
|
15
|
+
expect(pagination.current_page).to eq 1
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "pagination attributes" do
|
19
|
+
def collection(total: 1, per_page: 1, current_page: 1)
|
20
|
+
PaginatedCollection.new([], total: total, per_page: per_page, current_page: current_page)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "includes total pages" do
|
24
|
+
expect(collection(total: 10, per_page: 5).total_pages).to eq 2
|
25
|
+
expect(collection(total: 11, per_page: 5).total_pages).to eq 3
|
26
|
+
expect(collection(total: 0, per_page: 5).total_pages).to eq 0
|
27
|
+
expect(collection(total: 10, per_page: 0).total_pages).to eq 0
|
28
|
+
expect(collection(total: 2, per_page: 9).total_pages).to eq 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it "includes next page number" do
|
32
|
+
expect(collection(total: 10, per_page: 1, current_page: 1).next_page).to eq 2
|
33
|
+
expect(collection(total: 10, per_page: 1, current_page: 9).next_page).to eq 10
|
34
|
+
expect(collection(total: 10, per_page: 1, current_page: 10).next_page).to eq nil
|
35
|
+
|
36
|
+
expect(collection(total: 10, per_page: 0, current_page: 1).next_page).to eq nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it "includes previous page number" do
|
40
|
+
expect(collection(total: 10, per_page: 1, current_page: 10).previous_page).to eq 9
|
41
|
+
expect(collection(total: 10, per_page: 1, current_page: 2).previous_page).to eq 1
|
42
|
+
expect(collection(total: 10, per_page: 1, current_page: 1).previous_page).to eq nil
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is out of bounds if current page is after last page" do
|
46
|
+
expect(collection(total: 2, per_page: 1, current_page: 1)).to_not be_out_of_bounds
|
47
|
+
expect(collection(total: 2, per_page: 1, current_page: 2)).to_not be_out_of_bounds
|
48
|
+
|
49
|
+
expect(collection(total: 2, per_page: 1, current_page: 3)).to be_out_of_bounds
|
50
|
+
expect(collection(total: 2, per_page: 1, current_page: 0)).to be_out_of_bounds
|
51
|
+
end
|
52
|
+
|
53
|
+
# Only to be compatible with will_paginate < 3.0
|
54
|
+
it "has an offset" do
|
55
|
+
expect(collection(per_page: 5, current_page: 1).offset).to eq 0
|
56
|
+
expect(collection(per_page: 5, current_page: 2).offset).to eq 5
|
57
|
+
expect(collection(per_page: 50, current_page: 3).offset).to eq 100
|
58
|
+
|
59
|
+
expect(collection(per_page: 50, current_page: 0).offset).to eq 0
|
60
|
+
expect(collection(per_page: 0, current_page: 0).offset).to eq 0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/spec/post_spec.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module WordpressClient
|
4
|
+
describe Post do
|
5
|
+
let(:fixture) { json_fixture("simple-post.json") }
|
6
|
+
|
7
|
+
it "can be parsed from JSON data" do
|
8
|
+
post = Post.parse(fixture)
|
9
|
+
|
10
|
+
expect(post.id).to eq 1
|
11
|
+
expect(post.title_html).to eq "Hello world!"
|
12
|
+
expect(post.slug).to eq "hello-world"
|
13
|
+
|
14
|
+
expect(post.url).to eq "http://example.com/2015/11/03/hello-world/"
|
15
|
+
expect(post.guid).to eq "http://example.com/?p=1"
|
16
|
+
|
17
|
+
expect(post.excerpt_html).to eq(
|
18
|
+
"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start " \
|
19
|
+
"writing!</p>\n"
|
20
|
+
)
|
21
|
+
|
22
|
+
expect(post.content_html).to eq(
|
23
|
+
"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start " \
|
24
|
+
"writing!</p>\n"
|
25
|
+
)
|
26
|
+
|
27
|
+
expect(post.date).to_not be nil
|
28
|
+
expect(post.updated_at).to_not be nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "parses categories" do
|
32
|
+
post = Post.parse(fixture)
|
33
|
+
|
34
|
+
expect(post.categories).to eq [
|
35
|
+
Category.new(
|
36
|
+
id: 1, name_html: "Uncategorized", slug: "uncategorized"
|
37
|
+
)
|
38
|
+
]
|
39
|
+
|
40
|
+
expect(post.category_ids).to eq [1]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "parses tags" do
|
44
|
+
post = Post.parse(fixture)
|
45
|
+
|
46
|
+
expect(post.tags).to eq [
|
47
|
+
Tag.new(
|
48
|
+
id: 2, name_html: "Foo", slug: "foo"
|
49
|
+
)
|
50
|
+
]
|
51
|
+
|
52
|
+
expect(post.tag_ids).to eq [2]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "can have a Media as featured image" do
|
56
|
+
media = instance_double(Media, id: 12)
|
57
|
+
post = Post.new(featured_image: media)
|
58
|
+
|
59
|
+
expect(post.featured_image).to eq media
|
60
|
+
expect(post.featured_image_id).to eq 12
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "dates" do
|
64
|
+
it "uses GMT times if available" do
|
65
|
+
post = Post.parse(fixture.merge(
|
66
|
+
"date_gmt" => "2001-01-01T15:00:00",
|
67
|
+
"date" => "2001-01-01T12:00:00",
|
68
|
+
"modified_gmt" => "2001-01-01T15:00:00",
|
69
|
+
"modified" => "2001-01-01T12:00:00",
|
70
|
+
))
|
71
|
+
|
72
|
+
expect(post.date).to eq Time.utc(2001, 1, 1, 15, 0, 0)
|
73
|
+
expect(post.updated_at).to eq Time.utc(2001, 1, 1, 15, 0, 0)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "falls back to local time if no GMT date is provided" do
|
77
|
+
post = Post.parse(fixture.merge(
|
78
|
+
"date_gmt" => nil,
|
79
|
+
"date" => "2001-01-01T12:00:00",
|
80
|
+
"modified_gmt" => nil,
|
81
|
+
"modified" => "2001-01-01T12:00:00",
|
82
|
+
))
|
83
|
+
|
84
|
+
expect(post.date).to eq Time.local(2001, 1, 1, 12, 0, 0)
|
85
|
+
expect(post.updated_at).to eq Time.local(2001, 1, 1, 12, 0, 0)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "metadata" do
|
90
|
+
it "is parsed into a hash" do
|
91
|
+
post = Post.parse(json_fixture("post-with-metadata.json"))
|
92
|
+
expect(post.meta).to eq "foo" => "bar"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "raises UnauthorizedError when post it is forbidden" do
|
96
|
+
expect {
|
97
|
+
Post.parse(json_fixture("post-with-forbidden-metadata.json"))
|
98
|
+
}.to raise_error(UnauthorizedError)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "keeps track of the ID of each metadata key" do
|
102
|
+
post = Post.parse(json_fixture("post-with-metadata.json"))
|
103
|
+
expect(post.meta_id_for("foo")).to eq 2
|
104
|
+
end
|
105
|
+
|
106
|
+
it "raises ArgumentError when asked for the meta ID of a meta key not present" do
|
107
|
+
post = Post.parse(json_fixture("post-with-metadata.json"))
|
108
|
+
expect {
|
109
|
+
post.meta_id_for("clearly unreal")
|
110
|
+
}.to raise_error(ArgumentError, /clearly unreal/)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module WordpressClient
|
4
|
+
describe ReplaceMetadata do
|
5
|
+
it "does nothing if the new metadata is equal to the existing one" do
|
6
|
+
post = instance_double(Post, id: 5, meta: {"existing" => "1"})
|
7
|
+
|
8
|
+
# Note: connection double does not accept any message.
|
9
|
+
connection = instance_double(Connection)
|
10
|
+
|
11
|
+
ReplaceMetadata.apply(connection, post, existing: "1")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "adds missing metadata" do
|
15
|
+
connection = instance_double(Connection)
|
16
|
+
post = instance_double(Post, id: 5, meta: {"existing" => "1"})
|
17
|
+
|
18
|
+
expect(connection).to receive(:create_without_response).with(
|
19
|
+
"posts/5/meta", key: "new", value: "2"
|
20
|
+
)
|
21
|
+
|
22
|
+
ReplaceMetadata.apply(connection, post, existing: "1", new: "2")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "replaces changed metadata" do
|
26
|
+
connection = instance_double(Connection)
|
27
|
+
post = instance_double(Post, id: 5, meta: {"change_me" => "1"})
|
28
|
+
|
29
|
+
expect(post).to receive(:meta_id_for).with("change_me").and_return(13)
|
30
|
+
|
31
|
+
expect(connection).to receive(:patch_without_response).with(
|
32
|
+
"posts/5/meta/13", key: "change_me", value: "2"
|
33
|
+
)
|
34
|
+
|
35
|
+
ReplaceMetadata.apply(connection, post, change_me: "2")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "removes extra metadata" do
|
39
|
+
connection = instance_double(Connection)
|
40
|
+
post = instance_double(Post, id: 5, meta: {"old" => "1", "new" => "2"})
|
41
|
+
|
42
|
+
expect(post).to receive(:meta_id_for).with("old").and_return(45)
|
43
|
+
expect(connection).to receive(:delete).with("posts/5/meta/45", force: true)
|
44
|
+
|
45
|
+
ReplaceMetadata.apply(connection, post, new: "2")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns the number of changes" do
|
49
|
+
connection = instance_double(Connection).as_null_object
|
50
|
+
post = instance_double(Post, id: 5, meta: {"old" => "1", "change" => "2"}).as_null_object
|
51
|
+
|
52
|
+
result = ReplaceMetadata.apply(connection, post, change: "3", extra: "4")
|
53
|
+
expect(result).to eq 3
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module WordpressClient
|
4
|
+
describe ReplaceTerms do
|
5
|
+
it "adds missing categories" do
|
6
|
+
connection = double(Connection)
|
7
|
+
post = double(Post, id: 40, category_ids: [1])
|
8
|
+
|
9
|
+
expect(connection).to receive(:create_without_response).with("posts/40/terms/category/5", {})
|
10
|
+
|
11
|
+
ReplaceTerms.apply_categories(connection, post, [1, 5])
|
12
|
+
end
|
13
|
+
|
14
|
+
it "removes extra categories" do
|
15
|
+
connection = double(Connection)
|
16
|
+
post = double(Post, id: 40, category_ids: [8, 9, 10])
|
17
|
+
|
18
|
+
expect(connection).to receive(:delete).with("posts/40/terms/category/8", force: true)
|
19
|
+
expect(connection).to receive(:delete).with("posts/40/terms/category/9", force: true)
|
20
|
+
|
21
|
+
ReplaceTerms.apply_categories(connection, post, [10])
|
22
|
+
end
|
23
|
+
|
24
|
+
it "adds missing tags" do
|
25
|
+
connection = double(Connection)
|
26
|
+
post = double(Post, id: 40, tag_ids: [1])
|
27
|
+
|
28
|
+
expect(connection).to receive(:create_without_response).with("posts/40/terms/tag/5", {})
|
29
|
+
|
30
|
+
ReplaceTerms.apply_tags(connection, post, [1, 5])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "removes extra tags" do
|
34
|
+
connection = double(Connection)
|
35
|
+
post = double(Post, id: 40, tag_ids: [8, 9, 10])
|
36
|
+
|
37
|
+
expect(connection).to receive(:delete).with("posts/40/terms/tag/8", force: true)
|
38
|
+
expect(connection).to receive(:delete).with("posts/40/terms/tag/9", force: true)
|
39
|
+
|
40
|
+
ReplaceTerms.apply_tags(connection, post, [10])
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns the amount of changes made" do
|
44
|
+
connection = double(Connection).as_null_object
|
45
|
+
post = double(Post, id: 40, tag_ids: [8, 9, 10])
|
46
|
+
|
47
|
+
result = ReplaceTerms.apply_tags(connection, post, [10, 11])
|
48
|
+
expect(result).to eq 3
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
shared_examples_for(WordpressClient::Term) do |fixture_name:|
|
2
|
+
it "has an id, name_html and slug" do
|
3
|
+
term = described_class.new(id: 5, name_html: "Heyho", slug: "heyho")
|
4
|
+
expect(term.id).to eq 5
|
5
|
+
expect(term.name_html).to eq "Heyho"
|
6
|
+
expect(term.slug).to eq "heyho"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "can be parsed" do
|
10
|
+
term = described_class.parse(json_fixture(fixture_name))
|
11
|
+
expect(term.id).to be_kind_of Integer
|
12
|
+
|
13
|
+
expect(term.name_html).to be_kind_of String
|
14
|
+
expect(term.slug).to be_kind_of String
|
15
|
+
expect(term.name_html).to_not be_empty
|
16
|
+
expect(term.slug).to_not be_empty
|
17
|
+
end
|
18
|
+
|
19
|
+
it "is equal to other instances with the same id, name_html and slug" do
|
20
|
+
instance = described_class.new(id: 1, name_html: "One", slug: "one")
|
21
|
+
copy = described_class.new(id: 1, name_html: "One", slug: "one")
|
22
|
+
|
23
|
+
expect(instance).to eq instance
|
24
|
+
expect(instance).to eq copy
|
25
|
+
|
26
|
+
expect(instance).to_not eq described_class.new(id: 2, name_html: "One", slug: "one")
|
27
|
+
expect(instance).to_not eq described_class.new(id: 1, name_html: "Two", slug: "one")
|
28
|
+
expect(instance).to_not eq described_class.new(id: 1, name_html: "One", slug: "two")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "it not equal on other Term subclasses with the same id, name_html and slug" do
|
32
|
+
other_subclass = Class.new(WordpressClient::Tag)
|
33
|
+
|
34
|
+
term = described_class.new(id: 1, name_html: "One", slug: "one")
|
35
|
+
expect(term).to_not eq other_subclass.new(id: 1, name_html: "One", slug: "one")
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
if ENV['CODECLIMATE_REPO_TOKEN']
|
2
|
+
require "codeclimate-test-reporter"
|
3
|
+
CodeClimate::TestReporter.start
|
4
|
+
end
|
5
|
+
|
6
|
+
require "webmock/rspec"
|
7
|
+
|
8
|
+
require_relative "support/wordpress_server"
|
9
|
+
require_relative "support/fixtures"
|
10
|
+
require_relative "support/integration_macros"
|
11
|
+
|
12
|
+
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
|
13
|
+
require "wordpress_client"
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.extend IntegrationMacros
|
17
|
+
config.include Fixtures
|
18
|
+
|
19
|
+
config.run_all_when_everything_filtered = true
|
20
|
+
|
21
|
+
config.before do
|
22
|
+
WebMock.disable_net_connect!(allow_localhost: false)
|
23
|
+
end
|
24
|
+
|
25
|
+
config.after do
|
26
|
+
WebMock.allow_net_connect!
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "shellwords"
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
module DockerRunner
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def docker_installed?
|
8
|
+
system("hash docker > /dev/null 2> /dev/null")
|
9
|
+
end
|
10
|
+
|
11
|
+
def image_exists?(name)
|
12
|
+
system("docker images | grep -q '^#{name.shellescape} '")
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_image(name, path: Dir.pwd)
|
16
|
+
system("cd #{path.shellescape} && docker build -t #{name.shellescape} .")
|
17
|
+
end
|
18
|
+
|
19
|
+
def run_container(name, port:, environment: {})
|
20
|
+
environment_flags = environment.map { |key, value|
|
21
|
+
"-e #{key.to_s.upcase.shellescape}=#{value.shellescape}"
|
22
|
+
}
|
23
|
+
|
24
|
+
output = `
|
25
|
+
docker run \
|
26
|
+
-dit -p #{port.to_i}:80 \
|
27
|
+
#{environment_flags.join(" ")} \
|
28
|
+
#{name.shellescape}
|
29
|
+
`
|
30
|
+
if $?.success?
|
31
|
+
output.chomp
|
32
|
+
else
|
33
|
+
fail "Failed to start container. Maybe it's already running? Output: #{output}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def purge_container(id)
|
38
|
+
output = `docker kill #{id.shellescape}; docker rm #{id.shellescape} `
|
39
|
+
|
40
|
+
unless $?.success?
|
41
|
+
message = "Could not clean up docker image #{id}. Output was:\n#{output}.\n"
|
42
|
+
if ENV["CIRCLECI"]
|
43
|
+
puts message
|
44
|
+
else
|
45
|
+
raise message
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Fixtures
|
2
|
+
FixtureRoot = Pathname.new(File.expand_path("../../fixtures", __FILE__))
|
3
|
+
|
4
|
+
def fixture_path(name)
|
5
|
+
FixtureRoot.join(name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fixture_contents(name)
|
9
|
+
fixture_path(name).read
|
10
|
+
end
|
11
|
+
|
12
|
+
def json_fixture(name)
|
13
|
+
JSON.parse(fixture_contents(name))
|
14
|
+
end
|
15
|
+
|
16
|
+
def open_fixture(name)
|
17
|
+
fixture_path(name).open('r') { |file| yield file }
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative "docker_runner"
|
2
|
+
|
3
|
+
class WordpressServer
|
4
|
+
include Singleton
|
5
|
+
|
6
|
+
attr_reader :container_id, :port, :host
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@host = docker_host
|
10
|
+
@port = 8181
|
11
|
+
|
12
|
+
start_docker_container
|
13
|
+
at_exit { purge_container }
|
14
|
+
end
|
15
|
+
|
16
|
+
def url
|
17
|
+
"http://#{host_with_port}/wp-json"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Defined in the dbdump in spec/docker/dbdump.sql.gz
|
21
|
+
def username() "test" end
|
22
|
+
|
23
|
+
# Defined in the dbdump in spec/docker/dbdump.sql.gz
|
24
|
+
def password() "test" end
|
25
|
+
|
26
|
+
private
|
27
|
+
def host_with_port
|
28
|
+
"#{host}:#{port}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def docker_host
|
32
|
+
if ENV['DOCKER_HOST']
|
33
|
+
URI.parse(ENV['DOCKER_HOST']).host
|
34
|
+
else
|
35
|
+
"localhost"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_docker_container
|
40
|
+
fail_if_docker_missing
|
41
|
+
build_container_if_missing
|
42
|
+
|
43
|
+
@container_id = start_container
|
44
|
+
@running = true
|
45
|
+
|
46
|
+
begin
|
47
|
+
wait_for_container_to_start
|
48
|
+
rescue
|
49
|
+
purge_container
|
50
|
+
raise $!
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def fail_if_docker_missing
|
55
|
+
unless DockerRunner.docker_installed?
|
56
|
+
STDERR.puts(
|
57
|
+
"It does not look like you have docker installed. " \
|
58
|
+
"Please install docker so you can run integration tests."
|
59
|
+
)
|
60
|
+
fail "No docker installed"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_container_if_missing
|
65
|
+
unless DockerRunner.image_exists?("wpclient-test")
|
66
|
+
DockerRunner.build_image("wpclient-test", path: "spec/docker")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def start_container
|
71
|
+
DockerRunner.run_container(
|
72
|
+
"wpclient-test",
|
73
|
+
port: port,
|
74
|
+
environment: {wordpress_host: host_with_port}
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def purge_container
|
79
|
+
if @running
|
80
|
+
DockerRunner.purge_container(container_id)
|
81
|
+
@running = true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def wait_for_container_to_start
|
86
|
+
# Try to connect to the webserver in a loop until we successfully connect,
|
87
|
+
# the container process dies, or the timeout is reached.
|
88
|
+
timeout = 60
|
89
|
+
start = Time.now
|
90
|
+
|
91
|
+
loop do
|
92
|
+
fail "Timed out while waiting for the container to start" if Time.now - start > timeout
|
93
|
+
|
94
|
+
begin
|
95
|
+
response = Faraday.get(url)
|
96
|
+
return if response.status == 200
|
97
|
+
rescue Faraday::ConnectionFailed
|
98
|
+
# Server not yet started. Just wait it out...
|
99
|
+
end
|
100
|
+
sleep 0.5
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|