mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: Engel Nyst <engel.nyst@gmail.com> Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
163 lines
7.2 KiB
Python
163 lines
7.2 KiB
Python
from integrations.utils import (
|
|
has_exact_mention,
|
|
infer_repo_from_message,
|
|
markdown_to_jira_markup,
|
|
)
|
|
|
|
|
|
def test_has_exact_mention():
|
|
# Test basic exact match
|
|
assert has_exact_mention('Hello @openhands!', '@openhands') is True
|
|
assert has_exact_mention('@openhands at start', '@openhands') is True
|
|
assert has_exact_mention('End with @openhands', '@openhands') is True
|
|
assert has_exact_mention('@openhands', '@openhands') is True
|
|
|
|
# Test no match
|
|
assert has_exact_mention('No mention here', '@openhands') is False
|
|
assert has_exact_mention('', '@openhands') is False
|
|
|
|
# Test partial matches (should be False)
|
|
assert has_exact_mention('Hello @openhands-agent!', '@openhands') is False
|
|
assert has_exact_mention('Email: user@openhands.com', '@openhands') is False
|
|
assert has_exact_mention('Text@openhands', '@openhands') is False
|
|
assert has_exact_mention('@openhandsmore', '@openhands') is False
|
|
|
|
# Test with special characters in mention
|
|
assert has_exact_mention('Hi @open.hands!', '@open.hands') is True
|
|
assert has_exact_mention('Using @open-hands', '@open-hands') is True
|
|
assert has_exact_mention('With @open_hands_ai', '@open_hands_ai') is True
|
|
|
|
# Test case insensitivity (function now handles case conversion internally)
|
|
assert has_exact_mention('Hi @OpenHands', '@OpenHands') is True
|
|
assert has_exact_mention('Hi @OpenHands', '@openhands') is True
|
|
assert has_exact_mention('Hi @openhands', '@OpenHands') is True
|
|
assert has_exact_mention('Hi @OPENHANDS', '@openhands') is True
|
|
|
|
# Test multiple mentions
|
|
assert has_exact_mention('@openhands and @openhands again', '@openhands') is True
|
|
assert has_exact_mention('@openhands-agent and @openhands', '@openhands') is True
|
|
|
|
# Test with surrounding punctuation
|
|
assert has_exact_mention('Hey, @openhands!', '@openhands') is True
|
|
assert has_exact_mention('(@openhands)', '@openhands') is True
|
|
assert has_exact_mention('@openhands: hello', '@openhands') is True
|
|
assert has_exact_mention('@openhands? yes', '@openhands') is True
|
|
|
|
|
|
def test_markdown_to_jira_markup():
|
|
test_cases = [
|
|
('**Bold text**', '*Bold text*'),
|
|
('__Bold text__', '*Bold text*'),
|
|
('*Italic text*', '_Italic text_'),
|
|
('_Italic text_', '_Italic text_'),
|
|
('**Bold** and *italic*', '*Bold* and _italic_'),
|
|
('Mixed *italic* and **bold** text', 'Mixed _italic_ and *bold* text'),
|
|
('# Header', 'h1. Header'),
|
|
('`code`', '{{code}}'),
|
|
('```python\ncode\n```', '{code:python}\ncode\n{code}'),
|
|
('[link](url)', '[link|url]'),
|
|
('- item', '* item'),
|
|
('1. item', '# item'),
|
|
('~~strike~~', '-strike-'),
|
|
('> quote', 'bq. quote'),
|
|
]
|
|
|
|
for markdown, expected in test_cases:
|
|
result = markdown_to_jira_markup(markdown)
|
|
assert (
|
|
result == expected
|
|
), f'Failed for {repr(markdown)}: got {repr(result)}, expected {repr(expected)}'
|
|
|
|
|
|
def test_infer_repo_from_message():
|
|
test_cases = [
|
|
# Single GitHub URLs
|
|
('Clone https://github.com/demo123/demo1.git', ['demo123/demo1']),
|
|
(
|
|
'Check out https://github.com/OpenHands/OpenHands.git for details',
|
|
['OpenHands/OpenHands'],
|
|
),
|
|
('Visit https://github.com/microsoft/vscode', ['microsoft/vscode']),
|
|
# Single GitLab URLs
|
|
('Deploy https://gitlab.com/demo1670324/demo1.git', ['demo1670324/demo1']),
|
|
('See https://gitlab.com/gitlab-org/gitlab', ['gitlab-org/gitlab']),
|
|
(
|
|
'Repository at https://gitlab.com/user.name/my-project.git',
|
|
['user.name/my-project'],
|
|
),
|
|
# Single BitBucket URLs
|
|
('Pull from https://bitbucket.org/demo123/demo1.git', ['demo123/demo1']),
|
|
(
|
|
'Code is at https://bitbucket.org/atlassian/atlassian-connect-express',
|
|
['atlassian/atlassian-connect-express'],
|
|
),
|
|
# Single direct owner/repo mentions
|
|
('Please deploy the OpenHands/OpenHands repo', ['OpenHands/OpenHands']),
|
|
('I need help with the microsoft/vscode repository', ['microsoft/vscode']),
|
|
('Check facebook/react for examples', ['facebook/react']),
|
|
('The torvalds/linux kernel', ['torvalds/linux']),
|
|
# Multiple repositories in one message
|
|
(
|
|
'Compare https://github.com/user1/repo1.git with https://gitlab.com/user2/repo2',
|
|
['user1/repo1', 'user2/repo2'],
|
|
),
|
|
(
|
|
'Check facebook/react, microsoft/vscode, and google/angular',
|
|
['facebook/react', 'microsoft/vscode', 'google/angular'],
|
|
),
|
|
(
|
|
'URLs: https://github.com/python/cpython and https://bitbucket.org/atlassian/jira',
|
|
['python/cpython', 'atlassian/jira'],
|
|
),
|
|
(
|
|
'Mixed: https://github.com/owner/repo1.git and owner2/repo2 for testing',
|
|
['owner/repo1', 'owner2/repo2'],
|
|
),
|
|
# Multi-line messages with multiple repos
|
|
(
|
|
'Please check these repositories:\n\nhttps://github.com/python/cpython\nhttps://gitlab.com/gitlab-org/gitlab\n\nfor updates',
|
|
['python/cpython', 'gitlab-org/gitlab'],
|
|
),
|
|
(
|
|
'I found issues in:\n- facebook/react\n- microsoft/vscode\n- google/angular',
|
|
['facebook/react', 'microsoft/vscode', 'google/angular'],
|
|
),
|
|
# Duplicate handling (should not duplicate)
|
|
('Check https://github.com/user/repo.git and user/repo again', ['user/repo']),
|
|
(
|
|
'Both https://github.com/facebook/react and facebook/react library',
|
|
['facebook/react'],
|
|
),
|
|
# URLs with parameters and fragments
|
|
(
|
|
'Clone https://github.com/user/repo.git?ref=main and https://gitlab.com/group/project.git#readme',
|
|
['user/repo', 'group/project'],
|
|
),
|
|
# Complex mixed content (Git URLs have priority over direct mentions)
|
|
(
|
|
'Deploy https://github.com/main/app.git, check facebook/react docs, and https://bitbucket.org/team/utils',
|
|
['main/app', 'team/utils', 'facebook/react'],
|
|
),
|
|
# Messages that should return empty list
|
|
('This is a message without a repo mention', []),
|
|
('Just some text about 12/25 date format', []),
|
|
('Version 1.0/2.0 comparison', []),
|
|
('http://example.com/not-a-git-url', []),
|
|
('Some/path/to/file.txt', []),
|
|
('Check the config.json file', []),
|
|
# Edge cases with special characters
|
|
('https://github.com/My-User/My-Repo.git', ['My-User/My-Repo']),
|
|
('Check the my.user/my.repo repository', ['my.user/my.repo']),
|
|
('repos: user_1/repo-1 and user.2/repo_2', ['user_1/repo-1', 'user.2/repo_2']),
|
|
# Large number of repositories
|
|
('Repos: a/b, c/d, e/f, g/h, i/j', ['a/b', 'c/d', 'e/f', 'g/h', 'i/j']),
|
|
# Mixed with false positives that should be filtered
|
|
('Check user/repo and avoid 1.0/2.0 and file.txt', ['user/repo']),
|
|
]
|
|
|
|
for message, expected in test_cases:
|
|
result = infer_repo_from_message(message)
|
|
assert (
|
|
result == expected
|
|
), f'Failed for {repr(message)}: got {repr(result)}, expected {repr(expected)}'
|