Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: locustio/locust
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2.32.6
Choose a base ref
...
head repository: locustio/locust
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2.32.7
Choose a head ref
  • 20 commits
  • 49 files changed
  • 4 contributors

Commits on Jan 14, 2025

  1. fix readme image ref links

    Ben Chang committed Jan 14, 2025
    Copy the full SHA
    22f7498 View commit details
  2. Merge pull request #3031 from changchaishi/fix-readme

    fix readme image ref links
    cyberw authored Jan 14, 2025
    Copy the full SHA
    68fa4c2 View commit details

Commits on Jan 15, 2025

  1. Add tab with locust cloud features

    andrewbaldwin44 committed Jan 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    394a400 View commit details

Commits on Jan 16, 2025

  1. Update graphs

    andrewbaldwin44 committed Jan 16, 2025
    Copy the full SHA
    cb5e779 View commit details
  2. Add bullet points

    andrewbaldwin44 committed Jan 16, 2025
    Copy the full SHA
    437e8a2 View commit details
  3. Merge pull request #3032 from andrewbaldwin44/feature/locust-cloud-tab

    Add tab with locust cloud features
    cyberw authored Jan 16, 2025
    Copy the full SHA
    4a454be View commit details

Commits on Jan 17, 2025

  1. List MongoDBUser and PostgresUser in api docs

    cyberw committed Jan 17, 2025
    Copy the full SHA
    54c7b4f View commit details
  2. Fix doc link issue

    cyberw committed Jan 17, 2025
    Copy the full SHA
    1ee21af View commit details

Commits on Jan 18, 2025

  1. Increase stale timeout for tickets and PRs to 20 days.

    cyberw committed Jan 18, 2025
    Copy the full SHA
    8ceb930 View commit details

Commits on Jan 19, 2025

  1. Code quality: Fix unused imports and switch on related ruff check

    Π¨ΠΏΠ°ΠΊ АндрСй Π‘Π΅Ρ€Π³Π΅Π΅Π²ΠΈΡ‡ committed Jan 19, 2025
    Copy the full SHA
    a8302fc View commit details

Commits on Jan 20, 2025

  1. Copy the full SHA
    ddd0693 View commit details
  2. Merge pull request #3035 from andrewbaldwin44/feature/configured-x-axis

    Allow xAxis and Grid to be Configured in Echarts
    cyberw authored Jan 20, 2025
    Copy the full SHA
    d205db7 View commit details

Commits on Jan 21, 2025

  1. Copy the full SHA
    bfaf8a9 View commit details
  2. Add test

    andrewbaldwin44 committed Jan 21, 2025
    Copy the full SHA
    57b1c48 View commit details
  3. Merge pull request #3036 from andrewbaldwin44/bugfix/allow-empty-tables

    Allow Empty Tables when Filtering
    cyberw authored Jan 21, 2025
    Copy the full SHA
    3ddcc1d View commit details

Commits on Jan 24, 2025

  1. Allow Showing Only Error Message on Login Page

    andrewbaldwin44 committed Jan 24, 2025
    Copy the full SHA
    704562b View commit details
  2. Merge pull request #3037 from andrewbaldwin44/task/errors-on-login-page

    Web UI: Allow Showing Only an Error Message on the Login Page
    cyberw authored Jan 24, 2025
    Copy the full SHA
    c2bc7ef View commit details

Commits on Jan 26, 2025

  1. Merge pull request #3034 from insspb/feature/cq-imports

    Code quality: Fix unused imports and switch on related ruff check
    cyberw authored Jan 26, 2025
    Copy the full SHA
    67fa859 View commit details

Commits on Jan 29, 2025

  1. Expose hidden characters in debug log message when master-worker have…

    … different patch versions.
    cyberw committed Jan 29, 2025
    Copy the full SHA
    a47601d View commit details

Commits on Jan 30, 2025

  1. Update changelog for 2.32.7

    cyberw committed Jan 30, 2025
    Copy the full SHA
    f2790ef View commit details
Showing with 217 additions and 98 deletions.
  1. +5 βˆ’5 .github/workflows/stale.yml
  2. +1 βˆ’1 README.md
  3. +14 βˆ’0 docs/api.rst
  4. +7 βˆ’0 docs/changelog.rst
  5. +1 βˆ’1 docs/configuration.rst
  6. +3 βˆ’3 docs/quickstart.rst
  7. +0 βˆ’1 examples/custom_shape/wait_user_count.py
  8. +0 βˆ’2 examples/dispatch_test_scripts/locustfile.py
  9. +1 βˆ’1 examples/events.py
  10. +2 βˆ’2 examples/extend_web_ui.py
  11. +1 βˆ’1 examples/manual_stats_reporting.py
  12. +1 βˆ’1 examples/mongodb/locustfile.py
  13. +1 βˆ’1 examples/postgres/locustfile.py
  14. +0 βˆ’2 examples/terraform/aws/plan/basic.py
  15. +2 βˆ’2 examples/web_ui_cache_stats.py
  16. +4 βˆ’1 locust/__init__.py
  17. +0 βˆ’1 locust/argument_parser.py
  18. +1 βˆ’1 locust/contrib/fasthttp.py
  19. +0 βˆ’3 locust/html.py
  20. +2 βˆ’3 locust/main.py
  21. +5 βˆ’0 locust/rpc/__init__.py
  22. +1 βˆ’1 locust/runners.py
  23. +0 βˆ’1 locust/test/test_fasthttp.py
  24. +0 βˆ’1 locust/test/test_load_locustfile.py
  25. +1 βˆ’1 locust/test/test_main.py
  26. +0 βˆ’1 locust/test/test_parser.py
  27. +1 βˆ’1 locust/test/test_sequential_taskset.py
  28. +0 βˆ’1 locust/test/test_wait_time.py
  29. +1 βˆ’6 locust/test/test_web.py
  30. +1 βˆ’1 locust/test/test_zmqrpc.py
  31. +7 βˆ’0 locust/user/__init__.py
  32. +0 βˆ’1 locust/web.py
  33. BIN locust/webui/public/assets/graphs-dark.png
  34. BIN locust/webui/public/assets/graphs-light.png
  35. BIN locust/webui/public/assets/testruns-dark.png
  36. BIN locust/webui/public/assets/testruns-light.png
  37. +0 βˆ’30 locust/webui/src/components/LineChart/LineChart.test.tsx
  38. +14 βˆ’1 locust/webui/src/components/LineChart/LineChart.tsx
  39. +2 βˆ’0 locust/webui/src/components/LineChart/LineChart.types.ts
  40. +13 βˆ’9 locust/webui/src/components/LineChart/LineChart.utils.ts
  41. +26 βˆ’0 locust/webui/src/components/LineChart/tests/LineChartUtils.test.tsx
  42. +60 βˆ’0 locust/webui/src/components/LocustCloudTab/LocustCloudTab.tsx
  43. +7 βˆ’0 locust/webui/src/components/Tabs/Tabs.constants.tsx
  44. +22 βˆ’7 locust/webui/src/hooks/tests/useSortByField.test.tsx
  45. +3 βˆ’0 locust/webui/src/hooks/useSortByField.ts
  46. +3 βˆ’0 locust/webui/src/pages/Auth.tsx
  47. +2 βˆ’3 locust/webui/src/styles/theme.ts
  48. +1 βˆ’0 locust/webui/vite.lib.config.ts
  49. +1 βˆ’1 pyproject.toml
10 changes: 5 additions & 5 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
@@ -19,8 +19,8 @@ jobs:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 10 days."
close-issue-message: "This issue was closed because it has been stalled for 10 days with no activity. This does not necessarily mean that the issue is bad, but it most likely means that nobody is willing to take the time to fix it. If you have found Locust useful, then consider contributing a fix yourself!"
stale-pr-message: "This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 10 days."
close-pr-message: "This PR was closed because it has been stalled for 10 days with no activity."
days-before-close: 10
stale-issue-message: "This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 20 days."
close-issue-message: "This issue was closed because it has been marked stale for 20 days with no activity. This does not necessarily mean that the issue is bad, but it most likely means that nobody is willing to take the time to fix it. If you have found Locust useful, then consider contributing a fix yourself!"
stale-pr-message: "This PR is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 20 days."
close-pr-message: "This PR was closed because it has been marked stale for 20 days with no activity."
days-before-close: 20
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ Locust has a user friendly web interface that shows the progress of your test in
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-light.png" alt="Locust UI charts" height="100" width="200"/>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-dark.png" alt="Locust UI charts" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-light.png" alt="Locust UI charts" height="100" width="200"/>
<img src="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/bottlenecked-server-light.png" alt="Locust UI charts" height="100" width="200"/>
</picture>
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/locustio/locust/refs/heads/master/docs/images/webui-running-statistics-light.png" alt="Locust UI stats" height="100" width="200"/>
14 changes: 14 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -22,6 +22,20 @@ FastHttpUser class
:members: wait_time, tasks, client, abstract, rest
:noindex:

PostgresUser class
==================

.. autoclass:: locust.contrib.postgres.PostgresUser
:members: wait_time, tasks, client, abstract
:noindex:

MongoDBUser class
=================

.. autoclass:: locust.contrib.mongodb.MongoDBUser
:members: wait_time, tasks, client, abstract, rest
:noindex:

TaskSet class
=============

7 changes: 7 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -4,6 +4,13 @@ Changelog Highlights

For full details of changes, please see https://github.com/locustio/locust/releases or https://github.com/locustio/locust/blob/master/CHANGELOG.md

2.32.7
======
* Fix readme image ref links by @changchaishi in https://github.com/locustio/locust/pull/3031
* Add tab showing `Locust Cloud <https://www.locust.cloud>`_ features https://github.com/locustio/locust/pull/3032
* Minor UI enhancements https://github.com/locustio/locust/pull/3035, https://github.com/locustio/locust/pull/3036, https://github.com/locustio/locust/pull/3037
* Code quality: Fix unused imports and switch on related ruff check https://github.com/locustio/locust/pull/3034

2.32.6
======
* Update Dockerfile to use Python 3.12 https://github.com/locustio/locust/pull/3029
2 changes: 1 addition & 1 deletion docs/configuration.rst
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ You can specify an additional file using the ``--config`` flag.
Here's a minimalistic example of the configuration file supported by Locust:

Have a look later in this article for :ref:`All available configuration options`
Have a look later in this article for `All available configuration options`_

locust.conf
--------------
6 changes: 3 additions & 3 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
@@ -32,17 +32,17 @@ Locust's web interface

Open http://localhost:8089

.. image:: images/webui-splash-screenshot.png
.. image:: images/webui-splash-light.png

| Provide the host name of your server and try it out!
The following screenshots show what it might look like when running this test using 50 concurrent users, with a ramp up rate of 1 user/s

.. image:: images/webui-running-statistics.png
.. image:: images/webui-running-statistics-light.png

| Under the *Charts* tab you'll find things like requests per second (RPS), response times and number of running users:
.. image:: images/bottlenecked_server.png
.. image:: images/bottlenecked-server-light.png

.. note::

1 change: 0 additions & 1 deletion examples/custom_shape/wait_user_count.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from locust import HttpUser, LoadTestShape, TaskSet, constant, task

import math
import random
import time
from collections import namedtuple
2 changes: 0 additions & 2 deletions examples/dispatch_test_scripts/locustfile.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from locust import HttpUser, LoadTestShape, constant, task

import math


class UserA(HttpUser):
wait_time = constant(600)
2 changes: 1 addition & 1 deletion examples/events.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
track the sum of the content-length header in all successful HTTP responses
"""

from locust import HttpUser, TaskSet, between, events, task, web
from locust import HttpUser, TaskSet, between, events, task


class MyTaskSet(TaskSet):
4 changes: 2 additions & 2 deletions examples/extend_web_ui.py
Original file line number Diff line number Diff line change
@@ -4,14 +4,14 @@
successful HTTP responses and display them in the web UI.
"""

from locust import HttpUser, TaskSet, between, events, task, web
from locust import HttpUser, TaskSet, between, events, task

import json
import os
from html import escape
from time import time

from flask import Blueprint, jsonify, make_response, render_template, request
from flask import Blueprint, make_response, render_template, request


class MyTaskSet(TaskSet):
2 changes: 1 addition & 1 deletion examples/manual_stats_reporting.py
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ def my_task(self):
from locust import User, constant, events, task

import random
from contextlib import ContextDecorator, contextmanager
from contextlib import contextmanager
from time import sleep, time


2 changes: 1 addition & 1 deletion examples/mongodb/locustfile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust import between, task
from locust import task
from locust.contrib.mongodb import MongoDBUser

import os
2 changes: 1 addition & 1 deletion examples/postgres/locustfile.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust import TaskSet, between, task
from locust import task
from locust.contrib.postgres import PostgresUser

import os
2 changes: 0 additions & 2 deletions examples/terraform/aws/plan/basic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from locust import HttpUser, between, task

import time


class Quickstart(HttpUser):
wait_time = between(1, 5)
4 changes: 2 additions & 2 deletions examples/web_ui_cache_stats.py
Original file line number Diff line number Diff line change
@@ -4,14 +4,14 @@
and display them in the web UI.
"""

from locust import HttpUser, TaskSet, between, events, task, web
from locust import HttpUser, TaskSet, between, events, task

import json
import os
from html import escape
from time import time

from flask import Blueprint, jsonify, make_response, render_template, request
from flask import Blueprint, make_response, render_template, request


class MyTaskSet(TaskSet):
5 changes: 4 additions & 1 deletion locust/__init__.py
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
print("Uninstall trio package and remove the setting.")
try:
# preserve backwards compatibility for now
import trio
import trio # noqa: F401
except ModuleNotFoundError:
# dont show a massive callstack if trio is not installed
os._exit(1)
@@ -50,6 +50,9 @@
"events",
"LoadTestShape",
"run_single_user",
"HttpLocust",
"Locust",
"__version__",
)

# Used for raising a DeprecationWarning if old Locust/HttpLocust is used
1 change: 0 additions & 1 deletion locust/argument_parser.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
import os
import platform
import socket
import ssl
import sys
import tempfile
import textwrap
2 changes: 1 addition & 1 deletion locust/contrib/fasthttp.py
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
from locust.env import Environment
from locust.exception import CatchResponseError, LocustError, ResponseError
from locust.user import User
from locust.util.deprecation import DeprecatedFastHttpLocustClass as FastHttpLocust
from locust.util.deprecation import DeprecatedFastHttpLocustClass as FastHttpLocust # noqa: F401

import json
import json as unshadowed_json # some methods take a named parameter called json
3 changes: 0 additions & 3 deletions locust/html.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import glob
import os
import pathlib
from html import escape
from itertools import chain
from json import dumps

from jinja2 import Environment as JinjaEnvironment
from jinja2 import FileSystemLoader
5 changes: 2 additions & 3 deletions locust/main.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@
import importlib.metadata
import inspect
import itertools
import json
import logging
import os
import signal
@@ -39,12 +38,12 @@

# import external plugins if installed to allow for registering custom arguments etc
try:
import locust_plugins # pyright: ignore[reportMissingImports]
import locust_plugins # pyright: ignore[reportMissingImports] # noqa: F401
except ModuleNotFoundError as e:
if e.msg != "No module named 'locust_plugins'":
raise
try:
import locust_cloud # pyright: ignore[reportMissingImports]
import locust_cloud # pyright: ignore[reportMissingImports] # noqa: F401

locust_cloud_version = f" (locust-cloud {importlib.metadata.version('locust-cloud')})"
except ModuleNotFoundError as e:
5 changes: 5 additions & 0 deletions locust/rpc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
__all__ = (
"Message",
"rpc",
)

from . import zmqrpc as rpc
from .protocol import Message
2 changes: 1 addition & 1 deletion locust/runners.py
Original file line number Diff line number Diff line change
@@ -1002,7 +1002,7 @@ def client_listener(self) -> NoReturn:
elif msg.data != __version__ and msg.data != -1:
if msg.data[0:4] == __version__[0:4]:
logger.debug(
f"A worker ({client_id}) running a different patch version ({msg.data}) connected, master version is {__version__}"
f"A worker ({client_id}) running a different patch version ({repr(msg.data)}) connected, master version is {repr(__version__)}"
)
else:
logger.warning(
1 change: 0 additions & 1 deletion locust/test/test_fasthttp.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from locust import FastHttpUser
from locust.argument_parser import parse_options
from locust.contrib.fasthttp import FastHttpSession
from locust.exception import CatchResponseError, InterruptTaskSet, LocustError, ResponseError
from locust.user import TaskSet, task
1 change: 0 additions & 1 deletion locust/test/test_load_locustfile.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@

import filecmp
import os
import pathlib
import textwrap

from .mock_locustfile import MOCK_LOCUSTFILE_CONTENT, mock_locustfile
2 changes: 1 addition & 1 deletion locust/test/test_main.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@
import sys
import textwrap
import unittest
from subprocess import DEVNULL, PIPE, STDOUT
from subprocess import PIPE, STDOUT
from tempfile import TemporaryDirectory
from unittest import TestCase

1 change: 0 additions & 1 deletion locust/test/test_parser.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
import os
import unittest
from io import StringIO
from random import randint
from tempfile import NamedTemporaryFile, TemporaryDirectory
from unittest import mock

2 changes: 1 addition & 1 deletion locust/test/test_sequential_taskset.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust import User, constant, task
from locust import User, task
from locust.exception import RescheduleTask
from locust.user.sequential_taskset import SequentialTaskSet

1 change: 0 additions & 1 deletion locust/test/test_wait_time.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from locust import TaskSet, User, between, constant, constant_throughput
from locust.exception import MissingWaitTimeError

import random
import time
7 changes: 1 addition & 6 deletions locust/test/test_web.py
Original file line number Diff line number Diff line change
@@ -10,24 +10,19 @@
from locust.user import User, task
from locust.web import WebUI

import copy
import csv
import json
import logging
import os
import re
import textwrap
import traceback
from io import StringIO
from tempfile import NamedTemporaryFile, TemporaryDirectory
from tempfile import NamedTemporaryFile

import gevent
import requests
from flask_login import UserMixin
from pyquery import PyQuery as pq

from ..util.load_locustfile import load_locustfile
from .mock_locustfile import mock_locustfile
from .testcases import LocustTestCase
from .util import create_tls_cert

2 changes: 1 addition & 1 deletion locust/test/test_zmqrpc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from locust.exception import RPCError, RPCReceiveError, RPCSendError
from locust.exception import RPCError, RPCSendError
from locust.rpc import Message, zmqrpc
from locust.test.testcases import LocustTestCase

7 changes: 7 additions & 0 deletions locust/user/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
__all__ = (
"HttpUser",
"tag",
"task",
"TaskSet",
"User",
)
from .task import TaskSet, tag, task
from .users import HttpUser, User
1 change: 0 additions & 1 deletion locust/web.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,6 @@
from io import StringIO
from itertools import chain
from json import dumps
from time import time
from typing import TYPE_CHECKING, Any, TypedDict

import gevent
Binary file added locust/webui/public/assets/graphs-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added locust/webui/public/assets/graphs-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added locust/webui/public/assets/testruns-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added locust/webui/public/assets/testruns-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 0 additions & 30 deletions locust/webui/src/components/LineChart/LineChart.test.tsx

This file was deleted.

15 changes: 14 additions & 1 deletion locust/webui/src/components/LineChart/LineChart.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { useEffect, useState, useRef } from 'react';
import { init, dispose, ECharts, connect } from 'echarts';
import {
init,
dispose,
ECharts,
connect,
XAXisComponentOption,
GridComponentOption,
} from 'echarts';

import { CHART_THEME } from 'components/LineChart/LineChart.constants';
import {
@@ -21,6 +28,8 @@ interface IBaseChartType extends ILineChartMarkers, ILineChartTimeAxis {

interface ILineChartProps<ChartType extends IBaseChartType> extends ILineChart<ChartType> {
shouldReplaceMergeLines?: boolean;
xAxis?: XAXisComponentOption;
grid?: GridComponentOption;
}

export default function LineChart<ChartType extends IBaseChartType>({
@@ -31,6 +40,8 @@ export default function LineChart<ChartType extends IBaseChartType>({
chartValueFormatter,
splitAxis,
yAxisLabels,
xAxis,
grid,
scatterplot,
shouldReplaceMergeLines = false,
}: ILineChartProps<ChartType>) {
@@ -55,6 +66,8 @@ export default function LineChart<ChartType extends IBaseChartType>({
chartValueFormatter,
splitAxis,
yAxisLabels,
xAxis,
grid,
scatterplot,
}),
);
2 changes: 2 additions & 0 deletions locust/webui/src/components/LineChart/LineChart.types.ts
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@ export interface ILineChart<ChartType> {
chartValueFormatter?: (value?: any) => string | number;
splitAxis?: boolean;
yAxisLabels?: string | [string, string];
grid?: any;
xAxis?: any;
scatterplot?: boolean;
}

22 changes: 13 additions & 9 deletions locust/webui/src/components/LineChart/LineChart.utils.ts
Original file line number Diff line number Diff line change
@@ -78,6 +78,8 @@ export const createOptions = <ChartType extends Pick<ICharts, 'time'>>({
chartValueFormatter,
splitAxis,
yAxisLabels,
xAxis,
grid,
scatterplot,
}: ILineChart<ChartType>) => ({
title: { text: title },
@@ -106,15 +108,17 @@ export const createOptions = <ChartType extends Pick<ICharts, 'time'>>({
},
borderWidth: 0,
},
xAxis: {
type: 'time',
min: (charts.time || [new Date().toISOString()])[0],
startValue: (charts.time || [])[0],
axisLabel: {
formatter: formatTimeAxis,
},
},
grid: { left: 60, right: 40 },
xAxis: xAxis
? xAxis
: {
type: 'time',
min: (charts.time || [new Date().toISOString()])[0],
startValue: (charts.time || [])[0],
axisLabel: {
formatter: formatTimeAxis,
},
},
grid: grid ? grid : { left: 60, right: 40 },
yAxis: createYAxis({ splitAxis, yAxisLabels }),
series: getSeriesData<ChartType>({ charts, lines, scatterplot }),
color: colors,
Original file line number Diff line number Diff line change
@@ -178,6 +178,32 @@ describe('createOptions', () => {
expect(options.series).toEqual(mockScatterplotSeriesData);
expect(options.color).toEqual(['#fff']);
});

test('should allow xAxis config to be overriden', () => {
const mockXAxisConfig = {
type: 'category' as any,
minInterval: 1,
};
const options = createOptions<MockChartType>({
...createOptionsDefaultProps,
xAxis: mockXAxisConfig,
});

expect(options.xAxis).toEqual(mockXAxisConfig);
});

test('should allow grid config to be overriden', () => {
const mockGridConfig = {
left: '6%',
right: '6%',
};
const options = createOptions<MockChartType>({
...createOptionsDefaultProps,
grid: mockGridConfig,
});

expect(options.grid).toEqual(mockGridConfig);
});
});

describe('createMarkLine', () => {
60 changes: 60 additions & 0 deletions locust/webui/src/components/LocustCloudTab/LocustCloudTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Box, Link, Typography } from '@mui/material';

import Markdown from 'components/Markdown/Markdown';
import { useSelector } from 'redux/hooks';

const firstParagraph = `
Ready to take your load tests to the next level? With [Locust Cloud](locust.cloud), we take care of everything!
\n
Whether your doing small load, or needing to generate millions of requests, we take care of the
load generation.
\n
Not sure where to start? Get professional load test consultation! We have over 20 years of experience load testing in a wide array of industries!
\n
Locust Cloud comes powered with a suite of features, including advanced graphs, stored testruns, open telemetry, and so much more!
`;

export default function LocustCloudTab() {
const isDarkMode = useSelector(({ theme: { isDarkMode } }) => isDarkMode);

return (
<Box>
<Box sx={{ mb: 2 }}>
<Typography component='h2' mb={1} variant='h4'>
Power Up Your Load Tests!
</Typography>
<Markdown content={firstParagraph} />
</Box>
<ul>
<li>
<Typography sx={{ mb: 2 }}>
Our main graphs offer a concise view of the most vital stats, and go further by allowing
you to dig into data for each requests in your testrun
</Typography>
{isDarkMode ? (
<img src='/assets/graphs-dark.png' width='100%' />
) : (
<img src='/assets/graphs-light.png' width='100%' />
)}
</li>
<li>
<Typography sx={{ mb: 2 }}>
The testruns tab offers a detailed overview of how your system has performed
historically. This allows you to easily track and detect any changes in the performance
of your system.
</Typography>
{isDarkMode ? (
<img src='/assets/testruns-dark.png' width='100%' />
) : (
<img src='/assets/testruns-light.png' width='100%' />
)}
<Typography>
Vist us at{' '}
<Link href='https://www.locust.cloud/get-started?plan=basic'>locust.cloud</Link> for a
free consultation today!
</Typography>
</li>
</ul>
</Box>
);
}
7 changes: 7 additions & 0 deletions locust/webui/src/components/Tabs/Tabs.constants.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import ExceptionsTab from 'components/ExceptionsTab/ExceptionsTab';
import FailuresTable from 'components/FailuresTable/FailuresTable';
import LocustCloudTab from 'components/LocustCloudTab/LocustCloudTab';
import LogViewer from 'components/LogViewer/LogViewer';
import Reports from 'components/Reports/Reports';
import StatsTable from 'components/StatsTable/StatsTable';
@@ -52,6 +53,11 @@ export const tabConfig = {
title: 'Workers',
shouldDisplayTab: (state: IRootState) => state.swarm.isDistributed,
},
locustCloud: {
component: LocustCloudTab,
key: 'locustcloud',
title: 'Locust Cloud',
},
};

export const baseTabs: ITab[] = [
@@ -63,4 +69,5 @@ export const baseTabs: ITab[] = [
tabConfig.reports,
tabConfig.logs,
tabConfig.workers,
tabConfig.locustCloud,
];
29 changes: 22 additions & 7 deletions locust/webui/src/hooks/tests/useSortByField.test.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react';
import { act, render } from '@testing-library/react';
import { describe, expect, test } from 'vitest';

@@ -21,13 +22,12 @@ function MockHook({
hasTotalRow?: boolean;
defaultSortKey?: keyof (typeof mockStats)[0];
}) {
const { onTableHeadClick, sortedRows, currentSortField } = useSortByField(
hasTotalRow ? mockStatsWithTotalRow : mockStats,
{
hasTotalRow,
defaultSortKey,
},
);
const [stats, setStats] = useState(hasTotalRow ? mockStatsWithTotalRow : mockStats);

const { onTableHeadClick, sortedRows, currentSortField } = useSortByField(stats, {
hasTotalRow,
defaultSortKey,
});

return (
<div>
@@ -45,6 +45,9 @@ function MockHook({
>
Sort by numFailures
</button>
<button data-testid='emptyStats' onClick={() => setStats([])}>
Empty stats
</button>
<span data-testid='sortedStats'>{JSON.stringify(sortedRows)}</span>
<span data-testid='currentSortField'>{currentSortField}</span>
</div>
@@ -127,4 +130,16 @@ describe('useSortByField', () => {
expect(getByTestId('sortedStats').textContent).toBe(JSON.stringify(mockStats));
expect(getByTestId('currentSortField').textContent).toBe('');
});

test('should allow the sorted rows to be set to empty', () => {
const { getByTestId } = render(<MockHook />);

expect(getByTestId('sortedStats').textContent).toBe(JSON.stringify(mockStats));

act(() => {
getByTestId('emptyStats').click();
});

expect(getByTestId('sortedStats').textContent).toBe(JSON.stringify([]));
});
});
3 changes: 3 additions & 0 deletions locust/webui/src/hooks/useSortByField.ts
Original file line number Diff line number Diff line change
@@ -77,6 +77,9 @@ export default function useSortByField<Row>(
useEffect(() => {
if (rows.length) {
sortStats(currentSortField.current || defaultSortKey);
} else if (sortStats.length) {
// allows tables to be empty in the case of filtering
setSortedRows(rows);
}
}, [rows]);

3 changes: 3 additions & 0 deletions locust/webui/src/pages/Auth.tsx
Original file line number Diff line number Diff line change
@@ -76,6 +76,9 @@ export default function Auth({
{info && !customForm && !usernamePasswordCallback && (
<Alert severity='info'>{<Markdown content={info} />}</Alert>
)}
{error && !customForm && !usernamePasswordCallback && (
<Alert severity='error'>{<Markdown content={error} />}</Alert>
)}
{authProviders && (
<Box sx={{ display: 'flex', flexDirection: 'column', rowGap: 1 }}>
{authProviders.map(({ label, callbackUrl, iconUrl }, index) => (
5 changes: 2 additions & 3 deletions locust/webui/src/styles/theme.ts
Original file line number Diff line number Diff line change
@@ -17,9 +17,8 @@ const createTheme = (mode: PaletteMode) =>
':root': {
'--footer-height': '40px',
},
p: {
margin: 0,
},
p: { margin: 0 },
ul: { paddingLeft: '16px' },
},
},
},
1 change: 1 addition & 0 deletions locust/webui/vite.lib.config.ts
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@ export default defineConfig((config: UserConfig) => ({
dts({
outDir: './lib/types',
exclude: ['**/*.test.ts', '**/*.test.tsx', '**/test', '**/tests'],
rollupTypes: true,
}),
config.mode !== 'production' &&
config.mode !== 'test' &&
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -193,7 +193,7 @@ extend-exclude = [
"examples/issue_*.py",
"src/readthedocs-sphinx-search/",
]
lint.ignore = ["E402", "E501", "E713", "E731", "E741", "F401"]
lint.ignore = ["E402", "E501", "E713", "E731", "E741"]
lint.select = ["E", "F", "W", "UP", "FA102", "I001"]

[tool.ruff.lint.per-file-ignores]