Skip to content

Instantly share code, notes, and snippets.

@adiralashiva8
Created February 25, 2026 07:28
Show Gist options
  • Select an option

  • Save adiralashiva8/1edb8e9f9d254e0fe07da945eef58bbf to your computer and use it in GitHub Desktop.

Select an option

Save adiralashiva8/1edb8e9f9d254e0fe07da945eef58bbf to your computer and use it in GitHub Desktop.
Github copilot Instruction to create keywords, locator and files by following same standards in Copilot AI Code Creation

GitHub Copilot Instructions for Veeva Vault CRM Automation Framework

Overview

This document provides instructions for GitHub Copilot to generate code that aligns with the Veeva Vault CRM Automation Framework built using Robot Framework. Follow these conventions strictly to maintain consistency across the codebase.


Project Architecture

Layer Hierarchy (Top to Bottom)

  1. Tests Layer (Vault/CRM/{Module}/tests/)

    • Contains .robot test files
    • Organized by test type: smoke/, regression/, api/
  2. Implementation Layer (Vault/CRM/{Module}/implementation/)

    • Contains .resource files with _impl suffix
    • Business logic and test step compositions
  3. Pages Layer (Vault/CRM/{Module}/pages/ and pages/)

    • Contains _page_keywords.resource files
    • Page-specific locators and keywords
  4. Resource Layer (Vault/CRM/{Module}/resource/)

    • Contains _keywords.resource files
    • Domain-specific reusable keywords
  5. Data Layer (Vault/CRM/{Module}/data/ and data/)

    • Contains .resource and .robot files
    • Test data, configurations, API endpoints
  6. Common Layer (common/)

    • common_resources.resource - Main aggregator
    • vault_common_resources.resource - Vault element keywords aggregator
    • common_libraries.resource - External library imports
  7. Keywords Layer (keywords/)

    • vault_elements/ - Element-level interaction keywords
    • vql/ - VQL query helpers
    • api/ - API request helpers
    • Utility keywords files

File Naming Conventions

Test Files (.robot)

{feature_name}.robot
{feature_name}_{test_type}.robot

Examples:

  • smoke.robot
  • create_account_regression.robot
  • create_accounts_api_regression.robot

Implementation Files (.resource)

{feature_name}_impl.resource
{feature_name}_{test_type}_impl.resource

Examples:

  • smoke_impl.resource
  • create_account_regression_impl.resource

Page Keywords Files (.resource)

{page_name}_page_keywords.resource
{object_type}_page_keywords.resource

Examples:

  • vault_login_page_keywords.resource
  • account_object_type_page_keywords.resource

Element Keywords Files (.resource)

vault_{element_type}_keywords.resource

Examples:

  • vault_button_keywords.resource
  • vault_dropdown_keywords.resource
  • vault_textbox_keywords.resource
  • vault_section_keywords.resource

Resource/Helper Files (.resource)

{domain}_{function}_keywords.resource
vault_{helper_type}_helper.resource

Examples:

  • account_common_keywords.resource
  • account_search_keywords.resource
  • vault_vql_helper.resource
  • vault_api_helper.resource

Data Files

{data_type}_data.resource
{config_type}.resource
api_end_points.robot

Keyword Naming Conventions

General Rules

  1. Use Title Case with spaces between words
  2. Start with an action verb for action keywords
  3. Use "Should" pattern for assertions
  4. Include "In Vault" suffix for Vault-specific operations
  5. Use descriptive, business-readable names

Action Keywords Pattern

{Action} {Target} In Vault
{Action} {Target} {Modifier} In Vault

Examples:

Click On Button In Vault
Input Text Into Textbox In Vault
Select Value From Dropdown In Vault
Expand Section In Vault
Navigate To Vault URL

Assertion Keywords Pattern

{Element} Should Be Present In Vault
{Element} Should Not Be Present In Vault
{Element}s Should Be Present In Vault
{Element} Should Contain Value In Vault
{Element} Value Should Be In Vault

Examples:

Button Should Be Present In Vault
Field Should Be Present In Vault
Fields Should Be Present In Vault
Dropdown Should Contain Values In Vault
Field Value Should Be In Vault
Checkbox Should Be Selected In Vault

Plural Keywords Pattern

Always create plural versions that iterate over lists:

*** Keywords ***
Field Should Be Present In Vault
    [Arguments]    ${name}    ${index}=1
    # single element logic

Fields Should Be Present In Vault
    [Arguments]    @{names}    ${index}=1
    Set Selenium Timeout To Very Short
    FOR    ${name}    IN    @{names}
        Run Keyword And Continue On Failure
        ...    Field Should Be Present In Vault    ${name}    ${index}
    END
    [Teardown]    Set Selenium Timeout To Regular

Private Keywords

Mark internal helper keywords with robot:private tag:

Get Textbox Locator In Vault
    [Tags]    robot:private
    [Arguments]    ${name}    ${index}
    ${locator}=    Replace Placeholders    ${VAULT_TEXTBOX_LOCATOR.textbox_locator}    NAME=${name}    INDEX=${index}
    Log    Textbox Locator: ${locator}
    RETURN    ${locator}

Implementation Keywords Pattern

Use business-readable composite names:

Sections Should Be Present In New Professional Account Page
Required Fields Should Be Present In New Professional Account Page
Fields Should Be Present In Existing Hospital Account Page
Actions Should Be Present On Professional Account For Sales User
Go To Random Account Record With Type Professional

Variable Naming Conventions

Global/Suite Variables

Use SCREAMING_SNAKE_CASE:

*** Variables ***
${BROWSER}    Chrome
${VAULT_APP_URL}    https://training-lab-31003.veevavault.com
${REGULAR_TIMEOUT}    20s
${SHORT_WAIT}    5s

Locator Variables

Use dictionary format with descriptive keys:

*** Variables ***
&{VAULT_BUTTON_LOCATOR}=
...    button_text_locator=xpath=(//button[normalize-space()='__NAME__' and ${VAULT_BUTTON_CONDITION}])[__INDEX__]
...    button_partial_text_locator=xpath=(//button[contains(normalize-space(),'__NAME__') and ${VAULT_BUTTON_CONDITION}])[__INDEX__]
...    button_with_attribute_locator=xpath=(//*[__ATB-WITH-VALUE__ and ${VAULT_BUTTON_CONDITION}])[__INDEX__]

${VAULT_FIELD_LOCATOR}
...    ${VAULT_FIELD_LABEL_LOCATOR_BY_NAME}/following-sibling::div[contains(@class,'right')]

Placeholder Pattern

Use __PLACEHOLDER__ format for dynamic values:

${LOCATOR}=    xpath=(//button[normalize-space()='__NAME__'])[__INDEX__]

Replace with Replace Placeholders keyword:

${locator}=    Replace Placeholders    ${VAULT_BUTTON_LOCATOR.button_text_locator}    NAME=${name}    INDEX=${index}

Test Data Variables

Use dictionaries for structured data:

*** Variables ***
&{DETAILS}
...    salutation=Dr.
...    first_name=QA
&{ADDRESS}
...    line=456 Elm Avenue
...    street=Apt 12B
...    city=San Francisco
...    state=CA
...    postal_code=94107

Local Variables

Use snake_case or lower_case:

${locator}=    Get Textbox Locator In Vault    ${name}    ${index}
${actual_text}=    Get Value    ${locator}
&{data}=    Execute VQL Query    SELECT id FROM account__v LIMIT 1

Locator Best Practices

Robust XPath Patterns

  1. Use normalize-space() for text matching:
//button[normalize-space()='Save']
  1. Use contains() for partial matches:
//div[contains(@class,'vv-loading')]
  1. Combine conditions with and:
//button[normalize-space()='__NAME__' and (contains(@class,'vv_button') or @type='button')]
  1. Use indexed locators with [__INDEX__]:
(//input[contains(@aria-label,"__NAME__")])[__INDEX__]
  1. Navigate DOM relationships:
${VAULT_FIELD_LABEL_LOCATOR_BY_NAME}/following-sibling::div[contains(@class,'right')]
//label[contains(normalize-space(),'__NAME__')]/preceding-sibling::input

Locator Strategy Priority

  1. Prefer relative locators over absolute paths
  2. Use semantic attributes: @aria-label, @role, @type
  3. Use class names with contains() for Vault-specific classes
  4. Avoid brittle indexes unless necessary
  5. Make locators parameterized with placeholders

Common Vault Locator Patterns

# Field by label
${VAULT_FIELD_LABEL_LOCATOR_BY_NAME}
...    (//div[contains(@class,'label') and .//label[contains(normalize-space(),'__NAME__')]])[__INDEX__]

# Input within field
${VAULT_TEXTBOX_LOCATOR}=
...    textbox_locator=xpath=${VAULT_FIELD_LOCATOR}//input

# Dropdown option
...    dropdown_option_locator=xpath=(//ul[@role="listbox"]//li[@role='option' and contains(normalize-space(),'__OPTION__')])[__INDEX__]

# Section header
${SECTION_HEADER_LOCATOR}
...    (//div[(contains(@class,'-section') and @aria-expanded) and .//*[normalize-space()='__NAME__']])[__INDEX__]

Test Case Structure

Standard Test File Template

*** Settings ***
Resource            ${EXECDIR}/Vault/CRM/{Module}/implementation/{type}/{feature}_impl.resource
Test Setup          Login To Vault Application
Test Teardown       Close Current Session
Test Tags           {module}    {test_type}


*** Test Cases ***
{Descriptive Test Case Name}
    [Tags]    {owner}    {xray_id}    {priority}
    {Step 1 - Setup/Navigation}
    {Step 2 - Action}
    {Step 3 - Verification}
    {Step 4 - Cleanup if needed}

Test Tags Convention

  • Module tag: accounts, cases, etc.
  • Test type: smoke, regression, webservices
  • Owner: lowercase username (e.g., adirala, kumar)
  • Xray ID: vevt-{number} format
  • Priority: low, medium, high, veryhigh

Example:

Validate User Able To Create Professional Account Using API
    [Tags]    vevt-4521    high    shiva

API Test Template

*** Settings ***
Resource            ${EXECDIR}/Vault/CRM/{Module}/implementation/api/{feature}_api_impl.robot
Test Setup          API Test Setup
Test Teardown       API Test Teardown
Test Tags           {module}    webservices    regression

Implementation File Structure

Standard Implementation Template

*** Settings ***
Resource    ${EXECDIR}/common/common_resources.resource
Resource    ${EXECDIR}/Vault/CRM/{Module}/resource/{module}_common_keywords.resource


*** Variables ***
&{DATA_DICTIONARY}
...    key1=value1
...    key2=value2


*** Keywords ***
{Business Logic Keyword}
    # Compose element-level keywords into business actions
    Click On Section In Vault Side Navigator    Details
    Fields Should Be Present In Vault    Name    Status    Type
    Textbox Fields Should Be Present In Vault    Name
    Dropdown Fields Should Be Present In Vault    Status    Type

Element Keywords File Structure

Standard Element Keywords Template

*** Settings ***
Resource    ${EXECDIR}/common/common_resources.resource


*** Variables ***
&{VAULT_{ELEMENT}_LOCATOR}=
...    {element}_locator=xpath={xpath_pattern}


*** Keywords ***
{Element} Should Be Present In Vault
    [Arguments]    ${name}    ${index}=1
    ${locator}=    Get {Element} Locator In Vault    ${name}    ${index}
    Wait Until Page Contains Element    ${locator}

{Element} Fields Should Be Present In Vault
    [Arguments]    @{names}    ${index}=1
    Set Selenium Timeout To Very Short
    FOR    ${name}    IN    @{names}
        Run Keyword And Continue On Failure
        ...    {Element} Should Be Present In Vault    ${name}    ${index}
    END
    [Teardown]    Set Selenium Timeout To Regular

{Element} Should Not Be Present In Vault
    [Arguments]    ${name}    ${index}=1
    ${locator}=    Get {Element} Locator In Vault    ${name}    ${index}
    Wait Until Page Does Not Contain Element    ${locator}

{Element} Fields Should Not Be Present In Vault
    [Arguments]    @{names}    ${index}=1
    Set Selenium Timeout To Very Short
    FOR    ${name}    IN    @{names}
        Run Keyword And Continue On Failure
        ...    {Element} Should Not Be Present In Vault    ${name}    ${index}
    END
    [Teardown]    Set Selenium Timeout To Regular

Get {Element} Locator In Vault
    [Tags]    robot:private
    [Arguments]    ${name}    ${index}
    ${locator}=    Replace Placeholders    ${VAULT_{ELEMENT}_LOCATOR.{element}_locator}    NAME=${name}    INDEX=${index}
    Log    {Element} Locator: ${locator}
    RETURN    ${locator}

Common Patterns and Utilities

Wait Patterns

Wait Until Vault Page Is Loaded
    [Timeout]    ${VERY_LONG_TIMEOUT}
    Sleep    ${VERY_SHORT_WAIT}
    Wait Until DOM Content Loaded In Vault
    Wait Until Vault Loading Image Is Not Visible
    Wait Until Vault Loading Indicator Is Not Visible
    Wait Until Vault Loading Is Not Visible
    Wait Until Vault Loading Spinner Is Not Visible

Click Pattern with Scroll

Click On WebElement
    [Arguments]    ${locator}
    Wait Until Page Contains Element    ${locator}
    Wait Until Element Is Visible    ${locator}
    Scroll To Element Using Javascript    ${locator}
    Click Element    ${locator}

Input Text Pattern

Input Text Into Textbox
    [Arguments]    ${locator}    ${text}
    Wait Until Page Contains Element    ${locator}
    TRY
        Wait Until Element Is Visible    ${locator}
        Wait Until Element Is Enabled    ${locator}
        Scroll To Element Using Javascript    ${locator}
    EXCEPT
        Log    Element "${locator}" is not visible yet.
    END
    Input Text    ${locator}    ${text}

VQL Query Pattern

Execute VQL Query
    [Arguments]    ${vql_query}
    &{headers}=    Create Dictionary
    ...    Accept=application/json
    ...    Content-Type=application/x-www-form-urlencoded
    ...    Authorization=${SESSION_ID_COOKIE}
    &{body}=    Create Dictionary
    ...    q=${vql_query}
    ${response}=    POST    ${VAULT_APP_URL}/api/v20.2/query    headers=${headers}    data=${body}
    Should Be Equal As Integers    ${response.status_code}    200
    &{data}=    Set Variable    ${response.json()}[data][0]
    Log Dictionary    ${data}
    RETURN    &{data}

Navigate to Record Pattern

Go To Random Account Record With ID
    [Arguments]    ${account_id}    ${account_name}    ${edit_mode}=${False}
    ${url}=    Get Vault Object Standard URL For Record    ${ACCOUNT_OBJECT}    ${account_id}
    Navigate To Vault URL    ${url}
    Wait Until Vault Page Is Loaded
    Wait Until Page Contains    ${account_name}
    IF    ${edit_mode}
        Select Option From Actions    All Actions    Edit
        Wait Until Vault Page Is Loaded
    END
    Log    Navigated to Account Record with ID: ${account_id} and Name: ${account_name}

Impersonation Pattern

Impersonate User In Vault
    [Arguments]    ${user_name}
    &{data}=    Get User Record Information Using VQL    ${user_name}
    ${end_url}=    Get Vault Object Standard URL For Record    user__sys    ${data.id}
    Navigate To Vault URL    ${end_url}
    Select Option From Actions    All Actions    Log In As
    Click On Button In Vault    Log In As
    Wait Until Vault Page Is Loaded
    Viewer Banner Should Be Present
    Logged In As User Message Should Be Displayed    ${user_name}

Resource Import Pattern

Main Common Resource (common_resources.resource)

*** Settings ***
Resource    ${EXECDIR}/common/common_libraries.resource
Resource    ${EXECDIR}/common/vault_common_resources.resource
Resource    ${EXECDIR}/data/config.resource
# keywords
Resource    ${EXECDIR}/keywords/util_keywords.resource
Resource    ${EXECDIR}/keywords/javascript_keywords.resource
Resource    ${EXECDIR}/keywords/web_setup_keywords.resource
# vql
Resource    ${EXECDIR}/keywords/vql/vault_vql_helper.resource
# api
Resource    ${EXECDIR}/keywords/api/vault_api_helper.resource
# common
Resource    ${EXECDIR}/keywords/vault_common_keywords.resource
Resource    ${EXECDIR}/keywords/vault_impersonate_user_keywords.resource

Vault Common Resources (vault_common_resources.resource)

*** Settings ***
# element level keywords
Resource    ${EXECDIR}/keywords/vault_elements/vault_button_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_checkbox_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_dialog_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_dropdown_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_field_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_lookup_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_radio_button_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_searchbox_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_section_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_tab_collection_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_tab_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_textarea_keywords.resource
Resource    ${EXECDIR}/keywords/vault_elements/vault_textbox_keywords.resource
# common keywords
Resource    ${EXECDIR}/keywords/vault_wait_keywords.resource

Implementation File Import

*** Settings ***
Resource    ${EXECDIR}/common/common_resources.resource
Resource    ${EXECDIR}/Vault/CRM/{Module}/resource/{module}_common_keywords.resource

Timeout and Wait Configuration

Standard Timeouts

${VERY_SHORT_TIMEOUT}    2s
${SHORT_TIMEOUT}    5s
${REGULAR_TIMEOUT}    20s
${LONG_TIMEOUT}    30s
${VERY_LONG_TIMEOUT}    2m

Standard Waits

${VERY_SHORT_WAIT}    2s
${SHORT_WAIT}    5s
${MEDIUM_WAIT}    10s
${LONG_WAIT}    15s
${VERY_LONG_WAIT}    30s

Timeout Management Pattern

# Before iterating with short waits
Set Selenium Timeout To Very Short

# After iteration, restore
[Teardown]    Set Selenium Timeout To Regular

Error Handling Patterns

Continue on Failure for Bulk Assertions

FOR    ${name}    IN    @{names}
    Run Keyword And Continue On Failure
    ...    Field Should Be Present In Vault    ${name}    ${index}
END

TRY-EXCEPT for Optional Operations

TRY
    Wait Until Element Is Visible    ${locator}
    Wait Until Element Is Enabled    ${locator}
    Scroll To Element Using Javascript    ${locator}
EXCEPT
    Log    Element "${locator}" is not visible yet.
END

API Test Patterns

API Headers Pattern

&{headers}=    Create Dictionary
...    Accept=application/json
...    Content-Type=application/x-www-form-urlencoded
...    Authorization=${SESSION_ID_COOKIE}

API Response Validation

Response Status Code Should Be    200
Response Status Message Should Be    SUCCESS
Remember Record ID From Response

Soft Assert Pattern

Field Value Should Be In Vault
    [Arguments]    ${name}    ${expected_value}    ${index}=1    ${soft_assert}=False
    ${locator}=    Get Vault Field Locator    ${name}    ${index}
    Wait Until Page Contains Element    ${locator}
    ${actual_value}=    Get Text    ${locator}
    IF    ${soft_assert}
        Run Keyword And Continue On Failure
        ...    Should Be Equal As Strings    ${actual_value}    ${expected_value}
    ELSE
        Should Be Equal As Strings    ${actual_value}    ${expected_value}
    END

DO's and DON'Ts

DO

  • ✅ Use ${EXECDIR} for all resource imports
  • ✅ Use Wait Until Vault Page Is Loaded after navigation
  • ✅ Use plural keywords for bulk operations
  • ✅ Add [Tags] robot:private for internal helpers
  • ✅ Use Replace Placeholders for dynamic locators
  • ✅ Log locators in private getter keywords
  • ✅ Use dictionaries for structured data
  • ✅ Follow the layer hierarchy for imports
  • ✅ Use Run Keyword And Continue On Failure for bulk assertions
  • ✅ Use descriptive, business-readable keyword names

DON'T

  • ❌ Import element keywords directly in test files
  • ❌ Hardcode locators in keywords
  • ❌ Use absolute XPaths
  • ❌ Skip the In Vault suffix for Vault operations
  • ❌ Use Sleep without a specific reason (prefer explicit waits)
  • ❌ Create test files without proper tags
  • ❌ Mix implementation logic with test cases
  • ❌ Use camelCase for variable names
  • ❌ Skip the index parameter in locator keywords
  • ❌ Create keywords without proper documentation intent

Quick Reference: Element Type Keywords to Create

When creating a new element type, implement these keywords:

  1. {Element} Should Be Present In Vault
  2. {Element} Fields Should Be Present In Vault (plural)
  3. {Element} Should Not Be Present In Vault
  4. {Element} Fields Should Not Be Present In Vault (plural)
  5. Get {Element} Locator In Vault (private)
  6. Interaction keywords (Click, Input, Select, etc.)
  7. Value assertion keywords (Should Contain, Should Be, etc.)

Example: Creating a New Module

1. Create Directory Structure

Vault/CRM/{NewModule}/
├── tests/
│   ├── smoke/
│   │   └── smoke.robot
│   └── regression/
│       └── {feature}_regression.robot
├── implementation/
│   ├── smoke/
│   │   └── smoke_impl.resource
│   └── regression/
│       └── {feature}_regression_impl.resource
├── pages/
│   └── {page}_page_keywords.resource
├── resource/
│   └── {module}_common_keywords.resource
└── data/
    └── {module}_data.resource

2. Create Test File

*** Settings ***
Resource            ${EXECDIR}/Vault/CRM/{NewModule}/implementation/smoke/smoke_impl.resource
Test Setup          Login To Vault Application
Test Teardown       Close Current Session
Test Tags           {newmodule}    smoke


*** Test Cases ***
Validate Available Fields In {Record Type}
    [Tags]    {owner}    vevt-{id}    medium
    Go To {Module} Tab
    Go To Random {Record Type} Record
    Sections Should Be Present In {Record Type} Page
    Required Fields Should Be Present In {Record Type} Page
    Fields Should Be Present In {Record Type} Page

This instruction file is auto-generated based on workspace analysis. Last updated: February 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment