chore(trading): add playwright and market sim testing framework (#5199)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com> Co-authored-by: dalebennett1992 <dalebennett1992@hotmail.co.uk>
This commit is contained in:
parent
06769f25cf
commit
02c425f304
2
.github/workflows/ci-cd-trigger.yml
vendored
2
.github/workflows/ci-cd-trigger.yml
vendored
@ -205,7 +205,7 @@ jobs:
|
||||
|
||||
console-e2e:
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) console python'
|
||||
name: '(CI) trading e2e python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: needs.check-e2e-needed.outputs.run-tests == 'true' && contains(needs.build-sources.outputs.projects, 'trading')
|
||||
|
33
.github/workflows/console-test-run.yml
vendored
33
.github/workflows/console-test-run.yml
vendored
@ -10,7 +10,7 @@ on:
|
||||
inputs:
|
||||
console-test-branch:
|
||||
type: choice
|
||||
description: 'main: v0.72.14, develop: v0.73.0-preview7'
|
||||
description: 'main: v0.72.14, develop: v0.73.4'
|
||||
options:
|
||||
- main
|
||||
- develop
|
||||
@ -153,25 +153,19 @@ jobs:
|
||||
run: |
|
||||
docker load --input /tmp/console-image.tar
|
||||
docker image ls -a
|
||||
|
||||
#----------------------------------------------
|
||||
# check-out tests repo
|
||||
# check-out frontend-monorepo
|
||||
#----------------------------------------------
|
||||
- name: Checkout console test repo
|
||||
- name: Checkout frontend-monorepo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/console-test
|
||||
ref: ${{ needs.console-test-branch.outputs.console-branch }}
|
||||
|
||||
- name: Load console test envs
|
||||
id: console-test-env
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: '.env.${{ needs.console-test-branch.outputs.console-branch }}'
|
||||
export-variables: true
|
||||
keys-case: upper
|
||||
log-variables: true
|
||||
|
||||
ref: ${{ inputs.github-sha || github.sha }}
|
||||
#----------------------------------------------
|
||||
# get vega version
|
||||
#----------------------------------------------
|
||||
- name: Set VEGA_VERSION from .env
|
||||
id: set_vega_version
|
||||
run: echo "VEGA_VERSION=$(grep VEGA_VERSION apps/trading/e2e/.env | cut -d '=' -f2)" >> $GITHUB_ENV
|
||||
#----------------------------------------------
|
||||
# ----- Setup python -----
|
||||
#----------------------------------------------
|
||||
@ -194,22 +188,25 @@ jobs:
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
run: poetry install --no-interaction --no-root
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# install vega binaries
|
||||
#----------------------------------------------
|
||||
- name: Install vega binaries
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# install playwright
|
||||
# install playwrightworking-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
- name: install playwright
|
||||
run: poetry run playwright install --with-deps chromium
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# run tests
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
|
||||
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# upload traces
|
||||
#----------------------------------------------
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -53,4 +53,11 @@ cypress.env.json
|
||||
/apps/**/cypress/downloads/
|
||||
/apps/**/fixtures/wallet/node**
|
||||
|
||||
.nx/cache
|
||||
#console-test
|
||||
__pycache__/
|
||||
apps/trading/e2e/logs/
|
||||
apps/trading/e2e/.pytest_cache/
|
||||
apps/trading/e2e/traces/
|
||||
|
||||
.nx/cache
|
||||
|
||||
|
2
apps/trading/e2e/.env
Normal file
2
apps/trading/e2e/.env
Normal file
@ -0,0 +1,2 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||
VEGA_VERSION=v0.73.4
|
2
apps/trading/e2e/.env.develop
Normal file
2
apps/trading/e2e/.env.develop
Normal file
@ -0,0 +1,2 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
|
||||
VEGA_VERSION=v0.73.4
|
2
apps/trading/e2e/.env.main
Normal file
2
apps/trading/e2e/.env.main
Normal file
@ -0,0 +1,2 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:main
|
||||
VEGA_VERSION=v0.73.4
|
136
apps/trading/e2e/README.md
Normal file
136
apps/trading/e2e/README.md
Normal file
@ -0,0 +1,136 @@
|
||||
# Trading Market-Sim End-To-End Tests
|
||||
|
||||
This direcotry contains end-to-end tests for the trading application using vega-market-sim. This README will guide you through setting up your environment and running the tests.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
|
||||
- [Docker](https://www.docker.com/)
|
||||
- [Python versions ">=3.9,<3.11"](https://www.python.org/)
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. **Install Poetry**: Follow the instructions on the [official Poetry website](https://python-poetry.org/docs/#installing-with-the-official-installer).
|
||||
2. **Install Docker**: Follow the instructions on the [official Docker website](https://docs.docker.com/desktop/).
|
||||
3. **Install Python**: Follow the instructions on the [official Python website](https://www.python.org/)
|
||||
**ensure you install a version between 3.9 and 3.11.**
|
||||
4. **Start up a Poetry environment**: Execute the commands below to configure the Poetry environment.
|
||||
|
||||
### Ensure you are in the tests folder before running commands
|
||||
|
||||
```bash
|
||||
poetry shell
|
||||
```
|
||||
|
||||
5. **Install python dependencies**
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
|
||||
6. **Install Playwright Browsers**: Execute the command below to browsers for Playwright.
|
||||
|
||||
```bash
|
||||
playwright install chromium
|
||||
```
|
||||
|
||||
7. **Download necessary binaries**:
|
||||
Use the following command within your Python environment. The `--force` flag ensures the binaries are overwritten, and the `--version` specifies the desired version. e.g. `v0.73.4`
|
||||
|
||||
```bash
|
||||
python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
||||
```
|
||||
|
||||
8. **Pull the desired Docker image**
|
||||
|
||||
```bash
|
||||
docker pull vegaprotocol/trading:develop
|
||||
```
|
||||
|
||||
9. **Run tests**: Poetry/Python will serve the app from docker
|
||||
|
||||
### Update the .env file with the correct trading image.
|
||||
|
||||
```bash
|
||||
poetry run pytest
|
||||
```
|
||||
|
||||
### Docker images
|
||||
|
||||
Pull the desired image:
|
||||
|
||||
**Testnet**
|
||||
|
||||
```bash
|
||||
docker pull vegaprotocol/trading:develop
|
||||
```
|
||||
|
||||
**Mainnet**
|
||||
|
||||
```bash
|
||||
docker pull vegaprotocol/trading:main
|
||||
```
|
||||
|
||||
Find all available images on [Docker Hub](https://hub.docker.com/r/vegaprotocol/trading/tags).
|
||||
|
||||
#### Create a Docker Image of Your Locally Built Trading App
|
||||
|
||||
To build your Docker image, use the following commands:
|
||||
|
||||
```bash
|
||||
yarn nx build trading ./docker/prepare-dist.sh
|
||||
```
|
||||
|
||||
```bash
|
||||
docker build -f docker/node-outside-docker.Dockerfile --build-arg APP=trading --build-arg ENV_NAME=stagnet1 -t vegaprotocol/trading:latest .
|
||||
```
|
||||
|
||||
## Running Tests 🧪
|
||||
|
||||
Before running make sure the docker daemon is runnign so that the app can be served.
|
||||
|
||||
To run a specific test, use the `-k` option followed by the name of the test.
|
||||
|
||||
Run all tests:
|
||||
|
||||
```bash
|
||||
poetry run pytest
|
||||
```
|
||||
|
||||
Run a targeted test:
|
||||
|
||||
```bash
|
||||
poetry run pytest -k "test_name" -s
|
||||
```
|
||||
|
||||
Run from anywhere:
|
||||
|
||||
```bash
|
||||
yarn trading:test -- "test_name" -s
|
||||
```
|
||||
|
||||
## Running Tests in Parallel 🔢
|
||||
|
||||
To run tests in parallel, use the `--numprocesses auto` option. The `--dist loadfile` setting ensures that multiple runners are not assigned to a single test file.
|
||||
|
||||
### From within the e2e folder:
|
||||
|
||||
```bash
|
||||
poetry run pytest -s --numprocesses auto --dist loadfile
|
||||
```
|
||||
|
||||
### From anywhere:
|
||||
|
||||
```bash
|
||||
yarn trading:test:all
|
||||
```
|
||||
|
||||
# Things to know
|
||||
|
||||
If you "intellisense" isn't working follow these steps:
|
||||
|
||||
1. ```bash
|
||||
poetry run which python
|
||||
```
|
||||
|
||||
2. Then open the command menu in vscode (cmd + shift + p) and type `select interpreter` , press enter, select enter interpreter path press enter then paste in the output from that above command you should get the right python again
|
38
apps/trading/e2e/actions/utils.py
Normal file
38
apps/trading/e2e/actions/utils.py
Normal file
@ -0,0 +1,38 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from playwright.sync_api import Page
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from typing import Optional
|
||||
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
ASSET_NAME = "tDAI"
|
||||
|
||||
def wait_for_toast_confirmation(page: Page, timeout: int = 30000):
|
||||
page.wait_for_function("""
|
||||
document.querySelector('[data-testid="toast-content"]') &&
|
||||
document.querySelector('[data-testid="toast-content"]').innerText.includes('AWAITING CONFIRMATION')
|
||||
""", timeout=timeout)
|
||||
|
||||
def create_and_faucet_wallet(
|
||||
vega: VegaServiceNull,
|
||||
wallet: WalletConfig,
|
||||
symbol: Optional[str] = None,
|
||||
amount: float = 1e4,
|
||||
|
||||
):
|
||||
asset_id = vega.find_asset_id(symbol=symbol if symbol is not None else ASSET_NAME)
|
||||
vega.create_key(wallet.name)
|
||||
vega.mint(wallet.name, asset_id, amount)
|
||||
|
||||
def next_epoch(vega: VegaServiceNull):
|
||||
forwards = 0
|
||||
epoch_seq = vega.statistics().epoch_seq
|
||||
while epoch_seq == vega.statistics().epoch_seq:
|
||||
vega.wait_fn(1)
|
||||
forwards += 1
|
||||
if forwards > 2 * 10 * 60:
|
||||
raise Exception(
|
||||
"Epoch not started after forwarding the duration of two epochs."
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
65
apps/trading/e2e/actions/vega.py
Normal file
65
apps/trading/e2e/actions/vega.py
Normal file
@ -0,0 +1,65 @@
|
||||
from typing import List, Tuple, Optional
|
||||
from vega_sim.service import VegaService, PeggedOrder
|
||||
|
||||
def submit_order(
|
||||
vega: VegaService,
|
||||
wallet_name: str,
|
||||
market_id: str,
|
||||
side: str,
|
||||
volume: float,
|
||||
price: float,
|
||||
peak_size: Optional[float] = None,
|
||||
minimum_visible_size: Optional[float] = None,
|
||||
):
|
||||
return vega.submit_order(
|
||||
trading_key=wallet_name,
|
||||
market_id=market_id,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side=side,
|
||||
volume=volume,
|
||||
price=price,
|
||||
peak_size=peak_size,
|
||||
minimum_visible_size=minimum_visible_size,
|
||||
)
|
||||
|
||||
|
||||
def submit_multiple_orders(
|
||||
vega: VegaService,
|
||||
wallet_name: str,
|
||||
market_id: str,
|
||||
side: str,
|
||||
volume_price_pair: List[Tuple[float, float]],
|
||||
):
|
||||
for volume, price in volume_price_pair:
|
||||
submit_order(vega, wallet_name, market_id, side, volume, price)
|
||||
|
||||
|
||||
def submit_liquidity(vega: VegaService, wallet_name: str, market_id: str):
|
||||
vega.submit_simple_liquidity(
|
||||
key_name=wallet_name,
|
||||
market_id=market_id,
|
||||
commitment_amount=10000,
|
||||
fee=0.000,
|
||||
is_amendment=False,
|
||||
)
|
||||
vega.submit_order(
|
||||
market_id=market_id,
|
||||
trading_key=wallet_name,
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_MID", offset=1),
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
vega.submit_order(
|
||||
market_id=market_id,
|
||||
trading_key=wallet_name,
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_MID", offset=1),
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
9
apps/trading/e2e/config.py
Normal file
9
apps/trading/e2e/config.py
Normal file
@ -0,0 +1,9 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
console_image_name = os.getenv(
|
||||
"CONSOLE_IMAGE_NAME", default="vegaprotocol/trading:latest"
|
||||
)
|
||||
vega_version = os.getenv("VEGA_VERSION", default="latest")
|
243
apps/trading/e2e/conftest.py
Normal file
243
apps/trading/e2e/conftest.py
Normal file
@ -0,0 +1,243 @@
|
||||
import logging
|
||||
import pytest
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
import time
|
||||
import docker
|
||||
import http.server
|
||||
import socketserver
|
||||
from threading import Thread
|
||||
|
||||
|
||||
from contextlib import contextmanager
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from playwright.sync_api import Browser, Page
|
||||
from config import console_image_name, vega_version
|
||||
from fixtures.market import (
|
||||
setup_simple_market,
|
||||
setup_opening_auction_market,
|
||||
setup_continuous_market,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
# Workaround for current xdist issue with displaying live logs from multiple workers
|
||||
# https://github.com/pytest-dev/pytest-xdist/issues/402
|
||||
sys.stdout = sys.stderr
|
||||
|
||||
docker_client = docker.from_env()
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
outcome = "passed" if call.excinfo is None else "failed"
|
||||
item.config.cache.set(item.nodeid, outcome)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
worker_id = os.environ.get("PYTEST_XDIST_WORKER")
|
||||
if worker_id is not None:
|
||||
log_dir = os.path.join(os.getcwd(), "logs")
|
||||
log_name = f"tests_{worker_id}.log"
|
||||
if not os.path.exists(log_dir):
|
||||
os.makedirs(log_dir)
|
||||
logging.basicConfig(
|
||||
format=config.getini("log_file_format"),
|
||||
datefmt=config.getini("log_file_date_format"),
|
||||
filename=os.path.join(log_dir, log_name),
|
||||
level=config.getini("log_file_level"),
|
||||
)
|
||||
|
||||
class CustomHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
# Set the path to your website's directory here
|
||||
if self.path == '/':
|
||||
self.path = 'dist/apps/trading/exported/index.html'
|
||||
return http.server.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
# Start VegaServiceNull
|
||||
@contextmanager
|
||||
def init_vega(request=None):
|
||||
default_seconds = 1
|
||||
seconds_per_block = default_seconds
|
||||
if request and hasattr(request, "param"):
|
||||
seconds_per_block = request.param
|
||||
|
||||
logger.info(
|
||||
"Starting VegaServiceNull",
|
||||
extra={"worker_id": os.environ.get("PYTEST_XDIST_WORKER")},
|
||||
)
|
||||
logger.info(f"Using console image: {console_image_name}")
|
||||
logger.info(f"Using vega version: {vega_version}")
|
||||
with VegaServiceNull(
|
||||
run_with_console=False,
|
||||
launch_graphql=False,
|
||||
retain_log_files=True,
|
||||
use_full_vega_wallet=True,
|
||||
store_transactions=True,
|
||||
transactions_per_block=1000,
|
||||
seconds_per_block=seconds_per_block,
|
||||
) as vega:
|
||||
try:
|
||||
container = docker_client.containers.run(
|
||||
console_image_name, detach=True, ports={"80/tcp": vega.console_port}
|
||||
)
|
||||
# docker setup
|
||||
logger.info(
|
||||
f"Container {container.id} started",
|
||||
extra={"worker_id": os.environ.get("PYTEST_XDIST_WORKER")},
|
||||
)
|
||||
yield vega
|
||||
except docker.errors.APIError as e:
|
||||
logger.info(f"Container creation failed.")
|
||||
logger.info(e)
|
||||
raise e
|
||||
finally:
|
||||
logger.info(f"Stopping container {container.id}")
|
||||
container.stop()
|
||||
# Remove the container
|
||||
logger.info(f"Removing container {container.id}")
|
||||
container.remove()
|
||||
|
||||
@contextmanager
|
||||
def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRequest):
|
||||
with browser.new_context(
|
||||
viewport={"width": 1920, "height": 1080},
|
||||
base_url=f"http://localhost:{vega.console_port}",
|
||||
) as context, context.new_page() as page:
|
||||
context.tracing.start(screenshots=True, snapshots=True, sources=True)
|
||||
try:
|
||||
# Wait for the console to be up and running before any tests are run
|
||||
attempts = 0
|
||||
while attempts < 100:
|
||||
try:
|
||||
code = requests.get(
|
||||
f"http://localhost:{vega.console_port}/"
|
||||
).status_code
|
||||
if code == 200:
|
||||
break
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
attempts += 1
|
||||
if attempts < 100:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
else:
|
||||
raise e
|
||||
|
||||
# Set window._env_ so built app uses datanode from vega market sim
|
||||
env = json.dumps(
|
||||
{
|
||||
"VEGA_URL": f"http://localhost:{vega.data_node_rest_port}/graphql",
|
||||
"VEGA_WALLET_URL": f"http://localhost:{vega.wallet_port}",
|
||||
}
|
||||
)
|
||||
window_env = f"window._env_ = Object.assign({{}}, window._env_, {env})"
|
||||
page.add_init_script(script=window_env)
|
||||
yield page
|
||||
finally:
|
||||
if not os.path.exists("traces"):
|
||||
os.makedirs("traces")
|
||||
|
||||
# Check whether this test failed or passed
|
||||
outcome = request.config.cache.get(request.node.nodeid, None)
|
||||
if outcome != "passed":
|
||||
try:
|
||||
trace_path = os.path.join("traces", request.node.name + "trace.zip")
|
||||
context.tracing.stop(path=trace_path)
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to save trace: {e}")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
# Set auth token so eager connection for MarketSim wallet is successful
|
||||
def auth_setup(vega: VegaServiceNull, page: Page):
|
||||
DEFAULT_WALLET_NAME = "MarketSim" # This is the default wallet name within VegaServiceNull and CANNOT be changed
|
||||
|
||||
# Calling get_keypairs will internally call _load_tokens for the given wallet
|
||||
keypairs = vega.wallet.get_keypairs(DEFAULT_WALLET_NAME)
|
||||
wallet_api_token = vega.wallet.login_tokens[DEFAULT_WALLET_NAME]
|
||||
|
||||
# Set token to localStorage so eager connect hook picks it up and immediately connects
|
||||
wallet_config = json.dumps(
|
||||
{
|
||||
"token": f"VWT {wallet_api_token}",
|
||||
"connector": "jsonRpc",
|
||||
"url": f"http://localhost:{vega.wallet_port}",
|
||||
}
|
||||
)
|
||||
|
||||
storage_javascript = [
|
||||
# Store wallet config so eager connection is initiated
|
||||
f"localStorage.setItem('vega_wallet_config', '{wallet_config}');",
|
||||
# Ensure wallet ris dialog doesnt show, otherwise eager connect wont work
|
||||
"localStorage.setItem('vega_wallet_risk_accepted', 'true');",
|
||||
# Ensure initial risk dialog doesnt show
|
||||
"localStorage.setItem('vega_risk_accepted', 'true');",
|
||||
]
|
||||
script = "".join(storage_javascript)
|
||||
page.add_init_script(script)
|
||||
|
||||
return {
|
||||
"wallet": DEFAULT_WALLET_NAME,
|
||||
"wallet_api_token": wallet_api_token,
|
||||
"public_key": keypairs["Key 1"],
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def auth(vega: VegaServiceNull, page: Page):
|
||||
return auth_setup(vega, page)
|
||||
|
||||
|
||||
# Set 'risk accepted' flag, so that the risk dialog doesn't show up
|
||||
def risk_accepted_setup(page: Page):
|
||||
onboarding_config = json.dumps({"state": {"dismissed": True}, "version": 0})
|
||||
storage_javascript = [
|
||||
"localStorage.setItem('vega_risk_accepted', 'true');",
|
||||
f"localStorage.setItem('vega_onboarding', '{onboarding_config}');",
|
||||
"localStorage.setItem('vega_telemetry_approval', 'false');",
|
||||
"localStorage.setItem('vega_telemetry_viewed', 'true');",
|
||||
]
|
||||
script = "".join(storage_javascript)
|
||||
page.add_init_script(script)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def risk_accepted(page: Page):
|
||||
risk_accepted_setup(page)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def simple_market(vega, request):
|
||||
kwargs = {}
|
||||
if hasattr(request, "param"):
|
||||
kwargs.update(request.param)
|
||||
return setup_simple_market(vega, **kwargs)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def opening_auction_market(vega):
|
||||
return setup_opening_auction_market(vega)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def proposed_market(vega):
|
||||
return setup_simple_market(vega, approve_proposal=False)
|
156
apps/trading/e2e/fixtures/market.py
Normal file
156
apps/trading/e2e/fixtures/market.py
Normal file
@ -0,0 +1,156 @@
|
||||
from collections import namedtuple
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_multiple_orders, submit_order, submit_liquidity
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
mint_amount: float = 10e5
|
||||
market_name = "BTC:DAI_2023"
|
||||
|
||||
|
||||
def setup_simple_market(
|
||||
vega: VegaService,
|
||||
approve_proposal=True,
|
||||
custom_market_name=market_name,
|
||||
custom_asset_name="tDAI",
|
||||
custom_asset_symbol="tDAI",
|
||||
):
|
||||
for wallet in wallets:
|
||||
vega.create_key(wallet.name)
|
||||
|
||||
vega.mint(
|
||||
MM_WALLET.name,
|
||||
asset="VOTE",
|
||||
amount=mint_amount,
|
||||
)
|
||||
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="market.fee.factors.makerFee", new_value="0.1"
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.create_asset(
|
||||
MM_WALLET.name,
|
||||
name=custom_asset_name,
|
||||
symbol=custom_asset_symbol,
|
||||
decimals=5,
|
||||
max_faucet_amount=1e10,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
tdai_id = vega.find_asset_id(symbol=custom_asset_symbol)
|
||||
logger.info(f"Created asset: {custom_asset_symbol}")
|
||||
|
||||
vega.mint(
|
||||
"Key 1",
|
||||
asset=tdai_id,
|
||||
amount=mint_amount,
|
||||
)
|
||||
|
||||
vega.mint(
|
||||
MM_WALLET.name,
|
||||
asset=tdai_id,
|
||||
amount=mint_amount,
|
||||
)
|
||||
|
||||
vega.mint(
|
||||
MM_WALLET2.name,
|
||||
asset=tdai_id,
|
||||
amount=mint_amount,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
market_id = vega.create_simple_market(
|
||||
custom_market_name,
|
||||
proposal_key=MM_WALLET.name,
|
||||
settlement_asset_id=tdai_id,
|
||||
termination_key=TERMINATE_WALLET.name,
|
||||
market_decimals=5,
|
||||
approve_proposal=approve_proposal,
|
||||
forward_time_to_enactment=approve_proposal,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return market_id
|
||||
|
||||
|
||||
def setup_simple_successor_market(
|
||||
vega: VegaService, parent_market_id, tdai_id, market_name, approve_proposal=True
|
||||
):
|
||||
market_id = vega.create_simple_market(
|
||||
market_name,
|
||||
proposal_key=MM_WALLET.name,
|
||||
settlement_asset_id=tdai_id,
|
||||
termination_key=MM_WALLET2.name,
|
||||
market_decimals=5,
|
||||
approve_proposal=approve_proposal,
|
||||
forward_time_to_enactment=approve_proposal,
|
||||
parent_market_id=parent_market_id,
|
||||
parent_market_insurance_pool_fraction=0.5,
|
||||
)
|
||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET.name, market_id, "SIDE_SELL", [[1, 110], [1, 105]]
|
||||
)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET2.name, market_id, "SIDE_BUY", [[1, 90], [1, 95]]
|
||||
)
|
||||
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 1, 110)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return market_id
|
||||
|
||||
|
||||
def setup_opening_auction_market(vega: VegaService, market_id: str = None, **kwargs):
|
||||
if market_id is None or market_id not in vega.all_markets():
|
||||
market_id = setup_simple_market(vega, **kwargs)
|
||||
|
||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET.name, market_id, "SIDE_SELL", [[1, 110], [1, 105]]
|
||||
)
|
||||
submit_multiple_orders(
|
||||
vega, MM_WALLET2.name, market_id, "SIDE_BUY", [[1, 90], [1, 95]]
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return market_id
|
||||
|
||||
|
||||
def setup_continuous_market(vega: VegaService, market_id: str = None, **kwargs):
|
||||
if market_id is None or market_id not in vega.all_markets():
|
||||
market_id = setup_opening_auction_market(vega, **kwargs)
|
||||
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 1, 110)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return market_id
|
1345
apps/trading/e2e/poetry.lock
generated
Normal file
1345
apps/trading/e2e/poetry.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
29
apps/trading/e2e/pyproject.toml
Normal file
29
apps/trading/e2e/pyproject.toml
Normal file
@ -0,0 +1,29 @@
|
||||
[tool.poetry]
|
||||
name = "trading market-sim e2e"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Matthew Russell <mattrussell36@gmail.com>"]
|
||||
readme = "README.md"
|
||||
packages = [{include = "trading market-sim e2e"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<3.11"
|
||||
psutil = "^5.9.5"
|
||||
vega-sim = {git = "https://github.com/vegaprotocol/vega-market-sim.git"}
|
||||
pytest-playwright = "^0.4.2"
|
||||
docker = "^6.1.3"
|
||||
pytest-xdist = "^3.3.1"
|
||||
python-dotenv = "^1.0.0"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
log_cli = true
|
||||
log_cli_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
|
||||
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
|
||||
log_cli_level = "INFO"
|
||||
log_file_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
|
||||
log_file_date_format = "%Y-%m-%d %H:%M:%S"
|
||||
log_file_level = "INFO"
|
95
apps/trading/e2e/tests/assets/test_assets.py
Normal file
95
apps/trading/e2e/tests/assets/test_assets.py
Normal file
@ -0,0 +1,95 @@
|
||||
import pytest
|
||||
import re
|
||||
from playwright.sync_api import expect, Page
|
||||
|
||||
label_value_tooltip_pairs = [
|
||||
{
|
||||
"label": "ID",
|
||||
"value": "asset-id",
|
||||
},
|
||||
{
|
||||
"label": "Type",
|
||||
"value": "Builtin asset",
|
||||
"valueToolTip": "A Vega builtin asset",
|
||||
},
|
||||
{
|
||||
"label": "Name",
|
||||
"value": "tDAI",
|
||||
},
|
||||
{
|
||||
"label": "Symbol",
|
||||
"value": "tDAI",
|
||||
},
|
||||
{
|
||||
"label": "Decimals",
|
||||
"value": "5",
|
||||
"labelTooltip": "Number of decimal / precision handled by this asset",
|
||||
},
|
||||
{
|
||||
"label": "Quantum",
|
||||
"value": "0.00001",
|
||||
"labelTooltip": "The minimum economically meaningful amount of the asset",
|
||||
},
|
||||
{
|
||||
"label": "Status",
|
||||
"value": "Enabled",
|
||||
"labelTooltip": "The status of the asset in the Vega network",
|
||||
"valueToolTip": "Asset can be used on the Vega network",
|
||||
},
|
||||
{
|
||||
"label": "Max faucet amount",
|
||||
"value": "10,000,000,000.00",
|
||||
"labelTooltip": "Maximum amount that can be requested by a party through the built-in asset faucet at a time",
|
||||
},
|
||||
{
|
||||
"label": "Infrastructure fee account balance",
|
||||
"value": "0.00",
|
||||
"labelTooltip": "The infrastructure fee account in this asset",
|
||||
},
|
||||
{
|
||||
"label": "Global reward pool account balance",
|
||||
"value": "0.00",
|
||||
"labelTooltip": "The global rewards acquired in this asset",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def tooltip(page: Page, index: int, test_id: str, tooltip: str):
|
||||
page.locator(f"data-testid={index}_{test_id}").hover()
|
||||
expect(page.locator('[role="tooltip"]').locator("div")).to_have_text(tooltip)
|
||||
page.get_by_test_id("dialog-title").click()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_asset_details(page: Page):
|
||||
page.goto("/#/portfolio")
|
||||
page.locator('[data-testid="tab-collateral"] >> text=tDAI').click()
|
||||
|
||||
for index, pair in enumerate(label_value_tooltip_pairs):
|
||||
if index in [7, 8, 9]: # Skip indices 7, 8, and 9.
|
||||
continue
|
||||
|
||||
label = pair.get("label", "")
|
||||
value = pair.get("value", "")
|
||||
label_tooltip = pair.get("labelTooltip", "")
|
||||
value_tooltip = pair.get("valueToolTip", "")
|
||||
|
||||
if label == "ID":
|
||||
expect(page.get_by_role("button", name="Copy id to clipboard")).to_be_visible()
|
||||
asset_id_text = page.locator(f"[data-testid='{index}_value']").inner_text()
|
||||
pattern = r"^[0-9a-f]{6}\u2026[0-9a-f]{4}"
|
||||
|
||||
assert re.match(pattern, asset_id_text), f"Expected ID to match pattern but got {asset_id_text}"
|
||||
|
||||
else:
|
||||
expect(page.locator(f"[data-testid='{index}_label']")).to_have_text(label)
|
||||
expect(page.locator(f"[data-testid='{index}_value']")).to_have_text(value)
|
||||
|
||||
if label_tooltip:
|
||||
tooltip(page, index, "label", label_tooltip)
|
||||
|
||||
if value_tooltip:
|
||||
tooltip(page, index, "value", value_tooltip)
|
||||
|
||||
page.get_by_test_id("dialog-close").click()
|
||||
assert not page.query_selector("dialog-content")
|
13
apps/trading/e2e/tests/chart_depth/test_chart_depth.py
Normal file
13
apps/trading/e2e/tests/chart_depth/test_chart_depth.py
Normal file
@ -0,0 +1,13 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "risk_accepted")
|
||||
def test_see_market_depth_chart(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
# Click on the 'Depth' tab
|
||||
page.get_by_test_id("Depth").click()
|
||||
# Check if the 'Depth' tab and the depth chart are visible
|
||||
# 6006-DEPC-001
|
||||
expect(page.get_by_test_id("tab-depth")).to_be_visible()
|
||||
expect(page.locator('[class^="depth-chart-module_canvas__"]').first).to_be_visible()
|
142
apps/trading/e2e/tests/deal_ticket/test_basic_submit.py
Normal file
142
apps/trading/e2e/tests/deal_ticket/test_basic_submit.py
Normal file
@ -0,0 +1,142 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from datetime import datetime, timedelta
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
order_size = "order-size"
|
||||
order_price = "order-price"
|
||||
place_order = "place-order"
|
||||
order_side_sell = "order-side-SIDE_SELL"
|
||||
market_order = "order-type-Market"
|
||||
tif = "order-tif"
|
||||
expire = "expire"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_limit_buy_order_GTT(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(order_size).fill("10")
|
||||
page.get_by_test_id(order_price).fill("120")
|
||||
page.get_by_test_id(tif).select_option("Good 'til Time (GTT)")
|
||||
expires_at = datetime.now() + timedelta(days=1)
|
||||
expires_at_input_value = expires_at.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
page.get_by_test_id("date-picker-field").fill(expires_at_input_value)
|
||||
# 7002-SORD-011
|
||||
expect(page.get_by_test_id("place-order").locator("span").first).to_have_text(
|
||||
"Place limit order"
|
||||
)
|
||||
expect(page.get_by_test_id("place-order").locator("span").last).to_have_text(
|
||||
"10 BTC @ 120.00 BTC"
|
||||
)
|
||||
page.get_by_test_id(place_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("All").click()
|
||||
# 7002-SORD-017
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr10+10LimitFilled120.00GTT:"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_limit_buy_order(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
|
||||
page.get_by_test_id(order_size).fill("10")
|
||||
page.get_by_test_id(order_price).fill("120")
|
||||
page.get_by_test_id(place_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("All").click()
|
||||
# 7002-SORD-017
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr10+10LimitFilled120.00GTC"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_limit_sell_order(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(order_size).fill("10")
|
||||
page.get_by_test_id(order_price).fill("100")
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(tif).select_option("Good for Normal (GFN)")
|
||||
# 7002-SORD-011
|
||||
expect(page.get_by_test_id("place-order").locator("span").first).to_have_text(
|
||||
"Place limit order"
|
||||
)
|
||||
expect(page.get_by_test_id("place-order").locator("span").last).to_have_text(
|
||||
"10 BTC @ 100.00 BTC"
|
||||
)
|
||||
page.get_by_test_id(place_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("All").click()
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr10-10LimitFilled100.00GFN"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_market_sell_order(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(market_order).click()
|
||||
page.get_by_test_id(order_size).fill("10")
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
# 7002-SORD-011
|
||||
expect(page.get_by_test_id("place-order").locator("span").first).to_have_text(
|
||||
"Place market order"
|
||||
)
|
||||
expect(page.get_by_test_id("place-order").locator("span").last).to_have_text(
|
||||
"10 BTC @ market"
|
||||
)
|
||||
page.get_by_test_id(place_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id("All").click()
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr10-10MarketFilled-IOC"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_market_buy_order(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(market_order).click()
|
||||
page.get_by_test_id(order_size).fill("10")
|
||||
page.get_by_test_id(tif).select_option("Fill or Kill (FOK)")
|
||||
page.get_by_test_id(place_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("All").click()
|
||||
# 7002-SORD-010
|
||||
# 0003-WTXN-012
|
||||
# 0003-WTXN-003
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr10+10MarketFilled-FOK"
|
||||
)
|
@ -0,0 +1,35 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.skip("We currently can't approve wallet connection through Sim")
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_connect_vega_wallet(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("order-price").fill("101")
|
||||
page.get_by_test_id("order-connect-wallet").click()
|
||||
expect(page.locator('[role="dialog"]')).to_be_visible()
|
||||
page.get_by_test_id("connector-jsonRpc").click()
|
||||
expect(page.get_by_test_id("wallet-dialog-title")).to_be_visible()
|
||||
# TODO: accept wallet connection and assert wallet is connected.
|
||||
expect(page.get_by_test_id("order-type-Limit")).to_be_checked()
|
||||
expect(page.get_by_test_id("order-price")).to_have_value("101")
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_sidebar_should_be_open_after_reload(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
|
||||
page.get_by_test_id("Order").click()
|
||||
expect(page.get_by_test_id("deal-ticket-form")).not_to_be_visible()
|
||||
page.reload()
|
||||
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
|
@ -0,0 +1,96 @@
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
|
||||
notional = "deal-ticket-fee-notional"
|
||||
fees = "deal-ticket-fee-fees"
|
||||
margin_required = "deal-ticket-fee-margin-required"
|
||||
item_value = "item-value"
|
||||
market_trading_mode = "market-trading-mode"
|
||||
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_margin_and_fees_estimations(continuous_market, vega: VegaService, page: Page):
|
||||
# setup continuous trading market with one user buy trade
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
|
||||
# submit order from UI and verify fees and margin
|
||||
expect(page.get_by_test_id(notional)).to_have_text("Notional- BTC")
|
||||
expect(page.get_by_test_id(fees)).to_have_text("Fees- tDAI")
|
||||
expect(page.get_by_test_id(margin_required)).to_have_text(
|
||||
"Margin required0.00 tDAI"
|
||||
)
|
||||
page.get_by_test_id("order-size").type("200")
|
||||
page.get_by_test_id("order-price").type("20")
|
||||
|
||||
expect(page.get_by_test_id(notional)).to_have_text("Notional4,000.00 BTC")
|
||||
expect(page.get_by_test_id(fees)).to_have_text("Fees~402.00 tDAI")
|
||||
expect(page.get_by_test_id(margin_required)).to_have_text(
|
||||
"Margin required1,661.88832 tDAI"
|
||||
)
|
||||
|
||||
page.get_by_test_id("place-order").click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id(margin_required)).to_have_text(
|
||||
"Margin required1,661.88832 tDAI "
|
||||
)
|
||||
page.get_by_test_id("toast-close").click()
|
||||
|
||||
# submit order by sim function
|
||||
order = submit_order(vega, "Key 1", market_id, "SIDE_BUY", 400, 38329483272398.838)
|
||||
vega.forward("20s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id(margin_required)).to_have_text(
|
||||
"Margin required897,716,007,278,798.50 tDAI "
|
||||
)
|
||||
expect(page.get_by_test_id("deal-ticket-warning-margin")).to_contain_text(
|
||||
"You may not have enough margin available to open this position."
|
||||
)
|
||||
|
||||
# cancel order and verify that warning margin disappeared
|
||||
vega.cancel_order("Key 1", market_id, order)
|
||||
vega.forward("20s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id("deal-ticket-warning-auction")).to_contain_text(
|
||||
"Any orders placed now will not trade until the auction ends"
|
||||
)
|
||||
|
||||
# add order at the current price so that it is possible to change the status to price monitoring
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_SELL", 1, 110)
|
||||
vega.forward("20s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
page.reload()
|
||||
expect(page.get_by_test_id(margin_required)).to_have_text(
|
||||
"Margin required1,700.53688 tDAI"
|
||||
)
|
||||
expect(
|
||||
page.get_by_test_id(market_trading_mode).get_by_test_id(item_value)
|
||||
).to_have_text("Continuous")
|
||||
|
||||
# verify if we can submit order after reverted margin
|
||||
page.get_by_test_id("place-order").click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
# skip temporary
|
||||
# expect(page.get_by_test_id("toast-content")).to_contain_text(
|
||||
# "Your transaction has been confirmed"
|
||||
# )
|
416
apps/trading/e2e/tests/deal_ticket/test_stop_order.py
Normal file
416
apps/trading/e2e/tests/deal_ticket/test_stop_order.py
Normal file
@ -0,0 +1,416 @@
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from datetime import datetime, timedelta
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
stop_order_btn = "order-type-Stop"
|
||||
stop_limit_order_btn = "order-type-StopLimit"
|
||||
stop_market_order_btn = "order-type-StopMarket"
|
||||
order_side_sell = "order-side-SIDE_SELL"
|
||||
trigger_above = "triggerDirection-risesAbove"
|
||||
trigger_below = "triggerDirection-fallsBelow"
|
||||
trigger_price = "triggerPrice"
|
||||
trigger_type_price = "triggerType-price"
|
||||
trigger_type_trailing_percent_offset = "triggerType-trailingPercentOffset"
|
||||
order_size = "order-size"
|
||||
order_price = "order-price"
|
||||
order_tif = "order-tif"
|
||||
expire = "expire"
|
||||
expiry_strategy = '[for="expiryStrategy"]'
|
||||
expiry_strategy_submit = "expiryStrategy-submit"
|
||||
expiry_strategy_cancel = "expiryStrategy-cancel"
|
||||
date_picker_field = "date-picker-field"
|
||||
submit_stop_order = "place-order"
|
||||
stop_orders_tab = "Stop orders"
|
||||
row_table = "row"
|
||||
cancel = "cancel"
|
||||
market_name_col = '[col-id="market.tradableInstrument.instrument.code"]'
|
||||
trigger_col = '[col-id="trigger"]'
|
||||
expiresAt_col = '[col-id="expiresAt"]'
|
||||
size_col = '[col-id="submission.size"]'
|
||||
submission_type = '[col-id="submission.type"]'
|
||||
status_col = '[col-id="status"]'
|
||||
price_col = '[col-id="submission.price"]'
|
||||
timeInForce_col = '[col-id="submission.timeInForce"]'
|
||||
updatedAt_col = '[col-id="updatedAt"]'
|
||||
close_toast = "toast-close"
|
||||
|
||||
|
||||
def wait_for_graphql_response(page, query_name, timeout=5000):
|
||||
response_data = {}
|
||||
|
||||
def handle_response(route, request):
|
||||
if "graphql" in request.url:
|
||||
response = request.response()
|
||||
if response is not None:
|
||||
json_response = response.json()
|
||||
if json_response and "data" in json_response:
|
||||
data = json_response["data"]
|
||||
if query_name in data:
|
||||
response_data["data"] = data
|
||||
route.continue_()
|
||||
return
|
||||
route.continue_()
|
||||
|
||||
# Register the route handler
|
||||
page.route("**", handle_response)
|
||||
|
||||
# Wait for the response data to be populated
|
||||
page.wait_for_timeout(timeout)
|
||||
|
||||
# Unregister the route handler
|
||||
page.unroute("**", handle_response)
|
||||
|
||||
|
||||
def create_position(vega: VegaService, market_id):
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_SELL", 100, 110)
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 100, 110)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_stop_order_form_error_validation(continuous_market, page: Page):
|
||||
# 7002-SORD-032
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
expect(page.get_by_test_id("stop-order-error-message-trigger-price")).to_have_text(
|
||||
"You need provide a price"
|
||||
)
|
||||
expect(page.get_by_test_id("stop-order-error-message-size")).to_have_text(
|
||||
"Size cannot be lower than 1"
|
||||
)
|
||||
|
||||
page.get_by_test_id(order_size).fill("1")
|
||||
page.get_by_test_id(order_price).fill("0.0000001")
|
||||
expect(page.get_by_test_id("stop-order-error-message-price")).to_have_text(
|
||||
"Price cannot be lower than 0.00001"
|
||||
)
|
||||
|
||||
@pytest.mark.skip("core issue")
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_order_rejected(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(trigger_price).fill("103")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(1)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(trigger_col)).nth(1)).to_have_text(
|
||||
"Mark > 103.00"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(1)).to_have_text("")
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(1)).to_have_text("+3")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(1)).to_have_text(
|
||||
"Rejected"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(1)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(1)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(1)
|
||||
).not_to_be_empty()
|
||||
|
||||
@pytest.mark.skip("core issue")
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_market_order_triggered(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
# 7002-SORD-071
|
||||
# 7002-SORD-074
|
||||
# 7002-SORD-075
|
||||
# 7002-SORD-067
|
||||
# 7002-SORD-068
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
# create a position because stop order is reduce only type
|
||||
create_position(vega, continuous_market)
|
||||
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(trigger_price).fill("103")
|
||||
page.get_by_test_id(order_size).fill("1")
|
||||
page.get_by_test_id(expire).click()
|
||||
expires_at = datetime.now() + timedelta(days=1)
|
||||
expires_at_input_value = expires_at.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
page.get_by_test_id("date-picker-field").fill(expires_at_input_value)
|
||||
page.get_by_test_id(expiry_strategy_cancel).click()
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.wait_for_selector('[data-testid="toast-close"]', state="visible")
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(1)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(trigger_col)).nth(1)).to_have_text(
|
||||
"Mark > 103.00"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(1)).to_contain_text(
|
||||
"Cancels"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(1)).to_have_text("-1")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(1)).to_have_text(
|
||||
"Triggered"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(1)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(1)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(1)
|
||||
).not_to_be_empty()
|
||||
|
||||
@pytest.mark.skip("core issue")
|
||||
@pytest.mark.usefixtures("continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_limit_order_pending(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
# 7002-SORD-071
|
||||
# 7002-SORD-074
|
||||
# 7002-SORD-075
|
||||
# 7002-SORD-069
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
# create a position because stop order is reduce only type
|
||||
create_position(vega, continuous_market)
|
||||
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(trigger_below).click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_price).fill("99")
|
||||
page.get_by_test_id(order_size).fill("1")
|
||||
page.get_by_test_id("order-tif").select_option("TIME_IN_FORCE_IOC")
|
||||
page.get_by_test_id(expire).click()
|
||||
expires_at = datetime.now() + timedelta(days=1)
|
||||
expires_at_input_value = expires_at.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
page.get_by_test_id("date-picker-field").fill(expires_at_input_value)
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.wait_for_selector('[data-testid="toast-close"]', state="visible")
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(1)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(trigger_col)).nth(1)).to_have_text(
|
||||
"Mark < 102.00"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(1)).to_contain_text(
|
||||
"Submit"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(1)).to_have_text("-1")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Limit"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(1)).to_have_text(
|
||||
"Pending"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(1)).to_have_text(
|
||||
"99.00"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(1)).to_have_text(
|
||||
"IOC"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(1)
|
||||
).not_to_be_empty()
|
||||
|
||||
@pytest.mark.skip("core issue")
|
||||
@pytest.mark.usefixtures("continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_limit_order_cancel(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
# create a position because stop order is reduce only type
|
||||
create_position(vega, continuous_market)
|
||||
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(trigger_below).click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_price).fill("99")
|
||||
page.get_by_test_id(order_size).fill("1")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id(close_toast).first.click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(cancel).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id(close_toast).first.click()
|
||||
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator('[col-id="status"]')).nth(1)
|
||||
).to_have_text("Cancelled")
|
||||
|
||||
|
||||
class TestStopOcoValidation:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def continuous_market(self, vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_stop_market_order_form_validation(self, continuous_market, page: Page):
|
||||
# 7002-SORD-052
|
||||
# 7002-SORD-055
|
||||
# 7002-SORD-056
|
||||
# 7002-SORD-057
|
||||
# 7002-SORD-058
|
||||
# 7002-SORD-064
|
||||
# 7002-SORD-065
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
expect(
|
||||
page.get_by_test_id("sidebar-content").get_by_text("Trigger").first
|
||||
).to_be_visible()
|
||||
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_have_text(
|
||||
"Rises above"
|
||||
)
|
||||
expect(page.locator('[for="triggerDirection-fallsBelow"]')).to_have_text(
|
||||
"Falls below"
|
||||
)
|
||||
page.get_by_test_id(trigger_price).click()
|
||||
expect(page.get_by_test_id(trigger_price)).to_be_empty
|
||||
expect(page.locator('[for="triggerType-price"]')).to_have_text("Price")
|
||||
expect(page.locator('[for="triggerType-trailingPercentOffset"]')).to_have_text(
|
||||
"Trailing Percent Offset"
|
||||
)
|
||||
expect(page.locator('[for="order-size"]')).to_have_text("Size")
|
||||
page.get_by_test_id(order_size).click()
|
||||
expect(page.get_by_test_id(order_size)).to_be_empty
|
||||
expect(page.get_by_test_id(order_price)).not_to_be_visible()
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_stop_limit_order_form_validation(self, continuous_market, page: Page):
|
||||
# 7002-SORD-020
|
||||
# 7002-SORD-021
|
||||
# 7002-SORD-022
|
||||
# 7002-SORD-033
|
||||
# 7002-SORD-034
|
||||
# 7002-SORD-035
|
||||
# 7002-SORD-036
|
||||
# 7002-SORD-037
|
||||
# 7002-SORD-038
|
||||
# 7002-SORD-049
|
||||
# 7002-SORD-050
|
||||
# 7002-SORD-051
|
||||
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
expect(
|
||||
page.get_by_test_id("sidebar-content").get_by_text("Trigger").first
|
||||
).to_be_visible()
|
||||
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_have_text(
|
||||
"Rises above"
|
||||
)
|
||||
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_be_checked
|
||||
expect(page.locator('[for="triggerDirection-fallsBelow"]')).to_have_text(
|
||||
"Falls below"
|
||||
)
|
||||
page.get_by_test_id(trigger_price).click()
|
||||
expect(page.get_by_test_id(trigger_price)).to_be_empty
|
||||
expect(page.locator('[for="triggerType-price"]')).to_have_text("Price")
|
||||
expect(page.locator('[for="triggerType-price"]')).to_be_checked
|
||||
expect(page.locator('[for="triggerType-trailingPercentOffset"]')).to_have_text(
|
||||
"Trailing Percent Offset"
|
||||
)
|
||||
expect(page.locator('[for="order-size"]').first).to_have_text("Size")
|
||||
expect(page.locator('[for="order-price"]').last).to_have_text("Price")
|
||||
page.get_by_test_id(order_size).click()
|
||||
expect(page.get_by_test_id(order_size)).to_be_empty
|
||||
page.get_by_test_id(order_price).click()
|
||||
expect(page.get_by_test_id(order_price)).to_be_empty()
|
||||
|
||||
@pytest.mark.skip("core issue")
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_maximum_number_of_active_stop_orders(
|
||||
self, continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
# create a position because stop order is reduce only type
|
||||
create_position(vega, continuous_market)
|
||||
for i in range(4):
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.get_by_test_id(trigger_below).click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_price).fill("99")
|
||||
page.get_by_test_id(order_size).fill("1")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
if page.get_by_test_id(close_toast).is_visible():
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
# 7002-SORD-011
|
||||
expect(page.get_by_test_id("stop-order-warning-limit")).to_have_text(
|
||||
"There is a limit of 4 active stop orders per market. Orders submitted above the limit will be immediately rejected."
|
||||
)
|
498
apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py
Normal file
498
apps/trading/e2e/tests/deal_ticket/test_stop_order_oco.py
Normal file
@ -0,0 +1,498 @@
|
||||
from math import exp
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from conftest import init_vega, page
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
stop_order_btn = "order-type-Stop"
|
||||
stop_limit_order_btn = "order-type-StopLimit"
|
||||
stop_market_order_btn = "order-type-StopMarket"
|
||||
order_side_sell = "order-side-SIDE_SELL"
|
||||
trigger_above = "triggerDirection-risesAbove"
|
||||
trigger_below = "triggerDirection-fallsBelow"
|
||||
trigger_price = "triggerPrice"
|
||||
trigger_type_price = "triggerType-price"
|
||||
trigger_type_trailing_percent_offset = "triggerType-trailingPercentOffset"
|
||||
order_size = "order-size"
|
||||
order_price = "order-price"
|
||||
order_tif = "order-tif"
|
||||
expire = "expire"
|
||||
expiry_strategy = '[for="expiryStrategy"]'
|
||||
expiry_strategy_submit = "expiryStrategy-submit"
|
||||
expiry_strategy_cancel = "expiryStrategy-cancel"
|
||||
date_picker_field = "date-picker-field"
|
||||
submit_stop_order = "place-order"
|
||||
stop_orders_tab = "Stop orders"
|
||||
row_table = "row"
|
||||
cancel = "cancel"
|
||||
market_name_col = '[col-id="market.tradableInstrument.instrument.code"]'
|
||||
trigger_col = '[col-id="trigger"]'
|
||||
expiresAt_col = '[col-id="expiresAt"]'
|
||||
size_col = '[col-id="submission.size"]'
|
||||
submission_type = '[col-id="submission.type"]'
|
||||
status_col = '[col-id="status"]'
|
||||
price_col = '[col-id="submission.price"]'
|
||||
timeInForce_col = '[col-id="submission.timeInForce"]'
|
||||
updatedAt_col = '[col-id="updatedAt"]'
|
||||
close_toast = "toast-close"
|
||||
trigger_direction_fallsBelow_oco = "triggerDirection-fallsBelow-oco"
|
||||
trigger_direction_fallsAbove_oco = "triggerDirection-fallsAbove-oco"
|
||||
oco = "oco"
|
||||
trigger_price_oco = "triggerPrice-oco"
|
||||
order_size_oco = "order-size-oco"
|
||||
order_limit_price_oco = "order-price-oco"
|
||||
|
||||
|
||||
def wait_for_graphql_response(page, query_name, timeout=5000):
|
||||
response_data = {}
|
||||
|
||||
def handle_response(route, request):
|
||||
if "graphql" in request.url:
|
||||
response = request.response()
|
||||
if response is not None:
|
||||
json_response = response.json()
|
||||
if json_response and "data" in json_response:
|
||||
data = json_response["data"]
|
||||
if query_name in data:
|
||||
response_data["data"] = data
|
||||
route.continue_()
|
||||
return
|
||||
route.continue_()
|
||||
|
||||
# Register the route handler
|
||||
page.route("**", handle_response)
|
||||
|
||||
# Wait for the response data to be populated
|
||||
page.wait_for_timeout(timeout)
|
||||
|
||||
# Unregister the route handler
|
||||
page.unroute("**", handle_response)
|
||||
|
||||
|
||||
def create_position(vega: VegaService, market_id):
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_SELL", 100, 110)
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 100, 110)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_order_market_oco_rejected(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(trigger_price).fill("103")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
# 7002-SORD-098
|
||||
expect(
|
||||
page.get_by_test_id("stop-order-warning-message-trigger-price")
|
||||
).to_have_text("Stop order will be triggered immediately")
|
||||
|
||||
# 7002-SORD-082
|
||||
page.get_by_test_id(oco).click()
|
||||
# 7002-SORD-085
|
||||
expect(page.get_by_test_id(trigger_direction_fallsBelow_oco)).to_be_checked
|
||||
# 7002-SORD-086
|
||||
page.get_by_test_id(trigger_price_oco).fill("102")
|
||||
page.get_by_test_id(order_size_oco).fill("3")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(1)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(1)).to_have_text("")
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(1)).to_have_text("+3")
|
||||
# 7002-SORD-083
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(1)).to_have_text(
|
||||
"RejectedOCO"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(1)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(1)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(1)
|
||||
).not_to_be_empty()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(2)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(2)).to_have_text("")
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(2)).to_have_text("+3")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(2)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(2)).to_have_text(
|
||||
"RejectedOCO"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(2)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(2)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(2)
|
||||
).not_to_be_empty()
|
||||
# 7002-SORD-084
|
||||
trigger_price_list = (
|
||||
page.locator(".ag-center-cols-container").locator(trigger_col).all_inner_texts()
|
||||
)
|
||||
trigger_value_list = ["Mark < 102.00", "Mark > 103.00"]
|
||||
assert trigger_price_list.sort() == trigger_value_list.sort()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_oco_market_order_triggered(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
create_position(vega, market_id)
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(trigger_price).fill("103")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
|
||||
expect(
|
||||
page.get_by_test_id("stop-order-warning-message-trigger-price")
|
||||
).to_have_text("Stop order will be triggered immediately")
|
||||
|
||||
page.get_by_test_id(oco).click()
|
||||
expect(page.get_by_test_id(trigger_direction_fallsBelow_oco)).to_be_checked
|
||||
|
||||
page.get_by_test_id(trigger_price_oco).fill("102")
|
||||
page.get_by_test_id(order_size_oco).fill("3")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(1)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(1)).to_have_text("")
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(1)).to_have_text("+3")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(1)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(1)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(1)
|
||||
).not_to_be_empty()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(market_name_col)).nth(2)).to_have_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(expiresAt_col)).nth(2)).to_have_text("")
|
||||
expect((page.get_by_role(row_table).locator(size_col)).nth(2)).to_have_text("+3")
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(2)).to_have_text(
|
||||
"Market"
|
||||
)
|
||||
|
||||
expect((page.get_by_role(row_table).locator(price_col)).nth(2)).to_have_text("-")
|
||||
expect((page.get_by_role(row_table).locator(timeInForce_col)).nth(2)).to_have_text(
|
||||
"FOK"
|
||||
)
|
||||
expect(
|
||||
(page.get_by_role(row_table).locator(updatedAt_col)).nth(2)
|
||||
).not_to_be_empty()
|
||||
|
||||
status = (
|
||||
page.locator(".ag-center-cols-container").locator(status_col).all_inner_texts()
|
||||
)
|
||||
value = ["StoppedOCO", "TriggeredOCO"]
|
||||
assert status.sort() == value.sort()
|
||||
|
||||
trigger_price_list = (
|
||||
page.locator(".ag-center-cols-container").locator(trigger_col).all_inner_texts()
|
||||
)
|
||||
trigger_value_list = ["Mark < 102.00", "Mark > 103.00"]
|
||||
assert trigger_price_list.sort() == trigger_value_list.sort()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_oco_market_order_pending(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
create_position(vega, market_id)
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.locator("label").filter(has_text="Falls below").click()
|
||||
page.get_by_test_id(trigger_price).fill("99")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
page.get_by_test_id(oco).click()
|
||||
expect(page.get_by_test_id(trigger_direction_fallsAbove_oco)).to_be_checked
|
||||
page.get_by_test_id(trigger_price_oco).fill("120")
|
||||
page.get_by_test_id(order_size_oco).fill("2")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(1)).to_have_text(
|
||||
"PendingOCO"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(status_col)).nth(2)).to_have_text(
|
||||
"PendingOCO"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_oco_limit_order_pending(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
create_position(vega, market_id)
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.locator("label").filter(has_text="Falls below").click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
page.get_by_test_id(order_price).fill("103")
|
||||
page.get_by_test_id(oco).click()
|
||||
# 7002-SORD-090
|
||||
expect(page.get_by_test_id(trigger_direction_fallsAbove_oco)).to_be_checked
|
||||
page.get_by_test_id(trigger_price_oco).fill("120")
|
||||
page.get_by_test_id(order_size_oco).fill("2")
|
||||
# 7002-SORD-089
|
||||
page.get_by_test_id(order_limit_price_oco).fill("99")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_role(row_table).locator(market_name_col).nth(1).is_visible()
|
||||
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(1)).to_have_text(
|
||||
"Limit"
|
||||
)
|
||||
expect((page.get_by_role(row_table).locator(submission_type)).nth(2)).to_have_text(
|
||||
"Limit"
|
||||
)
|
||||
|
||||
price = (
|
||||
page.locator(".ag-center-cols-container").locator(price_col).all_inner_texts()
|
||||
)
|
||||
prices = ["103.00", "99.00"]
|
||||
assert price.sort() == prices.sort()
|
||||
|
||||
# 7002-SORD-091
|
||||
trigger_price_list = (
|
||||
page.locator(".ag-center-cols-container").locator(trigger_col).all_inner_texts()
|
||||
)
|
||||
trigger_value_list = ["Limit < 102.00", "Limit > 103.00"]
|
||||
assert trigger_price_list.sort() == trigger_value_list.sort()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "vega", "continuous_market", "auth", "risk_accepted")
|
||||
def test_submit_stop_oco_limit_order_cancel(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
create_position(vega, market_id)
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.locator("label").filter(has_text="Falls below").click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
page.get_by_test_id(order_price).fill("103")
|
||||
page.get_by_test_id(oco).click()
|
||||
# 7002-SORD-092
|
||||
expect(page.get_by_test_id(trigger_direction_fallsAbove_oco)).to_be_checked
|
||||
# 7002-SORD-094
|
||||
page.get_by_test_id(trigger_price_oco).fill("120")
|
||||
page.get_by_test_id(order_size_oco).fill("2")
|
||||
# 7002-SORD-093
|
||||
page.get_by_test_id(order_limit_price_oco).fill("99")
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(cancel).first.click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id(close_toast).first.click()
|
||||
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container").locator('[col-id="status"]').first
|
||||
).to_have_text("CancelledOCO")
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container").locator('[col-id="status"]').last
|
||||
).to_have_text("CancelledOCO")
|
||||
|
||||
|
||||
class TestStopOcoValidation:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def continuous_market(self, vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_stop_market_order_oco_form_validation(self, continuous_market, page: Page):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_market_order_btn).click()
|
||||
page.get_by_test_id(oco).click()
|
||||
expect(
|
||||
page.get_by_test_id("sidebar-content").get_by_text("Trigger").last
|
||||
).to_be_visible()
|
||||
# 7002-SORD-084
|
||||
expect(page.locator('[for="triggerDirection-risesAbove-oco"]')).to_have_text(
|
||||
"Rises above"
|
||||
)
|
||||
# 7002-SORD-085
|
||||
expect(page.locator('[for="triggerDirection-fallsBelow-oco"]')).to_have_text(
|
||||
"Falls below"
|
||||
)
|
||||
# 7002-SORD-087
|
||||
expect(page.locator('[for="triggerType-price-oco"]')).to_have_text("Price")
|
||||
expect(page.locator('[for="triggerType-price"]')).to_be_checked
|
||||
# 7002-SORD-088
|
||||
expect(
|
||||
page.locator('[for="triggerType-trailingPercentOffset-oco"]')
|
||||
).to_have_text("Trailing Percent Offset")
|
||||
expect(page.locator('[for="order-size-oco"]')).to_have_text("Size")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_stop_limit_order_oco_form_validation(self, continuous_market, page: Page):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_market_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(oco).click()
|
||||
expect(
|
||||
page.get_by_test_id("sidebar-content").get_by_text("Trigger").last
|
||||
).to_be_visible()
|
||||
# 7002-SORD-099
|
||||
expect(page.locator('[for="triggerDirection-risesAbove-oco"]')).to_have_text(
|
||||
"Rises above"
|
||||
)
|
||||
# 7002-SORD-091
|
||||
expect(page.locator('[for="triggerDirection-fallsBelow-oco"]')).to_have_text(
|
||||
"Falls below"
|
||||
)
|
||||
# 7002-SORD-095
|
||||
expect(page.locator('[for="triggerType-price-oco"]')).to_have_text("Price")
|
||||
expect(page.locator('[for="triggerType-price"]')).to_be_checked
|
||||
# 7002-SORD-095
|
||||
expect(
|
||||
page.locator('[for="triggerType-trailingPercentOffset-oco"]')
|
||||
).to_have_text("Trailing Percent Offset")
|
||||
|
||||
expect(page.locator('[for="order-size-oco"]')).to_have_text("Size")
|
||||
expect(page.locator('[for="order-price-oco"]')).to_have_text("Price")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_maximum_number_of_active_stop_orders_oco(
|
||||
self, continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(stop_orders_tab).click()
|
||||
create_position(vega, market_id)
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
page.get_by_test_id(stop_order_btn).click()
|
||||
page.get_by_test_id(stop_limit_order_btn).is_visible()
|
||||
page.get_by_test_id(stop_limit_order_btn).click()
|
||||
page.get_by_test_id(order_side_sell).click()
|
||||
page.locator("label").filter(has_text="Falls below").click()
|
||||
page.get_by_test_id(trigger_price).fill("102")
|
||||
page.get_by_test_id(order_size).fill("3")
|
||||
page.get_by_test_id(order_price).fill("103")
|
||||
page.get_by_test_id(oco).click()
|
||||
page.get_by_test_id(trigger_price_oco).fill("120")
|
||||
page.get_by_test_id(order_size_oco).fill("2")
|
||||
page.get_by_test_id(order_limit_price_oco).fill("99")
|
||||
for i in range(2):
|
||||
page.get_by_test_id(submit_stop_order).click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
if page.get_by_test_id(close_toast).is_visible():
|
||||
page.get_by_test_id(close_toast).click()
|
||||
wait_for_graphql_response(page, "stopOrders")
|
||||
# 7002-SORD-011
|
||||
expect(page.get_by_test_id("stop-order-warning-limit")).to_have_text(
|
||||
"There is a limit of 4 active stop orders per market. Orders submitted above the limit will be immediately rejected."
|
||||
)
|
@ -0,0 +1,51 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
|
||||
order_size = "order-size"
|
||||
order_price = "order-price"
|
||||
place_order = "place-order"
|
||||
deal_ticket_warning_margin = "deal-ticket-warning-margin"
|
||||
deal_ticket_deposit_dialog_button = "deal-ticket-deposit-dialog-button"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_should_display_info_and_button_for_deposit(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id(order_size).fill("200000")
|
||||
page.get_by_test_id(order_price).fill("20")
|
||||
# 7002-SORD-060
|
||||
expect(page.get_by_test_id(deal_ticket_warning_margin)).to_have_text("You may not have enough margin available to open this position.")
|
||||
page.get_by_test_id(deal_ticket_warning_margin).hover()
|
||||
expect(page.get_by_test_id("tooltip-content").nth(0)).to_have_text("1,661,896.6317 tDAI is currently required.You have only 1,000,000.00.Deposit tDAI")
|
||||
page.get_by_test_id(deal_ticket_deposit_dialog_button).nth(0).click()
|
||||
expect(page.get_by_test_id("sidebar-content")).to_contain_text("DepositFrom")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_should_show_an_error_if_your_balance_is_zero(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
vega.create_key("key_empty")
|
||||
page.get_by_test_id("manage-vega-wallet").click()
|
||||
page.locator('[role="menuitemradio"]').nth(4).click()
|
||||
page.reload()
|
||||
page.get_by_test_id(order_size).fill("200")
|
||||
page.get_by_test_id(order_price).fill("20")
|
||||
# 7002-SORD-060
|
||||
expect(page.get_by_test_id(place_order)).to_be_enabled()
|
||||
# 7002-SORD-003
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-zero-balance")).to_have_text("You need tDAI in your wallet to trade in this market. Make a deposit")
|
||||
expect(page.get_by_test_id(deal_ticket_deposit_dialog_button)).to_be_visible()
|
205
apps/trading/e2e/tests/get_started/test_get_started.py
Normal file
205
apps/trading/e2e/tests/get_started/test_get_started.py
Normal file
@ -0,0 +1,205 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
import json
|
||||
from vega_sim.service import VegaService
|
||||
from fixtures.market import setup_simple_market
|
||||
from conftest import init_vega
|
||||
from collections import namedtuple
|
||||
from actions.vega import submit_order
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
# we can reuse vega market-sim service and market in almost all tests
|
||||
@pytest.fixture(scope="class")
|
||||
def simple_market(vega: VegaService):
|
||||
return setup_simple_market(vega)
|
||||
|
||||
class TestGetStarted:
|
||||
@pytest.mark.usefixtures("page")
|
||||
def test_get_started_interactive(self, vega: VegaService, page: Page):
|
||||
page.goto("/")
|
||||
# 0007-FUGS-001
|
||||
expect(page.get_by_test_id("order-connect-wallet")).to_be_visible
|
||||
expect(page.get_by_test_id("order-connect-wallet")).to_be_enabled
|
||||
# 0007-FUGS-006
|
||||
# 0007-FUGS-002
|
||||
expect(page.locator(".list-none")).to_contain_text(
|
||||
"1.Connect2.Deposit funds3.Open a position"
|
||||
)
|
||||
DEFAULT_WALLET_NAME = "MarketSim" # This is the default wallet name within VegaServiceNull and CANNOT be changed
|
||||
|
||||
# Calling get_keypairs will internally call _load_tokens for the given wallet
|
||||
keypairs = vega.wallet.get_keypairs(DEFAULT_WALLET_NAME)
|
||||
wallet_api_token = vega.wallet.login_tokens[DEFAULT_WALLET_NAME]
|
||||
|
||||
# Set token to localStorage so eager connect hook picks it up and immediately connects
|
||||
wallet_config = json.dumps(
|
||||
{
|
||||
"token": f"VWT {wallet_api_token}",
|
||||
"connector": "jsonRpc",
|
||||
"url": f"http://localhost:{vega.wallet_port}",
|
||||
}
|
||||
)
|
||||
|
||||
storage_javascript = [
|
||||
# Store wallet config so eager connection is initiated
|
||||
f"localStorage.setItem('vega_wallet_config', '{wallet_config}');",
|
||||
# Ensure wallet ris dialog doesnt show, otherwise eager connect wont work
|
||||
"localStorage.setItem('vega_wallet_risk_accepted', 'true');",
|
||||
# Ensure initial risk dialog doesnt show
|
||||
"localStorage.setItem('vega_risk_accepted', 'true');",
|
||||
]
|
||||
script = "".join(storage_javascript)
|
||||
page.add_init_script(script)
|
||||
page.reload()
|
||||
|
||||
# Assert step 1 complete
|
||||
expect(page.get_by_test_id("icon-tick")).to_have_count(1)
|
||||
env = json.dumps(
|
||||
{
|
||||
"VEGA_URL": f"http://localhost:{vega.data_node_rest_port}/graphql",
|
||||
"VEGA_WALLET_URL": f"http://localhost:{vega.wallet_port}",
|
||||
}
|
||||
)
|
||||
window_env = f"window._env_ = Object.assign({{}}, window._env_, {env})"
|
||||
page.add_init_script(script=window_env)
|
||||
|
||||
page.reload()
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
mint_amount: float = 10e5
|
||||
|
||||
for wallet in wallets:
|
||||
vega.create_key(wallet.name)
|
||||
|
||||
vega.mint(
|
||||
MM_WALLET.name,
|
||||
asset="VOTE",
|
||||
amount=mint_amount,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.create_asset(
|
||||
MM_WALLET.name,
|
||||
name="tDAI",
|
||||
symbol="tDAI",
|
||||
decimals=5,
|
||||
max_faucet_amount=1e10,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
tdai_id = vega.find_asset_id(symbol="tDAI")
|
||||
logger.info(f"tDAI: {tdai_id}")
|
||||
|
||||
vega.mint(
|
||||
"Key 1",
|
||||
asset=tdai_id,
|
||||
amount=10,
|
||||
)
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
# Assert step 2 complete
|
||||
expect(page.get_by_test_id("icon-tick")).to_have_count(2)
|
||||
|
||||
market_id = vega.create_simple_market(
|
||||
"tDAI",
|
||||
proposal_key=MM_WALLET.name,
|
||||
settlement_asset_id=tdai_id,
|
||||
termination_key=TERMINATE_WALLET.name,
|
||||
market_decimals=5,
|
||||
approve_proposal=True,
|
||||
forward_time_to_enactment=True,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 1, 110)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("get-started-button").click()
|
||||
# Assert dialog isn't visible
|
||||
expect(page.get_by_test_id("welcome-dialog")).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_get_started_seen_already(self, simple_market, page: Page):
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
get_started_locator = page.get_by_test_id("connect-vega-wallet")
|
||||
page.wait_for_selector('[data-testid="connect-vega-wallet"]', state="attached")
|
||||
expect(get_started_locator).to_be_enabled
|
||||
expect(get_started_locator).to_be_visible
|
||||
# 0007-FUGS-015
|
||||
expect(get_started_locator).to_have_text("Get started")
|
||||
get_started_locator.click()
|
||||
# 0007-FUGS-007
|
||||
expect(page.get_by_test_id("dialog-content").nth(1)).to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page")
|
||||
def test_browser_wallet_installed(self, simple_market, page: Page):
|
||||
page.add_init_script("window.vega = {}")
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
locator = page.get_by_test_id("connect-vega-wallet")
|
||||
page.wait_for_selector('[data-testid="connect-vega-wallet"]', state="attached")
|
||||
expect(locator).to_be_enabled
|
||||
expect(locator).to_be_visible
|
||||
expect(locator).to_have_text("Connect")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_get_started_deal_ticket(self,simple_market, page: Page):
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
expect(page.get_by_test_id("order-connect-wallet")).to_have_text("Connect wallet")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_browser_wallet_installed_deal_ticket(simple_market, page: Page):
|
||||
page.add_init_script("window.vega = {}")
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
# 0007-FUGS-013
|
||||
page.wait_for_selector('[data-testid="sidebar-content"]', state="visible")
|
||||
expect(page.get_by_test_id("get-started-banner")).not_to_be_visible()
|
||||
|
||||
@pytest.mark.usefixtures("page")
|
||||
def test_redirect_default_market(self, continuous_market, vega: VegaService, page: Page):
|
||||
page.goto("/")
|
||||
# 0007-FUGS-012
|
||||
expect(page).to_have_url(
|
||||
f"http://localhost:{vega.console_port}/#/markets/{continuous_market}"
|
||||
)
|
||||
page.get_by_test_id("icon-cross").click()
|
||||
# 0007-FUGS-018
|
||||
expect(page.get_by_test_id("welcome-dialog")).not_to_be_visible()
|
||||
|
||||
class TestBrowseAll:
|
||||
@pytest.mark.usefixtures("page")
|
||||
def test_get_started_browse_all(self, simple_market, vega: VegaService, page: Page):
|
||||
page.goto("/")
|
||||
print(simple_market)
|
||||
page.get_by_test_id("browse-markets-button").click()
|
||||
# 0007-FUGS-005
|
||||
expect(page).to_have_url(f"http://localhost:{vega.console_port}/#/markets/{simple_market}")
|
182
apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py
Normal file
182
apps/trading/e2e/tests/iceberg_orders/test_iceberg_orders.py
Normal file
@ -0,0 +1,182 @@
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import expect, Page
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
|
||||
def hover_and_assert_tooltip(page: Page, element_text):
|
||||
element = page.get_by_text(element_text)
|
||||
element.hover()
|
||||
expect(page.get_by_role("tooltip")).to_be_visible()
|
||||
|
||||
|
||||
class TestIcebergOrdersValidations:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def continuous_market(self, vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_iceberg_submit(self, continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("iceberg").click()
|
||||
page.get_by_test_id("order-peak-size").type("2")
|
||||
page.get_by_test_id("order-minimum-size").type("1")
|
||||
page.get_by_test_id("order-size").type("3")
|
||||
page.get_by_test_id("order-price").type("107")
|
||||
page.get_by_test_id("place-order").click()
|
||||
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Awaiting confirmationPlease wait for your transaction to be confirmedView in block explorer"
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Order filledYour transaction has been confirmed View in block explorerSubmit order - filledBTC:DAI_2023+3 @ 107.00 tDAI"
|
||||
)
|
||||
page.get_by_test_id("All").click()
|
||||
expect(
|
||||
(page.get_by_role("row").locator('[col-id="type"]')).nth(1)
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_iceberg_tooltips(self, continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("iceberg").hover()
|
||||
expect(page.get_by_role("tooltip")).to_be_visible()
|
||||
page.get_by_test_id("iceberg").click()
|
||||
hover_and_assert_tooltip(page, "Peak size")
|
||||
hover_and_assert_tooltip(page, "Minimum size")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_iceberg_validations(self, continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("iceberg").click()
|
||||
page.get_by_test_id("place-order").click()
|
||||
expect(page.get_by_test_id("deal-ticket-peak-error-message")).to_be_visible()
|
||||
expect(page.get_by_test_id("deal-ticket-peak-error-message")).to_have_text(
|
||||
"You need to provide a peak size"
|
||||
)
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_be_visible()
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_have_text(
|
||||
"You need to provide a minimum visible size"
|
||||
)
|
||||
page.get_by_test_id("order-peak-size").clear()
|
||||
page.get_by_test_id("order-peak-size").type("1")
|
||||
page.get_by_test_id("order-minimum-size").clear()
|
||||
page.get_by_test_id("order-minimum-size").type("2")
|
||||
expect(page.get_by_test_id("deal-ticket-peak-error-message")).to_be_visible()
|
||||
expect(page.get_by_test_id("deal-ticket-peak-error-message")).to_have_text(
|
||||
"Peak size cannot be greater than the size (0)"
|
||||
)
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_be_visible()
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_have_text(
|
||||
"Minimum visible size cannot be greater than the peak size (1)"
|
||||
)
|
||||
page.get_by_test_id("order-minimum-size").clear()
|
||||
page.get_by_test_id("order-minimum-size").type("0.1")
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_be_visible()
|
||||
expect(page.get_by_test_id("deal-ticket-minimum-error-message")).to_have_text(
|
||||
"Minimum visible size cannot be lower than 1"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_iceberg_open_order(continuous_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
|
||||
submit_order(vega, "Key 1", continuous_market, "SIDE_SELL", 102, 101, 2, 1)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.wait_for_selector(".ag-center-cols-container .ag-row")
|
||||
expect(
|
||||
page.locator(
|
||||
".ag-center-cols-container .ag-row [col-id='openVolume'] [data-testid='stack-cell-primary']"
|
||||
)
|
||||
).to_have_text("-98")
|
||||
page.get_by_test_id("Open").click()
|
||||
page.wait_for_selector(".ag-center-cols-container .ag-row")
|
||||
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='remaining']")
|
||||
).to_have_text("99")
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='size']")
|
||||
).to_have_text("-102")
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='type'] ")
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='status']")
|
||||
).to_have_text("Active")
|
||||
expect(page.get_by_test_id("price-10100000")).to_be_visible
|
||||
expect(page.get_by_test_id("ask-vol-10100000")).to_have_text("3")
|
||||
page.get_by_test_id("Trades").click()
|
||||
expect(page.locator('[id^="cell-price-"]').first).to_have_text("101.50")
|
||||
expect(page.locator('[id^="cell-size-"]').first).to_have_text("99")
|
||||
|
||||
submit_order(vega, MM_WALLET2.name, continuous_market, "SIDE_BUY", 103, 101)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(
|
||||
page.locator(
|
||||
'[data-testid="tab-open-orders"] .ag-center-cols-container .ag-row'
|
||||
)
|
||||
).not_to_be_visible
|
||||
page.get_by_test_id("Closed").click()
|
||||
expect(
|
||||
page.locator(".ag-center-cols-container .ag-row [col-id='remaining']").first
|
||||
).to_have_text("102")
|
||||
expect(
|
||||
page.locator(
|
||||
"[data-testid=\"tab-closed-orders\"] .ag-center-cols-container .ag-row [col-id='size']"
|
||||
).first
|
||||
).to_have_text("-102")
|
||||
expect(
|
||||
page.locator(
|
||||
"[data-testid=\"tab-closed-orders\"] .ag-center-cols-container .ag-row [col-id='type']"
|
||||
).first
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
expect(
|
||||
page.locator(
|
||||
"[data-testid=\"tab-closed-orders\"] .ag-center-cols-container .ag-row [col-id='status']"
|
||||
).first
|
||||
).to_have_text("Filled")
|
||||
expect(page.locator('[id^="cell-price-"]').nth(2)).to_have_text("101.00")
|
||||
expect(page.locator('[id^="cell-size-"]').nth(2)).to_have_text("3")
|
||||
|
||||
|
||||
def verify_order_label(page: Page, test_id: str, expected_text: str):
|
||||
element = page.get_by_test_id(test_id)
|
||||
expect(element).to_be_visible()
|
||||
expect(element).to_have_text(expected_text)
|
||||
|
||||
|
||||
def verify_order_value(page: Page, test_id: str, expected_text: str):
|
||||
element = page.get_by_test_id(test_id)
|
||||
expect(element).to_be_visible()
|
||||
expect(element).to_have_text(expected_text)
|
@ -0,0 +1,52 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def continuous_market(vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_liquidity_provision_amendment(continuous_market, vega: VegaService, page: Page):
|
||||
# TODO Refactor asserting the grid
|
||||
page.goto(f"/#/liquidity/{continuous_market}")
|
||||
page.get_by_test_id("manage-vega-wallet").click()
|
||||
#TODO Rename "mm" to "marketMaker" so that we don't have to specify where to click when switching wallets
|
||||
# Currently the default click will click the middle of the element which will click the copy wallet key button
|
||||
page.locator('[role="menuitemradio"] >> .mr-2.uppercase').nth(1).click(position={ "x": 0, "y": 0}, force=True)
|
||||
page.reload()
|
||||
row = page.get_by_test_id("tab-myLP").locator(".ag-center-cols-container .ag-row").first
|
||||
expect(row).to_contain_text(
|
||||
"Active"
|
||||
)
|
||||
vega.submit_simple_liquidity(
|
||||
key_name="mm",
|
||||
market_id=continuous_market,
|
||||
commitment_amount=100,
|
||||
fee=0.001,
|
||||
is_amendment=True,
|
||||
)
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.reload()
|
||||
row = page.get_by_test_id("tab-myLP").locator(".ag-center-cols-container .ag-row").first
|
||||
expect(row).to_contain_text(
|
||||
"Updating next epoch"
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
page.reload()
|
||||
row = page.get_by_test_id("tab-myLP").locator(".ag-center-cols-container .ag-row").first
|
||||
expect(row).to_contain_text(
|
||||
"Active"
|
||||
)
|
135
apps/trading/e2e/tests/market/test_closed_markets.py
Normal file
135
apps/trading/e2e/tests/market/test_closed_markets.py
Normal file
@ -0,0 +1,135 @@
|
||||
import pytest
|
||||
import re
|
||||
import vega_sim.api.governance as governance
|
||||
from vega_sim.service import VegaService
|
||||
from playwright.sync_api import Page, expect
|
||||
from fixtures.market import setup_continuous_market
|
||||
from conftest import init_vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def create_settled_market(vega: VegaService):
|
||||
market_id = setup_continuous_market(vega)
|
||||
vega.submit_termination_and_settlement_data(
|
||||
settlement_key="FJMKnwfZdd48C8NqvYrG",
|
||||
settlement_price=110,
|
||||
market_id=market_id,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
class TestSettledMarket:
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth")
|
||||
def test_settled_header(self, page: Page, create_settled_market):
|
||||
page.goto(f"/#/markets/all")
|
||||
page.get_by_test_id("Closed markets").click()
|
||||
headers = [
|
||||
"Market",
|
||||
"Status",
|
||||
"Settlement date",
|
||||
"Best bid",
|
||||
"Best offer",
|
||||
"Mark price",
|
||||
"Settlement price",
|
||||
"Settlement asset",
|
||||
"",
|
||||
]
|
||||
|
||||
page.wait_for_selector('[data-testid="tab-closed-markets"]', state="visible")
|
||||
page_headers = (
|
||||
page.get_by_test_id("tab-closed-markets")
|
||||
.locator(".ag-header-cell-text")
|
||||
.all()
|
||||
)
|
||||
for i, header in enumerate(headers):
|
||||
expect(page_headers[i]).to_have_text(header)
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"risk_accepted",
|
||||
"auth",
|
||||
)
|
||||
def test_settled_rows(self, page: Page, create_settled_market):
|
||||
page.goto(f"/#/markets/all")
|
||||
page.get_by_test_id("Closed markets").click()
|
||||
|
||||
row_selector = page.locator(
|
||||
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row'
|
||||
).first
|
||||
|
||||
# 6001-MARK-001
|
||||
expect(row_selector.locator('[col-id="code"]')).to_have_text("BTC:DAI_2023Futr")
|
||||
# 6001-MARK-003
|
||||
expect(row_selector.locator('[col-id="state"]')).to_have_text("Settled")
|
||||
# 6001-MARK-004
|
||||
# 6001-MARK-005
|
||||
# 6001-MARK-009
|
||||
# 6001-MARK-008
|
||||
# 6001-MARK-010
|
||||
pattern = r"(\d+)\s+months\s+ago"
|
||||
date_text = row_selector.locator('[col-id="settlementDate"]').inner_text()
|
||||
assert re.match(pattern, date_text), f"Expected text to match pattern but got {date_text}"
|
||||
|
||||
|
||||
expected_pattern = re.compile(r"https://.*?/oracles/[a-f0-9]{64}")
|
||||
actual_href = row_selector.locator(
|
||||
'[col-id="settlementDate"] [data-testid="link"]'
|
||||
).get_attribute("href")
|
||||
assert expected_pattern.match(
|
||||
actual_href
|
||||
), f"Expected href to match {expected_pattern.pattern}, but got {actual_href}"
|
||||
# 6001-MARK-011
|
||||
expect(row_selector.locator('[col-id="bestBidPrice"]')).to_have_text("0.00")
|
||||
# 6001-MARK-012
|
||||
expect(row_selector.locator('[col-id="bestOfferPrice"]')).to_have_text("0.00")
|
||||
# 6001-MARK-013
|
||||
expect(row_selector.locator('[col-id="markPrice"]')).to_have_text("110.00")
|
||||
# 6001-MARK-014
|
||||
# 6001-MARK-015
|
||||
# 6001-MARK-016
|
||||
#tbd currently we have value unknown
|
||||
# expect(row_selector.locator('[col-id="settlementDataOracleId"]')).to_have_text(
|
||||
# "110.00"
|
||||
# )
|
||||
expected_pattern = re.compile(r"https://.*?/oracles/[a-f0-9]{64}")
|
||||
actual_href = row_selector.locator(
|
||||
'[col-id="settlementDataOracleId"] [data-testid="link"]'
|
||||
).get_attribute("href")
|
||||
assert expected_pattern.match(
|
||||
actual_href
|
||||
), f"Expected href to match {expected_pattern.pattern}, but got {actual_href}"
|
||||
|
||||
# 6001-MARK-018
|
||||
expect(row_selector.locator('[col-id="settlementAsset"]')).to_have_text("tDAI")
|
||||
# 6001-MARK-020
|
||||
assert re.match(pattern, date_text), f"Expected text to match pattern but got {date_text}"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth")
|
||||
def test_terminated_market_no_settlement_date(page: Page, vega: VegaService):
|
||||
setup_continuous_market(vega)
|
||||
print("I have started test_terminated_market_no_settlement_date")
|
||||
governance.submit_oracle_data(
|
||||
wallet=vega.wallet,
|
||||
payload={"trading.terminated": "true"},
|
||||
key_name="FJMKnwfZdd48C8NqvYrG",
|
||||
)
|
||||
vega.forward("60s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
page.goto(f"/#/markets/all")
|
||||
page.get_by_test_id("Closed markets").click()
|
||||
row_selector = page.locator(
|
||||
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row'
|
||||
).first
|
||||
expect(row_selector.locator('[col-id="state"]')).to_have_text("Trading Terminated")
|
||||
expect(row_selector.locator('[col-id="settlementDate"]')).to_have_text("Unknown")
|
||||
|
||||
# TODO Create test for terminated market with settlement date in future
|
||||
# TODO Create test for terminated market with settlement date in past
|
208
apps/trading/e2e/tests/market/test_market.py
Normal file
208
apps/trading/e2e/tests/market/test_market.py
Normal file
@ -0,0 +1,208 @@
|
||||
import pytest
|
||||
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService, PeggedOrder
|
||||
from actions.vega import submit_order
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
# Wallet Configurations
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
table_row_selector = (
|
||||
'[data-testid="tab-open-markets"] .ag-center-cols-container .ag-row'
|
||||
)
|
||||
trading_mode_col = '[col-id="tradingMode"]'
|
||||
state_col = '[col-id="state"]'
|
||||
item_value = "item-value"
|
||||
price_monitoring_bounds_row = "key-value-table-row"
|
||||
market_trading_mode = "market-trading-mode"
|
||||
market_state = "market-state"
|
||||
liquidity_supplied = "liquidity-supplied"
|
||||
item_value = "item-value"
|
||||
price_monitoring_bounds_row = "key-value-table-row"
|
||||
market_trading_mode = "market-trading-mode"
|
||||
market_state = "market-state"
|
||||
liquidity_supplied = "liquidity-supplied"
|
||||
|
||||
initial_commitment: float = 100
|
||||
initial_price: float = 1
|
||||
initial_volume: float = 1
|
||||
initial_spread: float = 0.1
|
||||
market_name = "BTC:DAI_2023"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "simple_market", "risk_accepted")
|
||||
def test_price_monitoring(simple_market, vega: VegaService, page: Page):
|
||||
page.goto(f"/#/markets/all")
|
||||
expect(page.locator(table_row_selector).locator(trading_mode_col)).to_have_text(
|
||||
"Opening auction"
|
||||
)
|
||||
expect(page.locator(table_row_selector).locator('[col-id="state"]')).to_have_text(
|
||||
"Pending"
|
||||
)
|
||||
result = page.get_by_text(market_name)
|
||||
result.first.click()
|
||||
page.get_by_test_id(market_trading_mode).get_by_text("Opening auction").hover()
|
||||
expect(page.get_by_test_id("opening-auction-sub-status").first).to_have_text(
|
||||
"Opening auction: Not enough liquidity to open"
|
||||
)
|
||||
logger.info(page.get_by_test_id("opening-auction-sub-status").inner_text)
|
||||
vega.submit_liquidity(
|
||||
key_name=MM_WALLET.name,
|
||||
market_id=simple_market,
|
||||
commitment_amount=initial_commitment,
|
||||
fee=0.002,
|
||||
is_amendment=False,
|
||||
)
|
||||
|
||||
vega.submit_order(
|
||||
market_id=simple_market,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
price=initial_price - 0.0005,
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
vega.submit_order(
|
||||
market_id=simple_market,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
price=initial_price + 0.0005,
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
|
||||
expect(
|
||||
page.get_by_test_id(liquidity_supplied).get_by_test_id(item_value)
|
||||
).to_have_text("0.00 (0.00%)")
|
||||
|
||||
# add orders to provide liquidity
|
||||
submit_order(
|
||||
vega, MM_WALLET.name, simple_market, "SIDE_BUY", initial_volume, initial_price
|
||||
)
|
||||
submit_order(
|
||||
vega, MM_WALLET.name, simple_market, "SIDE_SELL", initial_volume, initial_price
|
||||
)
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET.name,
|
||||
simple_market,
|
||||
"SIDE_BUY",
|
||||
initial_volume,
|
||||
initial_price + initial_spread / 2,
|
||||
)
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET.name,
|
||||
simple_market,
|
||||
"SIDE_SELL",
|
||||
initial_volume,
|
||||
initial_price + initial_spread / 2,
|
||||
)
|
||||
submit_order(
|
||||
vega, MM_WALLET2.name, simple_market, "SIDE_SELL", initial_volume, initial_price
|
||||
)
|
||||
expect(
|
||||
page.get_by_test_id(liquidity_supplied).get_by_test_id(item_value)
|
||||
).to_have_text("100.00 (>100%)")
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(
|
||||
page.get_by_test_id(liquidity_supplied).get_by_test_id(item_value)
|
||||
).to_have_text("50.00 (>100%)")
|
||||
|
||||
page.goto(f"/#/markets/all")
|
||||
# temporary skip
|
||||
# expect(page.locator(table_row_selector).locator(trading_mode_col)).to_have_text(
|
||||
# "Continuous"
|
||||
# )
|
||||
|
||||
# commented out because we have an issue #4233
|
||||
# expect(page.locator(row_selector).locator(state_col)
|
||||
# ).to_have_text("Pending")
|
||||
|
||||
page.goto(f"/#/markets/all")
|
||||
result = page.get_by_text(market_name)
|
||||
result.first.click()
|
||||
|
||||
page.get_by_test_id("Info").click()
|
||||
page.get_by_test_id("accordion-title").get_by_text(
|
||||
"Price monitoring bounds 1"
|
||||
).click()
|
||||
expect(
|
||||
page.get_by_test_id(price_monitoring_bounds_row).first.get_by_text(
|
||||
"1.32217 BTC"
|
||||
)
|
||||
).to_be_visible()
|
||||
expect(
|
||||
page.get_by_test_id(price_monitoring_bounds_row).last.get_by_text("0.79245 BTC")
|
||||
).to_be_visible()
|
||||
|
||||
# add orders that change the price so that it goes beyond the limits of price monitoring
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 110)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 90)
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 105)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 95)
|
||||
|
||||
# add order at the current price so that it is possible to change the status to price monitoring
|
||||
to_cancel = submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 1, 105)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(
|
||||
page.get_by_test_id(price_monitoring_bounds_row).first.get_by_text(
|
||||
"135.44204 BTC"
|
||||
)
|
||||
).to_be_visible()
|
||||
expect(
|
||||
page.get_by_test_id(price_monitoring_bounds_row).last.get_by_text(
|
||||
"81.17758 BTC"
|
||||
)
|
||||
).to_be_visible()
|
||||
expect(
|
||||
page.get_by_test_id(market_trading_mode).get_by_test_id(item_value)
|
||||
).to_have_text("Monitoring auction - price")
|
||||
expect(page.get_by_test_id(market_state).get_by_test_id(item_value)).to_have_text(
|
||||
"Suspended"
|
||||
)
|
||||
expect(
|
||||
page.get_by_test_id(liquidity_supplied).get_by_test_id(item_value)
|
||||
).to_have_text("50.00 (8.78%)")
|
||||
|
||||
# cancel order to increase liquidity
|
||||
vega.cancel_order(MM_WALLET2.name, simple_market, to_cancel)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
expect(page.get_by_text(market_name).first).to_be_attached()
|
||||
expect(
|
||||
page.get_by_test_id(market_trading_mode).get_by_test_id(item_value)
|
||||
).to_have_text("Continuous")
|
||||
expect(page.get_by_test_id(market_state).get_by_test_id(item_value)).to_have_text(
|
||||
"Active"
|
||||
)
|
||||
# commented out because we have an issue #4233
|
||||
# expect(page.get_by_text("Opening auction")).to_be_hidden()
|
||||
|
||||
expect(
|
||||
page.get_by_test_id(liquidity_supplied).get_by_test_id(item_value)
|
||||
).to_have_text("50.00 (>100%)")
|
294
apps/trading/e2e/tests/market/test_market_info.py
Normal file
294
apps/trading/e2e/tests/market/test_market_info.py
Normal file
@ -0,0 +1,294 @@
|
||||
import re
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
from conftest import init_page, init_vega, risk_accepted_setup
|
||||
|
||||
market_title_test_id = "accordion-title"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
# setting up everything in this single fixture, as all of the tests need the same setup, so no point in creating separate ones
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
setup_continuous_market(vega)
|
||||
risk_accepted_setup(page)
|
||||
page.goto("/")
|
||||
page.get_by_test_id("Info").click()
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def after_each(page: Page):
|
||||
yield
|
||||
opened_element = page.locator('h3[data-state="open"]')
|
||||
if opened_element.all() and opened_element.get_by_role("button").is_visible():
|
||||
opened_element.get_by_role("button").click()
|
||||
|
||||
|
||||
def validate_info_section(page: Page, fields: [[str, str]]):
|
||||
for rowNumber, field in enumerate(fields):
|
||||
name, value = field
|
||||
expect(
|
||||
page.get_by_test_id("key-value-table-row").nth(rowNumber).locator("dt")
|
||||
).to_contain_text(name)
|
||||
expect(
|
||||
page.get_by_test_id("key-value-table-row").nth(rowNumber).locator("dd")
|
||||
).to_contain_text(value)
|
||||
|
||||
|
||||
def test_market_info_current_fees(page: Page):
|
||||
# 6002-MDET-101
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Current fees").click()
|
||||
fields = [
|
||||
["Maker Fee", "10%"],
|
||||
["Infrastructure Fee", "0.05%"],
|
||||
["Liquidity Fee", "0%"],
|
||||
["Total Fees", "10.05%"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_market_price(page: Page):
|
||||
# 6002-MDET-102
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Market price").click()
|
||||
fields = [
|
||||
["Mark Price", "107.50"],
|
||||
["Best Bid Price", "101.50"],
|
||||
["Best Offer Price", "103.50"],
|
||||
["Quote Unit", "BTC"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_market_volume(page: Page):
|
||||
# 6002-MDET-103
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Market volume").click()
|
||||
fields = [
|
||||
["24 Hour Volume", "-"],
|
||||
["Open Interest", "1"],
|
||||
["Best Bid Volume", "99"],
|
||||
["Best Offer Volume", "99"],
|
||||
["Best Static Bid Volume", "1"],
|
||||
["Best Static Offer Volume", "1"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_insurance_pool(page: Page):
|
||||
# 6002-MDET-104
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Insurance pool").click()
|
||||
fields = [["Balance", "0.00 tDAI"]]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_key_details(page: Page, vega: VegaService):
|
||||
# 6002-MDET-201
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Key details").click()
|
||||
market_id = vega.find_market_id("BTC:DAI_2023")
|
||||
short_market_id = market_id[:6] + "…" + market_id[-4:]
|
||||
fields = [
|
||||
["Market ID", short_market_id],
|
||||
["Name", "BTC:DAI_2023"],
|
||||
["Parent Market ID", "-"],
|
||||
["Insurance Pool Fraction", "-"],
|
||||
["Status", "Active"],
|
||||
["Trading Mode", "Continuous"],
|
||||
["Market Decimal Places", "5"],
|
||||
["Position Decimal Places", "0"],
|
||||
["Settlement Asset Decimal Places", "5"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_instrument(page: Page):
|
||||
# 6002-MDET-202
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Instrument").click()
|
||||
fields = [
|
||||
["Market Name", "BTC:DAI_2023"],
|
||||
["Code", "BTC:DAI_2023"],
|
||||
["Product Type", "Future"],
|
||||
["Quote Name", "BTC"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
# @pytest.mark.skip("oracle test to be fixed")
|
||||
def test_market_info_oracle(page: Page, vega: VegaService):
|
||||
# 6002-MDET-203
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Oracle").click()
|
||||
expect(
|
||||
page.locator('[data-state="open"]').get_by_test_id("accordion-content")
|
||||
).to_contain_text("No oracle proof for settlement data")
|
||||
expect(page.get_by_test_id("oracle-spec-links")).to_have_text(
|
||||
"View settlement data specification"
|
||||
)
|
||||
# expect(page.get_by_test_id("oracle-spec-links")).to_have_attribute(
|
||||
# "href", re.compile(rf'(\/oracles\/{vega.find_market_id("BTC:DAI_2023")})')
|
||||
# )
|
||||
|
||||
|
||||
def test_market_info_settlement_asset(page: Page, vega: VegaService):
|
||||
# 6002-MDET-206
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Settlement asset").click()
|
||||
tdai_id = vega.find_asset_id("tDAI")
|
||||
tdai_id_short = tdai_id[:6] + "…" + tdai_id[-4:]
|
||||
fields = [
|
||||
["ID", tdai_id_short],
|
||||
["Type", "Builtin asset"],
|
||||
["Name", "tDAI"],
|
||||
["Symbol", "tDAI"],
|
||||
["Decimals", "5"],
|
||||
["Quantum", "0.00001"],
|
||||
["Status", "Enabled"],
|
||||
["Max faucet amount", "10,000,000,000.00"],
|
||||
["Infrastructure fee account balance", "0.00"],
|
||||
["Global reward pool account balance", "0.00"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_metadata(page: Page):
|
||||
# 6002-MDET-207
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Metadata").click()
|
||||
fields = [
|
||||
["Base", "BTC"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_risk_model(page: Page):
|
||||
# 6002-MDET-208
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Risk model").click()
|
||||
fields = [
|
||||
["Tau", "0.00011407711613050422"],
|
||||
["Risk Aversion Parameter", "0.000001"],
|
||||
["Sigma", "1"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_margin_scaling_factors(page: Page):
|
||||
# 6002-MDET-209
|
||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||
"Margin scaling factors"
|
||||
).click()
|
||||
fields = [
|
||||
["Linear Slippage Factor", "0.001"],
|
||||
["Quadratic Slippage Factor", "0"],
|
||||
["Search Level", "1.1"],
|
||||
["Initial Margin", "1.5"],
|
||||
["Collateral Release", "1.7"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_risk_factors(page: Page):
|
||||
# 6002-MDET-210
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Risk factors").click()
|
||||
fields = [
|
||||
["Long", "0.05153"],
|
||||
["Short", "0.05422"],
|
||||
["Max Leverage Long", "19.036"],
|
||||
["Max Leverage Short", "18.111"],
|
||||
["Max Initial Leverage Long", "12.691"],
|
||||
["Max Initial Leverage Short", "12.074"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_price_monitoring_bounds(page: Page):
|
||||
# 6002-MDET-211
|
||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||
"Price monitoring bounds 1"
|
||||
).click()
|
||||
expect(page.locator("p.col-span-1").nth(0)).to_contain_text(
|
||||
"99.9999% probability price bounds"
|
||||
)
|
||||
expect(page.locator("p.col-span-1").nth(1)).to_contain_text("Within 86,400 seconds")
|
||||
fields = [
|
||||
["Highest Price", "138.66685 BTC"],
|
||||
["Lowest Price", "83.11038 BTC"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_liquidity_monitoring_parameters(page: Page):
|
||||
# 6002-MDET-212
|
||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||
"Liquidity monitoring parameters"
|
||||
).click()
|
||||
fields = [
|
||||
["Triggering Ratio", "0.7"],
|
||||
["Time Window", "3,600"],
|
||||
["Scaling Factor", "1"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
# Liquidity resolves to 3 results
|
||||
def test_market_info_liquidit(page: Page):
|
||||
# 6002-MDET-213
|
||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||
"Liquidity", exact=True
|
||||
).click()
|
||||
fields = [
|
||||
["Target Stake", "5.82757 tDAI"],
|
||||
["Supplied Stake", "10,000.00 tDAI"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_liquidity_price_range(page: Page):
|
||||
# 6002-MDET-214
|
||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||
"Liquidity price range"
|
||||
).click()
|
||||
fields = [
|
||||
["Liquidity Price Range", "100% of mid price"],
|
||||
["Lowest Price", "0.00 BTC"],
|
||||
["Highest Price", "205.00 BTC"],
|
||||
]
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
def test_market_info_proposal(page: Page, vega: VegaService):
|
||||
# 6002-MDET-301
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Proposal").click()
|
||||
first_link = (
|
||||
page.get_by_test_id("accordion-content").get_by_test_id("external-link").first
|
||||
)
|
||||
second_link = (
|
||||
page.get_by_test_id("accordion-content").get_by_test_id("external-link").nth(1)
|
||||
)
|
||||
expect(first_link).to_have_text("View governance proposal")
|
||||
expect(first_link).to_have_attribute(
|
||||
"href", re.compile(rf'(\/proposals\/{vega.find_market_id("BTC:DAI_2023")})')
|
||||
)
|
||||
expect(second_link).to_have_text("Propose a change to market")
|
||||
|
||||
# create regular expression that matches "/proposals/propose/update-market" string
|
||||
expect(second_link).to_have_attribute(
|
||||
"href", re.compile(r"(\/proposals\/propose\/update-market)")
|
||||
)
|
||||
|
||||
|
||||
def test_market_info_succession_line(page: Page, vega: VegaService):
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Succession line").click()
|
||||
market_id = vega.find_market_id("BTC:DAI_2023")
|
||||
succession_line = page.get_by_test_id("succession-line-item")
|
||||
expect(succession_line.get_by_test_id("external-link")).to_have_text("BTC:DAI_2023")
|
||||
expect(succession_line.get_by_test_id("external-link")).to_have_attribute(
|
||||
"href", re.compile(rf"(\/proposals\/{market_id})")
|
||||
)
|
||||
expect(page.get_by_test_id("succession-line-item-market-id")).to_have_text(
|
||||
market_id
|
||||
)
|
88
apps/trading/e2e/tests/market/test_market_selector.py
Normal file
88
apps/trading/e2e/tests/market/test_market_selector.py
Normal file
@ -0,0 +1,88 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_market_selector(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
expect(page.get_by_test_id("market-selector")).not_to_be_visible()
|
||||
page.get_by_test_id("header-title").click()
|
||||
# 6001-MARK-066
|
||||
expect(page.get_by_test_id("market-selector")).to_be_visible()
|
||||
|
||||
# 6001-MARK-021
|
||||
# 6001-MARK-022
|
||||
# 6001-MARK-024
|
||||
# 6001-MARK-025
|
||||
btc_market = page.locator('[data-testid="market-selector-list"] a')
|
||||
expect(btc_market.locator("h3")).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(btc_market.locator('[data-testid="market-selector-volume"]')).to_have_text(
|
||||
"0.00"
|
||||
)
|
||||
expect(btc_market.locator('[data-testid="market-selector-price"]')).to_have_text(
|
||||
"107.50 tDAI"
|
||||
)
|
||||
expect(btc_market.locator("span.rounded-md.leading-none")).to_be_visible()
|
||||
expect(btc_market.locator("span.rounded-md.leading-none")).to_have_text("Futr")
|
||||
expect(btc_market.locator('[data-testid="sparkline-svg"]')).not_to_be_visible
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "simple_market", "auth", "risk_accepted")
|
||||
@pytest.mark.parametrize(
|
||||
"simple_market",
|
||||
[
|
||||
{
|
||||
"custom_market_name": "APPL.MF21",
|
||||
"custom_asset_name": "tUSDC",
|
||||
"custom_asset_symbol": "tUSDC",
|
||||
}
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_market_selector_filter(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("header-title").click()
|
||||
# 6001-MARK-027
|
||||
|
||||
page.get_by_test_id("product-Spot").click()
|
||||
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
|
||||
"Spot markets coming soon."
|
||||
)
|
||||
page.get_by_test_id("product-Perpetual").click()
|
||||
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
|
||||
"No perpetual markets."
|
||||
)
|
||||
page.get_by_test_id("product-Future").click()
|
||||
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(2)
|
||||
|
||||
# 6001-MARK-029
|
||||
page.get_by_test_id("search-term").fill("btc")
|
||||
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(1)
|
||||
expect(page.locator('[data-testid="market-selector-list"] a').nth(0)).to_have_text(
|
||||
"BTC:DAI_2023107.50 tDAI0.00"
|
||||
)
|
||||
|
||||
page.get_by_test_id("search-term").clear()
|
||||
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(2)
|
||||
|
||||
# 6001-MARK-030
|
||||
# 6001-MARK-031
|
||||
# 6001-MARK-032
|
||||
# 6001-MARK-033
|
||||
page.get_by_test_id("sort-trigger").click()
|
||||
|
||||
expect(page.get_by_test_id("sort-item-Gained")).to_have_text("Top gaining")
|
||||
expect(page.get_by_test_id("sort-item-Gained")).to_be_visible()
|
||||
expect(page.get_by_test_id("sort-item-Lost")).to_have_text("Top losing")
|
||||
expect(page.get_by_test_id("sort-item-Lost")).to_be_visible()
|
||||
expect(page.get_by_test_id("sort-item-New")).to_have_text("New markets")
|
||||
expect(page.get_by_test_id("sort-item-New")).to_be_visible()
|
||||
|
||||
# 6001-MARK-028
|
||||
page.get_by_test_id("sort-trigger").click(force=True)
|
||||
page.get_by_test_id("asset-trigger").click()
|
||||
page.get_by_role("menuitemcheckbox").nth(0).get_by_text("tDAI").click()
|
||||
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(1)
|
||||
expect(page.locator('[data-testid="market-selector-list"] a').nth(0)).to_have_text(
|
||||
"BTC:DAI_2023107.50 tDAI0.00"
|
||||
)
|
160
apps/trading/e2e/tests/market/test_markets_all.py
Normal file
160
apps/trading/e2e/tests/market/test_markets_all.py
Normal file
@ -0,0 +1,160 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
from conftest import init_vega
|
||||
|
||||
market_names = ["ETHBTC.QM21", "BTCUSD.MF21", "SOLUSD", "AAPL.MF21"]
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def create_markets(vega):
|
||||
for market_name in market_names:
|
||||
setup_continuous_market(vega, custom_market_name=market_name)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_table_headers(page: Page, create_markets):
|
||||
page.goto(f"/#/markets/all")
|
||||
headers = [
|
||||
"Market",
|
||||
"Description",
|
||||
"Trading mode",
|
||||
"Status",
|
||||
"Mark price",
|
||||
"24h volume",
|
||||
"Settlement asset",
|
||||
"Spread",
|
||||
"",
|
||||
]
|
||||
|
||||
page.wait_for_selector('[data-testid="tab-open-markets"]', state="visible")
|
||||
page_headers = (
|
||||
page.get_by_test_id("tab-open-markets").locator(".ag-header-cell-text").all()
|
||||
)
|
||||
for i, header in enumerate(headers):
|
||||
expect(page_headers[i]).to_have_text(header)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_markets_tab(page: Page, create_markets):
|
||||
page.goto(f"/#/markets/all")
|
||||
expect(page.get_by_test_id("Open markets")).to_have_attribute(
|
||||
"data-state", "active"
|
||||
)
|
||||
expect(page.get_by_test_id("Proposed markets")).to_have_attribute(
|
||||
"data-state", "inactive"
|
||||
)
|
||||
expect(page.get_by_test_id("Closed markets")).to_have_attribute(
|
||||
"data-state", "inactive"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_markets_content(page: Page, create_markets):
|
||||
page.goto(f"/#/markets/all")
|
||||
row_selector = page.locator(
|
||||
'[data-testid="tab-open-markets"] .ag-center-cols-container .ag-row'
|
||||
).first
|
||||
instrument_code_locator = '[col-id="tradableInstrument.instrument.code"] [data-testid="stack-cell-primary"]'
|
||||
# 6001-MARK-035
|
||||
expect(row_selector.locator(instrument_code_locator)).to_have_text("ETHBTC.QM21")
|
||||
|
||||
# 6001-MARK-073
|
||||
expect(row_selector.locator('[title="Future"]')).to_have_text("Futr")
|
||||
|
||||
# 6001-MARK-036
|
||||
expect(
|
||||
row_selector.locator('[col-id="tradableInstrument.instrument.name"]')
|
||||
).to_have_text("ETHBTC.QM21")
|
||||
|
||||
# 6001-MARK-037
|
||||
expect(row_selector.locator('[col-id="tradingMode"]')).to_have_text("Continuous")
|
||||
|
||||
# 6001-MARK-038
|
||||
expect(row_selector.locator('[col-id="state"]')).to_have_text("Active")
|
||||
|
||||
# 6001-MARK-039
|
||||
expect(row_selector.locator('[col-id="data.markPrice"]')).to_have_text("107.50")
|
||||
|
||||
# 6001-MARK-040
|
||||
expect(row_selector.locator('[col-id="data.candles"]')).to_have_text("0.00")
|
||||
|
||||
# 6001-MARK-042
|
||||
expect(
|
||||
row_selector.locator(
|
||||
'[col-id="tradableInstrument.instrument.product.settlementAsset.symbol"]'
|
||||
)
|
||||
).to_have_text("tDAI")
|
||||
|
||||
expect(row_selector.locator('[col-id="data.bestBidPrice"]')).to_have_text("2")
|
||||
|
||||
# 6001-MARK-043
|
||||
row_selector.locator(
|
||||
'[col-id="tradableInstrument.instrument.product.settlementAsset.symbol"] button'
|
||||
).click()
|
||||
expect(page.get_by_test_id("dialog-title")).to_have_text("Asset details - tDAI")
|
||||
# 6001-MARK-019
|
||||
page.get_by_test_id("close-asset-details-dialog").click()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_market_actions(page: Page, create_markets):
|
||||
# 6001-MARK-044
|
||||
# 6001-MARK-045
|
||||
# 6001-MARK-046
|
||||
# 6001-MARK-047
|
||||
page.goto(f"/#/markets/all")
|
||||
page.locator(
|
||||
'.ag-pinned-right-cols-container [col-id="market-actions"]'
|
||||
).first.locator("button").click()
|
||||
|
||||
actions = [
|
||||
"Copy Market ID",
|
||||
"View on Explorer",
|
||||
"View settlement asset details",
|
||||
]
|
||||
action_elements = (
|
||||
page.get_by_test_id("market-actions-content").get_by_role("menuitem").all()
|
||||
)
|
||||
|
||||
for i, action in enumerate(actions):
|
||||
expect(action_elements[i]).to_have_text(action)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_sort_markets(page: Page, create_markets):
|
||||
# 6001-MARK-064
|
||||
|
||||
page.goto(f"/#/markets/all")
|
||||
sorted_market_names = [
|
||||
"AAPL.MF21",
|
||||
"BTCUSD.MF21",
|
||||
"ETHBTC.QM21",
|
||||
"SOLUSD",
|
||||
]
|
||||
page.locator('.ag-header-row [col-id="tradableInstrument.instrument.code"]').click()
|
||||
for i, market_name in enumerate(sorted_market_names):
|
||||
expect(
|
||||
page.locator(
|
||||
f'[row-index="{i}"] [col-id="tradableInstrument.instrument.name"]'
|
||||
)
|
||||
).to_have_text(market_name)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_drag_and_drop_column(page: Page, create_markets):
|
||||
# 6001-MARK-065
|
||||
page.goto(f"/#/markets/all")
|
||||
col_instrument_code = '.ag-header-row [col-id="tradableInstrument.instrument.code"]'
|
||||
|
||||
page.locator(col_instrument_code).drag_to(
|
||||
page.locator('.ag-header-row [col-id="data.bestBidPrice"]')
|
||||
)
|
||||
expect(page.locator(col_instrument_code)).to_have_attribute("aria-colindex", "8")
|
36
apps/trading/e2e/tests/market/test_markets_no_markets.py
Normal file
36
apps/trading/e2e/tests/market/test_markets_no_markets.py
Normal file
@ -0,0 +1,36 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
|
||||
from conftest import init_page, init_vega, risk_accepted_setup
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
page.goto("/#/markets/all")
|
||||
yield page
|
||||
|
||||
|
||||
def test_no_open_markets(page: Page):
|
||||
# 6001-MARK-034
|
||||
page.get_by_test_id("Open markets").click()
|
||||
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No markets")
|
||||
|
||||
|
||||
def test_no_closed_markets(page: Page):
|
||||
page.get_by_test_id("Closed markets").click()
|
||||
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No markets")
|
||||
|
||||
|
||||
def test_no_proposed_markets(page: Page):
|
||||
# 6001-MARK-061
|
||||
page.get_by_test_id("Proposed markets").click()
|
||||
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No proposed markets")
|
132
apps/trading/e2e/tests/market/test_markets_proposed.py
Normal file
132
apps/trading/e2e/tests/market/test_markets_proposed.py
Normal file
@ -0,0 +1,132 @@
|
||||
from math import exp
|
||||
import pytest
|
||||
import vega_sim.api.governance as governance
|
||||
import re
|
||||
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_simple_market
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
row_selector = '[data-testid="tab-proposed-markets"] .ag-center-cols-container .ag-row'
|
||||
col_market_id = '[col-id="market"] [data-testid="stack-cell-primary"]'
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def proposed_market(vega: VegaService):
|
||||
# setup market without liquidity provided
|
||||
market_id = setup_simple_market(vega, approve_proposal=False)
|
||||
# approve market
|
||||
governance.approve_proposal(
|
||||
key_name=MM_WALLET.name,
|
||||
proposal_id=market_id,
|
||||
wallet=vega.wallet,
|
||||
)
|
||||
return market_id
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_can_see_table_headers(proposed_market, page: Page):
|
||||
page.goto("/#/markets/all")
|
||||
page.click('[data-testid="Proposed markets"]')
|
||||
|
||||
# Test that you can see table headers
|
||||
headers = [
|
||||
"Market",
|
||||
"Settlement asset",
|
||||
"State",
|
||||
"Parent market",
|
||||
"Voting",
|
||||
"Closing date",
|
||||
"Enactment date",
|
||||
"",
|
||||
]
|
||||
|
||||
header_elements = page.locator(".ag-header-cell-text")
|
||||
for i, header in enumerate(headers):
|
||||
assert header_elements.nth(i).inner_text() == header
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_renders_markets_correctly(proposed_market, page: Page):
|
||||
page.goto(f"/#/markets/all")
|
||||
page.click('[data-testid="Proposed markets"]')
|
||||
row = page.locator(row_selector)
|
||||
# 6001-MARK-049
|
||||
expect(row.locator(col_market_id)).to_have_text("BTC:DAI_2023")
|
||||
|
||||
# 6001-MARK-051
|
||||
expect(row.locator('[col-id="asset"]')).to_have_text("tDAI")
|
||||
|
||||
# 6001-MARK-052
|
||||
# 6001-MARK-053
|
||||
expect(row.locator('[col-id="state"]')).to_have_text("Open")
|
||||
expect(
|
||||
row.locator('[col-id="terms.change.successorConfiguration.parentMarketId"]')
|
||||
).to_have_text("-")
|
||||
|
||||
# 6001-MARK-054
|
||||
# 6001-MARK-055
|
||||
expect(row.get_by_test_id("vote-progress-bar-against")).to_be_visible()
|
||||
|
||||
# 6001-MARK-056
|
||||
expect(row.locator('[col-id="closing-date"]')).not_to_be_empty()
|
||||
|
||||
# 6001-MARK-057
|
||||
expect(row.locator('[col-id="enactment-date"]')).not_to_be_empty
|
||||
|
||||
# 6001-MARK-058
|
||||
page.get_by_test_id("dropdown-menu").click()
|
||||
dropdown_content = '[data-testid="proposal-actions-content"]'
|
||||
first_item_link = (
|
||||
page.locator(f"{dropdown_content} [role='menuitem']").nth(0).locator("a")
|
||||
)
|
||||
|
||||
# 6001-MARK-059
|
||||
expect(first_item_link).to_contain_text("View proposal")
|
||||
expect(first_item_link).to_have_attribute(
|
||||
"href",
|
||||
re.compile(r"\/proposals\/[a-f0-9]{64}$"),
|
||||
)
|
||||
|
||||
# temporary skip
|
||||
# 6001-MARK-060
|
||||
# proposed_markets_tab = page.get_by_test_id("tab-proposed-markets")
|
||||
# external_links = proposed_markets_tab.locator("font-alpha")
|
||||
# last_link = external_links.last
|
||||
# assert last_link.inner_text() == 'Propose a new market'
|
||||
|
||||
# expected_href = f"https://governance.stagnet1.vega.rocks/proposals/propose/new-market"
|
||||
# assert last_link.get_attribute('href') == expected_href
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_can_drag_and_drop_columns(proposed_market, page: Page):
|
||||
# 6001-MARK-063
|
||||
page.goto("/#/markets/all")
|
||||
page.click('[data-testid="Proposed markets"]')
|
||||
col_market = page.locator('[col-id="market"]').first
|
||||
col_vote = page.locator('[col-id="voting"]').first
|
||||
col_market.drag_to(col_vote)
|
||||
|
||||
# Check the attribute of the dragged element
|
||||
attribute_value = col_market.get_attribute("aria-colindex")
|
||||
assert attribute_value != "1"
|
@ -0,0 +1,131 @@
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from fixtures.market import setup_simple_market
|
||||
from conftest import init_vega
|
||||
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
TERMINATE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, TERMINATE_WALLET]
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def simple_market(vega):
|
||||
return setup_simple_market(vega)
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def setup_market_monitoring_auction(vega: VegaService, simple_market):
|
||||
vega.submit_liquidity(
|
||||
key_name=MM_WALLET.name,
|
||||
market_id=simple_market,
|
||||
commitment_amount=100,
|
||||
fee=0.002,
|
||||
is_amendment=False,
|
||||
)
|
||||
|
||||
vega.submit_order(
|
||||
market_id=simple_market,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
price=1 - 0.0005,
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
vega.submit_order(
|
||||
market_id=simple_market,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
price=1 + 0.0005,
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
|
||||
|
||||
# add orders to provide liquidity
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_BUY", 1, 1)
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 1, 1)
|
||||
submit_order(vega,MM_WALLET.name,simple_market, "SIDE_BUY",1,1 + 0.1 / 2,)
|
||||
submit_order(vega,MM_WALLET.name,simple_market,"SIDE_SELL",1,1 + 0.1 / 2)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_SELL", 1, 1)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# add orders that change the price so that it goes beyond the limits of price monitoring
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 110)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 90)
|
||||
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 105)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 95)
|
||||
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 1, 105)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted", "simple_market", "auth", "setup_market_monitoring_auction")
|
||||
def test_market_monitoring_auction_price_volatility_limit_order(page: Page, simple_market, vega: VegaService):
|
||||
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
page.get_by_test_id("order-size").clear()
|
||||
page.get_by_test_id("order-size").type("1")
|
||||
page.get_by_test_id("order-price").clear()
|
||||
page.get_by_test_id("order-price").type("110")
|
||||
page.get_by_test_id("order-tif").select_option("Fill or Kill (FOK)")
|
||||
page.get_by_test_id("place-order").click()
|
||||
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_have_text("This market is in auction due to high price volatility. Until the auction ends, you can only place GFA, GTT, or GTC limit orders")
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_be_visible()
|
||||
|
||||
expect(page.get_by_test_id("deal-ticket-warning-auction")).to_have_text("Any orders placed now will not trade until the auction ends")
|
||||
expect(page.get_by_test_id("deal-ticket-warning-auction")).to_be_visible()
|
||||
|
||||
page.get_by_test_id("order-tif").select_option("Good 'til Cancelled (GTC)")
|
||||
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-tif")).not_to_be_visible()
|
||||
|
||||
page.get_by_test_id("place-order").click()
|
||||
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.get_by_test_id("All").click()
|
||||
expect(page.get_by_role("row").nth(2)).to_contain_text(
|
||||
"BTC:DAI_2023Futr0+1LimitActive110.00GTC"
|
||||
)
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted", "simple_market", "auth", "setup_market_monitoring_auction")
|
||||
def test_market_monitoring_auction_price_volatility_market_order(page: Page, simple_market):
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
page.get_by_test_id("order-type-Market").click()
|
||||
page.get_by_test_id("order-size").clear()
|
||||
page.get_by_test_id("order-size").type("1")
|
||||
# 7002-SORD-060
|
||||
page.get_by_test_id("place-order").click()
|
||||
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_have_text("This market is in auction due to high price volatility. Until the auction ends, you can only place GFA, GTT, or GTC limit orders")
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_be_visible()
|
||||
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-type")).to_have_text("This market is in auction due to high price volatility. Only limit orders are permitted when market is in auction")
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-type")).to_be_visible()
|
174
apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py
Normal file
174
apps/trading/e2e/tests/market_lifecycle/test_market_lifecycle.py
Normal file
@ -0,0 +1,174 @@
|
||||
import pytest
|
||||
import vega_sim.api.governance as governance
|
||||
import re
|
||||
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService, PeggedOrder
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
import vega_sim.api.governance as governance
|
||||
from actions.vega import submit_order
|
||||
from fixtures.market import setup_continuous_market
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from vega_sim.service import MarketStateUpdateType
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
GOVERNANCE_WALLET = WalletConfig("FJMKnwfZdd48C8NqvYrG", "bY3DxwtsCstMIIZdNpKs")
|
||||
|
||||
wallets = [MM_WALLET, MM_WALLET2, GOVERNANCE_WALLET]
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "proposed_market", "risk_accepted")
|
||||
def test_market_lifecycle(proposed_market, vega: VegaService, page: Page):
|
||||
trading_mode = page.get_by_test_id("market-trading-mode").get_by_test_id(
|
||||
"item-value"
|
||||
)
|
||||
market_state = page.get_by_test_id("market-state").get_by_test_id("item-value")
|
||||
|
||||
# setup market in proposed step, without liquidity provided
|
||||
market_id = proposed_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
|
||||
# check that market is in proposed state
|
||||
expect(trading_mode).to_have_text("No trading")
|
||||
expect(market_state).to_have_text("Proposed")
|
||||
|
||||
# approve market
|
||||
governance.approve_proposal(
|
||||
key_name=MM_WALLET.name,
|
||||
proposal_id=market_id,
|
||||
wallet=vega.wallet,
|
||||
)
|
||||
|
||||
# "wait" for market to be approved and enacted
|
||||
vega.forward("60s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# check that market is in pending state
|
||||
expect(trading_mode).to_have_text("Opening auction")
|
||||
expect(market_state).to_have_text("Pending")
|
||||
|
||||
# Add liquidity and place some orders. Orders should match to produce the uncrossing price. A market can only move from opening auction to continuous trading when the enactment date has passed, there is sufficient liquidity and an uncrossing price is produced.
|
||||
vega.submit_simple_liquidity(
|
||||
key_name=MM_WALLET.name,
|
||||
market_id=market_id,
|
||||
commitment_amount=10000,
|
||||
fee=0.000,
|
||||
is_amendment=False,
|
||||
)
|
||||
|
||||
vega.submit_order(
|
||||
market_id=market_id,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_MID", offset=1),
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
vega.submit_order(
|
||||
market_id=market_id,
|
||||
trading_key=MM_WALLET.name,
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_MID", offset=1),
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=99,
|
||||
)
|
||||
|
||||
submit_order(vega, MM_WALLET.name, market_id, "SIDE_SELL", 1, 110)
|
||||
submit_order(vega, MM_WALLET2.name, market_id, "SIDE_BUY", 1, 90)
|
||||
submit_order(vega, MM_WALLET.name, market_id, "SIDE_SELL", 1, 105)
|
||||
submit_order(vega, MM_WALLET2.name, market_id, "SIDE_BUY", 1, 95)
|
||||
submit_order(vega, MM_WALLET.name, market_id, "SIDE_SELL", 1, 100)
|
||||
submit_order(vega, MM_WALLET2.name, market_id, "SIDE_BUY", 1, 100)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# check market state is now active and trading mode is continuous
|
||||
expect(trading_mode).to_have_text("Continuous")
|
||||
expect(market_state).to_have_text("Active")
|
||||
|
||||
# put invalid oracle to trigger market termination
|
||||
governance.submit_oracle_data(
|
||||
wallet=vega.wallet,
|
||||
payload={"trading.terminated": "true"},
|
||||
key_name=GOVERNANCE_WALLET.name,
|
||||
)
|
||||
vega.forward("60s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# market state should be changed to "Trading Terminated" because of the invalid oracle
|
||||
expect(trading_mode).to_have_text("No trading")
|
||||
expect(market_state).to_have_text("Trading Terminated")
|
||||
|
||||
# settle market
|
||||
vega.submit_termination_and_settlement_data(
|
||||
settlement_key=GOVERNANCE_WALLET.name,
|
||||
settlement_price=100,
|
||||
market_id=market_id,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# check market state is now settled
|
||||
expect(trading_mode).to_have_text("No trading")
|
||||
expect(market_state).to_have_text("Settled")
|
||||
|
||||
|
||||
""" @pytest.mark.usefixtures("page", "risk_accepted", "continuous_market")
|
||||
def test_market_closing_banners(page: Page, continuous_market, vega: VegaService):
|
||||
market_id = continuous_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
proposalID = vega.update_market_state(
|
||||
continuous_market,
|
||||
"mm",
|
||||
MarketStateUpdateType.Terminate,
|
||||
approve_proposal=False,
|
||||
vote_enactment_time = datetime.now() + timedelta(weeks=1),
|
||||
forward_time_to_enactment = False,
|
||||
price=107,
|
||||
)
|
||||
may_close_warning_pattern = r"TRADING ON MARKET BTC:DAI_2023 MAY STOP ON \d+ \w+\.\s*THERE IS OPEN PROPOSAL TO CLOSE THIS MARKET\.\nProposed final price is 107\.00 BTC\.\nView proposal"
|
||||
match_result = re.fullmatch(may_close_warning_pattern, page.locator(".grow").inner_text())
|
||||
assert match_result is not None
|
||||
|
||||
vega.update_market_state(
|
||||
continuous_market,
|
||||
"mm",
|
||||
MarketStateUpdateType.Terminate,
|
||||
approve_proposal=False,
|
||||
vote_enactment_time = datetime.now() + timedelta(weeks=1),
|
||||
forward_time_to_enactment = False,
|
||||
price=110,
|
||||
)
|
||||
|
||||
expect(page.locator(".grow")).to_have_text("Trading on Market BTC:DAI_2023 may stop. There are open proposals to close this marketView proposals")
|
||||
|
||||
governance.approve_proposal(
|
||||
proposal_id=proposalID,
|
||||
wallet=vega.wallet,
|
||||
key_name="mm"
|
||||
|
||||
)
|
||||
vega.forward("60s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
will_close_pattern = r"TRADING ON MARKET BTC:DAI_2023 WILL STOP ON \d+ \w+\nYou will no longer be able to hold a position on this market when it closes in \d+ days \d+ hours\. The final price will be 107\.00 BTC\."
|
||||
match_result = re.fullmatch(will_close_pattern, page.locator(".grow").inner_text())
|
||||
assert match_result is not None
|
||||
"""
|
111
apps/trading/e2e/tests/navigation/test_navigation.py
Normal file
111
apps/trading/e2e/tests/navigation/test_navigation.py
Normal file
@ -0,0 +1,111 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect, Locator
|
||||
|
||||
from conftest import init_page, init_vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
# we can reuse single page instance in all tests
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_network_switcher(page: Page):
|
||||
page.goto("/#/disclaimer")
|
||||
navbar = page.locator('nav[aria-label="Main"]')
|
||||
assert_network_switcher(navbar)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_navbar_pages(page: Page):
|
||||
page.goto("/#/disclaimer")
|
||||
navbar = page.locator('nav[aria-label="Main"]')
|
||||
assert_links(navbar)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_navigation_mobile(page: Page):
|
||||
page.goto("/#/disclaimer")
|
||||
page.set_viewport_size({"width": 800, "height": 1040})
|
||||
navbar = page.locator('nav[aria-label="Main"]')
|
||||
|
||||
# region navigation
|
||||
burger = navbar.get_by_test_id("navbar-mobile-burger")
|
||||
expect(burger).to_be_visible()
|
||||
burger.click()
|
||||
menu = navbar.get_by_test_id("navbar-menu-content")
|
||||
expect(menu).to_be_visible()
|
||||
assert_links(menu)
|
||||
assert_network_switcher(menu)
|
||||
menu.get_by_role("button", name="Close menu").click()
|
||||
# endregion
|
||||
|
||||
# region wallet
|
||||
wallet_button = navbar.get_by_test_id("navbar-mobile-wallet")
|
||||
expect(wallet_button).to_be_visible()
|
||||
wallet_button.click()
|
||||
dialog = page.get_by_test_id("dialog-content")
|
||||
expect(dialog.get_by_test_id("wallet-dialog-title")).to_be_visible()
|
||||
# endregion
|
||||
|
||||
|
||||
def assert_links(container: Locator):
|
||||
pages = [
|
||||
{"name": "Markets", "href": "#/markets"},
|
||||
{"name": "Trading", "href": "#/markets/"},
|
||||
{"name": "Portfolio", "href": "#/portfolio"},
|
||||
]
|
||||
|
||||
for page in pages:
|
||||
link = container.get_by_role("link", name=page["name"])
|
||||
expect(link).to_be_visible()
|
||||
expect(link).to_have_attribute("href", page["href"])
|
||||
|
||||
# False indicates external link configured by env var
|
||||
resource_pages = [
|
||||
{"name": "Docs", "href": False},
|
||||
{"name": "Give Feedback", "href": False},
|
||||
{"name": "Disclaimer", "href": "#/disclaimer"},
|
||||
]
|
||||
|
||||
container.get_by_role("button", name="Resources").click()
|
||||
|
||||
dropdown = container.get_by_test_id("navbar-content-resources")
|
||||
|
||||
for resource_page in resource_pages:
|
||||
page_name = resource_page["name"]
|
||||
page_href = resource_page["href"]
|
||||
link = dropdown.get_by_role("link", name=page_name)
|
||||
expect(link).to_be_visible()
|
||||
if not page_href:
|
||||
href = link.get_attribute("href")
|
||||
expect(link).to_have_attribute("target", "_blank")
|
||||
assert len(href) >= 0, f"href for {page_name} is empty"
|
||||
else:
|
||||
expect(link).to_have_attribute("href", page_href)
|
||||
|
||||
|
||||
def assert_network_switcher(container: Locator):
|
||||
network_switcher_trigger = container.get_by_test_id(
|
||||
"navbar-network-switcher-trigger"
|
||||
)
|
||||
# 0006-NETW-002
|
||||
expect(network_switcher_trigger).to_have_text = "Fairground testnet"
|
||||
network_switcher_trigger.click()
|
||||
dropdown = container.get_by_test_id("navbar-content-network-switcher")
|
||||
expect(dropdown).to_be_visible()
|
||||
links = dropdown.get_by_role("link")
|
||||
expect(links).to_have_count(2)
|
||||
mainnet_link = container.get_by_role("link", name="Mainnet")
|
||||
expect(mainnet_link).to_be_visible()
|
||||
# 0006-NETW-003
|
||||
expect(mainnet_link).to_have_attribute("href", "https://console.vega.xyz")
|
||||
expect(container.get_by_role("link", name="Fairground testnet")).to_be_visible()
|
64
apps/trading/e2e/tests/order/test_order_details.py
Normal file
64
apps/trading/e2e/tests/order/test_order_details.py
Normal file
@ -0,0 +1,64 @@
|
||||
import pytest
|
||||
import re
|
||||
from playwright.sync_api import expect, Page
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
|
||||
order_details = [
|
||||
("order-market-label", "Market", "order-market-value", "BTC:DAI_2023"),
|
||||
("order-side-label", "Side", "order-side-value", "Short"),
|
||||
("order-type-label", "Type", "order-type-value", "Limit"),
|
||||
("order-price-label", "Price", "order-price-value", "101.00"),
|
||||
("order-size-label", "Size", "order-size-value", "-102"),
|
||||
("order-remaining-label", "Remaining", "order-remaining-value", "-2"),
|
||||
("order-status-label", "Status", "order-status-value", "Active"),
|
||||
("order-id-label", "Order ID", "order-id-value", r"^.{10}\u2026.+Copy$", True),
|
||||
(
|
||||
"order-created-label",
|
||||
"Created",
|
||||
"order-created-value",
|
||||
r"^\d{1,2}/\d{1,2}/\d{4}, \d{1,2}:\d{2}:\d{2}$",
|
||||
True,
|
||||
),
|
||||
(
|
||||
"order-time-in-force-label",
|
||||
"Time in force",
|
||||
"order-time-in-force-value",
|
||||
"Good 'til Cancelled (GTC)",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def verify_order_label(page: Page, test_id: str, expected_text: str):
|
||||
element = page.get_by_test_id(test_id)
|
||||
expect(element).to_be_visible()
|
||||
expect(element).to_have_text(expected_text)
|
||||
|
||||
|
||||
def verify_order_value(
|
||||
page: Page, test_id: str, expected_text: str, is_regex: bool = False
|
||||
):
|
||||
element = page.get_by_test_id(test_id)
|
||||
expect(element).to_be_visible()
|
||||
if is_regex:
|
||||
actual_text = element.text_content()
|
||||
assert re.match(
|
||||
expected_text, actual_text
|
||||
), f"Expected {expected_text}, but got {actual_text}"
|
||||
else:
|
||||
expect(element).to_have_text(expected_text)
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("vega", "page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_order_details_are_correctly_displayed(
|
||||
continuous_market, vega: VegaService, page: Page
|
||||
):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
submit_order(vega, "Key 1", vega.all_markets()[0].id, "SIDE_SELL", 102, 101, 2, 1)
|
||||
page.get_by_test_id("Open").click()
|
||||
page.get_by_test_id("icon-kebab").click()
|
||||
page.get_by_test_id("view-order").click()
|
||||
for detail in order_details:
|
||||
label_id, label_text, value_id, value_text, is_regex = (*detail, False)[:5]
|
||||
verify_order_label(page, label_id, label_text)
|
||||
verify_order_value(page, value_id, value_text, is_regex)
|
191
apps/trading/e2e/tests/order/test_order_match.py
Normal file
191
apps/trading/e2e/tests/order/test_order_match.py
Normal file
@ -0,0 +1,191 @@
|
||||
import pytest
|
||||
import re
|
||||
from playwright.sync_api import expect, Page
|
||||
from vega_sim.service import VegaService
|
||||
|
||||
from playwright.sync_api import expect
|
||||
from actions.vega import submit_order
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
# Could be turned into a helper function in the future.
|
||||
def verify_data_grid(page, data_test_id, expected_pattern):
|
||||
page.get_by_test_id(data_test_id).click()
|
||||
# Required so that we can get liquidation price
|
||||
if data_test_id == "Positions":
|
||||
wait_for_graphql_response(page, "EstimatePosition")
|
||||
expect(
|
||||
page.locator(
|
||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
||||
)
|
||||
).to_be_visible()
|
||||
actual_text = page.locator(
|
||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
||||
).text_content()
|
||||
lines = actual_text.strip().split("\n")
|
||||
for expected, actual in zip(expected_pattern, lines):
|
||||
# We are using regex so that we can run tests in different timezones.
|
||||
if re.match(r"^\\d", expected): # check if it's a regex
|
||||
if re.search(expected, actual):
|
||||
logger.info(f"Matched: {expected} == {actual}")
|
||||
else:
|
||||
logger.info(f"Not Matched: {expected} != {actual}")
|
||||
raise AssertionError(f"Pattern does not match: {expected} != {actual}")
|
||||
else: # it's not a regex, so we escape it
|
||||
if re.search(re.escape(expected), actual):
|
||||
logger.info(f"Matched: {expected} == {actual}")
|
||||
else:
|
||||
logger.info(f"Not Matched: {expected} != {actual}")
|
||||
raise AssertionError(f"Pattern does not match: {expected} != {actual}")
|
||||
|
||||
|
||||
# Required so that we can get liquidation price - Could also become a helper
|
||||
def wait_for_graphql_response(page, query_name, timeout=5000):
|
||||
response_data = {}
|
||||
|
||||
def handle_response(route, request):
|
||||
if "graphql" in request.url:
|
||||
response = request.response()
|
||||
if response is not None:
|
||||
json_response = response.json()
|
||||
if json_response and "data" in json_response:
|
||||
data = json_response["data"]
|
||||
if query_name in data:
|
||||
response_data["data"] = data
|
||||
route.continue_()
|
||||
return
|
||||
route.continue_()
|
||||
|
||||
# Register the route handler
|
||||
page.route("**", handle_response)
|
||||
|
||||
# Wait for the response data to be populated
|
||||
page.wait_for_timeout(timeout)
|
||||
|
||||
# Unregister the route handler
|
||||
page.unroute("**", handle_response)
|
||||
|
||||
|
||||
def submit_order(vega, wallet_name, market_id, side, volume, price):
|
||||
vega.submit_order(
|
||||
trading_key=wallet_name,
|
||||
market_id=market_id,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side=side,
|
||||
volume=volume,
|
||||
price=price,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"vega", "page", "opening_auction_market", "auth", "risk_accepted"
|
||||
)
|
||||
def test_limit_order_trade_open_order(
|
||||
opening_auction_market, vega: VegaService, page: Page
|
||||
):
|
||||
market_id = opening_auction_market
|
||||
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 1, 110)
|
||||
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
|
||||
# Assert that the user order is displayed on the orderbook
|
||||
orderbook_trade = page.get_by_test_id("price-11000000").nth(1)
|
||||
# 6003-ORDB-001
|
||||
# 6003-ORDB-002
|
||||
expect(orderbook_trade).to_be_visible()
|
||||
|
||||
expected_open_order = [
|
||||
"BTC:DAI_2023",
|
||||
"+1",
|
||||
"Limit",
|
||||
"Active",
|
||||
"0/1",
|
||||
"110.00",
|
||||
"Good 'til Cancelled (GTC)",
|
||||
r"\d{1,2}/\d{1,2}/\d{4},\s*\d{1,2}:\d{2}:\d{2}\s*(?:AM|PM)",
|
||||
"-",
|
||||
]
|
||||
logger.info("Assert Open orders:")
|
||||
verify_data_grid(page, "Open", expected_open_order)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_limit_order_trade_open_position(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
|
||||
primary_id = "stack-cell-primary"
|
||||
secondary_id = "stack-cell-secondary"
|
||||
|
||||
position = {
|
||||
"market_code": "BTC:DAI_2023",
|
||||
"settlement_asset": "tDAI",
|
||||
"product_type": "Futr",
|
||||
"size": "+1",
|
||||
"notional": "107.50",
|
||||
"average_entry_price": "107.50",
|
||||
"mark_price": "107.50",
|
||||
"margin": "8.50269",
|
||||
"leverage": "1.0x",
|
||||
"liquidation": "0.00",
|
||||
"realised_pnl": "0.00",
|
||||
"unrealised_pnl": "0.00",
|
||||
}
|
||||
|
||||
tab = page.get_by_test_id("tab-positions")
|
||||
table = tab.locator(".ag-center-cols-container")
|
||||
|
||||
# 7004-POSI-001
|
||||
# 7004-POSI-002
|
||||
|
||||
market = table.locator("[col-id='marketCode']")
|
||||
expect(market.get_by_test_id(primary_id)).to_have_text(position["market_code"])
|
||||
expect(market.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["settlement_asset"] + position["product_type"]
|
||||
)
|
||||
|
||||
size_and_notional = table.locator("[col-id='openVolume']")
|
||||
expect(size_and_notional.get_by_test_id(primary_id)).to_have_text(position["size"])
|
||||
expect(size_and_notional.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["notional"]
|
||||
)
|
||||
|
||||
entry_and_mark = table.locator("[col-id='markPrice']")
|
||||
expect(entry_and_mark.get_by_test_id(primary_id)).to_have_text(
|
||||
position["average_entry_price"]
|
||||
)
|
||||
expect(entry_and_mark.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["mark_price"]
|
||||
)
|
||||
|
||||
margin_and_leverage = table.locator("[col-id='margin']")
|
||||
expect(margin_and_leverage.get_by_test_id(primary_id)).to_have_text(
|
||||
position["margin"]
|
||||
)
|
||||
expect(margin_and_leverage.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["leverage"]
|
||||
)
|
||||
|
||||
liquidation = table.locator("[col-id='liquidationPrice']")
|
||||
expect(liquidation.get_by_test_id("liquidation-price")).to_have_text(
|
||||
position["liquidation"]
|
||||
)
|
||||
|
||||
realisedPNL = table.locator("[col-id='realisedPNL']")
|
||||
expect(realisedPNL).to_have_text(position["realised_pnl"])
|
||||
|
||||
unrealisedPNL = table.locator("[col-id='unrealisedPNL']")
|
||||
expect(unrealisedPNL).to_have_text(position["unrealised_pnl"])
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_limit_order_trade_order_trade_away(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
# Assert that the order is no longer on the orderbook
|
||||
page.get_by_test_id("Orderbook").click()
|
||||
price_element = page.get_by_test_id("price-11000000").nth(1)
|
||||
# 6003-ORDB-010
|
||||
expect(price_element).to_be_hidden()
|
414
apps/trading/e2e/tests/order/test_order_status.py
Normal file
414
apps/trading/e2e/tests/order/test_order_status.py
Normal file
@ -0,0 +1,414 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService, PeggedOrder
|
||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
||||
from fixtures.market import setup_continuous_market, setup_simple_market
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
order_tab = "tab-orders"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def markets(vega: VegaService):
|
||||
market_1 = setup_continuous_market(
|
||||
vega,
|
||||
custom_market_name="market-1",
|
||||
)
|
||||
market_2 = setup_continuous_market(
|
||||
vega,
|
||||
custom_market_name="market-2",
|
||||
)
|
||||
market_3 = setup_continuous_market(
|
||||
vega,
|
||||
custom_market_name="market-3",
|
||||
)
|
||||
market_4 = setup_continuous_market(
|
||||
vega,
|
||||
custom_market_name="market-4",
|
||||
)
|
||||
market_5 = setup_simple_market(
|
||||
vega,
|
||||
custom_market_name="market-5",
|
||||
)
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_1,
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=100,
|
||||
price=130,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_1,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=100,
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_1,
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=100,
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_1,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=1e10,
|
||||
price=130,
|
||||
wait=False,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_2,
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_BUY",
|
||||
volume=100,
|
||||
price=104,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_3,
|
||||
time_in_force="TIME_IN_FORCE_GTT",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=10,
|
||||
price=120,
|
||||
expires_at=vega.get_blockchain_time() + 5 * 1e9,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
market_id=market_4,
|
||||
trading_key="Key 1",
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_MID", offset=5),
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=20,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
market_id=market_4,
|
||||
trading_key="Key 1",
|
||||
side="SIDE_BUY",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_BEST_BID", offset=10),
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=40,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
market_id=market_4,
|
||||
trading_key="Key 1",
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_BEST_ASK", offset=15),
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
market_id=market_5,
|
||||
trading_key="Key 1",
|
||||
side="SIDE_SELL",
|
||||
order_type="TYPE_LIMIT",
|
||||
pegged_order=PeggedOrder(reference="PEGGED_REFERENCE_BEST_ASK", offset=15),
|
||||
wait=False,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_2,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=10,
|
||||
price=150,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_2,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_SELL",
|
||||
volume=10,
|
||||
price=160,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=market_3,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_BUY",
|
||||
volume=10,
|
||||
price=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto("/")
|
||||
page.get_by_test_id("All").click()
|
||||
yield page
|
||||
|
||||
|
||||
# close toast that is still opened after test
|
||||
@pytest.fixture(autouse=True)
|
||||
def after_each(page: Page):
|
||||
yield
|
||||
if page.get_by_test_id("toast-close").is_visible():
|
||||
page.get_by_test_id("toast-close").click()
|
||||
|
||||
|
||||
# 7002-SORD-040 (as all the tests are about status)
|
||||
|
||||
|
||||
def test_order_sorted(page: Page):
|
||||
# 7003-MORD-002
|
||||
orders_update_date = page.locator(
|
||||
'.ag-center-cols-container [col-id="updatedAt"]'
|
||||
).all_text_contents()
|
||||
|
||||
orders_update_date_sorted = sorted(orders_update_date, reverse=True)
|
||||
|
||||
assert all([a == b for a, b in zip(orders_update_date, orders_update_date_sorted)])
|
||||
|
||||
|
||||
def test_order_status_active(page: Page):
|
||||
# 7002-SORD-041
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-2Futr" + "0" + "-10" + "Limit" + "Active" + "150.00" + "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_status_expired(page: Page):
|
||||
# 7002-SORD-042
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-3Futr" + "0" + "-10" + "Limit" + "Expired" + "120.00" + "GTT:"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_Stopped(page: Page):
|
||||
# 7002-SORD-044
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-1Futr" + "0" + "-100" + "Limit" + "Stopped" + "130.00" + "IOC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_partially_filled(page: Page):
|
||||
# 7002-SORD-045
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-2Futr" + "99" + "+100" + "Limit" + "Partially Filled" + "104.00" + "IOC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_filled(page: Page):
|
||||
# 7002-SORD-046
|
||||
# 7003-MORD-020
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-1Futr" + "100" + "-100" + "Limit" + "Filled" + "88.00" + "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_rejected(page: Page):
|
||||
# 7002-SORD-047
|
||||
# 7003-MORD-018
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-1Futr"
|
||||
+ "0"
|
||||
+ "-10,000,000,000"
|
||||
+ "Limit"
|
||||
+ "Rejected: Margin check failed"
|
||||
+ "130.00"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_parked(page: Page):
|
||||
# 7002-SORD-048
|
||||
# 7003-MORD-016
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-5Futr"
|
||||
+ "0"
|
||||
+ "-60"
|
||||
+ "Ask + 15.00 Peg limit"
|
||||
+ "Parked"
|
||||
+ "0.00"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_pegged_ask(page: Page):
|
||||
# 7003-MORD-016
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-4Futr"
|
||||
+ "0"
|
||||
+ "-60"
|
||||
+ "Ask + 15.00 Peg limit"
|
||||
+ "Active"
|
||||
+ "125.00"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_pegged_bid(page: Page):
|
||||
# 7003-MORD-016
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-4Futr"
|
||||
+ "0"
|
||||
+ "+40"
|
||||
+ "Bid - 10.00 Peg limit"
|
||||
+ "Active"
|
||||
+ "85.00"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_status_pegged_mid(page: Page):
|
||||
# 7003-MORD-016
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-4Futr"
|
||||
+ "0"
|
||||
+ "+20"
|
||||
+ "Mid - 5.00 Peg limit"
|
||||
+ "Active"
|
||||
+ "97.50"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_amend_order(vega: VegaService, page: Page):
|
||||
# 7002-SORD-053
|
||||
# 7003-MORD-012
|
||||
# 7003-MORD-014
|
||||
# 7003-MORD-015
|
||||
page.get_by_test_id("edit").nth(1).click()
|
||||
page.locator("#limitPrice").fill("170")
|
||||
page.locator("#size").fill("15")
|
||||
page.get_by_role("button", name="Update").click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-2Futr" + "0" + "-15" + "Limit" + "Active" + "170.00" + "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_cancel_single_order(vega: VegaService, page: Page):
|
||||
# 7003-MORD-009
|
||||
# 7003-MORD-010
|
||||
# 7003-MORD-011
|
||||
# 7002-SORD-043
|
||||
page.get_by_test_id("cancel").first.click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
expect(page.get_by_test_id(order_tab)).to_contain_text(
|
||||
"market-3Futr" + "0" + "+10" + "Limit" + "Cancelled" + "60.00" + "GTC"
|
||||
)
|
||||
|
||||
|
||||
def test_order_cancel_all_orders(vega: VegaService, page: Page):
|
||||
# 7003-MORD-009
|
||||
# 7003-MORD-010
|
||||
# 7003-MORD-011
|
||||
# 7002-SORD-043
|
||||
|
||||
page.get_by_test_id("cancelAll").click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
expect(page.get_by_test_id("cancelAll")).not_to_be_visible()
|
||||
expect(page.get_by_test_id("cancel")).not_to_be_visible()
|
||||
expect(
|
||||
page.locator('.ag-cell[col-id="status"]', has_text="Cancelled")
|
||||
).to_have_count(7)
|
272
apps/trading/e2e/tests/orderbook/test_orderbook.py
Normal file
272
apps/trading/e2e/tests/orderbook/test_orderbook.py
Normal file
@ -0,0 +1,272 @@
|
||||
import pytest
|
||||
from collections import namedtuple
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from typing import List
|
||||
from actions.vega import submit_order, submit_liquidity, submit_multiple_orders
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_simple_market
|
||||
|
||||
# Defined namedtuples
|
||||
WalletConfig = namedtuple("WalletConfig", ["name", "passphrase"])
|
||||
|
||||
# Wallet Configurations
|
||||
MM_WALLET = WalletConfig("mm", "pin")
|
||||
MM_WALLET2 = WalletConfig("mm2", "pin2")
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def setup_market(vega):
|
||||
market_id = setup_simple_market(vega)
|
||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||
submit_multiple_orders(
|
||||
vega,
|
||||
MM_WALLET.name,
|
||||
market_id,
|
||||
"SIDE_SELL",
|
||||
[[10, 130.005], [3, 130], [7, 120], [5, 110], [2, 105]],
|
||||
)
|
||||
submit_multiple_orders(
|
||||
vega,
|
||||
MM_WALLET2.name,
|
||||
market_id,
|
||||
"SIDE_BUY",
|
||||
[[10, 69.995], [5, 70], [5, 85], [3, 90], [3, 95]],
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return [
|
||||
vega,
|
||||
market_id,
|
||||
]
|
||||
|
||||
|
||||
# these values don't align with the multiple orders above as
|
||||
# creating a trade triggers the liquidity provision
|
||||
orderbook_content = [
|
||||
[130.00500, 10, 94],
|
||||
[130.00000, 3, 84],
|
||||
[120.00000, 7, 81],
|
||||
[110.00000, 5, 74],
|
||||
[105.00000, 2, 69],
|
||||
[101.00000, 67, 67],
|
||||
# mid
|
||||
[99.00000, 102, 102],
|
||||
[95.00000, 3, 105],
|
||||
[90.00000, 3, 108],
|
||||
[85.00000, 5, 113],
|
||||
[70.00000, 5, 118],
|
||||
[69.99500, 10, 128],
|
||||
]
|
||||
|
||||
|
||||
def verify_orderbook_grid(
|
||||
page: Page, content: List[List[float]], last_trade_price: float = False
|
||||
):
|
||||
rows = page.locator("[data-testid$=-rows-container]").all()
|
||||
for row_index, content_row in enumerate(content):
|
||||
cells = rows[row_index].locator("button").all()
|
||||
for cell_index, content_cell in enumerate(content_row):
|
||||
assert float(cells[cell_index].text_content()) == content_cell
|
||||
|
||||
|
||||
def verify_prices_descending(page: Page):
|
||||
prices_locator = page.get_by_test_id("tab-orderbook").locator(
|
||||
'[data-testid^="price-"]'
|
||||
)
|
||||
prices_locator.first.wait_for(state="visible")
|
||||
prices = [float(price.text_content()) for price in prices_locator.all()]
|
||||
assert prices == sorted(prices, reverse=True)
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_orderbook_grid_content(setup_market, page: Page):
|
||||
vega = setup_market[0]
|
||||
market_id = setup_market[1]
|
||||
|
||||
# Create a so that lastTradePrice is shown in the mid section
|
||||
# of the book
|
||||
matching_order = [1, 100]
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET.name,
|
||||
market_id,
|
||||
"SIDE_SELL",
|
||||
matching_order[0],
|
||||
matching_order[1],
|
||||
)
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET2.name,
|
||||
market_id,
|
||||
"SIDE_BUY",
|
||||
matching_order[0],
|
||||
matching_order[1],
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# 6003-ORDB-001
|
||||
# 6003-ORDB-002
|
||||
# 6003-ORDB-003
|
||||
# 6003-ORDB-004
|
||||
# 6003-ORDB-005
|
||||
# 6003-ORDB-006
|
||||
# 6003-ORDB-007
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
|
||||
page.locator("[data-testid=Orderbook]").click()
|
||||
|
||||
# 6003-ORDB-013
|
||||
assert (
|
||||
float(page.locator("[data-testid*=last-traded]").text_content())
|
||||
== matching_order[1]
|
||||
)
|
||||
|
||||
# 6003-ORDB-011
|
||||
# get the spread text trimming off the parentheses on either end
|
||||
spread_text = page.locator("[data-testid=spread]").text_content()[1:-1]
|
||||
assert (
|
||||
# TODO: figure out how to not have hardcoded value
|
||||
spread_text
|
||||
== "2.00"
|
||||
)
|
||||
|
||||
verify_orderbook_grid(page, orderbook_content)
|
||||
verify_prices_descending(page)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_orderbook_resolution_change(setup_market, page: Page):
|
||||
market_id = setup_market[1]
|
||||
# 6003-ORDB-008
|
||||
orderbook_content_0_00 = [
|
||||
[130.01, 10, 94],
|
||||
[130.00, 3, 84],
|
||||
[120.00, 7, 81],
|
||||
[110.00, 5, 74],
|
||||
[105.00, 2, 69],
|
||||
[101.00, 67, 67],
|
||||
# mid
|
||||
[99.00, 102, 102],
|
||||
[95.00, 3, 105],
|
||||
[90.00, 3, 108],
|
||||
[85.00, 5, 113],
|
||||
[70.00, 15, 128],
|
||||
]
|
||||
|
||||
orderbook_content_10 = [
|
||||
[130, 13, 94],
|
||||
[120, 7, 81],
|
||||
[110, 7, 74],
|
||||
[100, 67, 67],
|
||||
# mid
|
||||
[100, 105, 105],
|
||||
[90, 8, 113],
|
||||
[70, 15, 128],
|
||||
]
|
||||
|
||||
orderbook_content_100 = [
|
||||
[100, 94, 94],
|
||||
# mid
|
||||
[100, 128, 128],
|
||||
]
|
||||
|
||||
resolutions = [
|
||||
["0.00", orderbook_content_0_00],
|
||||
["10", orderbook_content_10],
|
||||
["100", orderbook_content_100],
|
||||
]
|
||||
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
# temporary skip
|
||||
# for resolution in resolutions:
|
||||
# page.get_by_test_id("resolution").click()
|
||||
# page.get_by_role("menu").get_by_text(resolution[0], exact=True).click()
|
||||
# verify_orderbook_grid(page, resolution[1])
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_orderbook_price_size_copy(setup_market, page: Page):
|
||||
market_id = setup_market[1]
|
||||
# 6003-ORDB-009
|
||||
prices = page.get_by_test_id("tab-orderbook").locator('[data-testid^="price-"]')
|
||||
volumes = page.get_by_test_id("tab-orderbook").locator('[data-testid*="-vol-"]')
|
||||
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
prices.first.wait_for(state="visible")
|
||||
|
||||
for price in prices.all():
|
||||
price.click()
|
||||
expect(page.get_by_test_id("order-price")).to_have_value(price.text_content())
|
||||
|
||||
for volume in volumes.all():
|
||||
volume.click()
|
||||
expect(page.get_by_test_id("order-size")).to_have_value(volume.text_content())
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_orderbook_price_movement(setup_market, page: Page):
|
||||
vega = setup_market[0]
|
||||
market_id = setup_market[1]
|
||||
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.locator("[data-testid=Orderbook]").click()
|
||||
|
||||
book_el = page.locator("[data-testid=orderbook-grid-element]")
|
||||
|
||||
# no arrow shown on load
|
||||
expect(book_el.locator("[data-testid^=icon-arrow]")).not_to_be_attached()
|
||||
|
||||
matching_order_1 = [1, 101]
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET2.name,
|
||||
market_id,
|
||||
"SIDE_BUY",
|
||||
matching_order_1[0],
|
||||
matching_order_1[1],
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# 6003-ORDB-013
|
||||
expect(book_el.locator("[data-testid=icon-arrow-up]")).to_be_attached()
|
||||
assert (
|
||||
float(page.locator("[data-testid*=last-traded]").text_content())
|
||||
== matching_order_1[1]
|
||||
)
|
||||
|
||||
matching_order_2 = [1, 99]
|
||||
submit_order(
|
||||
vega,
|
||||
MM_WALLET2.name,
|
||||
market_id,
|
||||
"SIDE_SELL",
|
||||
matching_order_2[0],
|
||||
matching_order_2[1],
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
expect(book_el.locator("[data-testid=icon-arrow-down]")).to_be_attached()
|
||||
|
||||
assert (
|
||||
float(page.locator("[data-testid*=last-traded]").text_content())
|
||||
== matching_order_2[1]
|
||||
)
|
143
apps/trading/e2e/tests/pnl/test_pnl.py
Normal file
143
apps/trading/e2e/tests/pnl/test_pnl.py
Normal file
@ -0,0 +1,143 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
|
||||
|
||||
def wait_for_graphql_response(page, query_name, timeout=5000):
|
||||
response_data = {}
|
||||
|
||||
def handle_response(route, request):
|
||||
if "graphql" in request.url:
|
||||
response = request.response()
|
||||
if response is not None:
|
||||
json_response = response.json()
|
||||
if json_response and "data" in json_response:
|
||||
data = json_response["data"]
|
||||
if query_name in data:
|
||||
response_data["data"] = data
|
||||
route.continue_()
|
||||
return
|
||||
route.continue_()
|
||||
|
||||
# Register the route handler
|
||||
page.route("**", handle_response)
|
||||
|
||||
# Wait for the response data to be populated
|
||||
page.wait_for_timeout(timeout)
|
||||
|
||||
# Unregister the route handler
|
||||
page.unroute("**", handle_response)
|
||||
|
||||
|
||||
def check_pnl_color_value(element, expected_color, expected_value):
|
||||
color = element.evaluate("element => getComputedStyle(element).color")
|
||||
value = element.inner_text()
|
||||
assert color == expected_color, f"Unexpected color: {color}"
|
||||
assert value == expected_value, f"Unexpected value: {value}"
|
||||
|
||||
@pytest.mark.usefixtures("vega", "page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_pnl(continuous_market, vega: VegaService, page: Page):
|
||||
page.set_viewport_size({"width": 1748, "height": 977})
|
||||
submit_order(vega, "Key 1", continuous_market, "SIDE_BUY", 1, 104.50000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
# Loss Trading unrealised
|
||||
row = (
|
||||
page.get_by_test_id("tab-positions")
|
||||
.locator(".ag-center-cols-container .ag-row")
|
||||
.nth(0)
|
||||
)
|
||||
realised_pnl = row.locator("[col-id='realisedPNL']")
|
||||
unrealised_pnl = row.locator("[col-id='unrealisedPNL']")
|
||||
|
||||
check_pnl_color_value(realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(236, 0, 60)", "-4.00")
|
||||
|
||||
# profit Trading unrealised
|
||||
page.get_by_test_id("manage-vega-wallet").click()
|
||||
page.locator('[role="menuitemradio"] >> .mr-2.uppercase').nth(1).click(position={ "x": 0, "y": 0}, force=True)
|
||||
check_pnl_color_value(realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(1, 145, 75)", "4.00")
|
||||
|
||||
# neutral Trading unrealised
|
||||
page.locator('[role="menuitemradio"] >> .mr-2.uppercase').nth(2).click(position={ "x": 0, "y": 0}, force=True)
|
||||
check_pnl_color_value(realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
# Portfolio Unrealised
|
||||
page.get_by_test_id("manage-vega-wallet").click(force=True)
|
||||
page.get_by_role("link", name="Portfolio").click()
|
||||
page.get_by_test_id("Positions").click()
|
||||
wait_for_graphql_response(page, "EstimatePosition")
|
||||
page.wait_for_selector(
|
||||
'[data-testid="tab-positions"] .ag-center-cols-container .ag-row',
|
||||
state="visible",
|
||||
)
|
||||
|
||||
key_1 = page.query_selector(
|
||||
'//div[@role="row" and .//div[@col-id="partyId"]/div/span[text()="Key 1"]]'
|
||||
)
|
||||
key_mm = page.query_selector(
|
||||
'//div[@role="row" and .//div[@col-id="partyId"]/div/span[text()="mm"]]'
|
||||
)
|
||||
key_mm2 = page.query_selector(
|
||||
'//div[@role="row" and .//div[@col-id="partyId"]/div/span[text()="mm2"]]'
|
||||
)
|
||||
|
||||
key_1_unrealised_pnl = key_1.query_selector('xpath=./div[@col-id="unrealisedPNL"]')
|
||||
key_1_realised_pnl = key_1.query_selector('xpath=./div[@col-id="realisedPNL"]')
|
||||
key_mm_unrealised_pnl = key_mm.query_selector('xpath=./div[@col-id="unrealisedPNL"]')
|
||||
key_mm_realised_pnl = key_mm.query_selector('xpath=./div[@col-id="realisedPNL"]')
|
||||
key_mm2_unrealised_pnl = key_mm2.query_selector('xpath=./div[@col-id="unrealisedPNL"]')
|
||||
key_mm2_realised_pnl = key_mm2.query_selector('xpath=./div[@col-id="realisedPNL"]')
|
||||
check_pnl_color_value(key_1_realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(key_1_unrealised_pnl, "rgb(236, 0, 60)", "-4.00")
|
||||
|
||||
check_pnl_color_value(key_mm_realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(key_mm_unrealised_pnl, "rgb(1, 145, 75)", "4.00")
|
||||
|
||||
check_pnl_color_value(key_mm2_realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(key_mm2_unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
submit_order(vega, "Key 1", continuous_market, "SIDE_SELL", 2, 101.50000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
wait_for_graphql_response(page, "EstimatePosition")
|
||||
|
||||
check_pnl_color_value(key_1_realised_pnl, "rgb(236, 0, 60)", "-8.00")
|
||||
check_pnl_color_value(key_1_unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
check_pnl_color_value(key_mm_realised_pnl, "rgb(1, 145, 75)", "8.00")
|
||||
check_pnl_color_value(key_mm_unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
check_pnl_color_value(key_mm2_realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(key_mm2_unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
page.get_by_role("link", name="Trading").click()
|
||||
|
||||
row = (
|
||||
page.get_by_test_id("tab-positions")
|
||||
.locator(".ag-center-cols-container .ag-row")
|
||||
.nth(0)
|
||||
)
|
||||
realised_pnl = row.locator("[col-id='realisedPNL']")
|
||||
unrealised_pnl = row.locator("[col-id='unrealisedPNL']")
|
||||
|
||||
# neutral trading realised
|
||||
check_pnl_color_value(realised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
# profit trading realised
|
||||
page.get_by_test_id("manage-vega-wallet").click()
|
||||
page.locator('[role="menuitemradio"] >> .mr-2.uppercase').nth(1).click(position={ "x": 0, "y": 0}, force=True)
|
||||
check_pnl_color_value(realised_pnl, "rgb(1, 145, 75)", "8.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
||||
|
||||
# loss trading realised
|
||||
page.locator('[role="menuitemradio"] >> .mr-2.uppercase').nth(0).click(position={ "x": 0, "y": 0}, force=True)
|
||||
check_pnl_color_value(realised_pnl, "rgb(236, 0, 60)", "-8.00")
|
||||
check_pnl_color_value(unrealised_pnl, "rgb(0, 0, 0)", "0.00")
|
31
apps/trading/e2e/tests/portfolio/test_ledger_entries.py
Normal file
31
apps/trading/e2e/tests/portfolio/test_ledger_entries.py
Normal file
@ -0,0 +1,31 @@
|
||||
import os
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted", "continuous_market")
|
||||
def test_ledger_entries_downloads(page: Page):
|
||||
page.goto("/#/portfolio")
|
||||
page.get_by_test_id("Ledger entries").click()
|
||||
expect(page.get_by_test_id("ledger-download-button")).to_be_enabled()
|
||||
# 7007-LEEN-001
|
||||
page.get_by_test_id("ledger-download-button").click()
|
||||
#7007-LEEN-009
|
||||
expect(page.get_by_test_id("toast-content")).to_contain_text(("Your file is ready"))
|
||||
# Get the user's Downloads directory
|
||||
downloads_directory = os.path.expanduser("~") + "/Downloads/"
|
||||
# Start waiting for the download
|
||||
with page.expect_download() as download_info:
|
||||
# Perform the action that initiates download
|
||||
page.get_by_role("link", name="Get file here").click()
|
||||
|
||||
|
||||
download = download_info.value
|
||||
# Wait for the download process to complete and save the downloaded file in the Downloads directory
|
||||
download.save_as(os.path.join(downloads_directory, download.suggested_filename))
|
||||
|
||||
# Verify the download by asserting that the file exists
|
||||
downloaded_file_path = os.path.join(downloads_directory, download.suggested_filename)
|
||||
assert os.path.exists(downloaded_file_path), f"Download failed! File not found at: {downloaded_file_path}"
|
||||
|
51
apps/trading/e2e/tests/positions/test_collateral.py
Normal file
51
apps/trading/e2e/tests/positions/test_collateral.py
Normal file
@ -0,0 +1,51 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
TOOLTIP_LABEL = "margin-health-tooltip-label"
|
||||
TOOLTIP_VALUE = "margin-health-tooltip-value"
|
||||
COL_ID_USED = ".ag-center-cols-container [col-id='used'] .ag-cell-value"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def continuous_market(vega: VegaService):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_usage_breakdown(continuous_market, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("Collateral").click()
|
||||
page.locator(".ag-floating-top-container .ag-row [col-id='used']").click()
|
||||
usage_breakdown = page.get_by_test_id('usage-breakdown')
|
||||
|
||||
# Verify headers
|
||||
headers = ['Market', 'Account type', 'Balance', 'Margin health']
|
||||
ag_headers = usage_breakdown.locator('.ag-header-cell-text').element_handles()
|
||||
for i, header_element in enumerate(ag_headers):
|
||||
header_text = header_element.text_content()
|
||||
assert header_text == headers[i]
|
||||
|
||||
# Other expectations
|
||||
expect(usage_breakdown.locator('[class="mb-2 text-sm"]')).to_have_text("You have 1,000,000.00 tDAI in total.")
|
||||
expect(usage_breakdown.locator(COL_ID_USED).first).to_have_text("8.50269 (0%)")
|
||||
expect(usage_breakdown.locator(COL_ID_USED).nth(1)).to_have_text("999,991.49731 (99%)")
|
||||
|
||||
# Maintenance Level
|
||||
expect(usage_breakdown.locator(".ag-center-cols-container [col-id='market.id'] .ag-cell-value").first).to_have_text("2.85556 above maintenance level")
|
||||
|
||||
# Margin health tooltip
|
||||
usage_breakdown.get_by_test_id("margin-health-chart-track").hover()
|
||||
tooltip_data = [("maintenance level", "5.64713"), ("search level", "6.21184"), ("initial level", "8.47069"), ("balance", "8.50269"), ("release level", "9.60012")]
|
||||
|
||||
for index, (label, value) in enumerate(tooltip_data):
|
||||
expect(page.get_by_test_id(TOOLTIP_LABEL).nth(index)).to_have_text(label)
|
||||
expect(page.get_by_test_id(TOOLTIP_VALUE).nth(index)).to_have_text(value)
|
||||
|
||||
|
||||
page.get_by_test_id('dialog-close').click()
|
29
apps/trading/e2e/tests/positions/test_positions.py
Normal file
29
apps/trading/e2e/tests/positions/test_positions.py
Normal file
@ -0,0 +1,29 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from fixtures.market import (
|
||||
setup_continuous_market,
|
||||
)
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_closed_market_position(vega: VegaService, page: Page):
|
||||
market_id = setup_continuous_market(vega)
|
||||
|
||||
vega.submit_termination_and_settlement_data(
|
||||
settlement_key="FJMKnwfZdd48C8NqvYrG",
|
||||
settlement_price=110,
|
||||
market_id=market_id,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
expect(page.locator(".ag-overlay-panel")).to_have_text("No positions")
|
||||
page.get_by_test_id("open-transfer").click()
|
||||
tab = page.get_by_test_id("tab-positions")
|
||||
table = tab.locator(".ag-center-cols-container")
|
||||
market = table.locator("[col-id='marketCode']")
|
||||
expect(market.get_by_test_id("stack-cell-primary")).to_have_text("BTC:DAI_2023")
|
||||
page.get_by_test_id("open-transfer").click()
|
||||
expect(page.locator(".ag-overlay-panel")).to_have_text("No positions")
|
||||
|
61
apps/trading/e2e/tests/settings/test_settings.py
Normal file
61
apps/trading/e2e/tests/settings/test_settings.py
Normal file
@ -0,0 +1,61 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
from conftest import init_vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_share_usage_data(page: Page):
|
||||
page.goto("/")
|
||||
# page.get_by_test_id("icon-cross").click()
|
||||
page.get_by_test_id("Settings").click()
|
||||
telemetry_switch = page.locator("#switch-settings-telemetry-switch")
|
||||
expect(telemetry_switch).to_have_attribute("data-state", "unchecked")
|
||||
|
||||
telemetry_switch.click()
|
||||
expect(telemetry_switch).to_have_attribute("data-state", "checked")
|
||||
page.reload()
|
||||
page.get_by_test_id("Settings").click()
|
||||
expect(telemetry_switch).to_have_attribute("data-state", "unchecked")
|
||||
|
||||
telemetry_switch.click()
|
||||
expect(telemetry_switch).to_have_attribute("data-state", "checked")
|
||||
page.reload()
|
||||
page.get_by_test_id("Settings").click()
|
||||
expect(telemetry_switch).to_have_attribute("data-state", "unchecked")
|
||||
|
||||
|
||||
# Define a mapping of icon selectors to toast selectors
|
||||
ICON_TO_TOAST = {
|
||||
'aria-label="arrow-top-left icon"': 'class="group absolute z-20 top-0 left-0 max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
'aria-label="arrow-up icon"': 'class="group absolute z-20 top-0 left-[50%] translate-x-[-50%] max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
'aria-label="arrow-top-right icon"': 'class="group absolute z-20 top-0 right-0 max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
'aria-label="arrow-bottom-left icon"': 'class="group absolute z-20 bottom-0 left-0 max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
'aria-label="arrow-down icon"': 'class="group absolute z-20 bottom-0 left-[50%] translate-x-[-50%] max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
'aria-label="arrow-bottom-right icon"': 'class="group absolute z-20 bottom-0 right-0 max-w-full max-h-full overflow-x-hidden overflow-y-auto p-4"',
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_toast_positions(page: Page):
|
||||
page.goto("/")
|
||||
page.get_by_test_id("Settings").click()
|
||||
for icon_selector, toast_selector in ICON_TO_TOAST.items():
|
||||
# Click the icon
|
||||
page.click(f"[{icon_selector}]")
|
||||
# Expect that the toast is displayed
|
||||
expect(page.locator(f"[{toast_selector}]")).to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_dark_mode(page: Page):
|
||||
page.goto("/")
|
||||
page.get_by_test_id("Settings").click()
|
||||
expect(page.locator("html")).not_to_have_attribute("class", "dark")
|
||||
page.locator("#switch-settings-theme-switch").click()
|
||||
expect(page.locator("html")).to_have_attribute("class", "dark")
|
@ -0,0 +1,47 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from fixtures.market import setup_continuous_market, setup_simple_successor_market
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@pytest.mark.usefixtures("vega")
|
||||
def successor_market(vega: VegaService):
|
||||
parent_market_id = setup_continuous_market(vega)
|
||||
tdai_id = vega.find_asset_id(symbol="tDAI")
|
||||
successor_market_id = setup_simple_successor_market(
|
||||
vega, parent_market_id, tdai_id, "successor_market"
|
||||
)
|
||||
vega.submit_termination_and_settlement_data(
|
||||
settlement_key="FJMKnwfZdd48C8NqvYrG",
|
||||
settlement_price=110,
|
||||
market_id=parent_market_id,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
return successor_market_id
|
||||
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "risk_accepted")
|
||||
def test_succession_line(page: Page, successor_market):
|
||||
page.goto(f"/#/markets/{successor_market}")
|
||||
page.get_by_test_id("Info").click()
|
||||
page.get_by_text("Succession line").click()
|
||||
|
||||
expect(page.get_by_test_id("succession-line-item").first).to_contain_text(
|
||||
"BTC:DAI_2023BTC:DAI_2023"
|
||||
)
|
||||
expect(
|
||||
page.get_by_test_id("succession-line-item").first.get_by_role("link")
|
||||
).to_be_attached
|
||||
expect(page.get_by_test_id("succession-line-item").last).to_contain_text(
|
||||
"successor_marketsuccessor_market"
|
||||
)
|
||||
expect(
|
||||
page.get_by_test_id("succession-line-item").last.get_by_role("link")
|
||||
).to_be_attached
|
||||
expect(
|
||||
page.get_by_test_id("succession-line-item").last.get_by_test_id("icon-bullet")
|
||||
).to_be_visible
|
106
apps/trading/e2e/tests/trade_history/test_trade_history.py
Normal file
106
apps/trading/e2e/tests/trade_history/test_trade_history.py
Normal file
@ -0,0 +1,106 @@
|
||||
import pytest
|
||||
import re
|
||||
from playwright.sync_api import expect
|
||||
from actions.vega import submit_order
|
||||
from conftest import init_vega
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
# Could be turned into a helper function in the future.
|
||||
def verify_data_grid(page, data_test_id, expected_pattern):
|
||||
page.get_by_test_id(data_test_id).click()
|
||||
# Required so that we can get liquidation price
|
||||
if data_test_id == "Positions":
|
||||
wait_for_graphql_response(page, "EstimatePosition")
|
||||
expect(
|
||||
page.locator(
|
||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container .ag-row-first'
|
||||
)
|
||||
).to_be_visible()
|
||||
actual_text = page.locator(
|
||||
f'[data-testid^="tab-{data_test_id.lower()}"] >> .ag-center-cols-container'
|
||||
).text_content()
|
||||
lines = actual_text.strip().split("\n")
|
||||
for expected, actual in zip(expected_pattern, lines):
|
||||
# We are using regex so that we can run tests in different timezones.
|
||||
if re.match(r"^\\d", expected): # check if it's a regex
|
||||
if re.search(expected, actual):
|
||||
logger.info(f"Matched: {expected} == {actual}")
|
||||
else:
|
||||
logger.info(f"Not Matched: {expected} != {actual}")
|
||||
raise AssertionError(f"Pattern does not match: {expected} != {actual}")
|
||||
else: # it's not a regex, so we escape it
|
||||
if re.search(re.escape(expected), actual):
|
||||
logger.info(f"Matched: {expected} == {actual}")
|
||||
else:
|
||||
logger.info(f"Not Matched: {expected} != {actual}")
|
||||
raise AssertionError(f"Pattern does not match: {expected} != {actual}")
|
||||
|
||||
|
||||
# Required so that we can get liquidation price - Could also become a helper
|
||||
def wait_for_graphql_response(page, query_name, timeout=5000):
|
||||
response_data = {}
|
||||
|
||||
def handle_response(route, request):
|
||||
if "graphql" in request.url:
|
||||
response = request.response()
|
||||
if response is not None:
|
||||
json_response = response.json()
|
||||
if json_response and "data" in json_response:
|
||||
data = json_response["data"]
|
||||
if query_name in data:
|
||||
response_data["data"] = data
|
||||
route.continue_()
|
||||
return
|
||||
route.continue_()
|
||||
|
||||
# Register the route handler
|
||||
page.route("**", handle_response)
|
||||
|
||||
# Wait for the response data to be populated
|
||||
page.wait_for_timeout(timeout)
|
||||
|
||||
# Unregister the route handler
|
||||
page.unroute("**", handle_response)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_limit_order_new_trade_top_of_list(continuous_market, vega, page):
|
||||
submit_order(vega, "Key 1", continuous_market, "SIDE_BUY", 1, 110)
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
expected_trade = [
|
||||
"103.50",
|
||||
"1",
|
||||
r"\d{1,2}/\d{1,2}/\d{4},\s*\d{1,2}:\d{2}:\d{2}\s*(?:AM|PM)" "107.50",
|
||||
"1",
|
||||
r"\d{1,2}/\d{1,2}/\d{4},\s*\d{1,2}:\d{2}:\d{2}\s*(?:AM|PM)",
|
||||
]
|
||||
# 6005-THIS-001
|
||||
# 6005-THIS-002
|
||||
# 6005-THIS-003
|
||||
# 6005-THIS-004
|
||||
# 6005-THIS-005
|
||||
# 6005-THIS-006
|
||||
verify_data_grid(page, "Trades", expected_trade)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
def test_price_copied_to_deal_ticket(continuous_market, page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("Trades").click()
|
||||
wait_for_graphql_response(page, "Trades")
|
||||
page.locator("[col-id=price]").last.click()
|
||||
# 6005-THIS-007
|
||||
expect(page.get_by_test_id("order-price")).to_have_value("107.50000")
|
214
apps/trading/e2e/tests/trade_match/test_trade_match.py
Normal file
214
apps/trading/e2e/tests/trade_match/test_trade_match.py
Normal file
@ -0,0 +1,214 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
from vega_sim.service import VegaService
|
||||
|
||||
from actions.vega import submit_multiple_orders
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures(
|
||||
"page", "vega", "opening_auction_market", "auth", "risk_accepted"
|
||||
)
|
||||
def test_trade_match_table(opening_auction_market: str, vega: VegaService, page: Page):
|
||||
row_locator = ".ag-center-cols-container .ag-row"
|
||||
page.goto(f"/#/markets/{opening_auction_market}")
|
||||
|
||||
# sending order to be rejected, wait=False to avoid returning error from market-sim
|
||||
vega.submit_order(
|
||||
trading_key="Key 1",
|
||||
market_id=opening_auction_market,
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
order_type="TYPE_LIMIT",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
price=10e15,
|
||||
wait=False,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
submit_multiple_orders(
|
||||
vega,
|
||||
"Key 1",
|
||||
opening_auction_market,
|
||||
"SIDE_BUY",
|
||||
[[5, 110], [5, 105], [1, 50]],
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
submit_multiple_orders(
|
||||
vega,
|
||||
"Key 1",
|
||||
opening_auction_market,
|
||||
"SIDE_SELL",
|
||||
[[5, 90], [5, 95], [1, 150]],
|
||||
)
|
||||
vega.forward("60s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
# Positions
|
||||
position = {
|
||||
"market_code": "BTC:DAI_2023",
|
||||
"settlement_asset": "tDAI",
|
||||
"product_type": "Futr",
|
||||
"size": "+2",
|
||||
"notional": "220.00",
|
||||
"average_entry_price": "110.00",
|
||||
"mark_price": "110.00",
|
||||
"margin": "93.52953",
|
||||
"leverage": "1.0x",
|
||||
"liquidation": "0.00",
|
||||
"realised_pnl": "0.00",
|
||||
"unrealised_pnl": "0.00",
|
||||
}
|
||||
page.goto(f"/#/markets/{opening_auction_market}")
|
||||
# 7004-POSI-001
|
||||
# 7004-POSI-002
|
||||
primary_id = "stack-cell-primary"
|
||||
secondary_id = "stack-cell-secondary"
|
||||
|
||||
tab = page.get_by_test_id("tab-positions")
|
||||
table = tab.locator(".ag-center-cols-container")
|
||||
|
||||
market = table.locator("[col-id='marketCode']")
|
||||
expect(market.get_by_test_id(primary_id)).to_have_text(position["market_code"])
|
||||
expect(market.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["settlement_asset"] + position["product_type"]
|
||||
)
|
||||
size_and_notional = table.locator("[col-id='openVolume']")
|
||||
expect(size_and_notional.get_by_test_id(primary_id)).to_have_text(position["size"])
|
||||
expect(size_and_notional.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["notional"]
|
||||
)
|
||||
|
||||
entry_and_mark = table.locator("[col-id='markPrice']")
|
||||
expect(entry_and_mark.get_by_test_id(primary_id)).to_have_text(
|
||||
position["average_entry_price"]
|
||||
)
|
||||
expect(entry_and_mark.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["mark_price"]
|
||||
)
|
||||
|
||||
margin_and_leverage = table.locator("[col-id='margin']")
|
||||
expect(margin_and_leverage.get_by_test_id(primary_id)).to_have_text(
|
||||
position["margin"]
|
||||
)
|
||||
expect(margin_and_leverage.get_by_test_id(secondary_id)).to_have_text(
|
||||
position["leverage"]
|
||||
)
|
||||
liquidation = table.locator("[col-id='liquidationPrice']")
|
||||
expect(liquidation.get_by_test_id("liquidation-price")).to_have_text(
|
||||
position["liquidation"]
|
||||
)
|
||||
|
||||
realisedPNL = table.locator("[col-id='realisedPNL']")
|
||||
expect(realisedPNL).to_have_text(position["realised_pnl"])
|
||||
|
||||
unrealisedPNL = table.locator("[col-id='unrealisedPNL']")
|
||||
expect(unrealisedPNL).to_have_text(position["unrealised_pnl"])
|
||||
|
||||
# Open
|
||||
page.get_by_test_id("Open").click()
|
||||
rows = page.get_by_test_id("tab-open-orders").locator(row_locator).all()
|
||||
expect(rows[0]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "-1" + "Limit" + "Active" + "150.00" + "GTC"
|
||||
)
|
||||
expect(rows[1]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "+1" + "Limit" + "Active" + "50.00" + "GTC"
|
||||
)
|
||||
expect(rows[2]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "+5" + "Limit" + "Active" + "105.00" + "GTC"
|
||||
)
|
||||
|
||||
# Closed
|
||||
page.get_by_test_id("Closed").click()
|
||||
rows = page.get_by_test_id("tab-closed-orders").locator(row_locator).all()
|
||||
expect(rows[0]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "-5" + "Limit" + "Filled" + "95.00" + "GTC"
|
||||
)
|
||||
expect(rows[1]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "5" + "-5" + "Limit" + "Filled" + "90.00" + "GTC"
|
||||
)
|
||||
expect(rows[2]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "5" + "+5" + "Limit" + "Filled" + "110.00" + "GTC"
|
||||
)
|
||||
|
||||
# Rejected
|
||||
page.get_by_test_id("Rejected").click()
|
||||
expect(
|
||||
page.get_by_test_id("tab-rejected-orders").locator(row_locator)
|
||||
).to_contain_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
+ "0"
|
||||
+ "+1"
|
||||
+ "Limit"
|
||||
+ "Rejected: Margin check failed"
|
||||
+ "10,000,000,000,000,000.00"
|
||||
+ "GTC"
|
||||
)
|
||||
|
||||
# All
|
||||
page.get_by_test_id("All").click()
|
||||
rows = page.get_by_test_id("tab-orders").locator(row_locator).all()
|
||||
expect(rows[0]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "-1" + "Limit" + "Active" + "150.00" + "GTC"
|
||||
)
|
||||
expect(rows[1]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "5" + "-5" + "Limit" + "Filled" + "95.00" + "GTC"
|
||||
)
|
||||
expect(rows[2]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "5" + "-5" + "Limit" + "Filled" + "90.00" + "GTC"
|
||||
)
|
||||
expect(rows[3]).to_contain_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
+ "0"
|
||||
+ "+1"
|
||||
+ "Limit"
|
||||
+ "Rejected: Margin check failed"
|
||||
+ "10,000,000,000,000,000.00"
|
||||
+ "GTC"
|
||||
)
|
||||
expect(rows[4]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "0" + "+1" + "Limit" + "Active" + "50.00" + "GTC"
|
||||
)
|
||||
expect(rows[5]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "1" + "+5" + "Limit" + "Active" + "105.00" + "GTC"
|
||||
)
|
||||
expect(rows[6]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "5" + "+5" + "Limit" + "Filled" + "110.00" + "GTC"
|
||||
)
|
||||
|
||||
# Stop Orders
|
||||
page.get_by_test_id("Stop orders").click()
|
||||
expect(page.get_by_test_id("tab-stop-orders")).to_be_visible()
|
||||
expect(page.get_by_test_id("tab-stop-orders").locator(row_locator)).to_be_visible(
|
||||
visible=False
|
||||
)
|
||||
|
||||
# Fills
|
||||
page.get_by_test_id("Fills").click()
|
||||
rows = page.get_by_test_id("tab-fills").locator(row_locator).all()
|
||||
expect(rows[0]).to_contain_text(
|
||||
"BTC:DAI_2023Futr"
|
||||
+ "-5"
|
||||
+ "106.50 tDAI"
|
||||
+ "532.50 tDAI"
|
||||
+ "Taker"
|
||||
+ "53.51625 tDAI"
|
||||
)
|
||||
expect(rows[1]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "+1" + "105.00 tDAI" + "105.00 tDAI" + "-" + "0.00 tDAI"
|
||||
)
|
||||
expect(rows[2]).to_contain_text(
|
||||
"BTC:DAI_2023Futr" + "+5" + "105.00 tDAI" + "525.00 tDAI" + "-" + "0.00 tDAI"
|
||||
)
|
||||
|
||||
# Collateral
|
||||
page.get_by_test_id("Collateral").click()
|
||||
expect(
|
||||
page.get_by_test_id("tab-accounts").locator(".ag-floating-top-viewport .ag-row")
|
||||
).to_contain_text("tDAI" + "43.94338" + "0.00%" + "999,904.04037" + "999,947.98375")
|
139
apps/trading/e2e/tests/trading_chart/test_trading_chart.py
Normal file
139
apps/trading/e2e/tests/trading_chart/test_trading_chart.py
Normal file
@ -0,0 +1,139 @@
|
||||
# import pytest
|
||||
# import re
|
||||
# from collections import namedtuple
|
||||
# from playwright.sync_api import Page
|
||||
# from vega_sim.service import VegaService
|
||||
# from actions.vega import submit_order
|
||||
|
||||
# import logging
|
||||
|
||||
# logger = logging.getLogger()
|
||||
|
||||
# InfoItem = namedtuple('InfoItem', ['name', 'infoText'])
|
||||
|
||||
# @pytest.mark.skip("temporary skip")
|
||||
# @pytest.mark.parametrize("vega", [120], indirect=True)
|
||||
# @pytest.mark.usefixtures("continuous_market","risk_accepted", "auth")
|
||||
# def test_trading_chart(continuous_market, vega: VegaService, page: Page):
|
||||
# page.goto(f"/#/markets/{continuous_market}")
|
||||
# vega.forward("24h")
|
||||
# vega.wait_for_total_catchup()
|
||||
# submit_order(vega, "mm", continuous_market, "SIDE_SELL", 1, 101.50000)
|
||||
# submit_order(vega, "mm2", continuous_market, "SIDE_SELL", 1, 101.50000)
|
||||
# vega.forward("10s")
|
||||
# vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
# page.click("button[aria-haspopup='menu']:has-text('Interval:')")
|
||||
# page.click(f"div[role='menuitemradio']:text-is('15m')")
|
||||
# page.wait_for_selector(".indicator-info-wrapper:visible")
|
||||
# # Check chart views and select
|
||||
# chart = "[aria-label$='chart icon']"
|
||||
# valid_chart_views = ['Mountain', 'Candlestick', 'Line', 'OHLC']
|
||||
# #6004-CHAR-002
|
||||
# #6004-CHAR-003
|
||||
# check_menu_items(page, chart, valid_chart_views, 'Candlestick')
|
||||
|
||||
# # Check study info
|
||||
# study_info = [
|
||||
# InfoItem("Eldar-ray","Eldar-ray: Bull -5.14286Bear -5.14286"),
|
||||
# InfoItem("Force index", "Force index: -0.85714"),
|
||||
# InfoItem("MACD", "MACD: S -0.09573D -0.38291MACD -0.47863"),
|
||||
# InfoItem("RSI", "RSI: 0.00000"),
|
||||
# InfoItem("Volume", "Volume: 1")
|
||||
# ]
|
||||
# """Preparation steps to check study info on the page."""
|
||||
# element = page.locator(".plot-area-interaction").nth(1)
|
||||
# element.hover()
|
||||
|
||||
# page.click(".pane__close-button-wrapper")
|
||||
|
||||
# info_items = page.query_selector_all(".plot-area")
|
||||
|
||||
# assert (len(info_items)) == 1
|
||||
# #6004-CHAR-005
|
||||
# #6004-CHAR-006
|
||||
# #6004-CHAR-007
|
||||
# #6004-CHAR-042
|
||||
# #6004-CHAR-045
|
||||
# #6004-CHAR-047
|
||||
# #6004-CHAR-049
|
||||
# #6004-CHAR-051
|
||||
# page.mouse.wheel(0, 10)
|
||||
# check_menu_item_checkbox(page, "Studies", study_info)
|
||||
# page.get_by_text("Studies").click(force=True)
|
||||
|
||||
|
||||
# # Check overlay info
|
||||
# overlay_info = [
|
||||
# InfoItem("Bollinger bands", "Bollinger: Upper 110.69473Lower 103.10527"),
|
||||
# InfoItem("Envelope", "Envelope: Upper 111.65000Lower 91.35000"),
|
||||
# InfoItem("EMA", "EMA: 106.30000"),
|
||||
# InfoItem("Moving average", "Moving average: 106.90000"),
|
||||
# InfoItem("Price monitoring bounds", "Price Monitoring Bounds 1: Min 83.11038Max 138.66685Reference 107.50000")
|
||||
# ]
|
||||
# #6004-CHAR-004
|
||||
# #6004-CHAR-008
|
||||
# #6004-CHAR-009
|
||||
# #6004-CHAR-034
|
||||
# #6004-CHAR-037
|
||||
# #6004-CHAR-039
|
||||
# #6004-CHAR-041
|
||||
# check_menu_item_checkbox(page, "Overlays", overlay_info)
|
||||
|
||||
# # Check chart info
|
||||
# # 6004-CHAR-010
|
||||
# expected_date_regex = r"^\d{2}:\d{2} \d{2} [A-Za-z]{3} \d{4}$"
|
||||
# expected_ohlc = "O 101.50000H 101.50000L 101.50000C 101.50000Change −6.00000(−5.58%)"
|
||||
# indicator_info_locator = page.locator(".indicator-info-wrapper").nth(0)
|
||||
# texts = indicator_info_locator.all_text_contents()
|
||||
# combined_text = ''.join(texts)
|
||||
# actual_date = combined_text[:-67]
|
||||
# actual_ohlc = combined_text[-67:]
|
||||
# logger.info(actual_date)
|
||||
# logger.info(actual_ohlc)
|
||||
# assert re.match(expected_date_regex, actual_date)
|
||||
# assert actual_ohlc == expected_ohlc
|
||||
# # Check interval options and select '15m'
|
||||
# interval = "button[aria-haspopup='menu']:has-text('Interval:')"
|
||||
# valid_intervals = ['1m', '5m', '15m', '1H', '6H', '1D']
|
||||
# #6004-CHAR-001
|
||||
# page.click("button[aria-haspopup='menu']:has-text('Interval:')", force=True)
|
||||
# check_menu_items(page, interval, valid_intervals, '1m')
|
||||
|
||||
|
||||
# def check_menu_items(page, trigger_selector, valid_texts, click_item=None):
|
||||
# page.click(trigger_selector, force=True)
|
||||
# items = page.locator("div[role='menuitemradio']").all()
|
||||
# assert len(items) == len(valid_texts), f"Expected {len(valid_texts)} items but found {len(items)} items."
|
||||
|
||||
# for i, el in enumerate(items):
|
||||
# text = el.text_content().strip()
|
||||
# assert text == valid_texts[i], f"Expected text '{valid_texts[i]}' but found '{text}'."
|
||||
# if click_item:
|
||||
# page.click(f"div[role='menuitemradio']:text-is('{click_item}')")
|
||||
# page.click(trigger_selector)
|
||||
# checked_item_text = page.text_content("div[role='menuitemradio'][data-state='checked']").strip()
|
||||
# assert checked_item_text == click_item, f"Expected checked item text '{click_item}' but found '{checked_item_text}'."
|
||||
# page.click(trigger_selector, force=True)
|
||||
|
||||
# def check_menu_item_checkbox(page, button_text, items):
|
||||
# button_selector = f"button:has-text('{button_text}')"
|
||||
|
||||
# for item in items:
|
||||
# page.click(button_selector)
|
||||
# page.click(f"div[role='menuitemcheckbox']:has-text('{item.name}')")
|
||||
|
||||
# page.click(button_selector)
|
||||
# checkbox_items = page.query_selector_all("div[role='menuitemcheckbox']")
|
||||
|
||||
# assert len(checkbox_items) == len(items), f"Expected {len(items)} checkboxes but found {len(checkbox_items)}."
|
||||
|
||||
# for i, el in enumerate(checkbox_items):
|
||||
# text = el.text_content().strip()
|
||||
# assert text == items[i].name, f"Expected checkbox text '{items[i].name}' but found '{text}'."
|
||||
|
||||
# for i, item in enumerate(items[0:]):
|
||||
# info_locator = page.locator(".indicator-info-wrapper").nth(i+1)
|
||||
# info_text = info_locator.text_content().strip()
|
||||
# assert info_text == item.infoText, f"Expected info text '{item.infoText}' but found '{info_text}'."
|
134
apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py
Normal file
134
apps/trading/e2e/tests/transfer/test_transfer_key_to_key.py
Normal file
@ -0,0 +1,134 @@
|
||||
import pytest
|
||||
import re
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.utils import wait_for_toast_confirmation, create_and_faucet_wallet, WalletConfig, next_epoch
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
|
||||
LIQ = WalletConfig("liq", "liq")
|
||||
PARTY_A = WalletConfig("party_a", "party_a")
|
||||
PARTY_B = WalletConfig("party_b", "party_b")
|
||||
PARTY_C = WalletConfig("party_c", "party_c")
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_transfer_submit(continuous_market, vega: VegaService, page: Page):
|
||||
# 1003-TRAN-001
|
||||
# 1003-TRAN-006
|
||||
# 1003-TRAN-007
|
||||
# 1003-TRAN-008
|
||||
# 1003-TRAN-009
|
||||
# 1003-TRAN-010
|
||||
# 1003-TRAN-023
|
||||
page.goto('/#/portfolio')
|
||||
|
||||
expect(page.get_by_test_id('transfer-form')).to_be_visible
|
||||
page.get_by_test_id('select-asset').click()
|
||||
expect(page.get_by_test_id('rich-select-option')).to_have_count(1)
|
||||
|
||||
page.get_by_test_id('rich-select-option').click()
|
||||
page.select_option('[data-testid=transfer-form] [name="toVegaKey"]', index=2)
|
||||
page.select_option('[data-testid=transfer-form] [name="fromAccount"]', index=1)
|
||||
|
||||
expected_asset_text = re.compile(r"tDAI tDAI999,991.49731 tDAI.{6}….{4}")
|
||||
actual_asset_text = page.get_by_test_id('select-asset').text_content().strip()
|
||||
|
||||
assert expected_asset_text.search(actual_asset_text), f"Expected pattern not found in {actual_asset_text}"
|
||||
|
||||
page.locator('[data-testid=transfer-form] input[name="amount"]').fill('1')
|
||||
expect(page.locator('[data-testid=transfer-form] input[name="amount"]')).not_to_be_empty()
|
||||
|
||||
page.locator('[data-testid=transfer-form] [type="submit"]').click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmed View in block explorerTransferTo .{6}….{6}1\.00 tDAI")
|
||||
actual_confirmation_text = page.get_by_test_id('toast-content').text_content()
|
||||
assert expected_confirmation_text.search(actual_confirmation_text), f"Expected pattern not found in {actual_confirmation_text}"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
||||
def test_transfer_vesting_below_minimum(continuous_market, vega: VegaService, page: Page):
|
||||
vega.update_network_parameter(
|
||||
"mm", parameter="transfer.minTransferQuantumMultiple", new_value="100000"
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A, amount=1e3)
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B, amount=1e5)
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C, amount=1e5)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=asset_id,
|
||||
asset_for_metric=asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
# Generate trades for non-zero metrics
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=continuous_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_SELL",
|
||||
price=0.30,
|
||||
volume=100,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_C.name,
|
||||
market_id=continuous_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=0.30,
|
||||
volume=100,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
page.goto('/#/portfolio')
|
||||
expect(page.get_by_test_id('transfer-form')).to_be_visible
|
||||
|
||||
page.get_by_test_id("manage-vega-wallet").click()
|
||||
page.locator('[role="menuitemradio"]').nth(5).click()
|
||||
page.reload()
|
||||
page.get_by_test_id('select-asset').click()
|
||||
page.get_by_test_id('rich-select-option').click()
|
||||
|
||||
option_value = page.locator('[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]').first.get_attribute("value")
|
||||
|
||||
page.select_option('[data-testid="transfer-form"] [name="fromAccount"]', option_value)
|
||||
|
||||
page.locator('[data-testid=transfer-form] input[name="amount"]').fill('0.000001')
|
||||
page.locator('[data-testid=transfer-form] [type="submit"]').click()
|
||||
expect(page.get_by_test_id('input-error-text')).to_be_visible
|
||||
expect(page.get_by_test_id('input-error-text')).to_have_text("Amount below minimum requirements for partial transfer. Use max to bypass")
|
||||
vega.one_off_transfer(
|
||||
from_key_name=PARTY_B.name,
|
||||
to_key_name=PARTY_B.name,
|
||||
from_account_type= vega_protos.vega.AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
|
||||
to_account_type= vega_protos.vega.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset= asset_id,
|
||||
amount= 24.999999,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(10)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.get_by_text("Use max").first.click()
|
||||
page.locator('[data-testid=transfer-form] [type="submit"]').click()
|
||||
wait_for_toast_confirmation(page)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expected_confirmation_text = re.compile(r"Transfer completeYour transaction has been confirmed View in block explorerTransferTo .{6}….{6}0\.00001 tDAI")
|
||||
actual_confirmation_text = page.get_by_test_id('toast-content').text_content()
|
||||
assert expected_confirmation_text.search(actual_confirmation_text), f"Expected pattern not found in {actual_confirmation_text}"
|
@ -1,13 +1,19 @@
|
||||
#!/bin/bash -e
|
||||
yarn --pure-lockfile
|
||||
app=${1:-trading}
|
||||
envCmd="envCmd="yarn -f ./apps/${app}/.env.${2:-mainnet}"
|
||||
|
||||
envCmd="yarn -f ./apps/${app}/.env.${2:-mainnet}"
|
||||
|
||||
yarn install
|
||||
|
||||
if [ "${app}" = "trading" ]; then
|
||||
$envCmd yarn nx export trading
|
||||
# Execute the command stored in envCmd and then run the nx export command
|
||||
$envCmd && yarn nx export trading
|
||||
DIST_LOCATION=dist/apps/trading/exported/
|
||||
else
|
||||
$envCmd yarn nx build ${app}
|
||||
# Execute the command stored in envCmd and then run the nx build command
|
||||
$envCmd && yarn nx build ${app}
|
||||
DIST_LOCATION=dist/apps/${app}
|
||||
fi
|
||||
|
||||
cp -r $DIST_LOCATION dist-result
|
||||
|
@ -13,7 +13,9 @@
|
||||
"lint:all": "nx run-many --all --target=lint",
|
||||
"e2e:all": "nx run-many --all --target=e2e",
|
||||
"vegacapsule": "vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl",
|
||||
"release": "git checkout develop ; git pull ; node scripts/make-release.js"
|
||||
"release": "git checkout develop ; git pull ; node scripts/make-release.js",
|
||||
"trading:test": "cd apps/trading/e2e && poetry run pytest -k",
|
||||
"trading:test:all": "cd apps/trading/e2e && poetry run pytest -s --numprocesses 6 --dist loadfile"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.9.0"
|
||||
|
Loading…
Reference in New Issue
Block a user