1import { describe, expect, it } from 'vitest'; 2import { getMetadata } from '../website/src/metadata_parser'; 3 4describe.concurrent('Metadata parser', () => { 5 it('loads a tag from inline comment', async () => { 6 const tune = `// @title Awesome song`; 7 expect(getMetadata(tune)).toStrictEqual({ 8 title: 'Awesome song', 9 }); 10 }); 11 12 it('loads many tags from inline comments', async () => { 13 const tune = `// @title Awesome song 14// @by Sam`; 15 expect(getMetadata(tune)).toStrictEqual({ 16 title: 'Awesome song', 17 by: ['Sam'], 18 }); 19 }); 20 21 it('loads many tags from one inline comment', async () => { 22 const tune = `// @title Awesome song @by Sam`; 23 expect(getMetadata(tune)).toStrictEqual({ 24 title: 'Awesome song', 25 by: ['Sam'], 26 }); 27 }); 28 29 it('loads a tag from a block comment', async () => { 30 const tune = `/* @title Awesome song */`; 31 expect(getMetadata(tune)).toStrictEqual({ 32 title: 'Awesome song', 33 }); 34 }); 35 36 it('loads many tags from a block comment', async () => { 37 const tune = `/* 38@title Awesome song 39@by Sam 40*/`; 41 expect(getMetadata(tune)).toStrictEqual({ 42 title: 'Awesome song', 43 by: ['Sam'], 44 }); 45 }); 46 47 it('loads many tags from many block comments', async () => { 48 const tune = `/* @title Awesome song */ 49/* @by Sam */`; 50 expect(getMetadata(tune)).toStrictEqual({ 51 title: 'Awesome song', 52 by: ['Sam'], 53 }); 54 }); 55 56 it('loads many tags from mixed comments', async () => { 57 const tune = `/* @title Awesome song */ 58// @by Sam 59`; 60 expect(getMetadata(tune)).toStrictEqual({ 61 title: 'Awesome song', 62 by: ['Sam'], 63 }); 64 }); 65 66 it('loads a title tag with quotes syntax', async () => { 67 const tune = `// "Awesome song"`; 68 expect(getMetadata(tune)).toStrictEqual({ 69 title: 'Awesome song', 70 }); 71 }); 72 73 it('loads a title tag with quotes syntax among other tags', async () => { 74 const tune = `// "Awesome song" made @by Sam`; 75 expect(getMetadata(tune)).toStrictEqual({ 76 title: 'Awesome song', 77 by: ['Sam'], 78 }); 79 }); 80 81 it('loads a title tag with quotes syntax from block comment', async () => { 82 const tune = `/* "Awesome song" 83@by Sam */`; 84 expect(getMetadata(tune)).toStrictEqual({ 85 title: 'Awesome song', 86 by: ['Sam'], 87 }); 88 }); 89 90 it('does not load a title tag with quotes syntax after a prefix', async () => { 91 const tune = `// I don't care about those "metadata".`; 92 expect(getMetadata(tune)).toStrictEqual({}); 93 }); 94 95 it('does not load a title tag with quotes syntax after an other comment', async () => { 96 const tune = `// I don't care about those 97// "metadata"`; 98 expect(getMetadata(tune)).toStrictEqual({}); 99 }); 100 101 it('does not load a title tag with quotes syntax after other tags', async () => { 102 const tune = `/* 103@by Sam aka "Lady Strudel" 104 "Sandyyy" 105*/`; 106 expect(getMetadata(tune)).toStrictEqual({ 107 by: ['Sam aka "Lady Strudel"', '"Sandyyy"'], 108 }); 109 }); 110 111 it('loads a tag list with comma-separated values syntax', async () => { 112 const tune = `// @by Sam, Sandy`; 113 expect(getMetadata(tune)).toStrictEqual({ 114 by: ['Sam', 'Sandy'], 115 }); 116 }); 117 118 it('loads a tag list with duplicate keys syntax', async () => { 119 const tune = `// @by Sam 120// @by Sandy`; 121 expect(getMetadata(tune)).toStrictEqual({ 122 by: ['Sam', 'Sandy'], 123 }); 124 }); 125 126 it('loads a tag list with duplicate keys syntax, with prefixes', async () => { 127 const tune = `// song @by Sam 128// samples @by Sandy`; 129 expect(getMetadata(tune)).toStrictEqual({ 130 by: ['Sam', 'Sandy'], 131 }); 132 }); 133 134 it('loads many tag lists with duplicate keys syntax, within code', async () => { 135 const tune = `note("a3 c#4 e4 a4") // @by Sam @license CC0 136 s("bd hh sd hh") // @by Sandy @license CC BY-NC-SA`; 137 expect(getMetadata(tune)).toStrictEqual({ 138 by: ['Sam', 'Sandy'], 139 license: ['CC0', 'CC BY-NC-SA'], 140 }); 141 }); 142 143 it('loads a tag list with duplicate keys syntax from block comment', async () => { 144 const tune = `/* @by Sam 145@by Sandy */`; 146 expect(getMetadata(tune)).toStrictEqual({ 147 by: ['Sam', 'Sandy'], 148 }); 149 }); 150 151 it('loads a tag list with newline syntax', async () => { 152 const tune = `/* 153@by Sam 154 Sandy */`; 155 expect(getMetadata(tune)).toStrictEqual({ 156 by: ['Sam', 'Sandy'], 157 }); 158 }); 159 160 it('loads a multiline tag from block comment', async () => { 161 const tune = `/* 162@details I wrote this song in February 19th, 2023. 163 It was around midnight and I was lying on 164 the sofa in the living room. 165*/`; 166 expect(getMetadata(tune)).toStrictEqual({ 167 details: 168 'I wrote this song in February 19th, 2023. ' + 169 'It was around midnight and I was lying on the sofa in the living room.', 170 }); 171 }); 172 173 it('loads a multiline tag from block comment with duplicate keys', async () => { 174 const tune = `/* 175@details I wrote this song in February 19th, 2023. 176@details It was around midnight and I was lying on 177 the sofa in the living room. 178*/`; 179 expect(getMetadata(tune)).toStrictEqual({ 180 details: 181 'I wrote this song in February 19th, 2023. ' + 182 'It was around midnight and I was lying on the sofa in the living room.', 183 }); 184 }); 185 186 it('loads a multiline tag from inline comments', async () => { 187 const tune = `// @details I wrote this song in February 19th, 2023. 188// @details It was around midnight and I was lying on 189// @details the sofa in the living room. 190*/`; 191 expect(getMetadata(tune)).toStrictEqual({ 192 details: 193 'I wrote this song in February 19th, 2023. ' + 194 'It was around midnight and I was lying on the sofa in the living room.', 195 }); 196 }); 197 198 it('loads empty tags from inline comments', async () => { 199 const tune = `// @title 200// @by`; 201 expect(getMetadata(tune)).toStrictEqual({ 202 title: '', 203 by: [], 204 }); 205 }); 206 207 it('loads tags with whitespaces from inline comments', async () => { 208 const tune = ` // @title Awesome song 209 // @by Sam Tagada `; 210 expect(getMetadata(tune)).toStrictEqual({ 211 title: 'Awesome song', 212 by: ['Sam Tagada'], 213 }); 214 }); 215 216 it('loads tags with whitespaces from block comment', async () => { 217 const tune = ` /* @title Awesome song 218 @by Sam Tagada */ `; 219 expect(getMetadata(tune)).toStrictEqual({ 220 title: 'Awesome song', 221 by: ['Sam Tagada'], 222 }); 223 }); 224 225 it('loads empty tags from block comment', async () => { 226 const tune = `/* @title 227@by */`; 228 expect(getMetadata(tune)).toStrictEqual({ 229 title: '', 230 by: [], 231 }); 232 }); 233 234 it('does not load tags if there is not', async () => { 235 const tune = `note("a3 c#4 e4 a4")`; 236 expect(getMetadata(tune)).toStrictEqual({}); 237 }); 238 239 it('does not load code that looks like a metadata tag', async () => { 240 const tune = `const str1 = '@title Awesome song'`; 241 // need a lexer to avoid this one, but it's a pretty rare use case: 242 // const tune = `const str1 = '// @title Awesome song'`; 243 244 expect(getMetadata(tune)).toStrictEqual({}); 245 }); 246});