Skip to content
Open
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
22 changes: 22 additions & 0 deletions pr_description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Description
This PR adds a new Quickstart guide for **Ruby (Sinatra + PostgreSQL)**.

It includes:
- A new guide: `samples-sinatra-postgres.md`
- Updates to `QuickStartFilter.js` to include Ruby language support.
- Updates to `QuickStartList.js` to list the new quickstart.
- Sidebar updates in `version-4.0.0-sidebars.json`.
- Terminal screenshots for both Docker and local setups.

## Related Issue
Fixes #3521

## Checklist
- [x] Documentation build passes (`npm run build`)
- [x] Added new language to `QuickStartFilter.js`
- [x] Added configuration for the new quickstart in `QuickStartList.js`
- [x] Added screenshots for commands (Record, Test, API calls)
- [x] Verified links and formatting

## Sample Code
The sample application code is available at: [Atul-Chahar/samples-ruby](https://github.com/Atul-Chahar/samples-ruby/tree/master/sinatra-postgres)
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
20 changes: 20 additions & 0 deletions src/components/QuickStartList.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,26 @@ 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;
Binary file added static/img/sinatra-postgres/bundle-install.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
179 changes: 179 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,179 @@
---
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" />

Get started with the User CRUD Application.

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
```

### Capture the test cases

Capture the test cases:

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

![Keploy Record Sinatra](/img/sinatra-postgres/keploy-record-sinatra.png)

### Generate testcases

To generate testcases we need to make some API calls. Open a **new terminal window** and run the following commands:

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
```

![Generate Testcases Sinatra](/img/sinatra-postgres/generate-testcases-sinatra.png)

Once you are done, you can stop the recording in the first terminal (Ctrl+C). Keploy will save the test cases in the `keploy` directory.

### Run the testcases

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

![Keploy Test Sinatra](/img/sinatra-postgres/keploy-test-sinatra.png)

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. **Start PostgreSQL Container:**

Since we are running the app locally, we need a database. We can spin up a PostgreSQL container easily:

```bash
docker run -d \
--name postgres-local \
-p 5432:5432 \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=keploy_demo \
postgres:15
```

2. **Install dependencies:**

```bash
bundle install
```

![Bundle Install Sinatra](/img/sinatra-postgres/bundle-install.png)


3. **Set up environment variables:**

Note: We use `127.0.0.1` instead of `localhost` to ensure IPv4 connection.

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

### Record Test Cases

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

![Keploy Record Local](/img/sinatra-postgres/keploy-record-local.png)

Then make API calls as shown above (in a separate terminal).

![Generate Testcases Local](/img/sinatra-postgres/generate-testcases-local.png)



### Run Tests

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

![Keploy Test Local](/img/sinatra-postgres/keploy-test-local.png)


### Conclusion

You have successfully recorded and replayed API tests for a Ruby Sinatra application using Keploy.
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