discourse_api 0.44.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +13 -17
  3. data/.gitignore +0 -19
  4. data/CHANGELOG.md +38 -7
  5. data/discourse_api.gemspec +5 -5
  6. data/examples/bookmark_topic.rb +15 -0
  7. data/examples/category.rb +3 -0
  8. data/examples/invite_users.rb +20 -2
  9. data/examples/manage_api_keys.rb +42 -0
  10. data/examples/notifications.rb +18 -0
  11. data/examples/topic_lists.rb +3 -0
  12. data/lib/discourse_api/api/api_key.rb +15 -9
  13. data/lib/discourse_api/api/categories.rb +41 -13
  14. data/lib/discourse_api/api/invite.rb +67 -2
  15. data/lib/discourse_api/api/notifications.rb +5 -2
  16. data/lib/discourse_api/api/private_messages.rb +10 -3
  17. data/lib/discourse_api/api/search.rb +1 -1
  18. data/lib/discourse_api/api/topics.rb +37 -2
  19. data/lib/discourse_api/api/users.rb +1 -1
  20. data/lib/discourse_api/client.rb +13 -1
  21. data/lib/discourse_api/error.rb +3 -0
  22. data/lib/discourse_api/version.rb +1 -1
  23. data/spec/discourse_api/api/api_key_spec.rb +59 -35
  24. data/spec/discourse_api/api/categories_spec.rb +90 -0
  25. data/spec/discourse_api/api/invite_spec.rb +123 -0
  26. data/spec/discourse_api/api/private_messages_spec.rb +4 -4
  27. data/spec/discourse_api/api/search_spec.rb +2 -2
  28. data/spec/discourse_api/api/topics_spec.rb +71 -0
  29. data/spec/discourse_api/client_spec.rb +15 -0
  30. data/spec/fixtures/api_key.json +12 -0
  31. data/spec/fixtures/list_api_keys.json +14 -0
  32. data/spec/fixtures/notification_success.json +3 -0
  33. data/spec/fixtures/retrieve_invite.json +116 -0
  34. data/spec/fixtures/top.json +108 -0
  35. data/spec/fixtures/topic_posts.json +1 -0
  36. metadata +24 -13
  37. data/spec/fixtures/api.json +0 -12
  38. data/spec/fixtures/generate_master_key.json +0 -7
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ describe DiscourseApi::API::Invite do
5
+ subject { DiscourseApi::Client.new("#{host}", "test_d7fd0429940", "test_user") }
6
+
7
+ describe "#invite_user" do
8
+ before do
9
+ stub_post("#{host}/invites").to_return(body: fixture("topic_invite_user.json"), headers: { content_type: "application/json" })
10
+ end
11
+
12
+ it "requests the correct resource" do
13
+ subject.invite_user(email: "fake_user@example.com", group_ids: "41,42")
14
+ expect(a_post("#{host}/invites")).to have_been_made
15
+ end
16
+
17
+ it "returns success" do
18
+ response = subject.invite_user(email: "fake_user@example.com", group_ids: "41,42")
19
+ expect(response).to be_a Hash
20
+ expect(response['success']).to be_truthy
21
+ end
22
+ end
23
+
24
+ describe "#update_invite" do
25
+ before do
26
+ stub_put("#{host}/invites/27").to_return(body: fixture("topic_invite_user.json"), headers: { content_type: "application/json" })
27
+ end
28
+
29
+ it "updates invite" do
30
+ subject.update_invite(27, email: "namee@example.com")
31
+ expect(a_put("#{host}/invites/27")).to have_been_made
32
+ end
33
+ end
34
+
35
+ describe "#retrieve_invite" do
36
+ before do
37
+ stub_get("#{host}/invites/retrieve.json?email=foo@bar.com").to_return(body: fixture("retrieve_invite.json"), headers: { content_type: "application/json" })
38
+ end
39
+
40
+ it "requests the correct resource" do
41
+ subject.retrieve_invite(email: "foo@bar.com")
42
+ expect(a_get("#{host}/invites/retrieve.json?email=foo@bar.com")).to have_been_made
43
+ end
44
+
45
+ it "returns the requested topics" do
46
+ invites = subject.retrieve_invite(email: "foo@bar.com")
47
+ expect(invites).to be_an Hash
48
+ end
49
+
50
+ it "returns the requested invite" do
51
+ invites = subject.retrieve_invite(email: "foo@bar.com")
52
+ expect(invites["email"]).to eq("foo@bar.com")
53
+ expect(invites).to have_key("invite_key")
54
+ end
55
+ end
56
+
57
+ describe "#destroy_all_expired_invites" do
58
+ let(:url) { "#{host}/invites/destroy-all-expired" }
59
+
60
+ before do
61
+ stub_post(url)
62
+ .to_return(
63
+ body: '{"success": "OK"}',
64
+ headers: { content_type: "application/json" }
65
+ )
66
+ end
67
+
68
+ it "destroys all expired invites" do
69
+ subject.destroy_all_expired_invites
70
+ expect(a_post(url)).to have_been_made
71
+ end
72
+ end
73
+
74
+ describe "#resend_all_invites" do
75
+ let(:url) { "#{host}/invites/reinvite-all" }
76
+
77
+ before do
78
+ stub_post(url)
79
+ .to_return(
80
+ body: '{"success": "OK"}',
81
+ headers: { content_type: "application/json" }
82
+ )
83
+ end
84
+
85
+ it "resends all invites" do
86
+ subject.resend_all_invites
87
+ expect(a_post(url)).to have_been_made
88
+ end
89
+ end
90
+
91
+ describe "#resend_invite" do
92
+ let(:url) { "#{host}/invites/reinvite" }
93
+
94
+ before do
95
+ stub_post(url)
96
+ .to_return(
97
+ body: '{"success": "OK"}',
98
+ headers: { content_type: "application/json" }
99
+ )
100
+ end
101
+
102
+ it "resends invite" do
103
+ subject.resend_invite("foo@bar.com")
104
+ expect(a_post(url)).to have_been_made
105
+ end
106
+ end
107
+
108
+ describe "#destroy_invite" do
109
+ let(:url) { "#{host}/invites?id=27" }
110
+
111
+ before do
112
+ stub_delete(url).to_return(
113
+ body: '{"success": "OK"}',
114
+ headers: { content_type: "application/json" }
115
+ )
116
+ end
117
+
118
+ it "destroys the invite" do
119
+ subject.destroy_invite(27)
120
+ expect(a_delete(url)).to have_been_made
121
+ end
122
+ end
123
+ end
@@ -36,19 +36,19 @@ describe DiscourseApi::API::PrivateMessages do
36
36
  end
37
37
  end
38
38
 
39
- describe '#create_private_message' do
39
+ describe '#create_pm' do
40
40
  before do
41
41
  stub_post("#{host}/posts")
42
- subject.create_private_message(
42
+ subject.create_pm(
43
43
  title: "Confidential: Hello World!",
44
44
  raw: "This is the raw markdown for my private message",
45
- target_usernames: "user1,user2"
45
+ target_recipients: "user1,user2"
46
46
  )
47
47
  end
48
48
 
49
49
  it "makes a create private message request" do
50
50
  expect(a_post("#{host}/posts").with(body:
51
- 'archetype=private_message&raw=This+is+the+raw+markdown+for+my+private+message&target_usernames=user1%2Cuser2&title=Confidential%3A+Hello+World%21')
51
+ 'archetype=private_message&raw=This+is+the+raw+markdown+for+my+private+message&target_recipients=user1%2Cuser2&title=Confidential%3A+Hello+World%21')
52
52
  ).to have_been_made
53
53
  end
54
54
  end
@@ -6,12 +6,12 @@ describe DiscourseApi::API::Search do
6
6
 
7
7
  describe "#search" do
8
8
  before do
9
- stub_get("#{host}/search/query").with(query: { term: "test" }).to_return(body: fixture("search.json"), headers: { content_type: "application/json" })
9
+ stub_get("#{host}/search").with(query: { q: "test" }).to_return(body: fixture("search.json"), headers: { content_type: "application/json" })
10
10
  end
11
11
 
12
12
  it "requests the correct resource" do
13
13
  subject.search("test")
14
- expect(a_get("#{host}/search/query").with(query: { term: "test" })).to have_been_made
14
+ expect(a_get("#{host}/search").with(query: { q: "test" })).to have_been_made
15
15
  end
16
16
 
17
17
  it "returns the requested search" do
@@ -25,6 +25,11 @@ describe DiscourseApi::API::Topics do
25
25
  expect(a_post("#{host}/t/12/invite")).to have_been_made
26
26
  end
27
27
 
28
+ it "requests the correct resource with new method 'invite_to_topic'" do
29
+ subject.invite_to_topic(12, email: "fake_user@example.com")
30
+ expect(a_post("#{host}/t/12/invite")).to have_been_made
31
+ end
32
+
28
33
  it "returns success" do
29
34
  response = subject.invite_user_to_topic(email: "fake_user@example.com", topic_id: 12)
30
35
  expect(response).to be_a Hash
@@ -55,6 +60,29 @@ describe DiscourseApi::API::Topics do
55
60
  end
56
61
  end
57
62
 
63
+ describe "#top_topics" do
64
+ before do
65
+ stub_get("#{host}/top.json").to_return(body: fixture("top.json"), headers: { content_type: "application/json" })
66
+ end
67
+
68
+ it "requests the correct resource" do
69
+ subject.top_topics
70
+ expect(a_get("#{host}/top.json")).to have_been_made
71
+ end
72
+
73
+ it "returns the requested topics" do
74
+ topics = subject.top_topics
75
+ expect(topics).to be_an Array
76
+ expect(topics.first).to be_a Hash
77
+ end
78
+
79
+ it "can take a hash param" do
80
+ topics = subject.top_topics({})
81
+ expect(topics).to be_an Array
82
+ expect(topics.first).to be_a Hash
83
+ end
84
+ end
85
+
58
86
  describe "#new_topics" do
59
87
  before do
60
88
  stub_get("#{host}/new.json").to_return(body: fixture("new.json"), headers: { content_type: "application/json" })
@@ -147,6 +175,14 @@ describe DiscourseApi::API::Topics do
147
175
  expect(body['post_stream']['posts']).to be_an Array
148
176
  expect(body['post_stream']['posts'].first).to be_a Hash
149
177
  end
178
+
179
+ it "can retrieve a topic posts' raw attribute" do
180
+ body = subject.topic_posts(57, [123], { include_raw: true })
181
+ expect(body).to be_a Hash
182
+ expect(body['post_stream']['posts']).to be_an Array
183
+ expect(body['post_stream']['posts'].first).to be_a Hash
184
+ expect(body['post_stream']['posts'].first['raw']).to be_an Array
185
+ end
150
186
  end
151
187
 
152
188
  describe "#create_topic_with_tags" do
@@ -166,4 +202,39 @@ describe DiscourseApi::API::Topics do
166
202
  end
167
203
  end
168
204
 
205
+ describe "#topic_set_user_notification_level" do
206
+ before do
207
+ stub_post("#{host}/t/1/notifications").to_return(body: fixture("notification_success.json"), headers: { content_type: "application/json" })
208
+ end
209
+
210
+ it "makes the post request" do
211
+ response = subject.topic_set_user_notification_level(1, notification_level: 3)
212
+ expect(a_post("#{host}/t/1/notifications").with(body: "notification_level=3")).to have_been_made
213
+ expect(response['success']).to eq('OK')
214
+ end
215
+ end
216
+
217
+ describe "#bookmark_topic" do
218
+ before do
219
+ stub_put("#{host}/t/1/bookmark.json").to_return(body: "", headers: { content_type: "application/json" })
220
+ end
221
+
222
+ it "makes the put request" do
223
+ response = subject.bookmark_topic(1)
224
+ expect(a_put("#{host}/t/1/bookmark.json")).to have_been_made
225
+ expect(response.body).to eq(nil)
226
+ end
227
+ end
228
+
229
+ describe "#remove_topic_bookmark" do
230
+ before do
231
+ stub_put("#{host}/t/1/remove_bookmarks.json").to_return(body: "", headers: { content_type: "application/json" })
232
+ end
233
+
234
+ it "makes the put request" do
235
+ response = subject.remove_topic_bookmark(1)
236
+ expect(a_put("#{host}/t/1/remove_bookmarks.json")).to have_been_made
237
+ expect(response.body).to eq(nil)
238
+ end
239
+ end
169
240
  end
@@ -28,6 +28,21 @@ describe DiscourseApi::Client do
28
28
  end
29
29
  end
30
30
 
31
+ describe "#timeout" do
32
+ context 'custom timeout' do
33
+ it "is set to Faraday connection" do
34
+ expect(subject.send(:connection).options.timeout).to eq(30)
35
+ end
36
+ end
37
+
38
+ context 'default timeout' do
39
+ it "is set to Faraday connection" do
40
+ subject.timeout = 25
41
+ expect(subject.send(:connection).options.timeout).to eq(25)
42
+ end
43
+ end
44
+ end
45
+
31
46
  describe "#api_key" do
32
47
  it "is publically accessible" do
33
48
  subject.api_key = "test_d7fd0429940"
@@ -0,0 +1,12 @@
1
+ {
2
+ "key": {
3
+ "id": 5,
4
+ "key": "e722e04df8cf6d097d565ca04eea1ff8e9e8f09beb405bae6f0c79852916f334",
5
+ "user": {
6
+ "id": 2,
7
+ "username": "robin",
8
+ "uploaded_avatar_id": 3,
9
+ "avatar_template": "/user_avatar/localhost/robin/{size}/3.png"
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "keys": [
3
+ {
4
+ "id": 1,
5
+ "key": "test_d7fd0429940",
6
+ "user": {
7
+ "id": 1,
8
+ "username": "test_user",
9
+ "uploaded_avatar_id": 7,
10
+ "avatar_template": "/user_avatar/localhost/test_user/{size}/7.png"
11
+ }
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "success": "OK"
3
+ }
@@ -0,0 +1,116 @@
1
+ {
2
+ "id": 26,
3
+ "invite_key": "CGUHjNC4Na",
4
+ "link": "http://localhost:3000/invites/CGUHjNC4Na",
5
+ "email": "foo@bar.com",
6
+ "emailed": true,
7
+ "custom_message": null,
8
+ "created_at": "2021-05-07T20:48:14.278Z",
9
+ "updated_at": "2021-05-07T20:48:14.278Z",
10
+ "expires_at": "2021-06-06T20:48:14.278Z",
11
+ "expired": false,
12
+ "topics": [
13
+ {
14
+ "id": 1,
15
+ "title": "About the Site Feedback category",
16
+ "fancy_title": "About the Site Feedback category",
17
+ "slug": "about-the-site-feedback-category",
18
+ "posts_count": 1
19
+ }
20
+ ],
21
+ "groups": [
22
+ {
23
+ "id": 1,
24
+ "automatic": true,
25
+ "name": "admins",
26
+ "display_name": "admins",
27
+ "user_count": 1,
28
+ "mentionable_level": 0,
29
+ "messageable_level": 0,
30
+ "visibility_level": 1,
31
+ "primary_group": false,
32
+ "title": null,
33
+ "grant_trust_level": null,
34
+ "incoming_email": null,
35
+ "has_messages": true,
36
+ "flair_url": null,
37
+ "flair_bg_color": null,
38
+ "flair_color": null,
39
+ "bio_raw": "",
40
+ "bio_cooked": null,
41
+ "bio_excerpt": null,
42
+ "public_admission": false,
43
+ "public_exit": false,
44
+ "allow_membership_requests": false,
45
+ "full_name": null,
46
+ "default_notification_level": 3,
47
+ "membership_request_template": null,
48
+ "members_visibility_level": 0,
49
+ "can_see_members": true,
50
+ "can_admin_group": true,
51
+ "publish_read_state": false
52
+ },
53
+ {
54
+ "id": 2,
55
+ "automatic": true,
56
+ "name": "moderators",
57
+ "display_name": "moderators",
58
+ "user_count": 1,
59
+ "mentionable_level": 0,
60
+ "messageable_level": 99,
61
+ "visibility_level": 1,
62
+ "primary_group": false,
63
+ "title": null,
64
+ "grant_trust_level": null,
65
+ "incoming_email": null,
66
+ "has_messages": true,
67
+ "flair_url": null,
68
+ "flair_bg_color": null,
69
+ "flair_color": null,
70
+ "bio_raw": null,
71
+ "bio_cooked": null,
72
+ "bio_excerpt": null,
73
+ "public_admission": false,
74
+ "public_exit": false,
75
+ "allow_membership_requests": false,
76
+ "full_name": null,
77
+ "default_notification_level": 2,
78
+ "membership_request_template": null,
79
+ "members_visibility_level": 0,
80
+ "can_see_members": true,
81
+ "can_admin_group": true,
82
+ "publish_read_state": false
83
+ },
84
+ {
85
+ "id": 3,
86
+ "automatic": true,
87
+ "name": "staff",
88
+ "display_name": "staff",
89
+ "user_count": 2,
90
+ "mentionable_level": 0,
91
+ "messageable_level": 0,
92
+ "visibility_level": 1,
93
+ "primary_group": false,
94
+ "title": null,
95
+ "grant_trust_level": null,
96
+ "incoming_email": null,
97
+ "has_messages": false,
98
+ "flair_url": null,
99
+ "flair_bg_color": null,
100
+ "flair_color": null,
101
+ "bio_raw": null,
102
+ "bio_cooked": null,
103
+ "bio_excerpt": null,
104
+ "public_admission": false,
105
+ "public_exit": false,
106
+ "allow_membership_requests": false,
107
+ "full_name": null,
108
+ "default_notification_level": 3,
109
+ "membership_request_template": null,
110
+ "members_visibility_level": 0,
111
+ "can_see_members": true,
112
+ "can_admin_group": true,
113
+ "publish_read_state": false
114
+ }
115
+ ]
116
+ }
@@ -0,0 +1,108 @@
1
+ {
2
+ "topic_list": {
3
+ "can_create_topic": false,
4
+ "more_topics_url": "/latest.json?page=1",
5
+ "draft": null,
6
+ "draft_key": "new_topic",
7
+ "draft_sequence": null,
8
+ "topics": [
9
+ {
10
+ "id": 1,
11
+ "title": "Test topic #1",
12
+ "fancy_title": "Test topic #1",
13
+ "slug": "test-topic-1",
14
+ "posts_count": 1,
15
+ "reply_count": 0,
16
+ "highest_post_number": 1,
17
+ "image_url": null,
18
+ "created_at": "2013-02-04T15:26:25.977-05:00",
19
+ "last_posted_at": "2013-02-05T12:14:17.364-05:00",
20
+ "bumped": true,
21
+ "bumped_at": "2013-02-07T13:43:11.191-05:00",
22
+ "unseen": false,
23
+ "pinned": true,
24
+ "excerpt": "Welcome! \n\nTry is a sandbox, a safe place to play with Discourse and its features.\n\nThis site is reset every day (or even more often). Any accounts or posts you create here will not exist tomorrow! \n\nFeel free to experim…",
25
+ "visible": true,
26
+ "closed": false,
27
+ "archived": false,
28
+ "views": 268,
29
+ "like_count": 14,
30
+ "has_best_of": false,
31
+ "archetype": "regular",
32
+ "last_poster_username": "test_user",
33
+ "category_id": 1,
34
+ "posters": [
35
+ {
36
+ "extras": null,
37
+ "description": "Original Poster, Most Recent Poster",
38
+ "user_id": 1
39
+ }
40
+ ]
41
+ },
42
+ {
43
+ "id": 1,
44
+ "title": "Test topic #2",
45
+ "fancy_title": "Test topic #2",
46
+ "slug": "test-topic-1",
47
+ "posts_count": 1,
48
+ "reply_count": 0,
49
+ "highest_post_number": 2,
50
+ "image_url": null,
51
+ "created_at": "2013-11-06T13:57:47.984-05:00",
52
+ "last_posted_at": "2013-11-06T13:57:48.111-05:00",
53
+ "bumped": true,
54
+ "bumped_at": "2013-11-06T13:57:48.111-05:00",
55
+ "unseen": false,
56
+ "pinned": false,
57
+ "visible": true,
58
+ "closed": false,
59
+ "archived": false,
60
+ "views": 1,
61
+ "like_count": 0,
62
+ "has_best_of": false,
63
+ "archetype": "regular",
64
+ "last_poster_username": "test_user",
65
+ "category_id": 1,
66
+ "posters": [
67
+ {
68
+ "extras": null,
69
+ "description": "Original Poster, Most Recent Poster",
70
+ "user_id": 1
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ "id": 1,
76
+ "title": "Test topic #3",
77
+ "fancy_title": "Test topic #3",
78
+ "slug": "test-topic-3",
79
+ "posts_count": 1,
80
+ "reply_count": 0,
81
+ "highest_post_number": 1,
82
+ "image_url": null,
83
+ "created_at": "2013-02-04T21:46:58.194-05:00",
84
+ "last_posted_at": "2013-11-06T13:56:27.753-05:00",
85
+ "bumped": true,
86
+ "bumped_at": "2013-11-06T13:56:27.753-05:00",
87
+ "unseen": false,
88
+ "pinned": false,
89
+ "visible": true,
90
+ "closed": false,
91
+ "archived": false,
92
+ "views": 82,
93
+ "like_count": 10,
94
+ "has_best_of": false,
95
+ "archetype": "regular",
96
+ "last_poster_username": "test_user",
97
+ "category_id": 1,
98
+ "posters": [
99
+ {
100
+ "extras": null,
101
+ "description": "Original Poster, Most Recent Poster",
102
+ "user_id": 1
103
+ }
104
+ ]
105
+ }
106
+ ]
107
+ }
108
+ }