diff --git a/README.md b/README.md index 30f3d98..c546fe2 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,11 @@ Using `react-secure-link` for outbound links prevents the new tab from having ac ### API -In addition to any prop defined as part of the `React.HTMLAttributes` interface (i.e. `className`, `id`, `role`, `style`), the `SecureLink` component has the following custom props: +`SecureLink` can be used to make text, images, or other children components clickable. In addition to any prop defined as part of the `React.HTMLAttributes` interface (i.e. `className`, `id`, `role`, `style`), the `SecureLink` component has the following custom props: | prop | Required | Type | Description | |-------------|----------|----------|--------------------------------------------------------------------------| | `url` | Yes | `string` | The URL to navigate to. | -| `text` | No | `string` | The text to show. If not provided, the given URL will be shown instead. | | `uniqueKey` | No | `string` or `number` | A unique key to identify the link. This is being used as a `key` value for the component. For more information, refer to [React's website about keys](https://reactjs.org/docs/lists-and-keys.html#keys). | ### Basic Usage Example @@ -52,9 +51,10 @@ In addition to any prop defined as part of the `React.HTMLAttributes +> + react-secure-link on NPM + ``` diff --git a/package-lock.json b/package-lock.json index d39ca8a..fd9c4c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { "name": "react-secure-link", - "version": "1.1.0", + "version": "2.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "1.1.0", + "version": "2.0.0", "license": "GPL-3.0-or-later", "devDependencies": { "@babel/core": "^7.12.9", diff --git a/package.json b/package.json index b47f228..08a3837 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-secure-link", - "version": "1.1.0", + "version": "2.0.0", "description": "A TypeScript compatible React component to avoid security exploits when opening a link in a new tab.", "keywords": [ "react", diff --git a/src/components/__tests__/secure-link.test.tsx b/src/components/__tests__/secure-link.test.tsx index b6dc79b..923858d 100644 --- a/src/components/__tests__/secure-link.test.tsx +++ b/src/components/__tests__/secure-link.test.tsx @@ -13,12 +13,6 @@ beforeAll(() => { url = faker.internet.url(); }); -const emptyTextValues = [ - undefined, - null, - "", -]; - const uniqueKeyPropValues = [ undefined, null, @@ -26,68 +20,86 @@ const uniqueKeyPropValues = [ faker.random.word(), ]; -function renderSecureLink(text: string, uniqueKey: Key): void { - render(); +function renderSecureLinkWithoutChildren(uniqueKey: Key): void { + render(); +} + +function renderSecureLinkWithChildren(text: string, uniqueKey: Key): void { + render({text}); } function getLinkByRole(): HTMLAnchorElement { return screen.getByRole("link") as HTMLAnchorElement; } -function itRendersWithoutCrashing(text: string, uniqueKey: Key): void { - it("renders link without crashing", () => { - renderSecureLink(text, uniqueKey); +each(uniqueKeyPropValues).describe(`when given uniqueKey: %s`, (uniqueKey?) => { + describe("when not given children", () => { + it("renders link without crashing", () => { + renderSecureLinkWithoutChildren(uniqueKey); - expect(getLinkByRole()).toBeInTheDocument(); - }); -} + expect(getLinkByRole()).toBeInTheDocument(); + }); -function itHasExpectedAttributes(text: string, uniqueKey: Key): void { - it("links to given URL", () => { - renderSecureLink(text, uniqueKey); + it("has given text", () => { + renderSecureLinkWithoutChildren(uniqueKey); - expect(getLinkByRole()).toHaveAttribute("href", url); - }); + expect(getLinkByRole()).toHaveTextContent(url); + }); - it("has expected attributes to open link securely", () => { - renderSecureLink(text, uniqueKey); + it("links to given URL", () => { + renderSecureLinkWithoutChildren(uniqueKey); - expect(getLinkByRole()).toHaveAttribute("rel", "noopener noreferrer"); - }); + expect(getLinkByRole()).toHaveAttribute("href", url); + }); - it("has expected attributes to open link in new tab", () => { - renderSecureLink(text, uniqueKey); + it("has expected attributes to open link securely", () => { + renderSecureLinkWithoutChildren(uniqueKey); - expect(getLinkByRole()).toHaveAttribute("target", "_blank"); - }); -} - -each(uniqueKeyPropValues).describe(`when given uniqueKey="%s"`, (uniqueKey?) => { - each(emptyTextValues).describe(`when given empty text="%s"`, (text?) => { - itRendersWithoutCrashing(text, uniqueKey); - itHasExpectedAttributes(text, uniqueKey); + expect(getLinkByRole()).toHaveAttribute("rel", "noopener noreferrer"); + }); - it("text is the same as the URL", () => { - renderSecureLink(text, uniqueKey); + it("has expected attributes to open link in new tab", () => { + renderSecureLinkWithoutChildren(uniqueKey); - expect(getLinkByRole()).toHaveTextContent(url); + expect(getLinkByRole()).toHaveAttribute("target", "_blank"); }); }); - describe("when given text", () => { + describe("when given children", () => { let text: string; beforeAll(() => { text = faker.lorem.word(); }); - itRendersWithoutCrashing(text, uniqueKey); - itHasExpectedAttributes(text, uniqueKey); + it("renders link without crashing", () => { + renderSecureLinkWithChildren(text, uniqueKey); + + expect(getLinkByRole()).toBeInTheDocument(); + }); it("has given text", () => { - renderSecureLink(text, uniqueKey); + renderSecureLinkWithChildren(text, uniqueKey); expect(getLinkByRole()).toHaveTextContent(text); }); + + it("links to given URL", () => { + renderSecureLinkWithChildren(text, uniqueKey); + + expect(getLinkByRole()).toHaveAttribute("href", url); + }); + + it("has expected attributes to open link securely", () => { + renderSecureLinkWithChildren(text, uniqueKey); + + expect(getLinkByRole()).toHaveAttribute("rel", "noopener noreferrer"); + }); + + it("has expected attributes to open link in new tab", () => { + renderSecureLinkWithChildren(text, uniqueKey); + + expect(getLinkByRole()).toHaveAttribute("target", "_blank"); + }); }); }); diff --git a/src/components/secure-link.tsx b/src/components/secure-link.tsx index be7f13c..efc8080 100644 --- a/src/components/secure-link.tsx +++ b/src/components/secure-link.tsx @@ -2,11 +2,10 @@ import React, { Key, ReactElement } from "react"; interface SecureLinkProps extends React.HTMLAttributes { url: string; - text?: string; uniqueKey?: Key; } -export function SecureLink({ url, text, uniqueKey }: SecureLinkProps): ReactElement { +export function SecureLink({ url, uniqueKey, children }: SecureLinkProps): ReactElement { return ( - { - text ? text : url - } + {children ? children : url} ); }