feat: run vitest on non-component files (#35)

### Explanation

This gives us coverage for all of our non-rendering logic, so we can use Playwright E2E testing for the actual components.

### Issue

_No response_

### Attestations

- [x] I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)
- [x] I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/).
- [x] My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/).

### Dependencies

- [x] I have pinned the dependencies to a specific patch version.

### Style

- [x] I have run the linter and resolved any errors.
- [x] My pull request uses an appropriate title, matching the conventional commit standards.
- [x] My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request.

### Tests

- [x] My contribution adds new code, and I have added tests to cover it.
- [x] My contribution modifies existing code, and I have updated the tests to reflect these changes.
- [x] All new and existing tests pass locally with my changes.
- [x] Code coverage remains at or above the configured threshold.

### Documentation

_No response_

### Versioning

Major - My pull request introduces a breaking change.

Reviewed-on: https://codeberg.org/nhcarrigan/portfolio/pulls/35
Co-authored-by: Naomi Carrigan <commits@nhcarrigan.com>
Co-committed-by: Naomi Carrigan <commits@nhcarrigan.com>
This commit is contained in:
Naomi Carrigan 2024-10-31 01:54:12 +00:00 committed by Naomi the Technomancer
parent fe370dabb5
commit c43635fa44
42 changed files with 3045 additions and 36 deletions

3
.gitignore vendored
View File

@ -34,3 +34,6 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
# coverage
.coverage

View File

@ -24,5 +24,11 @@ export default [
rules: { rules: {
"@typescript-eslint/consistent-type-assertions": "off" "@typescript-eslint/consistent-type-assertions": "off"
} }
},
{
files: ["test/**/*.spec.ts"],
rules: {
"max-nested-callbacks": "off"
}
} }
] ]

View File

@ -7,7 +7,8 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "eslint src --max-warnings 0" "lint": "eslint src test --max-warnings 0",
"test": "vitest run --coverage"
}, },
"dependencies": { "dependencies": {
"@fortawesome/fontawesome-svg-core": "6.6.0", "@fortawesome/fontawesome-svg-core": "6.6.0",
@ -25,9 +26,12 @@
"@types/node": "22.8.4", "@types/node": "22.8.4",
"@types/react": "18.3.12", "@types/react": "18.3.12",
"@types/react-dom": "18.3.1", "@types/react-dom": "18.3.1",
"@vitest/coverage-istanbul": "2.1.4",
"eslint": "9.13.0", "eslint": "9.13.0",
"jsdom": "25.0.1",
"postcss": "8.4.47", "postcss": "8.4.47",
"tailwindcss": "3.4.14", "tailwindcss": "3.4.14",
"typescript": "5.6.3" "typescript": "5.6.3",
"vitest": "2.1.4"
} }
} }

823
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -57,7 +57,8 @@ const About = (): JSX.Element => {
satisfaction, with an emphasis on making resources accessible to satisfaction, with an emphasis on making resources accessible to
newcomers in the field.`} newcomers in the field.`}
</li> </li>
<li className="mb-2"> <li className="mb-2 relative before:content-['🩵']
before:absolute before:left-[-1em]">
<strong>{`Mentorship and Advocacy:`}</strong> <strong>{`Mentorship and Advocacy:`}</strong>
{` Implemented programs to {` Implemented programs to
support aspiring developers, particularly those from support aspiring developers, particularly those from

View File

@ -118,7 +118,7 @@ Additionally, I guided and mentored other developers in the design and coding of
</li> </li>
</ul> </ul>
</div>`, </div>`,
end: new Date("June 4 2024"), end: new Date("June 5 2024"),
link: "https://deepgram.com", link: "https://deepgram.com",
logo: "deepgram.jpeg", logo: "deepgram.jpeg",
start: new Date("July 5 2023"), start: new Date("July 5 2023"),

View File

@ -20,7 +20,6 @@ export const NavItems = [
{ href: "/polycule", text: "Polycule" }, { href: "/polycule", text: "Polycule" },
{ href: "/activity", text: "Activity" }, { href: "/activity", text: "Activity" },
{ href: "/art", text: "Art" }, { href: "/art", text: "Art" },
{ href: "https://nhcarrigan.creator-spring.com/", text: "Merch" },
{ href: "/manifesto", text: "Transfemme Manifesto" }, { href: "/manifesto", text: "Transfemme Manifesto" },
].sort((a, b) => { ].sort((a, b) => {
return a.text.localeCompare(b.text); return a.text.localeCompare(b.text);

View File

@ -42,12 +42,11 @@ import {
faComputer, faComputer,
faEnvelope, faEnvelope,
faGamepad, faGamepad,
faGift,
faHashtag, faHashtag,
faMoneyBill, faMoneyBill,
faUniversity,
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { Codeberg } from "../icons/Codeberg"; import { Codeberg } from "../icons/Codeberg";
import { Coursera } from "../icons/Coursera";
import { Fiverr } from "../icons/Fiverr"; import { Fiverr } from "../icons/Fiverr";
import { Gather } from "../icons/Gather"; import { Gather } from "../icons/Gather";
import { Gog } from "../icons/Gog"; import { Gog } from "../icons/Gog";
@ -58,7 +57,9 @@ import { Pixiv } from "../icons/Pixiv";
import { Polywork } from "../icons/Polywork"; import { Polywork } from "../icons/Polywork";
import { Saylor } from "../icons/Saylor"; import { Saylor } from "../icons/Saylor";
import { TeeSpring } from "../icons/TeeSpring"; import { TeeSpring } from "../icons/TeeSpring";
import { Throne } from "../icons/Throne";
import { TreeNation } from "../icons/TreeNation"; import { TreeNation } from "../icons/TreeNation";
import { Udemy } from "../icons/Udemy";
import { VRoid } from "../icons/VRoid"; import { VRoid } from "../icons/VRoid";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
@ -85,7 +86,7 @@ const HireMe: {
color: "#003600", color: "#003600",
icon: faBriefcase, icon: faBriefcase,
label: "Hire Us!", label: "Hire Us!",
link: "https://docs.nhcarrigan.com/#/hire", link: "https://docs.nhcarrigan.com/about/hire/",
}; };
/** /**
@ -117,7 +118,7 @@ const Donate: {
color: "#003600", color: "#003600",
icon: faMoneyBill, icon: faMoneyBill,
label: "Donate 💜", label: "Donate 💜",
link: "https://docs.nhcarrigan.com/#/donate", link: "https://docs.nhcarrigan.com/about/donate/",
}; };
/** /**
@ -164,7 +165,7 @@ const Socials: Array<{
link: "https://matrix.to/#/#naomi:matrix.org", link: "https://matrix.to/#/#naomi:matrix.org",
}, },
{ {
alt: "Hash symbol", alt: "Octothorpe",
background: "#000", background: "#000",
color: "#FFF", color: "#FFF",
icon: faHashtag, icon: faHashtag,
@ -380,18 +381,18 @@ const Socials: Array<{
link: "https://docs.nhcarrigan.com/about/contact/#7-email-communication", link: "https://docs.nhcarrigan.com/about/contact/#7-email-communication",
}, },
{ {
alt: "University Icon", alt: "Coursera Logo",
background: "#0056D2", background: "#0056D2",
color: "#FFF", color: "#FFF",
icon: faUniversity, icon: Coursera,
label: "Coursera", label: "Coursera",
link: "https://www.coursera.org/learner/naomi-lgbt", link: "https://www.coursera.org/learner/naomi-lgbt",
}, },
{ {
alt: "University Icon", alt: "Udemy Logo",
background: "#EC5252", background: "#EC5252",
color: "#FFF", color: "#FFF",
icon: faUniversity, icon: Udemy,
label: "Udemy", label: "Udemy",
link: "https://www.udemy.com/user/naomi-carrigan/", link: "https://www.udemy.com/user/naomi-carrigan/",
}, },
@ -412,10 +413,10 @@ const Socials: Array<{
link: "https://pcpartpicker.com/user/nhcarrigan/", link: "https://pcpartpicker.com/user/nhcarrigan/",
}, },
{ {
alt: "Gift Icon", alt: "Throne.me Logo",
background: "#000", background: "#000",
color: "#FFF", color: "#FFF",
icon: faGift, icon: Throne,
label: "Throne", label: "Throne",
link: "https://throne.com/naomilgbt", link: "https://throne.com/naomilgbt",
}, },

126
src/icons/Coursera.ts Normal file
View File

@ -0,0 +1,126 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Coursera logo.
*/
export const Coursera: IconDefinition = {
icon: [
825,
825,
[],
"U+E002",
`M 397.00,0.23
C 397.00,0.23 421.00,0.23 421.00,0.23
421.00,0.23 436.00,1.92 436.00,1.92
436.00,1.92 445.00,1.92 445.00,1.92
464.83,2.24 500.36,9.70 520.00,14.91
564.71,26.78 604.32,45.18 642.72,70.91
642.72,70.91 666.54,87.59 666.54,87.59
679.69,97.87 691.91,109.49 703.71,121.29
750.05,167.63 785.48,224.18 804.76,287.00
804.76,287.00 816.55,331.00 816.55,331.00
816.55,331.00 818.37,344.00 818.37,344.00
820.23,353.40 822.89,368.59 823.09,378.00
823.09,378.00 823.09,390.00 823.09,390.00
823.81,395.27 824.91,394.72 825.00,402.00
825.00,402.00 825.00,419.00 825.00,419.00
824.99,427.76 823.88,428.69 823.08,436.00
823.08,436.00 823.08,446.00 823.08,446.00
822.88,455.97 820.17,471.99 818.31,482.00
818.31,482.00 816.76,493.00 816.76,493.00
813.29,511.46 806.77,533.13 800.72,551.00
800.72,551.00 789.17,579.17 789.17,579.17
743.04,685.52 649.01,770.68 538.00,804.76
514.40,812.01 493.53,817.23 469.00,820.29
469.00,820.29 445.00,823.09 445.00,823.09
445.00,823.09 435.00,823.09 435.00,823.09
427.99,823.92 429.93,824.98 420.00,825.00
420.00,825.00 405.00,825.00 405.00,825.00
405.00,825.00 389.00,823.08 389.00,823.08
389.00,823.08 379.00,823.08 379.00,823.08
368.84,822.88 353.18,820.20 343.00,818.31
343.00,818.31 332.00,816.76 332.00,816.76
308.66,812.37 277.98,802.81 256.00,793.71
211.64,775.33 173.47,751.31 137.46,719.58
137.46,719.58 121.29,703.71 121.29,703.71
74.93,657.35 39.53,600.84 20.24,538.00
20.24,538.00 8.24,493.00 8.24,493.00
8.24,493.00 6.81,482.00 6.81,482.00
6.81,482.00 5.21,475.00 5.21,475.00
3.59,463.77 2.02,452.36 2.00,441.00
2.00,441.00 0.00,421.00 0.00,421.00
0.00,421.00 0.00,405.00 0.00,405.00
0.00,405.00 1.92,389.00 1.92,389.00
1.92,389.00 1.92,380.00 1.92,380.00
2.15,367.31 4.82,354.46 6.86,342.00
12.62,306.62 23.37,271.55 38.55,239.00
85.92,137.42 175.10,56.39 282.00,21.68
301.73,15.28 321.55,10.19 342.00,6.86
342.00,6.86 350.00,5.18 350.00,5.18
350.00,5.18 378.00,2.00 378.00,2.00
387.62,1.89 387.16,2.56 397.00,0.23 Z
M 654.00,274.00
C 652.59,267.31 647.58,262.01 643.51,256.72
635.54,246.34 626.80,236.89 617.43,227.75
582.03,193.25 534.25,169.22 486.00,159.22
486.00,159.22 475.00,157.75 475.00,157.75
475.00,157.75 469.00,156.26 469.00,156.26
469.00,156.26 443.00,154.00 443.00,154.00
443.00,154.00 419.00,154.00 419.00,154.00
419.00,154.00 393.00,156.26 393.00,156.26
393.00,156.26 387.00,157.75 387.00,157.75
387.00,157.75 376.00,159.22 376.00,159.22
359.46,162.64 337.52,169.42 322.09,176.22
310.29,181.41 299.65,187.64 288.72,194.38
230.27,230.42 189.21,287.07 173.67,354.00
173.67,354.00 169.00,376.00 169.00,376.00
169.00,376.00 169.00,384.00 169.00,384.00
168.19,389.27 167.09,388.72 167.00,396.00
167.00,396.00 167.00,427.00 167.00,427.00
167.02,437.40 168.03,434.44 169.06,441.00
169.06,441.00 169.06,450.00 169.06,450.00
171.22,463.47 175.55,480.94 179.94,493.83
208.58,578.07 278.08,641.10 364.00,663.24
375.88,666.30 405.06,670.98 417.00,671.00
417.00,671.00 445.00,671.00 445.00,671.00
445.00,671.00 469.00,668.63 469.00,668.63
469.00,668.63 475.00,667.19 475.00,667.19
475.00,667.19 486.00,665.76 486.00,665.76
486.00,665.76 503.00,661.27 503.00,661.27
547.18,648.72 587.85,626.54 620.12,593.45
631.39,581.89 638.18,574.40 647.68,561.15
651.38,556.00 655.09,552.51 656.00,546.00
656.00,546.00 622.00,526.15 622.00,526.15
622.00,526.15 574.08,498.06 574.08,498.06
574.08,498.06 546.00,482.00 546.00,482.00
534.75,499.99 523.33,511.09 506.00,523.14
494.21,531.34 480.79,536.77 467.09,540.79
458.67,543.26 443.67,545.99 435.00,546.00
424.27,546.02 411.46,544.96 401.00,542.55
357.16,532.46 320.34,499.15 303.73,457.72
300.20,448.91 295.05,428.27 295.00,419.00
295.00,419.00 295.00,405.00 295.00,405.00
295.08,398.63 295.76,399.32 296.68,394.00
298.79,381.82 299.55,375.89 304.46,364.00
311.29,347.50 322.76,330.34 335.46,317.80
352.35,301.13 374.31,288.72 397.17,282.45
397.17,282.45 406.00,280.91 406.00,280.91
413.70,279.46 411.09,279.01 420.00,279.00
420.00,279.00 442.00,279.00 442.00,279.00
461.77,279.03 484.13,288.32 501.09,297.97
508.30,302.07 525.10,315.12 530.25,321.17
532.57,323.88 541.23,335.82 544.15,336.27
546.02,336.55 550.51,333.55 552.25,332.55
552.25,332.55 574.00,319.99 574.00,319.99
574.00,319.99 631.99,286.46 631.99,286.46
631.99,286.46 654.00,274.00 654.00,274.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

93
src/icons/Throne.ts Normal file
View File

@ -0,0 +1,93 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Throne.me logo.
*/
export const Throne: IconDefinition = {
icon: [
738,
621,
[],
"U+E002",
`M 364.00,0.65
C 380.58,-2.77 384.82,13.12 390.75,25.00
390.75,25.00 436.25,114.00 436.25,114.00
436.25,114.00 501.25,242.00 501.25,242.00
509.55,258.59 526.58,284.93 526.99,303.00
527.58,329.12 511.89,341.11 495.00,358.00
495.00,358.00 471.96,382.00 471.96,382.00
471.96,382.00 440.00,414.00 440.00,414.00
440.00,414.00 418.96,436.00 418.96,436.00
418.96,436.00 390.00,465.00 390.00,465.00
383.82,471.18 376.58,481.87 367.00,480.80
359.95,480.01 351.03,469.03 346.00,464.00
346.00,464.00 300.00,417.00 300.00,417.00
300.00,417.00 239.00,355.00 239.00,355.00
224.23,340.23 209.04,325.70 210.51,303.00
210.78,298.85 211.58,292.96 212.77,289.00
212.77,289.00 235.75,242.00 235.75,242.00
235.75,242.00 298.75,119.00 298.75,119.00
298.75,119.00 320.74,76.00 320.74,76.00
320.74,76.00 343.69,31.00 343.69,31.00
346.88,25.11 354.43,7.97 358.21,4.21
360.24,2.20 361.48,1.71 364.00,0.65 Z
M 11.00,204.59
C 13.62,204.13 15.36,203.84 18.00,204.59
23.76,206.43 34.33,218.33 39.00,223.00
39.00,223.00 102.00,287.00 102.00,287.00
102.00,287.00 131.96,317.00 131.96,317.00
131.96,317.00 141.01,327.00 141.01,327.00
141.01,327.00 176.96,363.00 176.96,363.00
176.96,363.00 186.01,373.00 186.01,373.00
186.01,373.00 235.96,423.00 235.96,423.00
235.96,423.00 316.00,505.00 316.00,505.00
316.00,505.00 361.00,551.00 361.00,551.00
366.28,556.28 376.33,564.19 376.52,572.00
376.65,577.57 372.41,583.22 367.00,584.58
367.00,584.58 360.00,585.17 360.00,585.17
360.00,585.17 345.00,586.00 345.00,586.00
345.00,586.00 334.00,586.96 334.00,586.96
299.43,588.47 264.60,593.98 231.00,602.37
212.72,606.95 183.56,617.64 167.00,618.82
163.80,619.04 161.15,618.37 158.00,618.07
135.75,616.01 118.33,604.57 107.44,585.00
102.99,577.01 98.68,561.24 96.15,552.00
96.15,552.00 64.42,443.00 64.42,443.00
64.42,443.00 26.02,311.00 26.02,311.00
26.02,311.00 3.42,233.00 3.42,233.00
0.08,221.29 -4.79,209.26 11.00,204.59 Z
M 720.00,204.61
C 730.62,202.68 739.38,209.98 737.53,221.00
737.53,221.00 729.71,249.00 729.71,249.00
729.71,249.00 714.58,301.00 714.58,301.00
714.58,301.00 678.42,425.00 678.42,425.00
678.42,425.00 646.72,534.00 646.72,534.00
638.26,562.21 633.90,594.97 606.00,611.13
601.21,613.90 595.29,616.69 590.00,618.28
569.52,624.42 556.97,616.60 538.00,611.14
538.00,611.14 500.00,600.87 500.00,600.87
491.51,598.75 482.71,597.52 475.00,593.12
465.90,587.93 450.35,570.35 442.00,562.00
442.00,562.00 416.72,536.00 416.72,536.00
412.08,530.66 408.35,526.63 410.43,519.00
411.45,515.25 414.38,512.76 416.92,510.00
416.92,510.00 432.00,494.00 432.00,494.00
432.00,494.00 465.96,460.01 465.96,460.01
465.96,460.01 483.00,442.00 483.00,442.00
483.00,442.00 509.96,415.00 509.96,415.00
509.96,415.00 519.01,405.00 519.01,405.00
519.01,405.00 552.96,371.01 552.96,371.01
552.96,371.01 651.00,271.00 651.00,271.00
651.00,271.00 665.04,256.00 665.04,256.00
665.04,256.00 696.00,225.00 696.00,225.00
702.65,218.35 711.22,207.67 720.00,204.61 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

155
src/icons/Udemy.ts Normal file
View File

@ -0,0 +1,155 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
/**
* Custom FontAwesome icon definition for the
* Udemy logo.
*/
export const Udemy: IconDefinition = {
icon: [
2118,
2118,
[],
"U+E002",
`M 1027.00,0.21
C 1027.00,0.21 1083.00,0.21 1083.00,0.21
1083.00,0.21 1098.00,1.00 1098.00,1.00
1098.00,1.00 1148.00,3.83 1148.00,3.83
1148.00,3.83 1185.00,7.28 1185.00,7.28
1242.11,14.33 1297.67,25.39 1353.00,41.29
1516.40,88.26 1668.12,175.50 1791.00,293.04
1933.98,429.80 2037.87,606.97 2085.87,799.00
2098.98,851.43 2107.96,904.25 2113.17,958.00
2113.17,958.00 2116.00,989.00 2116.00,989.00
2116.00,989.00 2116.00,998.00 2116.00,998.00
2116.00,998.00 2117.04,1008.00 2117.04,1008.00
2117.04,1008.00 2117.04,1023.00 2117.04,1023.00
2117.04,1023.00 2118.00,1035.00 2118.00,1035.00
2118.00,1035.00 2118.00,1083.00 2118.00,1083.00
2118.00,1083.00 2117.00,1100.00 2117.00,1100.00
2117.00,1100.00 2114.17,1148.00 2114.17,1148.00
2114.17,1148.00 2110.72,1185.00 2110.72,1185.00
2102.72,1249.75 2089.35,1313.67 2069.98,1376.00
2017.27,1545.58 1919.24,1702.31 1791.00,1824.96
1682.55,1928.69 1552.28,2008.03 1411.00,2058.31
1330.08,2087.10 1245.37,2104.90 1160.00,2113.17
1160.00,2113.17 1100.00,2117.00 1100.00,2117.00
1100.00,2117.00 1083.00,2118.00 1083.00,2118.00
1083.00,2118.00 1035.00,2118.00 1035.00,2118.00
1035.00,2118.00 1023.00,2117.04 1023.00,2117.04
1023.00,2117.04 1008.00,2117.04 1008.00,2117.04
1008.00,2117.04 982.00,2115.09 982.00,2115.09
982.00,2115.09 915.00,2108.28 915.00,2108.28
844.59,2099.01 767.69,2080.44 701.00,2056.05
586.65,2014.23 483.34,1956.90 389.00,1879.58
306.50,1811.96 237.26,1735.42 177.67,1647.00
84.91,1509.36 27.58,1349.41 7.28,1185.00
4.48,1162.30 1.03,1122.44 1.00,1100.00
1.00,1100.00 0.00,1083.00 0.00,1083.00
0.00,1083.00 0.00,1035.00 0.00,1035.00
0.00,1035.00 0.96,1023.00 0.96,1023.00
0.96,1023.00 0.96,1008.00 0.96,1008.00
0.96,1008.00 2.91,982.00 2.91,982.00
4.78,954.82 7.75,927.99 11.73,901.00
26.84,798.40 56.07,704.16 99.31,610.00
99.31,610.00 112.75,583.00 112.75,583.00
133.71,541.08 157.37,500.60 183.98,462.00
216.84,414.31 252.99,368.87 293.04,327.00
415.66,198.79 572.46,100.72 742.00,48.02
801.74,29.46 871.80,13.82 934.00,7.16
934.00,7.16 989.00,2.00 989.00,2.00
989.00,2.00 998.00,2.00 998.00,2.00
998.00,2.00 1009.00,1.00 1009.00,1.00
1015.02,0.97 1021.03,1.27 1027.00,0.21 Z
M 1518.00,690.00
C 1518.00,690.00 1518.00,426.00 1518.00,426.00
1518.00,423.77 1518.24,420.43 1517.01,418.53
1515.72,416.54 1512.07,414.78 1510.00,413.58
1510.00,413.58 1494.00,404.15 1494.00,404.15
1494.00,404.15 1419.00,359.80 1419.00,359.80
1419.00,359.80 1152.00,202.20 1152.00,202.20
1152.00,202.20 1083.00,161.58 1083.00,161.58
1083.00,161.58 1066.00,151.58 1066.00,151.58
1063.11,149.94 1060.49,148.08 1057.00,148.74
1054.06,149.29 1047.80,153.32 1045.00,155.00
1045.00,155.00 1024.00,167.40 1024.00,167.40
1024.00,167.40 952.00,209.99 952.00,209.99
952.00,209.99 789.00,306.01 789.00,306.01
789.00,306.01 704.00,356.28 704.00,356.28
704.00,356.28 624.00,403.42 624.00,403.42
624.00,403.42 608.00,412.99 608.00,412.99
605.78,414.29 601.33,416.46 599.99,418.53
598.76,420.43 599.00,423.77 599.00,426.00
599.00,426.00 599.00,689.00 599.00,689.00
599.00,689.00 638.00,667.20 638.00,667.20
638.00,667.20 710.00,624.60 710.00,624.60
710.00,624.60 940.00,488.99 940.00,488.99
940.00,488.99 1024.00,439.40 1024.00,439.40
1024.00,439.40 1048.00,425.15 1048.00,425.15
1048.00,425.15 1058.00,420.19 1058.00,420.19
1058.00,420.19 1068.00,424.72 1068.00,424.72
1068.00,424.72 1092.00,438.99 1092.00,438.99
1092.00,438.99 1183.00,492.60 1183.00,492.60
1183.00,492.60 1399.00,620.01 1399.00,620.01
1399.00,620.01 1481.00,668.42 1481.00,668.42
1481.00,668.42 1518.00,690.00 1518.00,690.00 Z
M 839.73,918.00
C 839.73,918.00 599.00,918.00 599.00,918.00
599.00,918.00 599.00,1443.00 599.00,1443.00
599.00,1443.00 599.00,1516.00 599.00,1516.00
599.00,1516.00 599.00,1560.00 599.00,1560.00
599.00,1560.00 603.45,1613.28 603.45,1613.28
614.91,1704.32 653.23,1790.62 722.00,1852.83
783.61,1908.57 850.45,1939.88 931.00,1957.58
951.57,1962.09 982.42,1966.56 1003.32,1967.81
1003.32,1967.81 1027.00,1969.00 1027.00,1969.00
1030.87,1969.05 1037.63,1969.15 1041.00,1971.00
1041.00,1971.00 1042.00,1969.00 1042.00,1969.00
1042.00,1969.00 1043.00,1971.00 1043.00,1971.00
1043.00,1971.00 1045.00,1969.00 1045.00,1969.00
1048.05,1971.81 1060.56,1971.10 1064.00,1969.00
1066.02,1970.69 1067.61,1969.70 1070.00,1969.00
1070.00,1969.00 1070.00,1971.00 1070.00,1971.00
1070.00,1971.00 1071.00,1971.00 1071.00,1971.00
1071.00,1971.00 1072.00,1969.00 1072.00,1969.00
1072.00,1969.00 1072.00,1971.00 1072.00,1971.00
1072.00,1971.00 1073.00,1971.00 1073.00,1971.00
1075.36,1968.47 1082.62,1969.01 1086.00,1969.00
1086.00,1969.00 1108.49,1967.78 1108.49,1967.78
1140.13,1965.79 1171.15,1959.99 1202.00,1952.99
1202.00,1952.99 1237.00,1942.67 1237.00,1942.67
1300.26,1921.58 1359.29,1886.83 1406.87,1839.86
1468.86,1778.64 1503.51,1693.23 1513.68,1607.58
1520.04,1554.02 1518.00,1499.86 1518.00,1446.00
1518.00,1446.00 1518.00,918.00 1518.00,918.00
1518.00,918.00 1277.21,918.00 1277.21,918.00
1277.21,918.00 1277.21,965.89 1277.21,965.89
1277.21,965.89 1277.21,1030.98 1277.21,1030.98
1277.21,1030.98 1277.21,1173.03 1277.21,1173.03
1277.21,1173.03 1277.21,1493.03 1277.21,1493.03
1277.21,1493.03 1277.21,1523.00 1277.21,1523.00
1276.78,1553.58 1270.07,1585.69 1258.55,1614.00
1225.82,1694.41 1146.00,1745.09 1060.00,1746.00
994.18,1746.69 928.60,1716.51 887.45,1665.00
876.49,1651.28 867.61,1635.94 860.31,1620.00
845.13,1586.86 839.80,1549.82 839.73,1513.67
839.73,1513.67 839.73,1116.33 839.73,1116.33
839.73,1116.33 839.73,984.33 839.73,984.33
839.73,984.33 839.73,941.67 839.73,941.67
839.73,941.67 839.73,918.00 839.73,918.00 Z
M 1048.00,1970.00
C 1048.00,1970.00 1047.00,1970.00 1047.00,1970.00
1047.00,1970.00 1048.00,1971.00 1048.00,1971.00
1048.00,1971.00 1048.00,1970.00 1048.00,1970.00 Z
M 1068.00,1970.00
C 1068.00,1970.00 1067.00,1970.00 1067.00,1970.00
1067.00,1970.00 1068.00,1971.00 1068.00,1971.00
1068.00,1971.00 1068.00,1970.00 1068.00,1970.00 Z`,
],
iconName: "yyy",
prefix: "xxx",
} as never;

View File

@ -0,0 +1,100 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable new-cap */
import { NextResponse } from "next/server";
import { describe, it, expect, vi } from "vitest";
import { GET } from "../../../../src/app/api/activity/route";
import { getCodebergData } from "../../../../src/lib/codeberg";
import { getGithubData } from "../../../../src/lib/github";
vi.mock("../../../../src/lib/codeberg");
vi.mock("../../../../src/lib/github");
describe("gET /api/activity", () => {
it("should return a sorted and limited list of activities", async() => {
expect.assertions(2);
const mockCodebergData = [
{
created: "2023-01-01T00:00:00Z",
op_type: "push",
repo: { full_name: "repo1", html_url: "https://codeberg.org/repo1" },
},
];
const mockGithubData = [
{
created_at: "2023-01-02T00:00:00Z",
repo: {
name: "repo2",
url: "https://api.github.com/repos/repo2",
},
type: "pull_request",
},
];
vi.mocked(getCodebergData).mockResolvedValue(mockCodebergData);
vi.mocked(getGithubData).mockResolvedValue(mockGithubData);
const response = await GET();
const json = await response.json();
expect(response, "did not respond with Next").toBeInstanceOf(NextResponse);
expect(json, "incorrect payload").toStrictEqual([
{
date: "2023-01-02T00:00:00.000Z",
repo: "https://github.com/repo2",
repoName: "repo2",
type: "pull_request",
},
{
date: "2023-01-01T00:00:00.000Z",
repo: "https://codeberg.org/repo1",
repoName: "repo1",
type: "push",
},
]);
});
it("should handle empty data from both sources", async() => {
expect.assertions(2);
vi.mocked(getCodebergData).mockResolvedValue([]);
vi.mocked(getGithubData).mockResolvedValue([]);
const response = await GET();
const json = await response.json();
expect(response, "did not use Next to respond").
toBeInstanceOf(NextResponse);
expect(json, "was not empty array").toStrictEqual([]);
});
it("should limit the results to 100 entries", async() => {
expect.assertions(2);
const mockCodebergData = Array.from({ length: 60 }, (_, index) => {
return {
created: `2023-01-${index + 1}T00:00:00Z`,
op_type: "push",
repo: { full_name: `repo${index + 1}`, html_url: `https://codeberg.org/repo${index + 1}` },
};
});
const mockGithubData = Array.from({ length: 60 }, (_, index) => {
return {
created_at: `2023-02-${index + 1}T00:00:00Z`,
repo: { name: `repo${index + 61}`, url: `https://api.github.com/repos/repo${index + 61}` },
type: "pull_request",
};
});
vi.mocked(getCodebergData).mockResolvedValue(mockCodebergData);
vi.mocked(getGithubData).mockResolvedValue(mockGithubData);
const response = await GET();
const json = await response.json();
expect(response, "did not use Next to respond").
toBeInstanceOf(NextResponse);
expect(json, "did not limit to 100 entries").toHaveLength(100);
});
});

37
test/config/Art.spec.ts Normal file
View File

@ -0,0 +1,37 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Art } from "../../src/config/Art";
describe("art objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Art.map((a) => {
return a.name;
}),
);
expect(set, "are not unique").toHaveLength(Art.length);
});
it("should have unique img properties", () => {
expect.assertions(1);
const set = new Set(
Art.map((a) => {
return a.img;
}),
);
expect(set, "are not unique").toHaveLength(Art.length);
});
it("should have alt text", () => {
expect.assertions(1);
const noText = Art.filter((a) => {
return a.alt.length === 0;
});
expect(noText, "found missing alt").toHaveLength(0);
});
});

View File

@ -0,0 +1,29 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Certifications } from "../../src/config/Certifications";
describe("certification objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Certifications.map((c) => {
return c.name;
}),
);
expect(set, "are not unique").toHaveLength(Certifications.length);
});
it("should have unique file names", () => {
expect.assertions(1);
const set = new Set(
Certifications.map((c) => {
return c.fileName;
}),
);
expect(set, "are not unique").toHaveLength(Certifications.length);
});
});

47
test/config/Games.spec.ts Normal file
View File

@ -0,0 +1,47 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Games } from "../../src/config/Games";
describe("games objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.name;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have unique img properties", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.img;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have unique urls", () => {
expect.assertions(1);
const set = new Set(
Games.map((g) => {
return g.url;
}),
);
expect(set, "are not unique").toHaveLength(Games.length);
});
it("should have alt text", () => {
expect.assertions(1);
const noText = Games.filter((g) => {
return g.alt.length === 0;
});
expect(noText, "found missing alt").toHaveLength(0);
});
});

33
test/config/Jobs.spec.ts Normal file
View File

@ -0,0 +1,33 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Jobs } from "../../src/config/Jobs";
describe("jobs objects", () => {
it("should have correct start dates", () => {
expect.hasAssertions();
for (const job of Jobs.slice(1)) {
expect(job.start.getDate(), `${job.title} has bad start`).toBe(5);
}
});
it("should have correct end dates", () => {
expect.hasAssertions();
for (const job of Jobs.slice(1)) {
if (!job.end) {
continue;
}
expect(job.end.getDate(), `${job.title} has bad end`).toBe(5);
}
});
it("should have no future start dates", () => {
expect.hasAssertions();
expect(Jobs.filter((job) => {
return job.start > new Date();
}), "have future start dates").toHaveLength(0);
});
});

View File

@ -0,0 +1,30 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { NavItems } from "../../src/config/NavItems";
describe("nav items", () => {
it("should be unique", () => {
expect.assertions(2);
const href = new Set(
NavItems.map((n) => {
return n.href;
}),
);
const text = new Set(NavItems.map((n) => {
return n.text;
}));
expect(href, "links are not unique").toHaveLength(NavItems.length);
expect(text, "names are not unique").toHaveLength(NavItems.length);
});
it("should be internal links", () => {
expect.hasAssertions();
for (const nav of NavItems) {
expect(nav.href, `${nav.href} is not internal`).toMatch(/^\/[\da-z-]+$/);
}
});
});

View File

@ -0,0 +1,29 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Partners } from "../../src/config/Partners";
describe("partner objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Partners.map((p) => {
return p.name;
}),
);
expect(set, "are not unique").toHaveLength(Partners.length);
});
it("should have unique avatars", () => {
expect.assertions(1);
const set = new Set(
Partners.map((p) => {
return p.avatar;
}),
);
expect(set, "are not unique").toHaveLength(Partners.length);
});
});

109
test/config/Socials.spec.ts Normal file
View File

@ -0,0 +1,109 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { faBriefcase, faMoneyBill } from "@fortawesome/free-solid-svg-icons";
import { describe, it, expect } from "vitest";
import { HireMe, Donate, Socials } from "../../src/config/Socials";
describe("socials objects", () => {
it("should have unique labels", () => {
expect.assertions(1);
const set = new Set(
Socials.map((s) => {
return s.label;
}),
);
expect(set, "are not unique").toHaveLength(Socials.length);
});
it("should have unique links", () => {
expect.assertions(1);
const set = new Set(
Socials.map((s) => {
return s.link;
}),
);
expect(set, "are not unique").toHaveLength(Socials.length);
});
it("should have unique icons", () => {
expect.assertions(1);
const set = new Set(
Socials.map((s) => {
return s.icon;
}),
);
expect(set, "are not unique").toHaveLength(Socials.length);
});
});
describe("hire me object", () => {
it("should have correct label", () => {
expect.assertions(1);
expect(HireMe.label, "does not").toBe("Hire Us!");
});
it("should have correct link", () => {
expect.assertions(1);
expect(HireMe.link, "does not").
toBe("https://docs.nhcarrigan.com/about/hire/");
});
it("should have correct colours", () => {
expect.assertions(2);
expect(HireMe.color, "colour is wrong").toBe("#003600");
expect(HireMe.background, "background is wrong").toBe(`linear-gradient(
90deg,
#5bcefa,
#f5a9b8,
#ffffff,
#f5a9b8,
#5bcefa
)`);
});
it("should have correct icon", () => {
expect.assertions(1);
expect(HireMe.icon, "does not").toBe(faBriefcase);
});
});
describe("donate object", () => {
it("should have correct label", () => {
expect.assertions(1);
expect(Donate.label, "does not").toBe("Donate 💜");
});
it("should have correct link", () => {
expect.assertions(1);
expect(Donate.link, "does not").
toBe("https://docs.nhcarrigan.com/about/donate/");
});
it("should have correct colours", () => {
expect.assertions(2);
expect(Donate.color, "has wrong colour").toBe("#003600");
expect(Donate.background, "has wrong background").toBe(`linear-gradient(
90deg,
rgba(255, 0, 0, 1) 0%,
rgba(251, 7, 217, 1) 10%,
rgba(186, 12, 248, 1) 20%,
rgba(95, 21, 242, 1) 30%,
rgba(28, 127, 238, 1) 40%,
rgba(47, 201, 226, 1) 50%,
rgba(63, 218, 216, 1) 60%,
rgba(79, 220, 74, 1) 70%,
rgba(208, 222, 33, 1) 80%,
rgba(255, 154, 0, 1) 90%,
rgba(255, 0, 0, 1) 100%
)`);
});
it("should have correct icon", () => {
expect.assertions(1);
expect(Donate.icon, "does not").toBe(faMoneyBill);
});
});

View File

@ -0,0 +1,36 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { TeamMembers } from "../../src/config/TeamMembers";
describe("partner objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
TeamMembers.map((t) => {
return t.name;
}),
);
expect(set, "are not unique").toHaveLength(TeamMembers.length);
});
it("should have unique avatars", () => {
expect.assertions(1);
const set = new Set(
TeamMembers.map((t) => {
return t.avatar;
}),
);
expect(set, "are not unique").toHaveLength(TeamMembers.length);
});
it("should have no future dates", () => {
expect.assertions(1);
expect(TeamMembers.filter((t) => {
return new Date(t.joinDate) > new Date();
}), "have future dates").toHaveLength(0);
});
});

View File

@ -0,0 +1,26 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Testimonials } from "../../src/config/Testimonials";
describe("testimonial objects", () => {
it("should have unique names", () => {
expect.assertions(1);
const set = new Set(
Testimonials.map((t) => {
return t.name;
}),
);
expect(set, "are not unique").toHaveLength(Testimonials.length);
});
it("should have no future dates", () => {
expect.assertions(1);
expect(Testimonials.filter((t) => {
return new Date(t.date) > new Date();
}), "have future dates").toHaveLength(0);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Codeberg } from "../../src/icons/Codeberg";
describe("codeberg icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Codeberg.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Codeberg.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Codeberg.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Codeberg.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Codeberg.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Coursera } from "../../src/icons/Coursera";
describe("coursera icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Coursera.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Coursera.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Coursera.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Coursera.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Coursera.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Fiverr.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Fiverr } from "../../src/icons/Fiverr";
describe("fiverr icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Fiverr.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Fiverr.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Fiverr.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Fiverr.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Fiverr.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Gather.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Gather } from "../../src/icons/Gather";
describe("gather icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Gather.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Gather.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Gather.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Gather.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Gather.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Gog.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Gog } from "../../src/icons/Gog";
describe("gog icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Gog.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Gog.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Gog.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Gog.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Gog.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Kofi.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Kofi } from "../../src/icons/KoFi";
describe("kofi icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Kofi.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Kofi.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Kofi.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Kofi.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Kofi.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Matrix.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Matrix } from "../../src/icons/Matrix";
describe("matrix icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Matrix.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Matrix.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Matrix.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Matrix.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Matrix.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Peerlist } from "../../src/icons/Peerlist";
describe("peerlist icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Peerlist.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Peerlist.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Peerlist.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Peerlist.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Peerlist.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Pixiv.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Pixiv } from "../../src/icons/Pixiv";
describe("pixiv icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Pixiv.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Pixiv.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Pixiv.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Pixiv.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Pixiv.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Polywork } from "../../src/icons/Polywork";
describe("polywork icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Polywork.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Polywork.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Polywork.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Polywork.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Polywork.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Saylor.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Saylor } from "../../src/icons/Saylor";
describe("saylor icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Saylor.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Saylor.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Saylor.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Saylor.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Saylor.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { TeeSpring } from "../../src/icons/TeeSpring";
describe("teespring icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(TeeSpring.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(TeeSpring.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(TeeSpring.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(TeeSpring.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(TeeSpring.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Throne.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Throne } from "../../src/icons/Throne";
describe("throne icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Throne.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Throne.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Throne.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Throne.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Throne.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { TreeNation } from "../../src/icons/TreeNation";
describe("treenation icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(TreeNation.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(TreeNation.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(TreeNation.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(TreeNation.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(TreeNation.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/Udemy.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Udemy } from "../../src/icons/Udemy";
describe("udemy icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Udemy.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Udemy.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Udemy.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Udemy.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Udemy.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

38
test/icons/VRoid.spec.ts Normal file
View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { VRoid } from "../../src/icons/VRoid";
describe("vroid icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(VRoid.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(VRoid.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(VRoid.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(VRoid.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(VRoid.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

View File

@ -0,0 +1,38 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect } from "vitest";
import { Volunteer } from "../../src/icons/Volunteer";
describe("volunteer icon", () => {
it("should have a valid width", () => {
expect.assertions(1);
expect(Volunteer.icon[0], "width is negative").toBeGreaterThan(0);
});
it("should have a valid height", () => {
expect.assertions(1);
expect(Volunteer.icon[1], "height is negative").toBeGreaterThan(0);
});
it("should not have any ligatures", () => {
expect.assertions(1);
expect(Volunteer.icon[2], "ligatures are present").toStrictEqual([]);
});
it("should have a valid unicode set", () => {
expect.assertions(1);
expect(Volunteer.icon[3], "unicode set is wrong").toBe("U+E002");
});
it("should have valid SVG path data", () => {
expect.assertions(1);
expect(Volunteer.icon[4], "path data is bad").toMatch(
// eslint-disable-next-line stylistic/max-len
/(?:[lm]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:[hv]\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))|(?:c\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){5})|(?:q\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3}(?:\s?t?\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+)))*)|(?:a\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2}[\s,]?(?:[01][\s,]+){2}(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){2})|(?:s\s?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))(?:[\s,]?-?(?:(?:\d+(?:\.\d+)?)|(?:\.\d+))){3})|z/gi,
);
});
});

345
test/lib/codeberg.spec.ts Normal file
View File

@ -0,0 +1,345 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
import { getCodebergData } from "../../src/lib/codeberg";
describe("codeberg", () => {
beforeEach(() => {
vi.resetAllMocks();
});
it("should fetch and cache activities", async() => {
expect.assertions(1);
const mockResponse = [
{
act_user: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
act_user_id: 1,
comment: {
assets: [],
body: "A comment",
created_at: "2023-01-01T00:00:00Z",
html_url: "https://example.com/comment",
id: 1,
issue_url: "https://example.com/issue",
original_author: "naomi",
original_author_id: 1,
pull_request_url: "https://example.com/pr",
updated_at: "2023-01-01T00:00:00Z",
user: null,
},
comment_id: 1,
content: "Activity content",
created: "2023-01-01T00:00:00Z",
id: 1,
is_private: false,
op_type: "create",
ref_name: "main",
repo: {
allow_fast_forward_only_merge: false,
allow_merge_commits: true,
allow_rebase: true,
allow_rebase_explicit: true,
allow_rebase_update: true,
allow_squash_merge: true,
archived: false,
archived_at: "2023-01-01T00:00:00Z",
avatar_url: "https://example.com/avatar.png",
clone_url: "https://example.com/repo.git",
created_at: "2023-01-01T00:00:00Z",
default_allow_maintainer_edit: true,
default_branch: "main",
default_delete_branch_after_merge: true,
default_merge_style: "merge",
description: "A repository",
empty: false,
external_tracker: {
external_tracker_format: "format",
external_tracker_regexp_pattern: "pattern",
external_tracker_style: "style",
external_tracker_url: "https://example.com/tracker",
},
fork: false,
forks_count: 5,
full_name: "naomi/repo",
globally_editable_wiki: false,
has_actions: true,
has_issues: true,
has_packages: true,
has_projects: true,
has_pull_requests: true,
has_releases: true,
has_wiki: true,
html_url: "https://example.com/repo",
id: 1,
ignore_whitespace_conflicts: false,
internal: false,
language: "TypeScript",
languages_url: "https://example.com/languages",
link: "https://example.com/repo",
mirror: false,
mirror_interval: "24h",
mirror_updated: "2023-01-01T00:00:00Z",
name: "repo",
object_format_name: "format",
open_issues_count: 1,
open_pr_counter: 0,
original_url: "https://example.com/repo",
owner: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
parent: null,
permissions: {
admin: true,
pull: true,
push: true,
},
private: false,
release_counter: 0,
repo_transfer: null,
size: 100,
ssh_url: "git@example.com:repo.git",
stars_count: 10,
template: false,
topics: [],
updated_at: "2023-01-01T00:00:00Z",
url: "https://example.com/repo",
watchers_count: 3,
website: "https://example.com",
wiki_branch: "main",
},
repo_id: 1,
user_id: 1,
},
];
vi.spyOn(global, "fetch").mockResolvedValue({
json: () => {
return Promise.resolve(mockResponse);
},
});
const data = await getCodebergData();
expect(data, "did not have correct payload").
toStrictEqual(mockResponse);
});
it("should return cached data if not stale", async() => {
expect.assertions(3);
const mockResponse = [
{
act_user: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
act_user_id: 1,
comment: {
assets: [],
body: "A comment",
created_at: "2023-01-01T00:00:00Z",
html_url: "https://example.com/comment",
id: 1,
issue_url: "https://example.com/issue",
original_author: "naomi",
original_author_id: 1,
pull_request_url: "https://example.com/pr",
updated_at: "2023-01-01T00:00:00Z",
user: null,
},
comment_id: 1,
content: "Activity content",
created: "2023-01-01T00:00:00Z",
id: 1,
is_private: false,
op_type: "create",
ref_name: "main",
repo: {
allow_fast_forward_only_merge: false,
allow_merge_commits: true,
allow_rebase: true,
allow_rebase_explicit: true,
allow_rebase_update: true,
allow_squash_merge: true,
archived: false,
archived_at: "2023-01-01T00:00:00Z",
avatar_url: "https://example.com/avatar.png",
clone_url: "https://example.com/repo.git",
created_at: "2023-01-01T00:00:00Z",
default_allow_maintainer_edit: true,
default_branch: "main",
default_delete_branch_after_merge: true,
default_merge_style: "merge",
description: "A repository",
empty: false,
external_tracker: {
external_tracker_format: "format",
external_tracker_regexp_pattern: "pattern",
external_tracker_style: "style",
external_tracker_url: "https://example.com/tracker",
},
fork: false,
forks_count: 5,
full_name: "naomi/repo",
globally_editable_wiki: false,
has_actions: true,
has_issues: true,
has_packages: true,
has_projects: true,
has_pull_requests: true,
has_releases: true,
has_wiki: true,
html_url: "https://example.com/repo",
id: 1,
ignore_whitespace_conflicts: false,
internal: false,
language: "TypeScript",
languages_url: "https://example.com/languages",
link: "https://example.com/repo",
mirror: false,
mirror_interval: "24h",
mirror_updated: "2023-01-01T00:00:00Z",
name: "repo",
object_format_name: "format",
open_issues_count: 1,
open_pr_counter: 0,
original_url: "https://example.com/repo",
owner: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
parent: null,
permissions: {
admin: true,
pull: true,
push: true,
},
private: false,
release_counter: 0,
repo_transfer: null,
size: 100,
ssh_url: "git@example.com:repo.git",
stars_count: 10,
template: false,
topics: [],
updated_at: "2023-01-01T00:00:00Z",
url: "https://example.com/repo",
watchers_count: 3,
website: "https://example.com",
wiki_branch: "main",
},
repo_id: 1,
user_id: 1,
},
];
vi.spyOn(global, "fetch").mockResolvedValue({
json: () => {
return Promise.resolve(mockResponse);
},
});
const data = await getCodebergData();
expect(data, "did not have correct payload").
toStrictEqual(mockResponse);
// Call again to check if cached data is returned
const cachedData = await getCodebergData();
expect(cachedData, "did not cache correct payload").
toStrictEqual(mockResponse);
expect(global.fetch, "did not hit cache").not.toHaveBeenCalled();
});
});

343
test/lib/github.spec.ts Normal file
View File

@ -0,0 +1,343 @@
/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
import { getGithubData } from "../../src/lib/github";
describe("github", () => {
beforeEach(() => {
vi.resetAllMocks();
});
it("should fetch and cache activities", async() => {
expect.assertions(1);
const mockResponse = [
{
act_user: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
act_user_id: 1,
comment: {
assets: [],
body: "A comment",
created_at: "2023-01-01T00:00:00Z",
html_url: "https://example.com/comment",
id: 1,
issue_url: "https://example.com/issue",
original_author: "naomi",
original_author_id: 1,
pull_request_url: "https://example.com/pr",
updated_at: "2023-01-01T00:00:00Z",
user: null,
},
comment_id: 1,
content: "Activity content",
created: "2023-01-01T00:00:00Z",
id: 1,
is_private: false,
op_type: "create",
ref_name: "main",
repo: {
allow_fast_forward_only_merge: false,
allow_merge_commits: true,
allow_rebase: true,
allow_rebase_explicit: true,
allow_rebase_update: true,
allow_squash_merge: true,
archived: false,
archived_at: "2023-01-01T00:00:00Z",
avatar_url: "https://example.com/avatar.png",
clone_url: "https://example.com/repo.git",
created_at: "2023-01-01T00:00:00Z",
default_allow_maintainer_edit: true,
default_branch: "main",
default_delete_branch_after_merge: true,
default_merge_style: "merge",
description: "A repository",
empty: false,
external_tracker: {
external_tracker_format: "format",
external_tracker_regexp_pattern: "pattern",
external_tracker_style: "style",
external_tracker_url: "https://example.com/tracker",
},
fork: false,
forks_count: 5,
full_name: "naomi/repo",
globally_editable_wiki: false,
has_actions: true,
has_issues: true,
has_packages: true,
has_projects: true,
has_pull_requests: true,
has_releases: true,
has_wiki: true,
html_url: "https://example.com/repo",
id: 1,
ignore_whitespace_conflicts: false,
internal: false,
language: "TypeScript",
languages_url: "https://example.com/languages",
link: "https://example.com/repo",
mirror: false,
mirror_interval: "24h",
mirror_updated: "2023-01-01T00:00:00Z",
name: "repo",
object_format_name: "format",
open_issues_count: 1,
open_pr_counter: 0,
original_url: "https://example.com/repo",
owner: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
parent: null,
permissions: {
admin: true,
pull: true,
push: true,
},
private: false,
release_counter: 0,
repo_transfer: null,
size: 100,
ssh_url: "git@example.com:repo.git",
stars_count: 10,
template: false,
topics: [],
updated_at: "2023-01-01T00:00:00Z",
url: "https://example.com/repo",
watchers_count: 3,
website: "https://example.com",
wiki_branch: "main",
},
repo_id: 1,
user_id: 1,
},
];
vi.spyOn(global, "fetch").mockResolvedValue({
json: () => {
return Promise.resolve(mockResponse);
},
});
const data = await getGithubData();
expect(data, "did not have correct payload").toStrictEqual(mockResponse);
});
it("should return cached data if not stale", async() => {
expect.assertions(3);
const mockResponse = [
{
act_user: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
act_user_id: 1,
comment: {
assets: [],
body: "A comment",
created_at: "2023-01-01T00:00:00Z",
html_url: "https://example.com/comment",
id: 1,
issue_url: "https://example.com/issue",
original_author: "naomi",
original_author_id: 1,
pull_request_url: "https://example.com/pr",
updated_at: "2023-01-01T00:00:00Z",
user: null,
},
comment_id: 1,
content: "Activity content",
created: "2023-01-01T00:00:00Z",
id: 1,
is_private: false,
op_type: "create",
ref_name: "main",
repo: {
allow_fast_forward_only_merge: false,
allow_merge_commits: true,
allow_rebase: true,
allow_rebase_explicit: true,
allow_rebase_update: true,
allow_squash_merge: true,
archived: false,
archived_at: "2023-01-01T00:00:00Z",
avatar_url: "https://example.com/avatar.png",
clone_url: "https://example.com/repo.git",
created_at: "2023-01-01T00:00:00Z",
default_allow_maintainer_edit: true,
default_branch: "main",
default_delete_branch_after_merge: true,
default_merge_style: "merge",
description: "A repository",
empty: false,
external_tracker: {
external_tracker_format: "format",
external_tracker_regexp_pattern: "pattern",
external_tracker_style: "style",
external_tracker_url: "https://example.com/tracker",
},
fork: false,
forks_count: 5,
full_name: "naomi/repo",
globally_editable_wiki: false,
has_actions: true,
has_issues: true,
has_packages: true,
has_projects: true,
has_pull_requests: true,
has_releases: true,
has_wiki: true,
html_url: "https://example.com/repo",
id: 1,
ignore_whitespace_conflicts: false,
internal: false,
language: "TypeScript",
languages_url: "https://example.com/languages",
link: "https://example.com/repo",
mirror: false,
mirror_interval: "24h",
mirror_updated: "2023-01-01T00:00:00Z",
name: "repo",
object_format_name: "format",
open_issues_count: 1,
open_pr_counter: 0,
original_url: "https://example.com/repo",
owner: {
active: true,
avatar_url: "https://example.com/avatar.png",
created: "2023-01-01T00:00:00Z",
description: "Developer",
email: "naomi@example.com",
followers_count: 100,
following_count: 50,
full_name: "Naomi Carrigan",
html_url: "https://example.com",
id: 1,
is_admin: false,
language: "en",
last_login: "2023-01-01T00:00:00Z",
location: "Earth",
login: "naomi",
login_name: "naomi",
prohibit_login: false,
pronouns: "she/her",
restricted: false,
source_id: 1,
starred_repos_count: 10,
username: "naomi",
visibility: "public",
website: "https://example.com",
},
parent: null,
permissions: {
admin: true,
pull: true,
push: true,
},
private: false,
release_counter: 0,
repo_transfer: null,
size: 100,
ssh_url: "git@example.com:repo.git",
stars_count: 10,
template: false,
topics: [],
updated_at: "2023-01-01T00:00:00Z",
url: "https://example.com/repo",
watchers_count: 3,
website: "https://example.com",
wiki_branch: "main",
},
repo_id: 1,
user_id: 1,
},
];
vi.spyOn(global, "fetch").mockResolvedValue({
json: () => {
return Promise.resolve(mockResponse);
},
});
const data = await getGithubData();
expect(data, "did not have correct payload").toStrictEqual(mockResponse);
// Call again to check if cached data is returned
const cachedData = await getGithubData();
expect(cachedData, "did not cache correct payload").
toStrictEqual(mockResponse);
expect(global.fetch, "did not hit cache").not.toHaveBeenCalled();
});
});

View File

@ -18,11 +18,6 @@
"name": "next" "name": "next"
} }
], ],
"paths": {
"@/*": [
"./src/*"
]
},
"allowJs": true "allowJs": true
}, },
"include": [ "include": [
@ -32,6 +27,7 @@
".next/types/**/*.ts" ".next/types/**/*.ts"
], ],
"exclude": [ "exclude": [
"node_modules" "node_modules",
"vitest.config.ts"
] ]
} }

20
vitest.config.ts Normal file
View File

@ -0,0 +1,20 @@
import { coverageConfigDefaults, defineConfig } from "vitest/config";
export default defineConfig({
test: {
coverage: {
provider: "istanbul",
reporter: ["text", "html"],
all: true,
allowExternal: true,
thresholds: {
lines: 100,
statements: 100,
functions: 100,
branches: 100
},
extension: [".ts"],
exclude: [...coverageConfigDefaults.exclude, "tailwind.config.ts"]
}
}
});