generate-test.mjs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #!/usr/bin/env node
  2. /* eslint-disable no-console, import/no-extraneous-dependencies */
  3. import prompts from 'prompts'
  4. import fs from 'node:fs/promises'
  5. /**
  6. * Utility function that strips indentation from multi-line strings.
  7. * Inspired from https://github.com/dmnd/dedent.
  8. */
  9. function dedent (strings, ...parts) {
  10. const nonSpacingChar = /\S/m.exec(strings[0])
  11. if (nonSpacingChar == null) return ''
  12. const indent = nonSpacingChar.index - strings[0].lastIndexOf('\n', nonSpacingChar.index) - 1
  13. const dedentEachLine = str => str.split('\n').map((line, i) => line.slice(i && indent)).join('\n')
  14. let returnLines = dedentEachLine(strings[0].slice(nonSpacingChar.index), indent)
  15. for (let i = 1; i < strings.length; i++) {
  16. returnLines += String(parts[i - 1]) + dedentEachLine(strings[i], indent)
  17. }
  18. return returnLines
  19. }
  20. const packageNames = await fs.readdir(new URL('../packages/@uppy', import.meta.url))
  21. const unwantedPackages = ['core', 'companion', 'redux-dev-tools', 'utils']
  22. const { name } = await prompts({
  23. type: 'text',
  24. name: 'name',
  25. message: 'What should the name of the test be (e.g `dashboard-tus`)?',
  26. validate: (value) => /^[a-z|-]+$/i.test(value),
  27. })
  28. const { packages } = await prompts({
  29. type: 'multiselect',
  30. name: 'packages',
  31. message: 'What packages do you want to test?',
  32. hint: '@uppy/core is automatically included',
  33. choices: packageNames
  34. .filter((pkg) => !unwantedPackages.includes(pkg))
  35. .map((pkg) => ({ title: pkg, value: pkg })),
  36. })
  37. const camelcase = (str) => str
  38. .toLowerCase()
  39. .replace(/([-][a-z])/g, (group) => group.toUpperCase().replace('-', ''))
  40. const testUrl = new URL(`cypress/integration/${name}.spec.ts`, import.meta.url)
  41. const test = dedent`
  42. describe('${name}', () => {
  43. beforeEach(() => {
  44. cy.visit('/${name}')
  45. })
  46. })
  47. `
  48. const htmlUrl = new URL(`clients/${name}/index.html`, import.meta.url)
  49. const html = dedent`
  50. <!doctype html>
  51. <html lang="en">
  52. <head>
  53. <meta charset="utf-8"/>
  54. <title>${name}</title>
  55. <script defer type="module" src="app.js"></script>
  56. </head>
  57. <body>
  58. <div id="app"></div>
  59. </body>
  60. </html>
  61. `
  62. const appUrl = new URL(`clients/${name}/app.js`, import.meta.url)
  63. // dedent is acting weird for this one but this formatting fixes it.
  64. const app = dedent`
  65. import Uppy from '@uppy/core'
  66. ${packages.map((pgk) => `import ${camelcase(pgk)} from '@uppy/${pgk}'`).join('\n')}
  67. const uppy = new Uppy()
  68. ${packages.map((pkg) => `.use(${camelcase(pkg)})`).join('\n\t')}
  69. // Keep this here to access uppy in tests
  70. window.uppy = uppy
  71. `
  72. await fs.writeFile(testUrl, test)
  73. await fs.mkdir(new URL(`clients/${name}`, import.meta.url))
  74. await fs.writeFile(htmlUrl, html)
  75. await fs.writeFile(appUrl, app)
  76. const homeUrl = new URL('clients/index.html', import.meta.url)
  77. const home = await fs.readFile(homeUrl, 'utf8')
  78. const newHome = home.replace(
  79. '</ul>',
  80. `\t<li><a href="${name}/index.html">${name}</a></li>\n\t\t\t</ul>`,
  81. )
  82. await fs.writeFile(homeUrl, newHome)
  83. const prettyPath = (url) => url.toString().split('uppy', 2)[1]
  84. console.log(`✅ Generated ${prettyPath(testUrl)}`)
  85. console.log(`✅ Generated ${prettyPath(htmlUrl)}`)
  86. console.log(`✅ Generated ${prettyPath(appUrl)}`)
  87. console.log(`✅ Updated ${prettyPath(homeUrl)}`)