async def test_http_methods(client): async with respx.mock: url = "https://foo.bar" route = respx.get(url, path="/") % 404 respx.post(url, path="/").respond(200) respx.post(url, path="/").respond(201) respx.put(url, path="/").respond(202) respx.patch(url, path="/").respond(500) respx.delete(url, path="/").respond(204) respx.head(url, path="/").respond(405) respx.options(url, path="/").respond(status_code=501) respx.request("GET", url, path="/baz/").respond(status_code=204) url += "/" response = httpx.get(url) assert response.status_code == 404 response = await client.get(url) assert response.status_code == 404 response = httpx.get(url + "baz/") assert response.status_code == 204 response = await client.get(url + "baz/") assert response.status_code == 204 response = httpx.post(url) assert response.status_code == 201 response = await client.post(url) assert response.status_code == 201 response = httpx.put(url) assert response.status_code == 202 response = await client.put(url) assert response.status_code == 202 response = httpx.patch(url) assert response.status_code == 500 response = await client.patch(url) assert response.status_code == 500 response = httpx.delete(url) assert response.status_code == 204 response = await client.delete(url) assert response.status_code == 204 response = httpx.head(url) assert response.status_code == 405 response = await client.head(url) assert response.status_code == 405 response = httpx.options(url) assert response.status_code == 501 response = await client.options(url) assert response.status_code == 501 assert route.called is True assert respx.calls.call_count == 8 * 2
def test_raise_on_request_error(client: Client) -> None: """If raise exception on a request error.""" respx.put( re.compile(PLATFORM_URL + "/api/v1/requests/.*$"), content=httpcore.ConnectError(), ) # TODO: do we really want to leak httpx to our clients? # We could catch all exception thrown by httpx, wrap it in a few library # exceptions and rethrow those. with pytest.raises(httpx.ConnectError): client.put(client.identity.public_identity)
def test_replace_namespaced(client: lightkube.Client): req = respx.put("https://localhost:9443/api/v1/namespaces/default/pods/xy").respond(json={'metadata': {'name': 'xy'}}) pod = client.replace(Pod(metadata=ObjectMeta(name="xy"))) assert req.calls[0][0].read() == b'{"metadata": {"name": "xy"}}' assert pod.metadata.name == 'xy' respx.put("https://localhost:9443/api/v1/namespaces/other/pods/xz").respond(json={'metadata': {'name': 'xz'}}) pod = client.replace(Pod(metadata=ObjectMeta(name="xz")), namespace='other') assert pod.metadata.name == 'xz' # namespace inside object definition need to match with provided namespace parameter. with pytest.raises(ValueError): client.replace(Pod(metadata=ObjectMeta(name="xx", namespace='ns1')), namespace='ns2')
async def test_http_methods(client): async with respx.mock: url = "https://foo.bar/" m = respx.get(url, status_code=404) respx.post(url, status_code=201) respx.put(url, status_code=202) respx.patch(url, status_code=500) respx.delete(url, status_code=204) respx.head(url, status_code=405) respx.options(url, status_code=501) response = httpx.get(url) assert response.status_code == 404 response = await client.get(url) assert response.status_code == 404 response = httpx.post(url) assert response.status_code == 201 response = await client.post(url) assert response.status_code == 201 response = httpx.put(url) assert response.status_code == 202 response = await client.put(url) assert response.status_code == 202 response = httpx.patch(url) assert response.status_code == 500 response = await client.patch(url) assert response.status_code == 500 response = httpx.delete(url) assert response.status_code == 204 response = await client.delete(url) assert response.status_code == 204 response = httpx.head(url) assert response.status_code == 405 response = await client.head(url) assert response.status_code == 405 response = httpx.options(url) assert response.status_code == 501 response = await client.options(url) assert response.status_code == 501 assert m.called is True assert respx.stats.call_count == 7 * 2
async def test_update_copyfactory_account(self): """Should update CopyFactory account via API.""" account = { 'name': 'Demo account', 'connectionId': 'e8867baa-5ec2-45ae-9930-4d5cea18d0d6', 'reservedMarginFraction': 0.25, 'subscriptions': [{ 'strategyId': 'ABCD', 'multiplier': 1 }] } rsps = respx.put( f'{copy_factory_api_url}/users/current/configuration/accounts/' + '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', json=account).mock(return_value=Response(200)) await copy_factory_client.update_account( '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef', account) assert rsps.calls[0].request.url == f'{copy_factory_api_url}/users/current/configuration/accounts/' + \ '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.read() == json.dumps(account).encode( 'utf-8')
async def test_update_strategy(self): """Should update strategy via API.""" strategy = { 'name': 'Test strategy', 'positionLifecycle': 'hedging', 'connectionId': 'e8867baa-5ec2-45ae-9930-4d5cea18d0d6', 'maxTradeRisk': 0.1, 'stopOutRisk': { 'value': 0.4, 'startTime': '2020-08-24T00:00:00.000Z' }, 'timeSettings': { 'lifetimeInHours': 192, 'openingIntervalInMinutes': 5 } } rsps = respx.put(f'{copy_factory_api_url}/users/current/configuration/strategies/ABCD', json=strategy)\ .mock(return_value=Response(200)) await copy_factory_client.update_strategy('ABCD', strategy) assert rsps.calls[ 0].request.url == f'{copy_factory_api_url}/users/current/configuration/strategies/ABCD' assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.content == json.dumps(strategy).encode( 'utf-8')
async def test_update_strategy(self): """Should update strategy via API.""" strategy = { 'name': 'Test strategy', 'description': 'Test description', 'maxTradeRisk': 0.1, 'stopOutRisk': { 'relativeValue': 0.4, 'startTime': date('2020-08-24T00:00:00.000Z') }, 'riskLimits': [{ 'type': 'monthly', 'applyTo': 'balance', 'maxRelativeRisk': 0.5, 'closePositions': False, 'startTime': date('2020-08-24T00:00:01.000Z') }], 'timeSettings': { 'lifetimeInHours': 192, 'openingIntervalInMinutes': 5 } } json_copy = deepcopy(strategy) json_copy['stopOutRisk']['startTime'] = format_date(json_copy['stopOutRisk']['startTime']) json_copy['riskLimits'][0]['startTime'] = format_date(json_copy['riskLimits'][0]['startTime']) rsps = respx.put(f'{copy_factory_api_url}/users/current/configuration/strategies/ABCD', json=json_copy)\ .mock(return_value=Response(200)) await copy_factory_client.update_strategy('ABCD', strategy) assert rsps.calls[0].request.url == f'{copy_factory_api_url}/users/current/configuration/strategies/ABCD' assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers['auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.content == json.dumps(json_copy).encode('utf-8')
async def test_update_appearance(self, gl, is_gl_sync): new_title = "new-title" new_description = "new-description" request = respx.put( re.compile("^http://localhost/api/v4/application/appearance"), content={ "title": new_title, "description": new_description, "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "header_message": "", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": False, }, status_code=codes.OK, ) if is_gl_sync: gl.appearance.update(title=new_title, description=new_description) else: await gl.appearance.update(title=new_title, description=new_description)
async def test_failed_async_set_command_permission(dispike_object: Dispike, ): respx.put( "https://discord.com/api/v8/applications/APPID/guilds/1111/commands/1234/permissions" ).mock(return_value=Response(500, )) _set_commands = await dispike_object.async_set_command_permission( command_id=1234, guild_id=1111, new_permissions=NewApplicationPermission(permissions=[ ApplicationCommandPermissions( permission=True, type=ApplicationCommandPermissionType.ROLE, id=1234) ]), ) assert _set_commands == False
async def test_diagnostics_reset( monkeypatch, optimizer: servo.configuration.Optimizer) -> None: monkeypatch.setenv("POD_NAMESPACE", "test-namespace") servo_runner = servo.runner.ServoRunner( servo.Servo( config=servo.BaseServoConfiguration(name="archibald", optimizer=optimizer), connectors=[], # Init empty servo )) put = respx.put( f"https://api.opsani.com/accounts/dev.opsani.com/applications/servox/{servo.telemetry.DIAGNOSTICS_CHECK_ENDPOINT}" ).mock(return_value=httpx.Response(200, text=f'{{"status": "ok"}}')) reset_state = servo.telemetry.DiagnosticStates.withhold response = await servo.telemetry.DiagnosticsHandler( servo_runner.servo)._diagnostics_api( method="PUT", endpoint=servo.telemetry.DIAGNOSTICS_CHECK_ENDPOINT, output_model=servo.api.Status, json=reset_state, ) assert put.called assert response.status == servo.api.OptimizerStatuses.ok
def test_field_manager(kubeconfig): config = KubeConfig.from_file(str(kubeconfig)) client = lightkube.Client(config=config, field_manager='lightkube') respx.patch("https://localhost:9443/api/v1/nodes/xx?fieldManager=lightkube").respond(json={'metadata': {'name': 'xx'}}) client.patch(Node, "xx", [{"op": "add", "path": "/metadata/labels/x", "value": "y"}], patch_type=types.PatchType.JSON) respx.post("https://localhost:9443/api/v1/namespaces/default/pods?fieldManager=lightkube").respond(json={'metadata': {'name': 'xx'}}) client.create(Pod(metadata=ObjectMeta(name="xx", labels={'l': 'ok'}))) respx.put("https://localhost:9443/api/v1/namespaces/default/pods/xy?fieldManager=lightkube").respond( json={'metadata': {'name': 'xy'}}) client.replace(Pod(metadata=ObjectMeta(name="xy"))) respx.put("https://localhost:9443/api/v1/namespaces/default/pods/xy?fieldManager=override").respond( json={'metadata': {'name': 'xy'}}) client.replace(Pod(metadata=ObjectMeta(name="xy")), field_manager='override')
async def test_replace_global(client: lightkube.AsyncClient): req = respx.put("https://localhost:9443/api/v1/nodes/xx").respond( json={'metadata': { 'name': 'xx' }}) pod = await client.replace(Node(metadata=ObjectMeta(name="xx"))) assert req.calls[0][0].read() == b'{"metadata": {"name": "xx"}}' assert pod.metadata.name == 'xx' await client.close()
async def test_get_update_appearance(self, gl, gl_get_value, is_gl_sync): title = "GitLab Test Instance" new_title = "new-title" description = "gitlab-test.example.com" new_description = "new-description" request_get_appearance = respx.get( "http://localhost/api/v4/application/appearance", content={ "title": title, "description": description, "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "header_message": "", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": False, }, status_code=codes.OK, ) request_update_appearance = respx.put( "http://localhost/api/v4/application/appearance", content={ "title": new_title, "description": new_description, "logo": "/uploads/-/system/appearance/logo/1/logo.png", "header_logo": "/uploads/-/system/appearance/header_logo/1/header.png", "favicon": "/uploads/-/system/appearance/favicon/1/favicon.png", "new_project_guidelines": "Please read the FAQs for help.", "header_message": "", "footer_message": "", "message_background_color": "#e75e40", "message_font_color": "#ffffff", "email_header_and_footer_enabled": False, }, status_code=codes.OK, ) appearance = gl.appearance.get() appearance = await gl_get_value(appearance) assert appearance.title == title assert appearance.description == description appearance.title = new_title appearance.description = new_description if is_gl_sync: appearance.save() else: await appearance.save() assert appearance.title == new_title assert appearance.description == new_description
async def test_put_request(self, gl, gl_get_value): request = respx.put( "http://localhost/api/v4/projects", headers={"content-type": "application/json"}, content='{"name": "project1"}', status_code=codes.OK, ) result = gl.http_put("/projects") result = await gl_get_value(result) assert isinstance(result, dict) assert result["name"] == "project1"
def test_bulk_edit_command_guild_only(dispike_object: Dispike, example_edit_command: DiscordCommand): respx.put( "https://discord.com/api/v8/applications/APPID/guilds/EXAMPLE_GUILD/commands" ).mock(return_value=Response( 200, json=[example_edit_command.dict(), example_edit_command.dict()], )) _edit_command = dispike_object.edit_command( new_command=[example_edit_command, example_edit_command], guild_only=True, bulk=True, guild_id_passed="EXAMPLE_GUILD", ) assert isinstance(_edit_command, list) == True assert len(_edit_command) == 2 for command in _edit_command: assert isinstance(command, DiscordCommand) assert command.id == example_edit_command.id assert command.name == example_edit_command.name
async def test_upload_file(self): """Should upload file to a provisioning profile via API.""" rsps = respx.put(f'{PROVISIONING_API_URL}/users/current/provisioning-profiles/id/servers.dat') \ .mock(return_value=Response(204)) with mock.patch('__main__.open', new=mock.mock_open(read_data='test')) as file: file.return_value = 'test', 'test2' await provisioning_client.upload_provisioning_profile_file( 'id', 'servers.dat', file()) assert rsps.calls[0].request.url == \ f'{PROVISIONING_API_URL}/users/current/provisioning-profiles/id/servers.dat' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign'
async def test_update(self): """Should update provisioning profile via API.""" rsps = respx.put(f'{PROVISIONING_API_URL}/users/current/provisioning-profiles/id') \ .mock(return_value=Response(200)) await provisioning_client.update_provisioning_profile( 'id', {'name': 'new name'}) assert rsps.calls[0].request.url == \ f'{PROVISIONING_API_URL}/users/current/provisioning-profiles/id' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.content == json.dumps({ 'name': 'new name' }).encode('utf-8')
async def test_update_mixin_no_id(self, gl): class M(UpdateMixin, FakeManager): _create_attrs = (("foo",), ("bar", "baz")) _update_attrs = (("foo",), ("bam",)) request = respx.put( "http://localhost/api/v4/tests", headers={"Content-Type": "application/json"}, content='{"foo": "baz"}', status_code=codes.OK, ) mgr = M(gl) server_data = await mgr.update(new_data={"foo": "baz"}) assert isinstance(server_data, dict) assert server_data["foo"] == "baz"
async def test_set_mixin(self, gl): class M(SetMixin, FakeManager): pass request = respx.put( "http://localhost/api/v4/tests/foo", headers={"Content-Type": "application/json"}, content='{"key": "foo", "value": "bar"}', status_code=codes.OK, ) mgr = M(gl) obj = await mgr.set("foo", "bar") assert isinstance(obj, FakeObject) assert obj.key == "foo" assert obj.value == "bar"
async def test_create_update_project_snippets(self, gl, gl_get_value, is_gl_sync): title = "Example Snippet Title" new_title = "new-title" visibility = "private" request_update = respx.put( "http://localhost/api/v4/projects/1/snippets", content={ "title": new_title, "description": "More verbose snippet description", "file_name": "example.txt", "content": "source code with multiple lines", "visibility": visibility, }, status_code=codes.OK, ) request_create = respx.post( "http://localhost/api/v4/projects/1/snippets", content={ "title": title, "description": "More verbose snippet description", "file_name": "example.txt", "content": "source code with multiple lines", "visibility": visibility, }, status_code=codes.OK, ) project = gl.projects.get(1, lazy=True) snippet = project.snippets.create({ "title": title, "file_name": title, "content": title, "visibility": visibility, }) snippet = await gl_get_value(snippet) assert snippet.title == title assert snippet.visibility == visibility snippet.title = new_title if is_gl_sync: snippet.save() else: await snippet.save() assert snippet.title == new_title assert snippet.visibility == visibility
async def test_update(self): """Should update MetaTrader account via API.""" update_account = { 'name': 'new account name', 'password': '******', 'server': 'ICMarketsSC2-Demo', 'tags': ['tag1'] } rsps = respx.put(f'{PROVISIONING_API_URL}/users/current/accounts/id', json=update_account) \ .mock(return_value=Response(204)) await account_client.update_account('id', update_account) assert rsps.calls[ 0].request.url == f'{PROVISIONING_API_URL}/users/current/accounts/id' assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.content == json.dumps( update_account).encode('utf-8')
async def test_update_external_signal(self): """Should update external signal.""" signal = { 'symbol': 'EURUSD', 'type': 'POSITION_TYPE_BUY', 'time': date('2020-08-24T00:00:00.000Z'), 'updateTime': date('2020-08-24T00:00:00.000Z'), 'volume': 1 } rsps = respx.put(f'{copy_factory_api_url}/users/current/strategies/ABCD/external-signals/0123456')\ .mock(return_value=Response(200)) await trading_client.update_external_signal('ABCD', '0123456', signal) assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers[ 'auth-token'] == 'header.payload.sign' signal['time'] = format_date(signal['time']) signal['updateTime'] = format_date(signal['updateTime']) assert rsps.calls[0].request.content == json.dumps(signal).encode( 'utf-8')
async def test_update_submodule(self, gl, gl_get_value): request_get_project = respx.get( "http://localhost/api/v4/projects/1", headers={"content-type": "application/json"}, content='{"name": "name", "id": 1}'.encode("utf-8"), status_code=codes.OK, ) request_update_submodule = respx.put( "http://localhost/api/v4/projects/1/repository/submodules/foo%2Fbar", headers={"content-type": "application/json"}, content="""{ "id": "ed899a2f4b50b4370feeea94676502b42383c746", "short_id": "ed899a2f4b5", "title": "Message", "author_name": "Author", "author_email": "*****@*****.**", "committer_name": "Author", "committer_email": "*****@*****.**", "created_at": "2018-09-20T09:26:24.000-07:00", "message": "Message", "parent_ids": [ "ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba" ], "committed_date": "2018-09-20T09:26:24.000-07:00", "authored_date": "2018-09-20T09:26:24.000-07:00", "status": null}""".encode("utf-8"), status_code=codes.OK, ) project = gl.projects.get(1) project = await gl_get_value(project) assert isinstance(project, Project) assert project.name == "name" assert project.id == 1 ret = project.update_submodule( submodule="foo/bar", branch="master", commit_sha="4c3674f66071e30b3311dac9b9ccc90502a72664", commit_message="Message", ) ret = await gl_get_value(ret) assert isinstance(ret, dict) assert ret["message"] == "Message" assert ret["id"] == "ed899a2f4b50b4370feeea94676502b42383c746"
async def test_save_mixin(self, gl): class M(UpdateMixin, FakeManager): pass class O(SaveMixin, RESTObject): pass request = respx.put( "http://localhost/api/v4/tests/42", headers={"Content-Type": "application/json"}, content='{"id": 42, "foo": "baz"}', status_code=codes.OK, ) mgr = M(gl) obj = O(mgr, {"id": 42, "foo": "bar"}) obj.foo = "baz" await obj.save() assert obj._attrs["foo"] == "baz" assert obj._updated_attrs == {}
async def test_update_portfolio_strategy(self): """Should update portfolio strategy via API.""" strategy = { 'name': 'Test strategy', 'members': [{ 'strategyId': 'BCDE' }], 'maxTradeRisk': 0.1, 'stopOutRisk': { 'relativeValue': 0.4, 'startTime': '2020-08-24T00:00:00.000Z' } } rsps = respx.put(f'{copy_factory_api_url}/users/current/configuration/portfolio-strategies/ABCD', json=strategy).mock(return_value=Response(200)) await copy_factory_client.update_portfolio_strategy('ABCD', strategy) assert rsps.calls[0].request.url == f'{copy_factory_api_url}/users/current/configuration/' \ f'portfolio-strategies/ABCD' assert rsps.calls[0].request.method == 'PUT' assert rsps.calls[0].request.headers['auth-token'] == 'header.payload.sign' assert rsps.calls[0].request.content == json.dumps(strategy).encode('utf-8')
async def test_deployment(self, gl, gl_get_value, is_gl_sync): content = '{"id": 42, "status": "success", "ref": "master"}' json_content = json.loads(content) request_deployment_create = respx.post( "http://localhost/api/v4/projects/1/deployments", headers={"content-type": "application/json"}, content=json_content, status_code=codes.OK, ) project = gl.projects.get(1, lazy=True) deployment = project.deployments.create({ "environment": "Test", "sha": "1agf4gs", "ref": "master", "tag": False, "status": "created", }) deployment = await gl_get_value(deployment) assert deployment.id == 42 assert deployment.status == "success" assert deployment.ref == "master" json_content["status"] = "failed" request_deployment_update = respx.put( "http://localhost/api/v4/projects/1/deployments/42", headers={"content-type": "application/json"}, content=json_content, status_code=codes.OK, ) deployment.status = "failed" if is_gl_sync: deployment.save() else: await deployment.save() assert deployment.status == "failed"