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,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
|