diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dba35a0..f1f3d71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,10 @@ on: [ push, pull_request ] jobs: test: runs-on: ubuntu-latest - + env: + CODETHREAT_ORG: ${{ secrets.CODETHREAT_ORG }} + CODETHREAT_TOKEN: ${{ secrets.CODETHREAT_TOKEN }} + CODETHREAT_URL: ${{ secrets.CODETHREAT_URL }} steps: - name: Checkout code uses: actions/checkout@v2 diff --git a/tests/test_auth.py b/tests/test_auth.py new file mode 100644 index 0000000..a132a70 --- /dev/null +++ b/tests/test_auth.py @@ -0,0 +1,64 @@ +import unittest +from unittest.mock import patch, mock_open +import os +from click.testing import CliRunner +import auth + + +class TestAuthCommands(unittest.TestCase): + + @patch('auth.requests.get') + @patch('builtins.open', new_callable=mock_open) + def test_login_with_github_secrets(self, mock_open_file, mock_requests_get): + # Mocking the requests + mock_requests_get.return_value.status_code = 200 + + # Retrieve secrets from environment variables + org = os.environ.get('CODETHREAT_ORG') + token = os.environ.get('CODETHREAT_TOKEN') + url = os.environ.get('CODETHREAT_URL') + + runner = CliRunner() + result = runner.invoke(auth.login, ['--key', token, '--url', url, '--org', org]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] Authentication successful.", result.output) + mock_open_file.assert_called_once_with(auth.CONFIG_FILE_PATH, "w") + + @patch('auth.requests.get') + def test_login_failure(self, mock_requests_get): + # Mocking a failed login attempt + mock_requests_get.return_value.status_code = 401 + + org = os.environ.get('CODETHREAT_ORG') + token = os.environ.get('CODETHREAT_TOKEN') + url = os.environ.get('CODETHREAT_URL') + + runner = CliRunner() + result = runner.invoke(auth.login, ['--key', token, '--url', url, '--org', org]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] Authentication failed:", result.output) + + @patch('os.remove') + def test_remove_auth_config(self, mock_os_remove): + runner = CliRunner() + + with patch('os.path.exists', return_value=True): + result = runner.invoke(auth.remove) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] Authentication configuration removed successfully.", result.output) + mock_os_remove.assert_called_once_with(auth.CONFIG_FILE_PATH) + + @patch('os.path.exists', return_value=False) + def test_remove_auth_config_not_found(self, mock_os_path_exists): + runner = CliRunner() + result = runner.invoke(auth.remove) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] No authentication configuration found.", result.output) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_scan.py b/tests/test_scan.py new file mode 100644 index 0000000..c863c88 --- /dev/null +++ b/tests/test_scan.py @@ -0,0 +1,86 @@ +import tempfile +import unittest +from unittest.mock import patch, MagicMock +import os +from click.testing import CliRunner +import scan + +class TestScanCommand(unittest.TestCase): + + @patch('scan.requests.get') + @patch('scan.requests.post') + @patch('shutil.make_archive') + @patch('tempfile.TemporaryDirectory') + def test_scan(self, mock_tempdir, mock_make_archive, mock_post, mock_get): + # Mocking environment variables and requests + mock_tempdir.return_value.__enter__.return_value = tempfile.gettempdir() + mock_make_archive.return_value = os.path.join(tempfile.gettempdir(), 'test.zip') + mock_get.return_value.status_code = 200 + mock_post.return_value.status_code = 200 + mock_post.return_value.json.return_value = {"scan_id": "fake_scan_id"} + + # Retrieve secrets from environment variables + org = os.environ.get('CODETHREAT_ORG') + token = os.environ.get('CODETHREAT_TOKEN') + url = os.environ.get('CODETHREAT_URL') + + # Use the actual source code directory for testing + source_code_path = os.path.abspath(os.path.dirname(__file__)) + + runner = CliRunner() + result = runner.invoke(scan.scan, ['--target', source_code_path, '--project', 'new_project', '--url', url, '--token', token, '--org', org]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] Scan started successfully", result.output) + mock_make_archive.assert_called_once() + mock_post.assert_called() + + @patch('scan.requests.get') + @patch('scan.requests.post') + def test_scan_project_creation(self, mock_post, mock_get): + # Mocking project creation and scan initiation + mock_get.return_value.status_code = 404 + mock_post.side_effect = [ + MagicMock(status_code=200, json=MagicMock(return_value={"result": {"message": "successfull"}, "error": False})), + MagicMock(status_code=200, json=MagicMock(return_value={"scan_id": "fake_scan_id"})) + ] + + # Retrieve secrets from environment variables + org = os.environ.get('CODETHREAT_ORG') + token = os.environ.get('CODETHREAT_TOKEN') + url = os.environ.get('CODETHREAT_URL') + + # Use the actual source code directory for testing + source_code_path = os.path.abspath(os.path.dirname(__file__)) + + runner = CliRunner() + result = runner.invoke(scan.scan, ['--target', source_code_path, '--project', 'new_project', '--url', url, '--token', token, '--org', org]) + + self.assertEqual(result.exit_code, 0) + self.assertIn("[CT*] Project 'new_project' created successfully.", result.output) + self.assertIn("[CT*] Scan started successfully", result.output) + mock_post.assert_called() + + @patch('scan.requests.get') + @patch('scan.requests.post') + def test_scan_failure(self, mock_post, mock_get): + # Mocking a failed scan initiation + mock_get.return_value.status_code = 200 + mock_post.return_value.status_code = 500 + + # Retrieve secrets from environment variables + org = os.environ.get('CODETHREAT_ORG') + token = os.environ.get('CODETHREAT_TOKEN') + url = os.environ.get('CODETHREAT_URL') + + # Use the actual source code directory for testing + source_code_path = os.path.abspath(os.path.dirname(__file__)) + + runner = CliRunner() + result = runner.invoke(scan.scan, ['--target', source_code_path, '--project', 'test_project_123', '--url', url, '--token', token, '--org', org]) + + self.assertEqual(result.exit_code, scan.FAILURE_EXIT_CODE) + self.assertIn("[CT*] Scan initiation failed", result.output) + +if __name__ == '__main__': + unittest.main()