Skip to content

Commit 045de46

Browse files
authored
Improved mock DevRev Server (#21)
Improved mock DevRev Server: - added ability to reset state (and adding a call for it to jest.setup.js) - storing info if artifacts was uploaded (and added an endpoint to be able to check it from the acceptance tests) Related issue: https://app.devrev.ai/devrev/works/ISS-206307
1 parent 8a5cdd0 commit 045de46

File tree

2 files changed

+89
-6
lines changed

2 files changed

+89
-6
lines changed

jest.setup.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,59 @@ global.test = (name, fn, timeout) => {
7676
}, timeout);
7777
};
7878

79+
// Function to reset the mock server state
80+
const resetMockServer = async () => {
81+
try {
82+
const http = require('http');
83+
84+
// Simple HTTP request that properly closes the connection
85+
const postData = '';
86+
const options = {
87+
hostname: 'localhost',
88+
port: 8003,
89+
path: '/reset-mock-server',
90+
method: 'POST',
91+
headers: {
92+
'Content-Type': 'application/json',
93+
'Content-Length': Buffer.byteLength(postData)
94+
}
95+
};
96+
97+
const response = await new Promise((resolve, reject) => {
98+
const req = http.request(options, (res) => {
99+
let data = '';
100+
res.on('data', (chunk) => data += chunk);
101+
res.on('end', () => resolve({ status: res.statusCode, data }));
102+
});
103+
104+
req.on('error', reject);
105+
req.on('timeout', () => {
106+
req.destroy();
107+
reject(new Error('Request timeout'));
108+
});
109+
110+
req.setTimeout(5000);
111+
req.write(postData);
112+
req.end();
113+
});
114+
115+
if (response.status !== 200) {
116+
console.warn(`Failed to reset mock server: ${response.status}`);
117+
}
118+
} catch (error) {
119+
console.warn(`Could not connect to mock server for reset: ${error.message}`);
120+
}
121+
};
122+
79123
const originalBeforeEach = global.beforeEach;
80124

81125
global.beforeEach = (fn, timeout) => {
82126
originalBeforeEach(async () => {
83127
try {
128+
// Reset the mock server state before each test
129+
await resetMockServer();
130+
131+
// Execute the original beforeEach function
84132
await fn();
85133
} catch (err) {
86134
expect(`beforeEach failed: ${err.message}`).toBe('beforeEach should not fail');

mock_devrev_server.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
import uuid
55
import json
66
import random
7+
import copy
78

89
app = FastAPI()
910

11+
# Initialize application state containers
12+
app.state.uploaded_states = {}
13+
app.state.uploaded_artifacts = set()
14+
1015
class ArtifactPrepareRequest(BaseModel):
1116
file_name: str
1217
file_type: str
@@ -28,6 +33,13 @@ class AirdropArtifactResponse(BaseModel):
2833
upload_url: str
2934
form_data: Dict[str, str]
3035

36+
@app.get("/is_uploaded/{artifact_id:path}")
37+
async def was_artifact_uploaded(artifact_id: str):
38+
"""Check if an artifact with the given artifact_id was uploaded"""
39+
if artifact_id in app.state.uploaded_artifacts:
40+
return {"artifact_id": artifact_id, "uploaded": True}
41+
raise HTTPException(status_code=404, detail="Artifact not found")
42+
3143
@app.post("/upload/{artifact_id:path}")
3244
async def upload_artifact(
3345
artifact_id: str,
@@ -41,6 +53,9 @@ async def upload_artifact(
4153
print(f"Content length: {len(content)}")
4254
print(f"Content type: {request.headers.get('content-type', 'unknown')}")
4355

56+
# Remember that this artifact_id was uploaded
57+
app.state.uploaded_artifacts.add(artifact_id)
58+
4459
return {"status": "success", "message": "File uploaded successfully"}
4560
except Exception as e:
4661
raise HTTPException(status_code=400, detail=str(e))
@@ -70,9 +85,11 @@ async def prepare_artifact(
7085
)
7186

7287
@app.get("/external-worker.get", response_model=ExternalWorkerResponse)
73-
async def get_external_worker():
74-
print("Received /external-worker.get GET body:")
75-
state = {
88+
async def get_external_worker(sync_unit: str):
89+
print(f"Received /external-worker.get GET request for sync_unit: {sync_unit}")
90+
91+
# Default state
92+
default_state = {
7693
"lastSyncStarted": "2024-06-01T12:00:00Z",
7794
"toDevRev": {
7895
"attachmentsMetadata": {
@@ -89,14 +106,24 @@ async def get_external_worker():
89106
"offset": 0
90107
}
91108
}
92-
return ExternalWorkerResponse(state=json.dumps(state))
109+
110+
# Check if uploaded_states contains the specific sync_unit
111+
if sync_unit in app.state.uploaded_states:
112+
print(f"Found uploaded state for sync_unit: {sync_unit}")
113+
return ExternalWorkerResponse(state=json.dumps(app.state.uploaded_states[sync_unit]))
114+
else:
115+
print(f"No uploaded state found for sync_unit: {sync_unit}, returning default state")
116+
return ExternalWorkerResponse(state=json.dumps(default_state))
93117

94118
@app.post("/external-worker.update")
95-
async def update_external_worker(request: Request):
119+
async def update_external_worker(sync_unit: str, request: Request):
96120
body = await request.body()
97-
print("Received /external-worker.update POST body:")
121+
print(f"Received /external-worker.update POST request for sync_unit: {sync_unit}")
98122
try:
99123
parsed = json.loads(body.decode("utf-8"))
124+
# Store the uploaded state under the specific sync_unit key
125+
app.state.uploaded_states[sync_unit] = copy.deepcopy(parsed)
126+
print(f"Stored state for sync_unit: {sync_unit}")
100127
print(json.dumps(parsed, indent=2))
101128
except Exception as e:
102129
print("Failed to pretty print JSON:", e)
@@ -148,6 +175,14 @@ async def confirm_upload(request: Request):
148175

149176
return {"status": "success"}
150177

178+
@app.post("/reset-mock-server")
179+
async def reset_mock_server():
180+
"""Reset the mock server state by clearing uploaded_states and uploaded_artifacts"""
181+
app.state.uploaded_states = {}
182+
app.state.uploaded_artifacts = set()
183+
print("Mock server state reset - uploaded_states and uploaded_artifacts cleared")
184+
return {"status": "success", "message": "Mock server state reset successfully"}
185+
151186
if __name__ == "__main__":
152187
import uvicorn
153188
uvicorn.run(app, host="localhost", port=8003)

0 commit comments

Comments
 (0)