|
| 1 | +const { describe, it } = require('node:test'); |
| 2 | +const assert = require('node:assert'); |
| 3 | +const { extractLegalBoilerplateSection } = require('./dangerfile-utils.js'); |
| 4 | + |
| 5 | +describe('Legal Boilerplate Validation', () => { |
| 6 | + describe('extractLegalBoilerplateSection', () => { |
| 7 | + it('should extract legal boilerplate section with ### header', () => { |
| 8 | + const template = ` |
| 9 | +# Pull Request Template |
| 10 | +
|
| 11 | +## Description |
| 12 | +Please describe your changes |
| 13 | +
|
| 14 | +### Legal Boilerplate |
| 15 | +Look, I get it. The entity doing business as "Sentry" was incorporated in the State of Delaware in 2015 as Functional Software, Inc. and is gonna need some rights from me in order to utilize my contributions in this here PR. So here's the deal: I retain all rights, title and interest in and to my contributions, and by keeping this boilerplate intact I confirm that Sentry can use, modify, copy, and redistribute my contributions, under Sentry's choice of terms. |
| 16 | +
|
| 17 | +## Checklist |
| 18 | +- [ ] Tests added |
| 19 | +`; |
| 20 | + |
| 21 | + const result = extractLegalBoilerplateSection(template); |
| 22 | + |
| 23 | + assert.ok(result.includes('### Legal Boilerplate'), 'Should include the header'); |
| 24 | + assert.ok(result.includes('Functional Software, Inc.'), 'Should include the legal text'); |
| 25 | + assert.ok(!result.includes('## Checklist'), 'Should not include the next section'); |
| 26 | + }); |
| 27 | + |
| 28 | + it('should extract legal boilerplate section with ## header', () => { |
| 29 | + const template = ` |
| 30 | +# Pull Request Template |
| 31 | +
|
| 32 | +## Legal Boilerplate |
| 33 | +
|
| 34 | +This is a legal notice. |
| 35 | +
|
| 36 | +## Other Section |
| 37 | +More content |
| 38 | +`; |
| 39 | + |
| 40 | + const result = extractLegalBoilerplateSection(template); |
| 41 | + |
| 42 | + assert.strictEqual(result.trim(), '## Legal Boilerplate\n\nThis is a legal notice.'); |
| 43 | + }); |
| 44 | + |
| 45 | + it('should extract legal boilerplate section with different heading levels', () => { |
| 46 | + const testCases = [ |
| 47 | + { header: '# Legal Boilerplate', text: 'Level 1 header' }, |
| 48 | + { header: '## Legal Boilerplate', text: 'Level 2 header' }, |
| 49 | + { header: '### Legal Boilerplate', text: 'Level 3 header' }, |
| 50 | + { header: '#### Legal Boilerplate', text: 'Level 4 header' }, |
| 51 | + { header: '##### Legal Boilerplate', text: 'Level 5 header' }, |
| 52 | + { header: '###### Legal Boilerplate', text: 'Level 6 header' } |
| 53 | + ]; |
| 54 | + |
| 55 | + testCases.forEach(({ header, text }) => { |
| 56 | + const template = `${header}\n${text}\n## Next Section`; |
| 57 | + const result = extractLegalBoilerplateSection(template); |
| 58 | + |
| 59 | + assert.ok(result.includes(header), `Should extract section with ${header}`); |
| 60 | + assert.ok(result.includes(text), `Should include text for ${header}`); |
| 61 | + assert.ok(!result.includes('Next Section'), `Should not include next section for ${header}`); |
| 62 | + }); |
| 63 | + }); |
| 64 | + |
| 65 | + it('should handle case-insensitive matching', () => { |
| 66 | + const templates = [ |
| 67 | + '### Legal Boilerplate\nContent', |
| 68 | + '### legal boilerplate\nContent', |
| 69 | + '### LEGAL BOILERPLATE\nContent', |
| 70 | + '### Legal BOILERPLATE\nContent' |
| 71 | + ]; |
| 72 | + |
| 73 | + templates.forEach(template => { |
| 74 | + const result = extractLegalBoilerplateSection(template); |
| 75 | + assert.ok(result.length > 0, `Should extract from: ${template.split('\n')[0]}`); |
| 76 | + assert.ok(result.includes('Content'), `Should include content from: ${template.split('\n')[0]}`); |
| 77 | + }); |
| 78 | + }); |
| 79 | + |
| 80 | + it('should handle legal boilerplate with multiple paragraphs', () => { |
| 81 | + const template = ` |
| 82 | +### Legal Boilerplate |
| 83 | +
|
| 84 | +First paragraph of legal text. |
| 85 | +
|
| 86 | +Second paragraph of legal text. |
| 87 | +
|
| 88 | +Third paragraph of legal text. |
| 89 | +
|
| 90 | +## Next Section |
| 91 | +`; |
| 92 | + |
| 93 | + const result = extractLegalBoilerplateSection(template); |
| 94 | + |
| 95 | + assert.ok(result.includes('First paragraph'), 'Should include first paragraph'); |
| 96 | + assert.ok(result.includes('Second paragraph'), 'Should include second paragraph'); |
| 97 | + assert.ok(result.includes('Third paragraph'), 'Should include third paragraph'); |
| 98 | + assert.ok(!result.includes('Next Section'), 'Should not include next section'); |
| 99 | + }); |
| 100 | + |
| 101 | + it('should handle legal boilerplate at end of template', () => { |
| 102 | + const template = ` |
| 103 | +# PR Template |
| 104 | +
|
| 105 | +## Description |
| 106 | +Content |
| 107 | +
|
| 108 | +### Legal Boilerplate |
| 109 | +Legal text at the end. |
| 110 | +`; |
| 111 | + |
| 112 | + const result = extractLegalBoilerplateSection(template); |
| 113 | + |
| 114 | + assert.ok(result.includes('### Legal Boilerplate'), 'Should include header'); |
| 115 | + assert.ok(result.includes('Legal text at the end.'), 'Should include text'); |
| 116 | + }); |
| 117 | + |
| 118 | + it('should return empty string when no legal boilerplate section exists', () => { |
| 119 | + const template = ` |
| 120 | +# Pull Request Template |
| 121 | +
|
| 122 | +## Description |
| 123 | +Please describe your changes |
| 124 | +
|
| 125 | +## Checklist |
| 126 | +- [ ] Tests added |
| 127 | +`; |
| 128 | + |
| 129 | + const result = extractLegalBoilerplateSection(template); |
| 130 | + |
| 131 | + assert.strictEqual(result, '', 'Should return empty string when no legal section found'); |
| 132 | + }); |
| 133 | + |
| 134 | + it('should handle empty template', () => { |
| 135 | + const result = extractLegalBoilerplateSection(''); |
| 136 | + assert.strictEqual(result, '', 'Should return empty string for empty template'); |
| 137 | + }); |
| 138 | + |
| 139 | + it('should handle template with only legal boilerplate section', () => { |
| 140 | + const template = '### Legal Boilerplate\nThis is the only content.'; |
| 141 | + const result = extractLegalBoilerplateSection(template); |
| 142 | + |
| 143 | + assert.ok(result.includes('### Legal Boilerplate'), 'Should include header'); |
| 144 | + assert.ok(result.includes('This is the only content.'), 'Should include content'); |
| 145 | + }); |
| 146 | + |
| 147 | + it('should handle legal boilerplate with special characters', () => { |
| 148 | + const template = ` |
| 149 | +### Legal Boilerplate |
| 150 | +Text with special chars: @#$%^&*()_+-={}[]|\\:";'<>?,./ |
| 151 | +And some unicode: 你好世界 🎉 |
| 152 | +
|
| 153 | +## Next |
| 154 | +`; |
| 155 | + |
| 156 | + const result = extractLegalBoilerplateSection(template); |
| 157 | + |
| 158 | + assert.ok(result.includes('special chars'), 'Should handle special characters'); |
| 159 | + assert.ok(result.includes('你好世界'), 'Should handle unicode'); |
| 160 | + assert.ok(result.includes('🎉'), 'Should handle emoji'); |
| 161 | + }); |
| 162 | + |
| 163 | + it('should handle legal boilerplate with code blocks', () => { |
| 164 | + const template = ` |
| 165 | +### Legal Boilerplate |
| 166 | +
|
| 167 | +Some text with code: |
| 168 | +
|
| 169 | +\`\`\`javascript |
| 170 | +const legal = true; |
| 171 | +\`\`\` |
| 172 | +
|
| 173 | +More text. |
| 174 | +
|
| 175 | +## Next Section |
| 176 | +`; |
| 177 | + |
| 178 | + const result = extractLegalBoilerplateSection(template); |
| 179 | + |
| 180 | + assert.ok(result.includes('const legal = true;'), 'Should include code blocks'); |
| 181 | + assert.ok(result.includes('More text.'), 'Should include text after code block'); |
| 182 | + assert.ok(!result.includes('Next Section'), 'Should not include next section'); |
| 183 | + }); |
| 184 | + |
| 185 | + it('should handle legal boilerplate with lists', () => { |
| 186 | + const template = ` |
| 187 | +### Legal Boilerplate |
| 188 | +
|
| 189 | +You agree to: |
| 190 | +- Item 1 |
| 191 | +- Item 2 |
| 192 | +- Item 3 |
| 193 | +
|
| 194 | +## Other |
| 195 | +`; |
| 196 | + |
| 197 | + const result = extractLegalBoilerplateSection(template); |
| 198 | + |
| 199 | + assert.ok(result.includes('- Item 1'), 'Should include list items'); |
| 200 | + assert.ok(result.includes('- Item 2'), 'Should include list items'); |
| 201 | + assert.ok(result.includes('- Item 3'), 'Should include list items'); |
| 202 | + }); |
| 203 | + |
| 204 | + it('should handle legal boilerplate with extra whitespace', () => { |
| 205 | + const template = ` |
| 206 | +### Legal Boilerplate |
| 207 | +Content with spaces. |
| 208 | +## Next |
| 209 | +`; |
| 210 | + |
| 211 | + const result = extractLegalBoilerplateSection(template); |
| 212 | + |
| 213 | + assert.ok(result.includes('Content with spaces.'), 'Should handle extra whitespace in header'); |
| 214 | + }); |
| 215 | + |
| 216 | + it('should stop at first subsequent header', () => { |
| 217 | + const template = ` |
| 218 | +### Legal Boilerplate |
| 219 | +First section content. |
| 220 | +### Another Legal Boilerplate |
| 221 | +This should not be included. |
| 222 | +`; |
| 223 | + |
| 224 | + const result = extractLegalBoilerplateSection(template); |
| 225 | + |
| 226 | + assert.ok(result.includes('First section content.'), 'Should include first section'); |
| 227 | + assert.ok(!result.includes('This should not be included.'), 'Should stop at next header'); |
| 228 | + }); |
| 229 | + |
| 230 | + it('should handle blank lines within legal section', () => { |
| 231 | + const template = ` |
| 232 | +### Legal Boilerplate |
| 233 | +
|
| 234 | +First paragraph. |
| 235 | +
|
| 236 | +
|
| 237 | +Second paragraph with blank lines above. |
| 238 | +
|
| 239 | +## Next |
| 240 | +`; |
| 241 | + |
| 242 | + const result = extractLegalBoilerplateSection(template); |
| 243 | + |
| 244 | + assert.ok(result.includes('First paragraph.'), 'Should include first paragraph'); |
| 245 | + assert.ok(result.includes('Second paragraph'), 'Should include second paragraph'); |
| 246 | + // Should preserve blank lines |
| 247 | + const blankLineCount = (result.match(/\n\n/g) || []).length; |
| 248 | + assert.ok(blankLineCount >= 1, 'Should preserve blank lines'); |
| 249 | + }); |
| 250 | + }); |
| 251 | +}); |
0 commit comments