Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ <H1>this is a really big heading tag. 51 chars long even. this is a really big h
<p> - List item</p>
<p>Split breaks:</p>
<p>1. List Item<br>2. List Item</p>
<a href="weird link">Link</a>
</textarea>
</div>
</div>
Expand Down
20 changes: 20 additions & 0 deletions src/rules/__tests__/__snapshots__/valid-links.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`data returns the proper object 1`] = `
Object {
"href": null,
}
`;

exports[`form returns the proper object 1`] = `
Array [
Object {
"dataKey": "href",
"label": "Change the URL for this link",
},
]
`;

exports[`message returns the proper message 1`] = `"Links should be valid."`;

exports[`why returns the proper why message 1`] = `"Invalid links become broken links which are confusing to all users."`;
76 changes: 76 additions & 0 deletions src/rules/__tests__/valid-links.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import rule from "../valid-links"

let body, a

beforeEach(() => {
body = document.createElement("body")
a = document.createElement("a")
body.appendChild(a)
a.textContent = "Link Text"
})

describe("test", () => {
test("returns true if not A element", () => {
expect(rule.test(document.createElement("div"))).toBe(true)
})

test("returns true for valid links", () => {
a.setAttribute("href", "http://example.com")
expect(rule.test(a)).toBe(true)
a.setAttribute("href", "mailto:[email protected]")
expect(rule.test(a)).toBe(true)
})

test("returns false for invalid links", () => {
a.setAttribute("href", "http://something weird")
expect(rule.test(a)).toBe(false)
a.setAttribute("href", "plaintext")
expect(rule.test(a)).toBe(false)
})
})

describe("data", () => {
test("returns the proper object", () => {
expect(rule.data(a)).toMatchSnapshot()
})
})

describe("form", () => {
test("returns the proper object", () => {
expect(rule.form(a)).toMatchSnapshot()
})
})

describe("update", () => {
test("returns same element", () => {
expect(rule.update(a, {})).toBe(a)
})
test("does not change href if href does not change", () => {
const href = "http://example.com"
a.setAttribute("href", href)
expect(rule.update(a, { href })).toBe(a)
})
test("changes href if it has been changed", () => {
const href = "bad"
a.setAttribute("href", href)
expect(rule.update(a, { href: "http://good.com" })).toBe(a)
})
})

describe("rootNode", () => {
test("returns the parentNode of an element", () => {
expect(rule.rootNode(a).tagName).toBe("BODY")
})
})

describe("message", () => {
test("returns the proper message", () => {
expect(rule.message()).toMatchSnapshot()
})
})

describe("why", () => {
test("returns the proper why message", () => {
expect(rule.why()).toMatchSnapshot()
})
})
4 changes: 3 additions & 1 deletion src/rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import headingsSequence from "./headings-sequence"
import imageAltLength from "./img-alt-length"
import paragraphsForHeadings from "./paragraphs-for-headings"
import listStructure from "./list-structure"
import validLinks from "./valid-links"

export default [
imgAlt,
Expand All @@ -23,5 +24,6 @@ export default [
headingsSequence,
imageAltLength,
paragraphsForHeadings,
listStructure
listStructure,
validLinks
]
61 changes: 61 additions & 0 deletions src/rules/valid-links.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import formatMessage from "../format-message"

const isValidURL =
typeof URL !== "function"
? url => {
try {
// the URL constructor is more accurate than regex
// but not supported in IE and some versions of jsdom.
new URL(url)
return true
} catch (_) {
return false
}
}
: url =>
/((http|ftp|https|mailto):\/\/)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.test(
url
)

export default {
test: function(elem) {
if (elem.tagName !== "A") return true
return isValidURL(elem.getAttribute("href"))
},

data: elem => {
return {
href: elem.getAttribute("href")
}
},

form: () => [
{
label: formatMessage("Change the URL for this link"),
dataKey: "href"
}
],

update: function(elem, data) {
const rootElem = elem.parentNode

if (data.href !== elem.getAttribute("href")) {
elem.setAttribute("href", data.href)
}

return elem
},

rootNode: function(elem) {
return elem.parentNode
},

message: () => formatMessage("Links should be valid."),

why: () =>
formatMessage(
"Invalid links become broken links which are confusing to all users."
),

link: "https://www.w3.org/TR/2016/NOTE-WCAG20-TECHS-20161007/H48"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this link isn't linking to the proper content.

}