mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-31 09:52:24 +00:00
Refactor copy logic to remove deprecated execCommand
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
84e7f50f96
commit
6d0bd25067
3 files changed
+112
-17
No files matched your search
@@ -399,6 +399,7 @@ export class EmbedVideoModal {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to copy using the Clipboard API
|
||||
if (navigator?.clipboard?.writeText) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(snippet);
|
||||
@@ -409,24 +410,13 @@ export class EmbedVideoModal {
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Select the text so the user can copy manually
|
||||
const textarea = this.snippetTextarea;
|
||||
textarea.focus();
|
||||
textarea.select();
|
||||
textarea.setSelectionRange(0, textarea.value.length);
|
||||
|
||||
let succeeded = false;
|
||||
try {
|
||||
succeeded = this.document.execCommand("copy");
|
||||
} catch (error) {
|
||||
logger.user.warn("Embed modal copy fallback failed.", error);
|
||||
succeeded = false;
|
||||
}
|
||||
|
||||
if (succeeded) {
|
||||
this.callbacks.showSuccess("Embed code copied to clipboard!");
|
||||
} else {
|
||||
this.callbacks.showError("Unable to copy embed code. Please copy it manually.");
|
||||
}
|
||||
this.callbacks.showError("Unable to copy embed code. Please copy it manually.");
|
||||
}
|
||||
|
||||
async open({ video, triggerElement } = {}) {
|
||||
|
||||
@@ -1550,11 +1550,8 @@ export default class LoginModalController {
|
||||
if (!copied && handshakeInput.select) {
|
||||
try {
|
||||
handshakeInput.select();
|
||||
if (this.document?.execCommand) {
|
||||
copied = this.document.execCommand("copy");
|
||||
}
|
||||
} catch (error) {
|
||||
copied = false;
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
if (copied) {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
// Mock globals
|
||||
if (!globalThis.window) {
|
||||
globalThis.window = {
|
||||
location: { origin: "http://localhost" },
|
||||
NostrTools: { nip19: { naddrEncode: () => "naddr...", neventEncode: () => "nevent..." } }
|
||||
};
|
||||
}
|
||||
if (!globalThis.document) {
|
||||
globalThis.document = {
|
||||
createElement: (tag) => {
|
||||
return {
|
||||
tagName: tag.toUpperCase(),
|
||||
innerHTML: "",
|
||||
firstChild: null,
|
||||
querySelector: () => null,
|
||||
classList: { add: () => {}, remove: () => {}, contains: () => false },
|
||||
addEventListener: () => {},
|
||||
setAttribute: () => {},
|
||||
appendChild: () => {},
|
||||
disabled: false,
|
||||
checked: false,
|
||||
value: ""
|
||||
};
|
||||
},
|
||||
createDocumentFragment: () => ({ appendChild: () => {} }),
|
||||
getElementById: () => null,
|
||||
body: { appendChild: () => {} },
|
||||
execCommand: () => {}
|
||||
};
|
||||
}
|
||||
if (!globalThis.navigator) {
|
||||
globalThis.navigator = {
|
||||
userAgent: "node",
|
||||
};
|
||||
}
|
||||
if (!globalThis.navigator.clipboard) {
|
||||
globalThis.navigator.clipboard = {
|
||||
writeText: async () => {},
|
||||
};
|
||||
}
|
||||
|
||||
import { EmbedVideoModal } from "../../../js/ui/components/EmbedVideoModal.js";
|
||||
|
||||
test("EmbedVideoModal handleCopy uses navigator.clipboard", async (t) => {
|
||||
let clipboardText = "";
|
||||
const originalWriteText = globalThis.navigator.clipboard.writeText;
|
||||
globalThis.navigator.clipboard.writeText = async (text) => {
|
||||
clipboardText = text;
|
||||
};
|
||||
|
||||
let successMsg = "";
|
||||
const callbacks = {
|
||||
showSuccess: (msg) => { successMsg = msg; },
|
||||
showError: () => {}
|
||||
};
|
||||
|
||||
const modal = new EmbedVideoModal({ callbacks });
|
||||
modal.snippetTextarea = { value: "<iframe></iframe>", select: () => {}, setSelectionRange: () => {}, focus: () => {} };
|
||||
|
||||
await modal.handleCopy();
|
||||
|
||||
assert.equal(clipboardText, "<iframe></iframe>");
|
||||
assert.equal(successMsg, "Embed code copied to clipboard!");
|
||||
|
||||
globalThis.navigator.clipboard.writeText = originalWriteText;
|
||||
});
|
||||
|
||||
test("EmbedVideoModal handleCopy handles clipboard failure without execCommand", async (t) => {
|
||||
// Simulate clipboard failure
|
||||
const originalWriteText = globalThis.navigator.clipboard.writeText;
|
||||
globalThis.navigator.clipboard.writeText = async () => { throw new Error("Clipboard error"); };
|
||||
|
||||
let errorMsg = "";
|
||||
const callbacks = {
|
||||
showSuccess: () => {},
|
||||
showError: (msg) => { errorMsg = msg; }
|
||||
};
|
||||
|
||||
// Mock document.execCommand to track calls
|
||||
let execCommandCalled = false;
|
||||
const originalExecCommand = globalThis.document.execCommand;
|
||||
globalThis.document.execCommand = () => { execCommandCalled = true; return false; };
|
||||
|
||||
const modal = new EmbedVideoModal({ callbacks });
|
||||
// Ensure modal uses our mocked document
|
||||
modal.document = globalThis.document;
|
||||
|
||||
let selectCalled = false;
|
||||
modal.snippetTextarea = {
|
||||
value: "<iframe></iframe>",
|
||||
select: () => { selectCalled = true; },
|
||||
setSelectionRange: () => {},
|
||||
focus: () => {}
|
||||
};
|
||||
|
||||
await modal.handleCopy();
|
||||
|
||||
assert.equal(execCommandCalled, false, "execCommand should not be called");
|
||||
assert.equal(selectCalled, true, "Text should be selected for manual copy");
|
||||
assert.ok(errorMsg.toLowerCase().includes("manual"), "Error message should mention manual copy");
|
||||
|
||||
// Restore
|
||||
globalThis.document.execCommand = originalExecCommand;
|
||||
globalThis.navigator.clipboard.writeText = originalWriteText;
|
||||
});
|
||||
Reference in new issue
Block a user