Skip to content
52 changes: 27 additions & 25 deletions src/components/QuickStartFilter.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import React, {useState} from "react";
import React, { useState } from "react";
import quickstarts from "./QuickStartList";
import Link from "@docusaurus/Link";
import {FaGolang} from "react-icons/fa6";
import {FaJava, FaLaptopCode, FaDocker, FaPython, FaCheck, FaArrowRight, FaArrowLeft} from "react-icons/fa";
import {TbBrandCSharp} from "react-icons/tb";
import {IoLogoJavascript} from "react-icons/io5";
import {useColorMode} from "@docusaurus/theme-common";
import { FaGolang } from "react-icons/fa6";
import { FaJava, FaLaptopCode, FaDocker, FaPython, FaCheck, FaArrowRight, FaArrowLeft } from "react-icons/fa";
import { TbBrandCSharp } from "react-icons/tb";
import { DiRuby } from "react-icons/di";
import { IoLogoJavascript } from "react-icons/io5";
import { useColorMode } from "@docusaurus/theme-common";

export default function QuickstartFilter({defaultLanguage = null}) {
const {colorMode} = useColorMode();
export default function QuickstartFilter({ defaultLanguage = null }) {
const { colorMode } = useColorMode();
const isDark = colorMode === "dark";

const [currentStep, setCurrentStep] = useState(defaultLanguage ? 2 : 1);
Expand All @@ -23,22 +24,23 @@ export default function QuickstartFilter({defaultLanguage = null}) {
});

const languages = [
{name: "Go", icon: <FaGolang size={24} />, color: "#00ADD8"},
{name: "Python", icon: <FaPython size={24} />, color: "#3776AB"},
{name: "Java", icon: <FaJava size={24} />, color: "#007396"},
{name: "JS/TS", icon: <IoLogoJavascript size={24} />, color: "#F7DF1E"},
{name: "C#", icon: <TbBrandCSharp size={24} />, color: "#512BD4"},
{ name: "Go", icon: <FaGolang size={24} />, color: "#00ADD8" },
{ name: "Python", icon: <FaPython size={24} />, color: "#3776AB" },
{ name: "Java", icon: <FaJava size={24} />, color: "#007396" },
{ name: "JS/TS", icon: <IoLogoJavascript size={24} />, color: "#F7DF1E" },
{ name: "C#", icon: <TbBrandCSharp size={24} />, color: "#512BD4" },
{ name: "Ruby", icon: <DiRuby size={24} />, color: "#CC342D" },
];

const servers = [
{name: "Local", icon: <FaLaptopCode size={24} />, description: "Run directly on your machine"},
{name: "Docker", icon: <FaDocker size={24} />, description: "Run in a Docker container"},
{ name: "Local", icon: <FaLaptopCode size={24} />, description: "Run directly on your machine" },
{ name: "Docker", icon: <FaDocker size={24} />, description: "Run in a Docker container" },
];

const steps = [
{id: 1, label: "Language", icon: languages.find(l => l.name === language)?.icon || null},
{id: 2, label: "Environment", icon: server === "Docker" ? <FaDocker size={16} /> : server === "Local" ? <FaLaptopCode size={16} /> : null},
{id: 3, label: "Quickstart", icon: null},
{ id: 1, label: "Language", icon: languages.find(l => l.name === language)?.icon || null },
{ id: 2, label: "Environment", icon: server === "Docker" ? <FaDocker size={16} /> : server === "Local" ? <FaLaptopCode size={16} /> : null },
{ id: 3, label: "Quickstart", icon: null },
];

const handleLanguageSelect = (lang) => {
Expand Down Expand Up @@ -372,10 +374,10 @@ export default function QuickstartFilter({defaultLanguage = null}) {
</div>
<span>{step.label}</span>
{currentStep > step.id && step.id === 1 && language && (
<span style={{color: '#ff914d', marginLeft: '0.25rem'}}>({language})</span>
<span style={{ color: '#ff914d', marginLeft: '0.25rem' }}>({language})</span>
)}
{currentStep > step.id && step.id === 2 && server && (
<span style={{color: '#ff914d', marginLeft: '0.25rem'}}>({server})</span>
<span style={{ color: '#ff914d', marginLeft: '0.25rem' }}>({server})</span>
)}
</div>
{idx < steps.length - 1 && (
Expand All @@ -402,7 +404,7 @@ export default function QuickstartFilter({defaultLanguage = null}) {
<div className="wizard-option-radio">
{language === lang.name && <FaCheck size={10} color="#fff" />}
</div>
<div className="wizard-option-icon" style={{color: lang.color}}>
<div className="wizard-option-icon" style={{ color: lang.color }}>
{lang.icon}
</div>
<span className="wizard-option-label">{lang.name}</span>
Expand All @@ -417,15 +419,15 @@ export default function QuickstartFilter({defaultLanguage = null}) {
<>
<h3 className="wizard-title">Select your environment</h3>
<p className="wizard-subtitle">Choose where you want to run the application server</p>
<div className="wizard-options" style={{gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))'}}>
<div className="wizard-options" style={{ gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))' }}>
{servers.map((srv) => (
<button
key={srv.name}
className={`wizard-option ${server === srv.name ? 'selected' : ''}`}
onClick={() => handleServerSelect(srv.name)}
style={{flexDirection: 'column', alignItems: 'flex-start', gap: '0.5rem'}}
style={{ flexDirection: 'column', alignItems: 'flex-start', gap: '0.5rem' }}
>
<div style={{display: 'flex', alignItems: 'center', gap: '0.75rem', width: '100%'}}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', width: '100%' }}>
<div className="wizard-option-radio">
{server === srv.name && <FaCheck size={10} color="#fff" />}
</div>
Expand All @@ -434,7 +436,7 @@ export default function QuickstartFilter({defaultLanguage = null}) {
</div>
<span className="wizard-option-label">{srv.name}</span>
</div>
<p className="wizard-option-desc" style={{marginLeft: '3.5rem'}}>{srv.description}</p>
<p className="wizard-option-desc" style={{ marginLeft: '3.5rem' }}>{srv.description}</p>
</button>
))}
</div>
Expand Down
19 changes: 19 additions & 0 deletions src/components/QuickStartList.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,25 @@ const quickstarts = [
"A sample app to demonstrate Keploy integration capabilities using TypeScript and Nhost.",
link: "/docs/quickstart/samples-typescript/#running-the-app-using-docker",
},

// Ruby list

{
title: "Sinatra + Postgres",
language: "Ruby",
server: "Docker",
description:
"A sample User CRUD app to demonstrate how seamlessly Keploy integrates with Sinatra and PostgreSQL.",
link: "/docs/quickstart/samples-sinatra-postgres/#using-docker-compose-",
},
{
title: "Sinatra + Postgres",
language: "Ruby",
server: "Local",
description:
"A sample User CRUD app to demonstrate how seamlessly Keploy integrates with Sinatra and PostgreSQL.",
link: "/docs/quickstart/samples-sinatra-postgres/#running-app-locally-on-linuxwsl-",
},
];

export default quickstarts;
158 changes: 158 additions & 0 deletions versioned_docs/version-4.0.0/quickstart/samples-sinatra-postgres.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
id: samples-sinatra-postgres
title: Sample User CRUD App (Sinatra + Postgres)
sidebar_label: Sinatra + Postgres
description: A sample User CRUD application built with Ruby Sinatra and PostgreSQL to demonstrate how Keploy records API calls and database interactions automatically.
tags:
- sinatra
- ruby
- quickstart
- samples
- examples
- tutorial
- ruby-framework
- postgresql
keyword:
- Sinatra Framework
- Ruby
- PostgreSQL
- API Test generator
- Auto case generation
---

import ProductTier from '@site/src/components/ProductTier';

<ProductTier tiers="Enterprise" offerings="Self-Hosted, Dedicated" />

🪄 Dive into the world of User CRUD Apps and see how seamlessly Keploy integrates with Sinatra and PostgreSQL. Buckle up, it's gonna be a fun ride! 🎢

import Link from '@docusaurus/Link'
import EnterpriseInstallReminder from '@site/src/components/EnterpriseInstallReminder';

<EnterpriseInstallReminder />

### Get Started! 🎬

### Clone the application 🧪

```bash
git clone https://github.com/keploy/samples-ruby.git && cd samples-ruby/sinatra-postgres
```

## Using Docker Compose 🐳

We will be using Docker Compose to run the application as well as PostgreSQL in Docker containers.

### Lights, Camera, Record! 🎥

Capture the test cases:

```shell
keploy record -c "docker compose up" --container-name "sinatra-app" --buildDelay 50
```

🔥 **Make some API calls**. Postman, Hoppscotch, or even curl - take your pick!

### Generate testcases

To generate testcases we just need to **make some API calls.**

1. **Health check:**

```bash
curl http://localhost:4567/
```

2. **Create a user:**

```bash
curl -X POST http://localhost:4567/users \
-H "Content-Type: application/json" \
-d '{"name": "John Doe", "email": "john@example.com"}'
```

3. **Create another user:**

```bash
curl -X POST http://localhost:4567/users \
-H "Content-Type: application/json" \
-d '{"name": "Jane Smith", "email": "jane@example.com"}'
```

4. **Get all users:**

```bash
curl http://localhost:4567/users
```

5. **Get a specific user:**

```bash
curl http://localhost:4567/users/1
```

6. **Delete a user:**

```bash
curl -X DELETE http://localhost:4567/users/2
```

And once you are done, you can stop the recording and give yourself a pat on the back! With that simple spell, you've conjured up test cases with mocks! Explore the **keploy** directory and you'll discover your handiwork in `tests` directory and `mocks.yml`.

### Time to run the testcases 🏃

```bash
keploy test -c "docker compose up" --containerName "sinatra-app" --delay 10
```

You can also check the test summary from your CLI.

## Running App Locally on Linux/WSL 🐧

### Prerequisites

- Ruby 3.0+ installed
- PostgreSQL installed and running
- Keploy installed

### Setup

1. **Install dependencies:**

```bash
bundle install
```

2. **Set up environment variables:**

```bash
export DATABASE_HOST=localhost
export DATABASE_PORT=5432
export DATABASE_NAME=keploy_demo
export DATABASE_USER=postgres
export DATABASE_PASSWORD=postgres
```

3. **Create the database:**

```bash
createdb keploy_demo
```

### Record Test Cases

```bash
keploy record -c "bundle exec ruby app.rb"
```

Then make API calls as shown above.

### Run Tests

```bash
keploy test -c "bundle exec ruby app.rb" --delay 5
```

### Wrapping it up 🎉

Congrats on the journey so far! You've seen Keploy's power, flexed your Ruby coding muscles, and had a bit of fun too! Now, go out there and keep exploring, innovating, and creating! Remember, with the right tools and a sprinkle of fun, anything's possible. 😊🚀
9 changes: 9 additions & 0 deletions versioned_sidebars/version-4.0.0-sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@
"items": [
"quickstart/samples-csharp"
]
},
{
"type": "category",
"label": "Ruby",
"collapsible": true,
"collapsed": true,
"items": [
"quickstart/samples-sinatra-postgres"
]
}
]
},
Expand Down