[READ-ONLY] a fast, modern browser for the npm registry
at main 152 lines 5.9 kB view raw
1import { describe, expect, it } from 'vitest' 2import { mountSuspended } from '@nuxt/test-utils/runtime' 3import LicenseDisplay from '~/components/LicenseDisplay.vue' 4 5describe('LicenseDisplay', () => { 6 describe('single license', () => { 7 it('renders a valid SPDX license as a link', async () => { 8 const component = await mountSuspended(LicenseDisplay, { 9 props: { license: 'MIT' }, 10 }) 11 const link = component.find('a') 12 expect(link.exists()).toBe(true) 13 expect(link.attributes('href')).toBe('https://spdx.org/licenses/MIT.html') 14 expect(link.text()).toBe('MIT') 15 }) 16 17 it('renders an invalid license as plain text', async () => { 18 const component = await mountSuspended(LicenseDisplay, { 19 props: { license: 'CustomLicense' }, 20 }) 21 const link = component.find('a') 22 expect(link.exists()).toBe(false) 23 expect(component.text()).toContain('CustomLicense') 24 }) 25 26 it('shows scales icon for valid license', async () => { 27 const component = await mountSuspended(LicenseDisplay, { 28 props: { license: 'MIT' }, 29 }) 30 const icon = component.find('.i-lucide\\:scale') 31 expect(icon.exists()).toBe(true) 32 }) 33 34 it('does not show scales icon for invalid license', async () => { 35 const component = await mountSuspended(LicenseDisplay, { 36 props: { license: 'CustomLicense' }, 37 }) 38 const icon = component.find('.i-lucide\\:scale') 39 expect(icon.exists()).toBe(false) 40 }) 41 }) 42 43 describe('compound expressions with OR', () => { 44 it('renders "MIT OR Apache-2.0" with both licenses linked', async () => { 45 const component = await mountSuspended(LicenseDisplay, { 46 props: { license: 'MIT OR Apache-2.0' }, 47 }) 48 const links = component.findAll('a') 49 expect(links).toHaveLength(2) 50 expect(links[0]?.attributes('href')).toBe('https://spdx.org/licenses/MIT.html') 51 expect(links[1]?.attributes('href')).toBe('https://spdx.org/licenses/Apache-2.0.html') 52 // Operator is rendered lowercase 53 expect(component.text().toLowerCase()).toContain('or') 54 }) 55 56 it('renders triple license choice correctly', async () => { 57 const component = await mountSuspended(LicenseDisplay, { 58 props: { license: '(BSD-2-Clause OR MIT OR Apache-2.0)' }, 59 }) 60 const links = component.findAll('a') 61 expect(links).toHaveLength(3) 62 }) 63 }) 64 65 describe('compound expressions with AND', () => { 66 it('renders "MIT AND Zlib" with both licenses linked', async () => { 67 const component = await mountSuspended(LicenseDisplay, { 68 props: { license: 'MIT AND Zlib' }, 69 }) 70 const links = component.findAll('a') 71 expect(links).toHaveLength(2) 72 expect(links[0]?.attributes('href')).toBe('https://spdx.org/licenses/MIT.html') 73 expect(links[1]?.attributes('href')).toBe('https://spdx.org/licenses/Zlib.html') 74 // Operator is rendered lowercase 75 expect(component.text().toLowerCase()).toContain('and') 76 }) 77 }) 78 79 describe('compound expressions with WITH', () => { 80 it('renders license with exception', async () => { 81 const component = await mountSuspended(LicenseDisplay, { 82 props: { license: 'GPL-2.0-only WITH Classpath-exception-2.0' }, 83 }) 84 // GPL-2.0-only is a valid license, Classpath-exception-2.0 is an exception (not a license) 85 const links = component.findAll('a') 86 expect(links.length).toBeGreaterThanOrEqual(1) 87 expect(links[0]?.attributes('href')).toBe('https://spdx.org/licenses/GPL-2.0-only.html') 88 // Operator is rendered lowercase 89 expect(component.text().toLowerCase()).toContain('with') 90 }) 91 }) 92 93 describe('mixed valid and invalid', () => { 94 it('renders valid licenses as links and invalid as text', async () => { 95 const component = await mountSuspended(LicenseDisplay, { 96 props: { license: 'MIT OR CustomLicense' }, 97 }) 98 const links = component.findAll('a') 99 expect(links).toHaveLength(1) 100 expect(links[0]?.text()).toBe('MIT') 101 expect(component.text()).toContain('CustomLicense') 102 }) 103 104 it('shows scales icon when at least one license is valid', async () => { 105 const component = await mountSuspended(LicenseDisplay, { 106 props: { license: 'CustomLicense OR MIT' }, 107 }) 108 const icon = component.find('.i-lucide\\:scale') 109 expect(icon.exists()).toBe(true) 110 }) 111 }) 112 113 describe('parentheses', () => { 114 it('strips parentheses from expressions for cleaner display', async () => { 115 const component = await mountSuspended(LicenseDisplay, { 116 props: { license: '(MIT OR Apache-2.0)' }, 117 }) 118 // Parentheses are stripped for cleaner display 119 expect(component.text()).not.toContain('(') 120 expect(component.text()).not.toContain(')') 121 const links = component.findAll('a') 122 expect(links).toHaveLength(2) 123 }) 124 }) 125 126 describe('real-world examples', () => { 127 it('handles rc package license: (BSD-2-Clause OR MIT OR Apache-2.0)', async () => { 128 const component = await mountSuspended(LicenseDisplay, { 129 props: { license: '(BSD-2-Clause OR MIT OR Apache-2.0)' }, 130 }) 131 const links = component.findAll('a') 132 expect(links).toHaveLength(3) 133 expect(links.map(l => l.text())).toEqual(['BSD-2-Clause', 'MIT', 'Apache-2.0']) 134 }) 135 136 it('handles jszip package license: (MIT OR GPL-3.0-or-later)', async () => { 137 const component = await mountSuspended(LicenseDisplay, { 138 props: { license: '(MIT OR GPL-3.0-or-later)' }, 139 }) 140 const links = component.findAll('a') 141 expect(links).toHaveLength(2) 142 }) 143 144 it('handles pako package license: (MIT AND Zlib)', async () => { 145 const component = await mountSuspended(LicenseDisplay, { 146 props: { license: '(MIT AND Zlib)' }, 147 }) 148 const links = component.findAll('a') 149 expect(links).toHaveLength(2) 150 }) 151 }) 152})