expose the output via api (#1223)

* expose the output via api

* remove mocks from job testing
This commit is contained in:
Henry Ruhs
2026-08-24 13:46:22 +02:00
committed by GitHub
parent 1bae62ad26
commit 4d3d2094ec
5 changed files with 207 additions and 71 deletions
+150 -60
View File
@@ -1,24 +1,37 @@
import os
from typing import Iterator
from unittest.mock import patch
import pytest
from starlette.testclient import TestClient
from facefusion import metadata, session_manager
from facefusion import metadata, session_manager, state_manager
from facefusion.apis import asset_store
from facefusion.apis.core import create_api
from facefusion.jobs.job_manager import clear_jobs, count_step_total, create_job, find_job_ids, init_jobs
from facefusion.download import conditional_download
from facefusion.jobs.job_manager import clear_jobs, count_step_total, create_job, find_job_ids, init_jobs, move_job_file, set_steps_status
from facefusion.program import create_program
from .assert_helper import get_test_jobs_directory
from .assert_helper import get_test_example_file, get_test_examples_directory, get_test_jobs_directory
@pytest.fixture(scope = 'module', autouse = True)
def before_all() -> None:
create_program()
conditional_download(get_test_examples_directory(),
[
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/source.jpg',
'https://github.com/facefusion/facefusion-assets/releases/download/examples-3.0.0/target-240p.mp4'
])
@pytest.fixture(scope = 'function', autouse = True)
def before_each() -> None:
session_manager.SESSIONS.clear()
asset_store.clear()
state_manager.init_item('source_paths', [ get_test_example_file('source.jpg') ])
state_manager.init_item('target_path', get_test_example_file('target-240p.mp4'))
state_manager.init_item('temp_path', get_test_jobs_directory())
clear_jobs(get_test_jobs_directory())
init_jobs(get_test_jobs_directory())
@@ -166,15 +179,23 @@ def test_submit_jobs(test_client : TestClient) -> None:
assert submit_jobs_body.get('message') == 'jobs not submitted'
assert submit_jobs_response.status_code == 400
with patch('facefusion.jobs.job_manager.submit_jobs', return_value = True):
submit_jobs_response = test_client.patch('/jobs?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
submit_jobs_body = submit_jobs_response.json()
test_client.post('/jobs/job-test-submit-jobs?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
assert submit_jobs_body.get('message') == 'ok'
assert submit_jobs_response.status_code == 200
submit_jobs_response = test_client.patch('/jobs?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
submit_jobs_body = submit_jobs_response.json()
assert submit_jobs_body.get('message') == 'ok'
assert find_job_ids('queued') == [ 'job-test-submit-jobs' ]
assert submit_jobs_response.status_code == 200
def test_submit_job(test_client : TestClient) -> None:
@@ -209,15 +230,23 @@ def test_submit_job(test_client : TestClient) -> None:
assert submit_job_body.get('message') == 'job not submitted'
assert submit_job_response.status_code == 400
with patch('facefusion.jobs.job_manager.submit_job', return_value = True):
submit_job_response = test_client.patch('/jobs/job-test-submit-job?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
submit_job_body = submit_job_response.json()
test_client.post('/jobs/job-test-submit-job?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
assert submit_job_body.get('message') == 'ok'
assert submit_job_response.status_code == 200
submit_job_response = test_client.patch('/jobs/job-test-submit-job?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
submit_job_body = submit_job_response.json()
assert submit_job_body.get('message') == 'ok'
assert find_job_ids('queued') == [ 'job-test-submit-job' ]
assert submit_job_response.status_code == 200
def test_run_jobs(test_client : TestClient) -> None:
@@ -241,17 +270,29 @@ def test_run_jobs(test_client : TestClient) -> None:
assert run_jobs_body.get('message') == 'jobs not run'
assert run_jobs_response.status_code == 400
with patch('facefusion.jobs.job_manager.find_job_ids', return_value = [ 'job-test-run-jobs' ]):
with patch('facefusion.jobs.job_runner.run_jobs', return_value = True) as run_jobs_mock:
run_jobs_response = test_client.patch('/jobs?action=run', headers =
{
'Authorization': 'Bearer ' + access_token
})
run_jobs_body = run_jobs_response.json()
create_job('job-test-run-jobs')
test_client.post('/jobs/job-test-run-jobs?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
test_client.patch('/jobs/job-test-run-jobs?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
assert run_jobs_body.get('message') == 'ok'
assert run_jobs_response.status_code == 202
assert run_jobs_mock.called is True
with patch('facefusion.jobs.job_runner.run_jobs', return_value = True) as run_jobs_mock:
run_jobs_response = test_client.patch('/jobs?action=run', headers =
{
'Authorization': 'Bearer ' + access_token
})
run_jobs_body = run_jobs_response.json()
assert run_jobs_body.get('message') == 'ok'
assert run_jobs_response.status_code == 202
assert run_jobs_mock.called is True
def test_run_job(test_client : TestClient) -> None:
@@ -277,17 +318,28 @@ def test_run_job(test_client : TestClient) -> None:
assert run_job_body.get('message') == 'job not run'
assert run_job_response.status_code == 400
with patch('facefusion.jobs.job_manager.find_job_ids', return_value = [ 'job-test-run-job' ]):
with patch('facefusion.jobs.job_runner.run_job', return_value = True) as run_job_mock:
run_job_response = test_client.patch('/jobs/job-test-run-job?action=run', headers =
{
'Authorization': 'Bearer ' + access_token
})
run_job_body = run_job_response.json()
test_client.post('/jobs/job-test-run-job?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
test_client.patch('/jobs/job-test-run-job?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
assert run_job_body.get('message') == 'ok'
assert run_job_response.status_code == 202
assert run_job_mock.called is True
with patch('facefusion.jobs.job_runner.run_job', return_value = True) as run_job_mock:
run_job_response = test_client.patch('/jobs/job-test-run-job?action=run', headers =
{
'Authorization': 'Bearer ' + access_token
})
run_job_body = run_job_response.json()
assert run_job_body.get('message') == 'ok'
assert run_job_response.status_code == 202
assert run_job_mock.called is True
def test_retry_jobs(test_client : TestClient) -> None:
@@ -311,17 +363,31 @@ def test_retry_jobs(test_client : TestClient) -> None:
assert retry_jobs_body.get('message') == 'jobs not retried'
assert retry_jobs_response.status_code == 400
with patch('facefusion.jobs.job_manager.find_job_ids', return_value = [ 'job-test-retry-jobs' ]):
with patch('facefusion.jobs.job_runner.retry_jobs', return_value = True) as retry_jobs_mock:
retry_jobs_response = test_client.patch('/jobs?action=retry', headers =
{
'Authorization': 'Bearer ' + access_token
})
retry_jobs_body = retry_jobs_response.json()
create_job('job-test-retry-jobs')
test_client.post('/jobs/job-test-retry-jobs?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
test_client.patch('/jobs/job-test-retry-jobs?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
set_steps_status('job-test-retry-jobs', 'failed')
move_job_file('job-test-retry-jobs', 'failed')
assert retry_jobs_body.get('message') == 'ok'
assert retry_jobs_response.status_code == 202
assert retry_jobs_mock.called is True
with patch('facefusion.jobs.job_runner.retry_jobs', return_value = True) as retry_jobs_mock:
retry_jobs_response = test_client.patch('/jobs?action=retry', headers =
{
'Authorization': 'Bearer ' + access_token
})
retry_jobs_body = retry_jobs_response.json()
assert retry_jobs_body.get('message') == 'ok'
assert retry_jobs_response.status_code == 202
assert retry_jobs_mock.called is True
def test_retry_job(test_client : TestClient) -> None:
@@ -345,17 +411,31 @@ def test_retry_job(test_client : TestClient) -> None:
assert retry_job_body.get('message') == 'job not retried'
assert retry_job_response.status_code == 400
with patch('facefusion.jobs.job_manager.find_job_ids', return_value = [ 'job-test-retry-job' ]):
with patch('facefusion.jobs.job_runner.retry_job', return_value = True) as retry_job_mock:
retry_job_response = test_client.patch('/jobs/job-test-retry-job?action=retry', headers =
{
'Authorization': 'Bearer ' + access_token
})
retry_job_body = retry_job_response.json()
create_job('job-test-retry-job')
test_client.post('/jobs/job-test-retry-job?action=add', headers =
{
'Authorization': 'Bearer ' + access_token
}, json =
{
'processors': [ 'face_swapper' ]
})
test_client.patch('/jobs/job-test-retry-job?action=submit', headers =
{
'Authorization': 'Bearer ' + access_token
})
set_steps_status('job-test-retry-job', 'failed')
move_job_file('job-test-retry-job', 'failed')
assert retry_job_body.get('message') == 'ok'
assert retry_job_response.status_code == 202
assert retry_job_mock.called is True
with patch('facefusion.jobs.job_runner.retry_job', return_value = True) as retry_job_mock:
retry_job_response = test_client.patch('/jobs/job-test-retry-job?action=retry', headers =
{
'Authorization': 'Bearer ' + access_token
})
retry_job_body = retry_job_response.json()
assert retry_job_body.get('message') == 'ok'
assert retry_job_response.status_code == 202
assert retry_job_mock.called is True
def test_delete_jobs(test_client : TestClient) -> None:
@@ -445,6 +525,7 @@ def test_create_step(test_client : TestClient) -> None:
'Authorization': 'Bearer ' + access_token
}, json =
{
'target_path': 'invalid.mp4',
'processors': [ 'face_swapper' ]
})
create_step_body = create_step_response.json()
@@ -458,8 +539,17 @@ def test_create_step(test_client : TestClient) -> None:
'Authorization': 'Bearer ' + access_token
})
get_job_body = get_job_response.json()
step_args = get_job_body.get('steps')[0].get('args')
assert get_job_body.get('steps')[0].get('args') == { 'processors': [ 'face_swapper' ] }
access_session_id = session_manager.find_session_id(access_token)
assert step_args ==\
{
'processors': [ 'face_swapper' ],
'source_paths': [ get_test_example_file('source.jpg') ],
'target_path': get_test_example_file('target-240p.mp4'),
'output_path': os.path.join(get_test_jobs_directory(), access_session_id, 'job-test-create-step.mp4')
}
create_step_response = test_client.post('/jobs/job-test-create-step/0?action=insert', headers =
{