diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..783b798 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# These owners will be the default owners for everything in +# the repo. Unless a later match takes precedence, +# @Josee9988 will be requested for +# review when someone opens a pull request. +# if you want to add more owners, just write it after @Josee9988 +* @Josee9988 diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..b60dfc1 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to make participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behaviour that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behaviour by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behaviour and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behaviour. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviours that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing or otherwise unacceptable behaviour may be +reported by contacting the project team at jgracia9988@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality concerning the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see + diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..605c8d9 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,23 @@ +# **Contributing** + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a [code of conduct](CODE_OF_CONDUCT.md); please follow it in all your interactions with the project. + +## Pull Request Process + +1. Ensure any install or build dependencies are removed before the end of the layer when doing a + build. +2. Update the README.md with details of changes to the interface; this includes new environment variables, exposed ports, valid file locations and container parameters. +3. Increase the version numbers in any examples files and the README.md to the new version that this + Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/). +4. You may merge the Pull Request once you have the sign-off of two other developers, or if you + do not have permission to do that, you may request the second reviewer to merge it for you. + +## Issue Report Process + +1. Go to the project's issues. +2. Select the template that better fits your issue. +3. Read the instructions carefully and write within the template guidelines. +4. Submit it and wait for support. diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..a2d624f --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: Josee9988 +custom: ['https://www.paypal.me/josee9988'] diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..184249d --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,41 @@ + + +# **Blank Issue Report** + +## **Describe the issue** + + +* + +--- + +### **Media prove** + + +--- + +### **Your environment** + + + +* OS: +* Node version: +* Npm version: +* Browser name and version: + +--- + +### **Additional context** + + +* diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md new file mode 100644 index 0000000..bf5745d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-bug-report.md @@ -0,0 +1,79 @@ +--- +name: "🐞 Bug Report" +about: "Report an issue to help the project improve." +title: "[Bug] " +labels: "Type: Bug" +assignees: Josee9988 + +--- + +# **🐞 Bug Report** + +## **Describe the bug** + + +* + +--- + +### **Is this a regression?** + + + +--- + +### **To Reproduce** + + + + + +1. +2. +3. +4. + +--- + +### **Expected behaviour** + + +* + +--- + +### **Media prove** + + +--- + +### **Your environment** + + + +* OS: +* Node version: +* Npm version: +* Browser name and version: + +--- + +### **Additional context** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/2-failing-test.md b/.github/ISSUE_TEMPLATE/2-failing-test.md new file mode 100644 index 0000000..ed5e43b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-failing-test.md @@ -0,0 +1,41 @@ +--- +name: "💉 Failing Test" +about: "Report failing tests or CI jobs." +title: "[Test] " +labels: "Type: Test" +assignees: Josee9988 + +--- + +# **💉 Failing Test** + +## **Which jobs/test(s) are failing** + + +* + +--- + +## **Reason for failure/description** + + +--- + +### **Media prove** + + +--- + +### **Additional context** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/3-docs-bug.md b/.github/ISSUE_TEMPLATE/3-docs-bug.md new file mode 100644 index 0000000..1982f3d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/3-docs-bug.md @@ -0,0 +1,60 @@ +--- +name: "📚 Documentation or README.md issue report" +about: "Report an issue in the project's documentation or README.md file." +title: "" +labels: "Documentation" +assignees: Josee9988 + +--- +# **📚 Documentation Issue Report** + +## **Describe the bug** + + +* + +--- + +### **To Reproduce** + + + + + +1. +2. +3. +4. + +--- + +### **Media prove** + + +--- + +## **Describe the solution you'd like** + + +* + +--- + +### **Additional context** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/4-feature-request.md b/.github/ISSUE_TEMPLATE/4-feature-request.md new file mode 100644 index 0000000..8f28326 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/4-feature-request.md @@ -0,0 +1,45 @@ +--- +name: "🚀🆕 Feature Request" +about: "Suggest an idea or possible new feature for this project." +title: "" +labels: "Type: Feature" +assignees: Josee9988 + +--- + +# **🚀 Feature Request** + +## **Is your feature request related to a problem? Please describe.** + + +* + +--- + +## **Describe the solution you'd like** + + +* + +--- + +## **Describe alternatives you've considered** + + +* + +--- + +### **Additional context** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/5-enhancement-request.md b/.github/ISSUE_TEMPLATE/5-enhancement-request.md new file mode 100644 index 0000000..bbbf635 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/5-enhancement-request.md @@ -0,0 +1,45 @@ +--- +name: "🚀➕ Enhancement Request" +about: "Suggest an enhancement for this project. Improve an existing feature" +title: "" +labels: "Type: Enhancement" +assignees: Josee9988 + +--- + +# **🚀 Enhancement Request** + +## **Is your enhancement request related to a problem? Please describe.** + + +* + +--- + +## **Describe the solution you'd like** + + +* + +--- + +## **Describe alternatives you've considered** + + +* + +--- + +### **Additional context** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/6-security-report.md b/.github/ISSUE_TEMPLATE/6-security-report.md new file mode 100644 index 0000000..c657b36 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/6-security-report.md @@ -0,0 +1,100 @@ +--- +name: "⚠️ Security Report" +about: "Report an issue to help the project improve." +title: "" +labels: "Type: Security" +assignees: Josee9988 + +--- + + + +# **⚠️ Security Report** + +## **Describe the security issue** + + +* + +--- + +### **To Reproduce** + + + + + +1. +2. +3. +4. + +--- + +### **Expected behaviour** + + +* + +--- + +### **Media prove** + + +--- + +### **Your environment** + + + +* OS: +* Node version: +* Npm version: +* Browser name and version: + +--- + +### **Additional context** + + +* diff --git a/.github/ISSUE_TEMPLATE/7-question-support.md b/.github/ISSUE_TEMPLATE/7-question-support.md new file mode 100644 index 0000000..56a13ac --- /dev/null +++ b/.github/ISSUE_TEMPLATE/7-question-support.md @@ -0,0 +1,28 @@ +--- +name: "❓ Question or Support Request" +about: "Questions and requests for support." +title: "" +labels: "Type: Question" +assignees: Josee9988 + +--- + +# **❓ Question or Support Request** + +## **Describe your question or ask for support.** + + +* + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..d36b886 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: Send an e-mail to the developer + url: mailto:jgracia9988@gmail.com + about: Please do NOT use this email to post issues or feature requests (only important business/personal contact). diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..4e0cb4d --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,11 @@ +# **Reporting Security Issues** + +The project's team and community take security issues. + +We appreciate your efforts to disclose your findings responsibly and will make every effort to acknowledge your contributions. + +To report a security issue, go to the project's issues and create a new issue using the ⚠️ Security Report 'issue template'. + +Read the instructions of this issue template carefully, and if your report could leak data or might expose how to gain access to a restricted area or break the system, please email [jgracia9988@gmail.com](mailto:jgracia9988@gmail.com) and include the word "SECURITY" in the subject line. + +We'll endeavour to respond quickly and keep you updated throughout the process. diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md new file mode 100644 index 0000000..49c13a9 --- /dev/null +++ b/.github/SUPPORT.md @@ -0,0 +1,11 @@ +# **Support** + +## Obtain direct support from the project's owners + +1. Open a new issue and select the issue with the template called "❓ Question or Support Request". +2. Read the instructions carefully in that template and submit the issue asking for support +or any question. + +## Bug reports + +See the [contributing guidelines](CONTRIBUTING.md) for sharing bug reports and read our [code of conduct](CODE_OF_CONDUCT.md). diff --git a/.github/config.yml b/.github/config.yml new file mode 100644 index 0000000..1e537f7 --- /dev/null +++ b/.github/config.yml @@ -0,0 +1,20 @@ +# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome + +# Comment to be posted to on first time issues +newIssueWelcomeComment: > + Thanks for opening your first issue in Josee9988/project-template! Be sure to follow the issue template and provide every bit of information to help the developers! + +# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome + +# Comment to be posted to on PRs from first time contributors in your repository +newPRWelcomeComment: > + Thanks for opening this pull request! Please check out our contributing guidelines and make sure to follow the pull request template. + +# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge + +# Comment to be posted to on pull requests merged by a first time user +firstPRMergeComment: > + Congrats on merging your first pull request! Keep making great things with us, thanks!! + +todo: + keyword: '@todo' diff --git a/.github/issue_label_bot.yaml b/.github/issue_label_bot.yaml new file mode 100644 index 0000000..b83d27f --- /dev/null +++ b/.github/issue_label_bot.yaml @@ -0,0 +1,4 @@ +label-alias: + bug: 'Type: Bug' + feature_request: 'Type: Feature' + question: 'Type: Question' diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..4cb113f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,29 @@ +# **Name of PR** + + + +## **Description** + + + +* + +--- + +### **Additional context** + + + +* + + diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..5aa8523 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,184 @@ +repository: + # See https://developer.github.com/v3/repos/#edit for all available settings. + + # The name of the repository. Changing this will rename the repository + #name: repo-name + + # A short description of the repository that will show up on GitHub + #description: description of repo + + # A URL with more information about the repository + #homepage: https://example.github.io/ + + # A comma-separated list of topics to set on the repository + #topics: project, template, project-template + + # Either `true` to make the repository private, or `false` to make it public. + #private: false + + # Either `true` to enable issues for this repository, `false` to disable them. + #has_issues: true + + # Either `true` to enable the wiki for this repository, `false` to disable it. + #has_wiki: true + + # Either `true` to enable downloads for this repository, `false` to disable them. + #has_downloads: true + + # Updates the default branch for this repository. + #default_branch: master + + # Either `true` to allow squash-merging pull requests, or `false` to prevent + # squash-merging. + #allow_squash_merge: true + + # Either `true` to allow merging pull requests with a merge commit, or `false` + # to prevent merging pull requests with merge commits. + #allow_merge_commit: true + + # Either `true` to allow rebase-merging pull requests, or `false` to prevent + # rebase-merging. + #allow_rebase_merge: true + +# Labels: define labels for Issues and Pull Requests +labels: + - name: 'Type: Bug' + color: e80c0c + description: Something isn't working as expected. + + - name: 'Type: Enhancement' + color: 54b2ff + description: Suggest an improvement for an existing feature. + + - name: 'Type: Feature' + color: 54b2ff + description: Suggest a new feature. + + - name: 'Type: Security' + color: fbff00 + description: A problem or enhancement related to a security issue. + + - name: 'Type: Question' + color: 9309ab + description: Request for information. + + - name: 'Type: Test' + color: ce54e3 + description: A problem or enhancement related to a test. + + - name: 'Status: Awaiting Review' + color: 24d15d + description: Ready for review. + + - name: 'Status: WIP' + color: 07b340 + description: Currently being worked on. + + - name: 'Status: Waiting' + color: 38C968 + description: Waiting on something else to be ready. + + - name: 'Status: Stale' + color: 66b38a + description: Has had no activity for some time. + + - name: 'Duplicate' + color: EB862D + description: Duplicate of another issue. + + - name: 'Invalid' + color: faef50 + description: This issue doesn't seem right. + + - name: 'Priority: High +' + color: ff008c + description: Task is considered higher-priority. + + - name: 'Priority: Low -' + color: 690a34 + description: Task is considered lower-priority. + + - name: 'Documentation' + color: 2fbceb + description: An issue/change with the documentation. + + - name: "Won't fix" + color: C8D9E6 + description: Reported issue is working as intended. + + - name: '3rd party issue' + color: e88707 + description: This issue might be caused by a 3rd party script/package/other reasons + + - name: 'Os: Windows' + color: AEB1C2 + description: Is Windows-specific + + - name: 'Os: Mac' + color: AEB1C2 + description: Is Mac-specific + + - name: 'Os: Linux' + color: AEB1C2 + description: Is Linux-specific +# # Collaborators: give specific users access to this repository. +# # See https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator for available options +# collaborators: +# # - username: bkeepers +# # permission: push +# # - username: hubot +# # permission: pull + +# # Note: `permission` is only valid on organization-owned repositories. +# # The permission to grant the collaborator. Can be one of: +# # * `pull` - can pull, but not push to or administer this repository. +# # * `push` - can pull and push, but not administer this repository. +# # * `admin` - can pull, push and administer this repository. +# # * `maintain` - Recommended for project managers who need to manage the repository without access to sensitive or destructive actions. +# # * `triage` - Recommended for contributors who need to proactively manage issues and pull requests without write access. + +# # See https://developer.github.com/v3/teams/#add-or-update-team-repository for available options +# teams: +# - name: core +# # The permission to grant the team. Can be one of: +# # * `pull` - can pull, but not push to or administer this repository. +# # * `push` - can pull and push, but not administer this repository. +# # * `admin` - can pull, push and administer this repository. +# # * `maintain` - Recommended for project managers who need to manage the repository without access to sensitive or destructive actions. +# # * `triage` - Recommended for contributors who need to proactively manage issues and pull requests without write access. +# permission: admin +# - name: docs +# permission: push + +# branches: +# - name: master +# # https://developer.github.com/v3/repos/branches/#update-branch-protection +# # Branch Protection settings. Set to null to disable +# protection: +# # Required. Require at least one approving review on a pull request, before merging. Set to null to disable. +# required_pull_request_reviews: +# # The number of approvals required. (1-6) +# required_approving_review_count: 1 +# # Dismiss approved reviews automatically when a new commit is pushed. +# dismiss_stale_reviews: true +# # Blocks merge until code owners have reviewed. +# require_code_owner_reviews: true +# # Specify which users and teams can dismiss pull request reviews. Pass an empty dismissal_restrictions object to disable. User and team dismissal_restrictions are only available for organization-owned repositories. Omit this parameter for personal repositories. +# dismissal_restrictions: +# users: [] +# teams: [] +# # Required. Require status checks to pass before merging. Set to null to disable +# required_status_checks: +# # Required. Require branches to be up-to-date before merging. +# strict: true +# # Required. The list of status checks to require in order to merge into this branch +# contexts: [] +# # Required. Enforce all configured restrictions for administrators. Set to true to enforce required status checks for repository administrators. Set to null to disable. +# enforce_admins: true +# # Prevent merge commits from being pushed to matching branches +# required_linear_history: true +# # Required. Restrict who can push to this branch. Team and user restrictions are only available for organization-owned repositories. Set to null to disable. +# restrictions: +# apps: [] +# users: [] +# teams: [] diff --git a/.github/workflows/shelltest.yml b/.github/workflows/shelltest.yml new file mode 100644 index 0000000..e360b95 --- /dev/null +++ b/.github/workflows/shelltest.yml @@ -0,0 +1,20 @@ +# this github actions will run the tests/TESTS_RUNNER.sh script and fail if any of the tests fail. +name: SH Tests runner + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v2 #checkout into the repository + - name: Run the TEST_RUNNER.sh script + run: ./tests/TESTS_RUNNER.sh # run the TESTS_RUNNER.sh script diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bde2b14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +###> Josee9988/project-template ### + +##### Folders ##### +build/ +dist/ +node_modules/ +vendor/ +var/ +.tmp/ + +# IDE's +.vscode/ +.idea/ + + +##### Files ##### +ignore.* +*.ignore.* + +# Environment variables and secret keys +.env +.env.test +*.pem + +###< Josee9988/project-template ### diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a1cdbcc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,456 @@ + +# **Change Log** 📜📝 + +All notable changes to the "**Project template**" repository will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [**1.11.9**] - 2022-10-03 + +### Fixed + +* Multiple and grammar issues. + +## [**1.11.8**] - 2022-08-07 + +### Fixed + +* Multiple typos and grammar issues. +* From 'cp -r *' to 'cp -r ./*' in the tests, so names with dashes won't become options. + +## [**1.11.7**] - 2021-12-05 + +### Added + +* In the main script, removing the bin/ folder, the LICENSE file and the script itself will not prompt errors if there are any problems + +## [**1.11.6**] - 2021-12-04 + +### Added + +* Two 'README.md' files at the bin/ and tests/ folder to help describe what the folder purpose is. + +## [**1.11.5**] - 2021-11-19 + +### Fixed + +* Some typos in multiple files. + +## [**1.11.4**] - 2021-11-01 + +### Fixed + +* Multiple spelling mistakes in the README and CHANGELOG files. + +## [**1.11.3**] - 2021-08-03 + +### Added + +* Improved gitignore comments + +## [**1.11.2**] - 2021-07-30 + +### Added + +* Git ignored multiple common folder and files. + +## [**1.11.1**] - 2021-07-25 + +### Added + +* Simple documentation in the bin/FUNCTION_HELPERS.sh script. + +## [**1.11.0**] - 2021-07-24 + +### Added + +* Divided the --omit-commit-and-verification argument into two separate ones '--omit-commit' and '--omit-verification'. + +## [**1.10.5**] - 2021-07-21 + +### Added + +* Improved all the documentation in the scripts. + +## [**1.10.4**] - 2021-07-20 + +### Added + +* More error information when the tests fail. +* The new logos in the generated README for the user to change them with their own one. +* More documentation in the project's readme.md +* Informational error in the script when an unknown argument is encountered. + +### Removed + +* Two useless FUNCTION_HELPERS's functions displaying errors. +* Useless 'chmod' declaration in the TESTS_RUNNER script +* The exit conditions of the TESTS_RUNNER script in the same if statement. + +## [**1.10.3**] - 2021-07-19 + +### Added + +* A new logo in the readme.md +* The brand logo in the sponsors part. +* Alt attribute for all the README's images +* More guidance for the used GitHub bots + +### Fixed + +* Some README's 'alt' attribute. +* Some README's broken links + +## [**1.10.2**] - 2021-07-17 + +### Added + +* A GitHub actions workflow to check the tests. +* Execute permissions for the SETUP_TEMPLATE.sh script + +### Fixed + +* Some minor issues with the README.md. + +## [**1.10.1**] - 2021-07-16 + +### Added + +* An exit code for the tests_runner script. +* The SETUP_TEMPLATE will look up for the tests_runner exit code to verify if the tests failed or not. +* All the tests which call the SETUP_TEMPLATE now will append the --omit-tests flag to avoid test recursion. + +## [**1.10.0**] - 2021-07-15 + +### Added + +* Checking of the tests before the execution of the script, avoidable using the --omit-test-check argument. + +## [**1.9.2**] - 2021-07-14 + +### Added + +* More tests for the help parser script +* A version argument that will display the current script version + +### Fixed + +* Some typos +* The README's link to the issues + +### Changed + +* The SETUP_TEMPLATE usage comments + +### Removed + +* When the user selects "n" in the choice, it will not show the help texts. Only if the --help argument is provided. + +## [**1.9.1**] - 2021-07-13 + +### Changed + +* Asciinema video explaining how the script works + +## [**1.9.0**] - 2021-07-13 + +### Added + +* The script will parse arguments like --argument=value. +* Added one "help" argument test. +* Updated the tests to be in sync with the new argument parse feature. +* The tests_runner will chmod the test folder before executing the tests. +* Aliases for the --omit-commit argument + +### Fixed + +* Some typos + +## [**1.8.2**] - 2021-07-11 + +### Added + +* Some minor comments in the test scripts + +### Changed + +* The asciinema video + +## [**1.8.1**] - 2021-07-10 + +### Added + +* Basic file documentation for all the tests. +* Improved the TESTS_RUNNER script. + +### Fixed + +* Some minor typos. +* The README's project tree + +### Changed + +* The comment 'BASH_VERSION' in all the scripts to the actual one. + +## [**1.8.0**] - 2021-07-09 + +### Added + +* Multiple bash unit tests. +* The SETUP_TEMPLATE.sh now takes a 4th argument which is the type of the project. +* Updated the README to add the documentation of the new test + +### Fixed + +* Modified a couple of files where the project name was not changed. + +### Changed + +* Modified the SETUP_TEMPLATE.sh to make it available for the tests. +* Improved the .github/SECURITY.md file + +## [**1.7.2**] - 2021-07-08 + +### Added + +* Multiple new .gitignore lines and improved its comment structure. + +### Fixed + +* Minor typo in the generated README.md + +## [**1.7.1**] - 2021-07-01 + +### Added + +* `.env` file will be ignored in the `.gitignore`. +* Disabled some Markdown link rules in the generated README.md +* Fixed some minor errors in the README.md file + +## [**1.7.0**] - 2021-06-01 + +### Added + +* Type: Test issue label. +* Failing test issue template adds the new Type Test issue label. +* Update README.md with the new label. + +## [**1.6.0**] - 2021-05-21 + +### Added + +* Divided the feature request into feature and enhancement requests, each one with its respective labels. + +### Changed + +* Position of disclaimers and comments in the issue templates are moved to the bottom (but the security report) as some users directly erased everything to not read the text. +* Image of the issue templates in the readme.md file. + +## [**1.5.0**] - 2021-05-15 + +### Added + +* Auto-detection of user email. + +## [**1.4.5**] - 2021-04-24 + +### Added + +* Sponsor section in the project's main readme.md file. +* Improved and added documentation in the scripts. + +### Fixed + +* README "What does it include" fixed list of files. +* Sponsor link in the generated README.md file. +* Some typos + +## [**1.4.4**] - 2021-04-22 + +### Added + +* --help option in the script. +* More documentation and information for the user in the script prompts + +## [**1.4.3**] - 2021-04-21 + +### Added + +* Support for GitHub to-do app. + +## [**1.4.2**] - 2021-04-20 + +### Added + +* An extra informational message in the script. +* Welcome bot and its config (.GitHub/config.yml) + +### Fixed + +* Issue templates now auto assigns the new labels. + +## [**1.4.1**] - 2021-04-20 + +### Added + +* Security label + +### Changed + +* Project tree to its updated version. + +## [**1.4.0**] - 2021-04-19 + +### Added + +* README file with the section with the recommended/used bots that the users should install. +* Some informational comments in the script referencing the project's documentation. +* A total of 18 new labels will be created right when you clone your repo using GitHub 'Probot' settings. + +## [**1.3.0**] - 2021-04-14 + +### Added + +* CODEOWNERS file inside the '.GitHub/' folder. + +### Fixed + +* Some README.md Markdown link bugs. + +## [**1.2.0**] - 2021-04-07 + +### Added + +* Bug report issue templates have the preceding "[BUG]" title. +* Multiple README template headings (About the project, project tree, screenshots, donators). +* Improved README.md template by fixing some minor problems. + +## [**1.1.1**] - 2021-04-02 + +### Added + +* Username and project name are automatically selected (user can manually force change them using bash parameters [Username] [Project-Name]) + +### Changed + +* Asciinema video + +## [**1.1.0**] - 2021-03-31 + +### Added + +* Gitignore file ignores all \*.ignore.\* files. +* Basic README.md template. +* A bin/FUNCTION_HELPERS script to improve the readability of the SETUP_TEMPLATE.sh file. + +### Changed + +* Header's emoji from the end of the README.md headers to the beginning to be shown better by the new GitHub's README table of contents. + +### Fixed + +* Git status is shown before the commit. + +### Fixed + +* Some typos in the CHANGELOG.md. + +## [**1.0.11**] - 2021-03-20 + +### Added + +* Social links of the repo in the README.md file. +* Added badges in the README.md file. +* Added sponsor link in the contributing.yml file. + +### Fixed + +* Some minor typos in the README.md file. + +## [**1.0.10**] - 2021-03-17 + +### Changed + +* `EXECUTEME.sh` script changed to `SETUP_TEMPLATE.sh`. +* Changed the execution video from the README.md file (Asciinema's video). + +## [**1.0.9**] - 2021-03-17 + +### Added + +* The script will 'git add' and 'commit' the new files/changes for you. + +## [**1.0.8**] - 2021-03-17 + +### Changed + +* Improved README.md structure and fixed some typos. + +### Added + +* 'Extra recommendations' section in the README.md file. + +## [**1.0.7**] - 2021-03-16 + +### Fixed + +* Some minor typos + +## [**1.0.6**] - 2021-03-16 + +### Changed + +* Simplified PR template to make it easier. + +## [**1.0.5**] - 2021-03-13 + +### Added + +* Checks to the shell script (check if the files exist) +* Colorized the output of the script. + +## [**1.0.4**] - 2021-02-26 + +### Added + +* MarkdownLint disable the rule in the "CHANGELOG.md" file. + +## [**1.0.3**] - 2021-02-23 + +### Removed + +* Josee's funding links. + +### Added + +* Shell script now checks if the '.github' directory exists. + +## [**1.0.2**] - 2020-09-08 + +### Added + +* One more screenshot to the README.md file showing the community profile. +* Documentation for the SETUP_TEMPLATE.sh script. + +### Changed + +* The project tree view showing the new LICENSE file. + +## [**1.0.1**] - 2020-09-08 + +### Added + +* A LICENSE for the project will be removed with the SETUP_TEMPLATE.sh script. + +### Changed + +* The location of the pull request template to the '.GitHub/' folder. + +## [**1.0.0**] - 2020-09-08 + +### Added + +* Added a CHANGELOG.md. +* Support for the CHANGELOG in the SETUP_TEMPLATE.sh file (when run, it will remove all the content and create a new file from scratch). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..383218f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Jose Gracia Berenguer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d60bfa8 --- /dev/null +++ b/README.md @@ -0,0 +1,259 @@ + +# 🔥 **Josee9988's GitHub Project Template** + +

+ + @Josee9988/project-template's + +
+ + @Josee9988/project-template's issues + + + @Josee9988/project-template's pull requests + + + @Josee9988/project-template link to create a new repository from the template + + + @Josee9988/project-template's tests + +

+ +--- + +## 🤔 **What is this template all about?** + +* This template can be used as a base layer for any of your future repositories/projects. +* Make your project easy to maintain with **8 issue templates**. +* Quick start your documentation with personalized **README badges** and an extraordinary README structure. +* Manage your issues with **20 issue labels** created just for you! +* Make your _community healthier_ with all the guides like code of conduct, contributing, support, security... +* Learn more with the [official GitHub guide on creating repositories from a template](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template). +* To start using it; "**[click use this template](https://github.com/Josee9988/project-template/generate)**" and create your new repository, +* All the basic setup is made through an easy script that will auto-detect all your data to make it lightning fast! 🗲🗲 Clone your new repository and execute the `SETUP_TEMPLATE.sh` shell script to personalize the files with your private details. Check how to run it [here](https://asciinema.org/a/425259). +* All the markdown follows ["MarkdownLint" rules](https://github.com/DavidAnson/markdownlint). + +--- + +## ⚡ **Installation** + +1. To create a new repository from this template, **[generate your new repository from this template](https://github.com/Josee9988/project-template/generate)**; +for more information or guidance, follow the [GitHub guide](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-from-a-template). +2. Install the [🤖 used GitHub bots](https://github.com/Josee9988/project-template#-used-github-bots) (recommended) +3. Clone your new repository **[generated from this template](https://github.com/Josee9988/project-template/generate)** and `cd` into it. +4. **Execute** the `SETUP_TEMPLATE.sh` shell script to **customize** the files with your data. + + ```bash + bash SETUP_TEMPLATE.sh + ``` + + Or + + ```bash + ./SETUP_TEMPLATE.sh + ``` + + Additionally, watch *[this video](https://asciinema.org/a/425259)* to see **how to execute the script** or use *`bash SETUP_TEMPLATE.sh --help`* to obtain some extra information. + + If the automatic detection of the username, project name or email is NOT correct, please post an issue, and you can **manually correct** them using the optional arguments like: *`bash SETUP_TEMPLATE.sh --username=whatever --projectName=whatever --email=whatever --projectType=whatever`* + +5. **Review** every single file and **customize** it as you like. +6. Build your project. 🚀 + +⚠️ _Customize every file to fit your requirements_ ⚠️ + +--- + +## 📚 **What does it include?** + +1. A **`SETUP_TEMPLATE.sh`** script that **MUST be executed right when you clone your repository**. +The script will customize all the data with yours in all the files. + + 1. A README template file with a default template to start documenting your project. (it includes personalized badges and text with your project details) + 2. A CHANGELOG template file based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + 3. An [issue_label_bot.yaml](/.github/issue_label_bot.yaml) file to use the issue adder GitHub bot. [Activate it or check its documentation](https://github.com/marketplace/issue-label-bot). + 4. A [config.yml](/.github/config.yml) file to modify multiple bot's behaviours. + 5. A [settings.yml](/.github/settings.yml) file to use the popular settings GitHub bot. [Activate it or check its documentation](https://probot.github.io/apps/settings/). + 6. A [CONTRIBUTING](/.github/CONTRIBUTING.md) explaining how to contribute to the project. [Learn more with the GitHub guide](https://docs.github.com/en/github/building-a-strong-community/setting-guidelines-for-repository-contributors). + 7. A [SUPPORT](/.github/SUPPORT.md) explaining how to support the project. [Learn more with the GitHub guide](https://docs.github.com/en/github/building-a-strong-community/adding-support-resources-to-your-project). + 8. A [SECURITY](/.github/SECURITY.md) with a guide on how to post a security issue. [Learn more with the GitHub guide](https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository). + 9. A [CODEOWNERS](/.github/CODEOWNERS) with the new user as the principal owner. [Learn more with the GitHub guide](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners). + 10. A [CODE_OF_CONDUCT](/.github/CODE_OF_CONDUCT.md) with a basic code of conduct. [Learn more with the GitHub guide](https://docs.github.com/en/github/building-a-strong-community/adding-a-code-of-conduct-to-your-project). + 11. A [PULL_REQUEST_TEMPLATE](/.github/pull_request_template.md) with a template for your pull request that closes issues with keywords. [Learn more with the GitHub guide](https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository). + 12. Multiple [issues templates](/.github/ISSUE_TEMPLATE). [Learn more with the GitHub guide](https://docs.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository). + 1. A [config.yml](/.github/ISSUE_TEMPLATE/config.yml) with the config and information about the issue templates. + 2. A [Blank issue template](/.github/ISSUE_TEMPLATE) with the super basic stuff, all the issues should contain. + 3. A [Bug issue template](/.github/ISSUE_TEMPLATE/1-bug-report.md). + 4. A [Failing test issue template](/.github/ISSUE_TEMPLATE/2-failing-test.md). + 5. A [Documentation issue template](/.github/ISSUE_TEMPLATE/3-docs-bug.md). + 6. A [Feature request issue template](/.github/ISSUE_TEMPLATE/4-feature-request.md). + 7. An [Enhancement request issue template](/.github/ISSUE_TEMPLATE/5-enhancement-request.md). + 8. A [Security report issue template](/.github/ISSUE_TEMPLATE/6-security-report.md). + 9. A [Question or support issue template](/.github/ISSUE_TEMPLATE/7-question-support.md). + +--- + +### 🌲 **Project tree** + +Files that will get removed after the execution of `SETUP_TEMPLATE.sh` are not shown! 🙈 + +```text +. +├── CHANGELOG.md +├── .github +│ ├── CODE_OF_CONDUCT.md +│ ├── CODEOWNERS +│ ├── config.yml +│ ├── CONTRIBUTING.md +│ ├── FUNDING.yml +│ ├── issue_label_bot.yaml +│ ├── ISSUE_TEMPLATE +│ │ ├── 1-bug-report.md +│ │ ├── 2-failing-test.md +│ │ ├── 3-docs-bug.md +│ │ ├── 4-feature-request.md +│ │ ├── 5-enhancement-request.md +│ │ ├── 6-security-report.md +│ │ ├── 7-question-support.md +│ │ └── config.yml +│ ├── ISSUE_TEMPLATE.md +│ ├── pull_request_template.md +│ ├── SECURITY.md +│ ├── settings.yml +│ └── SUPPORT.md +├── .gitignore +└── README.md + +2 directories, 22 files +``` + +--- + +## 📝 **Additional notes** + +* After **[generating your new repo with this template](https://github.com/Josee9988/project-template/generate)**, make sure to, right after you clone it, run the script `SETUP_TEMPLATE.sh`. + +* Then, after 'cloning' the repository you will be presented with all the files modified with your project details and information. It is essential to **manually review every file** to check if it fits your requirements and performs any necessary changes to customize the project as you want. + +* If you are using **Windows** and you don't know how to execute the `SETUP_TEMPLATE.sh` script: + 1. Install **[git for Windows](https://git-scm.com/download/win)**. + 2. Right-click on the git repository folder and click "*git bash here*". + 3. Then just perform *`bash SETUP_TEMPLATE.sh`* **or** *`chmod u+x SETUP_TEMPLATE.sh && ./SETUP_TEMPLATE.sh`*. + +### 🤖 **Used GitHub bots** + +These are recommended bots that are prepared and configured for this template. If you install them, your coding experience will probably be much better. +We sincerely recommend at least installing the [issue label bot](https://github.com/marketplace/issue-label-bot) as this bot is the one that adds all the labels used in the issue templates. + +1. The `issue_label_bot.yaml` file depends on the **[issue label bot](https://github.com/marketplace/issue-label-bot)** (✓ highly recommended). +2. The `settings.yml` file depends on the **[settings label bot](https://probot.github.io/apps/settings/)** (optional). +3. The `config.yml` file depends on the bot **[welcome bot](https://probot.github.io/apps/welcome/)** and **[to-do bot](https://probot.github.io/apps/todo/)** (optional). + +--- + +## 📸 **Screenshots** + +A couple of screenshots to delight you before you use this template. + +### 🔺 All the issue templates + +

+ All the issue templates. +

+ +### 🔻 An issue template opened + +

+ Bug issue template opened. +

+ +### 📘 The README template + +Badges and texts will be replaced with your project details! + +

+ README.md template. + + Or watch [this video](https://gifs.com/gif/josee9988-s-readme-md-MwO5E3) to see the whole README template. +

+ +### 🔖 The labels for your issues + +If the bot [probot-settings](https://probot.github.io/apps/settings/) is not installed you will not have these beautiful labels! (there are more issue labels than in the image!) + +

+ LABELS +

+ +### 📝 The CHANGELOG template + +(project name and project type will be replaced with yours) + +

+ CHANGELOG.md template. +

+ +### 🛡️ Security policy + +

+ Security issue. +

+ +### 💼 Community profile at 100% + +

+ Community profile. +

+ +--- + +## 🕵️ **Extra recommendations** + +For the proper maintenance of the CHANGELOG.md, we recommend this [VSCode extension](https://github.com/Josee9988/Changelog-and-Markdown-snippets) +and the read and understanding of the [keep a changelog guide](https://keepachangelog.com/en/1.0.0/). +Please read and comment about it in this [dev.to post](https://dev.to/josee9988/the-ultimate-github-project-template-1264). +We also recommend installing all the [used bots](https://github.com/Josee9988/project-template#-used-github-bots). + +## 💉 **Project tests** + +If you want to improve the development of this project, you must, after changing or improving whatever, run the project's tests to prove that they are working. + +To do so: + +```bash +bash tests/TESTS_RUNNER.sh +``` + +--- + +## 🍰 **Supporters and donators** + + + @Josee9988/project-template's brand logo without text + + +We are currently looking for new donators to help and maintain this project! ❤️ + +By donating, you will help the development of this project, and *you will be featured in this project's README.md*, so everyone can see your kindness and visit your content ⭐. + + + project logo + + +--- + +## 🎉 Was the template helpful? Please help us raise these numbers up + +[![GitHub's followers](https://img.shields.io/github/followers/Josee9988.svg?style=social)](https://github.com/Josee9988) +[![GitHub stars](https://img.shields.io/github/stars/Josee9988/project-template.svg?style=social)](https://github.com/Josee9988/project-template/stargazers) +[![GitHub watchers](https://img.shields.io/github/watchers/Josee9988/project-template.svg?style=social)](https://github.com/Josee9988/project-template/watchers) +[![GitHub forks](https://img.shields.io/github/forks/Josee9988/project-template.svg?style=social)](https://github.com/Josee9988/project-template/network/members) + +Enjoy! 😃 + +> ⚠️ Remember that this template should be reviewed and modified to fit your requirements. +> The script **SETUP_TEMPLATE.sh** should be executed right when you clone your new repository generated from [here](https://github.com/Josee9988/project-template/generate). +> There will be files that will need *manual revision* ⚠️ + +_Made with a lot of ❤️❤️ by **[@Josee9988](https://github.com/Josee9988)**_ diff --git a/SETUP_TEMPLATE.sh b/SETUP_TEMPLATE.sh new file mode 100755 index 0000000..3f98b97 --- /dev/null +++ b/SETUP_TEMPLATE.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# SCRIPT: SETUP_TEMPLATE.sh +# USAGE: bash SETUP_TEMPLATE.sh | ./SETUP_TEMPLATE.sh +# PURPOSE: Shell script that setups the @Josee9988/project-template GitHub project template. +# It detects the user's GitHub username, email and project name, +# and then prompts for the type of project that it is. All the data can be manually specified using +# the script optional arguments. For more information, please execute the script with the '--help' flag. +# After it will customize all the files with the user's data and remove some files and folders, +# even this own script. +# TITLE: SETUP_TEMPLATE +# AUTHOR: @Josee9988 +# VERSION: See in CHANGELOG.md or in variable 'SCRIPT_VERSION'. +# NOTES: This script will auto remove itself, and if you want to rerun it, the user must download +# it again or do a 'git stash' and revert the changes. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +RED='\033[1;31m' # color red +NAME_AND_PROJECT_UNPARSED=$(git ls-remote --get-url) # READ GITHUB USERNAME AND GITHUB PROJECT NAME +NEW_USERNAME=$(echo "$NAME_AND_PROJECT_UNPARSED" | cut -d':' -f 2 | cut -d'/' -f 1) +PROJECT_NAME=$(echo "$NAME_AND_PROJECT_UNPARSED" | cut -d'/' -f 2 | cut -d'.' -f 1) +NEW_EMAIL=$(git config user.email) +TEMP_TEST_OUTPUT=".ignore.test_output.txt" +PROJECT_TYPE="repository" # default value if not specified +will_omit_verification=false +will_omit_commit=false +will_omit_test=false +SCRIPT_VERSION="1.11.8" + +FILE_FUNCTION_HELPERS=bin/FUNCTION_HELPERS.sh + +if [ ! -f "$FILE_FUNCTION_HELPERS" ]; then # check if the function helpers file is not found + echo -e "${RED}X Can not find ${FILE_FUNCTION_HELPERS}" + exit 1 # it will exit if the function helpers file is not found +else + # shellcheck source=bin/FUNCTION_HELPERS.sh disable=SC1091 + source $FILE_FUNCTION_HELPERS || exit 1 # obtain some global functions and variables, if the file isn't found exit +fi + +# PARSE THE ARGUMENTS +for i in "$@"; do + case $i in + -u=* | --user=* | --username=* | --name=*) + NEW_USERNAME="${i#*=}" + shift # past argument=value + ;; + -p=* | --project=* | --project-name=* | --project_name=* | --projectName=*) + PROJECT_NAME="${i#*=}" + shift # past argument=value + ;; + -e=* | --email=* | --mail=*) + NEW_EMAIL="${i#*=}" + shift # past argument=value + ;; + -t=* | --type=* | --project_type=* | --projectType=*) + PROJECT_TYPE="${i#*=}" + shift # past argument=value + ;; + -h | --help | --info | --information) + displayHelpTexts + exit 0 + shift # past argument=value + ;; + -v | --version) + echo -e "${GREEN}$SCRIPT_VERSION${NC}" + exit 0 + shift # past argument=value + ;; + -o | --omit | --omit-commit-and-confirmation) + echo -e "${BBLUE}X Deprecated:${NC} The arguments '--omit-commit-and-confirmation', '-o' and '--omit' are ${RED}deprecated${NC}. Use '--omit-verification' and/or ' --omit-commit' instead." + will_omit_verification=true + will_omit_commit=true + choice="y" + shift # past argument with no value + ;; + --omit-verification) + will_omit_verification=true + choice="y" + shift # past argument with no value + ;; + --omit-commit) + will_omit_commit=true + shift # past argument with no value + ;; + --omit-test-check | --omit-tests-check | --omit-tests) + will_omit_test=true + shift # past argument with no value + ;; + *) # unknown option + echo -e "${RED}X Unknown option:${NC} '${i}', type the flag '${BBLUE}--help${NC}' to view all the options and flags." + ;; + esac +done + +echo -e "Thanks for using ${GREEN}@Josee9988/project-template${NC}" +echo -e "Read all the documentation carefully before you continue executing this script: ${UPURPLE}https://github.com/Josee9988/project-template${NC}\n" + +bash tests/TESTS_RUNNER.sh >/dev/null 2>&1 # PERFORM the TESTS + +if [ "$?" -eq 1 ] && [ $will_omit_test = false ]; then # if when running the tests any error was found + rm "$TEMP_TEST_OUTPUT" 2>/dev/null || : + displayTestErrorTexts + exit 1 +fi + +rm "$TEMP_TEST_OUTPUT" 2>/dev/null || : + +if [ "$PROJECT_TYPE" = "repository" ]; then # if the project's type has not been manually specified + read -p "Enter $(echo -e "$BBLUE""what your project is""$NC") (program/extension/API/web/CLI tool/backend/frontend/scrapper/automation tool/etc): " PROJECT_TYPE +fi + +if [ $will_omit_verification = false ]; then # if the ignore flag has not been manually specified + read -p "Is this data correct: username \"$(echo -e "$GREEN""$NEW_USERNAME""$NC")\", email: \"$(echo -e "$GREEN""$NEW_EMAIL""$NC")\", project name: \"$(echo -e "$GREEN""$PROJECT_NAME""$NC")\", of type: \"$(echo -e "$GREEN""$PROJECT_TYPE""$NC")\" (y/n)? " choice +fi + +# confirm that the data is correct +case "$choice" in +y | Y) + center "Setting everything up for you ;)" + + # replace the username and email + find .github/ -type f -name "*" -print0 | xargs -0 sed -i "s/Josee9988/${NEW_USERNAME}/g" + find .github/ -type f -name "*" -print0 | xargs -0 sed -i "s/jgracia9988@gmail.com/${NEW_EMAIL}/g" + find .github/ -type f -name "*" -print0 | xargs -0 sed -i "s/project-template/${PROJECT_NAME}/g" + find .gitignore -type f -name "*" -print0 | xargs -0 sed -i "s/Josee9988\/project-template/${NEW_USERNAME}\/${PROJECT_NAME}/g" + + rm LICENSE 2>/dev/null || : # remove the license + rm -r bin/ 2>/dev/null || : # remove the bin folder + rm -r tests/ 2>/dev/null || : # remove the tests folder + rm -r .github/workflows/ 2>/dev/null || : # remove the workflow folder + writeREADME # write the new README.md + writeCHANGELOG # write the basic structure of the CHANGELOG.md + echo -e "# add your own funding links" >.github/FUNDING.yml # remove author's custom funding links + + if [ $will_omit_commit = false ]; then # if the ignore option for tests has been specified + git add CHANGELOG.md README.md .gitignore .github SETUP_TEMPLATE.sh LICENSE bin tests # commit the new files + git -c color.status=always status | less -REX # show git status with colours + echo -e "Committing the changes for you :)\n" + git commit -m "📝 Set up '@Josee9988/project-template' template: Personalized files by executing the SETUP_TEMPLATE.sh script.🚀" + echo -e "\nRemember to review every file and customize it as you like.\nYou are ready to start your brand new awesome project🚀🚀." else + fi + + # self remove this script + rm -- "$0" 2>/dev/null || : + ;; +n | N) + echo -e "\nIf your username, project name or email were NOT right, you can manually change them. Read how to do it with the script's help: ${UPURPLE}bash SETUP_TEMPLATE.sh --help${NC}\n" + ;; +*) echo -e "${RED}X Invalid option${NC}" ;; +esac + +exit 0 diff --git a/bin/FUNCTION_HELPERS.sh b/bin/FUNCTION_HELPERS.sh new file mode 100644 index 0000000..181795c --- /dev/null +++ b/bin/FUNCTION_HELPERS.sh @@ -0,0 +1,210 @@ +#!/bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# PURPOSE: Secondary (helper) script that is called by the main SETUP_TEMPLATE.sh file to call +# some functions and obtain some exported variables to better modularize the code. +# TITLE: FUNCTION_HELPERS +# AUTHOR: @Josee9988 | Jose Gracia +# VERSION: See in CHANGELOG.md +# NOTES: This script will auto remove itself, and in case of wanting to run it again, the user must download +# it again or do a 'git stash' and revert the changes. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in ../LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +# SCRIPT WITH EXPORTED FUNCTIONS AND VARIABLES USED IN THE MAIN SETUP_TEMPLATE +RED='\033[1;31m' +export NC='\033[0m' # No Color +export BOLD='\033[1m' +export UPURPLE='\033[4;35m' +export BBLUE='\033[1;34m' +export UGREEN='\033[4;92m' +export GREEN='\033[1;32m' +export CYAN='\e[36m' +export DGRAY='\e[90m' + +# Function that centers a text in the terminal +center() { + term_width="$(tput cols)" + padding="$(printf '%0.1s' ={1..500})" + echo -e "\n${BBLUE}$(printf '%*.*s %s %*.*s\n' 0 "$(((term_width - 2 - ${#1}) / 2))" "$padding" "$1" 0 "$(((term_width - 1 - ${#1}) / 2))" "$padding")${NC}\n" +} + +# Function that displays the error texts in case the project's tests fails. +displayTestErrorTexts() { + echo -e "${RED}X ERROR: The tests failed!${NC}. Please, make sure that you are running this script with its original scaffolding (folder/file) structure without any modification.${NC}" + echo -e "You should try to 'git stash' your changes and execute this script from the project root again, or clone again the repository (the template) without any changes." + echo -e "Remember that your brand new repository should be created from here: ${BOLD}${UPURPLE}https://github.com/Josee9988/project-template/generate${NC}" + echo -e "\nThe program will now exit for you to check if this script is executed right when creating your new repository from the link above." + echo -e "To omit this error and proceed please execute this script again with the flag '${GREEN}--omit-test-check${NC}'" + echo -e "For more information about the script, use the '${BBLUE}--help${NC}' flag." +} + +# Displays the help texts, normally called by the '--help' flag +displayHelpTexts() { # (it will manually detect your git data and prompt for the project type) + center "User help ${DGRAY}$SCRIPT_VERSION${BBLUE}" + echo -e "Script usage: ${UGREEN}bash $0${NC} or ${UGREEN}./$0${NC}\n" + + echo -e "${BOLD}Optional arguments and flags:${NC}" + echo -e " ${CYAN}-u, --username, --name${NC}\t\tManually specify the GitHub username instead of the autodetected username." + echo -e " ${CYAN}-e, --email, --mail${NC}\t\t\tManually specify the GitHub email instead of the autodetected mail." + echo -e " ${CYAN}-t, --projectType, --type${NC}\t\tManually specify the type of project (what it is, eg: npm package or website or whatever) instead of being prompted inside the script." + echo -e " ${CYAN}-h, --help, --info${NC}\t\t\t(${BOLD}${DGRAY}FLAG${NC}) Displays this help text." + echo -e " ${CYAN}-v, --version${NC}\t\t\t\t(${BOLD}${DGRAY}FLAG${NC}) Displays the current script version." + echo -e " ${CYAN}--omit-verification${NC}\t\t\t(${BOLD}${DGRAY}FLAG${NC}) Will not prompt if you are sure about the data." + echo -e " ${CYAN}--omit-commit${NC}\t\t\t\t(${BOLD}${DGRAY}FLAG${NC}) Will not commit the data for your." + echo -e " ${CYAN}--omit-tests, --omit-test-check${NC}\t(${BOLD}${DGRAY}FLAG${NC}) Will not perform the script's tests." + echo -e "${BBLUE}\nAll arguments but the ones marked with ${NC}'${BOLD}${DGRAY}FLAG${NC}'${BBLUE}, require a value after an equal sign (--argument=value) eg: --email=etc@abc.com, the flags are just called without any equal signs.${NC}" + + echo -e "\n${BOLD}Examples of use:${NC}" + echo -e " bash $0" + echo -e " bash $0 -h" + echo -e " bash $0 --projectType=Angular-Website --omit-commit --omit-verification" + echo -e " bash $0 --email=jgracia9988@gmail.com" + echo -e " bash $0 --username=whatever --projectName=whatever --email=whatever --projectType=whatever${NC}" + echo -e " bash $0 -u=Josee9988 --projectType=Github-template --omit-commit${NC}\n" + + echo -e "The username, project-name and email are automatically gathered from your git repository and git config." + echo -e "Make sure you have ${BBLUE}read the documentation before executing${NC} this script: ${UPURPLE}https://github.com/Josee9988/project-template${NC}" + echo -e "If you have any questions or if any issue is found, please make sure to report it at: ${UPURPLE}https://github.com/Josee9988/project-template/issues${NC}" +} + +# Function that writes and parses variables to write the new generated README.md file +writeREADME() { + PROJECT_NAME_PARSED=${PROJECT_NAME/-/ } + bash -c "NEW_USERNAME='NEW_USERNAME' PROJECT_NAME='PROJECT_NAME' PROJECT_TYPE='PROJECT_TYPE'; cat << EOF > README.md + + +# 🔥 **$NEW_USERNAME/$PROJECT_NAME** + +
+ + + \"@$NEW_USERNAME/$PROJECT_NAME's + +
+ + \"$NEW_USERNAME/$PROJECT_NAME's + + + \"$NEW_USERNAME/$PROJECT_NAME's + +
+ +--- + +## 🤔 **About the project** + +* + +--- + +## ⚡ **Installation** + +* + +--- + +## 🚀 **Usage** + +* + +--- + +## 🌲 **Project tree** + + + +--- + +## 📝 **Additional notes** + +* + +--- + +## 📸 **Screenshots** + + + +--- + +## 🍰 **Supporters and donators** + + + + \"@$NEW_USERNAME/$PROJECT_NAME_PARSED's + + + +We are currently looking for new donators to help and maintain this project! ❤️ + +By donating, you will help the development of this project, and *you will be featured in this $PROJECT_NAME's README.md*, so everyone can see your kindness and visit your content ⭐. + + + + + + + +--- + +$PROJECT_NAME was generated from *[Josee9988/project-template](https://github.com/Josee9988/project-template)* 📚 + +--- + +## 🕵️ Extra recommendations + +* + +--- + +## 🎉 Was the $PROJECT_TYPE helpful? Help us raise these numbers up + +[![GitHub followers](https://img.shields.io/github/followers/$NEW_USERNAME.svg?style=social)](https://github.com/$NEW_USERNAME) +[![GitHub stars](https://img.shields.io/github/stars/$NEW_USERNAME/$PROJECT_NAME.svg?style=social)](https://github.com/$NEW_USERNAME/$PROJECT_NAME/stargazers) +[![GitHub watchers](https://img.shields.io/github/watchers/$NEW_USERNAME/$PROJECT_NAME.svg?style=social)](https://github.com/$NEW_USERNAME/$PROJECT_NAME/watchers) +[![GitHub forks](https://img.shields.io/github/forks/$NEW_USERNAME/$PROJECT_NAME.svg?style=social)](https://github.com/$NEW_USERNAME/$PROJECT_NAME/network/members) + +[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=github-sponsors&color=red&style=social)](https://github.com/sponsors/$NEW_USERNAME) + +Enjoy! 😃 + +--- + +## ⚖️📝 **License and Changelog** + +See the license in the '**[LICENSE](LICENSE)**' file. + +Watch the changes in the '**[CHANGELOG.md](CHANGELOG.md)**' file. + +--- + +_Made with a lot of ❤️❤️ by **[@$NEW_USERNAME](https://github.com/$NEW_USERNAME)**_ +EOF" +} + +# Function that writes and parses variables to write the new generated CHANGELOG.md file +writeCHANGELOG() { + ACTUAL_DATE=$(date '+%Y-%m-%d') + bash -c "PROJECT_NAME='PROJECT_NAME' PROJECT_TYPE='PROJECT_TYPE' ACTUAL_DATE='ACTUAL_DATE'; cat << EOF > CHANGELOG.md + +# **Change Log** 📜📝 + +All notable changes to the \"**$PROJECT_NAME**\" $PROJECT_TYPE will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [**0.0.1**] - $ACTUAL_DATE + +### Added + +* The basic project structure from **[josee9988/project-template](https://github.com/Josee9988/project-template)**. +EOF" +} diff --git a/bin/README.md b/bin/README.md new file mode 100644 index 0000000..628396b --- /dev/null +++ b/bin/README.md @@ -0,0 +1,9 @@ +# Folder **bin/** + +* Folder with additional scripts or executables to help with the development of the project. + +## Files + +### The *bin/FUNCTION_HELPERS.sh* + +* Secondary (helper) script that is called by the main "../SETUP_TEMPLATE.sh" file to call some functions and obtain some exported variables to better modularize the code. diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..a98689e --- /dev/null +++ b/tests/README.md @@ -0,0 +1,25 @@ +# Folder **tests/** + +* Folder with all the tests used to test the "../SETUP_TEMPLATE.sh" script. + +## Files + +### The *tests/shunit2* + +* Framework used for the unit tests; more info can be found in the [shunit2's GitHub repository](https://github.com/kward/shunit2). + +### The *tests/argument_help_parser.sh* + +* Test suite for testing the help flag (--help). + +### The *tests/custom_data_test.sh* + +* Test suite for testing the modified custom data after executing the SETUP_TEMPLATE script. + +### The *tests/project_scaffolding_test.sh* + +* Test suite for testing the project scaffolding after executing the SETUP_TEMPLATE script. + +### The *tests/TESTS_RUNNER.sh* + +* Main test script that will call all the individual unitary tests. Exit code 1 means an error in one or more tests was found; otherwise, the exit code will be 0. diff --git a/tests/TESTS_RUNNER.sh b/tests/TESTS_RUNNER.sh new file mode 100755 index 0000000..eabe4f2 --- /dev/null +++ b/tests/TESTS_RUNNER.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# PURPOSE: Main test script that will call all the individual unitary tests. Exit code 1 means an error in one +# or more tests were found; otherwise, the exit code will be 0. +# TITLE: TESTS_RUNNER +# AUTHOR: @Josee9988 | Jose Gracia +# VERSION: See in ./../CHANGELOG.md +# NOTES: This script does not contain any test; it only calls all the tests one by one. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in ../LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +LGREEN='\033[0;32m' +RED='\033[1;31m' +GREEN='\033[1;32m' +NC='\033[0m' # No Color +TESTS_TRASH_DIR="tests/.ignore.tests_trash/" +TEMP_TEST_OUTPUT=".ignore.test_runner_output.txt" +declare -a test_files=("tests/project_scaffolding_test.sh" "tests/custom_data_test.sh" "tests/argument_help_parser.sh") # all the tests + +center() { + term_width="$(tput cols)" + padding="$(printf '%0.1s' +{1..500})" + echo -e "\n${LGREEN}$(printf '%*.*s %s %*.*s\n' 0 "$(((term_width - 2 - ${#1}) / 2))" "$padding" "$1" 0 "$(((term_width - 1 - ${#1}) / 2))" "$padding")${NC}" +} + +rm -r $TESTS_TRASH_DIR 2>/dev/null || : # remove any possible old test run trash files + +# run all the tests +for file in "${test_files[@]}"; do + mkdir -p tests/.ignore.tests_trash # create the files where the tests will attack upon + center "TEST: running test ./$file" + ./"$file" | tee -a $TEMP_TEST_OUTPUT # run the test + rm -r $TESTS_TRASH_DIR # remove the previously created files +done + +if grep -q "FAILED" "$TEMP_TEST_OUTPUT"; then # if when running the tests any error was found + echo -e "\n${RED}X TESTS FAILED: One or more tests have failed!\nPlease check the output above${NC}" + rm "$TEMP_TEST_OUTPUT" 2>/dev/null || : + exit 1 # exit unsuccessfully +else # tests ran OK + rm "$TEMP_TEST_OUTPUT" 2>/dev/null || : + echo -e "\n${GREEN}✓ All tests ran successfully${NC}" + exit 0 # exit successfully +fi diff --git a/tests/argument_help_parser.sh b/tests/argument_help_parser.sh new file mode 100755 index 0000000..eb88d72 --- /dev/null +++ b/tests/argument_help_parser.sh @@ -0,0 +1,75 @@ +#! /bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# PURPOSE: Test suite for testing the help flag (--help). +# TITLE: Argument help parser tests +# AUTHOR: @Josee9988 | Jose Gracia +# VERSION: See in ./../CHANGELOG.md +# NOTES: This script is called by the TESTS_RUNNER.sh script. And it unit tests the newly generated scaffolding +# generated by the SETUP_TEMPLATE script. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in ../LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +TESTS_TRASH_DIR="tests/.ignore.tests_trash" +MAIL="FAKE_EMAIL_TESTS" +SCRIPT_OUTPUT="script_output.txt" + +setUp() { + cp -r ./* $TESTS_TRASH_DIR --copy-content 2>/dev/null || : + cp -r .github/ $TESTS_TRASH_DIR --copy-contents + cp -r bin/ $TESTS_TRASH_DIR --copy-contents + cp .gitignore $TESTS_TRASH_DIR --copy-contents + rm -r $TESTS_TRASH_DIR/tests/ 2>/dev/null || : + rm -r $TESTS_TRASH_DIR/.git/ 2>/dev/null || : + cd $TESTS_TRASH_DIR || exit +} + +tearDown() { + rm $SCRIPT_OUTPUT 2>/dev/null || : + cd "../.." || exit +} + +# TESTS +suite() { + suite_addTest testHelp + suite_addTest testHelpWithOtherArguments + suite_addTest testFilesAreNotChanged +} + +testHelp() { + expected_output="Script usage:" + expected_output2="read the documentation before executing" + expected_output3="User help" + bash SETUP_TEMPLATE.sh -h --omit-test-check --omit-test-check >script_output.txt # run the setup script + assertTrue " help output was not found" "grep -q \"$expected_output\" \"$SCRIPT_OUTPUT\"" + assertTrue " help output was not found" "grep -q \"$expected_output2\" \"$SCRIPT_OUTPUT\"" + assertTrue " help output was not found" "grep -q \"$expected_output3\" \"$SCRIPT_OUTPUT\"" +} + +testHelpWithOtherArguments() { + expected_output="Script usage:" + expected_output2="read the documentation before executing" + expected_output3="User help" + bash SETUP_TEMPLATE.sh --omit-commit --omit-verification --project=aaa --help --type=bbb --omit-test-check >$SCRIPT_OUTPUT # run the setup script + assertTrue " help output was not found" "grep -q \"$expected_output\" \"$SCRIPT_OUTPUT\"" + assertTrue " help output was not found" "grep -q \"$expected_output2\" \"$SCRIPT_OUTPUT\"" + assertTrue " help output was not found" "grep -q \"$expected_output3\" \"$SCRIPT_OUTPUT\"" +} + +testFilesAreNotChanged() { + bash SETUP_TEMPLATE.sh --help --omit-commit --omit-verification --project=aaa --type=bbb --omit-test-check >$SCRIPT_OUTPUT # run the setup script + + if [ ! -f "SETUP_TEMPLATE.sh" ] || [ ! -d "bin/" ] || [ ! -f "LICENSE" ]; then + assertTrue " files were removed and the help command should not modify the files" false + else + assertTrue " files were not removed (all ok)" true + fi +} + +# Load and run shUnit2. +. tests/shunit2 diff --git a/tests/custom_data_test.sh b/tests/custom_data_test.sh new file mode 100755 index 0000000..ef27c46 --- /dev/null +++ b/tests/custom_data_test.sh @@ -0,0 +1,100 @@ +#! /bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# PURPOSE: Test suite for testing the modified custom data after executing the SETUP_TEMPLATE script. +# TITLE: Custom Data tests +# AUTHOR: @Josee9988 | Jose Gracia +# VERSION: See in ./../CHANGELOG.md +# NOTES: This script is called by the TESTS_RUNNER.sh script. And it unit tests all the custom data modified +# by the SETUP_TEMPLATE script. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in ../LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +TESTS_TRASH_DIR="tests/.ignore.tests_trash" +USERNAME="FAKE_USERNAME_TESTS" +NAME="FAKE_NAME_TESTS" +MAIL="FAKE_EMAIL_TESTS" +TYPE="FAKE_TYPE_TESTS" + +oneTimeSetUp() { + cp -r ./* $TESTS_TRASH_DIR --copy-content 2>/dev/null || : + cp -r .github/ $TESTS_TRASH_DIR --copy-contents + cp -r bin/ $TESTS_TRASH_DIR --copy-contents + cp .gitignore $TESTS_TRASH_DIR --copy-contents + rm -r $TESTS_TRASH_DIR/tests/ 2>/dev/null || : + rm -r $TESTS_TRASH_DIR/.git/ 2>/dev/null || : + cd $TESTS_TRASH_DIR || exit + bash SETUP_TEMPLATE.sh --username=$USERNAME --projectName=$NAME --email=$MAIL --projectType=$TYPE --omit-commit --omit-verification --omit-test-check >/dev/null # run the setup script +} + +oneTimeTearDown() { + cd "../.." || exit +} + +# TESTS +suite() { + suite_addTest testDotGithubISSUE_TEMPLATEAsignees + suite_addTest testDotGithubISSUE_TEMPLATEConfig + suite_addTest testDotGithubConfig + suite_addTest testDotGithubSecurity + suite_addTest testDotGithubCODEOWNERS + suite_addTest testDotGitignore + suite_addTest testChangelog +} + +testDotGithubISSUE_TEMPLATEAsignees() { + assigneesWithName="assignees: $USERNAME" + declare -a files=( + ".github/ISSUE_TEMPLATE/1-bug-report.md" ".github/ISSUE_TEMPLATE/2-failing-test.md" + ".github/ISSUE_TEMPLATE/3-docs-bug.md" ".github/ISSUE_TEMPLATE/4-feature-request.md" + ".github/ISSUE_TEMPLATE/5-enhancement-request.md" ".github/ISSUE_TEMPLATE/6-security-report.md" + ".github/ISSUE_TEMPLATE/7-question-support.md") + + for file in "${files[@]}"; do + assertTrue " assignee was not found for file $file" "grep -q \"$assigneesWithName\" \"$file\"" + done +} +testDotGithubISSUE_TEMPLATEConfig() { + mailInConfig="url: mailto:$MAIL" + assertTrue "The mail $MAIL was not found in .github/ISSUE_TEMPLATE/config.yml" "grep -q \"$mailInConfig\" \".github/ISSUE_TEMPLATE/config.yml\"" +} + +testDotGithubConfig() { + newIssueWelcomeComment="Thanks for opening your first issue in $USERNAME/$NAME! Be sure to" + assertTrue "The $USERNAME/$NAME was not found in " "grep -q \"$newIssueWelcomeComment\" \".github/config.yml\"" +} + +testDotGithubSecurity() { + securityData1="(mailto:$MAIL)" + securityData2="[$MAIL]" + securityData3="he project's team and community take security issues" + assertTrue "The mail $MAIL was not found in .github/SECURITY.md" "grep -q \"$securityData1\" \".github/SECURITY.md\" && grep -q \"$securityData2\" \".github/SECURITY.md\" && grep -q \"$securityData3\" \".github/SECURITY.md\"" +} + +testDotGithubCODEOWNERS() { + usernameData="$USERNAME" + assertTrue "Could not find the username $USERNAME in the file .github/CODEOWNERS" "grep -q \"$usernameData\" \".github/CODEOWNERS\"" +} + +testDotGitignore() { + gitignoreData1="###> $USERNAME/$NAME ###" + gitignoreData2="###< $USERNAME/$NAME ###" + + assertTrue "Could not find the username $USERNAME and the name $NAME in the .gitignore file" "grep -q \"$gitignoreData1\" \".gitignore\" && grep -q \"$gitignoreData2\" \".gitignore\"" +} + +testChangelog() { + changelogData1="All notable changes to the" + changelogData2="**$NAME**" + changelogData3="$TYPE will be documented in this file." + + assertTrue "Could not find the name $NAME or the type $TYPE in the CHANGELOG.md file" "grep -q \"$changelogData1\" \"CHANGELOG.md\" && grep -q \"$changelogData2\" \"CHANGELOG.md\" && grep -q \"$changelogData3\" \"CHANGELOG.md\"" +} + +# Load and run shUnit2. +. tests/shunit2 diff --git a/tests/project_scaffolding_test.sh b/tests/project_scaffolding_test.sh new file mode 100755 index 0000000..467659d --- /dev/null +++ b/tests/project_scaffolding_test.sh @@ -0,0 +1,110 @@ +#! /bin/bash + +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# +# PURPOSE: Test suite for testing the project scaffolding after executing the SETUP_TEMPLATE script. +# TITLE: Project Scaffolding tests +# AUTHOR: @Josee9988 | Jose Gracia +# VERSION: See in ./../CHANGELOG.md +# NOTES: This script is called by the TESTS_RUNNER.sh script. And it unit tests the newly generated scaffolding +# generated by the SETUP_TEMPLATE script. +# BASH_VERSION: 5.1.4(1)-release (x86_64-pc-linux-gnu) +# LICENSE: see in ../LICENSE (project root) or https://github.com/Josee9988/project-template/blob/master/LICENSE +# GITHUB: https://github.com/Josee9988/ +# REPOSITORY: https://github.com/Josee9988/project-template +# ISSUES: https://github.com/Josee9988/project-template/issues +# MAIL: jgracia9988@gmail.com +#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~# + +TESTS_TRASH_DIR="tests/.ignore.tests_trash" +USERNAME="FAKE_USERNAME_TESTS" +NAME="FAKE_NAME_TESTS" +MAIL="FAKE_EMAIL_TESTS" +TYPE="FAKE_TYPE_TESTS" + +oneTimeSetUp() { + cp -r ./* $TESTS_TRASH_DIR --copy-content 2>/dev/null || : + cp -r .github/ $TESTS_TRASH_DIR --copy-contents + cp -r bin/ $TESTS_TRASH_DIR --copy-contents + cp .gitignore $TESTS_TRASH_DIR --copy-contents + rm -r $TESTS_TRASH_DIR/tests/ 2>/dev/null || : + rm -r $TESTS_TRASH_DIR/.git/ 2>/dev/null || : + cd $TESTS_TRASH_DIR || exit + bash SETUP_TEMPLATE.sh --username=$USERNAME --projectName=$NAME --email=$MAIL --projectType=$TYPE --omit-commit --omit-verification --omit-test-check >/dev/null # run the setup script +} + +oneTimeTearDown() { + cd "../.." || exit +} + +# TESTS +suite() { + suite_addTest testDotGithubFolder + suite_addTest testDotGithubISSUE_TEMPLATE + suite_addTest testDotGithubISSUE_TEMPLATEFiles + suite_addTest testDotGithubFiles + suite_addTest testTestRemovedFiles + suite_addTest testGlobalFiles + suite_addTest testRemovedFiles +} + +testDotGithubFolder() { + if [ ! -e ".github/" ]; then + assertEquals ".github file does not exist" 1 0 # error + fi +} + +testDotGithubISSUE_TEMPLATE() { + if [ ! -e ".github/ISSUE_TEMPLATE" ]; then + assertEquals ".github/ISSUE_TEMPLATE was not found" 1 0 # error + fi +} + +testDotGithubISSUE_TEMPLATEFiles() { + declare -a files=( + ".github/ISSUE_TEMPLATE/1-bug-report.md" ".github/ISSUE_TEMPLATE/2-failing-test.md" + ".github/ISSUE_TEMPLATE/3-docs-bug.md" ".github/ISSUE_TEMPLATE/4-feature-request.md" + ".github/ISSUE_TEMPLATE/5-enhancement-request.md" ".github/ISSUE_TEMPLATE/6-security-report.md" + ".github/ISSUE_TEMPLATE/7-question-support.md") + + for file in "${files[@]}"; do + assertTrue " $file does not exist" "[ -e \"$file\" ]" + done +} + +testDotGithubFiles() { + declare -a files=( + ".github/CODEOWNERS" ".github/CODE_OF_CONDUCT.md" ".github/CONTRIBUTING.md" ".github/ISSUE_TEMPLATE.md" + ".github/pull_request_template.md" ".github/SECURITY.md" ".github/SUPPORT.md" ".github/issue_label_bot.yaml" + ".github/config.yml" ".github/FUNDING.yml" ".github/settings.yml") + + for file in "${files[@]}"; do + assertTrue " $file does not exist" "[ -e \"$file\" ]" + done +} + +testTestRemovedFiles() { + filesFound=0 + if [ -e "tests/" ] && [ -e "tests/shunit2" ] && [ -e "tests/TESTS_RUNNER.sh" ]; then + filesFound=1 + fi + assertNotEquals " tests folder of some files were found" 1 $filesFound +} + +testGlobalFiles() { + filesFound=0 + if [ -e ".gitignore" ] && [ -e "CHANGELOG.md" ] && [ -e "README.md" ]; then + filesFound=1 + fi + assertEquals " gitignore, changelog or readme were not found" 1 $filesFound +} + +testRemovedFiles() { + filesFound=0 + if [ -e "LICENSE" ] && [ -e "bin" ] && [ -e "bin/FUNCTION_HELPERS.sh" ]; then + filesFound=1 + fi + assertNotEquals " LICENSE or the bin directory were found" 1 $filesFound +} + +# Load and run shUnit2. +. tests/shunit2 diff --git a/tests/shunit2 b/tests/shunit2 new file mode 100755 index 0000000..6239683 --- /dev/null +++ b/tests/shunit2 @@ -0,0 +1,1343 @@ +#! /bin/sh +# vim:et:ft=sh:sts=2:sw=2 +# +# Copyright 2008-2020 Kate Ward. All Rights Reserved. +# Released under the Apache 2.0 license. +# http://www.apache.org/licenses/LICENSE-2.0 +# +# shUnit2 -- Unit testing framework for Unix shell scripts. +# https://github.com/kward/shunit2 +# +# Author: kate.ward@forestent.com (Kate Ward) +# +# shUnit2 is a xUnit based unit test framework for Bourne shell scripts. It is +# based on the popular JUnit unit testing framework for Java. +# +# $() are not fully portable (POSIX != portable). +# shellcheck disable=SC2006 +# expr may be antiquated, but it is the only solution in some cases. +# shellcheck disable=SC2003 + +# Return if shunit2 already loaded. +command [ -n "${SHUNIT_VERSION:-}" ] && exit 0 +SHUNIT_VERSION='2.1.8' + +# Return values that scripts can use. +SHUNIT_TRUE=0 +SHUNIT_FALSE=1 +SHUNIT_ERROR=2 + +# Logging functions. +_shunit_warn() { + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_yellow}shunit2:WARN${__shunit_ansi_none} $*" >&2 +} +_shunit_error() { + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_red}shunit2:ERROR${__shunit_ansi_none} $*" >&2 +} +_shunit_fatal() { + ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_red}shunit2:FATAL${__shunit_ansi_none} $*" >&2 + exit ${SHUNIT_ERROR} +} + +# Determine some reasonable command defaults. +__SHUNIT_CMD_ECHO_ESC='echo -e' +# shellcheck disable=SC2039 +command [ "`echo -e test`" = '-e test' ] && __SHUNIT_CMD_ECHO_ESC='echo' + +__SHUNIT_UNAME_S=`uname -s` +case "${__SHUNIT_UNAME_S}" in + BSD) __SHUNIT_CMD_EXPR='gexpr' ;; + *) __SHUNIT_CMD_EXPR='expr' ;; +esac +__SHUNIT_CMD_TPUT='tput' + +# Commands a user can override if needed. +SHUNIT_CMD_EXPR=${SHUNIT_CMD_EXPR:-${__SHUNIT_CMD_EXPR}} +SHUNIT_CMD_TPUT=${SHUNIT_CMD_TPUT:-${__SHUNIT_CMD_TPUT}} + +# Enable color output. Options are 'never', 'always', or 'auto'. +SHUNIT_COLOR=${SHUNIT_COLOR:-auto} + +# Specific shell checks. +if command [ -n "${ZSH_VERSION:-}" ]; then + setopt |grep "^shwordsplit$" >/dev/null + if command [ $? -ne ${SHUNIT_TRUE} ]; then + _shunit_fatal 'zsh shwordsplit option is required for proper operation' + fi + if command [ -z "${SHUNIT_PARENT:-}" ]; then + _shunit_fatal "zsh does not pass \$0 through properly. please declare \ +\"SHUNIT_PARENT=\$0\" before calling shUnit2" + fi +fi + +# +# Constants +# + +__SHUNIT_MODE_SOURCED='sourced' +__SHUNIT_MODE_STANDALONE='standalone' +__SHUNIT_PARENT=${SHUNIT_PARENT:-$0} + +# User provided test prefix to display in front of the name of the test being +# executed. Define by setting the SHUNIT_TEST_PREFIX variable. +__SHUNIT_TEST_PREFIX=${SHUNIT_TEST_PREFIX:-} + +# ANSI colors. +__SHUNIT_ANSI_NONE='\033[0m' +__SHUNIT_ANSI_RED='\033[1;31m' +__SHUNIT_ANSI_GREEN='\033[1;32m' +__SHUNIT_ANSI_YELLOW='\033[1;33m' +__SHUNIT_ANSI_CYAN='\033[1;36m' + +# Set the constants readonly. +__shunit_constants=`set |grep '^__SHUNIT_' |cut -d= -f1` +echo "${__shunit_constants}" |grep '^Binary file' >/dev/null && \ + __shunit_constants=`set |grep -a '^__SHUNIT_' |cut -d= -f1` +for __shunit_const in ${__shunit_constants}; do + if command [ -z "${ZSH_VERSION:-}" ]; then + readonly "${__shunit_const}" + else + case ${ZSH_VERSION} in + [123].*) readonly "${__shunit_const}" ;; + *) readonly -g "${__shunit_const}" # Declare readonly constants globally. + esac + fi +done +unset __shunit_const __shunit_constants + +# +# Internal variables. +# + +# Variables. +__shunit_lineno='' # Line number of executed test. +__shunit_mode=${__SHUNIT_MODE_SOURCED} # Operating mode. +__shunit_reportGenerated=${SHUNIT_FALSE} # Is report generated. +__shunit_script='' # Filename of unittest script (standalone mode). +__shunit_skip=${SHUNIT_FALSE} # Is skipping enabled. +__shunit_suite='' # Suite of tests to execute. +__shunit_clean=${SHUNIT_FALSE} # _shunit_cleanup() was already called. + +# ANSI colors (populated by _shunit_configureColor()). +__shunit_ansi_none='' +__shunit_ansi_red='' +__shunit_ansi_green='' +__shunit_ansi_yellow='' +__shunit_ansi_cyan='' + +# Counts of tests. +__shunit_testSuccess=${SHUNIT_TRUE} +__shunit_testsTotal=0 +__shunit_testsPassed=0 +__shunit_testsFailed=0 + +# Counts of asserts. +__shunit_assertsTotal=0 +__shunit_assertsPassed=0 +__shunit_assertsFailed=0 +__shunit_assertsSkipped=0 + +# +# Macros. +# + +# shellcheck disable=SC2016,SC2089 +_SHUNIT_LINENO_='eval __shunit_lineno=""; if command [ "${1:-}" = "--lineno" ]; then command [ -n "$2" ] && __shunit_lineno="[$2] "; shift 2; fi' + +#----------------------------------------------------------------------------- +# Assertion functions. +# + +# Assert that two values are equal to one another. +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertEquals() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertEquals() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_expected_=$1 + shunit_actual_=$2 + + shunit_return=${SHUNIT_TRUE} + if command [ "${shunit_expected_}" = "${shunit_actual_}" ]; then + _shunit_assertPass + else + failNotEquals "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_expected_ shunit_actual_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_EQUALS_='eval assertEquals --lineno "${LINENO:-}"' + +# Assert that two values are not equal to one another. +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNotEquals() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertNotEquals() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_expected_=$1 + shunit_actual_=$2 + + shunit_return=${SHUNIT_TRUE} + if command [ "${shunit_expected_}" != "${shunit_actual_}" ]; then + _shunit_assertPass + else + failSame "${shunit_message_}" "${shunit_expected_}" "${shunit_actual_}" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_expected_ shunit_actual_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NOT_EQUALS_='eval assertNotEquals --lineno "${LINENO:-}"' + +# Assert that a container contains a content. +# +# Args: +# message: string: failure message [optional] +# container: string: container to analyze +# content: string: content to find +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertContains() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertContains() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_container_=$1 + shunit_content_=$2 + + shunit_return=${SHUNIT_TRUE} + if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then + _shunit_assertPass + else + failNotFound "${shunit_message_}" "${shunit_content_}" + shunit_return=${SHUNIT_FALSE} + fi + + unset shunit_message_ shunit_container_ shunit_content_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_CONTAINS_='eval assertContains --lineno "${LINENO:-}"' + +# Assert that a container does not contain a content. +# +# Args: +# message: string: failure message [optional] +# container: string: container to analyze +# content: string: content to look for +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNotContains() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertNotContains() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_container_=$1 + shunit_content_=$2 + + shunit_return=${SHUNIT_TRUE} + if echo "$shunit_container_" | grep -F -- "$shunit_content_" > /dev/null; then + failFound "${shunit_message_}" "${shunit_content_}" + shunit_return=${SHUNIT_FALSE} + else + _shunit_assertPass + fi + + unset shunit_message_ shunit_container_ shunit_content_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NOT_CONTAINS_='eval assertNotContains --lineno "${LINENO:-}"' + +# Assert that a value is null (i.e. an empty string) +# +# Args: +# message: string: failure message [optional] +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNull() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error "assertNull() requires one or two arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + assertTrue "${shunit_message_}" "[ -z '$1' ]" + shunit_return=$? + + unset shunit_message_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NULL_='eval assertNull --lineno "${LINENO:-}"' + +# Assert that a value is not null (i.e. a non-empty string) +# +# Args: +# message: string: failure message [optional] +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNotNull() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -gt 2 ]; then # allowing 0 arguments as $1 might actually be null + _shunit_error "assertNotNull() requires one or two arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_actual_=`_shunit_escapeCharactersInString "${1:-}"` + test -n "${shunit_actual_}" + assertTrue "${shunit_message_}" $? + shunit_return=$? + + unset shunit_actual_ shunit_message_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NOT_NULL_='eval assertNotNull --lineno "${LINENO:-}"' + +# Assert that two values are the same (i.e. equal to one another). +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertSame() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertSame() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + assertEquals "${shunit_message_}" "$1" "$2" + shunit_return=$? + + unset shunit_message_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_SAME_='eval assertSame --lineno "${LINENO:-}"' + +# Assert that two values are not the same (i.e. not equal to one another). +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertNotSame() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "assertNotSame() requires two or three arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_:-}$1" + shift + fi + assertNotEquals "${shunit_message_}" "$1" "$2" + shunit_return=$? + + unset shunit_message_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_NOT_SAME_='eval assertNotSame --lineno "${LINENO:-}"' + +# Assert that a value or shell test condition is true. +# +# In shell, a value of 0 is true and a non-zero value is false. Any integer +# value passed can thereby be tested. +# +# Shell supports much more complicated tests though, and a means to support +# them was needed. As such, this function tests that conditions are true or +# false through evaluation rather than just looking for a true or false. +# +# The following test will succeed: +# assertTrue 0 +# assertTrue "[ 34 -gt 23 ]" +# The following test will fail with a message: +# assertTrue 123 +# assertTrue "test failed" "[ -r '/non/existent/file' ]" +# +# Args: +# message: string: failure message [optional] +# condition: string: integer value or shell conditional statement +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertTrue() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error "assertTrue() takes one or two arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_condition_=$1 + + # See if condition is an integer, i.e. a return value. + shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` + shunit_return=${SHUNIT_TRUE} + if command [ -z "${shunit_condition_}" ]; then + # Null condition. + shunit_return=${SHUNIT_FALSE} + elif command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] + then + # Possible return value. Treating 0 as true, and non-zero as false. + command [ "${shunit_condition_}" -ne 0 ] && shunit_return=${SHUNIT_FALSE} + else + # Hopefully... a condition. + ( eval "${shunit_condition_}" ) >/dev/null 2>&1 + command [ $? -ne 0 ] && shunit_return=${SHUNIT_FALSE} + fi + + # Record the test. + if command [ ${shunit_return} -eq ${SHUNIT_TRUE} ]; then + _shunit_assertPass + else + _shunit_assertFail "${shunit_message_}" + fi + + unset shunit_message_ shunit_condition_ shunit_match_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_TRUE_='eval assertTrue --lineno "${LINENO:-}"' + +# Assert that a value or shell test condition is false. +# +# In shell, a value of 0 is true and a non-zero value is false. Any integer +# value passed can thereby be tested. +# +# Shell supports much more complicated tests though, and a means to support +# them was needed. As such, this function tests that conditions are true or +# false through evaluation rather than just looking for a true or false. +# +# The following test will succeed: +# assertFalse 1 +# assertFalse "[ 'apples' = 'oranges' ]" +# The following test will fail with a message: +# assertFalse 0 +# assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]" +# +# Args: +# message: string: failure message [optional] +# condition: string: integer value or shell conditional statement +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +assertFalse() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error "assertFalse() requires one or two arguments; $# given" + _shunit_assertFail + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_condition_=$1 + + # See if condition is an integer, i.e. a return value. + shunit_match_=`expr "${shunit_condition_}" : '\([0-9]*\)'` + shunit_return=${SHUNIT_TRUE} + if command [ -z "${shunit_condition_}" ]; then + # Null condition. + shunit_return=${SHUNIT_FALSE} + elif command [ -n "${shunit_match_}" -a "${shunit_condition_}" = "${shunit_match_}" ] + then + # Possible return value. Treating 0 as true, and non-zero as false. + command [ "${shunit_condition_}" -eq 0 ] && shunit_return=${SHUNIT_FALSE} + else + # Hopefully... a condition. + ( eval "${shunit_condition_}" ) >/dev/null 2>&1 + command [ $? -eq 0 ] && shunit_return=${SHUNIT_FALSE} + fi + + # Record the test. + if command [ "${shunit_return}" -eq "${SHUNIT_TRUE}" ]; then + _shunit_assertPass + else + _shunit_assertFail "${shunit_message_}" + fi + + unset shunit_message_ shunit_condition_ shunit_match_ + return "${shunit_return}" +} +# shellcheck disable=SC2016,SC2034 +_ASSERT_FALSE_='eval assertFalse --lineno "${LINENO:-}"' + +#----------------------------------------------------------------------------- +# Failure functions. +# + +# Records a test failure. +# +# Args: +# message: string: failure message [optional] +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +fail() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -gt 1 ]; then + _shunit_error "fail() requires zero or one arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 1 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + + _shunit_assertFail "${shunit_message_}" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_='eval fail --lineno "${LINENO:-}"' + +# Records a test failure, stating two values were not equal. +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failNotEquals() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "failNotEquals() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_expected_=$1 + shunit_actual_=$2 + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected:<${shunit_expected_}> but was:<${shunit_actual_}>" + + unset shunit_message_ shunit_expected_ shunit_actual_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_NOT_EQUALS_='eval failNotEquals --lineno "${LINENO:-}"' + +# Records a test failure, stating a value was found. +# +# Args: +# message: string: failure message [optional] +# content: string: found value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failFound() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error "failFound() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }Found" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_FOUND_='eval failFound --lineno "${LINENO:-}"' + +# Records a test failure, stating a content was not found. +# +# Args: +# message: string: failure message [optional] +# content: string: content not found +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failNotFound() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 1 -o $# -gt 2 ]; then + _shunit_error "failNotFound() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 2 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + shunit_content_=$1 + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }Not found:<${shunit_content_}>" + + unset shunit_message_ shunit_content_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_NOT_FOUND_='eval failNotFound --lineno "${LINENO:-}"' + +# Records a test failure, stating two values should have been the same. +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failSame() +{ + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "failSame() requires two or three arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + + shunit_message_=${shunit_message_%% } + _shunit_assertFail "${shunit_message_:+${shunit_message_} }expected not same" + + unset shunit_message_ + return ${SHUNIT_FALSE} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_SAME_='eval failSame --lineno "${LINENO:-}"' + +# Records a test failure, stating two values were not equal. +# +# This is functionally equivalent to calling failNotEquals(). +# +# Args: +# message: string: failure message [optional] +# expected: string: expected value +# actual: string: actual value +# Returns: +# integer: success (TRUE/FALSE/ERROR constant) +failNotSame() { + # shellcheck disable=SC2090 + ${_SHUNIT_LINENO_} + if command [ $# -lt 2 -o $# -gt 3 ]; then + _shunit_error "failNotSame() requires one or two arguments; $# given" + return ${SHUNIT_ERROR} + fi + _shunit_shouldSkip && return ${SHUNIT_TRUE} + + shunit_message_=${__shunit_lineno} + if command [ $# -eq 3 ]; then + shunit_message_="${shunit_message_}$1" + shift + fi + failNotEquals "${shunit_message_}" "$1" "$2" + shunit_return=$? + + unset shunit_message_ + return ${shunit_return} +} +# shellcheck disable=SC2016,SC2034 +_FAIL_NOT_SAME_='eval failNotSame --lineno "${LINENO:-}"' + +#----------------------------------------------------------------------------- +# Skipping functions. +# + +# Force remaining assert and fail functions to be "skipped". +# +# This function forces the remaining assert and fail functions to be "skipped", +# i.e. they will have no effect. Each function skipped will be recorded so that +# the total of asserts and fails will not be altered. +# +# Args: +# None +startSkipping() { __shunit_skip=${SHUNIT_TRUE}; } + +# Resume the normal recording behavior of assert and fail calls. +# +# Args: +# None +endSkipping() { __shunit_skip=${SHUNIT_FALSE}; } + +# Returns the state of assert and fail call skipping. +# +# Args: +# None +# Returns: +# boolean: (TRUE/FALSE constant) +isSkipping() { return ${__shunit_skip}; } + +#----------------------------------------------------------------------------- +# Suite functions. +# + +# Stub. This function should contains all unit test calls to be made. +# +# DEPRECATED (as of 2.1.0) +# +# This function can be optionally overridden by the user in their test suite. +# +# If this function exists, it will be called when shunit2 is sourced. If it +# does not exist, shunit2 will search the parent script for all functions +# beginning with the word 'test', and they will be added dynamically to the +# test suite. +# +# This function should be overridden by the user in their unit test suite. +# Note: see _shunit_mktempFunc() for actual implementation +# +# Args: +# None +#suite() { :; } # DO NOT UNCOMMENT THIS FUNCTION + +# Adds a function name to the list of tests schedule for execution. +# +# This function should only be called from within the suite() function. +# +# Args: +# function: string: name of a function to add to current unit test suite +suite_addTest() { + shunit_func_=${1:-} + + __shunit_suite="${__shunit_suite:+${__shunit_suite} }${shunit_func_}" + __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1` + + unset shunit_func_ +} + +# Stub. This function will be called once before any tests are run. +# +# Common one-time environment preparation tasks shared by all tests can be +# defined here. +# +# This function should be overridden by the user in their unit test suite. +# Note: see _shunit_mktempFunc() for actual implementation +# +# Args: +# None +#oneTimeSetUp() { :; } # DO NOT UNCOMMENT THIS FUNCTION + +# Stub. This function will be called once after all tests are finished. +# +# Common one-time environment cleanup tasks shared by all tests can be defined +# here. +# +# This function should be overridden by the user in their unit test suite. +# Note: see _shunit_mktempFunc() for actual implementation +# +# Args: +# None +#oneTimeTearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION + +# Stub. This function will be called before each test is run. +# +# Common environment preparation tasks shared by all tests can be defined here. +# +# This function should be overridden by the user in their unit test suite. +# Note: see _shunit_mktempFunc() for actual implementation +# +# Args: +# None +#setUp() { :; } # DO NOT UNCOMMENT THIS FUNCTION + +# Note: see _shunit_mktempFunc() for actual implementation +# Stub. This function will be called after each test is run. +# +# Common environment cleanup tasks shared by all tests can be defined here. +# +# This function should be overridden by the user in their unit test suite. +# Note: see _shunit_mktempFunc() for actual implementation +# +# Args: +# None +#tearDown() { :; } # DO NOT UNCOMMENT THIS FUNCTION + +#------------------------------------------------------------------------------ +# Internal shUnit2 functions. +# + +# Create a temporary directory to store various run-time files in. +# +# This function is a cross-platform temporary directory creation tool. Not all +# OSes have the `mktemp` function, so one is included here. +# +# Args: +# None +# Outputs: +# string: the temporary directory that was created +_shunit_mktempDir() { + # Try the standard `mktemp` function. + ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return + + # The standard `mktemp` didn't work. Use our own. + # shellcheck disable=SC2039 + if command [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then + _shunit_random_=`/usr/bin/od -vAn -N4 -tx4 "${_shunit_file_}" +#! /bin/sh +exit ${SHUNIT_TRUE} +EOF + command chmod +x "${_shunit_file_}" + done + + unset _shunit_file_ +} + +# Final cleanup function to leave things as we found them. +# +# Besides removing the temporary directory, this function is in charge of the +# final exit code of the unit test. The exit code is based on how the script +# was ended (e.g. normal exit, or via Ctrl-C). +# +# Args: +# name: string: name of the trap called (specified when trap defined) +_shunit_cleanup() { + _shunit_name_=$1 + + case "${_shunit_name_}" in + EXIT) ;; + INT) _shunit_signal_=130 ;; # 2+128 + TERM) _shunit_signal_=143 ;; # 15+128 + *) + _shunit_error "unrecognized trap value (${_shunit_name_})" + _shunit_signal_=0 + ;; + esac + if command [ "${_shunit_name_}" != 'EXIT' ]; then + _shunit_warn "trapped and now handling the (${_shunit_name_}) signal" + fi + + # Do our work. + if command [ ${__shunit_clean} -eq ${SHUNIT_FALSE} ]; then + # Ensure tear downs are only called once. + __shunit_clean=${SHUNIT_TRUE} + + tearDown + command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_warn "tearDown() returned non-zero return code." + oneTimeTearDown + command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_warn "oneTimeTearDown() returned non-zero return code." + + command rm -fr "${__shunit_tmpDir}" + fi + + if command [ "${_shunit_name_}" != 'EXIT' ]; then + # Handle all non-EXIT signals. + trap - 0 # Disable EXIT trap. + exit ${_shunit_signal_} + elif command [ ${__shunit_reportGenerated} -eq ${SHUNIT_FALSE} ]; then + _shunit_assertFail 'unknown failure encountered running a test' + _shunit_generateReport + exit ${SHUNIT_ERROR} + fi + + unset _shunit_name_ _shunit_signal_ +} + +# configureColor based on user color preference. +# +# Args: +# color: string: color mode (one of `always`, `auto`, or `none`). +_shunit_configureColor() { + _shunit_color_=${SHUNIT_FALSE} # By default, no color. + case $1 in + 'always') _shunit_color_=${SHUNIT_TRUE} ;; + 'auto') + command [ "`_shunit_colors`" -ge 8 ] && _shunit_color_=${SHUNIT_TRUE} + ;; + 'none') ;; + *) _shunit_fatal "unrecognized color option '$1'" ;; + esac + + case ${_shunit_color_} in + ${SHUNIT_TRUE}) + __shunit_ansi_none=${__SHUNIT_ANSI_NONE} + __shunit_ansi_red=${__SHUNIT_ANSI_RED} + __shunit_ansi_green=${__SHUNIT_ANSI_GREEN} + __shunit_ansi_yellow=${__SHUNIT_ANSI_YELLOW} + __shunit_ansi_cyan=${__SHUNIT_ANSI_CYAN} + ;; + ${SHUNIT_FALSE}) + __shunit_ansi_none='' + __shunit_ansi_red='' + __shunit_ansi_green='' + __shunit_ansi_yellow='' + __shunit_ansi_cyan='' + ;; + esac + + unset _shunit_color_ _shunit_tput_ +} + +# colors returns the number of supported colors for the TERM. +_shunit_colors() { + _shunit_tput_=`${SHUNIT_CMD_TPUT} colors 2>/dev/null` + if command [ $? -eq 0 ]; then + echo "${_shunit_tput_}" + else + echo 16 + fi + unset _shunit_tput_ +} + +# The actual running of the tests happens here. +# +# Args: +# None +_shunit_execSuite() { + for _shunit_test_ in ${__shunit_suite}; do + __shunit_testSuccess=${SHUNIT_TRUE} + + # Disable skipping. + endSkipping + + # Execute the per-test setup function. + setUp + command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_fatal "setup() returned non-zero return code." + + # Execute the test. + echo "${__SHUNIT_TEST_PREFIX}${_shunit_test_}" + eval "${_shunit_test_}" + if command [ $? -ne ${SHUNIT_TRUE} ]; then + _shunit_error "${_shunit_test_}() returned non-zero return code." + __shunit_testSuccess=${SHUNIT_ERROR} + _shunit_incFailedCount + fi + + # Execute the per-test tear-down function. + tearDown + command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_fatal "tearDown() returned non-zero return code." + + # Update stats. + if command [ ${__shunit_testSuccess} -eq ${SHUNIT_TRUE} ]; then + __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1` + else + __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1` + fi + done + + unset _shunit_test_ +} + +# Generates the user friendly report with appropriate OK/FAILED message. +# +# Args: +# None +# Output: +# string: the report of successful and failed tests, as well as totals. +_shunit_generateReport() { + command [ "${__shunit_reportGenerated}" -eq ${SHUNIT_TRUE} ] && return + + _shunit_ok_=${SHUNIT_TRUE} + + # If no exit code was provided, determine an appropriate one. + command [ "${__shunit_testsFailed}" -gt 0 \ + -o ${__shunit_testSuccess} -eq ${SHUNIT_FALSE} ] \ + && _shunit_ok_=${SHUNIT_FALSE} + + echo + _shunit_msg_="Ran ${__shunit_ansi_cyan}${__shunit_testsTotal}${__shunit_ansi_none}" + if command [ "${__shunit_testsTotal}" -eq 1 ]; then + ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} test." + else + ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_} tests." + fi + + if command [ ${_shunit_ok_} -eq ${SHUNIT_TRUE} ]; then + _shunit_msg_="${__shunit_ansi_green}OK${__shunit_ansi_none}" + command [ "${__shunit_assertsSkipped}" -gt 0 ] \ + && _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none})" + else + _shunit_msg_="${__shunit_ansi_red}FAILED${__shunit_ansi_none}" + _shunit_msg_="${_shunit_msg_} (${__shunit_ansi_red}failures=${__shunit_assertsFailed}${__shunit_ansi_none}" + command [ "${__shunit_assertsSkipped}" -gt 0 ] \ + && _shunit_msg_="${_shunit_msg_},${__shunit_ansi_yellow}skipped=${__shunit_assertsSkipped}${__shunit_ansi_none}" + _shunit_msg_="${_shunit_msg_})" + fi + + echo + ${__SHUNIT_CMD_ECHO_ESC} "${_shunit_msg_}" + __shunit_reportGenerated=${SHUNIT_TRUE} + + unset _shunit_msg_ _shunit_ok_ +} + +# Test for whether a function should be skipped. +# +# Args: +# None +# Returns: +# boolean: whether the test should be skipped (TRUE/FALSE constant) +_shunit_shouldSkip() { + command [ ${__shunit_skip} -eq ${SHUNIT_FALSE} ] && return ${SHUNIT_FALSE} + _shunit_assertSkip +} + +# Records a successful test. +# +# Args: +# None +_shunit_assertPass() { + __shunit_assertsPassed=`expr ${__shunit_assertsPassed} + 1` + __shunit_assertsTotal=`expr ${__shunit_assertsTotal} + 1` +} + +# Records a test failure. +# +# Args: +# message: string: failure message to provide user +_shunit_assertFail() { + __shunit_testSuccess=${SHUNIT_FALSE} + _shunit_incFailedCount + + \[ $# -gt 0 ] && ${__SHUNIT_CMD_ECHO_ESC} \ + "${__shunit_ansi_red}ASSERT:${__shunit_ansi_none}$*" +} + +# Increment the count of failed asserts. +# +# Args: +# none +_shunit_incFailedCount() { + __shunit_assertsFailed=`expr "${__shunit_assertsFailed}" + 1` + __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` +} + + +# Records a skipped test. +# +# Args: +# None +_shunit_assertSkip() { + __shunit_assertsSkipped=`expr "${__shunit_assertsSkipped}" + 1` + __shunit_assertsTotal=`expr "${__shunit_assertsTotal}" + 1` +} + +# Prepare a script filename for sourcing. +# +# Args: +# script: string: path to a script to source +# Returns: +# string: filename prefixed with ./ (if necessary) +_shunit_prepForSourcing() { + _shunit_script_=$1 + case "${_shunit_script_}" in + /*|./*) echo "${_shunit_script_}" ;; + *) echo "./${_shunit_script_}" ;; + esac + unset _shunit_script_ +} + +# Escape a character in a string. +# +# Args: +# c: string: unescaped character +# s: string: to escape character in +# Returns: +# string: with escaped character(s) +_shunit_escapeCharInStr() { + command [ -n "$2" ] || return # No point in doing work on an empty string. + + # Note: using shorter variable names to prevent conflicts with + # _shunit_escapeCharactersInString(). + _shunit_c_=$1 + _shunit_s_=$2 + + # Escape the character. + # shellcheck disable=SC1003,SC2086 + echo ''${_shunit_s_}'' |command sed 's/\'${_shunit_c_}'/\\\'${_shunit_c_}'/g' + + unset _shunit_c_ _shunit_s_ +} + +# Escape a character in a string. +# +# Args: +# str: string: to escape characters in +# Returns: +# string: with escaped character(s) +_shunit_escapeCharactersInString() { + command [ -n "$1" ] || return # No point in doing work on an empty string. + + _shunit_str_=$1 + + # Note: using longer variable names to prevent conflicts with + # _shunit_escapeCharInStr(). + for _shunit_char_ in '"' '$' "'" '`'; do + _shunit_str_=`_shunit_escapeCharInStr "${_shunit_char_}" "${_shunit_str_}"` + done + + echo "${_shunit_str_}" + unset _shunit_char_ _shunit_str_ +} + +# Extract list of functions to run tests against. +# +# Args: +# script: string: name of script to extract functions from +# Returns: +# string: of function names +_shunit_extractTestFunctions() { + _shunit_script_=$1 + + # Extract the lines with test function names, strip of anything besides the + # function name, and output everything on a single line. + _shunit_regex_='^\s*((function test[A-Za-z0-9_-]*)|(test[A-Za-z0-9_-]* *\(\)))' + # shellcheck disable=SC2196 + egrep "${_shunit_regex_}" "${_shunit_script_}" \ + |command sed 's/^[^A-Za-z0-9_-]*//;s/^function //;s/\([A-Za-z0-9_-]*\).*/\1/g' \ + |xargs + + unset _shunit_regex_ _shunit_script_ +} + +#------------------------------------------------------------------------------ +# Main. +# + +# Determine the operating mode. +if command [ $# -eq 0 -o "${1:-}" = '--' ]; then + __shunit_script=${__SHUNIT_PARENT} + __shunit_mode=${__SHUNIT_MODE_SOURCED} +else + __shunit_script=$1 + command [ -r "${__shunit_script}" ] || \ + _shunit_fatal "unable to read from ${__shunit_script}" + __shunit_mode=${__SHUNIT_MODE_STANDALONE} +fi + +# Create a temporary storage location. +__shunit_tmpDir=`_shunit_mktempDir` + +# Provide a public temporary directory for unit test scripts. +# TODO(kward): document this. +SHUNIT_TMPDIR="${__shunit_tmpDir}/tmp" +command mkdir "${SHUNIT_TMPDIR}" + +# Setup traps to clean up after ourselves. +trap '_shunit_cleanup EXIT' 0 +trap '_shunit_cleanup INT' 2 +trap '_shunit_cleanup TERM' 15 + +# Create phantom functions to work around issues with Cygwin. +_shunit_mktempFunc +PATH="${__shunit_tmpDir}:${PATH}" + +# Make sure phantom functions are executable. This will bite if `/tmp` (or the +# current `$TMPDIR`) points to a path on a partition that was mounted with the +# 'noexec' option. The noexec command was created with `_shunit_mktempFunc()`. +noexec 2>/dev/null || _shunit_fatal \ + 'Please declare TMPDIR with path on partition with exec permission.' + +# We must manually source the tests in standalone mode. +if command [ "${__shunit_mode}" = "${__SHUNIT_MODE_STANDALONE}" ]; then + # shellcheck disable=SC1090 + command . "`_shunit_prepForSourcing \"${__shunit_script}\"`" +fi + +# Configure default output coloring behavior. +_shunit_configureColor "${SHUNIT_COLOR}" + +# Execute the oneTimeSetUp function (if it exists). +oneTimeSetUp +command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_fatal "oneTimeSetUp() returned non-zero return code." + +# Command line selected tests or suite selected tests +if command [ "$#" -ge 2 ]; then + # Argument $1 is either the filename of tests or '--'; either way, skip it. + shift + # Remaining arguments ($2 .. $#) are assumed to be test function names. + # Interate through all remaining args in "$@" in a POSIX (likely portable) way. + # Helpful tip: https://unix.stackexchange.com/questions/314032/how-to-use-arguments-like-1-2-in-a-for-loop + for _shunit_arg_ do + suite_addTest "${_shunit_arg_}" + done + unset _shunit_arg_ +else + # Execute the suite function defined in the parent test script. + # DEPRECATED as of 2.1.0. + suite +fi + +# If no tests or suite specified, dynamically build a list of functions. +if command [ -z "${__shunit_suite}" ]; then + shunit_funcs_=`_shunit_extractTestFunctions "${__shunit_script}"` + for shunit_func_ in ${shunit_funcs_}; do + suite_addTest "${shunit_func_}" + done +fi +unset shunit_func_ shunit_funcs_ + +# Execute the suite of unit tests. +_shunit_execSuite + +# Execute the oneTimeTearDown function (if it exists). +oneTimeTearDown +command [ $? -eq ${SHUNIT_TRUE} ] \ + || _shunit_fatal "oneTimeTearDown() returned non-zero return code." + +# Generate a report summary. +_shunit_generateReport + +# That's it folks. +command [ "${__shunit_testsFailed}" -eq 0 ] +exit $?