-
Notifications
You must be signed in to change notification settings - Fork 2.6k
feat(forge) - Test scaffolding
#5495
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
2f3ec79
c6bd8c2
dc5ac50
d7ab547
068092e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // SPDX-License-Identifier: UNLICENSED | ||
| pragma solidity ^0.8.13; | ||
|
|
||
| import "forge-std/Test.sol"; | ||
| import "../src/{contract_name}.sol"; | ||
|
|
||
| contract {contract_name}Test is Test { | ||
| {contract_name} public {instance_name}; | ||
|
|
||
| function setUp() public { | ||
| {instance_name} = new {contract_name}(); | ||
|
mds1 marked this conversation as resolved.
|
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| //! generate command | ||
|
|
||
| use clap::{Parser, Subcommand}; | ||
| use std::fs; | ||
| use std::path::Path; | ||
|
|
||
| /// CLI arguments for `forge generate`. | ||
| #[derive(Debug, Parser)] | ||
| pub struct GenerateArgs { | ||
| #[clap(subcommand)] | ||
| pub sub: GenerateSubcommands, | ||
| } | ||
|
|
||
| #[derive(Debug, Subcommand)] | ||
| pub enum GenerateSubcommands { | ||
| /// Scaffolds test file for given contract. | ||
| Test(GenerateTestArgs), | ||
| } | ||
|
|
||
| #[derive(Debug, Parser)] | ||
| pub struct GenerateTestArgs { | ||
| /// Contract name for test generation. | ||
| #[clap(long, short, value_name = "CONTRACT_NAME")] | ||
| pub contract_name: String, | ||
| } | ||
|
|
||
| impl GenerateTestArgs { | ||
| pub fn run(self) -> eyre::Result<()> { | ||
| let contract_name = format_identifier(&self.contract_name, true); | ||
| let instance_name = format_identifier(&self.contract_name, false); | ||
|
|
||
| // Create the test file content. | ||
| let test_content = include_str!("../../../../assets/generated/TestTemplate.t.sol"); | ||
| let test_content = test_content | ||
| .replace("{contract_name}", &contract_name) | ||
| .replace("{instance_name}", &instance_name); | ||
|
|
||
| // Create the test directory if it doesn't exist. | ||
| fs::create_dir_all("test").unwrap(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we avoid
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Absolutely! I looked at some other files and figured there is wrapper around fs |
||
|
|
||
| // Define the test file path | ||
| let test_file_path = Path::new("test").join(format!("{}.t.sol", contract_name)); | ||
|
|
||
| // Write the test content to the test file. | ||
| fs::write(&test_file_path, test_content).unwrap(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto on unwrap
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed too |
||
|
|
||
| println!("Test file generated: {}", test_file_path.to_str().unwrap()); | ||
| Ok(()) | ||
| } | ||
| } | ||
|
|
||
| /// Utility function to convert an identifier to pascal or camel case. | ||
| fn format_identifier(input: &str, is_pascal_case: bool) -> String { | ||
| let mut result = String::new(); | ||
| let mut capitalize_next = is_pascal_case; | ||
|
|
||
| for word in input.split_whitespace() { | ||
| if !word.is_empty() { | ||
| let (first, rest) = word.split_at(1); | ||
| let formatted_word = if capitalize_next { | ||
| format!("{}{}", first.to_uppercase(), rest) | ||
| } else { | ||
| format!("{}{}", first.to_lowercase(), rest) | ||
| }; | ||
| capitalize_next = true; | ||
| result.push_str(&formatted_word); | ||
| } | ||
| } | ||
| result | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.