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,17 @@
|
|
1
|
+
module WordpressClient
|
2
|
+
module RestParser
|
3
|
+
private
|
4
|
+
def rendered(name)
|
5
|
+
(data[name] || {})["rendered"]
|
6
|
+
end
|
7
|
+
|
8
|
+
def read_date(name)
|
9
|
+
# Try to read UTC time first
|
10
|
+
if (gmt_time = data["#{name}_gmt"])
|
11
|
+
Time.iso8601("#{gmt_time}Z")
|
12
|
+
elsif (local_time = data[name])
|
13
|
+
Time.iso8601(local_time)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module WordpressClient
|
2
|
+
class Term
|
3
|
+
attr_reader :id, :name_html, :slug
|
4
|
+
|
5
|
+
def self.parse(data)
|
6
|
+
new(
|
7
|
+
id: data.fetch("id"),
|
8
|
+
name_html: data.fetch("name"),
|
9
|
+
slug: data.fetch("slug"),
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(id:, name_html:, slug:)
|
14
|
+
@id = id
|
15
|
+
@name_html = name_html
|
16
|
+
@slug = slug
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
if other.is_a? Term
|
21
|
+
other.class == self.class &&
|
22
|
+
other.id == id &&
|
23
|
+
other.name_html == name_html &&
|
24
|
+
other.slug == slug
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
"#<#{self.class} ##{id} #{name_html.inspect} (#{slug})>"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,411 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tmpdir"
|
3
|
+
|
4
|
+
module WordpressClient
|
5
|
+
describe Client do
|
6
|
+
subject(:client) { Client.new(connection) }
|
7
|
+
let(:connection) { instance_double(Connection) }
|
8
|
+
|
9
|
+
describe "finding posts" do
|
10
|
+
it "has working pagination" do
|
11
|
+
expect(connection).to receive(:get_multiple).with(
|
12
|
+
Post, "posts", hash_including(page: 2, per_page: 13)
|
13
|
+
).and_return []
|
14
|
+
|
15
|
+
expect(client.posts(per_page: 13, page: 2)).to eq []
|
16
|
+
end
|
17
|
+
|
18
|
+
it "embeds linked resources" do
|
19
|
+
expect(connection).to receive(:get_multiple).with(
|
20
|
+
Post, "posts", hash_including(_embed: nil)
|
21
|
+
).and_return []
|
22
|
+
|
23
|
+
expect(client.posts).to eq []
|
24
|
+
end
|
25
|
+
|
26
|
+
it "can filter on category slugs" do
|
27
|
+
expect(connection).to receive(:get_multiple).with(
|
28
|
+
Post, "posts", hash_including(filter: {category_name: "my-cat"})
|
29
|
+
).and_return []
|
30
|
+
|
31
|
+
expect(client.posts(category_slug: "my-cat")).to eq []
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can filter on tag slugs" do
|
35
|
+
expect(connection).to receive(:get_multiple).with(
|
36
|
+
Post, "posts", hash_including(filter: {tag: "my-cat"})
|
37
|
+
).and_return []
|
38
|
+
|
39
|
+
expect(client.posts(tag_slug: "my-cat")).to eq []
|
40
|
+
end
|
41
|
+
|
42
|
+
it "can filter on tag and category slugs" do
|
43
|
+
expect(connection).to receive(:get_multiple).with(
|
44
|
+
Post, "posts", hash_including(filter: {tag: "my-cat", category_name: "my-dog"})
|
45
|
+
).and_return []
|
46
|
+
|
47
|
+
expect(client.posts(tag_slug: "my-cat", category_slug: "my-dog")).to eq []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "fetching a single post" do
|
52
|
+
it "embeds linked resources" do
|
53
|
+
post = instance_double(Post)
|
54
|
+
|
55
|
+
expect(connection).to receive(:get).with(
|
56
|
+
Post, "posts/5", _embed: nil, context: "edit"
|
57
|
+
).and_return post
|
58
|
+
|
59
|
+
expect(client.find_post(5)).to eq post
|
60
|
+
end
|
61
|
+
|
62
|
+
it "can find using a slug" do
|
63
|
+
post = instance_double(Post)
|
64
|
+
|
65
|
+
expect(connection).to receive(:get_multiple).with(
|
66
|
+
Post, "posts", hash_including(filter: {name: "my-slug"})
|
67
|
+
).and_return [post]
|
68
|
+
|
69
|
+
expect(client.find_by_slug("my-slug")).to eq post
|
70
|
+
end
|
71
|
+
|
72
|
+
it "raises NotFoundError when trying to find by slug yields no posts" do
|
73
|
+
expect(connection).to receive(:get_multiple).with(
|
74
|
+
Post, "posts", hash_including(filter: {name: "my-slug"}, per_page: 1)
|
75
|
+
).and_return []
|
76
|
+
|
77
|
+
expect {
|
78
|
+
client.find_by_slug("my-slug")
|
79
|
+
}.to raise_error(NotFoundError, /my-slug/)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "creating a post" do
|
84
|
+
it "embeds linked resources when following redirect" do
|
85
|
+
post = instance_double(Post, id: 5)
|
86
|
+
attributes = {title: "Foo"}
|
87
|
+
|
88
|
+
expect(connection).to receive(:create).with(
|
89
|
+
Post, "posts", attributes, redirect_params: {_embed: nil}
|
90
|
+
).and_return post
|
91
|
+
|
92
|
+
# We don't expect here as the `create` call below could be enough, but
|
93
|
+
# it's also very possible that we need to fetch the post again after
|
94
|
+
# doing other things to it.
|
95
|
+
allow(connection).to receive(:get).with(
|
96
|
+
Post, "posts/5", hash_including(_embed: nil)
|
97
|
+
).and_return(post)
|
98
|
+
|
99
|
+
expect(client.create_post(attributes)).to eq post
|
100
|
+
end
|
101
|
+
|
102
|
+
it "adds metadata to the post" do
|
103
|
+
post = instance_double(Post, id: 5)
|
104
|
+
allow(connection).to receive(:create).and_return(post)
|
105
|
+
|
106
|
+
expect(ReplaceMetadata).to receive(:apply).with(
|
107
|
+
connection, post, {"hello" => "world"}
|
108
|
+
).and_return(0)
|
109
|
+
|
110
|
+
client.create_post(title: "Foo", meta: {"hello" => "world"})
|
111
|
+
end
|
112
|
+
|
113
|
+
it "sets categories of the post" do
|
114
|
+
post = instance_double(Post, id: 5)
|
115
|
+
allow(connection).to receive(:create).and_return(post)
|
116
|
+
|
117
|
+
expect(ReplaceTerms).to receive(:apply_categories).with(
|
118
|
+
connection, post, [1, 3, 7]
|
119
|
+
).and_return(0)
|
120
|
+
|
121
|
+
client.create_post(title: "Foo", category_ids: [1, 3, 7])
|
122
|
+
end
|
123
|
+
|
124
|
+
it "sets tags of the post" do
|
125
|
+
post = instance_double(Post, id: 5)
|
126
|
+
allow(connection).to receive(:create).and_return(post)
|
127
|
+
|
128
|
+
expect(ReplaceTerms).to receive(:apply_tags).with(
|
129
|
+
connection, post, [1, 3, 7]
|
130
|
+
).and_return(0)
|
131
|
+
|
132
|
+
client.create_post(title: "Foo", tag_ids: [1, 3, 7])
|
133
|
+
end
|
134
|
+
|
135
|
+
it "refreshes the post if terms or categories changed" do
|
136
|
+
post = instance_double(Post, id: 5)
|
137
|
+
allow(connection).to receive(:create).and_return(post)
|
138
|
+
|
139
|
+
expect(ReplaceTerms).to receive(:apply_tags).and_return(1)
|
140
|
+
expect(ReplaceTerms).to receive(:apply_categories).and_return(1)
|
141
|
+
expect(ReplaceMetadata).to receive(:apply).and_return(1)
|
142
|
+
|
143
|
+
expect(connection).to receive(:get).with(
|
144
|
+
Post, "posts/5", hash_including(_embed: nil)
|
145
|
+
).and_return(post)
|
146
|
+
|
147
|
+
client.create_post(title: "Foo", tag_ids: [], category_ids: [], meta: {})
|
148
|
+
end
|
149
|
+
|
150
|
+
it "does not refresh the post if neither terms nor categories changed" do
|
151
|
+
post = instance_double(Post, id: 5)
|
152
|
+
allow(connection).to receive(:create).and_return(post)
|
153
|
+
|
154
|
+
expect(ReplaceTerms).to receive(:apply_tags).and_return(0)
|
155
|
+
expect(ReplaceTerms).to receive(:apply_categories).and_return(0)
|
156
|
+
expect(ReplaceMetadata).to receive(:apply).and_return(0)
|
157
|
+
|
158
|
+
expect(connection).to_not receive(:get)
|
159
|
+
|
160
|
+
client.create_post(title: "Foo", tag_ids: [], category_ids: [], meta: {})
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe "updating a post" do
|
165
|
+
it "embeds linked resources" do
|
166
|
+
post = instance_double(Post)
|
167
|
+
|
168
|
+
expect(connection).to receive(:patch).with(
|
169
|
+
Post, "posts/5?_embed", hash_including(title: "Foo")
|
170
|
+
).and_return(post)
|
171
|
+
|
172
|
+
expect(client.update_post(5, title: "Foo")).to eq post
|
173
|
+
end
|
174
|
+
|
175
|
+
it "adds metadata to the post" do
|
176
|
+
post = instance_double(Post, id: 5)
|
177
|
+
allow(connection).to receive(:patch).and_return(post)
|
178
|
+
|
179
|
+
expect(ReplaceMetadata).to receive(:apply).with(
|
180
|
+
connection, post, {"hello" => "world"}
|
181
|
+
).and_return(0)
|
182
|
+
|
183
|
+
client.update_post(5, title: "Foo", meta: {"hello" => "world"})
|
184
|
+
end
|
185
|
+
|
186
|
+
it "changes categories of the post" do
|
187
|
+
post = instance_double(Post, id: 5)
|
188
|
+
allow(connection).to receive(:patch).and_return(post)
|
189
|
+
|
190
|
+
expect(ReplaceTerms).to receive(:apply_categories).with(
|
191
|
+
connection, post, [1, 3, 7]
|
192
|
+
).and_return(0)
|
193
|
+
|
194
|
+
client.update_post(5, title: "Foo", category_ids: [1, 3, 7])
|
195
|
+
end
|
196
|
+
|
197
|
+
it "changes tags of the post" do
|
198
|
+
post = instance_double(Post, id: 5)
|
199
|
+
allow(connection).to receive(:patch).and_return(post)
|
200
|
+
|
201
|
+
expect(ReplaceTerms).to receive(:apply_tags).with(
|
202
|
+
connection, post, [1, 3, 7]
|
203
|
+
).and_return(0)
|
204
|
+
|
205
|
+
client.update_post(5, title: "Foo", tag_ids: [1, 3, 7])
|
206
|
+
end
|
207
|
+
|
208
|
+
it "refreshes the post if terms or categories changed" do
|
209
|
+
post = instance_double(Post, id: 5)
|
210
|
+
allow(connection).to receive(:patch).and_return(post)
|
211
|
+
|
212
|
+
expect(ReplaceTerms).to receive(:apply_tags).and_return(1)
|
213
|
+
expect(ReplaceTerms).to receive(:apply_categories).and_return(1)
|
214
|
+
expect(ReplaceMetadata).to receive(:apply).and_return(1)
|
215
|
+
|
216
|
+
expect(connection).to receive(:get).with(
|
217
|
+
Post, "posts/5", hash_including(_embed: nil)
|
218
|
+
).and_return(post)
|
219
|
+
|
220
|
+
client.update_post(5, title: "Foo", tag_ids: [], category_ids: [], meta: {})
|
221
|
+
end
|
222
|
+
|
223
|
+
it "does not refresh the post if neither terms nor categories changed" do
|
224
|
+
post = instance_double(Post, id: 5)
|
225
|
+
allow(connection).to receive(:patch).and_return(post)
|
226
|
+
|
227
|
+
expect(ReplaceTerms).to receive(:apply_tags).and_return(0)
|
228
|
+
expect(ReplaceTerms).to receive(:apply_categories).and_return(0)
|
229
|
+
expect(ReplaceMetadata).to receive(:apply).and_return(0)
|
230
|
+
|
231
|
+
expect(connection).to_not receive(:get)
|
232
|
+
|
233
|
+
client.update_post(5, title: "Foo", tag_ids: [], category_ids: [], meta: {})
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "deleting posts" do
|
238
|
+
it "deletes a post without force by default" do
|
239
|
+
expect(connection).to receive(:delete).with(
|
240
|
+
"posts/1", {"force" => false}
|
241
|
+
).and_return true
|
242
|
+
|
243
|
+
expect(client.delete_post(1)).to eq true
|
244
|
+
end
|
245
|
+
|
246
|
+
it "deletes a post without force" do
|
247
|
+
expect(connection).to receive(:delete).with(
|
248
|
+
"posts/1", {"force" => false}
|
249
|
+
).and_return true
|
250
|
+
|
251
|
+
expect(client.delete_post(1, force: false)).to eq true
|
252
|
+
end
|
253
|
+
|
254
|
+
it "deletes a post with force" do
|
255
|
+
expect(connection).to receive(:delete).with(
|
256
|
+
"posts/1", {"force" => true}
|
257
|
+
).and_return true
|
258
|
+
|
259
|
+
expect(client.delete_post(1, force: true)).to eq true
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "categories" do
|
264
|
+
it "can be listed" do
|
265
|
+
expect(connection).to receive(:get_multiple).with(
|
266
|
+
Category, "terms/category", hash_including(page: 1, per_page: 10)
|
267
|
+
)
|
268
|
+
client.categories
|
269
|
+
|
270
|
+
expect(connection).to receive(:get_multiple).with(
|
271
|
+
Category, "terms/category", hash_including(page: 2, per_page: 60)
|
272
|
+
)
|
273
|
+
client.categories(page: 2, per_page: 60)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "can be found" do
|
277
|
+
category = instance_double(Category)
|
278
|
+
|
279
|
+
expect(connection).to receive(:get).with(
|
280
|
+
Category, "terms/category/12"
|
281
|
+
).and_return category
|
282
|
+
|
283
|
+
expect(client.find_category(12)).to eq category
|
284
|
+
end
|
285
|
+
|
286
|
+
it "can be created" do
|
287
|
+
category = instance_double(Category)
|
288
|
+
|
289
|
+
expect(connection).to receive(:create).with(
|
290
|
+
Category, "terms/category", name: "Foo"
|
291
|
+
).and_return category
|
292
|
+
|
293
|
+
expect(client.create_category(name: "Foo")).to eq category
|
294
|
+
end
|
295
|
+
|
296
|
+
it "can be updated" do
|
297
|
+
category = instance_double(Category)
|
298
|
+
|
299
|
+
expect(connection).to receive(:patch).with(
|
300
|
+
Category, "terms/category/45", name: "New"
|
301
|
+
).and_return category
|
302
|
+
|
303
|
+
expect(client.update_category(45, name: "New")).to eq category
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "tags" do
|
308
|
+
it "can be listed" do
|
309
|
+
expect(connection).to receive(:get_multiple).with(
|
310
|
+
Tag, "terms/tag", hash_including(page: 1, per_page: 10)
|
311
|
+
)
|
312
|
+
client.tags
|
313
|
+
|
314
|
+
expect(connection).to receive(:get_multiple).with(
|
315
|
+
Tag, "terms/tag", hash_including(page: 2, per_page: 60)
|
316
|
+
)
|
317
|
+
client.tags(page: 2, per_page: 60)
|
318
|
+
end
|
319
|
+
|
320
|
+
it "can be found" do
|
321
|
+
tag = instance_double(Tag)
|
322
|
+
|
323
|
+
expect(connection).to receive(:get).with(
|
324
|
+
Tag, "terms/tag/12"
|
325
|
+
).and_return tag
|
326
|
+
|
327
|
+
expect(client.find_tag(12)).to eq tag
|
328
|
+
end
|
329
|
+
|
330
|
+
it "can be created" do
|
331
|
+
tag = instance_double(Tag)
|
332
|
+
|
333
|
+
expect(connection).to receive(:create).with(
|
334
|
+
Tag, "terms/tag", name: "Foo"
|
335
|
+
).and_return tag
|
336
|
+
|
337
|
+
expect(client.create_tag(name: "Foo")).to eq tag
|
338
|
+
end
|
339
|
+
|
340
|
+
it "can be updated" do
|
341
|
+
tag = instance_double(Tag)
|
342
|
+
|
343
|
+
expect(connection).to receive(:patch).with(
|
344
|
+
Tag, "terms/tag/45", name: "New"
|
345
|
+
).and_return tag
|
346
|
+
|
347
|
+
expect(client.update_tag(45, name: "New")).to eq tag
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe "media" do
|
352
|
+
it "can be uploaded from IO objects" do
|
353
|
+
media = instance_double(Media)
|
354
|
+
io = double("io")
|
355
|
+
|
356
|
+
expect(connection).to receive(:upload).with(
|
357
|
+
Media, "media", io, mime_type: "text/plain", filename: "foo.txt"
|
358
|
+
).and_return media
|
359
|
+
|
360
|
+
expect(client.upload(io, mime_type: "text/plain", filename: "foo.txt")).to eq media
|
361
|
+
end
|
362
|
+
|
363
|
+
it "can be uploaded from files" do
|
364
|
+
media = instance_double(Media)
|
365
|
+
|
366
|
+
Dir.mktmpdir do |dir|
|
367
|
+
file = File.join(dir, "test.txt")
|
368
|
+
File.write(file, "hello world")
|
369
|
+
|
370
|
+
expect(connection).to receive(:upload) do |_, _, io, filename:, mime_type:|
|
371
|
+
expect(filename).to eq "test.txt"
|
372
|
+
expect(mime_type).to eq "text/plain"
|
373
|
+
|
374
|
+
expect(io.read).to eq "hello world"
|
375
|
+
media
|
376
|
+
end
|
377
|
+
|
378
|
+
expect(client.upload_file(file, mime_type: "text/plain")).to eq media
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
it "can be found" do
|
383
|
+
media = instance_double(Media)
|
384
|
+
|
385
|
+
expect(connection).to receive(:get).with(Media, "media/7").and_return(media)
|
386
|
+
|
387
|
+
expect(client.find_media(7)).to eq media
|
388
|
+
end
|
389
|
+
|
390
|
+
it "can be listed" do
|
391
|
+
media = instance_double(Media)
|
392
|
+
|
393
|
+
expect(connection).to receive(:get_multiple).with(
|
394
|
+
Media, "media", per_page: 10, page: 1
|
395
|
+
).and_return([media])
|
396
|
+
|
397
|
+
expect(client.media).to eq [media]
|
398
|
+
end
|
399
|
+
|
400
|
+
it "can be updated" do
|
401
|
+
media = instance_double(Media)
|
402
|
+
|
403
|
+
expect(connection).to receive(:patch).with(
|
404
|
+
Media, "media/7", title: "New"
|
405
|
+
).and_return(media)
|
406
|
+
|
407
|
+
expect(client.update_media(7, title: "New")).to eq media
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|