From 23c9717af1884c89f0e5f65d33df6bb5b759aca7 Mon Sep 17 00:00:00 2001 From: Kyle Gilliam Date: Mon, 5 Dec 2022 07:11:56 -0800 Subject: [PATCH] Add option for jest test scaffolding (#2200) * Add in option for jest scaffolding * Add tests for Jest in both JS/TS * Clone moved value; use new function name * Remove invalid tests --- cli/src/lib.rs | 64 +++++++++++++------ cli/src/template.rs | 146 ++++++++++++++++++++++++++++++++++++++------ 2 files changed, 173 insertions(+), 37 deletions(-) diff --git a/cli/src/lib.rs b/cli/src/lib.rs index b4e3ab56b..155f4eb20 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -68,6 +68,8 @@ pub enum Command { javascript: bool, #[clap(long)] no_git: bool, + #[clap(long)] + jest: bool, }, /// Builds the workspace. #[clap(name = "build", alias = "b")] @@ -359,7 +361,8 @@ pub fn entry(opts: Opts) -> Result<()> { name, javascript, no_git, - } => init(&opts.cfg_override, name, javascript, no_git), + jest, + } => init(&opts.cfg_override, name, javascript, no_git, jest), Command::New { name } => new(&opts.cfg_override, name), Command::Build { idl, @@ -466,7 +469,13 @@ pub fn entry(opts: Opts) -> Result<()> { } } -fn init(cfg_override: &ConfigOverride, name: String, javascript: bool, no_git: bool) -> Result<()> { +fn init( + cfg_override: &ConfigOverride, + name: String, + javascript: bool, + no_git: bool, + jest: bool, +) -> Result<()> { if Config::discover(cfg_override)?.is_some() { return Err(anyhow!("Workspace already initialized")); } @@ -474,7 +483,7 @@ fn init(cfg_override: &ConfigOverride, name: String, javascript: bool, no_git: b // We need to format different cases for the dir and the name let rust_name = name.to_snake_case(); let project_name = if name == rust_name { - name + rust_name.clone() } else { name.to_kebab_case() }; @@ -496,15 +505,28 @@ fn init(cfg_override: &ConfigOverride, name: String, javascript: bool, no_git: b fs::create_dir("app")?; let mut cfg = Config::default(); - cfg.scripts.insert( - "test".to_owned(), - if javascript { - "yarn run mocha -t 1000000 tests/" - } else { - "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" - } - .to_owned(), - ); + if jest { + cfg.scripts.insert( + "test".to_owned(), + if javascript { + "yarn run jest" + } else { + "yarn run jest --preset ts-jest" + } + .to_owned(), + ); + } else { + cfg.scripts.insert( + "test".to_owned(), + if javascript { + "yarn run mocha -t 1000000 tests/" + } else { + "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" + } + .to_owned(), + ); + } + let mut localnet = BTreeMap::new(); localnet.insert( rust_name, @@ -540,20 +562,25 @@ fn init(cfg_override: &ConfigOverride, name: String, javascript: bool, no_git: b if javascript { // Build javascript config let mut package_json = File::create("package.json")?; - package_json.write_all(template::package_json().as_bytes())?; + package_json.write_all(template::package_json(jest).as_bytes())?; - let mut mocha = File::create(&format!("tests/{}.js", &project_name))?; - mocha.write_all(template::mocha(&project_name).as_bytes())?; + if jest { + let mut test = File::create(&format!("tests/{}.test.js", &project_name))?; + test.write_all(template::jest(&project_name).as_bytes())?; + } else { + let mut test = File::create(&format!("tests/{}.js", &project_name))?; + test.write_all(template::mocha(&project_name).as_bytes())?; + } let mut deploy = File::create("migrations/deploy.js")?; deploy.write_all(template::deploy_script().as_bytes())?; } else { // Build typescript config let mut ts_config = File::create("tsconfig.json")?; - ts_config.write_all(template::ts_config().as_bytes())?; + ts_config.write_all(template::ts_config(jest).as_bytes())?; let mut ts_package_json = File::create("package.json")?; - ts_package_json.write_all(template::ts_package_json().as_bytes())?; + ts_package_json.write_all(template::ts_package_json(jest).as_bytes())?; let mut deploy = File::create("migrations/deploy.ts")?; deploy.write_all(template::ts_deploy_script().as_bytes())?; @@ -3169,6 +3196,7 @@ mod tests { "await".to_string(), true, false, + false, ) .unwrap(); } @@ -3184,6 +3212,7 @@ mod tests { "fn".to_string(), true, false, + false, ) .unwrap(); } @@ -3199,6 +3228,7 @@ mod tests { "1project".to_string(), true, false, + false, ) .unwrap(); } diff --git a/cli/src/template.rs b/cli/src/template.rs index aee8a811a..0517cf10b 100644 --- a/cli/src/template.rs +++ b/cli/src/template.rs @@ -221,9 +221,49 @@ describe("{}", () => {{ ) } -pub fn package_json() -> String { +pub fn jest(name: &str) -> String { format!( - r#"{{ + r#"const anchor = require("@project-serum/anchor"); + +describe("{}", () => {{ + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + it("Is initialized!", async () => {{ + // Add your test here. + const program = anchor.workspace.{}; + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }}); +}}); +"#, + name, + name.to_upper_camel_case(), + ) +} + +pub fn package_json(jest: bool) -> String { + if jest { + format!( + r#"{{ + "scripts": {{ + "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w", + "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check" + }}, + "dependencies": {{ + "@project-serum/anchor": "^{0}" + }}, + "devDependencies": {{ + "jest": "^29.0.3", + "prettier": "^2.6.2" + }} + }} + "#, + VERSION + ) + } else { + format!( + r#"{{ "scripts": {{ "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w", "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check" @@ -238,13 +278,37 @@ pub fn package_json() -> String { }} }} "#, - VERSION - ) + VERSION + ) + } } -pub fn ts_package_json() -> String { - format!( - r#"{{ +pub fn ts_package_json(jest: bool) -> String { + if jest { + format!( + r#"{{ + "scripts": {{ + "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w", + "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check" + }}, + "dependencies": {{ + "@project-serum/anchor": "^{0}" + }}, + "devDependencies": {{ + "@types/bn.js": "^5.1.0", + "@types/jest": "^29.0.3", + "jest": "^29.0.3", + "prettier": "^2.6.2", + "ts-jest": "^29.0.2", + "typescript": "^4.3.5" + }} + }} + "#, + VERSION + ) + } else { + format!( + r#"{{ "scripts": {{ "lint:fix": "prettier */*.js \"*/**/*{{.js,.ts}}\" -w", "lint": "prettier */*.js \"*/**/*{{.js,.ts}}\" --check" @@ -264,8 +328,9 @@ pub fn ts_package_json() -> String { }} }} "#, - VERSION - ) + VERSION + ) + } } pub fn ts_mocha(name: &str) -> String { @@ -295,18 +360,59 @@ describe("{}", () => {{ ) } -pub fn ts_config() -> &'static str { - r#"{ - "compilerOptions": { - "types": ["mocha", "chai"], - "typeRoots": ["./node_modules/@types"], - "lib": ["es2015"], - "module": "commonjs", - "target": "es6", - "esModuleInterop": true - } +pub fn ts_jest(name: &str) -> String { + format!( + r#"import * as anchor from "@project-serum/anchor"; +import {{ Program }} from "@project-serum/anchor"; +import {{ {} }} from "../target/types/{}"; + +describe("{}", () => {{ + // Configure the client to use the local cluster. + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.{} as Program<{}>; + + it("Is initialized!", async () => {{ + // Add your test here. + const tx = await program.methods.initialize().rpc(); + console.log("Your transaction signature", tx); + }}); +}}); +"#, + name.to_upper_camel_case(), + name.to_snake_case(), + name, + name.to_upper_camel_case(), + name.to_upper_camel_case(), + ) } -"# + +pub fn ts_config(jest: bool) -> &'static str { + if jest { + r#"{ + "compilerOptions": { + "types": ["jest"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true + } + } + "# + } else { + r#"{ + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true + } + } + "# + } } pub fn git_ignore() -> &'static str {