Skip to content

Commit

Permalink
Merge changes from v1.5.0-next.1 into main (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
trevor-anderson committed Jun 19, 2024
2 parents c539260 + 880c2da commit 71d7f37
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 11 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.

---

# [1.5.0-next.1](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.8...v1.5.0-next.1) (2024-06-18)


### Features

* add isValidHttpURL ([570cb33](https://github.com/Nerdware-LLC/ts-string-helpers/commit/570cb33ebf86b6d13dfd101ce0024484e4485d5c))

## [1.4.8](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.7...v1.4.8) (2024-06-17)

## [1.4.8-next.1](https://github.com/Nerdware-LLC/ts-string-helpers/compare/v1.4.7...v1.4.8-next.1) (2024-06-17)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ app.post("/register", (req, res, next) => {
| [`isValidNumeric`](src/validate/numeric.ts) | Returns `true` if `value` only contains numeric characters |
| [`isValidPassword`](src/validate/password.ts) | Returns `true` if `value` is a valid password (see jsdoc for details) |
| [`isValidPhone`](src/validate/phone.ts) | Returns `true` if `value` is a valid string of US phone number _DIGITS_ |
| [`isValidURL`](src/validate/url.ts) | Returns `true` if `value` is a valid absolute HTTP/S URL |
| [`isValidURL`](src/validate/url.ts) | Returns `true` if `value` is a valid absolute or relative URL (protocol agnostic) |
| [`isValidHttpURL`](src/validate/url.ts) | Returns `true` if `value` is a valid absolute HTTP/S URL |

## 🤝 Contributing

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nerdware/ts-string-helpers",
"version": "1.4.8",
"version": "1.5.0-next.1",
"description": "TypeScript string utils for sanitization, validation, and formatting.",
"author": {
"name": "Trevor Anderson",
Expand Down
76 changes: 70 additions & 6 deletions src/validate/url.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,88 @@
import { isValidURL } from "./url.js";
import { isValidURL, isValidHttpURL } from "./url.js";

describe("validate: url", () => {
describe("validate: URL", () => {
// POSITIVE TEST CASES:

test("returns true when given a valid absolute HTTP/S URL string", () => {
expect(isValidURL("https://example.com")).toBe(true);
expect(isValidURL("https://example.com/")).toBe(true);
expect(isValidURL("https://example.com/foo")).toBe(true);
expect(isValidURL("https://example.com/foo/path?query=value")).toBe(true);
expect(isValidURL("https://example.com/foo/path?query=value#anchor-name")).toBe(true);
});
test("returns true when given a valid relative URL without a protocol prefix", () => {
expect(isValidURL("example.com")).toBe(true);
expect(isValidURL("example.com/")).toBe(true);
expect(isValidURL("example.com/foo")).toBe(true);
expect(isValidURL("example.com/foo?bar=qux")).toBe(true);
expect(isValidURL("example.com/foo?bar=qux#anchor-name")).toBe(true);
});
test("returns true when given a valid URL with a protocol other than HTTP/S", () => {
expect(isValidURL("ftp://example.com")).toBe(true);
expect(isValidURL("ftp://example.com/")).toBe(true);
expect(isValidURL("ftp://example.com/foo")).toBe(true);
expect(isValidURL("ftp://example.com/foo?bar=qux")).toBe(true);
expect(isValidURL("ftp://example.com/foo?bar=qux#anchor-name")).toBe(true);

expect(isValidURL("s3://example.com")).toBe(true);
expect(isValidURL("s3://example.com/")).toBe(true);
expect(isValidURL("s3://example.com/foo")).toBe(true);
expect(isValidURL("s3://example.com/foo?bar=qux")).toBe(true);
expect(isValidURL("s3://example.com/foo?bar=qux#anchor-name")).toBe(true);
});

// NEGATIVE TEST CASES:

test("returns false when given a URL which exceeds the max length", () => {
expect(isValidURL(`https://example.com/${Array(2000).join("x")}`)).toBe(false);
});
test("returns false when given an absolute HTTP/S URL string which includes a null unicode character", () => {
expect(isValidURL("https://example\u0000.com")).toBe(false);
expect(isValidURL("https://example.com/\u0000")).toBe(false);
expect(isValidURL("https://example.com/foo\u0000")).toBe(false);
expect(isValidURL("https://example.com/foo?bar\u0000=qux")).toBe(false);
expect(isValidURL("https://example.com/foo?bar=qux\u0000")).toBe(false);
expect(isValidURL("https://example.com/foo?bar=qux#\u0000")).toBe(false);
expect(isValidURL("https://example.com/foo?bar=qux#anchor\u0000")).toBe(false);
});
});

describe("validate: HTTP URL", () => {
// POSITIVE TEST CASES:

test("returns true when given a valid absolute HTTP/S URL string", () => {
expect(isValidHttpURL("https://example.com")).toBe(true);
expect(isValidHttpURL("https://example.com/")).toBe(true);
expect(isValidHttpURL("https://example.com/foo")).toBe(true);
expect(isValidHttpURL("https://example.com/foo/path?query=value")).toBe(true);
expect(isValidHttpURL("https://example.com/foo/path?query=value#anchor-name")).toBe(true);
});

// NEGATIVE TEST CASES:

test("returns false when given a URL without a protocol prefix", () => {
expect(isValidURL("example.com/foo")).toBe(false);
expect(isValidHttpURL("example.com")).toBe(false);
expect(isValidHttpURL("example.com/")).toBe(false);
expect(isValidHttpURL("example.com/foo")).toBe(false);
expect(isValidHttpURL("example.com/foo?bar=qux")).toBe(false);
expect(isValidHttpURL("example.com/foo?bar=qux#anchor-name")).toBe(false);
});
test("returns false when given a URL with a protocol other than HTTP/S", () => {
expect(isValidURL("ftp://example.com/")).toBe(false);
expect(isValidHttpURL("abc://example.com")).toBe(false);
expect(isValidHttpURL("ftp://example.com")).toBe(false);
expect(isValidHttpURL("s3://example.com")).toBe(false);
expect(isValidHttpURL("x://example.com")).toBe(false);
});
test("returns false when given a URL which exceeds the max length", () => {
expect(isValidURL(`https://example.com/${Array(2000).join("x")}`)).toBe(false);
expect(isValidHttpURL(`https://example.com/${Array(2000).join("x")}`)).toBe(false);
});
test("returns false when given an absolute HTTP/S URL string which includes a null unicode character", () => {
expect(isValidURL("https://example.com/\u0000")).toBe(false);
expect(isValidHttpURL("https://example\u0000.com")).toBe(false);
expect(isValidHttpURL("https://example.com/\u0000")).toBe(false);
expect(isValidHttpURL("https://example.com/foo\u0000")).toBe(false);
expect(isValidHttpURL("https://example.com/foo?bar\u0000=qux")).toBe(false);
expect(isValidHttpURL("https://example.com/foo?bar=qux\u0000")).toBe(false);
expect(isValidHttpURL("https://example.com/foo?bar=qux#\u0000")).toBe(false);
expect(isValidHttpURL("https://example.com/foo?bar=qux#anchor\u0000")).toBe(false);
});
});
12 changes: 11 additions & 1 deletion src/validate/url.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import { getRegexValidatorFn } from "./_helpers.js";

/**
* Returns `true` if `value` is a valid absolute HTTP/S URL.
* Returns `true` if `value` is a valid absolute or relative URL.
*
* > The regex pattern used in this function is _protocol agnostic_ and will match any URL
* > that starts with a valid protocol comprised of 2-17 ASCII alphabetic characters.
*/
export const isValidURL = getRegexValidatorFn(
/^(([a-zA-Z]{2,17}:\/\/)?[-a-zA-Z0-9@:%._+~#=]{2,256}(\.[a-zA-Z]{2,6})?(:[0-9]+)?\b([-a-zA-Z0-9@:%_+.~#?&//=]{0,1700})?)$/
);

/**
* Returns `true` if `value` is a valid absolute http/https URL.
*/
export const isValidHttpURL = getRegexValidatorFn(
/^(http(s)?:\/\/[-a-zA-Z0-9@:%._+~#=]{2,256}(\.[a-zA-Z]{2,6})?(:[0-9]+)?\b([-a-zA-Z0-9@:%_+.~#?&//=]{0,1700})?)$/
);

0 comments on commit 71d7f37

Please sign in to comment.