diff --git a/tests/persimmons_gitea_fixture.py b/tests/persimmons_gitea_fixture.py new file mode 100644 index 0000000..ac61eab --- /dev/null +++ b/tests/persimmons_gitea_fixture.py @@ -0,0 +1,69 @@ +"""Contract fixture for the dedicated Gitea API, never a fallback auth store.""" +from copy import deepcopy +from persimmons import gitea + + +class GiteaFixture: + def __init__(self): + self.users = {} + self.repos = {} + self.calls = [] + self.variables = {} + self.secrets = {} + + def __call__(self, path, method='GET', body=None, login=None): + self.calls.append((path, method, deepcopy(body))) + if path == '/admin/users' and method == 'POST': + name = body['username'] + if name in self.users: + raise gitea.Failure(422) + user = {'id': len(self.users) + 2, 'login': name, 'is_admin': False, 'active': True} + self.users[name] = (user, body['password']) + return deepcopy(user) + if path == '/user': + if not login or login[0] not in self.users or login[1] != self.users[login[0]][1]: + raise gitea.Failure(401) + return deepcopy(self.users[login[0]][0]) + if path.startswith('/users/'): + if path[7:] not in self.users: + raise gitea.Failure(404) + return deepcopy(self.users[path[7:]][0]) + if path.startswith('/admin/users/') and path.endswith('/repos'): + name = path.split('/')[3] + key = (name, body['name'].lower()) + if key in self.repos: + raise gitea.Failure(409) + repo = {'id': len(self.repos) + 1, 'name': body['name'], 'owner': self.users[name][0], + 'private': body['private'], 'empty': not body['auto_init']} + self.repos[key] = deepcopy(repo) + return deepcopy(repo) + if '/actions/' in path: + base, action = path.split('/actions/') + self(base) + kind, _, name = action.partition('/') + kind = kind.split('?')[0] + store = self.variables if kind == 'variables' else self.secrets + key = (base, name) + if method == 'GET': + if kind == 'secrets': + raise AssertionError('Secret read forbidden') + if not name: + return [{'name': n, 'data': v} for (b, n), v in store.items() if b == base] + if key not in store: + raise gitea.Failure(404) + return {'name': name, 'data': store[key]} + if method == 'POST' and key in store: + raise gitea.Failure(409) + if method == 'DELETE': + if key not in store: + raise gitea.Failure(404) + del store[key] + else: + store[key] = body['value' if kind == 'variables' else 'data'] + return None + if path.startswith('/repos/'): + _, _, owner, name = path.split('/') + if (owner, name.lower()) not in self.repos: + raise gitea.Failure(404) + return deepcopy(self.repos[owner, name.lower()]) + raise AssertionError('Unexpected Gitea request: ' + path)