import MagicString, { SourceMap } from 'magic-string'
import { beforeEach, describe, expect, it } from 'vitest'
import { parse } from '@astrojs/compiler'
import * as utils from '@astrojs/compiler/utils'
import { MagicSFC as MagicAstroSFC, magicAstroSfcOptions } from '../src/astro/sfc'
import { astroScript, astroStyle, astroTemplate, completeAstroComponent } from './utils'
describe('Magic Astro SFC', async () => {
beforeEach(() => {
// Set default parser for MagicAstroSFC
magicAstroSfcOptions.parser = parse
magicAstroSfcOptions.parserUtils = utils
})
it('Can create the class', async () => {
const sfc = new MagicAstroSFC(astroTemplate)
expect(sfc.toString()).toBe(astroTemplate)
})
it('Cannot create a Magic astro SFC without a parser function', async () => {
magicAstroSfcOptions.parser = undefined
const sfc = new MagicAstroSFC(astroScript)
try {
await sfc.parse()
throw new Error('Code should node reach this point!')
}
catch (e) {
expect(e.message).toBe('You must provide a `parser` function (from @astrojs/compiler) in options when using MagicAstroSFC.')
}
})
it('Cannot create a Magic astro SFC without a parserUtils object', async () => {
magicAstroSfcOptions.parserUtils = undefined
const sfc = new MagicAstroSFC(astroScript)
try {
await sfc.parse()
throw new Error('Code should node reach this point!')
}
catch (e) {
expect(e.message).toBe('You must provide a `parserUtils` object (from @astrojs/compiler/utils) in options when using MagicAstroSFC.')
}
})
it('Can create the class from a MagicString', async () => {
const ms = new MagicString(astroScript)
const sfc = new MagicAstroSFC(ms)
await sfc.parse()
const appended = '\nlet secondTest: string'
sfc.scripts[0].append(appended)
expect(sfc.toString()).toBe(``)
})
it('Can get a sourcemap', async () => {
const sfc = new MagicAstroSFC(astroScript)
await sfc.parse()
expect(sfc.getSourcemap()).toBeInstanceOf(SourceMap)
})
it('Can parse a '
const expectedScript = ''
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].overwrite(27, 38, 'UpdatedComponent')
expect(sfc.toString()).toBe(expectedScript)
})
it('Can manipulate a '
const expectedStyle = ''
const sfc = new MagicAstroSFC(originalStyle)
await sfc.parse()
sfc.styles[0].overwrite(18, 21, 'blue')
expect(sfc.toString()).toBe(expectedStyle)
})
it('Can manipulate nested elements in a block', async () => {
const originalNestedTemplate = '
Hello, world!
'
const expectedNestedTemplate = 'Hello, Mars!
'
const sfc = new MagicAstroSFC(originalNestedTemplate)
await sfc.parse()
sfc.templates[0].overwrite(18, 23, 'Mars')
expect(sfc.toString()).toBe(expectedNestedTemplate)
})
it('Can handle empty blocks', async () => {
const emptyScript = ''
const emptyTemplate = '\n\n'
const emptyStyle = ''
const sfc = new MagicAstroSFC(`${emptyScript}\n${emptyTemplate}\n${emptyStyle}`)
await sfc.parse()
// Astro SFC parser does detect empty script blocks
expect(sfc.scripts.length).toBeTruthy()
// Astro SFC parser does detect empty style blocks
expect(sfc.styles.length).toBeTruthy()
// Astro SFC parser does not detect empty HTML
expect(sfc.templates.length).toBeFalsy()
})
it('Can append content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].append(appended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can appendLeft content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].appendLeft(0, appended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can appendRight content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].appendRight(baseContent.length, appended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can prepend content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].prepend(prepended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can prependLeft content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].prependLeft(0, prepended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can prependRight content to a `
const expectedScript = ``
const sfc = new MagicAstroSFC(originalScript)
await sfc.parse()
sfc.scripts[0].prependRight(baseContent.length, prepended)
expect(sfc.toString()).toBe(expectedScript)
})
it('Can manipulate every block of an SFC', async () => {
const originalSFC = `{{ msg }}
`
const expectedSFC = `{{ updatedMsg }}
`
const sfc = new MagicAstroSFC(originalSFC)
await sfc.parse()
sfc.templates[0].overwrite(8, 11, 'updatedMsg')
sfc.scripts[0].overwrite(61, 66, 'Mars')
sfc.styles[0].overwrite(18, 21, 'blue')
expect(sfc.toString()).toBe(expectedSFC)
})
it('Uses all methods on different blocks', async () => {
const originalSFC = `Hello, world!
`
const expectedSFC = `Hi, Mars!
Hello, world!
`
const sfc = new MagicAstroSFC(originalSFC)
await sfc.parse()
// Manipulate block
sfc.templates[0].prepend('Hi, Mars!\n')
// Manipulate