Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
How to implement automatic text-to-link conversion in TypeScript?
I'm trying to create an automatic text-to-link conversion feature in a TypeScript application. The desired workflow is:
- Copy a URL to the clipboard
- Select some text
- Paste the URL - this should convert the selected text into a link pointing to the pasted URL
For example:
Selected text: "Click here"
Pasted URL: "https://www.example.com"
Returns: [Click here](https://www.example.com)
This allows easily creating links on the fly without typing Markdown syntax manually.
I tried implementing this in a TypeScript project with the following code:
let selectedText = '';
document.addEventListener('copy', e => {
const selection = window.getSelection();
if (selection) {
selectedText = selection.toString();
}
});
document.addEventListener('paste', e => {
if (e.clipboardData) {
const pasted = e.clipboardData.getData('text');
if (isValidUrl(pasted)) {
e.preventDefault();
insertLink(selectedText, pasted);
}
}
});
function insertLink(text: string, url: string): void {
document.execCommand('insertHTML', false, `[${text}](${url})`);
}
function isValidUrl(url: string): boolean {
try {
new URL(url);
return true;
} catch (err) {
return false;
}
}
To test this code, I set up a TypeScript project on Manjaro Linux and configured Jest for testing:
- Installed Node.js and npm using
sudo pacman -S nodejs npm
- Created a new TS project
mkdir my-ts-project
cd my-ts-project
npm init -y
- Installed TypeScript with
npm install --save-dev typescript
- Added a
tsconfig.json
file withnpx tsc --init
- Installed Jest, ts-jest, and @types/jest packages with
npm install --save-dev jest ts-jest @types/jest
- Added jest.config.js for configuration
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
- Added test script to package.json
- Wrote the code in
src/index.ts
and test cases insrc/index.test.ts
// src/index.test.ts
import { Clipboard } from './mocks/clipboard';
describe('copy handler', () => {
it('copies selected text to clipboard', () => {
const selectedText = 'hello';
window.getSelection = () => {
return {
toString: () => selectedText
} as unknown as Selection;
};
document.addEventListener('copy', e => {
if(e.clipboardData) {
e.clipboardData.setData('text', selectedText);
}
});
document.dispatchEvent(new Event('copy'));
expect(Clipboard.prototype.writeText).toHaveBeenCalledWith(selectedText);
});
});
describe('paste handler', () => {
it('inserts link on valid url paste', () => {
const url = 'https://example.com';
Clipboard.prototype.clipboardText = url;
document.addEventListener('paste', e => {
if(e.clipboardData) {
const pasted = Clipboard.prototype.readText();
if(isValidUrl(pasted)) {
insertLink('text', pasted);
}
}
});
document.dispatchEvent(new Event('paste'));
expect(insertLink).toHaveBeenCalledWith('text', url);
});
});
// src/mocks/clipboard.ts
export class Clipboard {
public static prototype = {
writeText: jest.fn(),
readText: jest.fn(),
clipboardText: ''
};
}
- Ran tests with
npm test
However, when running npm test
, I got some errors:
> test@1.0.0 test
> jest
FAIL src/index.test.ts
● Test suite failed to run
src/index.test.ts:25:32 - error TS2339: Property 'writeText' does not exist on type 'Clipboard'.
25 expect(Clipboard.prototype.writeText).toHaveBeenCalledWith(selectedText);
~~~~~~~~~
src/index.test.ts:35:25 - error TS2339: Property 'clipboardText' does not exist on type 'Clipboard'.
35 Clipboard.prototype.clipboardText = url;
~~~~~~~~~~~~~
src/index.test.ts:39:44 - error TS2339: Property 'readText' does not exist on type 'Clipboard'.
39 const pasted = Clipboard.prototype.readText();
~~~~~~~~
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 2.056 s
Ran all test suites.
I want to write tests for:
- empty clipboard
- valid URL
- invalid URL
How can I fix the errors and properly mock the clipboard in the tests?
2 comment threads