wordpress_client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,270 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module WordpressClient
|
4
|
+
describe Connection do
|
5
|
+
subject(:connection) {
|
6
|
+
Connection.new(url: "http://example.com/", username: "jane", password: "doe")
|
7
|
+
}
|
8
|
+
|
9
|
+
let(:base_url) { "http://jane:doe@example.com/wp/v2" }
|
10
|
+
let(:model) { class_double(Post, parse: model_instance) }
|
11
|
+
let(:model_instance) { instance_double(Post) }
|
12
|
+
|
13
|
+
it "is constructed with a url, username and a password" do
|
14
|
+
connection = Connection.new(url: "http://example.com/wp-json", username: "x", password: "x")
|
15
|
+
expect(connection.url).to eq('http://example.com/wp-json')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "does not show password when inspected" do
|
19
|
+
connection = Connection.new(url: "/", username: "x", password: "secret")
|
20
|
+
expect(connection.to_s).to_not include "secret"
|
21
|
+
expect(connection.inspect).to_not include "secret"
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "get" do
|
25
|
+
it "can get a single model" do
|
26
|
+
stub_get("#{base_url}/foo?some_param=12", returns: {title: "Foo"})
|
27
|
+
expect(model).to receive(:parse).with("title" => "Foo").and_return(model_instance)
|
28
|
+
expect(connection.get(model, "foo", some_param: 12)).to eq model_instance
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can get several models" do
|
32
|
+
stub_get("#{base_url}/foos?some_param=12&page=1&per_page=1", returns: ["result"], total: 1)
|
33
|
+
|
34
|
+
expect(model).to receive(:parse).with("result").and_return(model_instance)
|
35
|
+
|
36
|
+
expect(
|
37
|
+
connection.get_multiple(model, "foos", some_param: 12, page: 1, per_page: 1).to_a
|
38
|
+
).to eq [model_instance]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "paginates the result when fetching multiple models" do
|
42
|
+
stub_get("#{base_url}/foos?page=4&per_page=15", returns: ["result"], total: 62)
|
43
|
+
collection = connection.get_multiple(model, "foos", page: 4, per_page: 15)
|
44
|
+
|
45
|
+
expect(collection).to be_instance_of(PaginatedCollection)
|
46
|
+
expect(collection.total).to eq 62
|
47
|
+
expect(collection.current_page).to eq 4
|
48
|
+
expect(collection.per_page).to eq 15
|
49
|
+
end
|
50
|
+
|
51
|
+
it "raises WordpressClient::TimeoutError when requests time out" do
|
52
|
+
stub_request(:get, /./).to_timeout
|
53
|
+
expect { connection.get(model, "foo") }.to raise_error(TimeoutError)
|
54
|
+
expect { connection.get_multiple(model, "foo") }.to raise_error(TimeoutError)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "raises ServerError if response is invalid JSON" do
|
58
|
+
stub_get(/./, body: "[")
|
59
|
+
expect { connection.get(model, "foo") }.to raise_error(ServerError, /parse/)
|
60
|
+
expect { connection.get_multiple(model, "foo") }.to raise_error(ServerError, /parse/)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "raises ServerError if response is not application/json" do
|
64
|
+
stub_get(/./, content_type: "text/plain")
|
65
|
+
expect { connection.get(model, "foo") }.to raise_error(ServerError, /plain/)
|
66
|
+
expect { connection.get_multiple(model, "foo") }.to raise_error(ServerError, /plain/)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "raises NotFoundError if response is 404" do
|
70
|
+
stub_get(/./, status: 404)
|
71
|
+
expect { connection.get(model, "foo") }.to raise_error(NotFoundError)
|
72
|
+
expect { connection.get_multiple(model, "foo") }.to raise_error(NotFoundError)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "creating" do
|
77
|
+
it "can create models" do
|
78
|
+
stub_successful_post_with_redirect(
|
79
|
+
"#{base_url}/foos", {title: "Bar"}, redirects_to: "#{base_url}/foos/1"
|
80
|
+
)
|
81
|
+
stub_get("#{base_url}/foos/1", returns: {id: 1, title: "Bar"})
|
82
|
+
|
83
|
+
expect(model).to receive(:parse).with(
|
84
|
+
"id" => 1, "title" => "Bar"
|
85
|
+
).and_return(model_instance)
|
86
|
+
|
87
|
+
response = connection.create(model, "foos", title: "Bar")
|
88
|
+
expect(response).to eq model_instance
|
89
|
+
end
|
90
|
+
|
91
|
+
it "can ignore the response" do
|
92
|
+
stub_successful_post_with_redirect(
|
93
|
+
"#{base_url}/foos", {title: "Bar"}, redirects_to: "#{base_url}/foos/1"
|
94
|
+
)
|
95
|
+
|
96
|
+
response = connection.create_without_response("foos", title: "Bar")
|
97
|
+
expect(response).to be true
|
98
|
+
end
|
99
|
+
|
100
|
+
it "can pass extra parameters when following redirect" do
|
101
|
+
stub_successful_post_with_redirect(
|
102
|
+
"#{base_url}/foos", {title: "Bar"}, redirects_to: "#{base_url}/foos/1"
|
103
|
+
)
|
104
|
+
redirect = stub_get("#{base_url}/foos/1?extra=param", returns: {})
|
105
|
+
|
106
|
+
connection.create(model, "foos", {title: "Bar"}, redirect_params: {extra: "param"})
|
107
|
+
expect(redirect).to have_been_made
|
108
|
+
end
|
109
|
+
|
110
|
+
it "raises NotFoundError if response is 400 with rest_post_invalid_id as error code" do
|
111
|
+
stub_failing_post(/./, returns: json_fixture("invalid-post-id.json"), status: 400)
|
112
|
+
|
113
|
+
expect { connection.create(model, "foo", {}) }.to raise_error(NotFoundError, /post id/i)
|
114
|
+
expect { connection.create_without_response("foo", {}) }.to raise_error(NotFoundError)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "raises ValidationError on any other 400 responses" do
|
118
|
+
stub_failing_post(/./, returns: json_fixture("validation-error.json"), status: 400)
|
119
|
+
|
120
|
+
expect {
|
121
|
+
connection.create(model, "foo", {})
|
122
|
+
}.to raise_error(ValidationError, /status is not one of/)
|
123
|
+
|
124
|
+
expect {
|
125
|
+
connection.create_without_response("foo", {})
|
126
|
+
}.to raise_error(ValidationError, /status is not one of/)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "patching" do
|
131
|
+
it "can patch models" do
|
132
|
+
stub_patch("#{base_url}/foos/1", {title: "Bar"}, returns: {id: 1, title: "Bar"})
|
133
|
+
|
134
|
+
expect(model).to receive(:parse).with(
|
135
|
+
"id" => 1, "title" => "Bar"
|
136
|
+
).and_return(model_instance)
|
137
|
+
|
138
|
+
response = connection.patch(model, "foos/1", title: "Bar")
|
139
|
+
expect(response).to eq model_instance
|
140
|
+
end
|
141
|
+
|
142
|
+
it "can ignore responses" do
|
143
|
+
stub_patch("#{base_url}/foos/1", {title: "Bar"}, returns: {id: 1, title: "Bar"})
|
144
|
+
response = connection.patch_without_response("foos/1", title: "Bar")
|
145
|
+
expect(response).to be true
|
146
|
+
end
|
147
|
+
|
148
|
+
it "raises NotFoundError if response is 400 with rest_post_invalid_id as error code" do
|
149
|
+
stub_patch(/./, {}, returns: json_fixture("invalid-post-id.json"), status: 400)
|
150
|
+
expect { connection.patch(model, "foo", {}) }.to raise_error(NotFoundError, /post id/i)
|
151
|
+
expect { connection.patch_without_response("foo", {}) }.to raise_error(NotFoundError)
|
152
|
+
end
|
153
|
+
|
154
|
+
it "raises ValidationError on any other 400 responses" do
|
155
|
+
stub_patch(/./, {}, returns: json_fixture("validation-error.json"), status: 400)
|
156
|
+
|
157
|
+
expect {
|
158
|
+
connection.patch(model, "foo", {})
|
159
|
+
}.to raise_error(ValidationError, /status is not one of/)
|
160
|
+
|
161
|
+
expect {
|
162
|
+
connection.patch_without_response("foo", {})
|
163
|
+
}.to raise_error(ValidationError, /status is not one of/)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
describe "deleting" do
|
168
|
+
it "can delete paths" do
|
169
|
+
encoding = "".encoding
|
170
|
+
|
171
|
+
stub_request(:delete, "#{base_url}/foos/1").with(
|
172
|
+
headers: {"content-type" => "application/json; charset=#{encoding}"},
|
173
|
+
body: {"force" => true}.to_json,
|
174
|
+
).to_return(
|
175
|
+
headers: {"content-type" => "application/json; charset=utf-8"},
|
176
|
+
body: {status: "Heyhoo! Nice one!"}.to_json,
|
177
|
+
)
|
178
|
+
|
179
|
+
response = connection.delete("foos/1", force: true)
|
180
|
+
expect(response).to be true
|
181
|
+
end
|
182
|
+
|
183
|
+
it "raises ValidationError on 400 responses" do
|
184
|
+
stub_request(:delete, /./).to_return(
|
185
|
+
status: 400,
|
186
|
+
body: "{}",
|
187
|
+
headers: {"content-type" => "application/json; charset=utf-8"},
|
188
|
+
)
|
189
|
+
|
190
|
+
expect {
|
191
|
+
connection.delete("foo", {})
|
192
|
+
}.to raise_error(ValidationError)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "uploading" do
|
197
|
+
it "posts the given IO and returns the resulting model" do
|
198
|
+
stub_request(:post, "#{base_url}/files").with(
|
199
|
+
headers: {
|
200
|
+
"content-length" => "11",
|
201
|
+
"content-type" => "text/plain",
|
202
|
+
# WP API does not parse normal Content-Disposition and instead ops
|
203
|
+
# to using their own format:
|
204
|
+
# https://github.com/WP-API/WP-API/issues/1744
|
205
|
+
"content-disposition" => 'filename=foo.txt',
|
206
|
+
},
|
207
|
+
body: "hello world",
|
208
|
+
).to_return(
|
209
|
+
status: 201, # Created
|
210
|
+
headers: {"Location" => "#{base_url}/files/67"}
|
211
|
+
)
|
212
|
+
stub_get("#{base_url}/files/67", returns: {id: 67})
|
213
|
+
|
214
|
+
model_instance = double("some model instance")
|
215
|
+
model = double("some model")
|
216
|
+
|
217
|
+
expect(model).to receive(:parse).with("id" => 67).and_return model_instance
|
218
|
+
|
219
|
+
result = connection.upload(
|
220
|
+
model, "files", StringIO.new("hello world"), mime_type: "text/plain", filename: "foo.txt"
|
221
|
+
)
|
222
|
+
|
223
|
+
expect(result).to eq model_instance
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def stub_get(
|
228
|
+
path,
|
229
|
+
returns: {},
|
230
|
+
status: 200,
|
231
|
+
body: returns.to_json,
|
232
|
+
total: nil,
|
233
|
+
content_type: "application/json"
|
234
|
+
)
|
235
|
+
headers = {"content-type" => "#{content_type}; charset=utf-8"}
|
236
|
+
headers["X-WP-Total"] = total.to_s if total
|
237
|
+
|
238
|
+
stub_request(:get, path).to_return(status: status, body: body, headers: headers)
|
239
|
+
end
|
240
|
+
|
241
|
+
def stub_successful_post_with_redirect(path, data, redirects_to:)
|
242
|
+
stub_request(:post, path).with(
|
243
|
+
headers: {"content-type" => "application/json; charset=#{"".encoding}"},
|
244
|
+
body: data.to_json,
|
245
|
+
).to_return(
|
246
|
+
status: 201, # Created
|
247
|
+
headers: {"Location" => redirects_to}
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
def stub_failing_post(path, returns:, status:)
|
252
|
+
stub_request(:post, path).to_return(
|
253
|
+
status: status,
|
254
|
+
body: returns.to_json,
|
255
|
+
headers: {"content-type" => "application/json; charset=utf-8"},
|
256
|
+
)
|
257
|
+
end
|
258
|
+
|
259
|
+
def stub_patch(path, data, returns:, status: 200)
|
260
|
+
stub_request(:patch, path).with(
|
261
|
+
headers: {"content-type" => "application/json; charset=#{"".encoding}"},
|
262
|
+
body: data.to_json,
|
263
|
+
).to_return(
|
264
|
+
status: status,
|
265
|
+
headers: {"content-type" => "application/json; charset=utf-8"},
|
266
|
+
body: returns.to_json,
|
267
|
+
)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
FROM appcontainers/wordpress
|
2
|
+
|
3
|
+
# base image only contains American timezones
|
4
|
+
RUN yum install -y tzdata
|
5
|
+
|
6
|
+
ENV APP_NAME testapp.com
|
7
|
+
ENV APACHE_SVRALIAS www.testapp.com localhost
|
8
|
+
ENV MYSQL_SERVER localhost
|
9
|
+
ENV MYSQL_CLIENT localhost
|
10
|
+
ENV MYSQL_PASS P@ssw0rd
|
11
|
+
ENV MYSQL_DB testapp
|
12
|
+
ENV APP_USER admin
|
13
|
+
ENV APP_PASS P@ssw0rd
|
14
|
+
ENV WP_KEY ILoveFlappyjacks
|
15
|
+
|
16
|
+
# Restore a copy of a set up database on first boot
|
17
|
+
COPY dbdump.sql.gz /tmp/dbdump.sql.gz
|
18
|
+
COPY restore-dbdump.sh /tmp/.restore-dbdump.sh
|
19
|
+
RUN chmod +x /tmp/.restore-dbdump.sh && \
|
20
|
+
echo "if [ -f /tmp/.restore-dbdump.sh ]; then /tmp/.restore-dbdump.sh; rm -fr /tmp/.restore-dbdump.sh; fi" >> /root/.bashrc
|
21
|
+
|
22
|
+
### Install API and API Basic Auth plugins
|
23
|
+
|
24
|
+
# We need tar to unpack the WP plugins
|
25
|
+
RUN yum install -y tar
|
26
|
+
|
27
|
+
# WP API
|
28
|
+
# Get download link from https://wordpress.org/plugins/rest-api/
|
29
|
+
RUN curl -SL -o /tmp/rest-api.zip https://downloads.wordpress.org/plugin/rest-api.2.0-beta8.zip \
|
30
|
+
&& unzip /tmp/rest-api.zip -d /var/www/html/wordpress/wp-content/plugins/ \
|
31
|
+
&& rm /tmp/rest-api.zip
|
32
|
+
|
33
|
+
# Basic Auth
|
34
|
+
# Get download link from GitHub or something.
|
35
|
+
RUN curl -SL https://github.com/WP-API/Basic-Auth/archive/master.tar.gz \
|
36
|
+
| tar -xzC /var/www/html/wordpress/wp-content/plugins/ \
|
37
|
+
&& mv /var/www/html/wordpress/wp-content/plugins/Basic-Auth* /var/www/html/wordpress/wp-content/plugins/basic-auth
|
38
|
+
|
39
|
+
# Make pretty permalinks work so API is accessible
|
40
|
+
COPY htaccess /var/www/html/wordpress/.htaccess
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# How this was built
|
2
|
+
|
3
|
+
## dbdump
|
4
|
+
|
5
|
+
If you need to regenerate the dbdump, remove the part where the file is copied and restored from the `Dockerfile`, then build and start the image.
|
6
|
+
|
7
|
+
```bash
|
8
|
+
docker build -t wpclient-test .
|
9
|
+
docker run -it -p 8181:80 wpclient-test
|
10
|
+
```
|
11
|
+
|
12
|
+
You'll get a prompt inside the container. Open your browser and go to the newly booted application (`localhost:8181` if you have native Docker; otherwise go to your `$DOCKER_HOST_IP:8181` URL – see `echo $DOCKER_HOST` in your local shell).
|
13
|
+
|
14
|
+
You'll be greeted by the Wordpress installer. Fill in everything and complete the installation.
|
15
|
+
|
16
|
+
Then, **in your container's terminal**, run the following command:
|
17
|
+
|
18
|
+
```bash
|
19
|
+
mysqldump -u "$MYSQL_USER" --password="$MYSQL_PASS" --host="$MYSQL_HOST" "$MYSQL_DB" | gzip -9 > /tmp/dbdump.sql.gz
|
20
|
+
```
|
21
|
+
|
22
|
+
You can then copy the file to your host using the `docker cp` command:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
docker ps | grep wpclient-test
|
26
|
+
# See the container ID or name of your running container
|
27
|
+
docker cp THE-CONTAINER-ID:/tmp/dbdump.sql.gz .
|
28
|
+
```
|
29
|
+
|
30
|
+
You can then shut down your container by logging out of the container terminal.
|
31
|
+
|
32
|
+
Restore the DB loading code from the `Dockerfile`, commit this file to the repo and rebuild everything and verify that Wordpress is still set up correctly when the dump is restored.
|
33
|
+
|
34
|
+
`spec/docker/restore-dbdump.sh` hard codes an expectation that the IP in your
|
35
|
+
datadump is a specfic IP. So you will need to change that hard coded
|
36
|
+
expectation to match the new IP used in your data dump. You can find out what
|
37
|
+
that IP is by examining the dumo but it is probably the value set in `$DOCKER_HOST`.
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
service mysqld start
|
3
|
+
|
4
|
+
gunzip -c /tmp/dbdump.sql.gz | \
|
5
|
+
sed "s/192\.168\.99\.100:8181/${WORDPRESS_HOST:-localhost:8181}/g" | \
|
6
|
+
mysql \
|
7
|
+
--user="$MYSQL_USER" \
|
8
|
+
--password="$MYSQL_PASS" \
|
9
|
+
--host="$MYSQL_SERVER" \
|
10
|
+
--batch \
|
11
|
+
"$MYSQL_DB"
|
12
|
+
|
13
|
+
rm /tmp/dbdump.sql.gz
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":1,"count":1,"description":"","link":"http:\/\/192.168.99.100:8080\/category\/uncategorized\/","name":"Uncategorized","slug":"uncategorized","taxonomy":"category","parent":0,"_links":{"self":[{"href":"http:\/\/192.168.99.100:8080\/wp-json\/wp\/v2\/terms\/category\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8080\/wp-json\/wp\/v2\/terms\/category"}]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":5,"date":"2015-11-17T14:51:26","guid":{"rendered":"http:\/\/example.com\/wp-content\/uploads\/2015\/11\/thoughtful.jpg"},"modified":"2015-11-17T14:51:26","modified_gmt":"2015-11-17T14:51:26","slug":"thoughtful","type":"attachment","link":"http:\/\/example.com\/?attachment_id=5","title":{"rendered":"thoughtful"},"author":1,"comment_status":"open","ping_status":"closed","alt_text":"","caption":"","description":"","media_type":"image","media_details":{"width":600,"height":800,"file":"2015\/11\/thoughtful.jpg","image_meta":{"aperture":0,"credit":"","camera":"","caption":"","created_timestamp":0,"copyright":"\u00a9 JoeDaEskimo - http:\/\/www.redbubble.com\/people\/JoeDaEskim","focal_length":0,"iso":0,"shutter_speed":0,"title":"","orientation":0},"sizes":{}},"post":null,"source_url":"http:\/\/example.com\/wp-content\/uploads\/2015\/11\/thoughtful.jpg","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/media\/5"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/media"}],"author":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/comments?post_id=5"}]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"code":"rest_post_invalid_id","message":"Invalid post ID.","data":{"status":404}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":4,"date":null,"guid":{"rendered":"http:\/\/192.168.99.100:8181\/?p=4"},"modified":null,"modified_gmt":null,"slug":"","type":"post","link":"http:\/\/192.168.99.100:8181\/?p=4","title":{"rendered":"Metadata creation"},"content":{"rendered":""},"excerpt":{"rendered":""},"author":1,"featured_image":0,"comment_status":"open","ping_status":"open","sticky":false,"format":"standard","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts"}],"author":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments?post_id=4"}],"version-history":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/revisions"}],"https:\/\/api.w.org\/attachment":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/media?post_parent=4"}],"https:\/\/api.w.org\/term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/category"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/tag"},{"taxonomy":"post_format","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/post_format"}],"https:\/\/api.w.org\/meta":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/meta"}]},"_embedded":{"author":[{"avatar_urls":{"24":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=24&d=mm&r=g","48":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=96&d=mm&r=g"},"description":"","id":1,"link":"http:\/\/192.168.99.100:8181\/author\/test\/","name":"test","url":"","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users"}]}}],"replies":[[{"id":1,"parent":0,"author":0,"author_name":"Mr WordPress","author_url":"https:\/\/wordpress.org\/","author_avatar_urls":{"24":"http:\/\/1.gravatar.com\/avatar\/?s=24&d=mm&r=g","48":"http:\/\/1.gravatar.com\/avatar\/?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g"},"date":"2015-11-03T07:47:41","content":{"rendered":"<p>Hi, this is a comment.<br \/>\nTo delete a comment, just log in and view the post's comments. There you will have the option to edit or delete them.<\/p>\n"},"link":"http:\/\/192.168.99.100:8181\/2015\/11\/03\/hello-world\/#comment-1","type":"comment","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments"}],"up":[{"embeddable":true,"post_type":"post","href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/1"}]}}]],"https:\/\/api.w.org\/term":[[{"id":1,"link":"http:\/\/192.168.99.100:8181\/category\/uncategorized\/","name":"Uncategorized","slug":"uncategorized","taxonomy":"category","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/terms\/category\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/terms\/category"}]}}],[],[{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}]],"https:\/\/api.w.org\/meta":[[{"code":"rest_forbidden","message":"Sorry, you cannot view the meta for this post.","data":{"status":403}}]]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":4,"date":null,"guid":{"rendered":"http:\/\/192.168.99.100:8181\/?p=4"},"modified":null,"modified_gmt":null,"slug":"","type":"post","link":"http:\/\/192.168.99.100:8181\/?p=4","title":{"rendered":"Metadata creation"},"content":{"rendered":""},"excerpt":{"rendered":""},"author":1,"featured_image":0,"comment_status":"open","ping_status":"open","sticky":false,"format":"standard","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts"}],"author":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments?post_id=4"}],"version-history":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/revisions"}],"https:\/\/api.w.org\/attachment":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/media?post_parent=4"}],"https:\/\/api.w.org\/term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/category"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/tag"},{"taxonomy":"post_format","embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/terms\/post_format"}],"https:\/\/api.w.org\/meta":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/4\/meta"}]},"_embedded":{"author":[{"avatar_urls":{"24":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=24&d=mm&r=g","48":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=96&d=mm&r=g"},"description":"","id":1,"link":"http:\/\/192.168.99.100:8181\/author\/test\/","name":"test","url":"","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/users"}]}}],"replies":[[{"id":1,"parent":0,"author":0,"author_name":"Mr WordPress","author_url":"https:\/\/wordpress.org\/","author_avatar_urls":{"24":"http:\/\/1.gravatar.com\/avatar\/?s=24&d=mm&r=g","48":"http:\/\/1.gravatar.com\/avatar\/?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g"},"date":"2015-11-03T07:47:41","content":{"rendered":"<p>Hi, this is a comment.<br \/>\nTo delete a comment, just log in and view the post's comments. There you will have the option to edit or delete them.<\/p>\n"},"link":"http:\/\/192.168.99.100:8181\/2015\/11\/03\/hello-world\/#comment-1","type":"comment","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/comments"}],"up":[{"embeddable":true,"post_type":"post","href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/posts\/1"}]}}]],"https:\/\/api.w.org\/term":[[{"id":1,"link":"http:\/\/192.168.99.100:8181\/category\/uncategorized\/","name":"Uncategorized","slug":"uncategorized","taxonomy":"category","_links":{"self":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/terms\/category\/1"}],"collection":[{"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/v2\/terms\/category"}]}}],[],[{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}]],"https:\/\/api.w.org\/meta":[[{"id":2,"key":"foo","value":"bar","_links":{"about":[{"embeddable":true,"href":"http:\/\/192.168.99.100:8181\/wp-json\/wp\/posts\/4"}]}}]]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":1,"date":"2015-11-03T07:47:41","guid":{"rendered":"http:\/\/example.com\/?p=1"},"modified":"2015-11-17T09:18:22","modified_gmt":"2015-11-17T09:18:22","slug":"hello-world","type":"post","link":"http:\/\/example.com\/2015\/11\/03\/hello-world\/","title":{"rendered":"Hello world!"},"content":{"rendered":"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"},"excerpt":{"rendered":"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"},"author":1,"featured_image":0,"comment_status":"open","ping_status":"open","sticky":false,"format":"standard","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts"}],"author":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/comments?post_id=1"}],"version-history":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1\/revisions"}],"https:\/\/api.w.org\/attachment":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/media?post_parent=1"}],"https:\/\/api.w.org\/term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/example.com\/wp-json\/wp\/v2\/posts\/1\/terms\/category"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1\/terms\/tag"},{"taxonomy":"post_format","embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1\/terms\/post_format"}],"https:\/\/api.w.org\/meta":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1\/meta"}]},"_embedded":{"author":[{"avatar_urls":{"24":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=24&d=mm&r=g","48":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/55502f40dc8b7c769880b10874abc9d0?s=96&d=mm&r=g"},"description":"","id":1,"link":"http:\/\/example.com\/author\/test\/","name":"test","url":"","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/users\/1"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/users"}]}}],"replies":[[{"id":1,"parent":0,"author":0,"author_name":"Mr WordPress","author_url":"http:\/\/wordpress.org\/","author_avatar_urls":{"24":"http:\/\/1.gravatar.com\/avatar\/?s=24&d=mm&r=g","48":"http:\/\/2.gravatar.com\/avatar\/?s=48&d=mm&r=g","96":"http:\/\/2.gravatar.com\/avatar\/?s=96&d=mm&r=g"},"date":"2015-11-03T07:47:41","content":{"rendered":"<p>Hi, this is a comment.<br \/>\nTo delete a comment, just log in and view the post's comments. There you will have the option to edit or delete them.<\/p>\n"},"link":"http:\/\/example.com\/2015\/11\/03\/hello-world\/#comment-1","type":"comment","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/comments\/1"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/comments"}],"up":[{"embeddable":true,"post_type":"post","href":"http:\/\/example.com\/wp-json\/wp\/v2\/posts\/1"}]}}]],"https:\/\/api.w.org\/term":[[{"id":1,"link":"http:\/\/example.com\/category\/uncategorized\/","name":"Uncategorized","slug":"uncategorized","taxonomy":"category","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/terms\/category\/1"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/terms\/category"}]}}],[{"id":2,"link":"http:\/\/example.com\/tag\/foo\/","name":"Foo","slug":"foo","taxonomy":"post_tag","_links":{"self":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/terms\/tag\/2"}],"collection":[{"href":"http:\/\/example.com\/wp-json\/wp\/v2\/terms\/tag"}]}}],[{"code":"rest_no_route","message":"No route was found matching the URL and request method","data":{"status":404}}]],"https:\/\/api.w.org\/meta":[[{"id":3,"key":"Some test","value":"Definitely","_links":{"about":[{"embeddable":true,"href":"http:\/\/example.com\/wp-json\/wp\/posts\/1"}]}}]]}}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"id":2,"count":1,"description":"","link":"http:\/\/192.168.99.100:8080\/tag\/foo\/","name":"Foo","slug":"foo","taxonomy":"post_tag","_links":{"self":[{"href":"http:\/\/192.168.99.100:8080\/wp-json\/wp\/v2\/terms\/tag\/2"}],"collection":[{"href":"http:\/\/192.168.99.100:8080\/wp-json\/wp\/v2\/terms\/tag"}]}}
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
{"code":"rest_invalid_param","message":"Invalid parameter(s): status (status is not one of publish, future, draft, pending, private)","data":{"status":400,"params":["status (status is not one of publish, future, draft, pending, private)"]}}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Attachments" do
|
4
|
+
setup_integration_client
|
5
|
+
|
6
|
+
it "can be created" do
|
7
|
+
media = open_fixture("thoughtful.jpg") do |io|
|
8
|
+
client.upload(io, mime_type: "image/jpeg", filename: "thoughtful.jpg")
|
9
|
+
end
|
10
|
+
|
11
|
+
expect(media).to be_instance_of(WordpressClient::Media)
|
12
|
+
|
13
|
+
expect(client.find_media(media.id)).to be_instance_of(WordpressClient::Media)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can be created from a file on disk" do
|
17
|
+
path = fixture_path("thoughtful.jpg")
|
18
|
+
media = client.upload_file(path, mime_type: "image/jpeg")
|
19
|
+
|
20
|
+
expect(media).to be_instance_of(WordpressClient::Media)
|
21
|
+
|
22
|
+
expect(client.find_media(media.id)).to be_instance_of(WordpressClient::Media)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can be updated" do
|
26
|
+
media = find_or_create_attachment
|
27
|
+
updated = client.update_media(media.id, title: "Totally updated media")
|
28
|
+
expect(updated.title_html).to eq "Totally updated media"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can be listed" do
|
32
|
+
find_or_create_attachment
|
33
|
+
|
34
|
+
media = client.media(per_page: 1)
|
35
|
+
|
36
|
+
expect(media.size).to be > 0
|
37
|
+
expect(media.first).to be_instance_of(WordpressClient::Media)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "uses HTML for the title" do
|
41
|
+
media = find_or_create_attachment
|
42
|
+
updated = client.update_media(media.id, title: "Images & paint")
|
43
|
+
expect(updated.title_html).to eq "Images & paint"
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_or_create_attachment
|
47
|
+
client.media(per_page: 1).first || open_fixture("thoughtful.jpg") do |io|
|
48
|
+
client.upload(io, mime_type: "image/jpeg", filename: "thoughtful.jpg")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|