diff --git a/src/paste/templates/paste.html b/src/paste/templates/paste.html index 07e8dd3..3bcddf4 100644 --- a/src/paste/templates/paste.html +++ b/src/paste/templates/paste.html @@ -189,7 +189,7 @@ .copy-buttons-container { position: absolute; right: 20px; - top: 20px; + top: 70px; display: flex; flex-direction: column; gap: 10px; @@ -305,7 +305,7 @@ .copy-buttons-container { right: 10px; - top: 10px; + top: 60px; } .copy-button { @@ -331,16 +331,15 @@
paste.py 🐍
-
+
+ + +
-
- - -
{{ highlighted_code | safe }}
@@ -402,77 +401,75 @@ }, 300); }); - function copyAllText() { - const codeElement = document.querySelector('.code pre'); - const range = document.createRange(); - range.selectNode(codeElement); - - const selection = window.getSelection(); - selection.removeAllRanges(); - selection.addRange(range); - - document.execCommand('copy'); - selection.removeAllRanges(); - - const copyButton = document.getElementById('copyButton'); - const originalText = copyButton.innerHTML; - copyButton.innerHTML = ' COPIED!'; - + function showCopyFeedback(button, success, successHTML, failureHTML) { + const originalText = button.innerHTML; + button.innerHTML = success ? successHTML : failureHTML; setTimeout(() => { - copyButton.innerHTML = originalText; + button.innerHTML = originalText; }, 2000); } - - function copyLink() { - const currentUrl = window.location.href; - - if (navigator.clipboard) { - navigator.clipboard.writeText(currentUrl).then(() => { - const copyLinkButton = document.getElementById('copyLinkButton'); - const originalText = copyLinkButton.innerHTML; - copyLinkButton.innerHTML = ' LINK COPIED!'; - - setTimeout(() => { - copyLinkButton.innerHTML = originalText; - }, 2000); - }).catch(() => { - fallbackCopyLink(currentUrl); - }); - } else { - fallbackCopyLink(currentUrl); - } - } - - function fallbackCopyLink(text) { + + function fallbackCopy(textToCopy, button, successHTML, failureHTML) { const textArea = document.createElement("textarea"); - textArea.value = text; + textArea.value = textToCopy; textArea.style.position = "fixed"; textArea.style.left = "-999999px"; textArea.style.top = "-999999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); - + + let success = false; try { - document.execCommand('copy'); - const copyLinkButton = document.getElementById('copyLinkButton'); - const originalText = copyLinkButton.innerHTML; - copyLinkButton.innerHTML = ' LINK COPIED!'; - - setTimeout(() => { - copyLinkButton.innerHTML = originalText; - }, 2000); + success = document.execCommand('copy'); } catch (err) { - const copyLinkButton = document.getElementById('copyLinkButton'); - const originalText = copyLinkButton.innerHTML; - copyLinkButton.innerHTML = ' COPY FAILED'; - - setTimeout(() => { - copyLinkButton.innerHTML = originalText; - }, 2000); + console.error('Fallback copy failed', err); } - + document.body.removeChild(textArea); + showCopyFeedback(button, success, successHTML, failureHTML); + } + + function copyAllText() { + const codeElement = document.querySelector('.code pre'); + if (!codeElement) return; + + const clone = codeElement.cloneNode(true); + const lineNumbers = clone.querySelectorAll('.linenos'); + lineNumbers.forEach(span => span.remove()); + const textToCopy = clone.textContent; + + const copyButton = document.getElementById('copyButton'); + const successHTML = ' COPIED!'; + const failureHTML = ' FAILED!'; + + if (navigator.clipboard) { + navigator.clipboard.writeText(textToCopy).then(() => { + showCopyFeedback(copyButton, true, successHTML, failureHTML); + }).catch(err => { + console.error('Async copy failed, using fallback', err); + fallbackCopy(textToCopy, copyButton, successHTML, failureHTML); + }); + } else { + fallbackCopy(textToCopy, copyButton, successHTML, failureHTML); + } + } + + function copyLink() { + const currentUrl = window.location.href; + const copyLinkButton = document.getElementById('copyLinkButton'); + const successHTML = ' LINK COPIED!'; + const failureHTML = ' COPY FAILED'; + + if (navigator.clipboard) { + navigator.clipboard.writeText(currentUrl).then(() => { + showCopyFeedback(copyLinkButton, true, successHTML, failureHTML); + }).catch(() => { + fallbackCopy(currentUrl, copyLinkButton, successHTML, failureHTML); + }); + } else { + fallbackCopy(currentUrl, copyLinkButton, successHTML, failureHTML); + } } {% endblock %} \ No newline at end of file diff --git a/tests/test_api.py b/tests/test_api.py index a2124dc..f8a6b41 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,133 +1,26 @@ from fastapi.testclient import TestClient from src.paste.main import app from typing import Optional -import os client: TestClient = TestClient(app) -file: Optional[str] = None +paste_id: Optional[str] = None def test_get_health_route() -> None: - data: dict = {"status": "ok"} response = client.get("/health") assert response.status_code == 200 - assert response.json() == data -def test_get_homepage_route() -> None: - response_expected_headers: str = "text/html; charset=utf-8" - response = client.get("/") - assert response.status_code == 200 - assert response.headers.get("Content-Type", "") == response_expected_headers - - -def test_get_web_route() -> None: - response_expected_headers: str = "text/html; charset=utf-8" - response = client.get("/web") - assert response.status_code == 200 - assert response.headers.get("Content-Type", "") == response_expected_headers - - -def test_get_paste_data_route() -> None: - data: str = "This is a test file." - response = client.get("/paste/test") - assert response.status_code == 200 - assert data in response.text - - -def test_post_web_route() -> None: - data: str = "This is a test data" - form_data: dict = {"content": data, "extension": ".txt"} - response = client.post("/web", data=form_data) - global file - file = str(response.url).split("/")[-1] - assert response.status_code == 200 - assert data in response.text - - -def test_delete_paste_route() -> None: - expected_response: str = f"File successfully deleted {file}" - response = client.delete(f"/paste/{file}") - assert response.status_code == 200 - assert response.text == expected_response - - -def test_post_file_route() -> None: - response = client.post("/file", files={"file": ("test.txt", b"test file content")}) - assert response.status_code == 201 - response_file_uuid: str = response.text - response = client.get(f"/paste/{response_file_uuid}") - assert response.status_code == 200 - assert "test file content" in response.text - response = client.delete(f"/paste/{response_file_uuid}") - assert response.status_code == 200 - assert f"File successfully deleted {response_file_uuid}" in response.text - - -def test_post_file_route_failure() -> None: - response = client.post("/file") - assert response.status_code == 422 # Unprocessable Entity - # Add body assertion in future. - - -def test_post_file_route_size_limit() -> None: - large_file_name: str = "large_file.txt" - file_size: int = 20 * 1024 * 1024 # 20 MB in bytes - additional_bytes: int = 100 # Adding some extra bytes to exceed 20 MB - content: bytes = b"This is a line in the file.\n" - with open(large_file_name, "wb") as file: - while file.tell() < file_size: - file.write(content) - file.write(b"Extra bytes to exceed 20 MB\n" * additional_bytes) - file.close() - f = open(large_file_name, "rb") - files: dict = {"file": f} - response = client.post("/file", files=files) - f.close() - # cleanup - os.remove(large_file_name) - assert response.status_code == 413 - assert "File is too large" in response.text - - -def test_post_api_paste_route() -> None: - paste_data = {"content": "This is a test paste content", "extension": "txt"} - response = client.post("/api/paste", json=paste_data) - assert response.status_code == 201 - response_json = response.json() - assert "uuid" in response_json - assert "url" in response_json - assert response_json["uuid"].endswith(".txt") - assert response_json["url"].startswith("http://paste.fosscu.org/paste/") - - # Clean up: delete the created paste - uuid = response_json["uuid"] - delete_response = client.delete(f"/paste/{uuid}") - assert delete_response.status_code == 200 - - -def test_get_api_paste_route() -> None: - # First, create a paste - paste_data = {"content": "This is a test paste content for GET", "extension": "md"} - create_response = client.post("/api/paste", json=paste_data) - assert create_response.status_code == 201 - created_uuid = create_response.json()["uuid"] - - # Now, test getting the paste - response = client.get(f"/api/paste/{created_uuid}") - assert response.status_code == 200 - response_json = response.json() - assert response_json["uuid"] == created_uuid - assert response_json["content"] == paste_data["content"] - assert response_json["extension"] == paste_data["extension"] - - # Clean up: delete the created paste - delete_response = client.delete(f"/paste/{created_uuid}") - assert delete_response.status_code == 200 +def test_paste_api_route() -> None: + respose = client.post( + "/api/paste", + json={ + "content": "Hello-World", + }, + ) + paste_id = respose.text + assert respose.status_code == 201 -def test_get_api_paste_route_not_found() -> None: - response = client.get("/api/paste/nonexistent_uuid.txt") - assert response.status_code == 404 - assert response.json()["detail"] == "Paste not found" +print(paste_id)