Skip to content

Commit

Permalink
chore: add home page automation tests (#370)
Browse files Browse the repository at this point in the history
  • Loading branch information
praveen5959 authored Nov 15, 2024
1 parent 1e6afa4 commit ca1bbc8
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 25 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
VITE_PARSEABLE_URL="https://demo.parseable.com"
VITE_USE_BASIC_AUTH=true
VITE_USERNAME=admin
VITE_PASSWORD=admin
5 changes: 0 additions & 5 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ jobs:
run: npm install -g pnpm && pnpm install
- name: Install Playwright Browsers
run: pnpm exec playwright install --with-deps
- name: Start the development server
run: pnpm run dev &
env:
PORT: 3001
VITE_PARSEABLE_URL: 'https://demo.parseable.com'
- name: Run Playwright tests
run: pnpm exec playwright test
- uses: actions/upload-artifact@v4
Expand Down
40 changes: 23 additions & 17 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './tests',
testIgnore: '**/login.spec.ts',
/* Run tests in files in parallel */
fullyParallel: true,
fullyParallel: true, // Set this to false to ensure sequential execution of files
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
reporter: 'line',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
Expand All @@ -27,22 +28,27 @@ export default defineConfig({
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},

{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},

{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
// {
// name: 'Firefox',
// use: { ...devices['Desktop Firefox'] },
// },
// {
// name: 'Safari',
// use: { ...devices['Desktop Safari'] },
// },
],

/* Run your local dev server before starting the tests */
// webServer: {
// command: 'npm run start',
// url: 'http://127.0.0.1:3000',
// reuseExistingServer: !process.env.CI,
// },
webServer: {
command: 'pnpm run dev',
url: 'http://localhost:3001',
reuseExistingServer: false,
env: {
PORT: '3001',
VITE_PARSEABLE_URL: 'https://demo.parseable.com',
VITE_USE_BASIC_AUTH: 'true',
VITE_USERNAME: 'admin',
VITE_PASSWORD: 'admin',
},
},
});
2 changes: 1 addition & 1 deletion src/pages/Stream/components/EventTimeLineGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const { makeTimeRangeLabel } = timeRangeUtils;
type CompactInterval = 'minute' | 'day' | 'hour' | 'quarter-hour' | 'half-hour' | 'month';

function extractWhereClause(sql: string) {
const whereClauseRegex = /WHERE\s+(.*?)(?=\s*(ORDER\s+BY|GROUP\s+BY|LIMIT|$))/i;
const whereClauseRegex = /WHERE\s+(.*?)(?=\s*(ORDER\s+BY|GROUP\s+BY|OFFSET|LIMIT|$))/i;
const match = sql.match(whereClauseRegex);
if (match) {
return match[1].trim();
Expand Down
2 changes: 1 addition & 1 deletion src/pages/Stream/components/PrimaryToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import classes from './styles/PrimaryToolbar.module.css';
const { toggleDeleteModal, onToggleView } = logsStoreReducers;
const { toggleSavedFiltersModal } = filterStoreReducers;
const renderMaximizeIcon = () => <IconMaximize size={px('1rem')} stroke={1.5} />;
const renderDeleteIcon = () => <IconTrash size={px('1rem')} stroke={1.5} />;
const renderDeleteIcon = () => <IconTrash data-id="delete-stream-btn" size={px('1rem')} stroke={1.5} />;

const MaximizeButton = () => {
const [_appStore, setAppStore] = useAppStore((_store) => null);
Expand Down
3 changes: 2 additions & 1 deletion src/pages/Stream/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const ConfigButton = (props: MenuItemProps) => {
<Stack
onClick={() => props.setCurrentView(viewName)}
style={{ padding: '4px 0', alignItems: 'center' }}
className={classes.menuItemContainer}>
className={classes.menuItemContainer}
data-id="manage-stream-btn">
<Tooltip label="Manage" position="right">
<Stack className={additionalClassNames} style={{ padding: '4px 4px' }}>
<IconSettings2
Expand Down
110 changes: 110 additions & 0 deletions tests/home.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { test, expect } from '@playwright/test';

const TEST_URL = 'http://localhost:3001';

test.describe('Home Page', () => {
test.beforeEach(async ({ page }) => {
await page.goto(`${TEST_URL}`);
});
test('should render the component correctly with default state', async ({ page }) => {
await expect(page.locator('text=All Streams')).toBeVisible();
await expect(page.locator('input[placeholder="Search Stream"]')).toBeVisible();
});

test('should render the component correctly with streams data', async ({ page }) => {
// Check that the streams are displayed
await expect(page.locator('text=backend')).toBeVisible();
await expect(page.locator('text=frontend')).toBeVisible();
});

test('should filter streams based on search input', async ({ page }) => {
const searchInput = page.locator('input[placeholder="Search Stream"]');
await searchInput.fill('backend');
await expect(page.locator('text=backend')).toBeVisible();

// Clear the search and check if both streams are visible
await searchInput.fill('');
await expect(page.locator('text=backend')).toBeVisible();
await expect(page.locator('text=frontend')).toBeVisible();
});

test('should display empty state if no streams are available', async ({ page }) => {
const searchInput = page.locator('input[placeholder="Search Stream"]');
await searchInput.fill(Math.random().toString());

// Expect empty state view to be visible
await expect(page.locator('text=No Stream found on this account')).toBeVisible();
await expect(page.locator('text=All Streams (0)')).toBeVisible();
});

test('should display the create stream button', async ({ page }) => {
const createButton = page.locator('text=Create Stream');
await expect(createButton).toBeVisible();
});

test('should display the create stream modal on click', async ({ page }) => {
const createButton = page.locator('text=Create Stream');
await expect(createButton).toBeVisible();
await createButton.click();
await expect(page.locator('text=Create Stream').nth(1)).toBeVisible();
});

test.describe('Create Stream Modal', () => {
test.beforeEach(async ({ page }) => {
const createButton = page.locator('text=Create Stream');
await createButton.click();
});

test('should render the form correctly', async ({ page }) => {
// Check if essential elements are present in the form
await expect(page.locator('input[placeholder="Name"]')).toBeVisible();
await expect(page.locator('text=Schema Type')).toBeVisible();
await expect(page.locator('button:has-text("Create")').nth(1)).toBeVisible();
});

test('should enable the submit button when form is valid', async ({ page }) => {
// Fill in the form with valid values
await page.fill('input[placeholder="Name"]', 'PlaywrightStream');

await page.locator('button:has-text("Create")').nth(1).click();
await page.waitForTimeout(1000);
});

test.describe('Delete Stream', () => {
test('search, navigate, and delete demo stream', async ({ page }) => {
// Step 1: Search for the demo stream
await page.goto(`${TEST_URL}`);
const searchInput = page.locator('input[placeholder="Search Stream"]');
await searchInput.fill('PlaywrightStream');
await expect(page.locator('text=PlaywrightStream')).toBeVisible();

// Step 2: Navigate to the demo stream
await page.locator('text=PlaywrightStream').click();
const manageBtn = page.locator('[data-id="manage-stream-btn"]');
await expect(manageBtn).toBeVisible();
await manageBtn.click();

await page.waitForTimeout(1000);

// Step 3: Delete the demo stream
const deleteBtn = page.locator('[data-id="delete-stream-btn"]');
await expect(deleteBtn).toBeVisible();
await deleteBtn.click();
await expect(page.locator('text=Delete Stream')).toBeVisible();
await page.fill('input[placeholder*="Type the name of the stream to confirm. i.e."]', 'PlaywrightStream');
const confirmDeleteBtn = page.getByRole('button', { name: 'Delete' });
await expect(confirmDeleteBtn).toBeEnabled();
await confirmDeleteBtn.click();

await page.waitForTimeout(1000);

// Step 4: Check if stream is deleted
await page.goto(`${TEST_URL}`);
await expect(searchInput).toBeVisible();
await searchInput.fill('PlaywrightStream');
await expect(page.locator('text=No Stream found on this account')).toBeVisible();
await expect(page.locator('text=All Streams (0)')).toBeVisible();
});
});
});
});

0 comments on commit ca1bbc8

Please sign in to comment.