From b01779bcd532fe122e3d01828b1a8ebe9ff93f41 Mon Sep 17 00:00:00 2001 From: Dominic Saadi Date: Sat, 30 Dec 2023 18:37:16 +0000 Subject: [PATCH] chore(crwa): add e2e tests --- .github/workflows/ci.yml | 76 ++++++++++++ packages/create-redwood-app/.babelrc.js | 2 - packages/create-redwood-app/jest.config.js | 8 ++ packages/create-redwood-app/package.json | 6 +- .../scripts/setUpTestProject.mjs | 36 ++++++ .../{ => scripts}/tsToJS.mjs | 6 +- .../templates/js/.editorconfig | 3 - .../templates/js/web/jsconfig.json | 3 +- .../create-redwood-app/tests/e2e.test.mjs | 108 ++++++++++++++++++ .../create-redwood-app/tests/e2e_prompts.sh | 42 +++++++ .../tests/e2e_prompts_git.sh | 38 ++++++ .../create-redwood-app/tests/e2e_prompts_m.sh | 39 +++++++ .../tests/e2e_prompts_overwrite.sh | 49 ++++++++ .../tests/e2e_prompts_ts.sh | 39 +++++++ .../{template.test.js => templates.test.mjs} | 9 +- 15 files changed, 451 insertions(+), 13 deletions(-) delete mode 100644 packages/create-redwood-app/.babelrc.js create mode 100644 packages/create-redwood-app/jest.config.js create mode 100644 packages/create-redwood-app/scripts/setUpTestProject.mjs rename packages/create-redwood-app/{ => scripts}/tsToJS.mjs (94%) create mode 100644 packages/create-redwood-app/tests/e2e.test.mjs create mode 100755 packages/create-redwood-app/tests/e2e_prompts.sh create mode 100755 packages/create-redwood-app/tests/e2e_prompts_git.sh create mode 100755 packages/create-redwood-app/tests/e2e_prompts_m.sh create mode 100755 packages/create-redwood-app/tests/e2e_prompts_overwrite.sh create mode 100755 packages/create-redwood-app/tests/e2e_prompts_ts.sh rename packages/create-redwood-app/tests/{template.test.js => templates.test.mjs} (96%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1bd24a1b7dde..3ebee7b3521d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -701,3 +701,79 @@ jobs: steps: - run: echo "Skipped" + + crwa: + needs: check + + name: 🌲 Create Redwood App + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: ⬢ Enable Corepack + run: corepack enable + + - name: ⬢ Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: 🐈 Set up yarn cache + uses: ./.github/actions/set-up-yarn-cache + + - name: 🐈 Yarn install + run: yarn install --inline-builds + env: + GITHUB_TOKEN: ${{ github.token }} + + - name: 🏗️ Build + run: yarn build + + - name: Set up test project + run: | + yarn build:pack + PROJECT_PATH=$(yarn set-up-test-project) + echo "PROJECT_PATH=$PROJECT_PATH" >> $GITHUB_ENV + working-directory: ./packages/create-redwood-app + env: + YARN_ENABLE_IMMUTABLE_INSTALLS: false + + - name: Set up git + run: | + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + + - name: e2e test + run: yarn test e2e + working-directory: ./packages/create-redwood-app + env: + PROJECT_PATH: ${{ env.PROJECT_PATH }} + + - name: Prompt tests + run: | + sudo apt-get update + sudo apt-get install expect + + ./tests/e2e_prompts.sh + sleep 1 + ./tests/e2e_prompts_git.sh + sleep 1 + ./tests/e2e_prompts_m.sh + sleep 1 + ./tests/e2e_prompts_ts.sh + sleep 1 + ./tests/e2e_prompts_overwrite.sh + working-directory: ./packages/create-redwood-app + env: + PROJECT_PATH: ${{ env.PROJECT_PATH }} + + crwa-skip: + needs: detect-changes + if: needs.detect-changes.outputs.onlydocs == 'true' + + name: 🌲 Create Redwood App + runs-on: ubuntu-latest + + steps: + - run: echo "Skipped" diff --git a/packages/create-redwood-app/.babelrc.js b/packages/create-redwood-app/.babelrc.js deleted file mode 100644 index 2958a991f2cd..000000000000 --- a/packages/create-redwood-app/.babelrc.js +++ /dev/null @@ -1,2 +0,0 @@ -// For testing only. -module.exports = { extends: '../../babel.config.js' } diff --git a/packages/create-redwood-app/jest.config.js b/packages/create-redwood-app/jest.config.js new file mode 100644 index 000000000000..2c638b714e5b --- /dev/null +++ b/packages/create-redwood-app/jest.config.js @@ -0,0 +1,8 @@ +/** @type {import('jest').Config} */ +const config = { + testMatch: ['/tests/*.test.mjs'], + testPathIgnorePatterns: ['/node_modules/', '/templates/'], + transform: {}, +} + +module.exports = config diff --git a/packages/create-redwood-app/package.json b/packages/create-redwood-app/package.json index 69d2e838eb40..e90e7e89148e 100644 --- a/packages/create-redwood-app/package.json +++ b/packages/create-redwood-app/package.json @@ -17,8 +17,10 @@ "build:pack": "yarn pack -o create-redwood-app.tgz", "build:watch": "nodemon --watch src --ignore dist,template --exec \"yarn build\"", "prepublishOnly": "NODE_ENV=production yarn build", - "test": "yarn run jest tests", - "ts-to-js": "yarn node ./tsToJS.mjs" + "set-up-test-project": "node ./scripts/setUpTestProject.mjs", + "test": "node --experimental-vm-modules $(yarn bin jest) templates", + "test:e2e": "node --experimental-vm-modules $(yarn bin jest) e2e", + "ts-to-js": "yarn node ./scripts/tsToJS.mjs" }, "dependencies": { "@opentelemetry/api": "1.7.0", diff --git a/packages/create-redwood-app/scripts/setUpTestProject.mjs b/packages/create-redwood-app/scripts/setUpTestProject.mjs new file mode 100644 index 000000000000..464a9ac0cc2c --- /dev/null +++ b/packages/create-redwood-app/scripts/setUpTestProject.mjs @@ -0,0 +1,36 @@ +/* eslint-env node */ + +import { fileURLToPath } from 'node:url' + +import Configstore from 'configstore' +import { cd, fs, os, path, $ } from 'zx' + +const config = new Configstore('create-redwood-app') +let projectPath = config.get('projectPath') + +const projectExists = projectPath && (await fs.pathExists(projectPath)) + +if (!projectExists) { + const [timestamp] = new Date().toISOString().replace(/-|:/g, '_').split('.') + + projectPath = path.join(os.tmpdir(), `crwa_${timestamp}`) + + await fs.ensureDir(projectPath) + await $`yarn --cwd ${projectPath} init -2` + + config.set('projectPath', projectPath) +} + +const packagePath = fileURLToPath(new URL('../', import.meta.url)) +const tarball = 'create-redwood-app.tgz' + +await fs.move( + path.join(packagePath, tarball), + path.join(projectPath, tarball), + { overwrite: true } +) + +cd(projectPath) +await $`yarn add ./${tarball}` + +console.log(projectPath) diff --git a/packages/create-redwood-app/tsToJS.mjs b/packages/create-redwood-app/scripts/tsToJS.mjs similarity index 94% rename from packages/create-redwood-app/tsToJS.mjs rename to packages/create-redwood-app/scripts/tsToJS.mjs index 35356af4642f..990386cc8600 100644 --- a/packages/create-redwood-app/tsToJS.mjs +++ b/packages/create-redwood-app/scripts/tsToJS.mjs @@ -10,12 +10,12 @@ import fs from 'fs-extra' import { format } from 'prettier' const [TS_TEMPLATE_FILEPATH, JS_TEMPLATE_FILEPATH] = [ - new URL('./templates/ts', import.meta.url), - new URL('./templates/js', import.meta.url), + new URL('../templates/ts', import.meta.url), + new URL('../templates/js', import.meta.url), ].map(fileURLToPath) const { default: prettierConfig } = await import( - new URL('./templates/ts/prettier.config.js', import.meta.url) + new URL('../templates/ts/prettier.config.js', import.meta.url) ) // Handle node_modules, .yarn/install-state.gz. diff --git a/packages/create-redwood-app/templates/js/.editorconfig b/packages/create-redwood-app/templates/js/.editorconfig index 6f8974c2f100..ae10a5cce3b2 100644 --- a/packages/create-redwood-app/templates/js/.editorconfig +++ b/packages/create-redwood-app/templates/js/.editorconfig @@ -8,6 +8,3 @@ indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true - -[*.{md,html,mjml}] -trim_trailing_whitespace = false diff --git a/packages/create-redwood-app/templates/js/web/jsconfig.json b/packages/create-redwood-app/templates/js/web/jsconfig.json index 7ddf4c33675e..cfaf517b955a 100644 --- a/packages/create-redwood-app/templates/js/web/jsconfig.json +++ b/packages/create-redwood-app/templates/js/web/jsconfig.json @@ -37,7 +37,8 @@ "../node_modules/@testing-library" ], "types": [ - "jest-dom", + "jest", + "jest-dom" ], "jsx": "preserve" }, diff --git a/packages/create-redwood-app/tests/e2e.test.mjs b/packages/create-redwood-app/tests/e2e.test.mjs new file mode 100644 index 000000000000..488f3d5178c2 --- /dev/null +++ b/packages/create-redwood-app/tests/e2e.test.mjs @@ -0,0 +1,108 @@ +#!/usr/bin/env node +/* eslint-env node */ + +import { cd, fs, $ } from 'zx' + +const projectPath = await fs.realpath(process.env.PROJECT_PATH) + +cd(projectPath) + +describe('crwa', () => { + test('--help', async () => { + const p = await $`yarn create-redwood-app --help` + + expect(p.exitCode).toEqual(0) + expect(p.stdout).toMatchInlineSnapshot(` + "------------------------------------------------------------------ + 🌲⚡️ Welcome to RedwoodJS! ⚡️🌲 + ------------------------------------------------------------------ + Usage: create-redwood-app [option] + + Options: + --help Show help [boolean] + --typescript, --ts Generate a TypeScript project. + [boolean] [default: null] + --overwrite Create even if target directory isn't empty + [boolean] [default: false] + --telemetry Enables sending telemetry events for this create + command and all Redwood CLI commands + https://telemetry.redwoodjs.com + [boolean] [default: true] + --git-init, --git Initialize a git repository. [boolean] [default: null] + -m, --commit-message Commit message for the initial commit. + [string] [default: null] + -y, --yes Skip prompts and use defaults. + [boolean] [default: null] + --version Show version number [boolean] + + Examples: + create-redwood-app newapp + [?25l[?25h" + `) + expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h"`) + }) + + test('--version', async () => { + const p = await $`yarn create-redwood-app --version` + + expect(p.exitCode).toEqual(0) + expect(p.stdout).toMatchInlineSnapshot(` + "------------------------------------------------------------------ + 🌲⚡️ Welcome to RedwoodJS! ⚡️🌲 + ------------------------------------------------------------------ + 6.0.7 + [?25l[?25h" + `) + expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h"`) + }) + + test('--yes, -y', async () => { + const p = await $`yarn create-redwood-app ./redwood-app --yes` + + // await $`yarn create-redwood-app redwood-app -y` + // # `yarn pack` seems to ignore `.yarnrc.yml` + // # cp "$SCRIPT_DIR/templates/ts/.yarnrc.yml" "$CRWA_ESM_TESTING_DIR" + + expect(p.exitCode).toEqual(0) + expect(p.stdout).toMatchInlineSnapshot(` + "------------------------------------------------------------------ + 🌲⚡️ Welcome to RedwoodJS! ⚡️🌲 + ------------------------------------------------------------------ + [?25l⠋ Checking node and yarn compatibility + [?25h[?25l✔ Compatibility checks passed + [?25h✔ Creating your Redwood app in ./redwood-app based on command line argument + ✔ Using TypeScript based on command line flag + ✔ Will initialize a git repo based on command line flag + [?25l⠋ Creating project files + [?25h[?25l✔ Project files created + [?25h[?25l⠋ Initializing a git repo + [?25h[?25l✔ Initialized a git repo with commit message "Initial commit" + [?25h + Thanks for trying out Redwood! + + ⚡️ Get up and running fast with this Quick Start guide: https://redwoodjs.com/quick-start + + Fire it up! 🚀 + + > cd redwood-app + > yarn install + > yarn rw dev + + [?25l✔ Initialized a git repo with commit message "Initial commit" + [?25h" + `) + expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h"`) + + await fs.rm('./redwood-app', { recursive: true, force: true }) + }) + + test.failing('fails on unknown options', async () => { + try { + await $`yarn create-redwood-app --unknown-options`.timeout(2500) + // Fail the test if the function didn't throw. + expect(true).toEqual(false) + } catch (p) { + expect(p.exitCode).toEqual(1) + } + }) +}) diff --git a/packages/create-redwood-app/tests/e2e_prompts.sh b/packages/create-redwood-app/tests/e2e_prompts.sh new file mode 100755 index 000000000000..3099ee4c5744 --- /dev/null +++ b/packages/create-redwood-app/tests/e2e_prompts.sh @@ -0,0 +1,42 @@ +#!/usr/bin/expect + +set projectPath $env(PROJECT_PATH) + +if {$projectPath eq ""} { + puts "PROJECT_PATH is not set" + exit +} + +cd $projectPath + +set projectDirectory "redwood-app-prompt-test" + +spawn yarn create-redwood-app + +expect "Where would you like to create your Redwood app?" +send "$projectDirectory\n" + +expect "Select your preferred language" +# TypeScript +send "\n" + +expect "Do you want to initialize a git repo?" +# Yes +send "\n" + +expect "Enter a commit message" +send "first\n" + +expect eof +catch wait result +set exitStatus [lindex $result 3] + +if {$exitStatus == 0} { + puts "Success" + exec rm -rf $projectDirectory + exit 0 +} else { + puts "Error: The process failed with exit status $exitStatus" + exec rm -rf $projectDirectory + exit 1 +} diff --git a/packages/create-redwood-app/tests/e2e_prompts_git.sh b/packages/create-redwood-app/tests/e2e_prompts_git.sh new file mode 100755 index 000000000000..e43f514a2bce --- /dev/null +++ b/packages/create-redwood-app/tests/e2e_prompts_git.sh @@ -0,0 +1,38 @@ +#!/usr/bin/expect + +set projectPath $env(PROJECT_PATH) + +if {$projectPath eq ""} { + puts "PROJECT_PATH is not set" + exit +} + +cd $projectPath + +set projectDirectory "redwood-app-prompt-git-test" + +spawn yarn create-redwood-app --git + +expect "Where would you like to create your Redwood app?" +send "$projectDirectory\n" + +expect "Select your preferred language" +# TypeScript +send "\n" + +expect "Enter a commit message" +send "first\n" + +expect eof +catch wait result +set exitStatus [lindex $result 3] + +if {$exitStatus == 0} { + puts "Success" + exec rm -rf $projectDirectory + exit 0 +} else { + puts "Error: The process failed with exit status $exitStatus" + exec rm -rf $projectDirectory + exit 1 +} diff --git a/packages/create-redwood-app/tests/e2e_prompts_m.sh b/packages/create-redwood-app/tests/e2e_prompts_m.sh new file mode 100755 index 000000000000..c9c24613e0b1 --- /dev/null +++ b/packages/create-redwood-app/tests/e2e_prompts_m.sh @@ -0,0 +1,39 @@ +#!/usr/bin/expect + +set projectPath $env(PROJECT_PATH) + +if {$projectPath eq ""} { + puts "PROJECT_PATH is not set" + exit +} + +cd $projectPath + +set projectDirectory "redwood-app-prompt-m-test" + +spawn yarn create-redwood-app -m "first" + +expect "Where would you like to create your Redwood app?" +send "$projectDirectory\n" + +expect "Select your preferred language" +# TypeScript +send "\n" + +expect "Do you want to initialize a git repo?" +# Yes +send "\n" + +expect eof +catch wait result +set exitStatus [lindex $result 3] + +if {$exitStatus == 0} { + puts "Success" + exec rm -rf $projectDirectory + exit 0 +} else { + puts "Error: The process failed with exit status $exitStatus" + exec rm -rf $projectDirectory + exit 1 +} diff --git a/packages/create-redwood-app/tests/e2e_prompts_overwrite.sh b/packages/create-redwood-app/tests/e2e_prompts_overwrite.sh new file mode 100755 index 000000000000..ad8d890f0100 --- /dev/null +++ b/packages/create-redwood-app/tests/e2e_prompts_overwrite.sh @@ -0,0 +1,49 @@ +#!/usr/bin/expect + +set projectPath $env(PROJECT_PATH) + +if {$projectPath eq ""} { + puts "PROJECT_PATH is not set" + exit +} + +cd $projectPath + +# Make directory that needs to be overwritten. +set projectDirectory "redwood-app-prompt-overwrite-test" +exec mkdir $projectDirectory +exec touch $projectDirectory/README.md + +spawn yarn create-redwood-app + +expect "Where would you like to create your Redwood app?" +send "$projectDirectory\n" + +expect "Select your preferred language" +# TypeScript +send "\n" + +expect "Do you want to initialize a git repo?" +# Yes +send "\n" + +expect "Enter a commit message" +send "first\n" + +expect "How would you like to proceed?" +# Quit install +send "\n" + +expect eof +catch wait result +set exitStatus [lindex $result 3] + +if {$exitStatus == 1} { + puts "Success" + exec rm -rf $projectDirectory + exit 0 +} else { + puts "Error: The process failed with exit status $exitStatus" + exec rm -rf $projectDirectory + exit 1 +} diff --git a/packages/create-redwood-app/tests/e2e_prompts_ts.sh b/packages/create-redwood-app/tests/e2e_prompts_ts.sh new file mode 100755 index 000000000000..8a8f17c52847 --- /dev/null +++ b/packages/create-redwood-app/tests/e2e_prompts_ts.sh @@ -0,0 +1,39 @@ +#!/usr/bin/expect + +set projectPath $env(PROJECT_PATH) + +if {$projectPath eq ""} { + puts "PROJECT_PATH is not set" + exit +} + +cd $projectPath + +set projectDirectory "redwood-app-prompt-ts-test" + +spawn yarn create-redwood-app --ts + +expect "Where would you like to create your Redwood app?" +send "$projectDirectory\n" + +expect "Do you want to initialize a git repo?" +# Yes +send "\n" + +expect "Enter a commit message" +# Initial commit +send "\n" + +expect eof +catch wait result +set exitStatus [lindex $result 3] + +if {$exitStatus == 0} { + puts "Success" + exec rm -rf $projectDirectory + exit 0 +} else { + puts "Error: The process failed with exit status $exitStatus" + exec rm -rf $projectDirectory + exit 1 +} diff --git a/packages/create-redwood-app/tests/template.test.js b/packages/create-redwood-app/tests/templates.test.mjs similarity index 96% rename from packages/create-redwood-app/tests/template.test.js rename to packages/create-redwood-app/tests/templates.test.mjs index be6cd2cc29c6..a1bbfb76e13e 100644 --- a/packages/create-redwood-app/tests/template.test.js +++ b/packages/create-redwood-app/tests/templates.test.mjs @@ -1,8 +1,11 @@ +import { fileURLToPath } from 'node:url' import path from 'path' import klawSync from 'klaw-sync' -const TS_TEMPLATE_DIR = path.join(__dirname, '../templates', 'ts') +const TS_TEMPLATE_DIR = fileURLToPath( + new URL('../templates/ts', import.meta.url) +) describe('template', () => { it('files should not have changed unintentionally', () => { @@ -85,7 +88,9 @@ describe('template', () => { }) }) -const JS_TEMPLATE_DIR = path.join(__dirname, '../templates', 'js') +const JS_TEMPLATE_DIR = fileURLToPath( + new URL('../templates/js', import.meta.url) +) describe('JS template', () => { it('files should not have changed unintentionally', () => {