Appian Locust Library documentation
What is Appian Locust?
Appian Locust is a wrapper library around Locust for load testing Appian. This library is intended to be used as an alternative to tools such as Jmeter and Load Runner.
Appian Locust capabilities
Logging in and logging out
Form interactions (filling/submitting)
Finding and interacting with basic components on a SAIL interface
Navigating to records/reports/sites
What is Locust?
It’s an open source python library for doing load testing (think JMeter, but in Python). It is by default HTTP-driven, but can be made to work with other types of interactions. Visit Locust for more information.
Locust has the benefit of relying purely on API requests, which makes it lower overhead than frameworks building
on Selenium or browser automation libraries. We have also found python to be common denominator across software and quality engineers,
making it a convenient language for extending the framework and defining tests.
Using Locust’s model of TaskSets
and TaskSequences
, it is easy to compose user operations in a maintainable way.
Appian-Locust builds on these concepts by defining AppianTaskSet
and AppianTaskSequence
, which layer on Appian-specific
functionality such as login and session management.
Quick Installation Guide
This is a quick guide to getting up and running with the appian-locust library. You will need Python 3.10 installed on your machine before proceeding.
Setup
Install appian-locust using pip, for more comprehensive projects we recommend using pipenv.
pip install appian-locust
If using pipenv
, simply start from the following Pipfile
:
[packages]
appian-locust = {version = "*"}
[requires]
python_version = "3.10"
[pipenv]
allow_prereleases = true
Download the sample test example_locustfile.py from the Appian Locust repo and run it.
locust -f example_locustfile.py
If everything is set up correctly, you should see a link to the Locust web interface, which you can use to start test runs and view results.
For more information about how to build the workflow for your locust test, see the How to Write a Locust Test section.
For more information on running locust tests, see the How to Run Locust section.
Build from source
Clone the repository:
git clone -o prod git@gitlab.com:appian-oss/appian-locust.git
Install the library globally:
pip install -e appian-locust
If you’re using a virtualenv or a dependency management tool (e.g. pipenv
), you can do the same type of install, but you will want to be in the context of the virtualenv (i.e. source the virtualenv), and you’ll need to pass the path to the repository you cloned.
Note: It’s highly recommended that you use a virtual environment when installing python artifacts. You can follow the instructions here to install virtualenv and pip.
If you have issues installing, make sure you have the proper prerequisites installed for Locust and its dependencies. If you’re having trouble on Windows, check here
Troubleshooting
Do not have permissions to clone appian-locust
Ensure you have added you ssh key to your profile. See here for how to do this.
“locust is not available”
Verify that you ran
pip install -e appian-locust
“Failed to establish a new connection: [Errno 8] nodename nor servname provided, or not known”
check that
host_address
is specified correctly in your locust test file.
“Login unsuccessful, no multipart cookie found…make sure credentials are correct”
check that auth specifies a valid username and password combination for the site you’re testing on in your locust test file.
“General request and response debugging”
Add
self.client.record_mode = True
to yourHttpUser
subclass. Files will be placed in/record_responses
where the runner is executed.
How to Write a Locust Test
The majority of the work involved in writing Appian Locust tests is around creating Locust Tasks. Each Task represents a workflow for a virtual Locust user to execute.
This section will go over how to get started writing tasks and introduce the two core Appian Locust concepts: the Visitor
class and the SailUiForm
class.
Sample Workflow
For this workflow, we will use the Employee Record Type found in the Appian documentation. We will implement a Locust Task that will create a new Employee record. The specific workflow will be as follows:
Navigate to the Employee Record List
Click the “New Employee” button
Fill in the First Name, Last Name, Department, Title, and Phone Number fields
Click the “Create” button
UI Interactions - SailUiForm
Now that we have navigated to the Employee Record List, we need to execute the workflow steps that will create the new Employee.
As briefly touched on above, all navigations done via the Visitor return a SailUiForm
which is capable of performing interactions with a UI.
SailUiForm supports filling in text fields
,
clicking buttons
and more.
In our specific case, because we navigated to a Record list, our visitor returned a subclass of the SailUiForm: the RecordListUiForm
. Some types of
interfaces in Appian have a specific subclass that will support additional functionality catered to the kind of interface it represents. The RecordListUiForm will enable us to click
on the Record List Action which is unique to Record Lists via click_record_list_action
, like so:
@task
def create_new_employee(self):
# Navigate to Employee Record List
record_list_uiform = self.appian.visitor.visit_record_type(record_type="Employees")
# Click on "New Employee" Record List Action
record_list_uiform.click_record_list_action(label="New Employee")
As shown above, in many cases the only thing required to interact with a UI element is the label associated with that element.
At this point in the workflow, the dialog to create a new employee has been launched. Now we can use the various other interactions supported by the base SailUiForm class which are available on all of its subclasses to fill out the new Employee’s information:
@task
def create_new_employee(self):
# Navigate to Employee Record List
record_list_uiform = self.appian.visitor.visit_record_type(record_type="Employees")
# Click on "New Employee" Record List Action
record_list_uiform.click_record_list_action(label="New Employee")
# Fill in new Employee information
record_list_uiform.fill_text_field(label="First Name", value="Sample")
record_list_uiform.fill_text_field(label="Last Name", value="User")
record_list_uiform.fill_text_field(label="Department", value="Engineering")
record_list_uiform.fill_text_field(label="Title", value="Senior Software Engineer")
record_list_uiform.fill_text_field(label="Phone Number", value="(703) 442-8844")
Now all we need to do is click the “Create” button, and our new Employee will be created!
@task
def create_new_employee(self):
# Navigate to Employee Record List
record_list_uiform = self.appian.visitor.visit_record_type(record_type="Employees")
# Click on "New Employee" Record List Action
record_list_uiform.click_record_list_action(label="New Employee")
# Fill in new Employee information
record_list_uiform.fill_text_field(label="First Name", value="Sample")
record_list_uiform.fill_text_field(label="Last Name", value="User")
record_list_uiform.fill_text_field(label="Department", value="Engineering")
record_list_uiform.fill_text_field(label="Title", value="Senior Software Engineer")
record_list_uiform.fill_text_field(label="Phone Number", value="(703) 442-8844")
# Create Employee!
record_list_uiform.click_button(label="Create")
If you run a locust test with the task above, you should be able to check the Employee record list and see the “Sample User” employees that the virtual Locust user just made! You can see a full version of a locust test including the task we just wrote here.
How to Run Locust
Once you have the library installed, you can simply follow the output from running locust -h
to run your test.
Note that if you don’t specify a locustfile with -f FILE_NAME
, locust will look for a file called locustfile in the current directory by default.
Command Line Flow
If you’re running Locust somewhere where there is no web ui, or you don’t want to bother with the web flow, I tend to run Locust like so:
locust -f examples/example_locustfile.py -u 1 -r 10 -t 3600 --headless
Required Arguments
This is the bare minimum to run a Locust test without the web view. You’ll notice you need to specify:
The hatch rate (-r is for rate)
The number of users (-u is for users)
The time of the test (-t) in seconds
The –headless flag
Once you run this command, the test will start immediately, and start logging output. It should run for the duration you run the test, and hitting ctrl+c may orphan some locusts. Some arguments that we use are
–csv-full-history -> prints out the different percentile changes every 30 seconds
It’s recommended to capture log file output when running Locust as well, i.e. | tee run.log
Web Flow
If you supply no arguments to locust
other than the locustfile, Locust will launch in a web mode. This is not recommended, mainly because you can’t automate running it as it requires manual interaction as well as access to the flask application.
locust -f example_locustfile.py
If you navigate to http://localhost:8089/ you’ll see the following:

These arguments map to the same arguments described in the Required Arguments section.
Once you hit “start swarming”, you’ll see graphs reporting latencies, errors, and other data. These can be useful for visually understanding how a load test is performing.
Debugging
Oftentimes you will encounter errors or not get the appropriate load you expect when running tests.
Things you can use to get more information:
Add print statements to your Locust code or the installed
appian-locust
libraryInspect the output of the latencies that Locust periodically prints out, to see if certain requests are much slower than you expect
Verify using the browser console that the requests you are attempting to simulate match up with what Locust/appian-locust is sending
Setting the “record_mode” attribute to True on your HttpUser’s
client
object will create a “recorded_responses” folder which will contain all requests and responses sent during test execution. You can do this in the__init__
method of your HttpUser, like so:
def __init__(self, environment) -> None:
super().__init__(environment)
self.client.record_mode = True
Limitations
Disclaimer: This library is continuously evolving. Currently the main focus is supporting essential use-cases. We are happy to accept contributions to further extend functionality, address bug fixes and improve usability. Please see the Contributing section and feel free to reach out.
Currently unsupported Appian Interactions
Multiple links with the same name on the same page, use labels to differentiate
Legacy forms
Limitations when running Locust
On Windows, running locust in distributed mode is not supported
Advanced Appian Locust Usage
Loading Test Settings from Config
These three lines look for a config.json
file at the location from which the script is run (not where the locustfile is).
from appian_locust.utilities import loadDriverUtils
utls = loadDriverUtils()
utls.load_config()
This takes the content of the config.json
file and places it into a variable as utls.c.
This allows us to access configurations required for logging in inside the class that extends HttpUser:
config = utls.c
auth = config['auth']
host = "https://" + config['host_address']
A minimal config.json looks like:
{
"host_address": "site-name.appiancloud.com",
"auth": [
"user.name",
"password"
]
}
Advanced Test Examples
Locust Test Example: Records
An example of a Locust Test showing interaction with Appian Records - example_locust_test_records.py.
This test has 2 locust tasks defined and it will execute all three for each spawned locust user for the duration of the test.
Task 1 will visit a random record instance for a random record type and return the SAIL form.
Task 2 will visit a random record type list and get the SAIL form for it, then filter the records in the list.
@task takes an optional weight argument that can be used to specify the task’s execution ratio. For example: If there are two tasks with weights 3 and 6 then second task will have twice the chance of being picked as first task.
# Locust tests executing against Appian with a TaskSet should set AppianTaskSet as their base class to have access to various functionality.
# This class handles creation of basic objects like self.appian (appian client) and actions like `login` and `logout`
class RecordsTaskSet(AppianTaskSet):
def on_start(self):
super().on_start()
# could be either view or list:
if "endpoint_type" not in CONFIG: # could be either view or list:
logger.error("endpoint_type not found in config.json")
sys.exit(1)
self.endpoint_type = CONFIG["endpoint_type"]
# view - to view records from opaqueId
# list - to list all the record types from url_stub
if "view" not in self.endpoint_type and "list" not in self.endpoint_type:
logger.error(
"This behavior is not defined for the provided endpoint type. Supported types are : view and list")
sys.exit(1)
def on_stop(self):
logger.info("logging out")
super().on_stop()
@task(X)
def visit_random_record(self):
if "view" in self.endpoint_type:
self.appian.visitor.visit_record_instance()
@task(X)
# this task visits a random record type list and return the SAIL form.
def visit_random_record_type_list(self):
if "list" in self.endpoint_type:
record_list = self.appian.records.visit_record_type_and_get_form()
record_list.filter_records_using_searchbox("Favorite Record Name")
By calling super().on_start() inside the on_start() function of the locust test you get access to the appian client which allows you to call self.appian.visitor, self.appian.system_operator etc. These properties allow us to navigate to a specific object or access metadata about available objects.
Functions like visit_XYZ() access the actual appian object and return its SAIL form as an instance of
uiform
. This class contains methods that helps you interact with the UI.
Locust Test Example: Grids
An example of a Locust Test showing interaction with Appian Grids - example_locust_test_grids.py.
This test has a locust task defined that will interact with a read-only paging grid layout that contains an Employee directory. Configuration for this grid layout is inspired by Appian’s Grid Tutorial. The goal of this test is to select all Engineering employees and view the details for one of them.
The first step in this workflow is to navigate our user to a report which is backed by an interface containing the grid:
@task
def interact_with_grid_in_interface(self):
# Navigate to the interface backed report that contains a grid
report_uiform = self.appian.visitor.visit_report(report_name="Employee Report with Grid")
The interface will look similar to this:

Now that we have navigated to the report, we will sort the grid by the Department field in the ascending order to have all Engineering department employees at the top:
@task
def interact_with_grid_in_interface(self):
# Navigate to the interface backed report that contains a grid
report_uiform = self.appian.visitor.visit_report(report_name="Employee Report with Grid")
# Sort the grid rows by the "Department" field name
report_uiform.sort_paging_grid(label="Employee Directory", field_name="Department", ascending=True)
The interface with the sorted grid will look similar to this:

Next, we will select the first five rows on the first page of the grid:
@task
def interact_with_grid_in_interface(self):
# Navigate to the interface backed report that contains a grid
report_uiform = self.appian.visitor.visit_report(report_name="Employee Report with Grid")
# Sort the grid rows by the "Department" field name
report_uiform.sort_paging_grid(label="Employee Directory", field_name="Department", ascending=True)
# Select the first five rows on the first page of the grid
report_uiform.select_rows_in_grid(rows=[0,1,2,3,4], label="Employee Directory")
Because the grid is configured to show the selected rows under Selected Employees, the resultant interface will look similar to this:

During development, this would be a good way to test the selection using the JSON response from the above request. Next, we will move to the second page of the grid and select the first row since it also contains an Engineering employee:
@task
def interact_with_grid_in_interface(self):
# Navigate to the interface backed report that contains a grid
report_uiform = self.appian.visitor.visit_report(report_name="Employee Report with Grid")
# Sort the grid rows by the "Department" field name
report_uiform.sort_paging_grid(label="Employee Directory", field_name="Department", ascending=True)
# Select the first five on the first page of the grid
report_uiform.select_rows_in_grid(rows=[0,1,2,3,4], label="Employee Directory")
# Move to the second page of the grid
report_uiform.move_to_right_in_paging_grid(label="Employee Directory")
# Select the first row on the second page of the grid
report_uiform.select_rows_in_grid(rows=[0], label="Employee Directory", append_to_existing_selected=True)
The interface will look similar to this:

The grid contains a First Name column which is a link to the employee record. Finally, we will click on the link for an employee William:
@task
def interact_with_grid_in_interface(self):
# Navigate to the interface backed report that contains a grid
report_uiform = self.appian.visitor.visit_report(report_name="Employee Report with Grid")
# Sort the grid rows by the "Department" field name
report_uiform.sort_paging_grid(label="Employee Directory", field_name="Department", ascending=True)
# Select the first five on the first page of the grid
report_uiform.select_rows_in_grid(rows=[0,1,2,3,4], label="Employee Directory")
# Move to the second page of the grid
report_uiform.move_to_right_in_paging_grid(label="Employee Directory")
# Select the first row on the second page of the grid
report_uiform.select_rows_in_grid(rows=[0], label="Employee Directory", append_to_existing_selected=True)
# Click on the row with a record link with the given label
report_uiform.click_record_link(label="William")
The user will be navigated to the employee’s record which will look similar to this:

You can see a full version of this locust test here. There are other useful functions for interacting with grids that can be found in our documentation.
Locust Test Example: Multiple Users
An example of a Locust Test showing interaction with the frontend and admin pages - example_multi_user_locustfile.py.
This test has 2 locust TaskSets defined and 2 HttpUsers defined that simulate different login information.
TaskSets
The
GetFrontPageTaskSet
simply navigates to a basic user landing pageThe
GetAdminPageTaskSet
navigates to the admin console
HttpUsers
The
FrontendUserActor
uses the login credentials for the regular frontend userThe
AdminUserActor
uses the login credentials for the admin user
Running
When running this locustfile, it is important to note that the users specified when running are spread evenly across the HttpUsers. If you only specify one user to run when running locust, it will only choose one user actor to start:
locust -f examples/example_multi_user_locustfile.py --headless -r 10 -t 3600 --users 1
...
All users hatched: FrontendUserActor: 1, AdminUserActor: 0 (0 already running)
Make sure to run the locustfile with at least as many users as required by how you have the weights configured for each HttpUser.
For the included sample, the weights are 3 and 1 respectively, meaning you’ll have to spawn 4 users to get the AdminUserActor
to start up
locust -f examples/example_multi_user_locustfile.py --headless -r 10 -t 3600 --users 4
...
All users hatched: FrontendUserActor: 3, AdminUserActor: 1 (0 already running)
Advanced Task Execution
Executing a specific number of tasks
One can also write a test that executes a set number of iterations of your TaskSequence Class and all its tasks, instead of executing the test for X number of seconds/mins/hours. Here’s a snippet showing how to run a test for a set number of iterations.
import json
import os
from locust import HttpUser, task, between, events
from appian_locust import AppianTaskSet
@events.init.add_listener
def on_locust_init(environment, **kw):
global ENV
ENV = environment
class OrderedEndToEndTaskSequence(AppianTaskSequence):
@task
def nav_to_random_site(self):
pass
@task
def nav_to_specific_site(self):
pass
@task
def increment_iteration_counter(self):
logger.info(f"Iteration Number: {self.iterations}")
# Stop the test if 40 iterations of the set have been completed.
# This would mean approximately 40K requests in total for the test.
if self.iterations >= CONFIG["num_of_iterations"]:
logger.info(f"Stopping the Locust runner")
ENV.runner.quit()
else:
logger.info(f"Incrementing the iteration set counter")
self.iterations += 1
class UserActor(HttpUser):
tasks = [GetFrontPageTaskSet]
config_file = "./example_config.json"
CONFIG = {}
if os.path.exists(config_file):
with open(config_file, 'r') as config_file:
CONFIG = json.load(config_file)
else:
raise Exception("No config.json found")
host = f'https://{CONFIG["host_address"]}'
auth = CONFIG["auth"]
wait_time = between(0.500, 0.500)
Note: CONFIG["num_of_iterations"]
is retrieved from the test configuration. This should be provided in the example_config.json file.
The way to achieve specific number of tasks in this test is by having a counter in your task, that you increment once in a specific Locust task and then stop the test when you have reached the desired number of iterations.
Waiting until all users are spawned
If you want to wait for your test to spawn all of the Locust users
from gevent.lock import Semaphore
all_locusts_spawned = Semaphore()
all_locusts_spawned.acquire()
@events.spawning_complete.add_listener
def on_spawn_complete(**kw):
print("All news users can start now!")
all_locusts_spawned.release()
class WaitingTaskSet(AppianTaskSet):
def on_start(self):
""" Executes before any tasks begin."""
super().on_start()
all_locusts_spawned.wait()
Latest Release
Version 2.0.0
Appian Locust v2.0 introduces a significant rework of the API to guide a clear and streamlined development experience. Our target was to meet feature parity while simplifying the steps to interact with Appian.
New Paradigm
Visitor
is the new hub for all SailUiForm navigations. From the client, you can call various methods to retrieve the desiredSailUiForm
that matches the type of page that the caller has navigated to, which will enable further interaction with the represented UI.SystemOperator
is for non UI form interactions at the system level (i.e.get_webapi()
).The
info
module extended fromAppianClient
provides metadata for News, Tasks, Records, Reports, Actions, and Sites (i.e.appian_locust.appian_client.AppianClient.actions_info
).
Breaking Changes
Appian Locust now requires Python 3.10. Update your dependencies globally or within your dependency management config file.
Fetching SailUIForms from News, Tasks, Records, Reports, Actions, and Sites have been marked as private. Use
Visitor
to handle all UI navigations.SailUIForms types can be found in the
uiform
module.Design objects and types have been moved to the
objects
module.Various helper methods have been moved to the
utilities
module.loadDriverUtils()
does not provideutls
anymore. Instead, callloadDriverUtils()
to setutls
:from appian_locust.utilities import loadDriverUtils utls = loadDriverUtils()
For a more comprehensive list of changes in Appian Locust 2.0, see the Appian Locust 2.0 Migration Guide document.
Appian Locust 2.0 Migration Guide
_actions.py
The _Actions class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
get_actions_interface |
Not available anymore. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_actions_feed |
Not available anymore. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_all |
We can do the same operation from the actions_info.py method named “get_all_available_actions”. |
all_available_actions = |
get_action |
We can do the same operation from the actions_info.py method named “get_action_info”. |
specific_action_info = |
visit_and_get_form |
We can perform the same operation by the “visit_action” method from visitor.py. |
uiform = |
visit |
Not available. Call the “visit_action” method from visitor.py instead. |
uiform = |
start_action |
We can perform the same operation by calling “start_action” in system_operator.py |
response = |
_admin.py
The _Admin class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
visit |
We can do the same operation by calling “visit_admin” method in visitor.py |
uiform = |
_design.py
The _Design class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
visit |
We can do the same operation by calling “visit_design” method in visitor.py |
uiform = |
visit_object |
We can do the same operation by calling “visit_design_object_by_id” method in visitor.py |
design_object_uiform = |
visit_app |
We can do the same operation by calling “visit_application_by_id” method in visitor.py |
application_uiform = |
create_application |
We can do the same operation by calling “create_application” method in design_uiform.py |
design_uiform = self.appian.visit_design()
application_uiform =
design_uiform.create_application(..) |
create_record_type |
We can do the same operation by calling “create_record_type” method in application_uiform.py |
application_uiform = self.appian.visitor.visit_application_by_id(..)
application_uiform =
application_uiform.create_record_type(..) |
create_report |
We can do the same operation by calling “create_recport” method in application_uiform.py |
application_uiform = self.appian.visitor.visit_application_by_id(..)
application_uiform =
application_uiform.create_report(..) |
_news.py
The _News class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
get_all |
We can do the same operation by calling the “get_all_available_entries” method in news_info.py. |
news_dict = |
get_news |
We can do the same operation by calling the “get_news_entry” method in news_info.py. |
specific_news_info = |
visit |
Not available. Call “get_news_entry” method in news_info.py instead. |
specific_news_info = |
visit_news_entry |
Not available. Call “get_news_entry” method in news_info.py instead. |
specific_news_info = |
search |
We can do the same operation by calling the “get_all_available_entries” with a search string argument. |
uiform = |
_records.py
The _Records class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
visit_record_instance_and_get_feed_form |
Not available. Call “visit_record_instance” method in visitor.py instead. |
record_instance_uiform = |
visit_record_instance_and_get_form |
We can do the same operation by calling the “visit_record_instance” method in visitor.py |
record_instance_uiform = |
visit_record_type_and_get_form |
We can do the same operation by calling the “visit_record_type” method in visitor.py |
record_list_uiform = |
get_all |
We can do the same operation from the record_list_uiform.py method named “get_visible_record_instances”. |
record_list_uiform = self.appian.visitor.visit_record_type(..)
all_records_info =
record_list_uiform.get_visible_record_instances(..) |
get_all_record_types |
“get_all_available_record_types” in records_info.py |
records_dict = |
get_all_records_of_record_type |
“get_visible_record_instances” in record_list_uiform.py |
record_list_uiform = self.appian.visitor.visit_record_type(..)
all_records_info =
record_list_uiform.get_visible_record_instances(..) |
get_records_interface |
Not available. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_records_nav |
Not available. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_all_records_of_record_type_mobile |
To interact with an Appian instance as a mobile client, pass in “is_mobile_client=True” in the AppianTaskSet on_start method. |
class SampleTaskSet(AppianTaskSet)
def on_start(self):
super().on_start(is_mobile_client=True)
|
get_all_mobile |
To interact with an Appian instance as a mobile client, pass in “is_mobile_client=True” in the AppianTaskSet on_start method. |
class SampleTaskSet(AppianTaskSet)
def on_start(self):
super().on_start(is_mobile_client=True)
|
fetch_record_instance |
Not available. Instead call “visit_record_instance” method in visitor.py |
record_instance_uiform = |
fetch_record_type |
Not available. Instead call “visit_record_type” method in visitor.py |
record_list_uiform = |
visit_record_instance |
Not available. Instead call “visit_record_instance” method in visitor.py |
record_instance_uiform = |
visit_record_type |
Not available. Instead call “visit_record_type” method in visitor.py |
record_list_uiform = |
_reports.py
The _Reports class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
get_reports_interface |
Not available anymore. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_reports_nav |
Not available anymore. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_all |
We can do the same operation by calling the “get_all_available_reports” in reports_info.py |
reports_dict = |
get_report |
We can do the same operation by calling the “get_report_info” in reports_info.py |
report_info = |
visit_and_get_form |
We can do the same operation by calling the “visit_report” in visitor.py |
uiform = |
visit |
Not available. Instead call “visit_report” in visitor.py |
uiform = |
_tasks.py
The _Tasks class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
get_all |
We can do the same operation by calling “get_all_available_tasks” method in tasks_info.py |
tasks_dict = |
get_task_pages |
Not available. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
get_next_task_page_uri |
Not available. Handled internally by the framework whenever it is necessary, so any calls to this can be removed without replacement. |
|
visit_and_get_form |
We can do the same operation by calling “visit_task” method in visitor.py |
uiform = |
visit |
Not available. Instead call “visit_task” in visitor.py |
uiform = |
_sites.py
The _Sites class is no longer available. You may migrate any functionality using this class as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
navigate_to_tab |
Not available. Instead call “visit_site” in visitor.py |
uiform = |
navigate_to_tab_and_record_if_applicable |
Not available. Instead call “visit_site_recordlist_and_get_random_record_form” in visitor.py |
record_instance_uiform = |
navigate_to_tab_and_record_get_form |
We can do the same operation by calling “visit_site_recordlist_and_get_random_record_form” in visitor.py |
record_instance_uiform = |
get_all |
We can do the same operation by calling “get_all_available_sites” in sites_info.py |
sites_dict = |
get_site_data_by_site_name |
We can do the same operation by calling “get_site_info” in sites_info.py |
specific_site = |
get_page_names_from_ui |
Not available. Instead call “get_site_info” in sites_info.py |
specific_site = |
get_site_page |
Not available. You can get page information from the Site object returned by “get_site_info” in sites_info.py |
specific_site = |
visit_and_get_form |
We can do the same operation by calling “visit_site” in visitor.py |
uiform = |
_app_importer.py
The _app_importer module is no longer available. You may migrate any functionality using this module as follows:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
import_app |
Available on DesignUiForm.py as “import_application” |
design_uiform = self.appian.visitor.visit_design()
design_uiform.import_application(..) |
uiform.py
The following methods in SailUiForm have removed or modified:
Method in 1.x |
Method in 2.x |
Example Usage |
---|---|---|
get_record_header_form |
Available on RecordInstanceUiForm.py as “get_header_view” |
record_form = self.appian.visitor.visit_record_instance(“record_type”, “record_name”)
record_header_form =
record_form.get_header_view() |
get_record_view_form |
Available on RecordInstanceUiForm.py as “get_summary_view” |
record_form = self.appian.visitor.visit_record_instance(“record_type”, “record_name”)
record_header_form =
record_form.get_summary_view() |
get_response |
Not available. Instead use “get_latest_state” |
|
latest_state |
Not available. Instead use “get_latest_state” |
|
get_latest_form |
Not available. This method basically just returned “this”, so it was unnecessary. |
|
click_record_link |
This method now returns a new type, a RecordInstanceUiForm, so you must make sure to save the return value into a new variable |
record_uiform: |
_records_helper.py
This class and all its methods are not accessible anymore.
_interactor.py
This class and all its methods are not accessible anymore. There are corresponding methods in other new classes/existing classes.
Import Changes
Class/Module |
Import in V1 |
Import in V2 |
---|---|---|
helper |
from appian_locust.helper import * |
from appian_locust.utilities.helper import * |
Site |
from appian_locust._sites import Site |
from appian_locust.objects import Site |
Page |
from appian_locust._sites import Page |
from appian_locust.objects import Page |
PageType |
from appian_locust._sites import PageType |
from appian_locust.objects import PageType |
utls |
from appian_locust.loadDriverUtils import utls |
from appian_locust.utilities import loadDriverUtils
utls = loadDriverUtils()
|
API
- class appian_locust.appian_client.AppianClient(session: HttpSession, host: str, base_path_override: str | None = None, portals_mode: bool = False, config_path: str = './config.json', is_mobile_client: bool = False)
Bases:
object
- property actions_info: ActionsInfo
Navigate to actions and gather information about available actions
- get_client_feature_toggles() None
- login(auth: list | None = None, check_login: bool = True) Tuple[HttpSession, Response]
- logout() None
Logout from Appian
- property records_info: RecordsInfo
Navigate to records and gather information about available records
- property reports_info: ReportsInfo
Navigate to reports and gather information about available reports
- property system_operator: SystemOperator
Abstraction used for system operation that do not require a UI
- appian_locust.appian_client.appian_client_without_locust(host: str, record_mode: bool = False, base_path_override: str | None = None) AppianClient
Returns an AppianClient that can be used without locust to make requests against a host, e.g.
>>> appian_client_without_locust() >>> client.login(auth=('username', 'password')) >>> client.get_client_feature_toggles()
This can be used for debugging/ making CLI style requests, instead of load testing You MUST call client.get_client_feature_toggles() to correctly finish initializing the client.
- Returns:
an Appian client that can be used
- Return type:
- class appian_locust.appian_task_set.AppianTaskSequence(parent: SequentialTaskSet)
Bases:
SequentialTaskSet
,AppianTaskSet
Appian Locust SequentialTaskSet. Provides functionality of Locust’s SequentialTaskSet and Handles creation of basic objects like``self.appian`` and actions like
login
andlogout
- tasks: List[TaskSet | Callable] = []
Collection of python callables and/or TaskSet classes that the User(s) will run.
If tasks is a list, the task to be performed will be picked randomly.
If tasks is a (callable,int) list of two-tuples, or a {callable:int} dict, the task to be performed will be picked randomly, but each task will be weighted according to its corresponding int value. So in the following case, ThreadPage will be fifteen times more likely to be picked than write_post:
class ForumPage(TaskSet): tasks = {ThreadPage:15, write_post:1}
- class appian_locust.appian_task_set.AppianTaskSet(parent: TaskSet)
Bases:
TaskSet
- property appian: AppianClient
A wrapper around the generated AppianClient
- on_start(portals_mode: bool = False, config_path: str = './config.json', is_mobile_client: bool = False) None
Overloaded function of Locust’s default on_start.
It will create object self.appian and logs in to Appian
- Parameters:
portals_mode (bool) – set to True if connecting to portals site
config_path (str) – path to configuration file
is_mobile_client (bool) – set to True if client should act as mobile
- on_stop() None
Overloaded function of Locust’s default on_stop.
It logs out the client from Appian.
- override_default_flags(flags_to_override: List[FeatureFlag]) None
override_default_flags gets the flag mask to set all of the flags to true given a list of flag enums and overrides the current feature flag extended value to set these flags to true.
- tasks: List[TaskSet | Callable] = []
Collection of python callables and/or TaskSet classes that the User(s) will run.
If tasks is a list, the task to be performed will be picked randomly.
If tasks is a (callable,int) list of two-tuples, or a {callable:int} dict, the task to be performed will be picked randomly, but each task will be weighted according to its corresponding int value. So in the following case, ThreadPage will be fifteen times more likely to be picked than write_post:
class ForumPage(TaskSet): tasks = {ThreadPage:15, write_post:1}
- class appian_locust.feature_flag.FeatureFlag(value)
Bases:
Enum
An enumeration.
- ALL_FEATURES = 1
- ALWAYS_ADD_RECORD_TYPE_INFORMATION = 45
- BILLBOARD_LAYOUT = 35
- BODY_URI_TEMPLATES = 14
- BOX_LAYOUT = 20
- CARD_LAYOUT = 39
- CERTIFIED_SAIL_EXTENSION = 47
- COMPACT_URI_TEMPLATES = 10
- DATA_EXPORT = 23
- DOCUMENT_VIEWER_LAYOUT = 44
- EVOLVED_BILLBOARD_LAYOUT = 50
- EVOLVED_GRIDFIELD = 52
- FILTERS_LAYOUT = 48
- FLUSH_RECORD_HEADERS = 57
- GAUGE_FIELD = 55
- GRID_ROW_SELECTION = 40
- ICON_WIDGET = 31
- IMAGES_INTERFACES_2 = 27
- IMAGE_CROPPING = 21
- IMPLICIT_SYSTYPE_NAMESPACE = 5
- INLINE_TASK_CONTROLS = 12
- IN_APP_BROWSER_AUTH = 59
- JUSTIFIED_LABEL_POSITION = 22
- LESS_OPAQUE_BILLBOARD_OVERLAYS = 58
- MEDIUM_LARGE_RICH_TEXT = 19
- MODERN_RECORD_TYPES_LIST = 38
- MULTIPLE_SAVE_USER_FILTERS = 60
- MULTI_SELECT_RECORD_FILTERS = 17
- NESTED_COLUMNS = 16
- NEWS_ENTRY_LAYOUT = 43
- NEWS_SUBSCRIPTION_SETTINGS = 46
- NEW_COLUMN_WIDTHS = 53
- NEW_RICH_TEXT_SIZES = 54
- NO_FEATURES = 0
- OFFLINE = 6
- PARTIAL_RENDERING = 7
- POSITIVE_NEGATIVE_RICH_TEXT = 18
- REACT_CLIENT = 11
- RECORD_ACTION_COMPONENT = 61
- RECORD_CHROME = 34
- RECORD_LIST_ACTION_LINK = 49
- RECORD_LIST_FEED_ITEM_DTO = 36
- RECORD_NEWS = 4
- RECORD_NEWS_FIELD = 37
- RELATIVE_URI_TEMPLATES = 13
- REPORT_LINK = 26
- REST_REDIRECT = 9
- RICH_TEXT_ACCENT_STYLE = 32
- SAIL_FORMS = 2
- SHORT_CIRCUIT_PARTIAL_RENDERING = 8
- SIDE_BY_SIDE_LAYOUT = 28
- SITE_RECORD_NEWS = 24
- START_PROCESS_LINK = 25
- SUBMISSION_LOCATION = 51
- TAG_FIELD = 56
- TASK_FORM_LAYOUT = 33
- TASK_PREVIEW = 3
- TWO_PART_RECORD_TAG_URI = 15
- USE_CLIENT_LOCALE = 41
- USE_MULTIPART_RECORD_UIS = 42
- WCC_READ_ONLY = 29
- WCC_READ_WRITE = 30
- class appian_locust.system_operator.SystemOperator(interactor: _Interactor, actions: _Actions)
Bases:
object
Class for providing the ability to perform activities that do not require a UI interaction i.e. triggering an action without a startform.
- fetch_autosuggestions(payload: Dict[str, Any], locust_request_label: str | None = None) Response
Retrieve suggestions from autosuggest endpoint :param payload: payload containing expression details to retrieve suggestions for :param locust_request_label: the label to be displayed by locust
Returns: Json response of suggestions
- fetch_content(opaque_id: str, locust_request_label: str | None) Response
Fetch a content element, such as an image :param opaque_id: The opaque id of the content to download :param locust_request_label: label to associate request with
Returns: Response object containing information of downloaded content
- get_webapi(uri: str, headers: Dict[str, Any] | None = None, locust_request_label: str | None = None, query_parameters: Dict[str, Any] = {}) Response
Make a GET request to a web api endpoint :param uri: API URI to be called :param headers: header for the REST API Call :param locust_request_label: the label to be displayed by locust :param query_parameters: Queries/Filters
Returns: Json response of GET operation
To set custom headers
>>> headers = {'Is-Admin': 'true'} ... self.appian.system_operator.get_webapi('/suite/webapi/headers', headers=headers)
To set custom query parameters
>>> params = {'age': 5, 'start-date': '10-05-2020'} ... self.appian.system_operator.get_webapi('/suite/webapi/query', query_parameters=params)
- post_webapi(uri: str, headers: Dict[str, Any] | None = None, locust_request_label: str | None = None) Response
Make a GET request to a web api endpoint :param uri: API URI to be called :param headers: header for the REST API Call :param locust_request_label: the label to be displayed by locust
Returns: Json response of GET operation
To set custom headers
>>> headers = {'Is-Admin': 'true'} ... self.appian.system_operator.post_webapi('/suite/webapi/headers', headers=headers)
- start_action(action_name: str, skip_design_call: bool = False, exact_match: bool = False) Response
Perform the post operation on action’s API to start specific action. Actions that do not have a UI can be called directly without using “GET” to retrieve the UI. this is controlled by the optional skip_design_call parameter
- Parameters:
action_name (str) – Name of the action
skip_design_call (bool, optional) – to skip the “GET” call for the action’s UI. Default : False
exact_match (bool, optional) – Should action name match exactly or to be partial match. Default : False
Returns: requests.models.Response
Example
>>> self.appian.site_helper.start_action("action_name")
- class appian_locust.visitor.Visitor(interactor: _Interactor, tasks: _Tasks, reports: _Reports, actions: _Actions, records: _Records, sites: _Sites)
Bases:
object
Provides methods to get an interactable
SailUiForm
from an Appian instance. Each method will return the respectedSailUiForm
type for which it will allow interactions with the visited page.- visit_action(action_name: str, exact_match: bool = False, locust_request_label: str | None = None) SailUiForm
Gets the action by name and returns the corresponding SailUiForm to interact with
If the action is activity chained, this will attempt to start the process and retrieve the chained SAIL form.
- Parameters:
action_name (str) – Name of the action to be called. Name of the action will be in the below pattern. “displayLabel::opaquqId”
exact_match (bool, optional) – Should action name match exactly or to be partial match. Default : False
locust_request_label (str, optional) – label to be used within locust. Default: ‘’ (empty string)
Returns: SailUiForm
Examples
If the full name of the action is known, with the opaque ID,
>>> self.appian.visitor.visit_action("action_name:igB0K7YxC0UQ2Fhx4hicRw...", exact_match=True)
If only the display name is known, or part of the display name
>>> self.appian.visitor.visit_action("action_name") >>> self.appian.visitor.visit_action("actio")
- visit_admin(locust_request_label: str | None = None) SailUiForm
Navigates to /admin :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns: SailUiForm
- visit_ai_skill_by_id(opaque_id: str, locust_request_label: str | None = None) AISkillUiForm
Visit an AI Skill by its opaque id :param opaque_id: opaque id of the AI Skill :type opaque_id: str :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (AISkillUiForm): UiForm representing AI Skill
- visit_ai_skill_by_name(ai_skill_name: str, locust_request_label: str | None = None) AISkillUiForm
Visit an AI Skill by its name :param ai_skill_name: The name of the AI Skill :type ai_skill_name: str :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (AISkillUiForm): UiForm representing AI Skill
- visit_application_by_id(application_id: str, locust_request_label: str | None = None) ApplicationUiForm
Visit an application by its opaque id
- Parameters:
application_id (str) – The opaque id of the application
locust_request_label (str, optional) – label to be used within locust
Returns (ApplicationUiForm): UiForm representing design application page
- visit_application_by_name(application_name: str, application_prefix: str | None = None, locust_request_label: str | None = None) ApplicationUiForm
Visit an application by name
- Parameters:
application_name (str) – The name of the application
application_prefix (str, optional) – The prefix of the application. Required if the application has a prefix.
locust_request_label (str, optional) – label to be used within locust
Returns (ApplicationUiForm): UiForm representing design application page
- visit_data_fabric(locust_request_label: str | None = None) SailUiForm
Navigate to Data Fabric :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (SailUiForm): UiForm representing Data Fabric
- visit_data_fabric_dashboard(encoded_uri_stub: str = 'new', locust_request_label: str | None = None) SailUiForm
Navigate to a Data Fabric Dashboard :param encoded_uri_stub: encoded uri stub of the dashboard to load. Defaults to “new” if not provided, :type encoded_uri_stub: str :param bringing the user to an empty dashboard.: :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (SailUiForm): UiForm representing a Data Fabric Dashboard
- visit_design(locust_request_label: str | None = None) DesignUiForm
Navigate to /design :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (DesignUiForm): UiForm representing /design
- visit_design_object_by_id(opaque_id: str, locust_request_label: str | None = None) DesignObjectUiForm
Visit a design object by its opaque id :param opaque_id: opaque id of the design object :type opaque_id: str :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (DesignObjectUiForm): UiForm representing design object
- visit_design_object_by_name(object_name: str, object_type: DesignObjectType, locust_request_label: str | None = None) DesignObjectUiForm
Visit a design object by its name and type :param object_name: The name of the design object :type object_name: str :param object_type: The type of the design object :type object_type: DesignObjectType :param locust_request_label: label to be used within locust :type locust_request_label: str, optional
Returns (DesignObjectUiForm): UiForm representing design object
- visit_portal_page(portal_unique_identifier: str, portal_page_unique_identifier: str, locust_request_label: str | None = None) SailUiForm
Navigate to portal’s page by url and returns the corresponding SailUiForm to interact with
- Parameters:
portal_unique_identifier (str) – portal web address unique identifier
portal_page_unique_identifier (str) – web address unique identifier for specific page in portal
locust_request_label (str, optional) – label to be used within locust
Returns: SailUiForm
Examples
If we have portal up and running with 2 pages with title “page1” and “page2”, we can visit any portal page with help of this method.
In order to visit “page1” with url (in browser: https://mysite.appian-internal.com/performance-testing/page/page1), we would use
>>> self.appian.visitor.visit_portal_page("performance-testing", "page1")
In order to visit “page2” with url (in browser: https://mysite.appian-internal.com/performance-testing/page/page2), we would use
>>> self.appian.visitor.visit_portal_page("performance-testing", "page2")
Note: sometimes when portal has just 1 page (for example page with title ‘page1’). appian use only “https://mysite.appian-internal.com/performance-testing” (in browser) instead of https://mysite.appian-internal.com/performance-testing/page/page1 . although it still works.
- visit_record_instance(record_type: str = '', record_name: str = '', view_url_stub: str = '', exact_match: bool = False, summary_view: bool = True, locust_request_label: str | None = None) RecordInstanceUiForm
Navigate to a specific record and return a RecordUiForm
- Parameters:
record_type (str) – Record Type Name. If not specified, a random record type will be selected.
record_name (str) – Name of the record to be called. If not specified, a random record will be selected.
view_url_stub (str, optional) – page/tab to be visited in the record. If not specified, “summary” dashboard will be selected.
exact_match (bool, optional) – Should record type and record name matched exactly as it is or partial match.
summary_view (bool, optional) – Should the Record UI be returned in Summary View, if false will return Header View
locust_request_label (str, optional) – Label locust should associate this request with
Returns (RecordUiForm): The UI for the record instance
- visit_record_type(record_type: str = '', locust_request_label: str | None = None) RecordListUiForm
This function calls the API for the specific record type and returns a SAIL form representing the list of records for that record type.
- Parameters:
record_type (str) – Record Type Name. If not specified, a random record type will be selected.
locust_request_label (str, optional) – Label locust should associate this request with
Returns (SailUiForm): UI representing list of records for that record type
- visit_report(report_name: str, exact_match: bool = True, locust_request_label: str | None = None) SailUiForm
Navigate to a report and return a SailUiForm for that report’s UI
- Parameters:
report_name (str) – Name of the report to be called.
exact_match (bool, optional) – Should report name match exactly or to be partial match. Default : True
locust_request_label (str, optional) – Label locust should associate this request with
Returns (SailUiForm): Response of report’s Get UI call in SailUiForm
- visit_site(site_name: str, page_name: str, locust_request_label: str | None = None) SailUiForm
Get a SailUiForm for a Task, Report or Action
- Parameters:
site_name (str) – Site where the page exists
page_name (str) – Page to navigate to
locust_request_label (str, optional) – Label locust should associate this request with
Returns: SailUiForm
Example
>>> self.appian.visitor.visit_site("site_name","page_name")
- visit_site_recordlist(site_name: str, page_name: str, locust_request_label: str | None = None) RecordListUiForm
Get a RecordListUiForm for a record list page on a site
- Parameters:
site_name (str) – Site where the page exists
page_name (str) – Page to navigate to
locust_request_label (str, optional) – label to be used within locust
- NOTE: The actual Type of the Site Page MUST be “Record List”, this will not work for sites that are of other page types,
such as an Interface with a record grid.
Returns: SailUiForm
Example
>>> self.appian.visitor.visit_site_recordlist("site_name","page_name")
- visit_site_recordlist_and_get_random_record_form(site_name: str, page_name: str, locust_request_label: str | None = None) RecordInstanceUiForm
Navigates to a site page that is a recordlist then clicks on a random record instance on the first page
- Parameters:
site_name – Site Url stub
page_name – Page Url stub
locust_request_label (str, optional) – label to be used within locust
- NOTE: The actual Type of the Site Page MUST be “Record List”, this will not work for sites that are of other page types,
such as an Interface with a record grid.
Returns: RecordInstanceUiForm
- visit_task(task_name: str, exact_match: bool = True, locust_request_label: str | None = None) SailUiForm
Gets the SailUiForm given a task name
- Parameters:
task_name (str) – Name of the task to search for
exact_match (bool, optional) – Whether or not a full match is returned. Defaults to True.
locust_request_label (str, optional) – label to be used within locust
- Returns:
SAIL form for the task
- Return type:
Exceptions module
- exception appian_locust.exceptions.exceptions.BadCredentialsException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.ChoiceNotFoundException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.ComponentNotFoundException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.IncorrectDesignAccessException(object_type: str, correct_access_method: str)
Bases:
Exception
- exception appian_locust.exceptions.exceptions.InvalidComponentException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.InvalidDateRangeException(start_date: date, end_date: date)
Bases:
Exception
- exception appian_locust.exceptions.exceptions.InvalidSiteException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.MissingConfigurationException(missing_keys: list)
Bases:
Exception
- exception appian_locust.exceptions.exceptions.MissingCsrfTokenException(found_cookies: dict)
Bases:
Exception
- exception appian_locust.exceptions.exceptions.MissingUrlProviderException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.PageNotFoundException
Bases:
Exception
- exception appian_locust.exceptions.exceptions.SiteNotFoundException
Bases:
Exception
Info module
- class appian_locust.info.actions_info.ActionsInfo(actions: _Actions)
Bases:
object
- get_action_info(action_name: str, exact_match: bool = False) Dict[str, Any]
Get the information about specific action by name.
- Parameters:
action_name (str) – Name of the action
exact_match (bool) – Should action name match exactly or to be partial match. Default : False
Returns (dict): Specific Action’s info
Raises: In case of action is not found in the system, it throws an “Exception”
Example
If full name of action is known:
>>> action_info.get_action_info("action_name", exact_match=True)
If only the display name is known, or part of the display name:
>>> action_info.get_action_info("actio")
- get_all_available_actions(locust_request_label_breadcrumb: str = 'Actions.MainMenu.AvailableActions') Dict[str, Any]
Retrieves all the available “actions” and associated metadata from “Appian-Tempo-Actions”
- Parameters:
locust_request_label_breadcrumb (str) – Base label used for each of the multiple requests made by this method
Returns (dict): List of actions and associated metadata
Examples
>>> actions_info.get_all_available_actions()
- class appian_locust.info.news_info.NewsInfo(news: _News)
Bases:
object
Class which provides metadata about news entries from the Tempo News tab
- get_all_available_entries(search_string: str | None = None, locust_request_label: str = 'News.AllAvailableEntries') Dict[str, Any]
Retrieves all the available “news” and associated metadata from “Appian-Tempo-News”
- Parameters:
search_string (str, optional) – results will be filtered based on the search string.
locust_request_label (str) – Label locust should associate with the request
Returns (dict): List of news and associated metadata
Examples
>>> news_info.get_all()
- get_news_entry(news_name: str, exact_match: bool = True, search_string: str | None = None) Dict[str, Any]
Get the information about specific news by name.
- Parameters:
news_name (str) – name of the news entry
exact_match (bool, optional) – Should news name match exactly or to be partial match. Default : True
search_string (str, optional) – results will be filtered based on the search string.
Returns: Specific News’s info
Raises: In case news is not found in the system, it throws an “Exception”
Example
If full name of action is known,
>>> news_info.get_news("news_name")
If only partial name is known,
>>> news_info.get_news("news_name", exact_match=False)
- get_news_entry_record_tags(news_name: str, locust_request_label: str | None = None) Response | None
Get the record tags associated with a news entry :param news_name: News entry ID :type news_name: str :param locust_request_label: Label locust should associate with the request for record tags :type locust_request_label: str, optional
Returns:
Request related records information for a news entry :param news_name: name of the news entry :type news_name: str :param exact_match: Should news name match exactly or to be partial match. Default : True :type exact_match: bool, optional :param search_string: results will be filtered based on the search string. :type search_string: str, optional :param locust_request_label: Label locust should associate with the request for related records :type locust_request_label: str, optional
Returns: Response object with related records information, if any exists
- class appian_locust.info.records_info.RecordsInfo(records: _Records)
Bases:
object
Class which provides metadata about available record types from the Tempo Records tab
- get_all_available_record_types(locust_request_label: str = 'Records.MainMenu_ViewAll') Dict[str, Any]
Get all metadata for visible record types on Tempo Records.
Returns (dict): List of record types and associated metadata
- class appian_locust.info.reports_info.ReportsInfo(reports: _Reports)
Bases:
object
Class which provides metadata about available reports from the Tempo Reports tab
- get_all_available_reports(search_string: str | None = None, locust_request_label: str | None = None) Dict[str, Any]
Retrieves all the available “reports” and associated metadata from “Appian-Tempo-Reports”
Returns (dict): List of reports and associated metadata
Examples
>>> reports_info.get_all_available_reports()
- get_report_info(report_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about specific report by name.
- Parameters:
report_name (str) – Name of the action
exact_match (bool) – Should action name match exactly or to be partial match. Default : True
Returns (dict): Specific Report’s info
Raises: In case of report is not found in the system, it throws an “Exception”
Example
If full name of report is known:
>>> report_info.get_report_info("report_name", exact_match=True)
If only the display name is known, or part of the display name:
>>> report_info.get_report_info("report")
- class appian_locust.info.sites_info.SitesInfo(sites: _Sites)
Bases:
object
Class which provides metadata about available Sites
- get_all_available_sites() Dict[str, Site]
Retrieves all the available “sites” and associated metadata
Returns (dict): List of sites and associated metadata
Examples
>>> sites_info.get_all_available_sites()
- get_site_info(site_name: str, exact_match: bool = True) Site
Get the information about specific site by name.
- Parameters:
site_name (str) – Name of the action
Returns (Site): Specific site’s info
Raises: In case of site is not found in the system, it throws an “Exception”
Example
If full name of site is known:
>>> site_info.get_site_info("site_name", exact_match=True)
If only the display name is known, or part of the display name:
>>> site_info.get_site_info("site")
- class appian_locust.info.tasks_info.TasksInfo(tasks: _Tasks)
Bases:
object
Class which provides metadata about available tasks from the Tempo Tasks tab
- get_all_available_tasks(locust_request_label: str = 'Tasks.MainMenu.GetAllAvailable') Dict[str, Any]
Retrieves all the available “tasks” and associated metadata from “Appian-Tempo-Tasks”
- Parameters:
locust_request_label (str) – Label locust should associate with the request
Returns (dict): List of tasks and associated metadata
Examples
>>> tasks_info.get_all_available_tasks()
- get_task_info(task_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about specific task by name.
- Parameters:
task_name (str) – Name of the action
exact_match (bool) – Should action name match exactly or to be partial match. Default : True
Returns (dict): Specific Task’s info
Raises: In case of task is not found in the system, it throws an “Exception”
Example
If full name of task is known:
>>> task_info.get_task_info("task_name", exact_match=True)
If only the display name is known, or part of the display name:
>>> task_info.get_task_info("task")
Objects module
- class appian_locust.objects.ai_skill.AiSkill(host_url: str, object_uuid: str)
Bases:
object
- class appian_locust.objects.ai_skill_type.AISkillObjectType(value)
Bases:
Enum
An enumeration.
- DOCUMENT_CLASSIFICATION = 2
- DOCUMENT_EXTRACTION = 5
- EMAIL_CLASSIFICATION = 8
- class appian_locust.objects.application.Application(name: str, opaque_id: str)
Bases:
object
Class representing an application
- class appian_locust.objects.design_object.DesignObject(name: str, opaque_id: str)
Bases:
object
Class representing an Design Object
- class appian_locust.objects.design_object.DesignObjectType(value)
Bases:
Enum
An enumeration.
- DATA_TYPE = 'Data Type'
- DECISION = 'Decision'
- EXPRESSION_RULE = 'Expression Rule'
- INTEGRATION = 'Integration'
- INTERFACE = 'Interface'
- RECORD_TYPE = 'Record Type'
- SITE = 'Site'
- TRANSLATION_SET = 'Translation Set'
- WEB_API = 'Web API'
- class appian_locust.objects.page.Page(page_name: str, page_type: PageType, site_stub: str, group_name: str | None = None)
Bases:
object
Class representing a single Page within a site
Uiform module
- class appian_locust.uiform.ai_skill_uiform.AISkillUiForm(rdo_interactor: _RDOInteractor, rdo_state: Dict[str, Any], ai_skill_id: str, breadcrumb: str = 'AISkillUi')
Bases:
SailUiForm
- save_ai_skill_changes(locust_request_label: str | None = None) AISkillUiForm
- Saves an AI Skill Object. This is done in two parts:
Clicking on the Save Changes button which creates an LCP request.
Persisting the model to the RDO Server
- Parameters:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (AISkillUiForm): The latest state of the AI Skill UiForm
Example
>>> form.save_ai_skill_changes()
- upload_documents_to_multiple_file_upload_field(label: str, file_paths: List[str], locust_request_label: str | None = None) AISkillUiForm
Uploads multiple documents to an MLAS upload field.
- Parameters:
label (str) – Currently Unused
file_paths (list) – List of document file paths in string form
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (AISkillUiForm): The latest state of the AI Skill UiForm
Example
>>> form.upload_document_to_multiple_file_upload_field(["/usr/local/appian/File1.pdf", "/usr/local/appian/File2.pdf"])
- class appian_locust.uiform.application_uiform.ApplicationUiForm(interactor: _Interactor, state: Dict[str, Any], breadcrumb: str = 'ApplicationUi')
Bases:
SailUiForm
- click_ai_skill(ai_skill_name: str, locust_request_label: str | None = None) AISkillUiForm
Click on an AI Skill in the design object grid. The current view of the grid must contain the skill you wish to click. :param ai_skill_name: The name of the AI Skill to click on
Returns (AISkillUiForm): UiForm representing UI of AI Skill
- click_design_object(design_object_name: str, locust_request_label: str | None = None) DesignObjectUiForm
Click on a design object in the design object grid. The current view of the grid must contain the object you wish to click. :param design_object_name: The name of the design object to click on
Returns (DesignObjectUiForm): UiForm representing UI of design object
- create_ai_skill_object(ai_skill_name: str, ai_skill_type: AISkillObjectType) ApplicationUiForm
Creates an AI Skill with the given name
Returns: The SAIL UI Form after the record type is created
- create_record_type(record_type_name: str) ApplicationUiForm
Creates a record type with the given name
Returns: The SAIL UI Form after the record type is created
- create_report(report_name: str) ApplicationUiForm
Creates a report with the given name
Returns: The SAIL UI Form after the report is created
- filter_design_objects(design_object_types: list[appian_locust.objects.design_object.DesignObjectType]) ApplicationUiForm
Filter the design object list in an Application, must be on page with design object list :param design_object_types: List of the types of objects you wish to filter on :type design_object_types: DesignObjectType
Returns (ApplicationUiForm): ApplicationUiForm with filtered list of design objects
- get_available_design_objects() Dict[str, DesignObject]
Retrieve all available design objects in the application, must be on page with design object list
Returns (dict): Dictionary mapping design object names to DesignObject
- search_objects(search_str: str, locust_label: str | None = None) ApplicationUiForm
Search the design object list in an Application, must be on page with design object list :param search_str: The string to search :type search_str: str :param locust_label: Label to associate request with :type locust_label: str
Returns (ApplicationUiForm): A UiForm with updated state after the search is complete
- class appian_locust.uiform.design_object_uiform.DesignObjectUiForm(interactor: _Interactor, state: Dict[str, Any], breadcrumb: str = 'DesignObjectUi')
Bases:
SailUiForm
Interacts with an ApplicationNavigationLayout component. This interaction involves clicking the Section Items in the navigation sidebar tab of Record Type e.g. Actions, Views, etc.
- Parameters:
navigation_tab_label (str) – The label or identifier for the navigation component.
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics.
Returns (DesignObjectUiForm): The latest state of the UiForm.
Examples
>>> form.click_record_type_application_navigation_tab(navigation_page_label="Actions")
- launch_query_editor() DesignObjectUiForm
Calls the post operation to click on the LaunchVQD button in the toolbar for the ExpressionEditorWidget. This will launch the query editor with the expression currently in the expression editor.
Returns (DesignObjectUiForm): UiForm updated with state representing launched query editor
- class appian_locust.uiform.design_uiform.DesignUiForm(interactor: _Interactor, state: Dict[str, Any], breadcrumb: str = 'DesignUi')
Bases:
SailUiForm
- click_application(application_name: str, locust_request_label: str | None = None) ApplicationUiForm
Click on an application in the /design application grid. Must be on the current page to be clicked.
- Parameters:
application_name (str) – The name of the application to click on
locust_request_label (str, optional) – label to be used within locust
Returns (ApplicationUiForm): The latest state of the UiForm, representing the application clicked on
- create_application(application_name: str) ApplicationUiForm
Creates an application and returns a form within representing the app contents
Returns: The SAIL UI Form
- filter_design_objects(design_object_types: list[appian_locust.objects.design_object.DesignObjectType]) DesignUiForm
Filter the design object list in /design, must be on page with design object list :param design_object_types: List of the types of objects you wish to filter on :type design_object_types: DesignObjectType
Returns (DesignUiForm): DesignUiForm with filtered list of design objects
- get_available_applications() Dict[str, Application]
Retrieve all available applications in /design. Must be on page with application list
Returns (dict): Dictionary mapping application names to Application
- get_available_design_objects() Dict[str, DesignObject]
Retrieve all available design objects in the application. Must be on page with design object list
Returns (dict): Dictionary mapping design object names to DesignObject
- import_application(app_file_path: str, customization_file_path: str | None = None, inspect_and_import: bool = False) None
Import an application into the Appian instance. :param app_file_path: Local path to the application zip file :param customization_file_path: Local path to customization file :param inspect_and_import: Set to true if Appian Locust should “Inspect” before importing
Returns: None
- search_applications(search_str: str, locust_label: str | None = None) DesignUiForm
Search the application list in /design, must be on page with application list :param search_str: The string to search :type search_str: str :param locust_label: Label to associate request with :type locust_label: str
Returns (DesignUiForm): A UiForm with updated state after the search is complete
- search_objects(search_str: str, locust_label: str | None = None) DesignUiForm
Search the design object list in /design, must be on page with design object list :param search_str: The string to search :type search_str: str :param locust_label: Label to associate request with :type locust_label: str
Returns (DesignUiForm): A UiForm with updated state after the search is complete
- class appian_locust.uiform.record_list_uiform.RecordListUiForm(interactor: _Interactor, state: Dict[str, Any], breadcrumb: str = 'RecordListUi')
Bases:
SailUiForm
UiForm representing a Record List from Tempo Records
- clear_records_search_filters() RecordListUiForm
Clear any search filters on the records list
Returns: Unfiltered RecordsListUiForm
- click_record_list_action(label: str, locust_request_label: str | None = None) RecordListUiForm
Click on an action in a record list :param label: The label of the record list action to click :param locust_request_label: The label locust should associate with this request
Returns: UiForm with action clicked
- filter_records_using_searchbox(search_term: str = '', locust_request_label: str = '') RecordListUiForm
This method allows you to Filter the Record Type List (displaying record instance for a specific record type) which makes the same request when typing something in the search box and reloading the page. More interactions (with the filtered list) can be performed on the returned SailUiForm Object.
Note: This function does not require unfocusing from the search box as you would in the UI.
- Parameters:
search_term (str, optional) – Term to filter records list to
locust_label (str, optional) – label to associate request with
Examples
>>> form.filter_records_using_searchbox('Donuts')
Returns (RecordListUiForm): The record type list UiForm with the filtered results.
- get_visible_record_instances(column_index: int | None = None) Dict[str, Any]
Retrieve information about all visible records on the page. :param column_index: Which column to retrieve record information for. If no column is selected, every record link in the UI will be retrieved.
Returns: Dictionary with record instance information
- class appian_locust.uiform.record_uiform.RecordInstanceUiForm(interactor: _Interactor, state: Dict[str, Any], summary_view: bool = True, breadcrumb: str = 'RecordUi')
Bases:
SailUiForm
UiForm representing a Record Instance UI. Supports both summary and header record views. Defaults to summary view
- get_header_view() RecordInstanceUiForm
Get the header view of the record instance Returns (RecordInstanceUiForm): UiForm updated to header view
- get_summary_view() RecordInstanceUiForm
Get the summary view of the record instance Returns (RecordInstanceUiForm): UiForm updated to summary view
- class appian_locust.uiform.uiform.SailUiForm(interactor: _Interactor, state: Dict[str, Any], breadcrumb: str = 'SailUi')
Bases:
object
- assert_no_validations_present() SailUiForm
Raises an exception if there are validations present on the form, otherwise, returns the form as is
Returns (SailUiForm): Form as it was when validations were asserted
- check_checkbox_by_label(label: str, indices: List[int], locust_request_label: str = '') SailUiForm
Checks a checkbox by its label Indices are positions to be checked
- Parameters:
label (str) – Value for label of the checkbox
indices (str) – Indices of the checkbox to check. Pass None or empty to uncheck all
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.check_checkbox_by_label('myLabel', [1]) # checks the first item >>> form.check_checkbox_by_label('myLabel', None) # unchecks
- check_checkbox_by_test_label(test_label: str, indices: List[int], locust_request_label: str = '') SailUiForm
Checks a checkbox by its testLabel attribute Indices are positions to be checked
- Parameters:
test_label (str) – Value for the testLabel attribute of the checkbox
indices (str) – Indices of the checkbox to check. Pass None or empty to uncheck all
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.check_checkbox_by_test_label('myTestLabel', [1]) # checks the first item >>> form.check_checkbox_by_test_label('myTestLabel', None) # unchecks
- click(label: str, is_test_label: bool = False, locust_request_label: str = '', index: int = 1) SailUiForm
Clicks on a component on the form, if there is one present with the following label (case sensitive) Otherwise throws a NotFoundException
Can also be called as ‘click_link’ or ‘click_button’ to convey intent
This can also click StartProcessLinks or ProcessTaskLinks
- Parameters:
label (str) – Label of the component to click
is_test_label (bool) – If you are clicking a button or link via a test label instead of a label, set this boolean to true
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the component to click if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click('Submit') >>> form.click('SampleTestLabel', is_test_label = True)
- click_button(label: str, is_test_label: bool = False, locust_request_label: str = '', index: int = 1) SailUiForm
Clicks on a component on the form, if there is one present with the following label (case sensitive) Otherwise throws a NotFoundException
This can also click StartProcessLinks or ProcessTaskLinks
- Parameters:
label (str) – Label of the component to click
is_test_label (bool) – If you are clicking a button via a test label instead of a label, set this boolean to true
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the component to click if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_button('Save') >>> form.click_link('Update')
- click_card_layout_by_index(index: int, locust_request_label: str = '') SailUiForm
Clicks a card layout link by index. This method will find the CardLayout component on the UI by index and then perform the click behavior on its Link component.
- Parameters:
index (int) – Index of the card layout on which to click. (first found card layout , or second etc.) (Indices start from 1)
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
This finds link field on the 2nd card layout on the page and clicks it. It handles StartProcessLink as well, so no need to call click_start_process_link() when it is on a CardLayout.
>>> form.click_card_layout_by_index(2)
- click_grid_plaintext_link(column_name: str, row_index: int, grid_label: str | None = None, grid_index: int | None = None, locust_request_label: str = '') SailUiForm
Click on a link in a grid with plaintext values
Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
column_name (str) – The name of the column the link is in
row_index (int) – The row in the column to click on, 0 indexed
grid_label (str) – The label of the grid, if index is not supplied
grid_index (str) – the index of the grid, if label is not supplied
locust_request_label (str, optional) – The label locust should associate this request with
Returns (SailUiForm): The latest state of the UiForm
- click_grid_plaintext_record_link(column_name: str, row_index: int, grid_label: str | None = None, grid_index: int | None = None, locust_request_label: str = '') RecordInstanceUiForm
Click on a Record link in a grid with plaintext values
Either a label or an index is required, indices are useful if there is no title for the grid
NOTE: This method returns a NEW RecordInstanceUiForm object, so you must save its return value into a new variable, like so:
>>> record_uiform = other_uiform.click_grid_plaintext_record_link(...)
- Parameters:
column_name (str) – The name of the column the link is in
row_index (int) – The row in the column to click on, 0 indexed
grid_label (str) – The label of the grid, if index is not supplied
grid_index (str) – the index of the grid, if label is not supplied
locust_request_label (str, optional) – The label locust should associate this request with
Returns (SailUiForm): The latest state of the UiForm
- click_grid_rich_text_link(column_name: str, row_index: int, grid_label: str | None = None, grid_index: int | None = None, locust_request_label: str = '') SailUiForm
Click on a link in a grid with RichText values
Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
column_name (str) – The name of the column the link is in
row_index (int) – The row in the column to click on, 0 indexed
grid_label (str) – The label of the grid, if index is not supplied
grid_index (str) – the index of the grid, if label is not supplied
locust_request_label (str, optional) – The label locust should associate this request with
Returns (SailUiForm): The latest state of the UiForm
- click_grid_rich_text_record_link(column_name: str, row_index: int, grid_label: str | None = None, grid_index: int | None = None, locust_request_label: str = '') RecordInstanceUiForm
Click on a Record link in a grid with RichText values
Either a label or an index is required, indices are useful if there is no title for the grid
NOTE: This method returns a NEW RecordInstanceUiForm object, so you must save its return value into a new variable, like so:
>>> record_uiform = other_uiform.click_grid_rich_text_record_link(...)
- Parameters:
column_name (str) – The name of the column the link is in
row_index (int) – The row in the column to click on, 0 indexed
grid_label (str) – The label of the grid, if index is not supplied
grid_index (str) – the index of the grid, if label is not supplied
locust_request_label (str, optional) – The label locust should associate this request with
Returns (SailUiForm): The latest state of the UiForm
- click_link(label: str, is_test_label: bool = False, locust_request_label: str = '', index: int = 1) SailUiForm
Clicks on a component on the form, if there is one present with the following label (case sensitive) Otherwise throws a NotFoundException
This can also click StartProcessLinks or ProcessTaskLinks
- Parameters:
label (str) – Label of the component to click
is_test_label (bool) – If you are clicking a link via a test label instead of a label, set this boolean to true
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the component to click if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_link('Update')
Clicks an item in a MenuLayout provided the index of the chosen MenuItem ValueError is thrown if component found is NOT a MenuLayout, IndexError is thrown if the provided choice index is out of bounds for the available menu items
- Parameters:
label (str) – Label of the MenuLayout
choice_index (str) – Index of the MenuItem to select
is_test_label (bool) – True if you are finding a MenuLayout by test label instead of a label, False o.w.
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_menu_item_by_choice_index("changeScopeMenu", 0, True, locust_request_label="Create Scope")
Clicks an item in a MenuLayout provided the primaryText of the chosen MenuItem ValueError is thrown if component found is NOT a MenuLayout, OR if the MenuLayout doesn’t contain specified choice
- Parameters:
label (str) – Label of the MenuLayout
choice_name (str) – PrimaryText of the MenuItem to select
is_test_label (bool) – True if you are finding a MenuLayout by test label instead of a label, False o.w.
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_menu_item_by_name("changeScopeMenu", "Scope 2", True, locust_request_label="Change Scope")
- click_record_link(label: str, is_test_label: bool = False, locust_request_label: str = '') RecordInstanceUiForm
Click a record link on the form if there is one present with the following label (case sensitive) Otherwise throws a ComponentNotFoundException
- Parameters:
label (str) – Label of the record link to click
is_test_label (bool) – If you are clicking a record link via a test label instead of a label, set this boolean to true
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
NOTE: This method returns a NEW RecordInstanceUiForm object, so you must save its return value into a new variable, like so:
>>> record_uiform = other_uiform.click_record_link(...)
Returns (RecordUiForm): The record form (feed) for the linked record.
- click_record_link_by_attribute_and_index(attribute: str = '', attribute_value: str = '', index: int = 1, locust_request_label: str = '') RecordInstanceUiForm
Click the index’th record link on the form if there is one present with an attribute matching attribute_value If no attribute is provided, the index’th record link is selected from all record links in the form Otherwise throws a ComponentNotFoundException
NOTE: This method returns a NEW RecordInstanceUiForm object, so you must save its return value into a new variable, like so:
>>> record_uiform = other_uiform.click_record_link_by_attribute_and_index(...)
- Keyword Arguments:
attribute (str) – Attribute to check for ‘attribute_value’ (default: “”)
attribute_value (str) – Attribute value of record link to click (default: “”)
index (int) – Index of record link to click (default: 1)
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The record form (feed) for the linked record.
- click_record_link_by_index(index: int, locust_request_label: str = '') RecordInstanceUiForm
Click the index’th record link on the form Otherwise throws a ComponentNotFoundException
- Parameters:
index (int) – Index of the record link to click (1-based)
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The record form (feed) for the linked record.
- click_record_search_button_by_index(index: int = 1, locust_request_label: str = '') SailUiForm
Clicks the Search button of a record grid.
- Parameters:
index (int) – Index of the record search button on the form
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_record_search_button_by_index(1)
- click_record_view_link(label: str, locust_request_label: str = '') RecordInstanceUiForm
Click a record view link on the form if there is one present with the following label (case sensitive) Otherwise throws a ComponentNotFoundException
- Parameters:
label (str) – Label of the record link to click
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
NOTE: This method returns a NEW RecordInstanceUiForm object, so you must save its return value into a new variable, like so:
>>> record_uiform = other_uiform.click_record_view_link(...)
Returns (SailUiForm): The record form (feed) for the linked record.
Clicks a related action (either a related action button or link) on the form by label If no link is found, throws a ComponentNotFoundException
- Parameters:
label (str) – Label of the related action
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
How to use click_related_action():
Use records function - visit_record_instance_and_get_feed_form() to get Record Instance SailUiForm, then get the header response and finally click on the related action by label.
>>> feed_form = records.visit_record_instance_and_get_feed_form()
We need to get the header response or view response depending on if the related action is under the related actions dashboard or if it is a related action link on the summary view UI (which opens in a dialog).
>>> header_form = feed_form.get_record_header_form() or feed_form.get_record_view_form()
>>> header_form.click_related_action('Request upgrade')
- click_start_process_link(label: str, is_test_label: bool = False, is_mobile: bool = False, locust_request_label: str = '') SailUiForm
Clicks a start process link on the form by label If no link is found, throws a ComponentNotFoundException
- Parameters:
label (str) – Label of the link
- Keyword Arguments:
is_mobile (bool) – Boolean to use the mobile form of the request
locust_request_label (str) – Label used to identify the request for locust statistics
is_test_label (bool) – Boolean indicating if label is a test label
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_start_process_link('Request upgrade')
- click_start_process_link_on_mobile(label: str, site_name: str, page_name: str, locust_request_label: str = '') SailUiForm
Clicks a start process link on the form by label (for Mobile) If no link is found, throws a ComponentNotFoundException
- Parameters:
label (str) – Label of the link
site_name (str) – Name of the site (i.e. the Sites feature)
page_name (str) – Name of the page within the site
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.click_start_process_link_on_mobile('Open Issue')
- click_tab_by_label(tab_label: str, tab_group_test_label: str, locust_request_label: str = '') SailUiForm
Selects a Tab by its label and its tab group’s testLabel
- Parameters:
tab_label (str) – Label of the tab to select
tab_group_test_label (str) – Test Label of the tab group (tab is part of a tab group)
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples:
- fill_cascading_pickerfield(label: str, selections: List[str], format_test_label: bool = True, locust_request_label: str = '') SailUiForm
Select a choice for a cascading pickerfield, one where multiple choices can be chained together
- Parameters:
label (str) – Label of the field to fill out
selections (str) – The series of options to select through
- Keyword Arguments:
format_test_label (bool) – If you don’t want to prepend a “test-” to the testLabel, set this to False
locust_request_label (str) – Label to associate in locust statistics with selecting the picker choice
- fill_date_field(label: str, date_input: date, locust_request_label: str = '') SailUiForm
Fills a date field with the specified date
- Parameters:
label (str) – Label of the date field
date_input (date) – Date used to fill the field
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_date_field('Today', datetime.date.today()) >>> form.fill_date_field('Date of Birth', datetime.date(1992, 12, 30))
- fill_datetime_field(label: str, datetime_input: datetime, locust_request_label: str = '') SailUiForm
Fills a datetime field with the specified datetime
NOTE: this does one api call for both the date and time, whereas filling the elements on screen requires two separate evaluations, one to fill the date field and one to fill the time field. This is the way the request would look if one of the fields were already filled.
- Parameters:
label (str) – Label of the datetime field
datetime_input (date) – Date time used to fill the field
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_datetime_field('Now', datetime.datetime.now()) >>> form.fill_datetime_field('Date and Time of Birth', datetime.datetime(1992, 12, 30, 12, 30, 5))
- fill_field_by_any_attribute(attribute: str, value_for_attribute: str, text_to_fill: str, locust_request_label: str = '', index: int = 1) SailUiForm
Selects a Field by “attribute” and its value provided “value_for_attribute” and fills it with text “text_to_fill”
- Parameters:
attribute (str) – Name of the component to fill
value_for_attribute (str) – Value for the attribute passed in to this function
text_to_fill (str) – Value to fill the field with
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the field to fill if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_field_by_any_attribute("placeholder", "Write a comment", "Hello, Testing") # selects the Component with the "placeholder" attribute having "Write a comment" value # and fills it with "Hello, Testing"
- fill_field_by_attribute_and_index(attribute: str, attribute_value: str, fill_value: str, index: int = 1, locust_request_label: str = '') SailUiForm
Selects a Field by “attribute” and its value provided “attribute_value” and an index if more than one Field is found and fills it with text “fill_value”
- Parameters:
attribute (str) – Name of the field to fill
attribute_value (str) – Value for the attribute passed in to this function
fill_value (str) – Value to fill in the field
- Keyword Arguments:
index (int) – Index of the field to fill if more than one match the attribute and attribute_value criteria (default: 1)
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_field_by_attribute_and_index("label", "Write a comment", "Hello, Testing") # selects the first Component with the "label" attribute having "Write a comment" value # and fills it with "Hello, Testing"
>>> form.fill_field_by_attribute_and_index("label", "Write a comment", "Hello, Testing", 2) # selects the second Component with the "label" attribute having "Write a comment" value # and fills it with "Hello, Testing"
- fill_field_by_index(type_of_component: str, index: int, text_to_fill: str, locust_request_label: str = '') SailUiForm
Selects a Field by its index and fills it with a text value
- Parameters:
type_of_component (str) – Name of the component to fill
index (int) – Index of the field on the page (is it the first one found, or second etc.)
value (int) – Value to fill in the field of type ‘type_of_component’
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_field_by_index("ParagraphField", 1, "Hello, Testing") # selects the first ParagraphField with the value "Hello, Testing"
- fill_paragraph_field(label: str, value: str, is_test_label: bool = False, locust_request_label: str = '', index: int = 1) SailUiForm
Fills a field on the form, if there is one present with the following label (case sensitive) Otherwise throws a NotFoundException
- Parameters:
label (str) – Label of the field to fill out
value (str) – Value to fill the field with
- Keyword Arguments:
is_test_label (bool) – If you are filling a text field via a test label instead of a label, set this boolean to true
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the field to fill if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_text_field('Title','My New Novel')
- fill_picker_field(label: str, value: str, identifier: str = 'id', format_test_label: bool = True, fill_request_label: str = '', pick_request_label: str = '') SailUiForm
Enters the value in the picker widget and selects one of the suggested items if the widget is present with the following label (case sensitive)
If there is more than one suggestion, this method will select a random one out of the list
Otherwise this throws a NotFoundException
The mechanism it uses to find a pickerWidget is prefixing the picker field label with test- and looking for a testLabel
- Parameters:
label (str) – Label of the field to fill out
value (str) – Value to update the label to
- Keyword Arguments:
identifier (str) – Key to select the field to filter on, defaults to ‘id’
format_test_label (bool) – If you don’t want to prepend a “test-” to the testLabel, set this to False
fill_request_label (str) – Label to associate in locust statistics with filling the picker field
pick_request_label (str) – Label to associate in locust statistics with selecting the picker suggestion
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_picker_field('Title','My New Novel') >>> form.fill_picker_field('People','Jeff George') >>> form.fill_picker_field('Customer', 'GAC Guyana', identifier='code')
- fill_text_field(label: str, value: str, is_test_label: bool = False, locust_request_label: str = '', index: int = 1) SailUiForm
Fills a field on the form, if there is one present with the following label (case sensitive) Otherwise throws a NotFoundException
- Parameters:
label (str) – Label of the field to fill out
value (str) – Value to fill the field with
- Keyword Arguments:
is_test_label (bool) – If you are filling a text field via a test label instead of a label, set this boolean to true
locust_request_label (str) – Label used to identify the request for locust statistics
index (int) – Index of the field to fill if more than one match the label criteria (default: 1)
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.fill_text_field('Title','My New Novel')
- get_dropdown_items(label: str, is_test_label: bool = False) List[str]
Gets all dropdown items for the dropdown label provided on the form If no dropdown found, throws a NotFoundException
- Parameters:
label (str) – Label of the dropdown
is_test_label (bool) – If you are interacting with a dropdown via a test label instead of a label, set this boolean to true. User filters on a record instance list use test labels.
Returns (List): A list of all the choices in the dropdown
Examples
>>> form.get_dropdown_items('MyDropdown')
- get_latest_state() Dict[str, Any]
Provides a deep copy of latest state of UI form.
Returns (dict): deep copy of last recorded response.
- go_to_next_record_grid_page(locust_request_label: str = '') SailUiForm
- move_to_beginning_of_paging_grid(label: str | None = None, index: int | None = None, locust_request_label: str = '') SailUiForm
Moves to the beginning of a paging grid, if possible Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
label (str) – Label of the grid
index (int) – Index of the grid
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.move_to_beginning_of_paging_grid(label='my nice grid')
- move_to_end_of_paging_grid(label: str | None = None, index: int | None = None, locust_request_label: str = '') SailUiForm
Moves to the end of a paging grid, if possible Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
label (str) – Label of the grid
index (int) – Index of the grid
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.move_to_end_of_paging_grid(label='my nice grid')
- move_to_left_in_paging_grid(label: str | None = None, index: int | None = None, locust_request_label: str = '') SailUiForm
Moves to the left in a paging grid, if possible It might require getting the state of the grid if you’ve moved to the end/ previous part of the grid Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
label (str) – Label of the grid
index (int) – Index of the grid
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.move_to_left_in_paging_grid(label='my nice grid')
- move_to_right_in_paging_grid(label: str | None = None, index: int | None = None, locust_request_label: str = '') SailUiForm
Moves to the right in a paging grid, if possible It might require getting the state of the grid if you’ve moved within the grid Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
label (str) – Label of the grid
index (int) – Index of the grid
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.move_to_right_in_paging_grid(index=0) # move to right in first grid on the page
- refresh_after_record_action(label: str, is_test_label: bool = False, locust_request_label: str = '') SailUiForm
Refreshes a form after the completion of a record action.
- Parameters:
label (str) – Label of the record action that has just been completed
is_test_label (bool) – If you are referencing a record action via a test label instead of a label, set this boolean to true
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> initial_form = copy(form) >>> form.click('Request upgrade') >>> ... >>> form.click('Submit') >>> initial_form.refresh_after_record_action('Request upgrade')
- select_card_choice_field_by_label(label: str, index: int, locust_request_label: str = '') SailUiForm
Select a card by its label Index is position to be selected
- Parameters:
label (str) – Label of the card choice field
index (int) – Index of the card to select
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_card_choice_field_by_label('myLabel', 1) # selects the first item
- select_date_range_user_filter(filter_label: str, filter_start_date: date, filter_end_date: date, locust_request_label: str | None = None) SailUiForm
Select a value on a date range user filter
- Parameters:
filter_label (str) – the testLabel of the filter to select a value for
filter_start_date (date) – the start date for the range
filter_end_date (date) – the end date for the range
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_date_range_user_filter(filter_label="userFilter", filter_start_date=datetime.date(2023, 10, 18), filter_end_date=datetime.date(2023,10,19))
- select_dropdown_item(label: str, choice_label: str, locust_request_label: str = '', is_test_label: bool = False) SailUiForm
Selects a dropdown item on the form If no dropdown found, throws a NotFoundException If no element found, throws a ChoiceNotFoundException
- Parameters:
label (str) – Label of the dropdown
choice_label (str) – Label of the dropdown item to select
is_test_label (bool) – If you are interacting with a dropdown via a test label instead of a label, set this boolean to true. User filters on a record instance list use test labels.
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_dropdown_item('MyDropdown', 'My First Choice')
- select_dropdown_item_by_index(index: int, choice_label: str, locust_request_label: str = '') SailUiForm
Selects a dropdown item on the form by index (1-based) If no dropdown found, throws a NotFoundException If no element found, throws a ChoiceNotFoundException
- Parameters:
index (int) – index(int): Index of the dropdown to select
choice_label (str) – Label of the dropdown item to select
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_dropdown_item_by_index(1, 'My First Choice')
- select_multi_dropdown_item(label: str, choice_label: List[str], locust_request_label: str = '', is_test_label: bool = False) SailUiForm
Selects a multiple dropdown item on the form If no multiple dropdown found, throws a NotFoundException If no element found, throws a ChoiceNotFoundException
- Parameters:
label (str) – Label of the dropdown
choice_label ([str]) – Label(s) of the multiple dropdown item to select
is_test_label (bool) – If you are interacting with a multiple dropdown via a test label instead of a label, set this boolean to true. User filters on a record instance list use test labels.
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_multi_dropdown_item('MyMultiDropdown', ['My First Choice','My Second Choice'])
- select_multi_dropdown_item_by_index(index: int, choice_label: List[str], locust_request_label: str = '') SailUiForm
Selects a multiple dropdown item on the form by index (1-based) If no multiple dropdown found, throws a NotFoundException If no element found, throws a ChoiceNotFoundException
- Parameters:
index (int) – Index of the multiple dropdown to select
choice_label ([str]) – Label(s) of the multiple dropdown item to select
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_multi_dropdown_item_by_index(2, ['My First Choice','My Second Choice'])
Selects an element of a navigation card group by its index
- Parameters:
nav_group_label (str) – Label of the navigation card group
index (int) – Index of the element
- Keyword Arguments:
is_test_label (bool) – If this label is a test label
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
- select_radio_button_by_index(field_index: int, index: int, locust_request_label: str = '') SailUiForm
Selects a radio button by its field index Index is position to be selected
- Parameters:
field_index (int) – Index of the radio button field on the page
index (int) – Index of the radio button to select
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_radio_button_by_index(1, 1) # selects the first item in the first radio button field
- select_radio_button_by_label(label: str, index: int, locust_request_label: str = '') SailUiForm
Selects a radio button by its label Index is position to be selected
- Parameters:
label (str) – Label of the radio button field
index (int) – Index of the radio button to select
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_radio_button_by_label('myLabel', 1) # selects the first item
- select_radio_button_by_test_label(test_label: str, index: int, locust_request_label: str = '') SailUiForm
Selects a radio button by its test label Index is position to be selected
- Parameters:
test_label (str) – Label of the radio button field
index (int) – Index of the radio button to select
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_radio_button_by_test_label('myTestLabel', 1) # selects the first item
- select_rows_in_grid(rows: List[int], label: str | None = None, index: int | None = None, append_to_existing_selected: bool = False, locust_request_label: str = '') SailUiForm
Selects rows in a grid Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
rows (List[int]) – The rows to select
label (str) – Label of the grid
index (int) – Index of the grid
append_to_existing_selected (bool) – Flag to control appending row selections
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.select_rows_in_grid(rows=[1], label='my nice grid')
- sort_paging_grid(label: str | None = None, index: int | None = None, field_name: str = '', ascending: bool = False, locust_request_label: str = '') SailUiForm
Sorts a paging grid by the field name, which is not necessarily the same as the label of the column And might require inspecting the JSON to determine what the sort field is
Sorts by ascending = False by default, override to set it to True
Either a label or an index is required, indices are useful if there is no title for the grid
- Parameters:
label (str) – Label of the grid
index (int) – Index of the grid
field_name (str) – Field to sort on (not necessarily the same as the displayed one)
ascending (bool) – Whether to sort ascending, default is false
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.sort_paging_grid(index=0,field_name='Total',ascending=True)
- upload_document_to_upload_field(label: str, file_path: str, locust_request_label: str = '') SailUiForm
Uploads a document to a named upload field There are two steps to this which can fail, one is the document upload, the other is finding the component and applying the update.
- Parameters:
label (str) – Label of the upload field
file_path (str) – File path to the document
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Examples
>>> form.upload_document_to_upload_field('Upload File', "/usr/local/appian/File.zip") >>> form.upload_document_to_upload_field('Upload Properties', "/usr/local/appian/File.properties")
- upload_documents_to_multiple_file_upload_field(label: str, file_paths: List[str], locust_request_label: str = '') SailUiForm
Uploads multiple documents to a named upload field There are two steps to this which can fail, one is the document uploads, the other is finding the component and applying the update.
- Parameters:
label (str) – Label of the upload field
file_paths (list) – List of document file paths in string form
- Keyword Arguments:
locust_request_label (str) – Label used to identify the request for locust statistics
Returns (SailUiForm): The latest state of the UiForm
Example
>>> form.multi_upload_document_to_upload_field('Upload Files', ["/usr/local/appian/File1.zip", "/usr/local/appian/File2.zip"])
Utilities module
- appian_locust.utilities.credentials.procedurally_generate_credentials(CONFIG: dict) None
Helper method that can be used to procedurally generate a set of Appian user credentials
Note: This class must be called in the UserActor class of your Locust test in order to create the credentials before any Locust users begin to pick them up.
- Parameters:
CONFIG – full locust config dictionary, AKA the utls.c variable in locust tests Make sure the following keys are present.
procedural_credentials_prefix – Base string for each generated username
procedural_credentials_count – Appended to prefix, will create 1 -> Count+1 users
procedural_credentials_password – String which will serve as the password for all users
- Returns:
None
- appian_locust.utilities.credentials.setup_distributed_creds(CONFIG: dict) dict
Helper method to distribute Appian credentials across separate load drivers when running Locust in distributed mode. Credential pairs will be passed out in Round Robin fashion to each load driver.
Note: This class must be called in the UserActor class of your Locust test to ensure that the “credentials” key is prepared before tests begin.
Note: If fewer credential pairs are provided than workers, credentials will be distributed to workers in a Modulo fashion.
- Parameters:
CONFIG – full locust config dictionary, AKA the utls.c variable in locust tests Make sure the following keys are present.
- Returns:
same as input but with credentials key updated to just the subset of credentials required for given load driver.
- Return type:
CONFIG
- appian_locust.utilities.helper.extract_all_by_label(obj: dict | list, label: str) list
Recursively search for all fields with a matching label in JSON tree. :param obj: The json tree to search for fields in :param label: The label used to identify elements we want to return
Returns (list): A list of all elements in obj that match label
- appian_locust.utilities.helper.extract_values(obj: Dict[str, Any], key: str, val: Any) List[Dict[str, Any]]
Pull all values of specified key from nested JSON.
- Parameters:
obj (dict) – Dictionary to be searched
key (str) – tuple of key and value.
val (any) – value, which can be any type
- Returns:
list of matched key-value pairs
- appian_locust.utilities.helper.extract_values_multiple_key_values(obj: Dict[str, Any], key: str, vals: List[Any]) List[Dict[str, Any]]
Pull all values where the key value matches an entry in vals from nested JSON.
- Parameters:
obj (dict) – Dictionary to be searched
key (str) – a key in the dictionary
vals (List[any]) – A list of values corresponding to the key, which can be any type
- Returns:
list of matched key-value pairs
- appian_locust.utilities.helper.find_component_by_attribute_and_index_in_dict(attribute: str, value: str, index: int, component_tree: Dict[str, Any]) Any
Find a UI component by the given attribute (label for example) in a dictionary It returns the index’th match in a depth first search of the json tree It returns the dictionary that contains the given attribute with the given value or throws an error when none is found
- Parameters:
attribute – an attribute to search (‘label’ for example)
value – the value of the attribute (‘Submit’ for example)
index – the index of the component to find if multiple components are found with the same ‘value’ for ‘attribute’ (1 for example)
component_tree – the json response.
- Returns:
The json object of the component
- Raises:
ComponentNotFoundException if the component cannot be found. –
Example
>>> find_component_by_attribute_and_index_in_dict('label', 'Submit', 1, self.json_response)
will search the json response to find the first component that has ‘Submit’ as the label
- appian_locust.utilities.helper.find_component_by_attribute_in_dict(attribute: str, value: str, component_tree: Dict[str, Any], raise_error: bool = True, throw_attribute_exception: bool = False) Any
Find a UI component by the given attribute (label for example) in a dictionary It only returns the first match in a depth first search of the json tree It returns the dictionary that contains the given attribute with the given value or throws an error when none is found.
- Parameters:
attribute – an attribute to search (‘label’ for example)
value – the value of the attribute (‘Submit’ for example)
component_tree – the json response.
raise_error – If set to False, will return None instead of raising an error. (Default: True)
throw_attribute_exception – If set to False then if the component is not found an exception is thrown using the attribute and value in the exception.
- Returns:
The json object of the component
- Raises:
ComponentNotFoundException if the component cannot be found. –
Example
>>> find_component_by_attribute_in_dict('label', 'Submit', self.json_response)
will search the json response to find a component that has ‘Submit’ as the label
- appian_locust.utilities.helper.find_component_by_index_in_dict(component_type: str, index: int, component_tree: Dict[str, Any]) Any
Find a UI component by the index of a given type of component (“RadioButtonField” for example) in a dictionary Performs a depth first search and counts quantity of the component, so the 1st is the first one It returns the dictionary that contains the given attribute with the requested index or throws an error when none is found.
- Parameters:
component_type – type of the component(#t in the JSON response, ‘RadioButtonField’ for example)
index – the index of the component with the component_type (‘1’ for example - Indices start from 1)
component_tree – the json response
- Returns:
The json object of the component
- Raises:
ComponentNotFoundException if the component cannot be found. –
Example
>>> find_component_by_index_in_dict('RadioButtonField', 1, self.json_response)
will search the json response to find the first component that has ‘RadioButtonField’ as the type
- appian_locust.utilities.helper.find_component_by_label_and_type_dict(attribute: str, value: str, type: str, component_tree: Dict[str, Any], raise_error: bool = True) Any
Find a UI component by the given attribute (like label) in a dictionary, and the type of the component as well. (#t should match the type value passed in) It only returns the first match in a depth first search of the json tree. It returns the dictionary that contains the given attribute with the given label and type or throws an error when none is found if the raise_error value is True. Otherwise it will return None if the component cannot be found.
- Parameters:
label – label of the component to search
value – the value of the label
type – Type of the component (TextField, StartProcessLink etc.)
component_tree – the json response.
raise_error – If set to False, will return None instead of raising an error. (Default: True)
- Returns:
The json object of the component or None if the component cannot be found.
- Raises:
ComponentNotFoundException if the component cannot be found. –
Example
>>> find_component_by_label_and_type_dict('label', 'MyLabel', 'StartProcessLink', self.json_response)
- appian_locust.utilities.helper.find_component_by_type_and_attribute_and_index_in_dict(component_tree: Dict[str, Any], type: str = '', attribute: str = '', value: str = '', index: int = 1, raise_error: bool = True) Any
Find a UI component by the given type and/or attribute with ‘value’ in a dictionary Returns the index’th match in a depth first search of the json tree Returns the dictionary that contains the given attribute with the given value or throws an error when none is found Note: Both type and attribute matching are optional, which will cause this function to return the index’th component in the tree
- Parameters:
component_tree – the json response
- Keyword Arguments:
type (str) – the component type to match against (default: ‘’)
attribute (str) – an attribute to search (default: ‘’)
value (str) – the value of the attribute (default: ‘’)
index (int) – the index of the component to find if multiple components match the above criteria, 1-indexed (default: 1)
raise_error (bool) – if this is set to false, it will return None instead of raising an error.
- Returns:
The json object of the component or None if ‘raise_error’ is set to false.
- Raises:
ComponentNotFoundException if the attribute or type checks fail. –
Exception if the component is found but at an incorrect index. –
Example
>>> find_component_by_attribute_and_index_in_dict('label', 'Submit', 1, self.json_response)
will search the json response to find the first component that has ‘Submit’ as the label
- appian_locust.utilities.helper.format_label(label: str, delimiter: str | None = None, index: int = 0) str
Simply formats the string by replacing a space with underscores
- Parameters:
label – string to be formatted
delimiter – If provided, string will be split by it
index – used with delimiter parameter, which item will be used in the “split”ed list.
- Returns:
formatted string
- appian_locust.utilities.helper.get_random_item(list_of_items: List[Any], exclude: List[Any] = []) Any
Gets a random item from the given list excluding the items if any provided
- Parameters:
list_of_items – list of items of any data type
exclude – if any items needs to be excluded in random pick
- Returns:
Randomly picked Item
- Raises:
In case of no item to pick, Exception will be raised –
- appian_locust.utilities.helper.get_username(auth: list) str
Returns the username from an auth list :param auth: Appian Locust authorization list
Returns (str): Username from auth list
- appian_locust.utilities.helper.list_filter(list_var: List[str], filter_string: str, exact_match: bool = False) List[str]
from the given list, return the list with filtered values.
- Parameters:
list_var (list) – list of strings
filter_string (str) – string which will be used to filter
exact_match (bool, optional) – filter should be based on exact match or partial match. default is partial.
- Returns:
List with filtered values
- appian_locust.utilities.helper.remove_type_info(sail_dict: Dict[str, Any]) Dict[str, Any]
Returns a flattened dictionary with SAIL type info removed :param sail_dict: SAIL Dictionary to remove type information from
Returns (dict): Flattened dictionary
- appian_locust.utilities.helper.repeat(num_times: int = 2, wait_time: float = 0.0) Callable
This function allows an arbitrary function to be executed an arbitrary number of times The intended use is as a decorator:
>>> @repeat(2) ... def arbitrary_function(): ... print("Hello World") ... arbitrary_function() Hello World Hello World
- Parameters:
num_times (int) – an integer
- Implicit Args:
arbitrary_function (Callable): a python function
- Returns:
A reference to a function which performs the decorated function num_times times
- class appian_locust.utilities.loadDriverUtils.loadDriverUtils
Bases:
object
- load_config(config_file: str = './config.json') dict
Load a json configuration file into a dictionary :param config_file: Location where config file can be found
- Returns (dict): Dictionary containing configuration. Will also be stored in
loadDriverUtils.c
- appian_locust.utilities.logger.getLogger(name: str | None = None) Logger
- Parameters:
name (str, optional) – Name of the logger. it is common practice to use file name here but it can be anything.
Returns: logger object
Note
By contributing to this Open Source project, you provide Appian Corporation a non-exclusive, perpetual, royalty-free license to use your contribution for any purpose.
Contributing
Fork the appian-locust repository
Make any desired changes
Commit changes and push to your fork
Make a merge request to the upstream fork and project maintainers will review it
New Development
As new development is done to Appian Locust, the core principle of user navigation and resulting interaction should be kept in mind.
Is your feature adding interaction capabilities to an existing type of page? If so, you likely want to add a new method to an
existing SailUiForm
type. Otherwise, you might need to create a new extention of SailUiForm
and ensure that the Visitor
class has the capabilities to visit the new page type. Lastly, functionality that doesn’t involve user interaction should be included in the
SiteHelper
class.
If you think that your development falls outside of the above criteria, you should submit an issue for the maintainers of this project to discuss your use case.
To Test Your Changes
In any test-implementation repo where you use appian-locust, change the following (assuming you’re using a Pipfile
)
appian-locust = {path="../appian-locust", editable=true}
NOTE The path above assumes appian-locust is checked out locally, hence we can use a relative directory path.
And run pipenv install --skip-lock
to allow you to use a local version of appian-locust
without recreating the lock file. However, remember to use a lock file in your test-implementation repo.
Now you can test your changes as you normally would.
Internal Classes
Apart from our exposed API, we provide internal classes for more granular control when developing or testing.
- class appian_locust._actions._Actions(interactor: _Interactor)
Bases:
_Base
- clear_actions_cache() None
- fetch_action_json(action_name: str, exact_match: bool = False, label: str = '') Dict[str, Any]
This function calls the API for the specific action to get its “form” data
- Parameters:
action_name (str) – Name of the action to be called. Name of the action will be in the below pattern. “displayLabel::opaquqId”
exact_match (bool, optional) – Should action name match exactly or to be partial match. Default : False
Returns (dict): Response of actions’s Get UI call in dictionary
Examples
If the full name of the action is known, with the opaque ID,
>>> self.appian.action.fetch_action_json("action_name:igB0K7YxC0UQ2Fhx4hicRw...", exact_match=True)
If only the display name is known, or part of the display name
>>> self.appian.action.fetch_action_json("action_name") >>> self.appian.action.fetch_action_json("actio")
- get_action(action_name: str, exact_match: bool = False) Dict[str, Any]
Get the information about specific action by name.
- Parameters:
action_name (str) – Name of the action
exact_match (bool) – Should action name match exactly or to be partial match. Default : False
Returns (dict): Specific Action’s info
Raises: In case of action is not found in the system, it throws an “Exception”
Example
If full name of action is known, with the opaque ID,
>>> self.appian.action.get_action("action_name:igB0K7YxC0UQ2Fhx4hicRw...", exact_match=True)
If only the display name is known, or part of the display name
>>> self.appian.action.get_action("action_name") >>> self.appian.action.get_action("actio")
- get_actions_feed(locust_request_label: str = 'Actions') Dict[str, Any]
- get_actions_interface(locust_request_label: str = 'Actions') Dict[str, Any]
- get_all(search_string: str | None = None, locust_request_label: str = 'Actions.MainMenu.AvailableActions') Dict[str, Any]
Retrieves all the available “actions” and associated metadata from “Appian-Tempo-Actions”
Note: All the retrieved data about actions is stored in the private variable self._actions
Returns (dict): List of actions and associated metadata
Examples
>>> self.appian.action.get_all()
- get_errors_count() int
- start_action(action_name: str, skip_design_call: bool = False, exact_match: bool = False) Response
Perform the post operation on action’s API to start specific action. Actions that do not have a UI can be called directly without using “GET” to retrieve the UI. this is controlled by the optional skip_design_call parameter
- Parameters:
action_name (str) – Name of the action
skip_design_call (bool, optional) – to skip the “GET” call for the action’s UI. Default : False
exact_match (bool, optional) – Should action name match exactly or to be partial match. Default : False
Returns: NONE
Example
>>> self.appian.action.start_action("action_name")
- class appian_locust._admin._Admin(interactor: _Interactor)
Bases:
object
- fetch_admin_json(locust_request_label: str | None = None) Dict[str, Any]
Navigates to /admin
Returns: The response of /admin
- class appian_locust._base._Base
Bases:
object
Base class for classes
_Actions
,_News
,_Records
,_Reports
,_Tasks
,Sites
- get(items_in_dict: dict, item_name: str, exact_match: bool = True, ignore_retry: bool = False, search_string: str | None = None) tuple
Common Get function to get the specific component from dictionary of items. If item is not found, it calls get_all function to update itself and retry.
Warning: Internal function, should never be called directly.
- Parameters:
items_in_dict (dict) – Dictionary of component (for ex, dictionary of actions if called from actions class)
item_name (str) – Component name (for ex, action name if called from actions class)
exact_match (bool, optional) – Should item name match exactly or to be partial match. Default : True
ignore_retry (bool, optional) – Whether to retry or not if item is not found in first try.
search_string (str, optional) – String to filter the results of get_all function. Currently supported only for
News
Returns: Tuple of item name and full properties of item If item found, otherwise tuple of Nones
- get_all(search_string: str | None = None, locust_request_label: str = '') Any
Common Get All function prototype that is overwritten by subclasses. Created only to conform to Mypy validation.
- class appian_locust._data_fabric._DataFabric(interactor: _Interactor)
Bases:
object
- fetch_data_fabric_dashboard_json(encoded_uri_stub: str = 'new', locust_request_label: str | None = None) Dict[str, Any]
- fetch_data_fabric_json(locust_request_label: str | None = None) Dict[str, Any]
- class appian_locust._design._Design(interactor: _Interactor)
Bases:
object
- click_expression_editor_toolbar_button(button_action: str, post_url: str, state: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
- create_ai_skill_object(ui_form: SailUiForm, ai_skill_name: str, ai_skill_type: AISkillObjectType) SailUiForm
- create_object(ui_form: SailUiForm, link_name: str, object_name: str) SailUiForm
- fetch_application_json(app_id: str, locust_request_label: str | None = None) Dict[str, Any]
Fetches the JSON of the UI for a specific application within the /design environment
Returns: JSON Dictionary
Example
>>> design.fetch_application_json("AADZeglVgAAgfpsAAJsAAAAAAdA")
- fetch_design_json(locust_request_label: str | None = None) Dict[str, Any]
Fetches the JSON of /design UI
Returns: JSON Dictionary
Example
>>> design.fetch_design_json()
- fetch_design_object_json(opaque_id: str, locust_request_label: str | None = None) Dict[str, Any]
Fetches the JSON of the UI for a specific object within the /design environment
Returns: JSON Dictionary
Example
>>> design.fetch_design_object_json("lABD1iTIu_lxy_3T_90Is2fs63uh52xESYi6-fun7FBWshlrBQ0EptlFUdGyIRzSSluPyVdvOhvGgL6aBlnjlkWfQlALYR2aRZ_AIliJ4lc3g")
- find_design_grid(state: Dict[str, Any]) Dict[str, Any]
- find_design_object_opaque_id_in_grid(design_object_name: str, current_state: Dict[str, Any]) str
- find_design_object_type_indices(current_state: Dict[str, Any], design_object_types: list[str]) list[int]
- search_design_grid(search_str: str, reeval_url: str, state: Dict[str, Any], context: Dict[str, Any], uuid: str, locust_label: str = 'Design.Search') Dict[str, Any]
Search a grid in /design :param search_str: string to search :type search_str: str :param reeval_url: url to send request to :type reeval_url: str :param state: current state of UI, which contains the search bar :type state: str :param context: current context :type context: str :param uuid: UUID of search component :type uuid: str :param locust_label: label to associate request with :type locust_label: str
Returns:
- appian_locust._design.get_available_design_objects(state: Dict[str, Any]) Dict[str, DesignObject]
- appian_locust._design.validate_design_object_access_method(design_object_json: Dict[str, Any], object_type_to_method_dict: Dict[str, Any]) None
- appian_locust._feature_toggle_helper.__get_javascript_feature_flag_regex() Generator[str, None, None]
- appian_locust._feature_toggle_helper.__get_javascript_uri_regex() Generator[str, None, None]
- appian_locust._feature_toggle_helper.__get_mobile_feature_flag_overrides() Generator[FeatureFlag, None, None]
- appian_locust._feature_toggle_helper._create_override_flag_mask(flags_to_override: Callable[[], Generator[FeatureFlag, None, None]]) int
Given a list of flag enums from FeatureFlag, this will set that flag to 1 to override the default feature set. returns flag mask reflecting all the flags combined.
- appian_locust._feature_toggle_helper._get_feature_flags_from_regex_match(flag_str: str) Tuple[str, str]
Coerce flags into proper format for sending as headers
- appian_locust._feature_toggle_helper._get_javascript_and_find_feature_flag(client: HttpSession, script_uri: str, headers: Dict[str, Any] | None = None) Any
Read through minified javascript for feature flags
- appian_locust._feature_toggle_helper._get_javascript_uri(interactor: _Interactor, headers: Dict[str, Any] | None = None) Any
Gets the URI for the javascript file that contains the Feature Toggles
- appian_locust._feature_toggle_helper._to_hex_str(flagVal: int) str
- appian_locust._feature_toggle_helper._truncate_flag_extended(flag_extended: int) int
- appian_locust._feature_toggle_helper.get_client_feature_toggles(interactor: _Interactor, session: HttpSession) Tuple[str, str]
Given an authenticated user, recover the feature toggles from the minified javascript
Returns: Returns feature flag if found, otherwise empty string
- appian_locust._feature_toggle_helper.override_default_feature_flags(interactor: _Interactor, flags_to_override: Callable[[], Generator[FeatureFlag, None, None]]) None
Given a list of flag enums from FeatureFlag, override_default_flags gets the flag mask to set all of the flags to true, and it overrides the current feature flag extended value to set these flags to true.
- appian_locust._feature_toggle_helper.set_mobile_feature_flags(interactor: _Interactor) None
This overrides the feature flags to tell the service that the request is coming from a mobile device.
- class appian_locust._grid_interactor.GridInteractor
Bases:
object
Set of utility methods for interacting with grids, i.e. finding them, and manipulating them
- _get_grid_data(paging_grid: Dict[str, Any]) Dict[str, Any]
- _get_sort_info(field_name: str, ascending: bool) List[Dict[str, Any]]
- _to_save_data(grid_data: Dict[str, Any], paging_grid: Dict[str, Any]) Dict[str, Any]
- _validate_grid_field_or_label(field_name: str, paging_grid: Dict[str, Any]) str
- find_grid_by_index(index: int, form: Dict[str, Any]) Dict[str, Any]
- find_grid_by_label(label: str, form: Dict[str, Any]) Dict[str, Any]
- find_grid_by_label_or_index(form: Dict[str, Any], label: str | None = None, index: int | None = None) Dict[str, Any]
- find_plaintext_grid_link_component(grid: Dict[str, Any], column_name: str, row_index: int) Dict[str, Any] | None
- find_rich_text_grid_link_component(grid: Dict[str, Any], column_name: str, row_index: int) Dict[str, Any] | None
- format_grid_display_label(grid: Dict[str, Any]) str
- move_to_first_page(paging_grid: Dict[str, Any]) Dict[str, Any]
- move_to_last_page(paging_grid: Dict[str, Any]) Dict[str, Any]
- move_to_the_left(paging_grid: Dict[str, Any]) Dict[str, Any]
- move_to_the_right(paging_grid: Dict[str, Any]) Dict[str, Any]
- select_rows(paging_grid: Dict[str, Any], rows: List[int], append_to_existing_selected: bool = False) Dict[str, Any]
- sort_grid(field_name: str, paging_grid: Dict[str, Any], ascending: bool = False) Dict[str, Any]
- validate_sort(field_name: str, paging_grid: Dict[str, Any]) None
- class appian_locust._interactor.DataTypeCache
Bases:
object
- cache(response_in_json: Dict[str, Any]) None
From the given json response, finds and caches the data type :param response_in_json: response of the API request
- clear() None
Clears the data type cache
- get() str
Concatenates all cached data types and returns a string
Returns: concatenated cached data type string
- class appian_locust._interactor._Interactor(session: HttpSession, host: str, portals_mode: bool = False, request_timeout: int = 300)
Bases:
object
- static _clean_filename(label: str) str
- _make_file_metadata(doc_info: Dict[str, Any]) dict
Produces a file metadata object to use for multifile upload fields
- Parameters:
id (int) – Document id of the object
- Returns:
Dictionary of the multifile upload data
- Return type:
dict
- check_login(resp: ResponseContextManager) None
Given a response, checks to see if it’s possible that we are not logged in and then performs a login if we are not
- Parameters:
resp – Response to check
Returns: None
- check_post_response_for_valid_auth(resp: ResponseContextManager) None
Given a POST response, checks to see if we are correctly authenticated :param resp: POST request response to examine
Returns: None
- click_button(post_url: str, component: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None, headers: Dict[str, Any] | None = None, client_mode: str | None = None) Dict[str, Any]
Calls the post operation to click certain SAIL components such as Buttons and Dynamic Links
- Parameters:
post_url – the url (not including the host and domain) to post to
component – the JSON code for the desired component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
label – the label to be displayed by locust for this action
headers – header for the REST API call
Returns: the response of post operation as json
- click_component(post_url: str, component: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None, headers: Dict[str, Any] | None = None, client_mode: str | None = None) Dict[str, Any]
Calls the post operation to click certain SAIL components such as Buttons and Dynamic Links
- Parameters:
post_url – the url (not including the host and domain) to post to
component – the JSON code for the desired component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
label – the label to be displayed by locust for this action
headers – header for the REST API call
Returns: the response of post operation as json
- click_generic_element(post_url: str, component: Dict[str, Any], context: Dict[str, Any], uuid: str, new_value: Dict[str, Any], label: str | None = None) Dict[str, Any]
Calls the post operation to click on a generic element
- Parameters:
post_url – the url (not including the host and domain) to post to
component – the JSON code for the component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
new_value – value for the payload
label – the label to be displayed by locust for this action
Returns: the response of post operation as json
- click_link(post_url: str, component: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None, headers: Dict[str, Any] | None = None, client_mode: str | None = None) Dict[str, Any]
Calls the post operation to click certain SAIL components such as Buttons and Dynamic Links
- Parameters:
post_url – the url (not including the host and domain) to post to
component – the JSON code for the desired component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
label – the label to be displayed by locust for this action
headers – header for the REST API call
Returns: the response of post operation as json
- click_record_link(get_url: str, component: Dict[str, Any], context: Dict[str, Any], label: str | None = None, headers: Dict[str, Any] | None = None, locust_label: str = '') Dict[str, Any]
Use this function to interact specifically with record links, which represent links to new sail forms. :param get_url: the url (not including the host and domain) to navigate to :param component: the JSON code for the RecordLink :param context: the Sail context parsed from the json response :param label: the label to be displayed by locust for this action :param headers: header for the REST API call
Returns: the response of get RecordLink operation as json
- click_record_list_action(component_label: str, process_model_uuid: str, cache_key: str, locust_request_label: str | None = None) Dict[str, Any]
- click_record_search_button(post_url: str, component: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
Calls the post operation to click a record search button
- Parameters:
post_url – the url (not including the host and domain) to post to
component – the JSON code for the desired SearchBoxWidget component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
label – the label to be displayed by locust for this action
Returns: the response of post operation as json
Use this function to interact with related action links, which start a process and return the start form. This can handle both relation actions and related action links that open in a dialog.
- Parameters:
component – the JSON representing the Related Action Link
record_type_stub – record type stub for the record
opaque_record_id – opaque id for the record
opaque_related_action_id – opaque id for the related action
locust_request_label – label to be used within locust
open_in_a_dialog – Does this link open in a dialog
Returns: the start form for the related action
- click_selected_tab(post_url: str, tab_group_component: Dict[str, Any], tab_label: str, context: Dict[str, Any], uuid: str) Dict[str, Any]
Calls the post operation to send an update to a tabgroup to select a tab
- Parameters:
post_url – the url (not including the host and domain) to post to
tab_group_component – the JSON representing the desired TabButtonGroup SAIL component
tab_label – Label of the tab to select
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
label – the label of the tab to select. It is one of the tabs inside TabButtonGroup
Returns: the response of post operation as json
- click_start_process_link(component: Dict[str, Any], process_model_opaque_id: str, cache_key: str, site_name: str, page_name: str, group_name: str | None = None, is_mobile: bool = False, locust_request_label: str | None = None) Dict[str, Any]
Use this function to interact with start process links, which start a process and return the start form. :param component: the JSON representing the Start Process Link :param process_model_opaque_id: opaque id for the process model of the Start Process Link :param cache_key: cachekey for the start process link :param site_name: name of site for link in starting process model. :param page_name: name of page for link in starting process model. :param group_name: name of group for link in starting process model, if there is one. :param is_mobile: indicates if it should hit the mobile endpoint. :param locust_request_label: label to be used within locust
Returns: the response of get Start Process Link operation as json
- construct_and_send_dropdown_update(component: Any, choice_label: str, context: Dict[str, Any], state: Dict[str, Any], uuid: str, context_label: str, exception_label: str, reeval_url: str, identifier: Dict[str, Any] | None = None) Dict[str, Any]
Calls the post operation to send an update to a dropdown
- Parameters:
component – the dropdown component to update
choice_label – Label of the dropdown
context – the Sail context parsed from the json response
state – the Sail state parsed from the json response
uuid – the uuid parsed from the json response
context_label – the label to be displayed by locust for this action
exception_label – information about the dropdown component to be displayed if there is an exception
reeval_url – URL for “rel”=”update”, which is used to do other interactions on the form
identifier – the Record List Identifier, if made on a Record List
Returns: the response of post operation as json
- construct_and_send_multiple_dropdown_update(component: Any, choice_label: List[str], context: Dict[str, Any], state: Dict[str, Any], uuid: str, context_label: str, exception_label: str, reeval_url: str, identifier: Dict[str, Any] | None = None) Dict[str, Any]
Calls the post operation to send an update to a multiple dropdown
- Parameters:
component – the multiple dropdown component to update
choice_label – Label(s) of the multiple dropdown item to select
context – the Sail context parsed from the json response
state – the Sail state parsed from the json response
uuid – the uuid parsed from the json response
context_label – the label to be displayed by locust for this action
exception_label – information about the multiple dropdown component to be displayed if there is an exception
reeval_url – URL for “rel”=”update”, which is used to do other interactions on the form
identifier – the Record List Identifier, if made on a Record List
Returns: the response of post operation as json
- fetch_new_cascading_pickerfield_selection(pickfield_payload: List, locust_request_label: str = 'SelectCascadingPickerField') Dict[str, Any]
- fill_cascading_pickerfield_request(request_payload: List, choice: Dict[str, Any]) List
- fill_pickerfield_text(post_url: str, picker_field: Dict[str, Any], text: str, context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
Fill a Picker field with the given text and randomly select one of the suggested item :param post_url: the url (not including the host and domain) to post to :param picker_field: the picker field component returned from find_component_by_attribute_in_dict :param text: the text to fill into the picker field :param context: the SAIL context parsed from the json response :param uuid: the uuid parsed from the json response :param label: the label to be displayed by locust for this action
Returns: the response of post operation as json
- fill_textfield(post_url: str, text_field: Dict[str, Any], text: str, context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
Fill a TextField with the given text :param post_url: the url (not including the host and domain) to post to :param text_field: the text field component returned from find_component_by_attribute_in_dict :param text: the text to fill into the text field :param context: the Sail context parsed from the json response :param uuid: the uuid parsed from the json response :param label: the label to be displayed by locust for this action
Returns: the response of post operation as json
- find_selection_from_choices(selection: str, choices: List) Dict[str, Any] | None
- get_interaction_host() str
- get_page(uri: str, headers: Dict[str, Any] | None = None, label: str | None = None, check_login: bool = True) Response
Given a uri, executes GET request and returns response
- Parameters:
uri – API URI to be called
headers – header for the REST API Call
label – the label to be displayed by locust
check_login – optional boolean to bypass checking if we are logged in
Returns: Json response of GET operation
- get_primary_button_payload(page_content_in_json: Dict[str, Any]) Dict[str, Any]
Finds the primary button from the page content response and creates the payload which can be used to simulate a click
- Parameters:
page_content_in_json – full page content that has a primary button
Returns: payload of the primary button
- get_url_provider() UrlProvider
- initialize_cascading_pickerfield_request(pickerfield_component: Dict[str, Any]) List
- interact_with_record_grid(post_url: str, grid_component: Dict[str, Any], context: Dict[str, Any], uuid: str, identifier: Dict[str, Any] | None = None, context_label: str | None = None) Dict[str, Any]
Calls the post operation to send a record grid update
- Parameters:
post_url – the url (not including the host and domain) to post to
grid_component – the JSON dict representing the grid to update
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
identifier – the Record List Identifier, if made on a Record List
context_label – the label to be displayed by locust for this action
Returns: the response of post operation as json
- login(auth: list | None = None, retry: bool = True, check_login: bool = True) Tuple[HttpSession, Response]
- post_page(uri: str, payload: Any = {}, headers: Dict[str, Any] | None = None, label: str | None = None, files: dict | None = None, raise_error: bool = True, check_login: bool = True) Response
Given a uri, executes POST request and returns response
- Parameters:
uri – API URI to be called
payload – Body of the API request. Can be either JSON or text input to allow for different payload types.
headers – header for the REST API Call
label – the label to be displayed by locust
Returns: Json response of post operation
- refresh_after_record_action(post_url: str, record_action_component: Dict[str, Any], record_action_trigger_component: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
Calls the post operation to refresh a form after completion of a record action
- Parameters:
post_url – the url (not including the host and domain) to post to
record_action_component – the JSON representing the relevant record action component
record_action_trigger_component – the JSON representing the form’s record action trigger component
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
Returns: the response of post operation as json
- replace_base_path_if_appropriate(uri: str) str
- select_checkbox_item(post_url: str, checkbox: Dict[str, Any], context: Dict[str, Any], uuid: str, indices: list, context_label: str | None = None) Dict[str, Any]
Calls the post operation to send an update to a checkbox to check all appropriate boxes
- Parameters:
post_url – the url (not including the host and domain) to post to
checkbox – the JSON representing the desired checkbox
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
indices – indices of the checkbox
label – the label to be displayed by locust for this action
headers – header for the REST API call
Returns: the response of post operation as json
- select_pickerfield_suggestion(post_url: str, picker_field: Dict[str, Any], selection: Dict[str, Any], context: Dict[str, Any], uuid: str, label: str | None = None) Dict[str, Any]
Select a Picker field from available selections :param post_url: the url (not including the host and domain) to post to :param picker_field: the text field component returned from find_component_by_attribute_in_dict :param selection: the suggested item to select for the picker field :param context: the SAIL context parsed from the json response :param uuid: the uuid parsed from the json response :param label: the label to be displayed by locust for this action
Returns: the response of post operation as json
- select_radio_button(post_url: str, buttons: Dict[str, Any], context: Dict[str, Any], uuid: str, index: int, context_label: str | None = None) Dict[str, Any]
Calls the post operation to send an update to a radio button to select the appropriate button
- Parameters:
post_url – the url (not including the host and domain) to post to
buttons – the JSON representing the desired radio button field
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
index – index of the button to be selected
label – the label to be displayed by locust for this action
headers – header for the REST API call
Returns: the response of post operation as json
- send_dropdown_update(post_url: str, dropdown: Dict[str, Any], context: Dict[str, Any], uuid: str, index: int, identifier: Dict[str, Any] | None = None, label: str | None = None) Dict[str, Any]
Calls the post operation to send an update to a dropdown
- Parameters:
post_url – the url (not including the host and domain) to post to
dropdown – the JSON code for the desired dropdown
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
index – location of the dropdown value
identifier – the Record List Identifier, if made on a Record List
label – the label to be displayed by locust for this action
Returns: the response of post operation as json
- send_multiple_dropdown_update(post_url: str, multi_dropdown: Dict[str, Any], context: Dict[str, Any], uuid: str, index: List[int], identifier: Dict[str, Any] | None = None, label: str | None = None) Dict[str, Any]
Calls the post operation to send an update to a multiple dropdown
- Parameters:
post_url – the url (not including the host and domain) to post to
dropdown – the JSON code for the desired dropdown
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
index – locations of the multiple dropdown value identifier: the Record List Identifier, if made on a Record List
label – the label to be displayed by locust for this action
Returns: the response of post operation as json
- set_url_provider(provider: UrlProvider) None
- set_user_agent_to_desktop() None
- set_user_agent_to_mobile() None
- setup_content_headers() dict
- setup_feed_headers() dict
- setup_request_headers(uri: str | None = None) dict
Generates standard headers for session
- Parameters:
uri (str) – URI to be assigned as the Referer
Returns (dict): headers
Examples
>>> self.appian._interactor.setup_request_headers()
- setup_sail_headers() dict
- update_date_field(post_url: str, date_field_component: Dict[str, Any], date_input: date, context: Dict[str, Any], uuid: str, locust_label: str | None = None) Dict[str, Any]
Calls the post operation to update a date field
- Parameters:
post_url – the url (not including the host and domain) to post to
date_field_component – the JSON representing the date field component
date_input – date field to convert to proper text format
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
Returns: the response of post operation as json
- update_datetime_field(post_url: str, datetime_field: Dict[str, Any], datetime_input: datetime, context: Dict[str, Any], uuid: str, locust_label: str | None = None) Dict[str, Any]
Calls the post operation to update a date field
- Parameters:
post_url – the url (not including the host and domain) to post to
datetime_field – the JSON representing the datetime field to edit
datetime_input – datetime field to convert to the proper text format
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
Returns: the response of post operation as json
- update_grid_from_sail_form(post_url: str, grid_component: Dict[str, Any], new_grid_save_value: Dict[str, Any], context: Dict[str, Any], uuid: str, context_label: str | None = None) Dict[str, Any]
Calls the post operation to send a grid update
- Parameters:
post_url – the url (not including the host and domain) to post to
grid_component – the JSON dict representing the grid to update
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
uuid – indices of the checkbox
context_label – the label to be displayed by locust for this action
Returns: the response of post operation as jso
- upload_document_to_field(post_url: str, upload_field: Dict[str, Any], context: Dict[str, Any], uuid: str, doc_info: Dict[str, Any] | List[Dict[str, Any]], locust_label: str | None = None, client_mode: str = 'DESIGN') Dict[str, Any]
Calls the post operation to send an update to a upload_field to upload a document or list thereof. Requires a previously uploaded document id or ids
- Parameters:
post_url – the url (not including the host and domain) to post to
upload_field – the JSON representing the desired checkbox
context – the Sail context parsed from the json response
uuid – the uuid parsed from the json response
doc_id – document id or list of document ids for the upload
context_label – the label to be displayed by locust for this action
client_mode – where this is being uploaded to, defaults to DESIGN
Returns: the response of post operation as json
- upload_document_to_server(file_path: str, validate_extensions: bool = False, is_encrypted: bool = False) Dict[str, Any]
Uploads a document to the server, so that it can be used in upload fields :param uri: API URI to be called :param validate_extensions: if extensions should be validated :param file_path: Path to the file to be uploaded
Returns: Document Id that can be used for upload fields
- write_response_to_lib_folder(label: str | None, response: Response) None
Used for internal testing, to grab the response and put it in a file of type JSON
- Parameters:
label (Optional[str]) – Optional label, used to name the file
response (Response) – Response object to write to a file
Writes to a recorded_responses folder from wherever you run locust
- appian_locust._locust_error_handler._format_http_error(resp: Response, uri: str, username: str) str
- Taken from Response.raise_for_status. Formats the http error message,
additionally adding the username
- Parameters:
resp (Response) – Response to generate an http error message from
uri (str) – URI accessed as part of the request
username (str) – Username of the calling user
- Returns:
the http error message to use
- Return type:
str
- appian_locust._locust_error_handler.test_response_for_error(resp: ResponseContextManager, uri: str = 'No URI Specified', raise_error: bool = True, username: str = '', name: str = '') None
Locust relies on errors to be logged to the global_stats attribute for error handling. This function is used to notify Locust that its instances are failing and that it should fail too.
- Parameters:
resp (Response) – a python response object from a client.get() or client.post() call in Locust tests.
uri (Str) – URI in the request that caused the above response.
username (Str) – identifies the current user when we use multiple different users for locust test)
- Returns:
None
Example (Returns a HTTP 500 error):
username = 'admin' uri = 'https://httpbin.org/status/500' with self.client.get(uri) as resp: test_response_for_error(resp, uri, username)
- class appian_locust._news._News(interactor: _Interactor)
Bases:
_Base
- _visit_internal(news_name: str, exact_match: bool = True, search_string: str | None = None) Tuple
- fetch_news_entry_record_tags(news_entry_id: str, locust_request_label: str) Response
- get_all(search_string: str | None = None, locust_request_label: str = '') Dict[str, Any]
Retrieves all the available “news” and associated metadata from “Appian-Tempo-News”
Note: All the retrieved data about news is stored in the private variable self._news
- Parameters:
search_string (str, optional) – results will be filtered based on the search string.
Returns (dict): List of news and associated metadata
Examples
>>> self.appian.action.get_all()
- get_news(news_name: str, exact_match: bool = True, search_string: str | None = None) Dict[str, Any]
Get the information about specific news by name.
- Parameters:
news_name (str) – name of the news entry
exact_match (bool, optional) – Should news name match exactly or to be partial match. Default : True
search_string (str, optional) – results will be filtered based on the search string.
Returns: Specific News’s info
Raises: In case news is not found in the system, it throws an “Exception”
Example
If full name of action is known,
>>> self.appian.news.get("news_name")
If only partial name is known,
>>> self.appian.news.get("news_name", exact_match=False)
- search(search_string: str = '*') Dict[str, Any]
- visit(news_name: str, exact_match: bool = True, search_string: str | None = None) None
This function calls the nav API for the specific news item and its related records if any
- Parameters:
news_name (str) – Name of the news entry to be called
exact_match (bool, optional) – Should news name match exactly or to be partial match. Default : True
search_string (str, optional) – results will be filtered based on the search string.
Returns: None
Examples
If full name of news is known,
>>> self.appian.news.visit("news_name")
If only partial name is known,
>>> self.appian.news.visit("news_name", exact_match=False)
- visit_news_entry(news_name: str, exact_match: bool = True, search_string: str | None = None) Tuple
This function simulates navigating to a single entry in the ui. There are two parts to navigating to a news entry: navigating to the view and getting the news entry’s feed.
- Parameters:
news_name (str) – Name of the news entry to be called
exact_match (bool, optional) – Should news name match exactly or to be partial match. Default : True
search_string (str, optional) – results will be filtered based on the search string.
Returns (Tuple): Response codes for the view navigation and getting the feed entry
Examples
If full name of news is known,
>>> self.appian.news.visit("news_name")
If only partial name is known,
>>> self.appian.news.visit("news_name", exact_match=False)
- class appian_locust._portals._Portals(interactor: _Interactor)
Bases:
object
- fetch_page_json(portal_unique_identifier: str, portal_page__unique_identifier: str, locust_request_label: str | None = None) Dict[str, Any]
Navigates to specific portal’s page
Returns: The response of portal’s page
- static get_full_url(portal_unique_identifier: str, portal_page__unique_identifier: str) str
- class appian_locust._rdo_interactor._RDOInteractor(interactor: _Interactor, rdo_host: str)
Bases:
_Interactor
- _make_mlas_file_metadata(id: int, doc_size: int, position: int, file_name: str) dict
Produces a file metadata object to use for multifile upload fields
- ai_skill_creation_payload(jwt_token: str, app_prefix: str) dict
- ai_skill_creation_save_payload(state: Dict[str, Any], object_uuid: str) dict
- fetch_ai_skill_creation_dialog_json(app_prefix: str, locust_request_label: str = 'AISkill.CreateDialog') Dict[str, Any]
- fetch_ai_skill_creation_save_dialog_json(state: Dict[str, Any], rdo_state: Dict[str, Any], locust_request_label: str = 'AISkill.CreationSaveDialog') Dict[str, Any]
- fetch_ai_skill_designer_json(ai_skill_id: str, locust_request_label: str | None = None) Dict[str, Any]
- fetch_jwt_token() Tuple
- get_interaction_host() str
- get_presigned_url(ai_skill_id: str, model_id: str) dict
- patch_page(uri: str, payload: Any = {}, headers: Dict[str, Any] | None = None, label: str | None = None, files: dict | None = None, raise_error: bool = True) Response
- persist_ai_skill_changes_to_rdo(ai_skill_id: str, state: Dict[str, Any], locust_request_label: str | None = None) Dict[str, Any]
- post_page(uri: str, payload: Any = {}, headers: Dict[str, Any] | None = None, label: str | None = None, files: dict | None = None, raise_error: bool = True, check_login: bool = True) Response
Given a uri, executes POST request and returns response
- Parameters:
uri – API URI to be called
payload – Body of the API request. Can be either JSON or text input to allow for different payload types.
headers – header for the REST API Call
label – the label to be displayed by locust
Returns: Json response of post operation
- put_page(uri: str, payload: Any = {}, headers: Dict[str, Any] | None = None, label: str | None = None, files: dict | None = None, raise_error: bool = True) Response
- save_ai_skill_ui_request(component: Dict[str, Any], context: Dict[str, Any], uuid: str, value: Dict[str, Any], locust_request_label: str | None = None) Dict[str, Any]
- setup_mlas_file_upload_headers(kms_id: str) dict
- setup_rdo_ui_request_headers() dict
- upload_document_to_ai_skill_server(file_path: str, ai_skill_id: str, model_id: str, locust_request_label: str | None = None) Tuple[Any, int]
- upload_document_to_mlas_field(upload_field: Dict[str, Any], context: Dict[str, Any], uuid: str, file_infos: List[Dict[str, Any]], locust_label: str | None = None) Dict[str, Any]
- v1_post_request(jwt_token: str, rdo_csrf_token: str) Any
- class appian_locust._records._Records(interactor: _Interactor, is_mobile_client: bool = False)
Bases:
_Base
- _get_mobile_records_uri(record_type_url_stub: str, search_string: str | None = None) str
- _get_random_record_instance(record_type: str = '') Tuple[str, str]
- _get_random_record_type() str
- _is_response_good(response_text: str) bool
- _record_type_list_request(record_type: str, is_mobile: bool = False, search_string: str | None = None, locust_request_label: str | None = None) Dict[str, Any]
- fetch_all_records_json(locust_request_label: str = 'Records') Dict[str, Any]
- fetch_record_instance(record_type: str, record_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about a specific record by specifying its name and its record type.
- Parameters:
record_type (str) – Name of the record type.
record_name (str) – Name of the record which should be available in the given record type
exact_match (bool) – Should record name match exactly or to be partial match. Default : True
Returns (dict): Specific record’s info
Raises: In case of record is not found in the system, it throws an “Exception”
Example
If full name of record type and record is known,
>>> self.appian.records.get("record_type_name", "record_name")
If only partial name is known,
>>> self.appian.records.get("record_type_name", "record_name", exact_match=False)
- fetch_record_type(record_type: str, exact_match: bool = True) Dict[str, Any]
Fetch information about record type from the cache. Raises Exception if record type does not exist in cache.
- Parameters:
record_type (str) – Name of the record type.
Returns (dict): Specific record type’s info
Raises: In case the record type is not found in the system, it throws an “Exception”
Example
>>> self.appian.records.get_record_type("record_type_name")
- fetch_record_type_json(record_type_url_stub: str, is_mobile: bool = False, search_string: str | None = None, label: str | None = None) Dict[str, Any]
- get_all(search_string: str | None = None, locust_request_label: str = 'Records') Dict[str, Any]
Retrieves all available “records types” and “records” and associated metadata from “Appian-Tempo-Records”
Note: All the retrieved data about record types and records is stored in the private variables self._record_types and self._records respectively
Returns (dict): List of records and associated metadata
- get_all_record_types(locust_request_label: str = 'Records') Dict[str, Any]
Navigate to Tempo Records Tab and load all metadata for associated list of record types into cache.
Returns (dict): List of record types and associated metadata
- get_all_records_of_record_type(record_type: str, column_index: int | None = None, search_string: str | None = None) Dict[str, Any]
Navigate to the desired record type and load all metadata for the associated list of record views into cache.
- Parameters:
record_type (str) – Name of record type for which we want to enumerate the record instances.
column_index (int, optional) – Column index to only fetch record links from a specific column, starts at 0.
Returns (dict): List of records and associated metadata
Examples
>>> self.appian.records.get_all_records_of_record_type("record_type_name")
- get_record(record_type: str, record_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about a specific record by specifying its name and its record type.
- Parameters:
record_type (str) – Name of the record type.
record_name (str) – Name of the record which should be available in the given record type
exact_match (bool) – Should record name match exactly or to be partial match. Default : True
Returns (dict): Specific record’s info
Raises: In case of record is not found in the system, it throws an “Exception”
Example
If full name of record type and record is known,
>>> self.appian.records.get("record_type_name", "record_name")
If only partial name is known,
>>> self.appian.records.get("record_type_name", "record_name", exact_match=False)
- get_records_interface(locust_request_label: str | None = 'Records') Dict[str, Any]
- visit(record_type: str = '', record_name: str = '', view_url_stub: str = '', exact_match: bool = True, locust_request_label: str | None = None) Dict[str, Any]
This function calls the API for the specific record view/instance to get its response data.
Note: This function is meant to only traverse to Record forms, not to interact with them. For that, use visit_record_instance_and_get_form()
- Parameters:
record_type (str) – Record Type Name. If not specified, a random record type will be selected.
record_name (str) – Name of the record to be called. If not specified, a random record will be selected.
view_url_stub (str, optional) – page/tab to be visited in the record. If not specified, “summary” dashboard will be selected.
exact_match (bool, optional) – Should record type and record name matched exactly as it is or partial match.
locust_request_label (str,optional) – Label used to identify the request for locust statistics
Returns (dict): Responses of Record’s Get UI call in a dictionary
Examples
If full name of record type and record is known,
>>> self.appian.records.visit_record_instance("record_type_name", "record_name", "summary")
If only partial name is known,
>>> self.appian.records.visit_record_instance("record_type_name", "record_name", "summary", exact_match=False)
If a random record is desired,
>>> self.appian.records.visit_record_instance()
If random record of a specific record type is desired,
>>> self.appian.records.visit_record_instance("record_type_name")
- visit_record_instance(record_type: str = '', record_name: str = '', view_url_stub: str = '', exact_match: bool = True, locust_request_label: str | None = None) Dict[str, Any]
This function calls the API for the specific record view/instance to get its response data.
Note: This function is meant to only traverse to Record forms, not to interact with them. For that, use visit_record_instance_and_get_form()
- Parameters:
record_type (str) – Record Type Name. If not specified, a random record type will be selected.
record_name (str) – Name of the record to be called. If not specified, a random record will be selected.
view_url_stub (str, optional) – page/tab to be visited in the record. If not specified, “summary” dashboard will be selected.
exact_match (bool, optional) – Should record type and record name matched exactly as it is or partial match.
locust_request_label (str,optional) – Label used to identify the request for locust statistics
Returns (dict): Responses of Record’s Get UI call in a dictionary
Examples
If full name of record type and record is known,
>>> self.appian.records.visit_record_instance("record_type_name", "record_name", "summary")
If only partial name is known,
>>> self.appian.records.visit_record_instance("record_type_name", "record_name", "summary", exact_match=False)
If a random record is desired,
>>> self.appian.records.visit_record_instance()
If random record of a specific record type is desired,
>>> self.appian.records.visit_record_instance("record_type_name")
- visit_record_type(record_type: str = '', locust_request_label: str | None = None) Dict[str, Any]
Navigate into desired record type and retrieve all metadata for associated list of record views.
Returns (dict): List of records and associated metadata
Examples
>>> self.appian.records.visit_record_type("record_type_name")
- appian_locust._records_helper._get_feedItemLayout_label(item: Dict[str, Any]) str
- appian_locust._records_helper._get_linkedItem_label(item: Dict[str, Any]) str
- appian_locust._records_helper._is_grid(res_dict_var: Dict[str, Any]) bool
- appian_locust._records_helper.get_all_record_types_from_json(json_response: Dict[str, Any]) Dict[str, Any]
- appian_locust._records_helper.get_all_records_from_json(json_response: Dict[str, Any]) Tuple[Dict[str, Any], int]
- appian_locust._records_helper.get_record_header_response(form_json: Dict[str, Any]) Dict[str, Any]
This returns the contents of “x-embedded-header” from Record Instance’s Feed response. Header response is needed in cases like clicking on a related action.
- appian_locust._records_helper.get_record_summary_view_response(form_json: Dict[str, Any]) Dict[str, Any]
This returns the contents of “x-embedded-summary” from Record Instance’s Feed response
- appian_locust._records_helper.get_records_from_json_by_column(json_response: Dict[str, Any], column_index: int) Tuple[Dict[str, Any], int]
- appian_locust._records_helper.get_url_stub_from_record_list_post_request_url(post_url: str | None) str | None
Given post_url, returns the URL stub IF the url matches the url for a record list. If not, returns None.
- Parameters:
post_url – the post request url (not including the host and domain) to post to
Returns: The url stub if post_url matches a record instance list url, otherwise None
- appian_locust._records_helper.get_url_stub_from_record_list_url_path(url: str | None) str | None
Attempts to parse the url stub the url of a record list. It should only be able to parse the url stub if the page is a record list. If the url stub cannot be parsed, returns None.
- Parameters:
url – url path to attempt to parse the record list URL stub from
Returns: The url stub if post_url matches a record list url, otherwise None
- class appian_locust._reports._Reports(interactor: _Interactor)
Bases:
_Base
- fetch_report_json(report_name: str, exact_match: bool = True, locust_request_label: str | None = None) Dict[str, Any]
This function calls the API for the specific report to get its “form” data
- Parameters:
report_name (str) – Name of the report to be called.
exact_match (bool, optional) – Should report name match exactly or to be partial match. Default : True
locust_request_label (str, optional) – Label locust should associate this request with
Returns (dict): Response of report’s Get UI call in dictionary
Examples
If full name of report is known,
>>> self.appian.reports.fetch_report_json("report_name")
If only partial name is known,
>>> self.appian.reports.fetch_report_json("report_name", exact_match=False)
- get_all(search_string: str | None = None, locust_request_label: str = 'Reports.Feed') Dict[str, Any]
Retrieves all the available “reports” and associated metadata from “Appian-Tempo-Reports”
Note: All the retrieved data about reports is stored in the private variable self._reports
Returns (dict): List of reports and associated metadata
Examples
>>> self.appian.reports.get_all()
- get_report(report_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about specific report by name.
- Parameters:
report_name (str) – Name of the report
exact_match (bool) – Should report name match exactly or to be partial match. Default : True
Returns (dict): Specific Report’s info
Raises: In case of report is not found in the system, it throws an “Exception”
Example
If full name of report is known,
>>> self.appian.reports.get("report_name")
If only partial name is known,
>>> self.appian.reports.get("report_name", exact_match=False)
- get_report_form_uri(report_name: str, exact_match: bool = True) str
- get_reports_interface(locust_request_label: str = 'Reports') Dict[str, Any]
- class appian_locust._save_request_builder._SaveRequestBuilder
Bases:
object
Builds a save request, that can be used to trigger saves on the UI
- build() Dict[str, Any]
- component(component: Dict[str, Any]) _SaveRequestBuilder
- context(context: Dict[str, Any]) _SaveRequestBuilder
- identifier(identifier: Dict[str, Any] | None) _SaveRequestBuilder
- uuid(uuid: str) _SaveRequestBuilder
- value(value: dict | list) _SaveRequestBuilder
- appian_locust._save_request_builder.save_builder() _SaveRequestBuilder
- class appian_locust._sites._Sites(interactor: _Interactor)
Bases:
_Base
- BROWSER_ACCEPT_HEADER = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3'
- _get_and_memoize_site_data_from_ui(initial_nav_json: Dict[str, Any], site_name: str, display_name: str) Site
- _setup_headers_with_accept() dict
- _setup_headers_with_sail_json() dict
- fetch_site_page_metadata(site_name: str, page_name: str, group_name: str | None = None) Page | None
Gets site page from the site url stub and page url stub
- Parameters:
site_name – Site url stub
page_name – Page url stub
group_name – Group url stub, if there is one
Returns: Page object, representing an individual page of a site
- fetch_site_tab_json(site_name: str, page_name: str, locust_request_label: str | None = None) Dict[str, Any]
Navigates to a site page, either a record, action or report.
- Parameters:
site_name – Site Url stub
page_name – Page Url stub
locust_request_label (str, optional) – Label locust should associate this request with
Returns: Response of report/action/record
- fetch_site_tab_record_json(site_name: str, page_name: str, locust_request_label: str | None = None) Dict[str, Any]
Navigate to a recordList page on a site, then grab a random page from that site
Note: Any record available in the record list as a recordLink will be hit using this function. There is no guarantee that this record will be of any specific type and may not point to a record view.
- Parameters:
site_name – Site Url stub
page_name – Page Url stub
locust_request_label (str, optional) – Label locust should associate this request with
Returns: Response of report/action, or in the case of a record, response of record object
- get_all(search_string: str | None = None, locust_request_label: str | None = None) Dict[str, Any]
Gets and stores data for all sites, including all of their url stubs
- get_site_data_by_site_name(site_name: str) Site
Gets site data from just the site url stub
- Parameters:
site_name – Site url stub
Returns: Site object, containing the site name and pages
- get_site_stubs() List[str]
- class appian_locust._task_opener._TaskOpener(interactor: _Interactor)
Bases:
object
- accept_a_task(payload: str, task_id: str, headers: Dict[str, Any] | None = None, task_title: str = '', locust_request_label: str = '') Dict[str, Any]
Accept a task if necessary
- Parameters:
payload (str) – string to send as part of accepting a task
task_id (str) – task identifier
headers (Dict[str, Any], optional) – Headers to send. Defaults to {}.
task_title (str, optional) – Task title used to describe the interaction. Defaults to “”.
locust_request_label (str, optional) – label to be used within locust
- Returns:
Response from accepting
- Return type:
Dict[str, Any]
- visit_by_task_id(task_title: str, task_id: str, extra_headers: Dict[str, Any] | None = None, locust_request_label: str = '') Dict[str, Any]
Vist a task page and the corresponding json using the task_id
- Parameters:
task_title (str) – Title to identify the task
task_id (str) – Id used to navigate to the task
extra_headers (Dict[str, Any], optional) – Extra headers, used for sites requests. Defaults to None.
locust_request_label (str, optional) – label to be used within locust
- Returns:
State returned by visiting the task
- Return type:
Dict[str, Any]
- class appian_locust._tasks._Tasks(interactor: _Interactor)
Bases:
_Base
- INITIAL_FEED_URI = '/suite/api/feed/tempo?m=menu-tasks&t=t&s=pt&defaultFacets=%255Bstatus-open%255D'
- get_all(search_string: str | None = None, locust_request_label: str = 'Tasks') Dict[str, Any]
Retrieves all the available “tasks” and associated metadata from “Appian-Tempo-Tasks”
Note: All the retrieved data about tasks is stored in the private variable self._tasks
Returns (dict): List of tasks and associated metadata
Examples
>>> self.appian.task.get_all()
- get_next_task_page_uri(get_default: bool = True) str | None
Retrieves the next URI in the sequence of Task pages being fetched using self.get_task_pages().
If the previous call to self.get_task_pages() reached the end of the available pages then this method will return either a value of None or the default initial page URI depending on the get_default argument.
- Returns (str): The URI for the next page of Tasks (or the first page if the previous page fetches
reached the end).
- get_task(task_name: str, exact_match: bool = True) Dict[str, Any]
Get the information about specific task by name.
- Parameters:
task_name (str) – Name of the task
exact_match (bool) – Should task name match exactly or to be partial match. Default : True
Returns (dict): Specific task’s info
Raises: In case of task is not found in the system, it throws an “Exception”
Example
If full name of task is known,
>>> self.appian.task.get("task_name")
If only partial name is known,
>>> self.appian.task.get("task_name", exact_match=False)
- get_task_form_json(task_name: str, locust_request_label: str = '', exact_match: bool = True) Dict[str, Any]
This function calls the API for the specific task to get its “form” data
- Parameters:
task_name (str) – Name of the task to be called.
exact_match (bool, optional) – Should task name match exactly or to be partial match. Default : True
Returns (dict): Response of task’s Get UI call in dictionary
Examples
If full name of task is known,
>>> self.appian.task.get_task_form_json("task_name")
If only partial name is known,
>>> self.appian.task.get_task_form_json("task_name", exact_match=False)
- get_task_pages(locust_request_label: str = 'Tasks', next_uri: str | None = '/suite/api/feed/tempo?m=menu-tasks&t=t&s=pt&defaultFacets=%255Bstatus-open%255D', pages_requested: int = -1) Dict[str, Any]
Retrieves all the available “tasks” and associated metadata from “Appian-Tempo-Tasks”
If the next_uri argument is specified then the calls to fetch tasks will begin at that URI. If omitted the fetching starts at the first page of Tasks. This can be useful for fetching a subset of pages one call at a time. To control the number of pages fetched use the page_count argument. The default of -1 means fetch all pages (starting from the given URI.
Note: If the page_count is used and is less than the total number of pages available then the URI of the _next_ page in the sequence will be stored in self._next_uri and can be fetched with self.get_next_task_page_uri()
Note: All the retrieved data about tasks is stored in the private variable self._tasks
Returns (dict): List of tasks and associated metadata
Examples:
Start at the first page and get all content from that point forward:
>>> self.appian.task.get_task_pages()
Start at the next page (from the previous call to get_task_pages) and fetch the next three pages of Tasks:
>>> self.appian.task.get_task_pages(next_uri=self.get_next_task_page_uri(), pages_requested=3)
- class appian_locust._ui_reconciler.UiReconciler
Bases:
object
- CID_KEY = '_cId'
Reconciles the SAIL UI, based on the different responses passed
- COMPONENT_DELTA_TYPE = 'UiComponentsDelta'
- MODIFIED_COMPONENTS_KEY = 'modifiedComponents'
- _traverse_and_update_state(state: Any, cid_to_component: dict) None
Moves through a dict recursively, swapping out any components that have been modified with new ones
- reconcile_ui(old_state: dict, new_state: dict) dict
- In the case where components are simply modified:
Makes a copy of the old_state, and applies whichever changes are necessary from the new_state
- In the case where a completely new UI is returned:
Replaces the old state with the new state