Skip to content

Commit 0af7072

Browse files
authored
Merge pull request #485 from radofuchs/LCORE_493_auth_e2e_tests
added e2e tests for authorized endpoint
2 parents 7d1d95e + 81244e1 commit 0af7072

File tree

9 files changed

+290
-55
lines changed

9 files changed

+290
-55
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Lightspeed Core Service (LCS)
2+
service:
3+
host: 0.0.0.0
4+
port: 8080
5+
auth_enabled: false
6+
workers: 1
7+
color_log: true
8+
access_log: true
9+
llama_stack:
10+
# Uses a remote llama-stack service
11+
# The instance would have already been started with a llama-stack-run.yaml file
12+
use_as_library_client: false
13+
# Alternative for "as library use"
14+
# use_as_library_client: true
15+
# library_client_config_path: <path-to-llama-stack-run.yaml-file>
16+
url: http://llama-stack:8321
17+
api_key: xyzzy
18+
user_data_collection:
19+
feedback_enabled: true
20+
feedback_storage: "/tmp/data/feedback"
21+
transcripts_enabled: true
22+
transcripts_storage: "/tmp/data/transcripts"
23+
24+
authentication:
25+
module: "noop-with-token"

tests/e2e/features/authorized.feature

Lines changed: 0 additions & 34 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
Feature: Authorized endpoint API tests for the noop authentication module
2+
3+
Background:
4+
Given The service is started locally
5+
And REST API service hostname is localhost
6+
And REST API service port is 8080
7+
And REST API service prefix is /v1
8+
9+
Scenario: Check if the authorized endpoint works fine when user_id and auth header are not provided
10+
Given The system is in default state
11+
When I access endpoint "authorized" using HTTP POST method
12+
"""
13+
{"placeholder":"abc"}
14+
"""
15+
Then The status code of the response is 200
16+
And The body of the response is the following
17+
"""
18+
{"user_id": "00000000-0000-0000-0000-000","username": "lightspeed-user"}
19+
"""
20+
21+
Scenario: Check if the authorized endpoint works when auth token is not provided
22+
Given The system is in default state
23+
When I access endpoint "authorized" using HTTP POST method with user_id "test_user"
24+
Then The status code of the response is 200
25+
And The body of the response is the following
26+
"""
27+
{"user_id": "test_user","username": "lightspeed-user"}
28+
"""
29+
30+
Scenario: Check if the authorized endpoint works when user_id is not provided
31+
Given The system is in default state
32+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
33+
When I access endpoint "authorized" using HTTP POST method without user_id
34+
Then The status code of the response is 200
35+
And The body of the response is the following
36+
"""
37+
{"user_id": "00000000-0000-0000-0000-000","username": "lightspeed-user"}
38+
"""
39+
40+
Scenario: Check if the authorized endpoint works when providing empty user_id
41+
Given The system is in default state
42+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
43+
When I access endpoint "authorized" using HTTP POST method with user_id ""
44+
Then The status code of the response is 200
45+
And The body of the response is the following
46+
"""
47+
{"user_id": "","username": "lightspeed-user"}
48+
"""
49+
50+
Scenario: Check if the authorized endpoint works when providing proper user_id
51+
Given The system is in default state
52+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
53+
When I access endpoint "authorized" using HTTP POST method with user_id "test_user"
54+
Then The status code of the response is 200
55+
And The body of the response is the following
56+
"""
57+
{"user_id": "test_user","username": "lightspeed-user"}
58+
"""
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
@Authorized
2+
Feature: Authorized endpoint API tests for the noop-with-token
3+
4+
Background:
5+
Given The service is started locally
6+
And REST API service hostname is localhost
7+
And REST API service port is 8080
8+
And REST API service prefix is /v1
9+
10+
Scenario: Check if the authorized endpoint fails when user_id and auth header are not provided
11+
Given The system is in default state
12+
When I access endpoint "authorized" using HTTP POST method
13+
"""
14+
{"placeholder":"abc"}
15+
"""
16+
Then The status code of the response is 400
17+
And The body of the response is the following
18+
"""
19+
{"detail": "No Authorization header found"}
20+
"""
21+
22+
Scenario: Check if the authorized endpoint works when user_id is not provided
23+
Given The system is in default state
24+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
25+
When I access endpoint "authorized" using HTTP POST method without user_id
26+
Then The status code of the response is 200
27+
And The body of the response is the following
28+
"""
29+
{"user_id": "00000000-0000-0000-0000-000","username": "lightspeed-user"}
30+
"""
31+
32+
Scenario: Check if the authorized endpoint works when providing empty user_id
33+
Given The system is in default state
34+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
35+
When I access endpoint "authorized" using HTTP POST method with user_id ""
36+
Then The status code of the response is 200
37+
And The body of the response is the following
38+
"""
39+
{"user_id": "","username": "lightspeed-user"}
40+
"""
41+
42+
Scenario: Check if the authorized endpoint works when providing proper user_id
43+
Given The system is in default state
44+
And I set the Authorization header to Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
45+
When I access endpoint "authorized" using HTTP POST method with user_id "test_user"
46+
Then The status code of the response is 200
47+
And The body of the response is the following
48+
"""
49+
{"user_id": "test_user","username": "lightspeed-user"}
50+
"""
51+
52+
Scenario: Check if the authorized endpoint works with proper user_id but bearer token is not present
53+
Given The system is in default state
54+
When I access endpoint "authorized" using HTTP POST method with user_id "test_user"
55+
Then The status code of the response is 400
56+
And The body of the response is the following
57+
"""
58+
{"detail": "No Authorization header found"}
59+
"""
60+
61+
Scenario: Check if the authorized endpoint works when auth token is malformed
62+
Given The system is in default state
63+
And I set the Authorization header to BearereyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpva
64+
When I access endpoint "authorized" using HTTP POST method with user_id "test_user"
65+
Then The status code of the response is 400
66+
And The body of the response is the following
67+
"""
68+
{"detail": "No token found in Authorization header"}
69+
"""

tests/e2e/features/environment.py

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99

1010
import subprocess
1111
import time
12-
from behave.model import Scenario
12+
from behave.model import Scenario, Feature
1313
from behave.runner import Context
1414

15+
from tests.e2e.utils.utils import switch_config_and_restart
16+
1517
try:
1618
import os # noqa: F401
1719
except ImportError as e:
@@ -82,5 +84,22 @@ def after_scenario(context: Context, scenario: Scenario) -> None:
8284
print(f"Warning: Could not restore Llama Stack connection: {e}")
8385

8486

85-
def before_feature(context: Context, feature: Scenario) -> None:
87+
def before_feature(context: Context, feature: Feature) -> None:
8688
"""Run before each feature file is exercised."""
89+
if "Authorized" in feature.tags:
90+
context.backup_file = switch_config_and_restart(
91+
"lightspeed-stack.yaml",
92+
"tests/e2e/configuration/lightspeed-stack-auth-noop-token.yaml",
93+
"lightspeed-stack",
94+
)
95+
96+
97+
def after_feature(context: Context, feature: Feature) -> None:
98+
"""Run after each feature file is exercised."""
99+
if "Authorized" in feature.tags:
100+
switch_config_and_restart(
101+
"lightspeed-stack.yaml",
102+
context.backup_file,
103+
"lightspeed-stack",
104+
cleanup=True,
105+
)

tests/e2e/features/steps/auth.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,60 @@
11
"""Implementation of common test steps."""
22

3-
from behave import given, then # pyright: ignore[reportAttributeAccessIssue]
3+
import requests
4+
from behave import given, when # pyright: ignore[reportAttributeAccessIssue]
45
from behave.runner import Context
6+
from tests.e2e.utils.utils import normalize_endpoint
57

68

7-
@then("The body of the response has proper username")
8-
def check_body_username(context: Context) -> None:
9-
"""Check that the username is correct in response."""
10-
# TODO: add step implementation
11-
assert context is not None
9+
@given("I set the Authorization header to {header_value}")
10+
def set_authorization_header_custom(context: Context, header_value: str) -> None:
11+
"""Set a custom Authorization header value."""
12+
if not hasattr(context, "auth_headers"):
13+
context.auth_headers = {}
14+
context.auth_headers["Authorization"] = header_value
15+
print(f"🔑 Set Authorization header to: {header_value}")
1216

1317

14-
@given("I remove the auth header")
15-
def remove_auth_header(context: Context) -> None:
16-
"""Remove the auth header."""
17-
# TODO: add step implementation
18-
assert context is not None
18+
@when("I access endpoint {endpoint} using HTTP POST method with user_id {user_id}")
19+
def access_rest_api_endpoint_post(
20+
context: Context, endpoint: str, user_id: str
21+
) -> None:
22+
"""Send POST HTTP request with payload in the endpoint as parameter to tested service.
1923
24+
The response is stored in `context.response` attribute.
25+
"""
26+
endpoint = normalize_endpoint(endpoint)
27+
user_id = user_id.replace('"', "")
28+
base = f"http://{context.hostname}:{context.port}"
29+
path = f"{endpoint}?user_id={user_id}".replace("//", "/")
30+
url = base + path
2031

21-
@given("I modify the auth header so that the user is it authorized")
22-
def modify_auth_header(context: Context) -> None:
23-
"""Modify the auth header making the user unauthorized."""
24-
# TODO: add step implementation
25-
assert context is not None
32+
if not hasattr(context, "auth_headers"):
33+
context.auth_headers = {}
34+
35+
# perform REST API call
36+
context.response = requests.post(
37+
url, json="", headers=context.auth_headers, timeout=10
38+
)
39+
40+
41+
@when("I access endpoint {endpoint} using HTTP POST method without user_id")
42+
def access_rest_api_endpoint_post_without_param(
43+
context: Context, endpoint: str
44+
) -> None:
45+
"""Send POST HTTP request without user_id payload.
46+
47+
The response is stored in `context.response` attribute.
48+
"""
49+
endpoint = normalize_endpoint(endpoint)
50+
base = f"http://{context.hostname}:{context.port}"
51+
path = f"{endpoint}".replace("//", "/")
52+
url = base + path
53+
54+
if not hasattr(context, "auth_headers"):
55+
context.auth_headers = {}
56+
57+
# perform REST API call
58+
context.response = requests.post(
59+
url, json="", headers=context.auth_headers, timeout=10
60+
)

tests/e2e/features/steps/common_http.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,17 @@ def access_rest_api_endpoint_get(context: Context, endpoint: str) -> None:
241241
context.response = requests.get(url, timeout=DEFAULT_TIMEOUT)
242242

243243

244-
@when("I access endpoint {endpoint:w} using HTTP POST method")
244+
@when("I access endpoint {endpoint} using HTTP POST method")
245245
def access_rest_api_endpoint_post(context: Context, endpoint: str) -> None:
246246
"""Send POST HTTP request with JSON payload to tested service.
247247
248248
The JSON payload is retrieved from `context.text` attribute,
249249
which must not be None. The response is stored in
250250
`context.response` attribute.
251251
"""
252+
endpoint = normalize_endpoint(endpoint)
252253
base = f"http://{context.hostname}:{context.port}"
253-
path = f"{context.api_prefix}/{endpoint}".replace("//", "/")
254+
path = f"{endpoint}".replace("//", "/")
254255
url = base + path
255256

256257
assert context.text is not None, "Payload needs to be specified"

tests/e2e/test_list.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
features/smoketests.feature
2-
features/authorized.feature
2+
features/authorized_noop.feature
3+
features/authorized_noop_token.feature
34
features/conversations.feature
45
features/feedback.feature
56
features/health.feature

0 commit comments

Comments
 (0)