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