Skip to content

Commit 35b858a

Browse files
authored
chore(crwa): add e2e tests for create-redwood-app (#9783)
Similar to #9766, I was working on ESM and started with CRWA since it's the easiest package, and there really weren't any tests for it. (I think other tests, like the cypress e2e test, use it, so I think we'd catch if it totally broke, but it's not trivial to run that one locally for quick feedback.) This PR adds a couple of e2e tests. To run them locally: ```bash # Build the framework yarn build # Tar CRWA cd ./packages/create-redwood-app yarn build:pack # Create a test project to run the e2e tests on PROJECT_PATH=$(yarn set-up-test-project) # Run the jest test or a prompt test PROJECT_PATH=$PROJECT_PATH yarn test:e2e PROJECT_PATH=$PROJECT_PATH ./tests/e2e_prompts.sh ``` Some of the CRWA e2e tests use [expect](https://core.tcl-lang.org/expect/index). I tried testing the prompts using `zx`, Node's `child_process`, etc and writing to `process.stdin`, but it never worked consistently and when it did it was hacky. Expect more or less just worked. Those tests are limited to Ubuntu, but better than the nothing we had before. In making the ts-to-js script ESM, I was running it and it seems like the JS template was a little out of date. So updated that as well. A couple of other notes - i got rid of the `.babelrc.js` file which was only there for jest. all the tests are ESM now - since i added a new script (setUpTestProject), i made a new scripts directory and added tsToJS to it too - one e2e test i don't have yet is for when the node version is lower or higher. i couldn't seem to set it up with expect. will keep thinking about how to test that one - it's likely that the expect tests could be consolidated or just be better in general - every invocation of `yarn create-redwood-app` seems to be printing some escape codes to `stderr`: ```js const p = await $`yarn create-redwood-app --help` expect(p.stderr).toMatchInlineSnapshot(`"�[?25l�[?25h"`) ``` - `yarn create-redwood-app --version` prints the banner and some escape codes; both seem unnecessary: ```js 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" `) ```
1 parent 2bba6f8 commit 35b858a

15 files changed

+451
-13
lines changed

.github/workflows/ci.yml

+76
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,79 @@ jobs:
701701

702702
steps:
703703
- run: echo "Skipped"
704+
705+
crwa:
706+
needs: check
707+
708+
name: 🌲 Create Redwood App
709+
runs-on: ubuntu-latest
710+
711+
steps:
712+
- uses: actions/checkout@v4
713+
714+
- name: ⬢ Enable Corepack
715+
run: corepack enable
716+
717+
- name: ⬢ Set up Node.js
718+
uses: actions/setup-node@v4
719+
with:
720+
node-version: 20
721+
722+
- name: 🐈 Set up yarn cache
723+
uses: ./.github/actions/set-up-yarn-cache
724+
725+
- name: 🐈 Yarn install
726+
run: yarn install --inline-builds
727+
env:
728+
GITHUB_TOKEN: ${{ github.token }}
729+
730+
- name: 🏗️ Build
731+
run: yarn build
732+
733+
- name: Set up test project
734+
run: |
735+
yarn build:pack
736+
PROJECT_PATH=$(yarn set-up-test-project)
737+
echo "PROJECT_PATH=$PROJECT_PATH" >> $GITHUB_ENV
738+
working-directory: ./packages/create-redwood-app
739+
env:
740+
YARN_ENABLE_IMMUTABLE_INSTALLS: false
741+
742+
- name: Set up git
743+
run: |
744+
git config --global user.email "[email protected]"
745+
git config --global user.name "Your Name"
746+
747+
- name: e2e test
748+
run: yarn test e2e
749+
working-directory: ./packages/create-redwood-app
750+
env:
751+
PROJECT_PATH: ${{ env.PROJECT_PATH }}
752+
753+
- name: Prompt tests
754+
run: |
755+
sudo apt-get update
756+
sudo apt-get install expect
757+
758+
./tests/e2e_prompts.sh
759+
sleep 1
760+
./tests/e2e_prompts_git.sh
761+
sleep 1
762+
./tests/e2e_prompts_m.sh
763+
sleep 1
764+
./tests/e2e_prompts_ts.sh
765+
sleep 1
766+
./tests/e2e_prompts_overwrite.sh
767+
working-directory: ./packages/create-redwood-app
768+
env:
769+
PROJECT_PATH: ${{ env.PROJECT_PATH }}
770+
771+
crwa-skip:
772+
needs: detect-changes
773+
if: needs.detect-changes.outputs.onlydocs == 'true'
774+
775+
name: 🌲 Create Redwood App
776+
runs-on: ubuntu-latest
777+
778+
steps:
779+
- run: echo "Skipped"

packages/create-redwood-app/.babelrc.js

-2
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** @type {import('jest').Config} */
2+
const config = {
3+
testMatch: ['<rootDir>/tests/*.test.mjs'],
4+
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/templates/'],
5+
transform: {},
6+
}
7+
8+
module.exports = config

packages/create-redwood-app/package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
"build:pack": "yarn pack -o create-redwood-app.tgz",
1818
"build:watch": "nodemon --watch src --ignore dist,template --exec \"yarn build\"",
1919
"prepublishOnly": "NODE_ENV=production yarn build",
20-
"test": "yarn run jest tests",
21-
"ts-to-js": "yarn node ./tsToJS.mjs"
20+
"set-up-test-project": "node ./scripts/setUpTestProject.mjs",
21+
"test": "node --experimental-vm-modules $(yarn bin jest) templates",
22+
"test:e2e": "node --experimental-vm-modules $(yarn bin jest) e2e",
23+
"ts-to-js": "yarn node ./scripts/tsToJS.mjs"
2224
},
2325
"dependencies": {
2426
"@opentelemetry/api": "1.7.0",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/* eslint-env node */
2+
3+
import { fileURLToPath } from 'node:url'
4+
5+
import Configstore from 'configstore'
6+
import { cd, fs, os, path, $ } from 'zx'
7+
8+
const config = new Configstore('create-redwood-app')
9+
let projectPath = config.get('projectPath')
10+
11+
const projectExists = projectPath && (await fs.pathExists(projectPath))
12+
13+
if (!projectExists) {
14+
const [timestamp] = new Date().toISOString().replace(/-|:/g, '_').split('.')
15+
16+
projectPath = path.join(os.tmpdir(), `crwa_${timestamp}`)
17+
18+
await fs.ensureDir(projectPath)
19+
await $`yarn --cwd ${projectPath} init -2`
20+
21+
config.set('projectPath', projectPath)
22+
}
23+
24+
const packagePath = fileURLToPath(new URL('../', import.meta.url))
25+
const tarball = 'create-redwood-app.tgz'
26+
27+
await fs.move(
28+
path.join(packagePath, tarball),
29+
path.join(projectPath, tarball),
30+
{ overwrite: true }
31+
)
32+
33+
cd(projectPath)
34+
await $`yarn add ./${tarball}`
35+
36+
console.log(projectPath)

packages/create-redwood-app/tsToJS.mjs packages/create-redwood-app/scripts/tsToJS.mjs

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ import fs from 'fs-extra'
1010
import { format } from 'prettier'
1111

1212
const [TS_TEMPLATE_FILEPATH, JS_TEMPLATE_FILEPATH] = [
13-
new URL('./templates/ts', import.meta.url),
14-
new URL('./templates/js', import.meta.url),
13+
new URL('../templates/ts', import.meta.url),
14+
new URL('../templates/js', import.meta.url),
1515
].map(fileURLToPath)
1616

1717
const { default: prettierConfig } = await import(
18-
new URL('./templates/ts/prettier.config.js', import.meta.url)
18+
new URL('../templates/ts/prettier.config.js', import.meta.url)
1919
)
2020

2121
// Handle node_modules, .yarn/install-state.gz.

packages/create-redwood-app/templates/js/.editorconfig

-3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,3 @@ indent_size = 2
88
indent_style = space
99
insert_final_newline = true
1010
trim_trailing_whitespace = true
11-
12-
[*.{md,html,mjml}]
13-
trim_trailing_whitespace = false

packages/create-redwood-app/templates/js/web/jsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"../node_modules/@testing-library"
3838
],
3939
"types": [
40-
"jest-dom",
40+
"jest",
41+
"jest-dom"
4142
],
4243
"jsx": "preserve"
4344
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#!/usr/bin/env node
2+
/* eslint-env node */
3+
4+
import { cd, fs, $ } from 'zx'
5+
6+
const projectPath = await fs.realpath(process.env.PROJECT_PATH)
7+
8+
cd(projectPath)
9+
10+
describe('crwa', () => {
11+
test('--help', async () => {
12+
const p = await $`yarn create-redwood-app --help`
13+
14+
expect(p.exitCode).toEqual(0)
15+
expect(p.stdout).toMatchInlineSnapshot(`
16+
"------------------------------------------------------------------
17+
🌲⚡️ Welcome to RedwoodJS! ⚡️🌲
18+
------------------------------------------------------------------
19+
Usage: create-redwood-app <project directory> [option]
20+
21+
Options:
22+
--help Show help [boolean]
23+
--typescript, --ts Generate a TypeScript project.
24+
[boolean] [default: null]
25+
--overwrite Create even if target directory isn't empty
26+
[boolean] [default: false]
27+
--telemetry Enables sending telemetry events for this create
28+
command and all Redwood CLI commands
29+
https://telemetry.redwoodjs.com
30+
[boolean] [default: true]
31+
--git-init, --git Initialize a git repository. [boolean] [default: null]
32+
-m, --commit-message Commit message for the initial commit.
33+
[string] [default: null]
34+
-y, --yes Skip prompts and use defaults.
35+
[boolean] [default: null]
36+
--version Show version number [boolean]
37+
38+
Examples:
39+
create-redwood-app newapp
40+
[?25l[?25h"
41+
`)
42+
expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h"`)
43+
})
44+
45+
test('--version', async () => {
46+
const p = await $`yarn create-redwood-app --version`
47+
48+
expect(p.exitCode).toEqual(0)
49+
expect(p.stdout).toMatchInlineSnapshot(`
50+
"------------------------------------------------------------------
51+
🌲⚡️ Welcome to RedwoodJS! ⚡️🌲
52+
------------------------------------------------------------------
53+
6.0.7
54+
[?25l[?25h"
55+
`)
56+
expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h"`)
57+
})
58+
59+
test('--yes, -y', async () => {
60+
const p = await $`yarn create-redwood-app ./redwood-app --yes`
61+
62+
// await $`yarn create-redwood-app redwood-app -y`
63+
// # `yarn pack` seems to ignore `.yarnrc.yml`
64+
// # cp "$SCRIPT_DIR/templates/ts/.yarnrc.yml" "$CRWA_ESM_TESTING_DIR"
65+
66+
expect(p.exitCode).toEqual(0)
67+
expect(p.stdout).toMatchInlineSnapshot(`
68+
"------------------------------------------------------------------
69+
🌲⚡️ Welcome to RedwoodJS! ⚡️🌲
70+
------------------------------------------------------------------
71+
[?25l⠋ Checking node and yarn compatibility
72+
[?25h[?25l✔ Compatibility checks passed
73+
[?25h✔ Creating your Redwood app in ./redwood-app based on command line argument
74+
✔ Using TypeScript based on command line flag
75+
✔ Will initialize a git repo based on command line flag
76+
[?25l⠋ Creating project files
77+
[?25h[?25l✔ Project files created
78+
[?25h[?25l⠋ Initializing a git repo
79+
[?25h[?25l✔ Initialized a git repo with commit message "Initial commit"
80+
[?25h
81+
Thanks for trying out Redwood!
82+
83+
⚡️ Get up and running fast with this Quick Start guide: https://redwoodjs.com/quick-start
84+
85+
Fire it up! 🚀
86+
87+
> cd redwood-app
88+
> yarn install
89+
> yarn rw dev
90+
91+
[?25l✔ Initialized a git repo with commit message "Initial commit"
92+
[?25h"
93+
`)
94+
expect(p.stderr).toMatchInlineSnapshot(`"[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h[?25l[?25h"`)
95+
96+
await fs.rm('./redwood-app', { recursive: true, force: true })
97+
})
98+
99+
test.failing('fails on unknown options', async () => {
100+
try {
101+
await $`yarn create-redwood-app --unknown-options`.timeout(2500)
102+
// Fail the test if the function didn't throw.
103+
expect(true).toEqual(false)
104+
} catch (p) {
105+
expect(p.exitCode).toEqual(1)
106+
}
107+
})
108+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/expect
2+
3+
set projectPath $env(PROJECT_PATH)
4+
5+
if {$projectPath eq ""} {
6+
puts "PROJECT_PATH is not set"
7+
exit
8+
}
9+
10+
cd $projectPath
11+
12+
set projectDirectory "redwood-app-prompt-test"
13+
14+
spawn yarn create-redwood-app
15+
16+
expect "Where would you like to create your Redwood app?"
17+
send "$projectDirectory\n"
18+
19+
expect "Select your preferred language"
20+
# TypeScript
21+
send "\n"
22+
23+
expect "Do you want to initialize a git repo?"
24+
# Yes
25+
send "\n"
26+
27+
expect "Enter a commit message"
28+
send "first\n"
29+
30+
expect eof
31+
catch wait result
32+
set exitStatus [lindex $result 3]
33+
34+
if {$exitStatus == 0} {
35+
puts "Success"
36+
exec rm -rf $projectDirectory
37+
exit 0
38+
} else {
39+
puts "Error: The process failed with exit status $exitStatus"
40+
exec rm -rf $projectDirectory
41+
exit 1
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/expect
2+
3+
set projectPath $env(PROJECT_PATH)
4+
5+
if {$projectPath eq ""} {
6+
puts "PROJECT_PATH is not set"
7+
exit
8+
}
9+
10+
cd $projectPath
11+
12+
set projectDirectory "redwood-app-prompt-git-test"
13+
14+
spawn yarn create-redwood-app --git
15+
16+
expect "Where would you like to create your Redwood app?"
17+
send "$projectDirectory\n"
18+
19+
expect "Select your preferred language"
20+
# TypeScript
21+
send "\n"
22+
23+
expect "Enter a commit message"
24+
send "first\n"
25+
26+
expect eof
27+
catch wait result
28+
set exitStatus [lindex $result 3]
29+
30+
if {$exitStatus == 0} {
31+
puts "Success"
32+
exec rm -rf $projectDirectory
33+
exit 0
34+
} else {
35+
puts "Error: The process failed with exit status $exitStatus"
36+
exec rm -rf $projectDirectory
37+
exit 1
38+
}

0 commit comments

Comments
 (0)