Skip to main content

Flow Model

The Flow model represents automation test flows that can be executed on Android devices. It contains the flow definition, execution logic, and caching information.

Schema Definition

model Flow {
id String @id @default(uuid())
name String
testInstructions String
targetDevice String
setupHooks String[]
tearDownHooks String[]
cachedParsedCommand Json?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
cachedSetupHooks Json?
cachedTeardownHooks Json?
displayOrder Int @default(0)
isSubflow Boolean @default(false)
labels String[] @default([])
subflowReferences Json?
coordinateCache FlowCoordinateCache[]
recordings Recording[]
}

Field Descriptions

Primary Fields

FieldTypeDescription
idStringUUID primary key
nameStringHuman-readable flow name
testInstructionsStringNatural language description of what the flow does
targetDeviceStringTarget device identifier for execution

Hook System (Legacy)

FieldTypeDescription
setupHooksString[]Array of raw command strings to run before flow execution
tearDownHooksString[]Array of raw command strings to run after flow execution

Cached Data

FieldTypeDescription
cachedParsedCommandJson?Parsed and structured command representation
cachedSetupHooksJson?Processed setup hook data
cachedTeardownHooksJson?Processed teardown hook data

Organization

FieldTypeDescription
displayOrderIntOrder for displaying flows in UI (default: 0)
isSubflowBooleanWhether this flow can be used as a subflow (default: false)
labelsString[]Array of label strings for organization
subflowReferencesJson?Structured references to setup/teardown subflows

Metadata

FieldTypeDescription
createdAtDateTimeCreation timestamp
updatedAtDateTimeLast update timestamp

Relationships

One-to-Many

  • coordinateCache: FlowCoordinateCache[] - Cached UI element coordinates for this flow
  • recordings: Recording[] - Associated automation session recordings

Usage Examples

Creating a Basic Flow

const flow = await prisma.flow.create({
data: {
name: "Login Test",
testInstructions: "Test user login functionality",
targetDevice: "emulator-5554",
labels: ["authentication", "smoke-test"]
}
});

Creating a Flow with Hooks

const flow = await prisma.flow.create({
data: {
name: "Complete User Journey",
testInstructions: "Test full user registration and login",
targetDevice: "device-123",
setupHooks: [
"launch_app com.example.app",
"wait 2000"
],
tearDownHooks: [
"force_stop com.example.app"
],
labels: ["registration", "integration"]
}
});

Creating a Subflow

const subflow = await prisma.flow.create({
data: {
name: "Login Helper",
testInstructions: "Reusable login steps",
targetDevice: "any",
isSubflow: true,
labels: ["helper", "authentication"]
}
});

Flow with Subflow References

const flow = await prisma.flow.create({
data: {
name: "E-commerce Test Suite",
testInstructions: "Complete e-commerce user journey",
targetDevice: "device-456",
subflowReferences: {
setupSubflowReferences: [
{
flowId: "setup-environment",
preSubflowDelay: 1000,
postSubflowDelay: 500
}
],
teardownSubflowReferences: [
{
flowId: "cleanup-data",
preSubflowDelay: 0,
postSubflowDelay: 1000
}
]
},
labels: ["ecommerce", "integration"]
}
});

Query Examples

Find Flows by Labels

const authFlows = await prisma.flow.findMany({
where: {
labels: {
hasSome: ["authentication"]
}
}
});

Get Flow with Relations

const flow = await prisma.flow.findUnique({
where: { id: "flow-123" },
include: {
coordinateCache: true,
recordings: {
orderBy: { createdAt: "desc" },
take: 5
}
}
});

Get Flows for Device

const deviceFlows = await prisma.flow.findMany({
where: {
OR: [
{ targetDevice: "emulator-5554" },
{ targetDevice: "any" }
]
},
orderBy: { displayOrder: "asc" }
});

Update Flow Labels

await prisma.flow.update({
where: { id: "flow-123" },
data: {
labels: {
push: "new-label"
}
}
});

Migration Notes

From Legacy Hooks to Subflows

The schema supports both legacy string-based hooks and modern subflow references:

Legacy (still supported):

{
"setupHooks": ["launch_app com.example.app", "wait 2000"],
"tearDownHooks": ["force_stop com.example.app"]
}

Modern (recommended):

{
"subflowReferences": {
"setupSubflowReferences": [
{
"flowId": "app-launch-flow",
"preSubflowDelay": 1000,
"postSubflowDelay": 500
}
]
}
}

Coordinate Caching

UI element coordinates are cached separately in FlowCoordinateCache for performance. This allows different coordinate sets for the same flow on different devices/screen sizes.

Recording Association

Recordings are linked to flows to provide execution history and debugging capabilities. Multiple recordings can be associated with a single flow.

Performance Considerations

Indexing

  • Primary key on id
  • Consider index on targetDevice for device-specific queries
  • Consider GIN index on labels for label filtering
  • Index on displayOrder for sorted listings
  • Index on isSubflow for subflow filtering

Query Optimization

  • Use select to fetch only needed fields
  • Include relations only when necessary
  • Use pagination for large result sets
  • Cache frequently accessed flows

Data Volume

  • JSON fields can store complex data structures
  • Consider archiving old execution data
  • Regular cleanup of unused coordinate cache entries