github.com/evanw/esbuild@v0.21.4/scripts/deno-tests.js (about)

     1  // To run this, you must first build the Deno package with "make platform-deno"
     2  import * as esbuildNative from '../deno/mod.js'
     3  import * as esbuildWASM from '../deno/wasm.js'
     4  import * as path from 'https://deno.land/std@0.95.0/path/mod.ts'
     5  import * as asserts from 'https://deno.land/std@0.95.0/testing/asserts.ts'
     6  
     7  const __dirname = path.dirname(path.fromFileUrl(import.meta.url))
     8  const rootTestDir = path.join(__dirname, '.deno-tests')
     9  const wasmModule = await WebAssembly.compile(await Deno.readFile(path.join(__dirname, '..', 'deno', 'esbuild.wasm')))
    10  
    11  try {
    12    Deno.removeSync(rootTestDir, { recursive: true })
    13  } catch {
    14  }
    15  Deno.mkdirSync(rootTestDir, { recursive: true })
    16  
    17  function test(name, backends, fn) {
    18    // Note: Do not try to add a timeout for the tests below. It turns out that
    19    // calling "setTimeout" from within "Deno.test" changes how Deno waits for
    20    // promises in a way that masks problems that would otherwise occur. We want
    21    // test coverage for the way that people will likely be using these API calls.
    22    //
    23    // Specifically tests that Deno would otherwise have failed with "error:
    24    // Promise resolution is still pending but the event loop has already
    25    // resolved" were being allowed to pass instead. See this issue for more
    26    // information: https://github.com/evanw/esbuild/issues/3682
    27  
    28    for (const backend of backends) {
    29      switch (backend) {
    30        case 'native':
    31          Deno.test(name + '-native', async () => {
    32            let testDir = path.join(rootTestDir, name + '-native')
    33            await Deno.mkdir(testDir, { recursive: true })
    34            try {
    35              await fn({ esbuild: esbuildNative, testDir })
    36              await Deno.remove(testDir, { recursive: true }).catch(() => null)
    37            } finally {
    38              await esbuildNative.stop()
    39            }
    40          })
    41          break
    42  
    43        case 'wasm-main':
    44          Deno.test(name + '-wasm-main', async () => {
    45            let testDir = path.join(rootTestDir, name + '-wasm-main')
    46            await esbuildWASM.initialize({ wasmModule, worker: false })
    47            await Deno.mkdir(testDir, { recursive: true })
    48            try {
    49              await fn({ esbuild: esbuildWASM, testDir })
    50              await Deno.remove(testDir, { recursive: true }).catch(() => null)
    51            } finally {
    52              await esbuildWASM.stop()
    53            }
    54          })
    55          break
    56  
    57        case 'wasm-worker':
    58          Deno.test(name + '-wasm-worker', async () => {
    59            let testDir = path.join(rootTestDir, name + '-wasm-worker')
    60            await esbuildWASM.initialize({ wasmModule, worker: true })
    61            await Deno.mkdir(testDir, { recursive: true })
    62            try {
    63              await fn({ esbuild: esbuildWASM, testDir })
    64              await Deno.remove(testDir, { recursive: true }).catch(() => null)
    65            } finally {
    66              await esbuildWASM.stop()
    67            }
    68          })
    69          break
    70      }
    71    }
    72  }
    73  
    74  window.addEventListener("unload", (e) => {
    75    try {
    76      Deno.removeSync(rootTestDir, { recursive: true })
    77    } catch {
    78      // root test dir possibly already removed, so ignore
    79    }
    80  })
    81  
    82  // This test doesn't run in WebAssembly because it requires file system access
    83  test("basicBuild", ['native'], async ({ esbuild, testDir }) => {
    84    const input = path.join(testDir, 'in.ts')
    85    const dep = path.join(testDir, 'dep.ts')
    86    const output = path.join(testDir, 'out.ts')
    87    await Deno.writeTextFile(input, 'import dep from "./dep.ts"; export default dep === 123')
    88    await Deno.writeTextFile(dep, 'export default 123')
    89    await esbuild.build({
    90      entryPoints: [input],
    91      bundle: true,
    92      outfile: output,
    93      format: 'esm',
    94    })
    95    const result = await import(path.toFileUrl(output))
    96    asserts.assertStrictEquals(result.default, true)
    97  })
    98  
    99  test("basicContext", ['native'], async ({ esbuild, testDir }) => {
   100    const input = path.join(testDir, 'in.ts')
   101    const dep = path.join(testDir, 'dep.ts')
   102    const output = path.join(testDir, 'out.ts')
   103    await Deno.writeTextFile(input, 'import dep from "./dep.ts"; export default dep === 123')
   104    await Deno.writeTextFile(dep, 'export default 123')
   105    const ctx = await esbuild.context({
   106      entryPoints: ['in.ts'],
   107      bundle: true,
   108      outfile: output,
   109      format: 'esm',
   110      absWorkingDir: testDir,
   111    })
   112    const { errors, warnings } = await ctx.rebuild()
   113    asserts.assertStrictEquals(errors.length, 0)
   114    asserts.assertStrictEquals(warnings.length, 0)
   115    await ctx.dispose()
   116    const result = await import(path.toFileUrl(output))
   117    asserts.assertStrictEquals(result.default, true)
   118  })
   119  
   120  test("basicPlugin", ['native', 'wasm-main', 'wasm-worker'], async ({ esbuild }) => {
   121    const build = await esbuild.build({
   122      entryPoints: ['<entry>'],
   123      bundle: true,
   124      format: 'esm',
   125      write: false,
   126      plugins: [{
   127        name: 'plug',
   128        setup(build) {
   129          build.onResolve({ filter: /^<.*>$/ }, args => ({ path: args.path, namespace: '<>' }))
   130          build.onLoad({ filter: /^<entry>$/ }, () => ({ contents: `import dep from "<dep>"; export default dep === 123` }))
   131          build.onLoad({ filter: /^<dep>$/ }, () => ({ contents: `export default 123` }))
   132        },
   133      }],
   134    })
   135    const result = await import('data:application/javascript;base64,' + btoa(build.outputFiles[0].text))
   136    asserts.assertStrictEquals(result.default, true)
   137  })
   138  
   139  test("basicTransform", ['native', 'wasm-main', 'wasm-worker'], async ({ esbuild }) => {
   140    const ts = 'let x: number = 1+2'
   141    const result = await esbuild.transform(ts, { loader: 'ts' })
   142    asserts.assertStrictEquals(result.code, 'let x = 1 + 2;\n')
   143  })
   144  
   145  // This test doesn't run in WebAssembly because of a stack overflow
   146  test("largeTransform", ['native'], async ({ esbuild }) => {
   147    // This should be large enough to be bigger than Deno's write buffer
   148    let x = '0'
   149    for (let i = 0; i < 1000; i++) x += '+' + i
   150    x += ','
   151    let y = 'return['
   152    for (let i = 0; i < 1000; i++) y += x
   153    y += ']'
   154    const result = await esbuild.build({
   155      stdin: {
   156        contents: y,
   157      },
   158      write: false,
   159      minifyWhitespace: true,
   160    })
   161    asserts.assertStrictEquals(result.outputFiles[0].text, y.slice(0, -2) + '];\n')
   162  })
   163  
   164  test("analyzeMetafile", ['native', 'wasm-main', 'wasm-worker'], async ({ esbuild }) => {
   165    const result = await esbuild.analyzeMetafile({
   166      outputs: {
   167        'out.js': {
   168          bytes: 4096,
   169          inputs: {
   170            'in.js': {
   171              bytesInOutput: 1024,
   172            },
   173          },
   174        },
   175      },
   176    })
   177    asserts.assertStrictEquals(result, `
   178    out.js    4.0kb  100.0%
   179     └ in.js  1.0kb   25.0%
   180  `)
   181  })