def test_historical_prices_v3_num_points_happy(self):

        # fetch_historical_prices v3 - number of data points, weekly resolution

        with open('tests/data/historic_prices_num_points.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP',
            match_querystring=False,
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json=response_body,
            status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
        result = ig_service.fetch_historical_prices_by_epic(
            epic='MT.D.GC.Month2.IP', resolution='W', numpoints=10)

        prices = result['prices']
        assert isinstance(result, dict)
        assert isinstance(prices, pd.DataFrame)

        # assert DataFrame shape
        assert prices.shape[0] == 10
        assert prices.shape[1] == 13

        # assert time series rows are 1 week apart
        prices['tvalue'] = prices.index
        prices['delta'] = (prices['tvalue'] - prices['tvalue'].shift())
        assert any(prices["delta"].dropna() == datetime.timedelta(weeks=1))
    def test_historical_prices_v3_num_points_bad_resolution(self):

        # fetch_historical_prices v3 - number of data points, invalid resolution

        with open('tests/data/historic_prices_num_points.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP',
            match_querystring=False,
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json=response_body,
            status=200)

        with pytest.raises(ValueError) as excinfo:
            ig_service = IGService('username', 'password', 'api_key', 'DEMO')
            ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
            ig_service.fetch_historical_prices_by_epic(
                epic='MT.D.GC.Month2.IP',
                resolution='X',
                numpoints=10,
                format=ig_service.flat_prices)
            assert "Invalid frequency" in str(excinfo.value)
    def test_historical_prices_by_epic_and_date_range_happy(self):

        # fetch_historical_prices_by_epic_and_date_range, daily resolution

        with open('tests/data/historic_prices_v1.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP/DAY',
            match_querystring=False,
            headers={'CST': 'abc123', 'X-SECURITY-TOKEN': 'xyz987'},
            json=response_body,
            status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
        result = ig_service.fetch_historical_prices_by_epic_and_date_range(
            epic='MT.D.GC.Month2.IP',
            resolution='D',
            start_date='2020:09:01-00:00:00',
            end_date='2020:09:04-23:59:59')

        prices = result['prices']
        assert isinstance(result, dict)
        assert isinstance(prices, pd.DataFrame)

        # assert DataFrame shape
        assert prices.shape[0] == 4
        assert prices.shape[1] == 13

        # assert time series rows are 1 day apart
        prices['tvalue'] = prices.index
        prices['delta'] = (prices['tvalue'] - prices['tvalue'].shift())
        assert any(prices["delta"].dropna() == datetime.timedelta(days=1))
Exemple #4
0
    def test_fetch_accounts_happy(self):

        with open('tests/data/accounts_balances.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(responses.GET,
                      'https://demo-api.ig.com/gateway/deal/accounts',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
        result = ig_service.fetch_accounts()

        pd.set_option('display.max_columns', 13)
        print(result)

        assert isinstance(result, pd.DataFrame)
        assert result.iloc[0]['accountId'] == 'XYZ987'
        assert result.iloc[0]['balance'] == 1000.0
        assert result.iloc[1]['accountId'] == 'ABC123'
        assert pd.isna(result.iloc[1]['balance'])
        assert pd.isna(result.iloc[1]['deposit'])
    def test_historical_prices_v3_num_points_bad_numpoints(self):

        # fetch_historical_prices v3 - number of data points, invalid numpoints

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP',
            match_querystring=False,
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json={
                'errorCode':
                'Unable to convert value=3.14159 to type= Integer int'
            },  # noqa
            status=400)

        with pytest.raises(Exception):
            ig_service = IGService('username', 'password', 'api_key', 'DEMO')
            ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
            result = ig_service.fetch_historical_prices_by_epic(
                epic='MT.D.GC.Month2.IP',
                resolution='X',
                numpoints=3.14159,
                format=ig_service.flat_prices)
            assert result['errorCode'].startswith('Unable to convert value')
    def test_switch_account(self):

        with open('tests/data/switch.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)
        responses.add(responses.PUT,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')

        ig_service.create_session()
        result = ig_service.switch_account(account_id='XYZ987',
                                           default_account=True)

        assert result['trailingStopsEnabled'] is True
        assert result['dealingEnabled'] is True
    def test_session_details(self):

        with open('tests/data/session.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)
        responses.add(responses.GET,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')

        ig_service.create_session()
        result = ig_service.read_session()

        assert result['clientId'] == '100112233'
        assert result['accountId'] == 'ABC123'
        assert result['currency'] == 'GBP'
    def test_activities_by_date(self):

        # fetch_account_activity_by_date

        with open('tests/data/activities_v1.json', 'r') as file:
            response_body = json.loads(file.read())

        url = "https://demo-api.ig.com/gateway/deal/"
        date_pat = '[0-9]{2}-[0-9]{2}-[0-9]{4}'  # NOT a very god regexp for dates will suffice here

        responses.add(
            responses.GET,
            re.compile(f"{url}history/activity/{date_pat}/{date_pat}"),
            match_querystring=False,
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json=response_body,
            status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        to_date = datetime.now()
        from_date = to_date - timedelta(days=7)
        result = ig_service.fetch_account_activity_by_date(from_date, to_date)

        # we expect a pd.DataFrame with 17 columns and 3 rows
        assert isinstance(result, pd.DataFrame)
        assert result.shape[0] == 3
        assert result.shape[1] == 17
    def test_login_v2_encrypted_happy(self):

        with open('tests/data/accounts.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/session/encryptionKey',
            json={
                'encryptionKey':
                'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp9te7zwed8HhdRFsn47EI8exZ1Yi+bJoKtclGTiuaP1T+4AclNqB2mIya/Ik6IV6A2pt4FFVoqvrhJA46dWi4XgA4Ojhl2Xxw4++blAMgT3jU7N5nY13LdJzZuYv/oPZKRcEj6RrlBV68HjrTnjAMWARl0jFbVCiLWovTGJ0stx/zJAKX0GFyuUlsoaJISJJRYeOLUtZ8Z4BE6ZkmKnz4V8YNyyoWCyXQp+IKCZrfoEdlMOPBgsjbRy02Gh9xZqcm2erLsp40F+w3AjHUqQQi7eQuPQaPWq9Lhm8cVDH2CB2BtfM8Ew8T5/A36eqa5eoeQcZaMnLUQP5UYtG2Wd//wIDAQAB',  # noqa
                'timeStamp': '1601218928621'
            },
            status=200)

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        result = ig_service.create_session(encryption=True, version='2')

        assert ig_service.crud_session.CLIENT_TOKEN == 'abc123'
        assert ig_service.crud_session.SECURITY_TOKEN == 'xyz987'
        assert result['accountType'] == 'SPREADBET'
        assert result['currentAccountId'] == 'ABC123'
        assert len(result['accounts']) == 2
        assert result['accounts'][1]['accountName'] == 'Demo-cfd'
        assert result['accounts'][1]['accountType'] == 'CFD'
        assert result['trailingStopsEnabled'] is True
    def test_historical_prices_v3_defaults_happy(self):

        # fetch_historical_prices v3 - default params

        with open('tests/data/historic_prices.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            'https://demo-api.ig.com/gateway/deal/prices/MT.D.GC.Month2.IP',
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json=response_body,
            status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
        result = ig_service.fetch_historical_prices_by_epic(
            epic='MT.D.GC.Month2.IP')
        prices = result['prices']

        assert isinstance(result, dict)
        assert isinstance(prices, pd.DataFrame)

        # with no other params, default returns 10 rows at MINUTE resolution
        assert prices.shape[0] == 10
        assert prices.shape[1] == 13

        # assert time series rows are 1 minute apart
        prices['tvalue'] = prices.index
        prices['delta'] = (prices['tvalue'] - prices['tvalue'].shift())
        assert any(prices["delta"].dropna() == datetime.timedelta(minutes=1))
    def test_login_v1_happy(self):

        with open('tests/data/accounts.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        result = ig_service.create_session()

        assert ig_service.crud_session.CLIENT_TOKEN == 'abc123'
        assert ig_service.crud_session.SECURITY_TOKEN == 'xyz987'

        assert result['accountType'] == 'SPREADBET'
        assert result['currentAccountId'] == 'ABC123'
        assert len(result['accounts']) == 2
        assert result['accounts'][1]['accountName'] == 'Demo-cfd'
        assert result['accounts'][1]['accountType'] == 'CFD'
        assert result['trailingStopsEnabled'] is True
    def test_workingorders_happy(self):

        with open('tests/data/workingorders.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(responses.GET,
                      'https://demo-api.ig.com/gateway/deal/workingorders',
                      headers={
                          'CST': 'abc123',
                          'X-SECURITY-TOKEN': 'xyz987'
                      },
                      json=response_body,
                      status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        ig_service.crud_session.HEADERS["LOGGED_IN"] = {}
        result = ig_service.fetch_working_orders()

        pd.set_option('display.max_columns', 50)
        print(result)

        assert isinstance(result, pd.DataFrame)
        assert result.iloc[0]['instrumentName'] == 'Spot Gold'
        assert result.iloc[0]['exchangeId'] == 'FX_C_GCSI_ST'
        assert result.iloc[0]['marketStatus'] == 'EDITS_ONLY'
        assert result.iloc[0]['level'] == 2000.0
        assert result.iloc[0]['epic'] == 'CS.D.CFDGOLD.CFDGC.IP'
        assert result.iloc[0]['currencyCode'] == 'USD'
    def test_activities_by_period(self):

        # test_activities_by_period

        with open('tests/data/activities_v1.json', 'r') as file:
            response_body = json.loads(file.read())

        responses.add(
            responses.GET,
            re.compile(
                'https://demo-api.ig.com/gateway/deal/history/activity/.+'),
            match_querystring=False,
            headers={
                'CST': 'abc123',
                'X-SECURITY-TOKEN': 'xyz987'
            },
            json=response_body,
            status=200)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')
        result = ig_service.fetch_account_activity_by_period(10000000)

        # we expect a pd.DataFrame with 17 columns and 3 rows
        assert isinstance(result, pd.DataFrame)
        assert result.shape[0] == 3
        assert result.shape[1] == 17
    def test_create_open_position(self, ig_service: IGService):

        epic = 'IX.D.FTSE.DAILY.IP'
        market_info = ig_service.fetch_market_by_epic(epic)
        status = market_info.snapshot.marketStatus
        min_bet = market_info.dealingRules.minDealSize.value
        bid = market_info.snapshot.bid
        offer = market_info.snapshot.offer
        if status != 'TRADEABLE':
            pytest.skip('Skipping open position test, market not open')

        open_result = ig_service.create_open_position(
            epic=epic, direction='BUY', currency_code='GBP', order_type='MARKET', expiry='DFB',
            force_open='false', guaranteed_stop='false', size=min_bet, level=None, limit_level=None, limit_distance=None,
            quote_id=None, stop_distance=None, stop_level=None, trailing_stop=None, trailing_stop_increment=None)
        assert open_result['dealStatus'] == 'ACCEPTED'
        assert open_result['reason'] == 'SUCCESS'
        time.sleep(10)

        update_v1_result = ig_service.update_open_position(offer * 1.5, bid * 0.5, open_result['dealId'], version='1')
        assert update_v1_result['dealStatus'] == 'ACCEPTED'
        assert update_v1_result['reason'] == 'SUCCESS'
        time.sleep(10)

        update_v2_result = ig_service.update_open_position(offer * 1.4, bid * 0.4, open_result['dealId'],
            trailing_stop=True, trailing_stop_distance=25.0, trailing_stop_increment=10.0)
        assert update_v2_result['dealStatus'] == 'ACCEPTED'
        assert update_v2_result['reason'] == 'SUCCESS'
        time.sleep(10)

        close_result = ig_service.close_open_position(deal_id=open_result['dealId'], direction='SELL',
            epic=None, expiry='DFB', level=None, order_type='MARKET', quote_id=None, size=0.5, session=None)
        assert close_result['dealStatus'] == 'ACCEPTED'
        assert close_result['reason'] == 'SUCCESS'
    def test_fetch_markets_by_epics(self, ig_service: IGService):
        markets_list = ig_service.fetch_markets_by_epics("IX.D.SPTRD.MONTH1.IP,IX.D.FTSE.MONTH1.IP", version='1')
        assert isinstance(markets_list, list)
        assert len(markets_list) == 2
        assert markets_list[0].instrument.name == 'FTSE 100'
        assert markets_list[0].dealingRules is not None
        assert markets_list[1].instrument.name == 'US 500'

        markets_list = ig_service.fetch_markets_by_epics("MT.D.PL.Month2.IP,MT.D.PA.Month1.IP,MT.D.HG.Month1.IP",
            detailed=False)
        assert len(markets_list) == 3
        assert markets_list[0].instrument.name == None
        assert markets_list[0].snapshot.bid != 0
        assert markets_list[0].snapshot.offer != 0
        assert markets_list[0].dealingRules is None

        assert markets_list[1].instrument.name == None
        assert markets_list[1].snapshot.bid != 0
        assert markets_list[1].snapshot.offer != 0
        assert markets_list[1].dealingRules is None

        assert markets_list[2].instrument.name == None
        assert markets_list[2].snapshot.bid != 0
        assert markets_list[2].snapshot.offer != 0
        assert markets_list[2].dealingRules is None
 def test_create_session_v3(self, retrying):
     ig_service = IGService(config.username, config.password, config.api_key, config.acc_type,
                            acc_number=config.acc_number, retryer=retrying)
     ig_service.create_session(version='3')
     assert 'X-IG-API-KEY' in ig_service.session.headers
     assert 'Authorization' in ig_service.session.headers
     assert 'IG-ACCOUNT-ID' in ig_service.session.headers
     assert len(ig_service.fetch_accounts()) == 2
Exemple #17
0
 def test_create_session_bad_api_key(self, retrying):
     ig_service = IGService(config.username,
                            config.password,
                            'wrong',
                            config.acc_type,
                            retryer=retrying)
     with pytest.raises(IGException):
         ig_service.create_session()
Exemple #18
0
 def test_create_session_v3_no_acc_num(self, retrying):
     ig_service = IGService(config.username,
                            config.password,
                            config.api_key,
                            config.acc_type,
                            retryer=retrying)
     with pytest.raises(IGException):
         ig_service.create_session(version='3')
Exemple #19
0
 def test_create_session_encrypted_password(self, retrying):
     ig_service = IGService(config.username,
                            config.password,
                            config.api_key,
                            config.acc_type,
                            retryer=retrying)
     ig_service.create_session(encryption=True)
     assert 'CST' in ig_service.session.headers
def watchlist_id(ig_service: IGService):
    """test fixture creates a dummy watchlist for use in tests,
    and returns the ID. In teardown it also deletes the dummy watchlist"""
    epics = ['CS.D.GBPUSD.TODAY.IP', 'IX.D.FTSE.DAILY.IP']
    now = datetime.now()
    data = ig_service.create_watchlist(f"test_{now.strftime('%Y%m%d%H%H%S')}", epics)
    watchlist_id = data['watchlistId']
    yield watchlist_id
    ig_service.delete_watchlist(watchlist_id)
def ig_service():
    """test fixture logs into IG with the configured credentials"""
    if config.acc_type == 'LIVE':
        pytest.fail(
            'this integration test should not be executed with a LIVE account')
    ig_service = IGService(config.username, config.password, config.api_key,
                           config.acc_type)
    ig_service.create_session()
    return ig_service
    def test_retry(self):

        with open('tests/data/accounts_balances.json', 'r') as file:
            response_body = json.loads(file.read())

        url = 'https://demo-api.ig.com/gateway/deal/accounts'
        headers = {'CST': 'abc123', 'X-SECURITY-TOKEN': 'xyz987'}
        api_exceeded = {
            'errorCode': 'error.public-api.exceeded-api-key-allowance'
        }
        account_exceeded = {
            'errorCode': 'error.public-api.exceeded-account-allowance'
        }
        trading_exceeded = {
            'errorCode': 'error.public-api.exceeded-account-trading-allowance'
        }

        responses.add(
            Response(method='GET',
                     url=url,
                     headers={},
                     json=api_exceeded,
                     status=403))
        responses.add(
            Response(method='GET',
                     url=url,
                     headers={},
                     json=account_exceeded,
                     status=403))
        responses.add(
            Response(method='GET',
                     url=url,
                     headers={},
                     json=trading_exceeded,
                     status=403))
        responses.add(
            Response(method='GET',
                     url=url,
                     headers=headers,
                     json=response_body,
                     status=200))

        ig_service = IGService(
            'username',
            'password',
            'api_key',
            'DEMO',
            retryer=Retrying(
                wait=tenacity.wait_exponential(),
                retry=tenacity.retry_if_exception_type(ApiExceededException)))

        result = ig_service.fetch_accounts()

        assert responses.assert_call_count(url, 4) is True
        assert isinstance(result, pd.DataFrame)
        assert result.iloc[0]['accountId'] == 'XYZ987'
Exemple #23
0
def get_session():
    ig_service = IGService(
        config.username,
        config.password,
        config.api_key,
        config.acc_type,
        acc_number=config.acc_number,
        retryer=DEFAULT_RETRY)
    ig_service.create_session(version='3')
    return ig_service
def ig_service(request, retrying):
    """test fixture logs into IG with the configured credentials. Tests both v2 and v3 types"""
    if config.acc_type == 'LIVE':
        pytest.fail('this integration test should not be executed with a LIVE account')
    ig_service = IGService(config.username, config.password, config.api_key, config.acc_type,
        acc_number=config.acc_number, retryer=retrying)
    service = ig_service.create_session(version=request.param)
    if request.param == '2' and service['accountType'] != 'SPREADBET':
        pytest.fail('Integration test currently only works with a spreadbet account')

    yield ig_service
    ig_service.logout()
def test_login_v2_encrypted_bad_key():

    responses.add(responses.GET,
                  'https://demo-api.ig.com/gateway/deal/session/encryptionKey',
                  json={'errorCode': 'error.security.api-key-invalid'},
                  status=403)

    ig_service = IGService('username', 'password', 'api_key', 'DEMO')

    with pytest.raises(IGException):
        result = ig_service.create_session(encryption=True)
        assert result['errorCode'] == 'error.security.api-key-invalid'
    def test_create_working_order_guaranteed_stop_loss(self, ig_service: IGService):

        epic = 'CS.D.GBPUSD.TODAY.IP'
        market_info = ig_service.fetch_market_by_epic(epic)
        status = market_info.snapshot.marketStatus
        min_bet = market_info.dealingRules.minDealSize.value
        offer = market_info.snapshot.offer
        bid = market_info.snapshot.bid

        logging.info(f"min bet: {min_bet}")
        logging.info(f"offer: {offer}")
        logging.info(f"bid: {bid}")

        if status != 'TRADEABLE':
            pytest.skip('Skipping create working order test, market not open')

        create_result = ig_service.create_working_order(
            epic=epic, direction='BUY', currency_code='GBP', order_type='LIMIT', expiry='DFB', guaranteed_stop='true',
            time_in_force='GOOD_TILL_CANCELLED', size=min_bet, level=offer * 0.90, limit_level=None,
            limit_distance=None, stop_distance=200, stop_level=None)

        logging.info(f"result: {create_result['dealStatus']}, reason {create_result['reason']}")

        assert create_result['dealStatus'] == 'ACCEPTED'
        assert create_result['reason'] == 'SUCCESS'
        assert create_result['guaranteedStop']

        time.sleep(10)

        update_result = ig_service.update_working_order(
            good_till_date=None,
            level=offer * 0.85,
            limit_distance=None,
            limit_level=None,
            stop_distance=None,
            stop_level=offer * 0.80,
            guaranteed_stop='true',
            time_in_force='GOOD_TILL_CANCELLED',
            order_type='LIMIT',
            deal_id=create_result['dealId'])

        logging.info(f"result: {update_result['dealStatus']}, reason {update_result['reason']}")

        assert update_result['dealStatus'] == 'ACCEPTED'
        assert update_result['reason'] == 'SUCCESS'
        assert update_result['guaranteedStop']

        time.sleep(10)

        delete_result = ig_service.delete_working_order(create_result['dealId'])
        assert delete_result['dealStatus'] == 'ACCEPTED'
        assert delete_result['reason'] == 'SUCCESS'
    def test_login_v1_bad_api_key(self):

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={},
                      json={'errorCode': 'error.security.api-key-invalid'},
                      status=403)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')

        with pytest.raises(Exception):
            result = ig_service.create_session(version='1')
            assert result['errorCode'] == 'error.security.api-key-invalid'
    def test_read_session_fetch_session_tokens(self, ig_service: IGService):
        ig_service.read_session(fetch_session_tokens='true')
        assert 'X-IG-API-KEY' in ig_service.session.headers
        assert 'CST' in ig_service.session.headers
        assert 'X-SECURITY-TOKEN' in ig_service.session.headers

        if ig_service.session.headers['VERSION'] == '2':
            assert 'Authorization' not in ig_service.session.headers
            assert 'IG-ACCOUNT-ID' not in ig_service.session.headers

        if ig_service.session.headers['VERSION'] == '3':
            assert 'Authorization' in ig_service.session.headers
            assert 'IG-ACCOUNT-ID' in ig_service.session.headers
def test_login_v1_bad_credentials():

    responses.add(responses.POST,
                  'https://demo-api.ig.com/gateway/deal/session',
                  headers={'CST': 'abc123abc123abc123abc123abc123abc123'},
                  json={'errorCode': 'error.security.invalid-details'},
                  status=401)

    ig_service = IGService('username', 'password', 'api_key', 'DEMO')

    with pytest.raises(Exception):
        result = ig_service.create_session()
        assert result['errorCode'] == 'error.security.invalid-details'
    def test_login_v2_bad_credentials(self):

        responses.add(responses.POST,
                      'https://demo-api.ig.com/gateway/deal/session',
                      headers={},
                      json={'errorCode': 'error.security.invalid-details'},
                      status=401)

        ig_service = IGService('username', 'password', 'api_key', 'DEMO')

        with pytest.raises(Exception):
            result = ig_service.create_session(version='2')
            assert result['errorCode'] == 'error.security.invalid-details'
            assert ig_service.crud_session.CLIENT_TOKEN is None
            assert ig_service.crud_session.SECURITY_TOKEN is None