Skip to content
2 changes: 1 addition & 1 deletion tests/e2e-playwright/TEST_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ The test plan is organized by feature area. Tests are grouped for parallel execu
### 1.8 Decompression
| Status | Group | Test Case |
|--------|-------|-----------|
| 🔲 | main | Confirm setting a decompression type works |
| | main | Confirm setting a decompression type works |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to actually verify decompression works?

  1. Seed some compressed keys in the database
  2. Connect to the database(as this test does right now)
  3. But also verify the keys are properly rendered later, in the Browser


---

Expand Down
25 changes: 24 additions & 1 deletion tests/e2e-playwright/helpers/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,24 @@ export class ApiHelper {
}
}

/**
* Update a database via API (PATCH)
*/
async updateDatabase(
id: string,
data: Record<string, unknown>,
): Promise<DatabaseInstance> {
const ctx = await this.getContext();
const response = await ctx.patch(`/api/databases/${id}`, { data });

if (!response.ok()) {
const body = await response.text();
throw new Error(`Failed to update database: ${response.status()} - ${body}`);
}

return response.json();
}

/**
* Get all databases
*/
Expand Down Expand Up @@ -124,8 +142,13 @@ export class ApiHelper {

/**
* Create a String key via API
* Value can be a string or a Buffer-like object { type: 'Buffer', data: number[] } for binary data
*/
async createStringKey(databaseId: string, keyName: string, value: string): Promise<void> {
async createStringKey(
databaseId: string,
keyName: string,
value: string | { type: 'Buffer'; data: number[] },
): Promise<void> {
const ctx = await this.getContext();
const response = await ctx.post(`/api/databases/${databaseId}/string`, {
data: { keyName, value },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class AddDatabaseDialog {

// Decompression & Formatters tab
readonly enableDecompressionCheckbox: Locator;
readonly compressorDropdown: Locator;
readonly keyNameFormatDropdown: Locator;

constructor(page: Page) {
Expand Down Expand Up @@ -103,6 +104,7 @@ export class AddDatabaseDialog {

// Decompression & Formatters tab
this.enableDecompressionCheckbox = page.getByRole('checkbox', { name: /enable automatic data decompression/i });
this.compressorDropdown = page.getByTestId('select-compressor');
this.keyNameFormatDropdown = page.getByRole('combobox', { name: /key name format/i });
}

Expand Down Expand Up @@ -191,14 +193,23 @@ export class AddDatabaseDialog {
}

/**
* Go to decompression tab and enable decompression
* Go to decompression tab and enable decompression with a specific format
*/
async enableDecompression(): Promise<void> {
async enableDecompression(format: string = 'GZIP'): Promise<void> {
await this.decompressionTab.click();
const isChecked = await this.enableDecompressionCheckbox.isChecked();
if (!isChecked) {
await this.enableDecompressionCheckbox.click();
}
await this.selectCompressor(format);
}

/**
* Select a compressor format from the dropdown
*/
async selectCompressor(format: string): Promise<void> {
await this.compressorDropdown.click();
await this.page.getByRole('option', { name: format }).click();
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { gzipSync } from 'zlib';
import { test, expect } from 'e2eSrc/fixtures/base';
import { StandaloneConfigFactory } from 'e2eSrc/test-data/databases';
import { DatabaseInstance } from 'e2eSrc/types';

/**
* Decompression Tests (TEST_PLAN.md: 1.8 Decompression)
*
* Tests for configuring automatic data decompression on database connections.
*/
test.describe('Decompression', () => {
let database: DatabaseInstance;

test.beforeAll(async ({ apiHelper }) => {
const config = StandaloneConfigFactory.build();
database = await apiHelper.createDatabase(config);
});

test.afterAll(async ({ apiHelper }) => {
if (database?.id) {
await apiHelper.deleteDatabase(database.id);
}
});

test.beforeEach(async ({ databasesPage }) => {
await databasesPage.goto();
});

test('should confirm setting a decompression type works', async ({ databasesPage }) => {
const { databaseList, addDatabaseDialog } = databasesPage;
const compressorFormat = 'GZIP';

// Open edit dialog for the database
await databaseList.search(database.name);
await databaseList.edit(database.name);
const editDialog = databasesPage.page.getByRole('dialog', { name: /edit database/i });
await expect(editDialog).toBeVisible();

// Enable decompression with GZIP format
await addDatabaseDialog.enableDecompression(compressorFormat);
await expect(addDatabaseDialog.enableDecompressionCheckbox).toBeChecked();

// Save the changes
await addDatabaseDialog.generalTab.click();
await addDatabaseDialog.submit();
await editDialog.waitFor({ state: 'hidden' });

// Reopen edit dialog and verify the setting persisted
await databaseList.search(database.name);
await databaseList.edit(database.name);
await expect(editDialog).toBeVisible();
await addDatabaseDialog.decompressionTab.click();
await expect(addDatabaseDialog.enableDecompressionCheckbox).toBeChecked();
await expect(addDatabaseDialog.compressorDropdown).toContainText(compressorFormat);

// Clean up: disable decompression and save
await addDatabaseDialog.enableDecompressionCheckbox.click();
await addDatabaseDialog.generalTab.click();
await addDatabaseDialog.submit();
await editDialog.waitFor({ state: 'hidden' });
});

test('should decompress GZIP-compressed key values in Browser', async ({
apiHelper,
browserPage,
}) => {
const originalText = 'Hello, this is decompressed data!';
const keyName = `decompression-test:${Date.now()}`;
const compressedBuffer = gzipSync(Buffer.from(originalText));

// Seed a GZIP-compressed key into the database
await apiHelper.createStringKey(database.id, keyName, {
type: 'Buffer',
data: Array.from(compressedBuffer),
});

// Enable GZIP decompression on the database via API
await apiHelper.updateDatabase(database.id, { compressor: 'GZIP' });

try {
// Navigate to Browser and verify decompressed value
await browserPage.goto(database.id);
await browserPage.keyList.searchKeys(keyName);
await browserPage.keyList.clickKey(keyName);
await browserPage.keyDetails.waitForKeyDetails();

const displayedValue = await browserPage.keyDetails.getStringValue();
expect(displayedValue).toContain(originalText);
} finally {
// Clean up: remove compressor and delete test key
await apiHelper.updateDatabase(database.id, { compressor: 'NONE' });
await apiHelper.deleteKeysByPattern(database.id, keyName);
}
});
});
Loading