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.
-
Tests Layer (
Vault/CRM/{Module}/tests/)- Contains
.robottest files - Organized by test type:
smoke/,regression/,api/
- Contains
-
Implementation Layer (
Vault/CRM/{Module}/implementation/)- Contains
.resourcefiles with_implsuffix - Business logic and test step compositions
- Contains
-
Pages Layer (
Vault/CRM/{Module}/pages/andpages/)- Contains
_page_keywords.resourcefiles - Page-specific locators and keywords
- Contains
-
Resource Layer (
Vault/CRM/{Module}/resource/)- Contains
_keywords.resourcefiles - Domain-specific reusable keywords
- Contains
-
Data Layer (
Vault/CRM/{Module}/data/anddata/)- Contains
.resourceand.robotfiles - Test data, configurations, API endpoints
- Contains
-
Common Layer (
common/)common_resources.resource- Main aggregatorvault_common_resources.resource- Vault element keywords aggregatorcommon_libraries.resource- External library imports
-
Keywords Layer (
keywords/)vault_elements/- Element-level interaction keywordsvql/- VQL query helpersapi/- API request helpers- Utility keywords files
{feature_name}.robot
{feature_name}_{test_type}.robot
Examples:
smoke.robotcreate_account_regression.robotcreate_accounts_api_regression.robot
{feature_name}_impl.resource
{feature_name}_{test_type}_impl.resource
Examples:
smoke_impl.resourcecreate_account_regression_impl.resource
{page_name}_page_keywords.resource
{object_type}_page_keywords.resource
Examples:
vault_login_page_keywords.resourceaccount_object_type_page_keywords.resource
vault_{element_type}_keywords.resource
Examples:
vault_button_keywords.resourcevault_dropdown_keywords.resourcevault_textbox_keywords.resourcevault_section_keywords.resource
{domain}_{function}_keywords.resource
vault_{helper_type}_helper.resource
Examples:
account_common_keywords.resourceaccount_search_keywords.resourcevault_vql_helper.resourcevault_api_helper.resource
{data_type}_data.resource
{config_type}.resource
api_end_points.robot
- Use Title Case with spaces between words
- Start with an action verb for action keywords
- Use "Should" pattern for assertions
- Include "In Vault" suffix for Vault-specific operations
- Use descriptive, business-readable names
{Action} {Target} In Vault
{Action} {Target} {Modifier} In VaultExamples:
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{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 VaultExamples:
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 VaultAlways 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 RegularMark 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}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 ProfessionalUse SCREAMING_SNAKE_CASE:
*** Variables ***
${BROWSER} Chrome
${VAULT_APP_URL} https://training-lab-31003.veevavault.com
${REGULAR_TIMEOUT} 20s
${SHORT_WAIT} 5sUse 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')]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}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=94107Use 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- Use
normalize-space()for text matching:
//button[normalize-space()='Save']
- Use
contains()for partial matches:
//div[contains(@class,'vv-loading')]
- Combine conditions with
and:
//button[normalize-space()='__NAME__' and (contains(@class,'vv_button') or @type='button')]
- Use indexed locators with
[__INDEX__]:
(//input[contains(@aria-label,"__NAME__")])[__INDEX__]
- Navigate DOM relationships:
${VAULT_FIELD_LABEL_LOCATOR_BY_NAME}/following-sibling::div[contains(@class,'right')]
//label[contains(normalize-space(),'__NAME__')]/preceding-sibling::input
- Prefer relative locators over absolute paths
- Use semantic attributes:
@aria-label,@role,@type - Use class names with
contains()for Vault-specific classes - Avoid brittle indexes unless necessary
- Make locators parameterized with placeholders
# 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__]*** 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}- 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*** 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*** 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*** 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}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 VisibleClick 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 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}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}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}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}*** 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*** 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*** Settings ***
Resource ${EXECDIR}/common/common_resources.resource
Resource ${EXECDIR}/Vault/CRM/{Module}/resource/{module}_common_keywords.resource${VERY_SHORT_TIMEOUT} 2s
${SHORT_TIMEOUT} 5s
${REGULAR_TIMEOUT} 20s
${LONG_TIMEOUT} 30s
${VERY_LONG_TIMEOUT} 2m${VERY_SHORT_WAIT} 2s
${SHORT_WAIT} 5s
${MEDIUM_WAIT} 10s
${LONG_WAIT} 15s
${VERY_LONG_WAIT} 30s# Before iterating with short waits
Set Selenium Timeout To Very Short
# After iteration, restore
[Teardown] Set Selenium Timeout To RegularFOR ${name} IN @{names}
Run Keyword And Continue On Failure
... Field Should Be Present In Vault ${name} ${index}
ENDTRY
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&{headers}= Create Dictionary
... Accept=application/json
... Content-Type=application/x-www-form-urlencoded
... Authorization=${SESSION_ID_COOKIE}Response Status Code Should Be 200
Response Status Message Should Be SUCCESS
Remember Record ID From ResponseField 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- ✅ Use
${EXECDIR}for all resource imports - ✅ Use
Wait Until Vault Page Is Loadedafter navigation - ✅ Use plural keywords for bulk operations
- ✅ Add
[Tags] robot:privatefor internal helpers - ✅ Use
Replace Placeholdersfor 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 Failurefor bulk assertions - ✅ Use descriptive, business-readable keyword names
- ❌ Import element keywords directly in test files
- ❌ Hardcode locators in keywords
- ❌ Use absolute XPaths
- ❌ Skip the
In Vaultsuffix for Vault operations - ❌ Use
Sleepwithout 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
When creating a new element type, implement these keywords:
{Element} Should Be Present In Vault{Element} Fields Should Be Present In Vault(plural){Element} Should Not Be Present In Vault{Element} Fields Should Not Be Present In Vault(plural)Get {Element} Locator In Vault(private)- Interaction keywords (Click, Input, Select, etc.)
- Value assertion keywords (Should Contain, Should Be, etc.)
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
*** 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} PageThis instruction file is auto-generated based on workspace analysis. Last updated: February 2025