generate-test.mjs 3.2 KB

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