Skip to content

Commit 27bd1bd

Browse files
committed
Fix updating project feature spec
Previously this spec was not representative of how the API was being used in practice and it was only really working by accident. The PUT requests in the examples were using the `Project#id` rather than the `Project#identifier` as they should have been. The spec was working even though the `Api::ProjectsController#load_project` before action was *not* finding the project, because the `load_and_authorize_resource` before action was then finding the project using `Project.find(params[:id])` and setting the `@project` instance variable used by the rest of the logic in the controller. However, clients of editor-api like editor-standalone use the project identifier as the resource ID in the URL path [1], so this spec was completely unrepresentative of how the endpoint was really being used. In this commit I've changed the examples to use the `Project#identifier` as the resource ID in the PUT requests. This means that the `Api::ProjectsController#load_project` before action now finds the project by identifier and since it sets the `@project` instance variable the `load_and_authorize_resource` before action no longer attempts to load the resource, it just does the authorize step using the already loaded project. In order to make this work reliably, I had to explicitly set the `Project#locale` to one of the fallback locales in `ProjectLoader` [2], i.e. 'en' or `nil`. Otherwise, the random locale selected in the project factory [3] meant that sometimes the `load_project` before action (which uses the `ProjectLoader` did not find the project and the `load_and_authorize_resource` before action raised an `ActiveRecord::RecordNotFound` resulting in a 404 Not Found. Now the spec is no longer making use of the randome locale from the factory, I've taken the opportunity to add some new examples demonstrating the behaviour when the project has different locales. This effectively demonstrates that `load_project` is wired up to `ProjectLoader` correctly. As an aside, I'm not convinced that having the factory select a locale at random is a good idea. I found it very confusing when it led to undeterministic specs. However, I'll leave that for another time. [1]: https://github.com/RaspberryPiFoundation/editor-standalone/blob/1d4375635cb6890794732072d608dbd4b05b3bb0/src/utils/apiCallHandler/projects.js#L16 [2]: https://github.com/RaspberryPiFoundation/editor-api/blob/b4bd337d09a88b1f41ecdc13136f7d11da0dcf89/lib/project_loader.rb#L8 [3]: https://github.com/RaspberryPiFoundation/editor-api/blob/b4bd337d09a88b1f41ecdc13136f7d11da0dcf89/spec/factories/project.rb#L9
1 parent 85a1eac commit 27bd1bd

File tree

1 file changed

+30
-6
lines changed

1 file changed

+30
-6
lines changed

spec/features/project/updating_a_project_spec.rb

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
RSpec.describe 'Updating a project', type: :request do
66
let(:headers) { { Authorization: UserProfileMock::TOKEN } }
7-
let!(:project) { create(:project, name: 'Test Project', user_id: owner.id) }
7+
let(:locale) { 'en' }
8+
let!(:project) { create(:project, name: 'Test Project', user_id: owner.id, locale:) }
89
let(:owner) { create(:owner, school:) }
910
let(:school) { create(:school) }
1011

@@ -26,31 +27,54 @@
2627
end
2728

2829
it 'responds 200 OK' do
29-
put("/api/projects/#{project.id}", headers:, params:)
30+
put("/api/projects/#{project.identifier}", headers:, params:)
3031
expect(response).to have_http_status(:ok)
3132
end
3233

3334
it 'responds with the project JSON' do
34-
put("/api/projects/#{project.id}", headers:, params:)
35+
put("/api/projects/#{project.identifier}", headers:, params:)
3536
data = JSON.parse(response.body, symbolize_names: true)
3637

3738
expect(data[:name]).to eq('New Name')
3839
end
3940

4041
it 'responds with the components JSON' do
41-
put("/api/projects/#{project.id}", headers:, params:)
42+
put("/api/projects/#{project.identifier}", headers:, params:)
4243
data = JSON.parse(response.body, symbolize_names: true)
4344

4445
expect(data[:components].first[:content]).to eq('print("hello")')
4546
end
4647

4748
it 'responds 422 Unprocessable Entity when params are invalid' do
48-
put("/api/projects/#{project.id}", headers:, params: { project: { components: [{ name: ' ' }] } })
49+
put("/api/projects/#{project.identifier}", headers:, params: { project: { components: [{ name: ' ' }] } })
4950
expect(response).to have_http_status(:unprocessable_entity)
5051
end
5152

5253
it 'responds 401 Unauthorized when no token is given' do
53-
put("/api/projects/#{project.id}", params:)
54+
put("/api/projects/#{project.identifier}", params:)
5455
expect(response).to have_http_status(:unauthorized)
5556
end
57+
58+
context 'when locale is nil, i.e. the other fallback locale in ProjectLoader' do
59+
let(:locale) { nil }
60+
61+
it 'responds 200 OK even though no locale is specified in query string' do
62+
put("/api/projects/#{project.identifier}", headers:, params:)
63+
expect(response).to have_http_status(:ok)
64+
end
65+
end
66+
67+
context "when locale is 'fr', i.e. not a fallback locale in ProjectLoader" do
68+
let(:locale) { 'fr' }
69+
70+
it 'responds 200 OK if locale is specified in query string' do
71+
put("/api/projects/#{project.identifier}?locale=fr", headers:, params:)
72+
expect(response).to have_http_status(:ok)
73+
end
74+
75+
it 'responds 404 Not Found if locale is not specified in query string' do
76+
put("/api/projects/#{project.identifier}", headers:, params:)
77+
expect(response).to have_http_status(:not_found)
78+
end
79+
end
5680
end

0 commit comments

Comments
 (0)