Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(glob): properly handles tailing comma #8181

Merged
merged 2 commits into from May 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
253 changes: 203 additions & 50 deletions packages/vite/src/node/__tests__/plugins/importGlob/parse.test.ts
Expand Up @@ -8,7 +8,11 @@ async function run(input: string) {
process.cwd(),
(id) => id
)
return items.map((i) => ({ globs: i.globs, options: i.options }))
return items.map((i) => ({
globs: i.globs,
options: i.options,
start: i.start
}))
}

async function runError(input: string) {
Expand All @@ -23,31 +27,66 @@ describe('parse positives', async () => {
it('basic', async () => {
expect(
await run(`
import.meta.importGlob(\'./modules/*.ts\')
import.meta.glob(\'./modules/*.ts\')
`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"./modules/*.ts",
],
"options": {},
"start": 5,
},
]
`)
).toMatchInlineSnapshot('[]')
})

it('array', async () => {
expect(
await run(`
import.meta.importGlob([\'./modules/*.ts\', './dir/*.{js,ts}\'])
import.meta.glob([\'./modules/*.ts\', './dir/*.{js,ts}\'])
`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"./modules/*.ts",
"./dir/*.{js,ts}",
],
"options": {},
"start": 5,
},
]
`)
).toMatchInlineSnapshot('[]')
})

it('options with multilines', async () => {
expect(
await run(`
import.meta.importGlob([
import.meta.glob([
\'./modules/*.ts\',
"!./dir/*.{js,ts}"
], {
eager: true,
import: 'named'
})
`)
).toMatchInlineSnapshot('[]')
).toMatchInlineSnapshot(`
[
{
"globs": [
"./modules/*.ts",
"!./dir/*.{js,ts}",
],
"options": {
"eager": true,
"import": "named",
},
"start": 5,
},
]
`)
})

it('options with multilines', async () => {
Expand All @@ -68,6 +107,7 @@ describe('parse positives', async () => {
"/dir/**",
],
"options": {},
"start": 21,
},
]
`)
Expand Down Expand Up @@ -98,6 +138,99 @@ describe('parse positives', async () => {
"raw": true,
},
},
"start": 21,
},
]
`)
})

it('object properties - 1', async () => {
expect(
await run(`
export const pageFiles = {
'.page': import.meta.glob('/**/*.page.*([a-zA-Z0-9])')
};`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"/**/*.page.*([a-zA-Z0-9])",
],
"options": {},
"start": 47,
},
]
`)
})

it('object properties - 2', async () => {
expect(
await run(`
export const pageFiles = {
'.page': import.meta.glob('/**/*.page.*([a-zA-Z0-9])'),
};`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"/**/*.page.*([a-zA-Z0-9])",
],
"options": {},
"start": 47,
},
]
`)
})

it('object properties - 3', async () => {
expect(
await run(`
export const pageFiles = {
'.page.client': import.meta.glob('/**/*.page.client.*([a-zA-Z0-9])'),
'.page.server': import.meta.glob('/**/*.page.server.*([a-zA-Z0-9])'),
};`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"/**/*.page.client.*([a-zA-Z0-9])",
],
"options": {},
"start": 54,
},
{
"globs": [
"/**/*.page.server.*([a-zA-Z0-9])",
],
"options": {},
"start": 130,
},
]
`)
})

it('array item', async () => {
expect(
await run(`
export const pageFiles = [
import.meta.glob('/**/*.page.client.*([a-zA-Z0-9])'),
import.meta.glob('/**/*.page.server.*([a-zA-Z0-9])'),
]`)
).toMatchInlineSnapshot(`
[
{
"globs": [
"/**/*.page.client.*([a-zA-Z0-9])",
],
"options": {},
"start": 38,
},
{
"globs": [
"/**/*.page.server.*([a-zA-Z0-9])",
],
"options": {},
"start": 98,
},
]
`)
Expand All @@ -106,97 +239,117 @@ describe('parse positives', async () => {

describe('parse negatives', async () => {
it('syntax error', async () => {
expect(await runError('import.meta.importGlob(')).toMatchInlineSnapshot(
'undefined'
expect(await runError('import.meta.glob(')).toMatchInlineSnapshot(
'[SyntaxError: Unexpected token (1:17)]'
)
})

it('empty', async () => {
expect(await runError('import.meta.importGlob()')).toMatchInlineSnapshot(
'undefined'
expect(await runError('import.meta.glob()')).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected 1-2 arguments, but got 0]'
)
})

it('3 args', async () => {
expect(
await runError('import.meta.importGlob("", {}, {})')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("", {}, {})')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected 1-2 arguments, but got 3]'
)
})

it('in string', async () => {
expect(await runError('"import.meta.importGlob()"')).toBeUndefined()
expect(await runError('"import.meta.glob()"')).toBeUndefined()
})

it('variable', async () => {
expect(await runError('import.meta.importGlob(hey)')).toMatchInlineSnapshot(
'undefined'
expect(await runError('import.meta.glob(hey)')).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
})

it('template', async () => {
// eslint-disable-next-line no-template-curly-in-string
expect(
await runError('import.meta.importGlob(`hi ${hey}`)')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob(`hi ${hey}`)')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
})

it('be string', async () => {
expect(await runError('import.meta.importGlob(1)')).toMatchInlineSnapshot(
'undefined'
expect(await runError('import.meta.glob(1)')).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected glob to be a string, but got "number"]'
)
})

it('be array variable', async () => {
expect(await runError('import.meta.glob([hey])')).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
expect(
await runError('import.meta.importGlob([hey])')
).toMatchInlineSnapshot('undefined')
expect(
await runError('import.meta.importGlob(["1", hey])')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob(["1", hey])')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
})

it('options', async () => {
expect(
await runError('import.meta.importGlob("hey", hey)')
).toMatchInlineSnapshot('undefined')
expect(
await runError('import.meta.importGlob("hey", [])')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("hey", hey)')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected the second argument o to be a object literal, but got "Identifier"]'
)
expect(await runError('import.meta.glob("hey", [])')).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected the second argument o to be a object literal, but got "ArrayExpression"]'
)
})

it('options props', async () => {
expect(
await runError('import.meta.importGlob("hey", { hey: 1 })')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("hey", { hey: 1 })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Unknown options hey]'
)
expect(
await runError('import.meta.importGlob("hey", { import: hey })')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("hey", { import: hey })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
expect(
await runError('import.meta.importGlob("hey", { eager: 123 })')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("hey", { eager: 123 })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected the type of option "eager" to be "boolean", but got "number"]'
)
})

it('options query', async () => {
expect(
await runError(
'import.meta.importGlob("./*.js", { as: "raw", query: "hi" })'
)
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("./*.js", { as: "raw", query: "hi" })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Options "as" and "query" cannot be used together]'
)
expect(
await runError('import.meta.importGlob("./*.js", { query: 123 })')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("./*.js", { query: 123 })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Expected query to be a string, but got "number"]'
)
expect(
await runError('import.meta.importGlob("./*.js", { query: { foo: {} } })')
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("./*.js", { query: { foo: {} } })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
expect(
await runError(
'import.meta.importGlob("./*.js", { query: { foo: hey } })'
)
).toMatchInlineSnapshot('undefined')
await runError('import.meta.glob("./*.js", { query: { foo: hey } })')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
expect(
await runError(
'import.meta.importGlob("./*.js", { query: { foo: 123, ...a } })'
'import.meta.glob("./*.js", { query: { foo: 123, ...a } })'
)
).toMatchInlineSnapshot('undefined')
).toMatchInlineSnapshot(
'[Error: Invalid glob import syntax: Could only use literals]'
)
})
})