Skip to content

Add MongoDB e2e testing plugin (@lowdefy/community-plugin-e2e-mdb) #56

@machielvdw

Description

@machielvdw

Brief

Problem

Lowdefy e2e tests can verify UI state and client-side request responses, but cannot verify that data actually persisted correctly in MongoDB. After a form submission, tests can check ldf.expect.request() succeeded, but not that the database contains the right document with the right fields. This forces developers to either trust the UI layer or write separate integration tests.

Additionally:

  • Tests currently require a real MongoDB instance, which complicates CI/CD and local development
  • Atlas-specific features (Atlas Search, vector search, etc.) can't be tested against mongodb-memory-server

Requirements

MongoDB In-Memory Server:

  • Use mongodb-memory-server for test database — no external MongoDB instance required
  • Each Playwright worker gets an isolated in-memory database
  • Tests run without network dependencies, faster execution, works offline

Database Operations:

  • The mdb package should export fixture definitions (not a pre-built test object) so developers compose it themselves via test.extend(mdbFixtures) in their local e2e/fixtures.js
  • The mdb package should have no dependency on @lowdefy/e2e-utils — it's a standalone Playwright fixture that works with any project
  • Users should be able to assert MongoDB document state within Playwright e2e tests via an mdb fixture
  • Users should be able to load snap files (YAML) to set up known database state before tests
  • Users should be able to create/update snap files from current database state
  • Snap files should live in e2e/snaps/<name>/<collection>.yaml
  • Assertions should auto-poll with configurable timeout (matching Playwright's expect.poll pattern) since DB writes from Lowdefy requests are async
  • Users should be able to seed collections inline with JavaScript objects as an alternative to snap files
  • Users should have direct MongoDB collection access (findOne, insertOne, aggregate) as an escape hatch

Request Mocking for Atlas Features:

  • For Atlas-specific features (Atlas Search, vector search, etc.) that mongodb-memory-server doesn't support, provide request mocking
  • Developers configure which Lowdefy requests to mock via config file (e.g., e2e/mocks.yaml or similar)
  • May require changes to Lowdefy build output to support request interception in e2e mode
  • Mock responses can be static (from config) or dynamic (based on test setup)

API Shape (Reference)

Developer's e2e/fixtures.js after adding mdb plugin:

import { test as ldfTest, expect } from '@lowdefy/e2e-utils/fixtures';
import { mdbFixtures } from '@lowdefy/community-plugin-e2e-mdb';

export const test = ldfTest.extend(mdbFixtures);
export { expect };

Test files import locally (unchanged when adding plugins):

import { test, expect } from './fixtures.js';

test('creates ticket', async ({ ldf, mdb }) => {
  // Setup: load snap or seed inline (uses in-memory MongoDB)
  await mdb.load('clean-tickets');
  // or: await mdb.seed('tickets', [{ name: 'Existing', status: 'open' }]);

  // Act via UI
  await ldf.goto('/tickets/new');
  await ldf.do.blocks['name_input'].fill('John Doe');
  await ldf.do.blocks['priority_select'].select('High');
  await ldf.do.blocks['submit_btn'].click();

  // Assert DB state (auto-polls)
  await mdb.expect('tickets').toContainDocument({ name: 'John Doe', priority: 'high' });
  await mdb.expect('tickets').toHaveDocumentCount(2);
  await mdb.expect('tickets').not.toContainDocument({ _id: 'deleted-id' });

  // Direct access escape hatch
  const doc = await mdb.collection('tickets').findOne({ name: 'John Doe' });
  expect(doc.tags).toContain('urgent');
});

Request mocking config (conceptual — TBD during implementation):

# e2e/mocks.yaml
mocks:
  - requestId: search_products
    response:
      - _id: prod-1
        name: "Widget"
        score: 0.95
  - requestId: vector_search_docs
    response: []  # empty results for this test scenario

Acceptance Criteria

MongoDB in-memory:

  • Package created as @lowdefy/community-plugin-e2e-mdb
  • Package exports mdbFixtures object for use with test.extend(mdbFixtures)
  • Package has no dependency on @lowdefy/e2e-utils
  • Uses mongodb-memory-server — no external MongoDB required
  • Each Playwright worker gets isolated in-memory database instance
  • mdb.load('name') reads YAML snap files from e2e/snaps/<name>/ and restores collections
  • mdb.snap('name') creates/updates snap files from current database state
  • mdb.seed(collection, docs) clears collection and inserts provided documents
  • mdb.expect(collection).toContainDocument(filter) polls until document found or timeout
  • mdb.expect(collection).toHaveDocumentCount(n) polls until count matches
  • mdb.expect(collection).not.toContainDocument(filter) polls until document absent
  • mdb.collection(name) returns raw MongoDB collection for direct operations
  • Snap YAML format supports query match/project, replace/merge modes, and optional cleanup

Request mocking:

  • Developers can configure which Lowdefy requests to mock via config
  • Mocked requests return configured responses instead of hitting the (non-existent) Atlas features
  • Build/runtime changes in Lowdefy core (if needed) to support request interception in e2e mode

Related Work

Source

Brainstorm discussion about integrating MongoDB data tests into e2e testing. User wants to verify database state within the same e2e test — assert documents exist after UI actions, load/restore snapshots for test setup, seed data inline. Key decisions:

  • Community plugin package (not in core repo since it only supports MongoDB)
  • Fully decoupled from e2e-utils (exports fixture definitions, no dependency)
  • Use mongodb-memory-server for isolation, speed, and no external dependencies
  • Built-in request mocking for Atlas Search and other unsupported features (requires Lowdefy build changes + developer config)

Brief Agent - Created: 2026-02-04 CAT

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions