summaryrefslogtreecommitdiff
path: root/tests/test_auth_device.py
diff options
context:
space:
mode:
authorpennae <github@quasiparticle.net>2022-07-18 17:12:52 +0200
committerpennae <github@quasiparticle.net>2022-07-18 17:12:52 +0200
commita89158377f829720a98342cf434a18b962006ee7 (patch)
tree680e35a2e8e3311d832da336df8cf625c7bf07a7 /tests/test_auth_device.py
parenta4a929218528920c4ae525e2510562dd209f6b3a (diff)
downloadminor-skulk-a89158377f829720a98342cf434a18b962006ee7.tar.gz
minor-skulk-a89158377f829720a98342cf434a18b962006ee7.tar.xz
minor-skulk-a89158377f829720a98342cf434a18b962006ee7.zip
speed up test suite
mostly by grouping tests that can reuse the same account (which is expensive to create) into classes and scoping accounts to classes.
Diffstat (limited to 'tests/test_auth_device.py')
-rw-r--r--tests/test_auth_device.py557
1 files changed, 284 insertions, 273 deletions
diff --git a/tests/test_auth_device.py b/tests/test_auth_device.py
index 8504ba7..5ec42f3 100644
--- a/tests/test_auth_device.py
+++ b/tests/test_auth_device.py
@@ -29,58 +29,113 @@ def test_create_noauth(client):
'message': 'invalid request signature'
}
-@pytest.mark.parametrize("args,code,errno,error,message", [
- ({ 'name': 'dev', 'availableCommands': {'a':1} },
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({ 'name': 'dev', 'availableCommands': {'a':1}, 'extra': 0 },
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({},
- 400, 108, 'Bad Request', 'missing parameter in request body'),
- ({ 'id': '00' * 16, 'name': 'dev' },
- 400, 108, 'Bad Request', 'missing parameter in request body'),
-])
-def test_create_invalid(account_or_rt, args, code, errno, error, message):
- with pytest.raises(ClientError) as e:
- account_or_rt.post_a("/account/device", args)
- assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
-
-def test_destroy_noauth(client, populate_devices):
- with pytest.raises(ClientError) as e:
- client.post_a("/account/device/destroy")
- assert e.value.details == {
- 'code': 401,
- 'errno': 109,
- 'error': 'Unauthorized',
- 'message': 'invalid request signature'
- }
- with pytest.raises(ClientError) as e:
- client.post_a("/account/device/destroy", {'id': populate_devices[0]['id']})
- assert e.value.details == {
- 'code': 401,
- 'errno': 109,
- 'error': 'Unauthorized',
- 'message': 'invalid request signature'
- }
-
-@pytest.mark.parametrize("args,code,errno,error,message", [
- ({ 'id': '00' },
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({ 'id': '00' * 16, 'extra': 0 },
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({ 'id': '00' * 16 },
- 400, 123, 'Bad Request', 'unknown device'),
-])
-def test_destroy_invalid(account_or_rt, args, code, errno, error, message):
- with pytest.raises(ClientError) as e:
- account_or_rt.post_a("/account/device/destroy", args)
- assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
+class TestBadCreate:
+ @pytest.mark.parametrize("args,code,errno,error,message", [
+ ({ 'name': 'dev', 'availableCommands': {'a':1} },
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({ 'name': 'dev', 'availableCommands': {'a':1}, 'extra': 0 },
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({},
+ 400, 108, 'Bad Request', 'missing parameter in request body'),
+ ({ 'id': '00' * 16, 'name': 'dev' },
+ 400, 108, 'Bad Request', 'missing parameter in request body'),
+ ])
+ def test_create_invalid(self, account_or_rt, args, code, errno, error, message):
+ with pytest.raises(ClientError) as e:
+ account_or_rt.post_a("/account/device", args)
+ assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
+
+class TestDestroyNoauth:
+ def test_destroy_noauth(self, client, populate_devices):
+ with pytest.raises(ClientError) as e:
+ client.post_a("/account/device/destroy")
+ assert e.value.details == {
+ 'code': 401,
+ 'errno': 109,
+ 'error': 'Unauthorized',
+ 'message': 'invalid request signature'
+ }
+ with pytest.raises(ClientError) as e:
+ client.post_a("/account/device/destroy", {'id': populate_devices[0]['id']})
+ assert e.value.details == {
+ 'code': 401,
+ 'errno': 109,
+ 'error': 'Unauthorized',
+ 'message': 'invalid request signature'
+ }
+
+class TestDestroyInvalid:
+ @pytest.mark.parametrize("args,code,errno,error,message", [
+ ({ 'id': '00' },
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({ 'id': '00' * 16, 'extra': 0 },
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({ 'id': '00' * 16 },
+ 400, 123, 'Bad Request', 'unknown device'),
+ ])
+ def test_destroy_invalid(self, account_or_rt, args, code, errno, error, message):
+ with pytest.raises(ClientError) as e:
+ account_or_rt.post_a("/account/device/destroy", args)
+ assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
def test_create_destroy(account_or_rt):
dev = account_or_rt.post_a("/account/device", device_data[0])
account_or_rt.post_a("/account/device/destroy", {'id': dev['id']})
-def test_create_unverified(unverified_account):
- unverified_account.post_a("/account/device", device_data[0])
+class TestUnverified:
+ def test_create_unverified(self, unverified_account):
+ unverified_account.post_a("/account/device", device_data[0])
+
+ def test_list_unverified(self, unverified_account):
+ with pytest.raises(ClientError) as e:
+ unverified_account.get_a("/account/devices")
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 138,
+ 'error': 'Bad Request',
+ 'message': 'unverified session'
+ }
+
+ def test_invoke_unverified(self, unverified_account):
+ body = {"target": "0" * 32, "command": "foo", "payload": {}, "ttl": 10}
+ with pytest.raises(ClientError) as e:
+ unverified_account.post_a("/account/devices/invoke_command", body)
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 138,
+ 'error': 'Bad Request',
+ 'message': 'unverified session'
+ }
+
+ def test_commands_unverified(self, unverified_account):
+ with pytest.raises(ClientError) as e:
+ unverified_account.get_a("/account/device/commands?index=1")
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 138,
+ 'error': 'Bad Request',
+ 'message': 'unverified session'
+ }
+
+ def test_attached_clients_unverified(self, unverified_account):
+ with pytest.raises(ClientError) as e:
+ unverified_account.get_a("/account/attached_clients")
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 138,
+ 'error': 'Bad Request',
+ 'message': 'unverified session'
+ }
+
+ def test_attached_client_destroy_unverified(self, unverified_account):
+ with pytest.raises(ClientError) as e:
+ unverified_account.post_a("/account/attached_client/destroy")
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 138,
+ 'error': 'Bad Request',
+ 'message': 'unverified session'
+ }
def test_list_noauth(client):
with pytest.raises(ClientError) as e:
@@ -92,19 +147,10 @@ def test_list_noauth(client):
'message': 'invalid request signature'
}
-def test_list_unverified(unverified_account):
- with pytest.raises(ClientError) as e:
- unverified_account.get_a("/account/devices")
- assert e.value.details == {
- 'code': 400,
- 'errno': 138,
- 'error': 'Bad Request',
- 'message': 'unverified session'
- }
-
-def test_list_none(account_or_rt):
- devs = account_or_rt.get_a("/account/devices")
- assert devs == []
+class TestListNone:
+ def test_list_none(self, account_or_rt):
+ devs = account_or_rt.get_a("/account/devices")
+ assert devs == []
@pytest.mark.usefixtures("populate_devices")
def test_list(account_or_rt):
@@ -157,76 +203,68 @@ def test_invoke_noauth(client):
'message': 'invalid request signature'
}
-def test_invoke_unverified(unverified_account):
- body = {"target": "0" * 32, "command": "foo", "payload": {}, "ttl": 10}
- with pytest.raises(ClientError) as e:
- unverified_account.post_a("/account/devices/invoke_command", body)
- assert e.value.details == {
- 'code': 400,
- 'errno': 138,
- 'error': 'Bad Request',
- 'message': 'unverified session'
- }
-
-@pytest.mark.parametrize("args,code,errno,error,message", [
- ({"target": "00", "command": "foo", "payload": {}, "ttl": 10},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"target": "00" * 16, "command": "foo", "payload": {}, "ttl": 10, 'extra': 0},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"target": "0" * 32, "command": "foo", "payload": {}, "ttl": 10},
- 400, 123, 'Bad Request', 'unknown device'),
-])
-def test_invoke_invalid(account_or_rt, args, code, errno, error, message):
- with pytest.raises(ClientError) as e:
- account_or_rt.post_a("/account/devices/invoke_command", args)
- assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
-
-def test_invoke_nocmd(account_or_rt, populate_devices):
- body = {"target": populate_devices[0]['id'], "command": "foo", "payload": {}, "ttl": 10}
- with pytest.raises(ClientError) as e:
- account_or_rt.post_a("/account/devices/invoke_command", body)
- assert e.value.details == {
- 'code': 400,
- 'errno': 157,
- 'error': 'Bad Request',
- 'message': 'unavailable device command'
- }
+class TestBadInvoke:
+ @pytest.mark.parametrize("args,code,errno,error,message", [
+ ({"target": "00", "command": "foo", "payload": {}, "ttl": 10},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"target": "00" * 16, "command": "foo", "payload": {}, "ttl": 10, 'extra': 0},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"target": "0" * 32, "command": "foo", "payload": {}, "ttl": 10},
+ 400, 123, 'Bad Request', 'unknown device'),
+ ])
+ def test_invoke_invalid(self, account_or_rt, args, code, errno, error, message):
+ with pytest.raises(ClientError) as e:
+ account_or_rt.post_a("/account/devices/invoke_command", args)
+ assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
+
+ def test_invoke_nocmd(self, account_or_rt, populate_devices):
+ body = {"target": populate_devices[0]['id'], "command": "foo", "payload": {}, "ttl": 10}
+ with pytest.raises(ClientError) as e:
+ account_or_rt.post_a("/account/devices/invoke_command", body)
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 157,
+ 'error': 'Bad Request',
+ 'message': 'unavailable device command'
+ }
+
+class TestInvokeOther:
+ def test_invoke_other_account(self, account_or_rt, account2):
+ dev = account2.post_a("/account/device", device_data[0])
+ body = {"target": dev['id'], "command": "foo", "payload": {}, "ttl": 10}
+ with pytest.raises(ClientError) as e:
+ account_or_rt.post_a("/account/devices/invoke_command", body)
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 123,
+ 'error': 'Bad Request',
+ 'message': 'unknown device'
+ }
+
+class TestInvoke:
+ @pytest.mark.parametrize("ttl", [None, 1, 60, 999999999])
+ @pytest.mark.parametrize("has_sender", [False, True])
+ def test_invoke(self, account_or_rt, login, ttl, has_sender):
+ sender = account_or_rt.post_a("/account/device", device_data[1])['id'] if has_sender else None
+ dev = login.post_a("/account/device", device_data[0])
+
+ body = {
+ "target": dev['id'],
+ "command": "a",
+ "payload": { "data": str(random.random()), },
+ "ttl": ttl,
+ }
+ resp = account_or_rt.post_a("/account/devices/invoke_command", body)
+ assert resp['enqueued']
+ assert not resp['notified']
+ assert resp['notifyError'] == "no push callback"
-def test_invoke_other_account(account_or_rt, account2):
- dev = account2.post_a("/account/device", device_data[0])
- body = {"target": dev['id'], "command": "foo", "payload": {}, "ttl": 10}
- with pytest.raises(ClientError) as e:
- account_or_rt.post_a("/account/devices/invoke_command", body)
- assert e.value.details == {
- 'code': 400,
- 'errno': 123,
- 'error': 'Bad Request',
- 'message': 'unknown device'
- }
-
-@pytest.mark.parametrize("ttl", [None, 1, 60, 999999999])
-@pytest.mark.parametrize("has_sender", [False, True])
-def test_invoke(account_or_rt, login, ttl, has_sender):
- sender = account_or_rt.post_a("/account/device", device_data[1])['id'] if has_sender else None
- dev = login.post_a("/account/device", device_data[0])
-
- body = {
- "target": dev['id'],
- "command": "a",
- "payload": { "data": str(random.random()), },
- "ttl": ttl,
- }
- resp = account_or_rt.post_a("/account/devices/invoke_command", body)
- assert resp['enqueued']
- assert not resp['notified']
- assert resp['notifyError'] == "no push callback"
-
- cmd = login.get_a("/account/device/commands?index=0&limit=11")
- assert cmd['last']
- assert len(cmd['messages']) == 1
- assert cmd['messages'][0]['data']['command'] == 'a'
- assert cmd['messages'][0]['data']['payload'] == body['payload']
- assert cmd['messages'][0]['data']['sender'] == sender
+ cmd = login.get_a("/account/device/commands?index=0&limit=11")
+ assert cmd['last']
+ assert len(cmd['messages']) == 1
+ assert cmd['messages'][0]['data']['command'] == 'a'
+ assert cmd['messages'][0]['data']['payload'] == body['payload']
+ assert cmd['messages'][0]['data']['sender'] == sender
def test_commands_noauth(client):
with pytest.raises(ClientError) as e:
@@ -238,65 +276,56 @@ def test_commands_noauth(client):
'message': 'invalid request signature'
}
-def test_commands_unverified(unverified_account):
- with pytest.raises(ClientError) as e:
- unverified_account.get_a("/account/device/commands?index=1")
- assert e.value.details == {
- 'code': 400,
- 'errno': 138,
- 'error': 'Bad Request',
- 'message': 'unverified session'
- }
-
-def test_commands_nodev(account_or_rt):
- with pytest.raises(ClientError) as e:
- account_or_rt.get_a("/account/device/commands?index=1")
- assert e.value.details == {
- 'code': 400,
- 'errno': 123,
- 'error': 'Bad Request',
- 'message': 'unknown device'
- }
-
-@pytest.mark.parametrize('n_cmds,offset,limit', [
- (1, 0, 0),
- (1, 0, 1),
- (1, 0, 100),
- (1, 1, 0),
- (1, 1, 1),
- (1, 1, 100),
- (2, 0, 0),
- (2, 0, 1),
- (2, 0, 100),
- (2, 1, 0),
- (2, 1, 1),
- (2, 1, 100),
- (101, 0, 100),
- (101, 10, 100),
-])
-def test_device_commands_list(account_or_rt, login, n_cmds, offset, limit):
- account_or_rt.post_a("/account/device", device_data[1])['id']
- dev = login.post_a("/account/device", device_data[0])
-
- bodies = [ {
- "target": dev['id'],
- "command": "a",
- "payload": { "data": str(i), },
- } for i in range(0, n_cmds) ]
-
- for b in bodies:
- resp = account_or_rt.post_a("/account/devices/invoke_command", b)
- assert resp['enqueued']
- assert not resp['notified']
- assert resp['notifyError'] == "no push callback"
-
- cmd = login.get_a("/account/device/commands", params={ "index": 0, "limit": 1 })
- assert cmd == login.get_a("/account/device/commands", params={ "index": 0, "limit": 1 })
-
- first_index = cmd['index']
- cmds = login.get_a("/account/device/commands", params={ "limit": limit, "index": first_index + offset })
- assert cmds['last'] == (offset + limit >= n_cmds)
- assert len(cmds['messages']) == min(max(n_cmds - offset, 0), limit)
+class TestDeviceCommands:
+ def test_commands_nodev(self, account_or_rt):
+ with pytest.raises(ClientError) as e:
+ account_or_rt.get_a("/account/device/commands?index=1")
+ assert e.value.details == {
+ 'code': 400,
+ 'errno': 123,
+ 'error': 'Bad Request',
+ 'message': 'unknown device'
+ }
+
+ @pytest.mark.parametrize('n_cmds,offset,limit', [
+ (1, 0, 0),
+ (1, 0, 1),
+ (1, 0, 100),
+ (1, 1, 0),
+ (1, 1, 1),
+ (1, 1, 100),
+ (2, 0, 0),
+ (2, 0, 1),
+ (2, 0, 100),
+ (2, 1, 0),
+ (2, 1, 1),
+ (2, 1, 100),
+ (101, 0, 100),
+ (101, 10, 100),
+ ])
+ def test_device_commands_list(self, account_or_rt, login, n_cmds, offset, limit):
+ account_or_rt.post_a("/account/device", device_data[1])['id']
+ dev = login.post_a("/account/device", device_data[0])
+
+ bodies = [ {
+ "target": dev['id'],
+ "command": "a",
+ "payload": { "data": str(i), },
+ } for i in range(0, n_cmds) ]
+
+ for b in bodies:
+ resp = account_or_rt.post_a("/account/devices/invoke_command", b)
+ assert resp['enqueued']
+ assert not resp['notified']
+ assert resp['notifyError'] == "no push callback"
+
+ cmd = login.get_a("/account/device/commands", params={ "index": 0, "limit": 1 })
+ assert cmd == login.get_a("/account/device/commands", params={ "index": 0, "limit": 1 })
+
+ first_index = cmd['index']
+ cmds = login.get_a("/account/device/commands", params={ "limit": limit, "index": first_index + offset })
+ assert cmds['last'] == (offset + limit >= n_cmds)
+ assert len(cmds['messages']) == min(max(n_cmds - offset, 0), limit)
def test_attached_clients_unauth(client):
with pytest.raises(ClientError) as e:
@@ -308,25 +337,26 @@ def test_attached_clients_unauth(client):
'message': 'invalid request signature'
}
-def test_attached_clients_unverified(unverified_account):
- with pytest.raises(ClientError) as e:
- unverified_account.get_a("/account/attached_clients")
- assert e.value.details == {
- 'code': 400,
- 'errno': 138,
- 'error': 'Bad Request',
- 'message': 'unverified session'
- }
-
-def test_attached_clients_badauth(refresh_token):
- with pytest.raises(ClientError) as e:
- refresh_token.get_a("/account/attached_clients")
- assert e.value.details == {
- 'code': 401,
- 'errno': 109,
- 'error': 'Unauthorized',
- 'message': 'invalid request signature'
- }
+class TestAttachedClientBadauth:
+ def test_attached_clients_badauth(self, refresh_token):
+ with pytest.raises(ClientError) as e:
+ refresh_token.get_a("/account/attached_clients")
+ assert e.value.details == {
+ 'code': 401,
+ 'errno': 109,
+ 'error': 'Unauthorized',
+ 'message': 'invalid request signature'
+ }
+
+ def test_attached_client_destroy_badauth(self, refresh_token):
+ with pytest.raises(ClientError) as e:
+ refresh_token.post_a("/account/attached_client/destroy")
+ assert e.value.details == {
+ 'code': 401,
+ 'errno': 109,
+ 'error': 'Unauthorized',
+ 'message': 'invalid request signature'
+ }
def test_attached_clients(account, refresh_token, push_server):
dev1 = Device(account, "dev1")
@@ -366,69 +396,50 @@ def test_attached_client_destroy_unauth(client):
'message': 'invalid request signature'
}
-def test_attached_client_destroy_unverified(unverified_account):
- with pytest.raises(ClientError) as e:
- unverified_account.post_a("/account/attached_client/destroy")
- assert e.value.details == {
- 'code': 400,
- 'errno': 138,
- 'error': 'Bad Request',
- 'message': 'unverified session'
- }
-
-def test_attached_client_destroy_badauth(refresh_token):
- with pytest.raises(ClientError) as e:
- refresh_token.post_a("/account/attached_client/destroy")
- assert e.value.details == {
- 'code': 401,
- 'errno': 109,
- 'error': 'Unauthorized',
- 'message': 'invalid request signature'
- }
-
-@pytest.mark.parametrize("args,code,errno,error,message", [
- ({"sessionTokenId": "0"},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"refreshTokenId": "0"},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"deviceId": "0"},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"sessionTokenId": "00" * 16, 'extra': 0},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"sessionTokenId": "00" * 16, 'refreshTokenId': "00" * 16},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({"sessionTokenId": "00" * 16, 'refreshTokenId': "00" * 16, 'deviceId': "00" * 16},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
- ({'refreshTokenId': "00" * 16, 'deviceId': "00" * 16},
- 400, 107, 'Bad Request', 'invalid parameter in request body'),
-])
-def test_attached_client_destroy_invalid(account, args, code, errno, error, message):
- with pytest.raises(ClientError) as e:
- account.post_a("/account/attached_client/destroy", args)
- assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
-
-@pytest.mark.parametrize("fn", [
- (lambda d: {'sessionTokenId': d['sessionTokenId']}),
- (lambda d: {'refreshTokenId': d['refreshTokenId']}),
- (lambda d: {'deviceId': d['deviceId']}),
-], ids=["session", "refresh", "device"])
-def test_attached_client_destroy(account, refresh_token, fn):
- Device(refresh_token, "dev2")
- devs = account.get_a("/account/attached_clients")
- account.post_a("/account/attached_client/destroy", fn(devs[0]))
- devs2 = account.get_a("/account/attached_clients")
- assert len(devs2) == len(devs) - 1
-
-def test_attached_client_destroy_push(account, refresh_token, push_server):
- dev = Device(account, "dev")
- dev2 = Device(refresh_token, "dev2")
- dev.update_pcb(push_server.good("4ed8d1d3-e756-4866-9169-aafe612eb1e9"))
- account.post_a("/account/attached_client/destroy", { 'deviceId': dev2.id })
- p = push_server.wait()
- assert p[0] == "/4ed8d1d3-e756-4866-9169-aafe612eb1e9"
- assert dev.decrypt(p[2]) == {
- 'command': 'fxaccounts:device_disconnected',
- 'data': {'id': dev2.id},
- 'version': 1
- }
- assert push_server.done()
+class TestAttachedClients:
+ @pytest.mark.parametrize("args,code,errno,error,message", [
+ ({"sessionTokenId": "0"},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"refreshTokenId": "0"},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"deviceId": "0"},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"sessionTokenId": "00" * 16, 'extra': 0},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"sessionTokenId": "00" * 16, 'refreshTokenId': "00" * 16},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({"sessionTokenId": "00" * 16, 'refreshTokenId': "00" * 16, 'deviceId': "00" * 16},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ({'refreshTokenId': "00" * 16, 'deviceId': "00" * 16},
+ 400, 107, 'Bad Request', 'invalid parameter in request body'),
+ ])
+ def test_attached_client_destroy_invalid(self, account, args, code, errno, error, message):
+ with pytest.raises(ClientError) as e:
+ account.post_a("/account/attached_client/destroy", args)
+ assert e.value.details == {'code': code, 'errno': errno, 'error': error, 'message': message}
+
+ @pytest.mark.parametrize("fn", [
+ (lambda d: {'sessionTokenId': d['sessionTokenId']}),
+ (lambda d: {'refreshTokenId': d['refreshTokenId']}),
+ (lambda d: {'deviceId': d['deviceId']}),
+ ], ids=["session", "refresh", "device"])
+ def test_attached_client_destroy(self, account, refresh_token, fn):
+ Device(refresh_token, "dev2")
+ devs = account.get_a("/account/attached_clients")
+ account.post_a("/account/attached_client/destroy", fn(devs[0]))
+ devs2 = account.get_a("/account/attached_clients")
+ assert len(devs2) == len(devs) - 1
+
+ def test_attached_client_destroy_push(self, account, refresh_token, push_server):
+ dev = Device(account, "dev")
+ dev2 = Device(refresh_token, "dev2")
+ dev.update_pcb(push_server.good("4ed8d1d3-e756-4866-9169-aafe612eb1e9"))
+ account.post_a("/account/attached_client/destroy", { 'deviceId': dev2.id })
+ p = push_server.wait()
+ assert p[0] == "/4ed8d1d3-e756-4866-9169-aafe612eb1e9"
+ assert dev.decrypt(p[2]) == {
+ 'command': 'fxaccounts:device_disconnected',
+ 'data': {'id': dev2.id},
+ 'version': 1
+ }
+ assert push_server.done()