initial tests for frant and back end
This commit is contained in:
parent
b4428e7048
commit
c26c2bb7e5
|
|
@ -0,0 +1,3 @@
|
|||
# backend/requirements-dev.txt
|
||||
pytest
|
||||
pytest-dotenv # loads .env before running tests (optional)
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
# backend/tests/test_api.py
|
||||
"""
|
||||
Simple smoke–test suite for the ComplyCore FastAPI backend.
|
||||
|
||||
Run with:
|
||||
poetry install --with dev # or `pip install -r requirements-dev.txt`
|
||||
pytest backend/tests # or simply `pytest` at repo root
|
||||
"""
|
||||
|
||||
import os
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
import jwt # PyJWT
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
# ---- local import of your FastAPI app ---------------------------------------
|
||||
from backend.main import app # adjusts if your main.py lives elsewhere
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Helpers #
|
||||
# --------------------------------------------------------------------------- #
|
||||
def make_test_jwt(
|
||||
user_id: str = "00000000-0000-0000-0000-000000000002",
|
||||
email: str = "testuser@complycore.dev",
|
||||
role: str = "authenticated",
|
||||
) -> str:
|
||||
"""
|
||||
Craft a short-lived JWT signed with the same secret the API expects.
|
||||
"""
|
||||
secret = os.getenv("SUPABASE_JWT_SECRET", "NOT_SET")
|
||||
if secret == "NOT_SET":
|
||||
raise RuntimeError(
|
||||
"SUPABASE_JWT_SECRET not loaded – copy backend/.env.example → "
|
||||
".env and set your secret before running the tests"
|
||||
)
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
payload = {
|
||||
"sub": user_id,
|
||||
"aud": "authenticated",
|
||||
"role": role,
|
||||
"email": email,
|
||||
"iat": int(now.timestamp()),
|
||||
"exp": int((now + timedelta(minutes=10)).timestamp()),
|
||||
"iss": "supabase",
|
||||
"email_confirmed_at": now.isoformat(),
|
||||
}
|
||||
return jwt.encode(payload, secret, algorithm="HS256")
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Tests #
|
||||
# --------------------------------------------------------------------------- #
|
||||
def test_healthz():
|
||||
r = client.get("/healthz")
|
||||
assert r.status_code == 200
|
||||
assert r.json() == {"status": "ok"}
|
||||
|
||||
|
||||
@pytest.mark.skipif(
|
||||
os.getenv("CI") == "true",
|
||||
reason="Requires network access to Supabase; skip on CI",
|
||||
)
|
||||
def test_supabase_check():
|
||||
"""
|
||||
Only a connectivity smoke test – we don’t assert DB/user values because
|
||||
those differ per environment, we just ensure *something* comes back.
|
||||
"""
|
||||
r = client.get("/supabase-check")
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
assert body.get("status") == "connected"
|
||||
assert "db" in body and "user" in body
|
||||
|
||||
|
||||
def test_me_authorized():
|
||||
token = make_test_jwt()
|
||||
r = client.get("/me", headers={"Authorization": f"Bearer {token}"})
|
||||
assert r.status_code == 200
|
||||
body = r.json()
|
||||
assert body["id"] == "00000000-0000-0000-0000-000000000002"
|
||||
assert body["email"] == "testuser@complycore.dev"
|
||||
assert body["role"] == "authenticated"
|
||||
|
||||
|
||||
def test_me_unauthorized():
|
||||
r = client.get("/me") # no token
|
||||
assert r.status_code == 401
|
||||
|
|
@ -37,6 +37,8 @@ dependencies:
|
|||
supabase_flutter: ^2.9.1
|
||||
flutter_dotenv: ^5.2.1
|
||||
gotrue: ^2.13.0
|
||||
http: ^1.2.0
|
||||
dart_jsonwebtoken: ^2.12.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
// frontend/complycore_flutter/test/api_smoke_test.dart
|
||||
//
|
||||
// Basic integration-style smoke tests that hit the running ComplyCore
|
||||
// FastAPI backend from a Flutter test runner.
|
||||
//
|
||||
// Run with:
|
||||
//
|
||||
// flutter test --dart-define=SUPABASE_JWT_SECRET=your_secret_here
|
||||
//
|
||||
// …while the backend is already up on http://localhost:8000.
|
||||
//
|
||||
// If you need a different host/port, override at the top of this file
|
||||
// or pass --dart-define=API_BASE_URL=http://YOUR_HOST:PORT
|
||||
//
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart';
|
||||
|
||||
/// Base URL for the API the tests will hit.
|
||||
/// Override at runtime with:
|
||||
/// flutter test --dart-define=API_BASE_URL=http://192.168.1.50:8000
|
||||
const String _apiBaseUrl = const String.fromEnvironment(
|
||||
'API_BASE_URL',
|
||||
defaultValue: 'http://localhost:8000',
|
||||
);
|
||||
|
||||
/// Build a short-lived JWT signed with the same secret the backend expects.
|
||||
String _buildJwt({
|
||||
String userId = '00000000-0000-0000-0000-000000000002',
|
||||
String email = 'testuser@complycore.dev',
|
||||
String role = 'authenticated',
|
||||
}) {
|
||||
final secret = const String.fromEnvironment(
|
||||
'SUPABASE_JWT_SECRET',
|
||||
defaultValue: 'NOT_SET',
|
||||
);
|
||||
|
||||
if (secret == 'NOT_SET') {
|
||||
throw StateError(
|
||||
'SUPABASE_JWT_SECRET not provided.\n'
|
||||
'Run tests with:\n'
|
||||
' flutter test --dart-define=SUPABASE_JWT_SECRET=your_secret_here',
|
||||
);
|
||||
}
|
||||
|
||||
final now = DateTime.now().toUtc();
|
||||
final jwt = JWT({
|
||||
'sub': userId,
|
||||
'aud': 'authenticated',
|
||||
'role': role,
|
||||
'email': email,
|
||||
'iat': (now.millisecondsSinceEpoch / 1000).floor(),
|
||||
'exp': (now.add(const Duration(minutes: 10)).millisecondsSinceEpoch / 1000)
|
||||
.floor(),
|
||||
'iss': 'supabase',
|
||||
'email_confirmed_at': now.toIso8601String(),
|
||||
});
|
||||
|
||||
return jwt.sign(SecretKey(secret), algorithm: JWTAlgorithm.HS256);
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('ComplyCore API smoke tests (Flutter)', () {
|
||||
test('GET /healthz → 200 {"status":"ok"}', () async {
|
||||
final res = await http.get(Uri.parse('$_apiBaseUrl/healthz'));
|
||||
expect(res.statusCode, 200);
|
||||
expect(jsonDecode(res.body)['status'], 'ok');
|
||||
});
|
||||
|
||||
test(
|
||||
'GET /supabase-check → 200, status=="connected"',
|
||||
() async {
|
||||
final res = await http.get(Uri.parse('$_apiBaseUrl/supabase-check'));
|
||||
expect(res.statusCode, 200);
|
||||
final body = jsonDecode(res.body);
|
||||
expect(body['status'], 'connected');
|
||||
},
|
||||
skip: const bool.fromEnvironment('CI', defaultValue: false),
|
||||
); // skip on CI
|
||||
|
||||
test('GET /me with valid JWT → 200, correct email', () async {
|
||||
final token = _buildJwt();
|
||||
final res = await http.get(
|
||||
Uri.parse('$_apiBaseUrl/me'),
|
||||
headers: {'Authorization': 'Bearer $token'},
|
||||
);
|
||||
|
||||
expect(res.statusCode, 200);
|
||||
final body = jsonDecode(res.body) as Map<String, dynamic>;
|
||||
expect(body['email'], 'testuser@complycore.dev');
|
||||
expect(body['role'], 'authenticated');
|
||||
});
|
||||
|
||||
test('GET /me without token → 401/403', () async {
|
||||
final res = await http.get(Uri.parse('$_apiBaseUrl/me'));
|
||||
expect(res.statusCode, anyOf(401, 403));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:complycore_flutter/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
Loading…
Reference in New Issue