workable 1.0.0 → 2.0.0rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,73 @@
1
+ {
2
+ "jobs": [
3
+ {
4
+ "id": "61884e2",
5
+ "title": "Sales Intern",
6
+ "full_title": "Sales Intern - US/3/SI",
7
+ "shortcode": "GROOV003",
8
+ "code": "US/3/SI",
9
+ "state": "draft",
10
+ "department": "Sales",
11
+ "url": "https://groove-tech.workable.com/jobs/102268944",
12
+ "application_url": "https://groove-tech.workable.com/jobs/102268944/candidates/new",
13
+ "shortlink": "https://groove-tech.workable.com/j/GROOV003",
14
+ "location": {
15
+ "country": "United States",
16
+ "country_code": "US",
17
+ "region": "Oregon",
18
+ "region_code": "OR",
19
+ "city": "Portland",
20
+ "zip_code": "97201",
21
+ "telecommuting": false
22
+ },
23
+ "created_at": "2015-07-01T00:00:00Z"
24
+ },
25
+ {
26
+ "id": "1166bf8c",
27
+ "title": "Operations Manager",
28
+ "full_title": "Operations Manager - US/02/CM",
29
+ "shortcode": "GROOV001",
30
+ "code": "US/02/CM",
31
+ "state": "archived",
32
+ "department": "Operations",
33
+ "url": "https://groove-tech.workable.com/jobs/291945146",
34
+ "application_url": "https://groove-tech.workable.com/jobs/291945146/candidates/new",
35
+ "shortlink": "https://groove-tech.workable.com/j/GROOV001",
36
+ "location": {
37
+ "country": "United States",
38
+ "country_code": "US",
39
+ "region": "Illinois",
40
+ "region_code": "IL",
41
+ "city": "Chicago",
42
+ "zip_code": "60290",
43
+ "telecommuting": false
44
+ },
45
+ "created_at": "2015-05-07T00:00:00Z"
46
+ },
47
+ {
48
+ "id": "167636b1",
49
+ "title": "Office Manager",
50
+ "full_title": "Office Manager - US/4/OM",
51
+ "shortcode": "GROOV005",
52
+ "code": "US/4/OM",
53
+ "state": "published",
54
+ "department": "Administration",
55
+ "url": "https://groove-tech.workable.com/jobs/376844767",
56
+ "application_url": "https://groove-tech.workable.com/jobs/376844767/candidates/new",
57
+ "shortlink": "https://groove-tech.workable.com/j/GROOV005",
58
+ "location": {
59
+ "country": "United States",
60
+ "country_code": "US",
61
+ "region": "Illinois",
62
+ "region_code": "IL",
63
+ "city": "Chicago",
64
+ "zip_code": "60290",
65
+ "telecommuting": false
66
+ },
67
+ "created_at": "2015-06-06T00:00:00Z"
68
+ }
69
+ ],
70
+ "paging": {
71
+ "next": "https://www.workable.com/spi/v3/accounts/subdomain/jobs?limit=3&since_id=2700d6df"
72
+ }
73
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "members": [
3
+ {
4
+ "id": "13e0eb0e",
5
+ "name": "Eduardo Vallente",
6
+ "headline": "Operations Manager",
7
+ "email": "eduardo.vallente@workabledemo.com",
8
+ "role": "admin"
9
+ },
10
+ {
11
+ "id": "19782abc",
12
+ "name": "Nadia Sawahla",
13
+ "headline": "Talent Manager",
14
+ "email": "nadia.sawahla@name.com",
15
+ "role": "recruiter"
16
+ },
17
+ {
18
+ "id": "3247e8c7",
19
+ "name": "Alexia Middleton",
20
+ "headline": "Commercial Director",
21
+ "email": "alexia.middleton@workabledemo.com",
22
+ "role": "simple"
23
+ },
24
+ {
25
+ "id": "3c00c3ac",
26
+ "name": "David Bodello",
27
+ "headline": "IT Specialist Recruiter",
28
+ "email": "david.bodellos@gmail.com",
29
+ "role": "recruiter"
30
+ }
31
+ ]
32
+ }
@@ -0,0 +1,60 @@
1
+ {
2
+ "candidate": {
3
+ "name": "Jj Botha",
4
+ "firstname": "Jj",
5
+ "lastname": "Botha",
6
+ "headline": "Professional Administration Manager",
7
+ "summary": "A focussed, results-driven team player with many year experience in the field. Working my way up to management level, I have experience of every aspect of this role. I understand the challenges it brings, and have a proven track record of providing solutions.",
8
+ "address": "25772 Gustave Shore, Iowa, USA",
9
+ "phone": "1-859-557-6573",
10
+ "email": "jj_botha@fakemail.com",
11
+ "cover_letter": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
12
+
13
+ "education_entries": [
14
+ { "degree": "MBA", "school": "University of Pennsylvania", "field_of_study": null, "start_date": "2008-03-01", "end_date": "2011-03-30" },
15
+ { "degree": "B.S.", "school": "University of Chicago", "field_of_study": "Marketing Communication & Economics", "start_date": "2004-09-01", "end_date": "2007-03-30" }
16
+ ],
17
+
18
+ "experience_entries": [
19
+ {
20
+ "title": "Sales Director",
21
+ "summary": null,
22
+ "start_date": "2011-03-01",
23
+ "end_date": "2014-03-30",
24
+ "current": false,
25
+ "company": "Vox Mobile",
26
+ "industry": "Telecommunications"
27
+ }
28
+ ],
29
+
30
+ "answers": [
31
+ {
32
+ "question_key": "2128d717",
33
+ "body": "Planning"
34
+ },
35
+ {
36
+ "question_key": "3399e6cd",
37
+ "choices": ["1e477229"]
38
+ }
39
+ ],
40
+
41
+ "skills": [ "Travel Planning", "Problem Solving"],
42
+ "social_profiles": [
43
+ {
44
+ "type": "twitter",
45
+ "name": "Twitter",
46
+ "username": "jj_botha",
47
+ "url": "http://www.twitter.com/jj_botha"
48
+ },
49
+ {
50
+ "type": "linkedin",
51
+ "name": "LinkedIn",
52
+ "url": "http://www.linkedin.com/in/jj_botha"
53
+ },
54
+ {
55
+ "type": "googleplus",
56
+ "url": "https://plus.google.com/6908286706342698"
57
+ }
58
+ ]
59
+ }
60
+ }
@@ -0,0 +1,109 @@
1
+ {
2
+ "status": "created",
3
+ "candidate": {
4
+ "id": "3fc9a80f",
5
+ "name": "Jj Botha",
6
+ "firstname": null,
7
+ "lastname": null,
8
+ "headline": "Professional Administration Manager",
9
+ "image_url": null,
10
+ "account": {
11
+ "subdomain": "groove-tech",
12
+ "name": "Groove Tech"
13
+ },
14
+ "job": {
15
+ "shortcode": "GROOV005",
16
+ "title": "Office Manager"
17
+ },
18
+ "stage": "Sourced",
19
+ "disqualified": false,
20
+ "disqualified_at": null,
21
+ "disqualification_reason": null,
22
+ "sourced": true,
23
+ "profile_url": "https://groove-tech.workable.com/backend/jobs/376844767/candidates/1070179133",
24
+ "address": "25772 Gustave Shore, Iowa, USA",
25
+ "phone": "1-859-557-6573",
26
+ "email": "jj_botha@fakemail.com",
27
+ "outbound_mailbox": "b-6adwdc@outbound.dev-workable.mailgun.org",
28
+ "domain": null,
29
+ "uploader_id": null,
30
+ "created_at": "2015-07-09T10:55:53Z",
31
+ "updated_at": "2015-07-09T10:55:53Z",
32
+ "cover_letter": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
33
+ "summary": "A focussed, results-driven team player with many year experience in the field. Working my way up to management level, I have experience of every aspect of this role. I understand the challenges it brings, and have a proven track record of providing solutions.",
34
+ "education_entries": [
35
+ {
36
+ "degree": "MBA",
37
+ "school": "University of Pennsylvania",
38
+ "field_of_study": null,
39
+ "start_date": "2008-03-01",
40
+ "end_date": "2011-03-30"
41
+ },
42
+ {
43
+ "degree": "B.S.",
44
+ "school": "University of Chicago",
45
+ "field_of_study": "Marketing Communication & Economics",
46
+ "start_date": "2004-09-01",
47
+ "end_date": "2007-03-30"
48
+ }
49
+ ],
50
+ "experience_entries": [
51
+ {
52
+ "title": "Sales Director",
53
+ "summary": null,
54
+ "start_date": "2011-03-01",
55
+ "end_date": "2014-03-30",
56
+ "company": "Vox Mobile",
57
+ "industry": "Telecommunications",
58
+ "current": false
59
+ }
60
+ ],
61
+ "skills": [
62
+ {
63
+ "name": "travel planning"
64
+ },
65
+ {
66
+ "name": "problem solving"
67
+ }
68
+ ],
69
+ "answers": [
70
+ {
71
+ "question": {
72
+ "body": "Explain one aspect of this role you believe you will excel at."
73
+ },
74
+ "answer": {
75
+ "body": "<p>Planning</p>"
76
+ }
77
+ },
78
+ {
79
+ "question": {
80
+ "body": "How many years administrative experience do you have?"
81
+ },
82
+ "answer": {
83
+ "choices": [
84
+ {
85
+ "body": "Over 5 years"
86
+ }
87
+ ]
88
+ }
89
+ }
90
+ ],
91
+ "resume_url": null,
92
+ "social_profiles": [
93
+ {
94
+ "type": "twitter",
95
+ "username": "jj_botha",
96
+ "url": "http://www.twitter.com/jj_botha"
97
+ },
98
+ {
99
+ "type": "linkedin",
100
+ "url": "http://www.linkedin.com/in/jj_botha"
101
+ },
102
+ {
103
+ "type": "googleplus",
104
+ "url": "https://plus.google.com/6908286706342698"
105
+ }
106
+ ],
107
+ "tags": []
108
+ }
109
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "recruiters": [
3
+ {
4
+ "id": "19782abc",
5
+ "name": "Nadia Sawahla",
6
+ "email": "nadia.sawahla@name.com"
7
+ },
8
+ {
9
+ "id": "3c00c3ac",
10
+ "name": "David Bodello",
11
+ "email": "david.bodellos@gmail.com"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "stages": [
3
+ {
4
+ "slug": "sourced",
5
+ "name": "Sourced",
6
+ "kind": "sourced",
7
+ "position": 0
8
+ },
9
+ {
10
+ "slug": "applied",
11
+ "name": "Applied",
12
+ "kind": "applied",
13
+ "position": 1
14
+ },
15
+ {
16
+ "slug": "phone-screen",
17
+ "name": "Phone Screen",
18
+ "kind": "phone-screen",
19
+ "position": 2
20
+ },
21
+ {
22
+ "slug": "interview",
23
+ "name": "Interview",
24
+ "kind": "interview",
25
+ "position": 3
26
+ },
27
+ {
28
+ "slug": "offer",
29
+ "name": "Offer",
30
+ "kind": "offer",
31
+ "position": 4
32
+ },
33
+ {
34
+ "slug": "hired",
35
+ "name": "Hired",
36
+ "kind": "hired",
37
+ "position": 5
38
+ }
39
+ ]
40
+ }
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Workable::Client do
4
+ let(:client) { described_class.new(api_key: 'test', subdomain: 'subdomain') }
5
+ let(:headers){ { 'Authorization' => 'Bearer test', 'User-Agent' => 'Workable Ruby Client' } }
4
6
 
5
7
  describe '#new' do
6
8
  it 'raises an error on missing api_key / subdomain' do
@@ -14,176 +16,210 @@ describe Workable::Client do
14
16
  end
15
17
  end
16
18
 
17
- describe '#jobs' do
18
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
19
-
20
- it 'returns array of posted jobs' do
21
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs?phase=published")
22
- .with(headers: { 'Authorization'=>'Bearer test', 'User-Agent'=>'Workable Ruby Client' })
23
- .to_return(status: 200, body: jobs_index_json_fixture, headers: {})
19
+ describe '#about' do
20
+ it 'returns information about company as a hash' do
21
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/')
22
+ .to_return(status: 200, body: about_json_fixture)
23
+ expect(client.about['name']).to eq('Groove Tech')
24
+ end
25
+ end
24
26
 
25
- expect(client.jobs).to be_kind_of(Array)
27
+ describe '#members' do
28
+ it 'returns array of members' do
29
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/members')
30
+ .to_return(status: 200, body: members_json_fixture)
31
+
32
+ expect(client.members).to be_kind_of(Array)
33
+ expect(client.members[0]).to eq(
34
+ 'id' => '13e0eb0e',
35
+ 'name' => 'Eduardo Vallente',
36
+ 'headline' => 'Operations Manager',
37
+ 'email' => 'eduardo.vallente@workabledemo.com',
38
+ 'role' => 'admin'
39
+ )
26
40
  end
41
+ end
27
42
 
28
- it 'raises exception on not authorized error (401)' do
29
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs?phase=published")
30
- .to_return(status: 401, body: '{"error":"Not authorized"}', headers: {})
43
+ describe '#recruiters' do
44
+ it 'returns array of recruiters' do
45
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/recruiters')
46
+ .to_return(status: 200, body: recruiters_json_fixture)
31
47
 
32
- expect { client.jobs }.to raise_error(Workable::Errors::NotAuthorized)
48
+ expect(client.recruiters).to be_kind_of(Array)
49
+ expect(client.recruiters[0]).to eq(
50
+ 'id' => '19782abc',
51
+ 'name' => 'Nadia Sawahla',
52
+ 'email' => 'nadia.sawahla@name.com'
53
+ )
33
54
  end
55
+ end
34
56
 
35
- it 'raises exception when status code differs from 200' do
36
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs?phase=published")
37
- .to_return(status: 500, body: '', headers: {})
57
+ describe '#stages' do
58
+ it 'returns array of stages' do
59
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/stages')
60
+ .to_return(status: 200, body: stages_json_fixture)
38
61
 
39
- expect { client.jobs }.to raise_error(Workable::Errors::InvalidResponse)
62
+ expect(client.stages).to be_kind_of(Array)
63
+ expect(client.stages[0]).to eq(
64
+ 'slug' => 'sourced',
65
+ 'name' => 'Sourced',
66
+ 'kind' => 'sourced',
67
+ 'position' => 0
68
+ )
40
69
  end
41
70
  end
42
71
 
43
- describe '#job_details' do
44
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
72
+ describe '#jobs' do
73
+ context 'happy path' do
74
+ before do
75
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
76
+ .with(headers: headers)
77
+ .to_return(status: 200, body: jobs_index_json_fixture)
78
+ end
79
+
80
+ it 'returns collection of posted jobs' do
81
+ expect(client.jobs).to be_kind_of(Workable::Collection)
82
+ expect(client.jobs.data).to be_kind_of(Array)
83
+ expect(client.jobs.data[0]).to include('title' => 'Sales Intern', 'full_title' => 'Sales Intern - US/3/SI')
84
+ expect(client.jobs.data.size).to eq(3)
85
+ end
86
+
87
+ it 'includes next page method that returns next collection' do
88
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs?limit=3&since_id=2700d6df')
89
+ .with(headers: headers)
90
+ .to_return(status: 200, body: jobs_index_json_fixture)
91
+
92
+ jobs = client.jobs.fetch_next_page
93
+ expect(jobs).to be_kind_of(Workable::Collection)
94
+ expect(client.jobs.data).to be_kind_of(Array)
95
+ end
96
+ end
97
+
98
+ context 'sad path' do
99
+ it 'raises exception on not authorized error (401)' do
100
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
101
+ .to_return(status: 401, body: '{"error":"Not authorized"}')
102
+
103
+ expect { client.jobs }.to raise_error(Workable::Errors::NotAuthorized)
104
+ end
105
+
106
+ it 'raises exception when status code differs from 200' do
107
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs')
108
+ .to_return(status: 500, body: '')
109
+
110
+ expect { client.jobs }.to raise_error(Workable::Errors::InvalidResponse)
111
+ end
112
+ end
113
+ end
45
114
 
115
+ describe '#job_details' do
46
116
  it 'returns details of given job' do
47
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs/03FF356C8B")
48
- .to_return(status: 200, body: job_json_fixture, headers: {})
117
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B')
118
+ .to_return(status: 200, body: job_json_fixture)
49
119
 
50
120
  expect(client.job_details('03FF356C8B')).to be_kind_of(Hash)
51
121
  end
52
122
 
53
123
  it 'raises an exception when job is not found' do
54
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs/invalid")
55
- .to_return(status: 404, body: '{"error":"Not found"}', headers: {})
124
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/invalid')
125
+ .to_return(status: 404, body: '{"error":"Not found"}')
56
126
 
57
127
  expect { client.job_details('invalid') }.to raise_error(Workable::Errors::NotFound)
58
128
  end
59
129
  end
60
130
 
61
131
  describe '#job_questions' do
62
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
63
-
64
132
  it 'returns questions for given job' do
65
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs/03FF356C8B/questions")
66
- .to_return(status: 200, body: job_questions_json_fixture, headers: {})
133
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/questions')
134
+ .to_return(status: 200, body: job_questions_json_fixture)
67
135
 
68
- expect(client.job_questions('03FF356C8B')).to be_kind_of(Array)
136
+ questions = client.job_questions('03FF356C8B')
137
+ expect(questions).to be_kind_of(Array)
138
+ expect(questions[0]['body']).to eq('Explain one aspect of this role you believe you will excel at.')
69
139
  end
70
-
71
140
  end
72
141
 
73
- describe "#build_job_candidates_url" do
74
- subject{ described_class.new(api_key: 'test', subdomain: 'subdomain') }
75
-
76
- it "builds url without options" do
77
- expect(subject.send(:build_job_candidates_url, "test", {})).to eq("jobs/test/candidates")
78
- end
79
-
80
- it "builds url with multiple unknown options" do
81
- expect(subject.send(:build_job_candidates_url, "test", {:a => 1, :b =>1})).to eq("jobs/test/candidates?a=1&b=1")
82
- end
83
-
84
- it "builds url with limit" do
85
- expect(subject.send(:build_job_candidates_url, "test", {:limit => 100})).to eq("jobs/test/candidates?limit=100")
142
+ describe '#job_members' do
143
+ it "returns array of job's members" do
144
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job_slug/members')
145
+ .to_return(status: 200, body: members_json_fixture)
146
+
147
+ expect(client.job_members('job_slug')).to be_kind_of(Array)
148
+ expect(client.job_members('job_slug')[0]).to eq(
149
+ 'id' => '13e0eb0e',
150
+ 'name' => 'Eduardo Vallente',
151
+ 'headline' => 'Operations Manager',
152
+ 'email' => 'eduardo.vallente@workabledemo.com',
153
+ 'role' => 'admin'
154
+ )
86
155
  end
156
+ end
87
157
 
88
- it "builds url with stage slug" do
89
- expect(subject.send(:build_job_candidates_url, "test", {:stage => "sourced"})).to eq("jobs/test/sourced/candidates")
90
- end
158
+ describe 'job_recruiters' do
159
+ it "returns array of job's recruiters" do
160
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job_slug/recruiters')
161
+ .to_return(status: 200, body: recruiters_json_fixture)
91
162
 
92
- it "builds url with stage slug and limit" do
93
- expect(subject.send(:build_job_candidates_url, "test", {:limit => 100, :stage => "sourced"})).to eq("jobs/test/sourced/candidates?limit=100")
163
+ expect(client.job_recruiters('job_slug')).to be_kind_of(Array)
164
+ expect(client.job_recruiters('job_slug')[0]).to eq(
165
+ 'id' => '19782abc',
166
+ 'name' => 'Nadia Sawahla',
167
+ 'email' => 'nadia.sawahla@name.com'
168
+ )
94
169
  end
95
170
  end
96
171
 
97
172
  describe '#job_candidates' do
98
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
99
-
100
- it 'returns array of candidates for given job' do
101
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs/03FF356C8B/candidates")
102
- .to_return(status: 200, body: job_candidates_json_fixture, headers: {})
103
-
104
- expect(client.job_candidates('03FF356C8B')).to be_kind_of(Array)
105
- end
173
+ context 'happy path' do
174
+ let(:candidates){ client.job_candidates('03FF356C8B') }
175
+ before do
176
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/candidates')
177
+ .to_return(status: 200, body: job_candidates_json_fixture)
178
+ end
106
179
 
107
- it 'raises exception on to long requests' do
108
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/jobs?phase=published")
109
- .to_return(status: 503, body: '{"error":"Not authorized"}', headers: {})
110
-
111
- expect { client.jobs }.to raise_error(Workable::Errors::RequestToLong)
112
- end
113
-
114
- end
115
-
116
- describe '#stages' do
117
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
180
+ it 'returns collection of candidates for given job' do
181
+ expect(candidates).to be_kind_of(Workable::Collection)
182
+ expect(candidates.data[0]['name']).to eq('Lakita Marrero')
183
+ end
118
184
 
119
- it 'returns array of stages' do
120
- stub_request(:get, "https://www.workable.com/spi/v2/accounts/subdomain/stages")
121
- .to_return(status: 200, body: stages_json_fixture, headers: {})
185
+ it 'includes next page method that returns next collection' do
186
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/subdomain/candidates?limit=3&since_id=2700d6df')
187
+ .with(headers: headers)
188
+ .to_return(status: 200, body: job_candidates_json_fixture)
122
189
 
123
- expect(client.stages).to be_kind_of(Array)
190
+ next_candidates = candidates.fetch_next_page
191
+ expect(next_candidates).to be_kind_of(Workable::Collection)
192
+ expect(next_candidates.data).to be_kind_of(Array)
193
+ end
124
194
  end
125
- end
126
195
 
127
- describe "#transform_to" do
128
- let(:client){
129
- described_class.new(
130
- api_key: 'test',
131
- subdomain: 'subdomain',
132
- transform_to: {
133
- candidate: OpenStruct.method(:new)
134
- }
135
- )
136
- }
196
+ context 'sad path' do
197
+ it 'raises exception on to long requests' do
198
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/03FF356C8B/candidates')
199
+ .to_return(status: 503, body: '{"error":"Not authorized"}')
137
200
 
138
- it "transforms candidate" do
139
- result = client.send(:transform_to, :candidate, {:name => "Tom"})
140
- expect(result).to be_kind_of(OpenStruct)
141
- expect(result.name).to eq("Tom")
201
+ expect { client.job_candidates('03FF356C8B') }.to raise_error(Workable::Errors::RequestToLong)
202
+ end
142
203
  end
143
204
  end
144
205
 
145
- describe "#transform_from" do
146
- let(:client){
147
- described_class.new(
148
- api_key: 'test',
149
- subdomain: 'subdomain',
150
- transform_from: {
151
- candidate: lambda { |input| input.marshal_dump }
152
- }
153
- )
154
- }
206
+ describe '#job_candidate' do
207
+ it 'returns detailed info about given candidate' do
208
+ stub_request(:get, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/job-slug/candidates/some-id')
209
+ .to_return(status: 200, body: job_candidate_json_fixture)
155
210
 
156
- it "transforms candidate" do
157
- input = client.send(:transform_from, :candidate, OpenStruct.new({:name => "Tom"}))
158
- expect(input).to be_kind_of(Hash)
159
- expect(input[:name]).to eq("Tom")
211
+ expect(client.job_candidate('job-slug', 'some-id')['name']).to eq('Cindy Sawyers')
160
212
  end
161
213
  end
162
214
 
163
- describe "#transform" do
164
- let(:client){ described_class.new(api_key: 'test', subdomain: 'subdomain') }
165
-
166
- it "transforms one" do
167
- result = client.send(:transform, OpenStruct.method(:new), {:name => "Tom"})
168
- expect(result).to be_kind_of(OpenStruct)
169
- expect(result.name).to eq("Tom")
170
- end
171
-
172
- it "transforms many" do
173
- data = client.send(:transform, OpenStruct.method(:new), [{:name => "Tom"}, {:name => "Alice"}])
174
- expect(data).to be_kind_of(Array)
175
- expect(data.map(&:class)).to eq([OpenStruct, OpenStruct])
176
- end
215
+ describe '#create_job_candidate' do
216
+ it 'POSTs requests and parses response' do
217
+ stub_request(:post, 'https://www.workable.com/spi/v3/accounts/subdomain/jobs/slug/candidates')
218
+ .with(body: new_candiate_hash_fixture.to_json)
219
+ .to_return(status: 200, body: new_candiate_response_json_fixture)
177
220
 
178
- it "does not transform nil" do
179
- data = client.send(:transform, OpenStruct.method(:new), nil)
180
- expect(data).to eq(nil)
181
- end
182
-
183
- it "does not transform without transformation" do
184
- data = client.send(:transform, nil, OpenStruct.new({:slug => "sourced"}))
185
- expect(data).to eq(OpenStruct.new({:slug => "sourced"}))
221
+ candidate = client.create_job_candidate(new_candiate_hash_fixture, 'slug')
222
+ expect(candidate['id']).to eq('3fc9a80f')
186
223
  end
187
224
  end
188
-
189
225
  end