Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions app/controllers/api/solutions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,7 @@ def unpublish
def diff
files = Git::Exercise::GenerateDiffBetweenVersions.(@solution.exercise, @solution.git_slug, @solution.git_sha)

# TODO: (Optional): Change this to always be a 200 and handle the empty files in React
if files.present?
status = 200
else
status = 400
Sentry.capture_exception(RuntimeError.new("No files were found during solution diff"))
end
Solution::UpdateToLatestExerciseVersion.(@solution) if files.blank?

render json: {
diff: {
Expand All @@ -121,7 +115,7 @@ def diff
update: Exercism::Routes.sync_api_solution_url(@solution.uuid)
}
}
}, status:
}, status: :ok
end

def sync
Expand Down
3 changes: 3 additions & 0 deletions app/css/modals/update-exercise.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
@apply flex flex-col;
width: 80%;
}
&:has(.auto-updated-notice) .--modal-content {
max-width: 500px;
}
& .header {
@apply mb-16;
& h2 {
Expand Down
38 changes: 36 additions & 2 deletions app/javascript/components/modals/ExerciseUpdateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import React from 'react'
import { FetchingBoundary } from '../FetchingBoundary'
import { Modal, ModalProps } from './Modal'
import { Icon } from '../common'
import { Icon, GraphicalIcon } from '../common'
import { useRequestQuery } from '../../hooks/request-query'
import { ExerciseUpdateForm } from './exercise-update-modal/ExerciseUpdateForm'
import { Exercise } from '../types'
Expand Down Expand Up @@ -43,13 +43,47 @@ export const ExerciseUpdateModal = ({
defaultError={DEFAULT_ERROR}
>
{data ? (
<ExerciseUpdateForm diff={data.diff} onCancel={props.onClose} />
data.diff.files.length > 0 ? (
<ExerciseUpdateForm diff={data.diff} onCancel={props.onClose} />
) : (
<AutoUpdatedNotice onClose={props.onClose} />
)
) : null}
</FetchingBoundary>
</Modal>
)
}

const AutoUpdatedNotice = ({ onClose }: { onClose: () => void }) => {
const { t } = useAppTranslation('components/modals/ExerciseUpdateModal.tsx')
return (
<div className="auto-updated-notice flex flex-col items-center text-center">
<GraphicalIcon
icon="completed-check-circle"
height={64}
width={64}
className="mb-20"
/>
<h2 className="text-h3 mb-8">
{t('exerciseUpdateModal.autoUpdatedTitle')}
</h2>
<p className="text-p-large mb-24">
{t('exerciseUpdateModal.autoUpdatedBody')}
</p>
<button
type="button"
className="btn-primary btn-m"
onClick={() => {
onClose()
window.location.reload()
}}
>
{t('exerciseUpdateModal.continue')}
</button>
</div>
)
}

const LoadingComponent = () => {
const { t } = useAppTranslation('components/modals/ExerciseUpdateModal.tsx')
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// namespace: components/modals/ExerciseUpdateModal.tsx
export default {
'exerciseUpdateModal.loadingExerciseDiff': 'Loading exercise diff',
'exerciseUpdateModal.sorryCantWorkOutWhatNeedsUpdating':
"Sorry - it seems that we can't work out what needs updating for this exercise. We've been alerted and will have a look.",
'exerciseUpdateModal.autoUpdatedTitle': 'Exercise Updated',
'exerciseUpdateModal.autoUpdatedBody':
'This exercise has been automatically updated to the latest version. There are no file changes to review.',
'exerciseUpdateModal.continue': 'Continue',
}
17 changes: 6 additions & 11 deletions test/controllers/api/solutions_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,22 +173,17 @@ class API::SolutionsControllerTest < API::BaseTestCase
assert_equal expected, actual
end

test "Diff returns 400 if diff does not contain files" do
test "Diff auto-syncs and returns 200 when diff does not contain files" do
user = create :user
setup_user(user)
solution = create(:concept_solution, user:)
get diff_api_solution_path(solution.uuid), headers: @headers, as: :json

assert_response :bad_request
end

test "Sentry is alerted if diff does not contain files" do
user = create :user
setup_user(user)
solution = create(:concept_solution, user:)
Sentry.expects(:capture_exception).with(RuntimeError.new("No files were found during solution diff"))
Solution::UpdateToLatestExerciseVersion.expects(:call).with(solution)

get diff_api_solution_path(solution.uuid), headers: @headers, as: :json

assert_response :ok
response_body = JSON.parse(response.body)
assert_empty response_body.dig("diff", "files")
end

########
Expand Down
Loading