Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests #7319

Merged
merged 14 commits into from
Jan 30, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ export const CodeMirror = forwardRef(function _CodeMirror(
return (
<div className="editor-wrapper" style={style}>
<div
data-cy="codemirror-editor"
data-ci="codemirror-editor"
id="bootcamp-cm-editor"
className="editor"
ref={setTextarea}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export function CheckScenariosButton({
const { shouldAutoRunCode, setShouldAutoRunCode } = useEditorStore()
return (
<button
data-ci="check-scenarios-button"
className="scenarios-button btn-primary btn-s"
onClick={() => {
handleRunCode()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { assembleClassNames } from '@/utils/assemble-classnames'

function _ControlButtons({ handleRunCode }: { handleRunCode: () => void }) {
return (
<div className="flex items-center gap-8 pb-12 overflow-auto shrink-0">
<div
data-ci="control-buttons"
className="flex items-center gap-8 pb-12 overflow-auto shrink-0"
>
{/* Run the tests with this button */}
<CheckScenariosButton handleRunCode={handleRunCode} />
{/* These buttons let you select a test/scenario that you want to inspect. */}
Expand All @@ -34,6 +37,7 @@ function PreviewTestButtons() {
<div className="test-selector-buttons ">
{flatPreviewTaskTests.map((taskTest, testIdx) => (
<button
data-ci="preview-scenario-button"
key={testIdx}
onClick={() => setInspectedPreviewTaskTest(taskTest)}
className={assembleClassNames(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function InformationWidgetToggleButton({
}
}, [shouldShowInformationWidget, inspectedTestResult])
return (
<label className="switch">
<label data-ci="information-widget-toggle" className="switch">
<input
disabled={disabled}
type="checkbox"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function Scrubber({

return (
<div
data-cy="scrubber"
data-ci="scrubber"
id="scrubber"
onClick={() => {
// we wanna focus the range input, so keyboard shortcuts work
Expand All @@ -60,7 +60,7 @@ function Scrubber({
/>
)}
<input
data-cy="scrubber-range-input"
data-ci="scrubber-range-input"
disabled={shouldScrubberBeDisabled(
hasCodeBeenEdited,
animationTimeline,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export default function SolveExercisePage({
secondarySize: BottomHeight,
handleMouseDown: handleHeightChangeMouseDown,
} = useResizablePanels({
initialSize: 800,
secondaryMinSize: 200,
initialSize: 500,
secondaryMinSize: 250,
direction: 'vertical',
localStorageId: 'solve-exercise-page-editor-height',
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function _TaskPreview() {
}

return (
<section className="c-scenario pending">
<section data-ci="task-preview" className="c-scenario pending">
{exercise.config.testsType === 'io' ? (
<IOPreview inspectedPreviewTaskTest={inspectedPreviewTaskTest} />
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function TaskList({ tasks }: { tasks: Task[] }) {

function Task({ task, onClick }: { task: Task; onClick: () => void }) {
return (
<div data-cy="task" className={`task ${task.status}`}>
<div data-ci="task" className={`task ${task.status}`}>
<div className="imgs">
<Icon
icon="bootcamp-task-completed"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ function _Tasks() {

if (!tasks) return null
return (
<div data-cy="task-list" id="tasks">
<div data-ci="task-list" id="tasks">
<div className="flex flex-row items-center justify-between">
<h2>
<span>Your</span> Tasks
</h2>
<div data-cy="task-completion-count">
<div data-ci="task-completion-count">
{numberOfCompletedTasks}/{numberOfTasks}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function InspectedTestResultViewLHS({
[flatPreviewTaskTests, result.testIndex]
)
return (
<div className="scenario-lhs">
<div data-ci="inspected-test-result-view" className="scenario-lhs">
<div className="scenario-lhs-content">
<h3>
<strong>Scenario: </strong>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export function TestResultsButtons() {
{testSuiteResult.tests.map((test, idx) => {
return (
<button
data-ci="test-selector-button"
key={test.name + idx}
onClick={() =>
handleSetInspectedTestResult({
Expand Down
8 changes: 7 additions & 1 deletion app/models/bootcamp/exercise.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ def readonly_ranges

private
def file_contents(filename)
File.read(Rails.root / "bootcamp_content/projects/#{project.slug}/exercises/#{slug}/#{filename}")
File.read(root_dir / "projects/#{project.slug}/exercises/#{slug}/#{filename}")
end

def root_dir
return Rails.root / "test/repos/bootcamp_content" if Rails.env.test?

Rails.root / "bootcamp_content"
end
end
5 changes: 0 additions & 5 deletions app/views/layouts/bootcamp-ui.haml
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@
%meta{ name: "turbo-prefetch", content: "false" }
%meta{ name: "user-id", content: current_user&.id }

%link{ href: "/manifest.json", rel: "manifest" }
%link{ href: "/icon.png", rel: "icon", type: "image/png" }
%link{ href: "/icon.svg", rel: "icon", type: "image/svg+xml" }
%link{ href: "/icon.png", rel: "apple-touch-icon" }
-# = javascript_include_tag "application", "data-turbo-track": "reload", type: "module", crossorigin: :anonymous
= javascript_include_tag "bootcamp-ui-js", "data-turbo-track": "reload", type: "module", crossorigin: :anonymous

%body{ class: body_class }
Expand Down
20 changes: 20 additions & 0 deletions test/factories/bootcamp/exercises.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,24 @@
description { "Exercise Description" }
level_idx { (Bootcamp::Level.first || create(:bootcamp_level)).idx }
end

trait :penguin do
slug { "penguin" }
project { Bootcamp::Project.find_by(slug: "drawing") || create(:bootcamp_project, slug: "drawing") }
end

trait :even_or_odd do
slug { "even-or-odd" }
project { Bootcamp::Project.find_by(slug: "numbers") || create(:bootcamp_project, slug: "numbers") }
end

trait :manual_solve do
slug { "manual-solve" }
project { Bootcamp::Project.find_by(slug: "maze") || create(:bootcamp_project, slug: "maze") }
end

trait :automated_solve do
slug { "automated-solve" }
project { Bootcamp::Project.find_by(slug: "maze") || create(:bootcamp_project, slug: "maze") }
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
"idx": 4,
"title": "Penguin",
"description": "Make the penguin symmetrical",
"project_type": "draw",
"level": 1,
"concepts": [],
"tests_type": "state",
"readonly_ranges": [],
"tasks": [
{
"name": "Draw the scene",
"tests": [
{
"slug": "draw-scence",
"name": "Make the penguin symmetrical.",
"description_html": "Fix all the TODO comments to make the penguin symmetrical.",
"function": "main",
"checks": [
{
"name": "getRectangleAt(0, 0, 100, 100)",
"matcher": "toBeDefined",
"error_html": "The sky has gone wrong."
},
{
"name": "getRectangleAt(0, 70, 100, 30)",
"matcher": "toBeDefined",
"error_html": "The ground has gone wrong."
},
{
"name": "getEllipseAt(28, 55, 10, 25)",
"matcher": "toBeDefined",
"error_html": "The left wing doesn't seem right."
},
{
"name": "getEllipseAt(72, 55, 10, 25)",
"matcher": "toBeDefined",
"error_html": "The right wing doesn't seem right."
},
{
"name": "getEllipseAt(50, 53, 25, 40)",
"matcher": "toBeDefined",
"error_html": "The outer body has gone wrong."
},
{
"name": "getEllipseAt(50, 50, 21, 39)",
"matcher": "toBeDefined",
"error_html": "The inner body has gone wrong."
},
{
"name": "getCircleAt(50, 31, 23)",
"matcher": "toBeDefined",
"error_html": "The head has gone wrong."
},
{
"name": "getEllipseAt(41, 32, 11, 14)",
"matcher": "toBeDefined",
"error_html": "The left side of the face doesn't look right."
},
{
"name": "getEllipseAt(59, 32, 11, 14)",
"matcher": "toBeDefined",
"error_html": "The right side of the face doesn't look right."
},
{
"name": "getEllipseAt(50, 40, 16, 11)",
"matcher": "toBeDefined",
"error_html": "The lower part of the face doesn't look right."
},
{
"name": "getCircleAt(42, 33, 3)",
"matcher": "toBeDefined",
"error_html": "The left eye seems off."
},
{
"name": "getCircleAt(43, 34, 1)",
"matcher": "toBeDefined",
"error_html": "The left iris seems off."
},
{
"name": "getCircleAt(58, 33, 3)",
"matcher": "toBeDefined",
"error_html": "The right eye seems off."
},
{
"name": "getCircleAt(57, 34, 1)",
"matcher": "toBeDefined",
"error_html": "The right iris seems off."
},
{
"name": "getEllipseAt(40, 93, 7, 4)",
"matcher": "toBeDefined",
"error_html": "The left foot's gone astray."
},
{
"name": "getEllipseAt(60, 93, 7, 4)",
"matcher": "toBeDefined",
"error_html": "The right foot's not right."
},
{
"name": "getTriangleAt(46, 38, 54, 38, 50, 47)",
"matcher": "toBeDefined",
"error_html": "The nose isn't right."
}
]
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Light blue background
fill_color_hex("#ADD8E6")
rectangle(0, 0, 100, 100)

// Ground
fill_color_hex("#ffffff") // Ice ground
rectangle(0, 70, 100, 30) // Ice ground

// Penguin wings
fill_color_hex("#000000") // Black
ellipse(28, 55, 10, 25) // Left wing
ellipse(72, 55, 10, 25) // Right wing

// Penguin body
fill_color_hex("#000000") // Black for the body
ellipse(50, 53, 25, 40) // Outer body (oval shape)
fill_color_hex("#ffffff") // White for the belly
ellipse(50, 50, 21, 39) // Inner belly (oval shape)

// Penguin head
fill_color_hex("#000000") // Black
circle(50, 31, 23) // Head (circle)
fill_color_hex("#ffffff") // White for the face
ellipse(41, 32, 11, 14) // Left part of the face
ellipse(59, 32, 11, 14) // Right part of the face
ellipse(50, 40, 16, 11) // Lower part of the face

// Penguin eyes
fill_color_hex("#000000") // Black
circle(42, 33, 3) // Left eye
fill_color_hex("#ffffff") // White
circle(43, 34, 1) // Left iris

fill_color_hex("#000000") // Black
circle(58, 33, 3) // Right eye
fill_color_hex("#ffffff") // White
circle(57, 34, 1) // Right iris

// Feet
fill_color_hex("#FFA500")
ellipse(40, 93, 7, 4)
ellipse(60, 93, 7, 4)
triangle(46, 38, 54, 38, 50, 47)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Introduction

This is fun!
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Follow the `TODO` comments to make the penguin symmetrical.

As you get each bit right, tidy up the comments by removing the `TODO` and replacing it with a nicer comment.

Use the "Check Scenarios" button regularly, and have fun!
Loading
Loading