-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: dependency to handle slash commands request (#4)
- Loading branch information
Showing
15 changed files
with
352 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from asgi_lifespan import LifespanManager | ||
from httpx import ASGITransport, AsyncClient | ||
from pytest import fixture | ||
|
||
|
||
@fixture | ||
async def app(): | ||
from demo import app | ||
|
||
from fastapi_slack import with_valid_signature | ||
|
||
async with LifespanManager(app): | ||
app.dependency_overrides[with_valid_signature] = lambda: "signature" | ||
yield app | ||
|
||
|
||
@fixture | ||
async def client(app): | ||
async with LifespanManager(app): | ||
transport = ASGITransport(app=app) | ||
async with AsyncClient( | ||
transport=transport, base_url="http://example.local" | ||
) as client: | ||
yield client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
from fastapi import Depends, FastAPI | ||
|
||
from fastapi_slack import SlashCommand, router, with_slash_command | ||
|
||
app = FastAPI(title="demo") | ||
app.include_router(router) | ||
|
||
|
||
@app.post("/slack-commands") | ||
def commands(command: SlashCommand = Depends(with_slash_command)): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from pytest import fixture, mark | ||
|
||
pytestmark = mark.asyncio | ||
|
||
|
||
@fixture | ||
def payload() -> str: | ||
return ( | ||
"token=gIkuvaNzQIHg97ATvDxqgjtO" | ||
"&team_id=T0001" | ||
"&team_domain=example" | ||
"&enterprise_id=E0001" | ||
"&enterprise_name=Globular%20Construct%20Inc" | ||
"&channel_id=C2147483705" | ||
"&channel_name=test" | ||
"&user_id=U2147483697" | ||
"&user_name=Steve" | ||
"&command=/weather" | ||
"&text=94070" | ||
"&response_url=https://hooks.slack.com/commands/1234/5678" | ||
"&trigger_id=13345224609.738474920.8088930838d88f008e0" | ||
"&api_app_id=A123456" | ||
) | ||
|
||
|
||
async def test_slack_command(client, payload): | ||
res = await client.post("/slack-commands", content=payload) | ||
assert res.status_code == 200, res.content |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from pytest import fixture | ||
|
||
|
||
@fixture | ||
def secret(): | ||
"""Valid slack signing secret.""" | ||
return "e33f1fb286333652295f920c461de67d" | ||
|
||
|
||
@fixture | ||
def timestamp(): | ||
"""Valid timestamp.""" | ||
return 1602970682 | ||
|
||
|
||
@fixture | ||
def signature(): | ||
"""Valid signature.""" | ||
return "v0=9f214e30377799cf44e680e22991f04147a32bf2434954247728d60304180dc2" | ||
|
||
|
||
@fixture | ||
def body() -> bytes: | ||
"""Valid slack command body.""" | ||
return ( | ||
b"token=zLKyq9QNyqgGQ3weXwtSov90&team_id=T129F61FC&team_domain=dialoguemd&channe" | ||
b"l_id=D1V7CLUH3&channel_name=directmessage&user_id=U1V5RS49Z&user_name=hadrien&" | ||
b"command=%2Fdev-ohs&text=&api_app_id=A01D64BPMTK&response_url=https%3A%2F%2Fhoo" | ||
b"ks.slack.com%2Fcommands%2FT129F61FC%2F1435644863042%2FgV9qwUtCPGS3AQry7kNLiVsX" | ||
b"&trigger_id=1428914092678.36321205522.18053fc39d1f89c8bab43fd18ee47ed8" | ||
) | ||
|
||
|
||
def test_check_signature(secret, timestamp, signature, body): | ||
from fastapi_slack import check_signature | ||
|
||
assert check_signature(secret, timestamp, signature, body) is True | ||
|
||
|
||
def test_check_signature_return_false_on_invalid_signature(): | ||
from fastapi_slack import check_signature | ||
|
||
assert check_signature("secret", 12345, "signature", b"body") is False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from fastapi import HTTPException | ||
from pytest import fixture, mark, raises | ||
|
||
pytestmark = mark.asyncio | ||
|
||
|
||
@fixture | ||
def missing_variables(monkeypatch): | ||
monkeypatch.delenv("slack_access_token") | ||
monkeypatch.delenv("slack_signing_secret") | ||
|
||
|
||
async def test_on_startup_fails_with_invalid_settings(missing_variables): | ||
from fastapi_slack import on_startup | ||
|
||
with raises(Exception): | ||
await on_startup() | ||
|
||
|
||
async def test_on_startup(): | ||
from fastapi_slack import on_startup | ||
|
||
await on_startup() | ||
|
||
|
||
async def test_with_settings(settings): | ||
from fastapi_slack import with_settings | ||
|
||
assert with_settings() == settings | ||
|
||
|
||
async def test_with_settings_raises_500_with_missing_variables(missing_variables): | ||
from fastapi_slack import with_settings | ||
|
||
with raises(HTTPException) as raise_info: | ||
with_settings() | ||
|
||
assert raise_info.value.status_code == 500 |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
from unittest.mock import AsyncMock | ||
|
||
from fastapi import Request | ||
from pytest import mark | ||
|
||
pytestmark = mark.asyncio | ||
|
||
|
||
async def test_with_body(): | ||
from fastapi_slack import with_body | ||
|
||
request = AsyncMock(spec=Request) | ||
request.body.return_value = b"b o d y" | ||
|
||
assert await with_body(request) == b"b o d y" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
def test_with_form_data(): | ||
from fastapi_slack import with_form_data | ||
|
||
assert with_form_data(b"param1=1¶m2=abc") == { | ||
"param1": "1", | ||
"param2": "abc", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from pytest import fixture | ||
|
||
|
||
@fixture | ||
def form_data() -> dict: | ||
# https://api.slack.com/interactivity/slash-commands#app_command_handling | ||
return { | ||
"token": "gIkuvaNzQIHg97ATvDxqgjtO", | ||
"team_id": "T0001", | ||
"team_domain": "example", | ||
"enterprise_id": "E0001", | ||
"enterprise_name": "Globular Construct Inc", | ||
"channel_id": "C2147483705", | ||
"channel_name": "test", | ||
"user_id": "U2147483697", | ||
"user_name": "Steve", | ||
"command": "/weather", | ||
"text": "94070", | ||
"response_url": "https://hooks.slack.com/commands/1234/5678", | ||
"trigger_id": "13345224609.738474920.8088930838d88f008e0", | ||
"api_app_id": "A123456", | ||
} | ||
|
||
|
||
def test_slash_commands(settings, form_data): | ||
from fastapi_slack import with_slash_command | ||
|
||
slash_command = with_slash_command(form_data, "signature") | ||
|
||
assert slash_command.dict() == form_data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from unittest.mock import patch | ||
|
||
from fastapi import HTTPException | ||
from pytest import fixture, raises | ||
|
||
|
||
@fixture | ||
def check_signature(): | ||
with patch("fastapi_slack.check_signature") as check_signature: | ||
check_signature.return_value = True | ||
yield check_signature | ||
|
||
|
||
def test_with_valid_signature(check_signature, settings): | ||
from fastapi_slack import with_valid_signature | ||
|
||
with_valid_signature(b"b o d y", settings, 12345, "signature") | ||
|
||
|
||
def test_with_valid_signature_raises_403_when_signature_is_invalid( | ||
check_signature, settings | ||
): | ||
from fastapi_slack import with_valid_signature | ||
|
||
check_signature.return_value = False | ||
with raises(HTTPException) as raise_info: | ||
with_valid_signature(b"b o d y", settings, 12345, "signature") | ||
|
||
assert raise_info.value.status_code == 403 |
Oops, something went wrong.