« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/test/snapshot
diff options
context:
space:
mode:
Diffstat (limited to 'test/snapshot')
-rw-r--r--test/snapshot/generateAdditionalFilesList.js64
-rw-r--r--test/snapshot/generateAdditionalFilesShortcut.js36
-rw-r--r--test/snapshot/generateAlbumBanner.js34
-rw-r--r--test/snapshot/generateAlbumCoverArtwork.js35
-rw-r--r--test/snapshot/generateAlbumReleaseInfo.js74
-rw-r--r--test/snapshot/generateAlbumSecondaryNav.js55
-rw-r--r--test/snapshot/generateAlbumSidebarGroupBox.js55
-rw-r--r--test/snapshot/generateAlbumTrackList.js48
-rw-r--r--test/snapshot/generateBanner.js22
-rw-r--r--test/snapshot/generateCoverArtwork.js33
-rw-r--r--test/snapshot/generateTrackCoverArtwork.js63
-rw-r--r--test/snapshot/generateTrackReleaseInfo.js51
-rw-r--r--test/snapshot/image.js101
-rw-r--r--test/snapshot/linkArtist.js30
-rw-r--r--test/snapshot/linkContribution.js67
-rw-r--r--test/snapshot/linkExternal.js54
-rw-r--r--test/snapshot/linkExternalFlash.js24
-rw-r--r--test/snapshot/linkTemplate.js35
18 files changed, 881 insertions, 0 deletions
diff --git a/test/snapshot/generateAdditionalFilesList.js b/test/snapshot/generateAdditionalFilesList.js
new file mode 100644
index 00000000..60b46ae8
--- /dev/null
+++ b/test/snapshot/generateAdditionalFilesList.js
@@ -0,0 +1,64 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAdditionalFilesList (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('no additional files', {
+    name: 'generateAdditionalFilesList',
+    args: [[]],
+  });
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateAdditionalFilesList',
+    args: [
+      [
+        {
+          title: 'SBURB Wallpaper',
+          files: [
+            'sburbwp_1280x1024.jpg',
+            'sburbwp_1440x900.jpg',
+            'sburbwp_1920x1080.jpg',
+          ],
+        },
+        {
+          title: 'Fake Section',
+          description: 'Ooo, what happens if there are NO file links provided?',
+          files: [
+            'oops.mp3',
+            'Internet Explorer.gif',
+            'daisy.mp3',
+          ],
+        },
+        {
+          title: 'Alternate Covers',
+          description: 'This is just an example description.',
+          files: [
+            'Homestuck_Vol4_alt1.jpg',
+            'Homestuck_Vol4_alt2.jpg',
+            'Homestuck_Vol4_alt3.jpg',
+          ],
+        },
+      ],
+    ],
+    slots: {
+      fileLinks: {
+        'sburbwp_1280x1024.jpg': 'link to 1280x1024',
+        'sburbwp_1440x900.jpg': 'link to 1440x900',
+        'sburbwp_1920x1080.jpg': null,
+        'Homestuck_Vol4_alt1.jpg': 'link to alt1',
+        'Homestuck_Vol4_alt2.jpg': null,
+        'Homestuck_Vol4_alt3.jpg': 'link to alt3',
+      },
+      fileSizes: {
+        'sburbwp_1280x1024.jpg': 2500,
+        'sburbwp_1440x900.jpg': null,
+        'sburbwp_1920x1080.jpg': null,
+        'Internet Explorer.gif': 1,
+        'Homestuck_Vol4_alt1.jpg': 1234567,
+        'Homestuck_Vol4_alt2.jpg': 1234567,
+        'Homestuck_Vol4_alt3.jpg': 1234567,
+      }
+    },
+  });
+});
diff --git a/test/snapshot/generateAdditionalFilesShortcut.js b/test/snapshot/generateAdditionalFilesShortcut.js
new file mode 100644
index 00000000..0ca777b4
--- /dev/null
+++ b/test/snapshot/generateAdditionalFilesShortcut.js
@@ -0,0 +1,36 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAdditionalFilesShortcut (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('no additional files', {
+    name: 'generateAdditionalFilesShortcut',
+    args: [[]],
+  });
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateAdditionalFilesShortcut',
+    args: [
+      [
+        {
+          title: 'SBURB Wallpaper',
+          files: [
+            'sburbwp_1280x1024.jpg',
+            'sburbwp_1440x900.jpg',
+            'sburbwp_1920x1080.jpg',
+          ],
+        },
+        {
+          title: 'Alternate Covers',
+          description: 'This is just an example description.',
+          files: [
+            'Homestuck_Vol4_alt1.jpg',
+            'Homestuck_Vol4_alt2.jpg',
+            'Homestuck_Vol4_alt3.jpg',
+          ],
+        },
+      ],
+    ],
+  });
+});
diff --git a/test/snapshot/generateAlbumBanner.js b/test/snapshot/generateAlbumBanner.js
new file mode 100644
index 00000000..e2260cdd
--- /dev/null
+++ b/test/snapshot/generateAlbumBanner.js
@@ -0,0 +1,34 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumBanner (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateAlbumBanner',
+    args: [{
+      directory: 'cool-album',
+      hasBannerArt: true,
+      bannerDimensions: [800, 200],
+      bannerFileExtension: 'png',
+    }],
+  });
+
+  evaluate.snapshot('no dimensions', {
+    name: 'generateAlbumBanner',
+    args: [{
+      directory: 'cool-album',
+      hasBannerArt: true,
+      bannerDimensions: null,
+      bannerFileExtension: 'png',
+    }],
+  });
+
+  evaluate.snapshot('no banner', {
+    name: 'generateAlbumBanner',
+    args: [{
+      directory: 'cool-album',
+      hasBannerArt: false,
+    }],
+  });
+});
diff --git a/test/snapshot/generateAlbumCoverArtwork.js b/test/snapshot/generateAlbumCoverArtwork.js
new file mode 100644
index 00000000..150b12bc
--- /dev/null
+++ b/test/snapshot/generateAlbumCoverArtwork.js
@@ -0,0 +1,35 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumCoverArtwork (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const extraDependencies = {
+    getSizeOfImageFile: () => 0,
+  };
+
+  const album = {
+    directory: 'bee-forus-seatbelt-safebee',
+    coverArtFileExtension: 'png',
+    artTags: [
+      {name: 'Damara', directory: 'damara', isContentWarning: false},
+      {name: 'Cronus', directory: 'cronus', isContentWarning: false},
+      {name: 'Bees', directory: 'bees', isContentWarning: false},
+      {name: 'creepy crawlies', isContentWarning: true},
+    ],
+  };
+
+  evaluate.snapshot('display: primary', {
+    name: 'generateAlbumCoverArtwork',
+    args: [album],
+    slots: {mode: 'primary'},
+    extraDependencies,
+  });
+
+  evaluate.snapshot('display: thumbnail', {
+    name: 'generateAlbumCoverArtwork',
+    args: [album],
+    slots: {mode: 'thumbnail'},
+    extraDependencies,
+  });
+});
diff --git a/test/snapshot/generateAlbumReleaseInfo.js b/test/snapshot/generateAlbumReleaseInfo.js
new file mode 100644
index 00000000..7e3b37bd
--- /dev/null
+++ b/test/snapshot/generateAlbumReleaseInfo.js
@@ -0,0 +1,74 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumReleaseInfo (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateAlbumReleaseInfo',
+    args: [{
+      artistContribs: [
+        {who: {name: 'Toby Fox', directory: 'toby-fox', urls: null}, what: 'music probably'},
+        {who: {name: 'Tensei', directory: 'tensei', urls: ['https://tenseimusic.bandcamp.com/']}, what: 'hot jams'},
+      ],
+
+      coverArtistContribs: [
+        {who: {name: 'Hanni Brosh', directory: 'hb', urls: null}, what: null},
+      ],
+
+      wallpaperArtistContribs: [
+        {who: {name: 'Hanni Brosh', directory: 'hb', urls: null}, what: null},
+        {who: {name: 'Niklink', directory: 'niklink', urls: null}, what: 'edits'},
+      ],
+
+      bannerArtistContribs: [
+        {who: {name: 'Hanni Brosh', directory: 'hb', urls: null}, what: null},
+        {who: {name: 'Niklink', directory: 'niklink', urls: null}, what: 'edits'},
+      ],
+
+      name: 'AlterniaBound',
+      date: new Date('March 14, 2011'),
+      coverArtDate: new Date('April 1, 1991'),
+      urls: [
+        'https://homestuck.bandcamp.com/album/alterniabound-with-alternia',
+        'https://www.youtube.com/playlist?list=PLnVpmehyaOFZWO9QOZmD6A3TIK0wZ6xE2',
+        'https://www.youtube.com/watch?v=HO5V2uogkYc',
+      ],
+
+      tracks: [{duration: 253}, {duration: 372}],
+    }],
+  });
+
+  const sparse = {
+    artistContribs: [],
+    coverArtistContribs: [],
+    wallpaperArtistContribs: [],
+    bannerArtistContribs: [],
+
+    name: 'Suspicious Album',
+    urls: [],
+    tracks: [],
+  };
+
+  evaluate.snapshot('reduced details', {
+    name: 'generateAlbumReleaseInfo',
+    args: [sparse],
+  });
+
+  evaluate.snapshot('URLs only', {
+    name: 'generateAlbumReleaseInfo',
+    args: [{
+      ...sparse,
+      urls: ['https://homestuck.bandcamp.com/foo', 'https://soundcloud.com/bar'],
+    }],
+  });
+
+  evaluate.snapshot('equal cover art date', {
+    name: 'generateAlbumReleaseInfo',
+    args: [{
+      ...sparse,
+      date: new Date('2020-04-13'),
+      coverArtDate: new Date('2020-04-13'),
+    }],
+  });
+});
diff --git a/test/snapshot/generateAlbumSecondaryNav.js b/test/snapshot/generateAlbumSecondaryNav.js
new file mode 100644
index 00000000..180cb6e0
--- /dev/null
+++ b/test/snapshot/generateAlbumSecondaryNav.js
@@ -0,0 +1,55 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumSecondaryNav (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  let album, group1, group2;
+
+  group1 = {name: 'VCG', directory: 'vcg'};
+  group2 = {name: 'Bepis', directory: 'bepis'};
+
+  album = {
+    date: new Date('2010-04-13'),
+    groups: [group1, group2],
+  };
+
+  group1.albums = [
+    {name: 'First', directory: 'first', date: new Date('2010-04-10')},
+    album,
+    {name: 'Last', directory: 'last', date: new Date('2010-06-12')},
+  ];
+
+  group2.albums = [
+    album,
+    {name: 'Second', directory: 'second', date: new Date('2011-04-13')},
+  ];
+
+  evaluate.snapshot('basic behavior, mode: album', {
+    name: 'generateAlbumSecondaryNav',
+    args: [album],
+    slots: {mode: 'album'},
+  });
+
+  evaluate.snapshot('basic behavior, mode: track', {
+    name: 'generateAlbumSecondaryNav',
+    args: [album],
+    slots: {mode: 'track'},
+  });
+
+  album = {
+    date: null,
+    groups: [group1, group2],
+  };
+
+  group1.albums = [
+    ...group1.albums,
+    album,
+  ];
+
+  evaluate.snapshot('dateless album in mixed group', {
+    name: 'generateAlbumSecondaryNav',
+    args: [album],
+    slots: {mode: 'album'},
+  });
+});
diff --git a/test/snapshot/generateAlbumSidebarGroupBox.js b/test/snapshot/generateAlbumSidebarGroupBox.js
new file mode 100644
index 00000000..52348230
--- /dev/null
+++ b/test/snapshot/generateAlbumSidebarGroupBox.js
@@ -0,0 +1,55 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumSidebarGroupBox (snapshot)', async (t, evaluate) => {
+  await evaluate.load({
+    mock: {
+      ...evaluate.mock.transformContent,
+    },
+  });
+
+  let album, group;
+
+  album = {
+    date: new Date('2010-04-13'),
+  };
+
+  group = {
+    name: 'VCG',
+    directory: 'vcg',
+    descriptionShort: 'Very cool group.',
+    urls: ['https://vcg.bandcamp.com/', 'https://youtube.com/@vcg'],
+    albums: [
+      {name: 'First', directory: 'first', date: new Date('2010-04-10')},
+      album,
+      {name: 'Last', directory: 'last', date: new Date('2010-06-12')},
+    ],
+  };
+
+  evaluate.snapshot('basic behavior, mode: album', {
+    name: 'generateAlbumSidebarGroupBox',
+    args: [album, group],
+    slots: {mode: 'album'},
+  });
+
+  evaluate.snapshot('basic behavior, mode: track', {
+    name: 'generateAlbumSidebarGroupBox',
+    args: [album, group],
+    slots: {mode: 'track'},
+  });
+
+  album = {
+    date: null,
+  };
+
+  group.albums = [
+    ...group.albums,
+    album,
+  ];
+
+  evaluate.snapshot('dateless album in mixed group', {
+    name: 'generateAlbumSidebarGroupBox',
+    args: [album, group],
+    slots: {mode: 'album'},
+  });
+});
diff --git a/test/snapshot/generateAlbumTrackList.js b/test/snapshot/generateAlbumTrackList.js
new file mode 100644
index 00000000..ea3cfef3
--- /dev/null
+++ b/test/snapshot/generateAlbumTrackList.js
@@ -0,0 +1,48 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateAlbumTrackList (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const contribs1 = [
+    {who: {name: 'Apricot', directory: 'apricot', urls: null}},
+  ];
+
+  const contribs2 = [
+    {who: {name: 'Apricot', directory: 'apricot', urls: null}},
+    {who: {name: 'Peach', directory: 'peach', urls: ['https://peach.bandcamp.com/']}},
+  ];
+
+  const color1 = '#fb07ff';
+  const color2 = '#ea2e83';
+
+  const tracks = [
+    {name: 'Track 1', directory: 't1', duration: 20, artistContribs: contribs1, color: color1},
+    {name: 'Track 2', directory: 't2', duration: 30, artistContribs: contribs1, color: color1},
+    {name: 'Track 3', directory: 't3', duration: 40, artistContribs: contribs1, color: color1},
+    {name: 'Track 4', directory: 't4', duration: 5, artistContribs: contribs2, color: color2},
+  ];
+
+  evaluate.snapshot('basic behavior, with track sections', {
+    name: 'generateAlbumTrackList',
+    args: [{
+      color: color1,
+      artistContribs: contribs1,
+      trackSections: [
+        {name: 'First section', tracks: tracks.slice(0, 3)},
+        {name: 'Second section', tracks: tracks.slice(3)},
+      ],
+      tracks,
+    }],
+  });
+
+  evaluate.snapshot('basic behavior, default track section', {
+    name: 'generateAlbumTrackList',
+    args: [{
+      color: color1,
+      artistContribs: contribs1,
+      trackSections: [{isDefaultTrackSection: true, tracks}],
+      tracks,
+    }],
+  });
+});
diff --git a/test/snapshot/generateBanner.js b/test/snapshot/generateBanner.js
new file mode 100644
index 00000000..587ce04a
--- /dev/null
+++ b/test/snapshot/generateBanner.js
@@ -0,0 +1,22 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateBanner (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateBanner',
+    slots: {
+      path: ['media.albumBanner', 'cool-album', 'png'],
+      alt: 'Very cool banner art.',
+      dimensions: [800, 200],
+    },
+  });
+
+  evaluate.snapshot('no dimensions', {
+    name: 'generateBanner',
+    slots: {
+      path: ['media.albumBanner', 'cool-album', 'png'],
+    },
+  });
+});
diff --git a/test/snapshot/generateCoverArtwork.js b/test/snapshot/generateCoverArtwork.js
new file mode 100644
index 00000000..025a6d0d
--- /dev/null
+++ b/test/snapshot/generateCoverArtwork.js
@@ -0,0 +1,33 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateCoverArtwork (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const extraDependencies = {
+    getSizeOfImageFile: () => 0,
+  };
+
+  const artTags = [
+    {name: 'Damara', directory: 'damara', isContentWarning: false},
+    {name: 'Cronus', directory: 'cronus', isContentWarning: false},
+    {name: 'Bees', directory: 'bees', isContentWarning: false},
+    {name: 'creepy crawlies', isContentWarning: true},
+  ];
+
+  const path = ['media.albumCover', 'bee-forus-seatbelt-safebee', 'png'];
+
+  evaluate.snapshot('display: primary', {
+    name: 'generateCoverArtwork',
+    args: [artTags],
+    slots: {path, mode: 'primary'},
+    extraDependencies,
+  });
+
+  evaluate.snapshot('display: thumbnail', {
+    name: 'generateCoverArtwork',
+    args: [artTags],
+    slots: {path, mode: 'thumbnail'},
+    extraDependencies,
+  });
+});
diff --git a/test/snapshot/generateTrackCoverArtwork.js b/test/snapshot/generateTrackCoverArtwork.js
new file mode 100644
index 00000000..bfefb5fb
--- /dev/null
+++ b/test/snapshot/generateTrackCoverArtwork.js
@@ -0,0 +1,63 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateTrackCoverArtwork (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const extraDependencies = {
+    getSizeOfImageFile: () => 0,
+  };
+
+  const album = {
+    directory: 'bee-forus-seatbelt-safebee',
+    coverArtFileExtension: 'png',
+    artTags: [
+      {name: 'Damara', directory: 'damara', isContentWarning: false},
+      {name: 'Cronus', directory: 'cronus', isContentWarning: false},
+      {name: 'Bees', directory: 'bees', isContentWarning: false},
+      {name: 'creepy crawlies', isContentWarning: true},
+    ],
+  };
+
+  const track1 = {
+    directory: 'beesmp3',
+    hasUniqueCoverArt: true,
+    coverArtFileExtension: 'jpg',
+    artTags: [{name: 'Bees', directory: 'bees', isContentWarning: false}],
+    album,
+  };
+
+  const track2 = {
+    directory: 'fake-bonus-track',
+    hasUniqueCoverArt: false,
+    album,
+  };
+
+  evaluate.snapshot('display: primary - unique art', {
+    name: 'generateTrackCoverArtwork',
+    args: [track1],
+    slots: {mode: 'primary'},
+    extraDependencies,
+  });
+
+  evaluate.snapshot('display: thumbnail - unique art', {
+    name: 'generateTrackCoverArtwork',
+    args: [track1],
+    slots: {mode: 'thumbnail'},
+    extraDependencies,
+  });
+
+  evaluate.snapshot('display: primary - no unique art', {
+    name: 'generateTrackCoverArtwork',
+    args: [track2],
+    slots: {mode: 'primary'},
+    extraDependencies,
+  });
+
+  evaluate.snapshot('display: thumbnail - no unique art', {
+    name: 'generateTrackCoverArtwork',
+    args: [track2],
+    slots: {mode: 'thumbnail'},
+    extraDependencies,
+  });
+});
diff --git a/test/snapshot/generateTrackReleaseInfo.js b/test/snapshot/generateTrackReleaseInfo.js
new file mode 100644
index 00000000..5556f38b
--- /dev/null
+++ b/test/snapshot/generateTrackReleaseInfo.js
@@ -0,0 +1,51 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'generateTrackReleaseInfo (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const artistContribs = [{who: {name: 'Toby Fox', directory: 'toby-fox', urls: null}, what: null}];
+  const coverArtistContribs = [{who: {name: 'Alpaca', directory: 'alpaca', urls: null}, what: '🔥'}];
+
+  evaluate.snapshot('basic behavior', {
+    name: 'generateTrackReleaseInfo',
+    args: [{
+      artistContribs,
+      name: 'An Apple Disaster!!',
+      date: new Date('2011-11-30'),
+      duration: 58,
+      urls: ['https://soundcloud.com/foo', 'https://youtube.com/watch?v=bar'],
+    }],
+  });
+
+  const sparse = {
+    artistContribs,
+    name: 'Suspicious Track',
+    date: null,
+    duration: null,
+    urls: [],
+  };
+
+  evaluate.snapshot('reduced details', {
+    name: 'generateTrackReleaseInfo',
+    args: [sparse],
+  });
+
+  evaluate.snapshot('cover artist contribs, non-unique', {
+    name: 'generateTrackReleaseInfo',
+    args: [{
+      ...sparse,
+      coverArtistContribs,
+      hasUniqueCoverArt: false,
+    }],
+  });
+
+  evaluate.snapshot('cover artist contribs, unique', {
+    name: 'generateTrackReleaseInfo',
+    args: [{
+      ...sparse,
+      coverArtistContribs,
+      hasUniqueCoverArt: true,
+    }],
+  });
+});
diff --git a/test/snapshot/image.js b/test/snapshot/image.js
new file mode 100644
index 00000000..62e1cd9a
--- /dev/null
+++ b/test/snapshot/image.js
@@ -0,0 +1,101 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'image (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const quickSnapshot = (message, opts) =>
+    evaluate.snapshot(message, {
+      name: 'image',
+      extraDependencies: {
+        getSizeOfImageFile: () => 0,
+      },
+      ...opts,
+    });
+
+  quickSnapshot('source via path', {
+    slots: {
+      path: ['media.albumCover', 'beyond-canon', 'png'],
+    },
+  });
+
+  quickSnapshot('source via src', {
+    slots: {
+      src: 'https://example.com/bananas.gif',
+    },
+  });
+
+  quickSnapshot('source missing', {
+    slots: {
+      missingSourceContent: 'Example of missing source message.',
+    },
+  });
+
+  quickSnapshot('id without link', {
+    slots: {
+      src: 'foobar',
+      id: 'banana',
+    },
+  });
+
+  quickSnapshot('id with link', {
+    slots: {
+      src: 'foobar',
+      link: true,
+      id: 'banana',
+    },
+  });
+
+  quickSnapshot('id with square', {
+    slots: {
+      src: 'foobar',
+      square: true,
+      id: 'banana',
+    },
+  });
+
+  quickSnapshot('width & height', {
+    slots: {
+      src: 'foobar',
+      width: 600,
+      height: 400,
+    },
+  });
+
+  quickSnapshot('square', {
+    slots: {
+      src: 'foobar',
+      square: true,
+    },
+  });
+
+  quickSnapshot('lazy with square', {
+    slots: {
+      src: 'foobar',
+      lazy: true,
+      square: true,
+    },
+  });
+
+  quickSnapshot('link with file size', {
+    extraDependencies: {
+      getSizeOfImageFile: () => 10 ** 6,
+    },
+    slots: {
+      path: ['media.albumCover', 'pingas', 'png'],
+      link: true,
+    },
+  });
+
+  quickSnapshot('content warnings via tags', {
+    args: [
+      [
+        {name: 'Dirk Strider', directory: 'dirk'},
+        {name: 'too cool for school', isContentWarning: true},
+      ],
+    ],
+    slots: {
+      path: ['media.albumCover', 'beyond-canon', 'png'],
+    },
+  });
+});
diff --git a/test/snapshot/linkArtist.js b/test/snapshot/linkArtist.js
new file mode 100644
index 00000000..684affc3
--- /dev/null
+++ b/test/snapshot/linkArtist.js
@@ -0,0 +1,30 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'linkArtist (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('basic behavior', {
+    name: 'linkArtist',
+    args: [
+      {
+        name: `Toby Fox`,
+        directory: `toby-fox`,
+      }
+    ],
+  });
+
+  evaluate.snapshot('prefer short name', {
+    name: 'linkArtist',
+    args: [
+      {
+        name: 'ICCTTCMDMIROTMCWMWFTPFTDDOTARHPOESWGBTWEATFCWSEBTSSFOFG',
+        nameShort: '55gore',
+        directory: '55gore',
+      },
+    ],
+    slots: {
+      preferShortName: true,
+    },
+  });
+});
diff --git a/test/snapshot/linkContribution.js b/test/snapshot/linkContribution.js
new file mode 100644
index 00000000..10b1bd08
--- /dev/null
+++ b/test/snapshot/linkContribution.js
@@ -0,0 +1,67 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'linkContribution (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  const quickSnapshot = (message, slots) =>
+    evaluate.snapshot(message, {
+      name: 'linkContribution',
+      multiple: [
+        {args: [
+          {who: {
+            name: 'Clark Powell',
+            directory: 'clark-powell',
+            urls: ['https://soundcloud.com/plazmataz'],
+          }, what: null},
+        ]},
+        {args: [
+          {who: {
+            name: 'Grounder & Scratch',
+            directory: 'the-big-baddies',
+            urls: [],
+          }, what: 'Snooping'},
+        ]},
+        {args: [
+          {who: {
+            name: 'Toby Fox',
+            directory: 'toby-fox',
+            urls: ['https://tobyfox.bandcamp.com/', 'https://toby.fox/'],
+          }, what: 'Arrangement'},
+        ]},
+      ],
+      slots,
+    });
+
+  quickSnapshot('showContribution & showIcons', {
+    showContribution: true,
+    showIcons: true,
+  });
+
+  quickSnapshot('only showContribution', {
+    showContribution: true,
+  });
+
+  quickSnapshot('only showIcons', {
+    showIcons: true,
+  });
+
+  quickSnapshot('no accents', {});
+
+  evaluate.snapshot('loads of links', {
+    name: 'linkContribution',
+    args: [
+      {who: {name: 'Lorem Ipsum Lover', directory: 'lorem-ipsum-lover', urls: [
+        'https://loremipsum.io',
+        'https://loremipsum.io/generator/',
+        'https://loremipsum.io/#meaning',
+        'https://loremipsum.io/#usage-and-examples',
+        'https://loremipsum.io/#controversy',
+        'https://loremipsum.io/#when-to-use-lorem-ipsum',
+        'https://loremipsum.io/#lorem-ipsum-all-the-things',
+        'https://loremipsum.io/#original-source',
+      ]}, what: null},
+    ],
+    slots: {showIcons: true},
+  });
+});
diff --git a/test/snapshot/linkExternal.js b/test/snapshot/linkExternal.js
new file mode 100644
index 00000000..391d5a10
--- /dev/null
+++ b/test/snapshot/linkExternal.js
@@ -0,0 +1,54 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'linkExternal (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('missing domain (arbitrary local path)', {
+    name: 'linkExternal',
+    args: ['/foo/bar/baz.mp3']
+  });
+
+  evaluate.snapshot('unknown domain (arbitrary world wide web path)', {
+    name: 'linkExternal',
+    args: ['https://snoo.ping.as/usual/i/see/'],
+  });
+
+  evaluate.snapshot('basic domain matches', {
+    name: 'linkExternal',
+    multiple: [
+      {args: ['https://homestuck.bandcamp.com/']},
+      {args: ['https://soundcloud.com/plazmataz']},
+      {args: ['https://aeritus.tumblr.com/']},
+      {args: ['https://twitter.com/awkwarddoesart']},
+      {args: ['https://www.deviantart.com/chesswanderlust-sama']},
+      {args: ['https://en.wikipedia.org/wiki/Haydn_Quartet_(vocal_ensemble)']},
+      {args: ['https://www.poetryfoundation.org/poets/christina-rossetti']},
+      {args: ['https://www.instagram.com/levc_egm/']},
+      {args: ['https://www.patreon.com/CecilyRenns']},
+      {args: ['https://open.spotify.com/artist/63SNNpNOicDzG3LY82G4q3']},
+      {args: ['https://buzinkai.newgrounds.com/']},
+    ],
+  });
+
+  evaluate.snapshot('custom matches - album', {
+    name: 'linkExternal',
+    multiple: [
+      {args: ['https://youtu.be/abc']},
+      {args: ['https://youtube.com/watch?v=abc']},
+      {args: ['https://youtube.com/Playlist?list=kweh']},
+    ],
+    slots: {
+      mode: 'album',
+    },
+  });
+
+  evaluate.snapshot('custom domains for common platforms', {
+    name: 'linkExternal',
+    multiple: [
+      // Just one domain of each platform is OK here
+      {args: ['https://music.solatrus.com/']},
+      {args: ['https://types.pl/']},
+    ],
+  });
+});
diff --git a/test/snapshot/linkExternalFlash.js b/test/snapshot/linkExternalFlash.js
new file mode 100644
index 00000000..7bb86c6a
--- /dev/null
+++ b/test/snapshot/linkExternalFlash.js
@@ -0,0 +1,24 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'linkExternalFlash (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('basic behavior', {
+    name: 'linkExternalFlash',
+    multiple: [
+      {args: ['https://homestuck.com/story/4109/', {page: '4109'}]},
+      {args: ['https://youtu.be/FDt-SLyEcjI', {page: '4109'}]},
+      {args: ['https://www.bgreco.net/hsflash/006009.html', {page: '4109'}]},
+      {args: ['https://www.newgrounds.com/portal/view/582345', {page: '4109'}]},
+    ],
+  });
+
+  evaluate.snapshot('secret page', {
+    name: 'linkExternalFlash',
+    multiple: [
+      {args: ['https://homestuck.com/story/pony/', {page: 'pony'}]},
+      {args: ['https://youtu.be/USB1pj6hAjU', {page: 'pony'}]},
+    ],
+  });
+});
diff --git a/test/snapshot/linkTemplate.js b/test/snapshot/linkTemplate.js
new file mode 100644
index 00000000..bef0935c
--- /dev/null
+++ b/test/snapshot/linkTemplate.js
@@ -0,0 +1,35 @@
+import t from 'tap';
+import {testContentFunctions} from '../lib/content-function.js';
+
+testContentFunctions(t, 'linkTemplate (snapshot)', async (t, evaluate) => {
+  await evaluate.load();
+
+  evaluate.snapshot('fill many slots', {
+    name: 'linkTemplate',
+
+    extraDependencies: {
+      getColors: c => ({primary: c + 'ff', dim: c + '77'}),
+    },
+
+    slots: {
+      'color': '#123456',
+      'href': 'https://hsmusic.wiki/media/cool file.pdf',
+      'hash': 'fooey',
+      'attributes': {class: 'dog', id: 'cat1'},
+      'content': 'My Cool Link',
+    },
+  });
+
+  evaluate.snapshot('fill path slot & provide appendIndexHTML', {
+    name: 'linkTemplate',
+
+    extraDependencies: {
+      to: (...path) => '/c*lzone/' + path.join('/') + '/',
+      appendIndexHTML: true,
+    },
+
+    slots: {
+      path: ['myCoolPath', 'ham', 'pineapple', 'tomato'],
+    },
+  });
+});