Object-Oriented Programming (OOP) Cheat Sheet for LATP Developers
This cheat sheet explains the core Object-Oriented Programming (OOP) concepts used in the LATP (LENS AI Test Pilot) automation framework, using examples from action.ts file.
Object-Oriented Programming is a programming paradigm that organizes code using objects and classes, making systems modular, reusable, and easier to maintain.
1. Abstract Classes
An Abstract Class defines common structure and behavior for other classes, but cannot be instantiated directly.
It is meant to be extended by child classes.
Use it when
- Multiple classes share common properties
- Multiple classes share common methods
- You want to enforce a consistent structure for all child classes
Common Syntax
abstract class clAction {
action: string; actionData: TTactionsData;
constructor(iAction: string, iaActionData: TTactionsData) { this.action = iAction; this.actionData = iaActionData; }
executeAction(): void {}
}Real LATP Use Case
In action.ts, the base class for all actions is clAction.
clAction (Abstract Base) │ ├── clActionOnLoad ├── clActionOnChange ├── clActionAddRow ├── clActionSave ├── clActionSubmitExample:
export class clActionOnChange extends clActionThis ensures every action class follows the same structure.
2. Inheritance
Inheritance allows a class to reuse properties and methods from another class.
A child class extends a parent class and can add or modify behavior.
Use it when
- Multiple classes share common logic
- You want to avoid duplicate code
- Child classes only need small variations of parent logic
Common Syntax
class clActionSave extends clAction {
executeAction(): void { cy.get('.primary-action').click(); }
}Real LATP Use Case
Example from LATP code:
export class clActionAmend extends clActionSave { protected lActionMessage: string = "amend successfully.";}Structure:
clAction│└── clActionSave │ └── clActionAmendclActionAmend reuses the Save logic but changes the message.
3. Polymorphism
Polymorphism means different classes implement the same method in different ways.
The caller does not need to know which class is executing.
Use it when
- Multiple classes must implement the same method
- Behavior changes depending on action type
- The execution engine should remain generic
Common Syntax
class clActionSubmit extends clAction {
executeAction(): void { cy.contains('button', 'Submit').click(); }
}
class clActionCancel extends clAction {
executeAction(): void { cy.contains('button', 'Cancel').click(); }
}Both classes implement the same method:
executeAction()But their behavior is different.
Real LATP Use Case
The action execution engine calls actions generically:
const action = clActionFactory.createAction(iAction, actionData);
action.executeAction();The engine does not know the actual class type.
Possible classes include:
clActionSaveclActionSubmitclActionDeleteclActionAddRowclActionOnChangeEach class implements its own behavior.
4. Factory Pattern
A Factory Pattern is a design pattern used to create objects dynamically based on input.
Instead of writing large if or switch statements, object creation is centralized.
Use it when
- Many classes represent different behaviors
- Object creation depends on runtime configuration
- You want scalable and maintainable code
Common Syntax
static createAction(iAction: string, iaActionData: TTactionsData) {
const ActionClass = this.actionsMap[iAction];
if (!ActionClass) { throw new Error(`Invalid action type`); }
return new ActionClass(iAction, iaActionData);
}Real LATP Use Case
In LATP Test Case configurator, actions are stored as text:
On ChangeSaveSubmitAPI GETThe factory maps them to classes:
private static actionsMap = { "On Change": clActionOnChange, "Save": clActionSave, "Submit": clActionSubmit,}Example usage:
clActionFactory.createAction("Save", data);Which creates:
new clActionSave()5. Composition
Composition means a class uses other classes to perform part of its work.
Instead of extending everything through inheritance, classes delegate responsibilities to helper components.
Use it when
- A class depends on other services
- Logic should be modular
- You want flexible architecture
Common Syntax
this.dataType = clDataTypeFactory.createDataType(ldRow.data_type, this);Here clAction uses another factory class.
Real LATP Use Case
Inside clAction.executeAction():
this.dataType = clDataTypeFactory.createDataType(ldRow.data_type, this);
this.checkFieldValue();this.checkFieldProperties();Architecture:
clAction│├── clDataTypeFactory│ ├── Text│ ├── Int│ └── Float│└── clPropertiesFactory ├── Required ├── ReadOnly └── HiddenThe action class delegates validation logic to these components.