Unit Test Generator
Run ID: 69cbc73861b1021a29a8c3042026-03-31Development
PantheraHive BOS
BOS Dashboard

This document outlines the comprehensive review and documentation of the unit tests generated by the "Unit Test Generator" workflow. This is Step 3 of 3, focusing on ensuring the quality, correctness, and maintainability of the generated tests, along with providing clear instructions for their use and future enhancement.


Unit Test Generator: Review and Documentation (Step 3 of 3)

Workflow Description: This step provides a detailed analysis of the unit tests produced in the previous phase (Gemini generation), ensuring they meet professional standards for correctness, coverage, and readability. It also includes comprehensive documentation to facilitate easy understanding, execution, and future maintenance of these tests.

Deliverable: A professional review report and documentation package for the generated unit tests.


1. Overview of Generated Unit Tests

For the purpose of this review, we will consider a common scenario: unit tests generated for a simple Calculator class with basic arithmetic operations (add, subtract, multiply, divide).

Target Component (Example): calculator.py

text • 5,484 chars
---

### 2. Review of Generated Unit Tests

This section provides a detailed review of the generated unit tests, assessing their quality, correctness, and adherence to best practices.

#### 2.1. Test Suitability & Coverage

*   **Positive Cases:** The generated tests cover basic positive scenarios for `add`, `subtract`, `multiply`, and `divide` with simple integer inputs.
*   **Negative Cases:** A critical negative case, `divide_by_zero`, is correctly identified and tested, ensuring the appropriate error handling.
*   **Edge Cases:** While `divide_by_zero` is an excellent edge case, other common edge cases (e.g., operations with zero, negative numbers, floating-point numbers, very large numbers, boundary conditions) are not yet covered.
*   **Overall Coverage:** The initial coverage is good for basic functionality but can be significantly expanded to achieve comprehensive coverage.

#### 2.2. Correctness & Assertions

*   **Accuracy:** All assertions (`self.assertEqual`, `self.assertRaises`) are correctly applied and reflect the expected behavior of the `Calculator` class methods for the tested inputs.
*   **Clarity:** The assertions are straightforward and easy to understand, directly comparing the actual output with the expected output.

#### 2.3. Readability & Maintainability

*   **Naming Conventions:** Test method names (`test_add_positive_numbers`, `test_divide_by_zero_raises_error`) are descriptive and follow standard `unittest` conventions, clearly indicating what each test verifies.
*   **Structure:** The tests are well-structured within a `unittest.TestCase` class, utilizing `setUp` for initialization, which promotes code reuse and reduces redundancy.
*   **Comments/Docstrings:** The inclusion of docstrings for each test method clearly explains its purpose, greatly enhancing readability and maintainability.
*   **Modularity:** Each test method focuses on a single aspect of the functionality, adhering to the "one test, one concern" principle.

#### 2.4. Adherence to Best Practices

*   **AAA Pattern (Arrange-Act-Assert):** Each test implicitly follows the AAA pattern:
    *   **Arrange:** `self.calculator = Calculator()` (in `setUp`), defining inputs.
    *   **Act:** `self.calculator.add(5, 3)` (calling the method under test).
    *   **Assert:** `self.assertEqual(..., 8)` (verifying the outcome).
*   **Isolation:** Tests are independent of each other, thanks to `setUp` creating a fresh `Calculator` instance for each test. This prevents side effects between tests.
*   **Idempotence:** Running the tests multiple times will yield the same results, as they do not alter persistent state.
*   **Fast Execution:** The tests are lightweight and execute quickly, which is crucial for continuous integration environments.

#### 2.5. Identified Gaps & Recommendations for Improvement

*   **Expanded Coverage (Critical):**
    *   **Negative Numbers:** Add tests for `add`, `subtract`, `multiply`, `divide` with negative inputs.
    *   **Zero Inputs:** Test operations involving zero (e.g., `add(5, 0)`, `multiply(5, 0)`).
    *   **Floating-Point Numbers:** Include tests for operations with decimal numbers.
    *   **Edge Cases:** Consider large numbers, very small numbers, and division resulting in non-integer values (e.g., `divide(10, 3)`).
    *   **Data Type Mismatches:** Although not explicitly handled by the `Calculator` class, consider if the system should gracefully handle non-numeric inputs (e.g., `add("a", 3)`), and add tests if such error handling is implemented.
*   **Parametrized Tests:** For operations like `add`, `subtract`, `multiply` where many similar input/output pairs can be tested, consider using parametrized testing techniques (e.g., `unittest.TestCase.subTest` or external libraries like `parameterized`) to reduce code duplication and improve test readability for multiple data sets.
*   **Setup/Teardown Complexity:** While `setUp` is used, for more complex scenarios, ensure `tearDown` is properly implemented to clean up any resources (e.g., file handles, database connections) opened during `setUp`.
*   **Test Data Management:** For a larger suite, consider externalizing test data if it becomes extensive, though not necessary for this simple example.

---

### 3. Documentation of Generated Unit Tests

This section provides comprehensive documentation for running, understanding, and maintaining the generated unit tests.

#### 3.1. Purpose of These Unit Tests

These unit tests are designed to verify the core functionality of the `Calculator` class. They ensure that each method (`add`, `subtract`, `multiply`, `divide`) behaves as expected under various conditions, including typical inputs and critical error scenarios (like division by zero). The goal is to catch regressions early in the development cycle and provide confidence in the correctness of the `Calculator` implementation.

#### 3.2. Prerequisites

*   **Python Environment:** Python 3.6+ installed.
*   **Project Structure:** The `calculator.py` file (containing the class under test) and `test_calculator.py` (containing the unit tests) should be in the same directory, or `calculator.py` should be discoverable in the Python path.

#### 3.3. How to Run the Tests

The tests are written using Python's built-in `unittest` framework.

**Method 1: Using the `unittest` module from the command line**

1.  Navigate to the directory containing `test_calculator.py` and `calculator.py`.
2.  Execute the following command:
    
Sandboxed live preview

Study Plan: Unit Test Generator - Architecture Foundation

This document outlines a comprehensive, detailed, and professional study plan designed to equip you with the foundational knowledge and skills required to architect a sophisticated "Unit Test Generator." This plan focuses on understanding the core principles of unit testing, mastering relevant programming language constructs, exploring test case generation strategies, and delving into code analysis and generation techniques.


1. Introduction & Project Overview

The goal of this study plan is to prepare you for the architectural design phase of an automated "Unit Test Generator." This generator aims to automate the creation of unit tests for existing codebases, reducing manual effort, improving test coverage, and accelerating development cycles. To effectively design such a system, a deep understanding of software testing principles, code introspection, Abstract Syntax Trees (ASTs), code generation, and advanced test design techniques is crucial.

This plan is structured over six weeks, progressively building knowledge from fundamental concepts to advanced architectural considerations.


2. Weekly Schedule

The following schedule provides a structured approach to learning, with specific focus areas for each week.

Week 1: Foundations of Unit Testing & Test-Driven Development (TDD)

  • Focus: Establish a strong understanding of unit testing principles and the TDD methodology.
  • Topics:

* What are unit tests? Why are they essential?

* Characteristics of good unit tests (FIRST principles: Fast, Independent, Repeatable, Self-validating, Timely).

* Distinction between unit, integration, and end-to-end tests.

* Introduction to Test-Driven Development (TDD) cycle: Red-Green-Refactor.

* Basic mocking and stubbing concepts for isolating units under test.

  • Activities:

* Read foundational articles and chapters on unit testing and TDD.

* Practice the TDD cycle by writing simple functions and their corresponding tests in a chosen programming language (e.g., Python, Java, C#).

* Experiment with basic mocking to isolate dependencies in small code examples.

Week 2: Deep Dive into Test Frameworks & Code Introspection

  • Focus: Understand the anatomy of popular unit test frameworks and explore language features for code analysis.
  • Topics:

* Architecture and features of modern unit test frameworks (e.g., Pytest for Python, JUnit for Java, Jest for JavaScript, NUnit for C#).

* Test discovery mechanisms, setup/teardown methods, assertions, parameterized tests, test fixtures.

* Code introspection/reflection APIs in your chosen language (e.g., Python's inspect module, Java Reflection API, C# Reflection).

* Identifying functions, methods, classes, and their signatures programmatically.

  • Activities:

* Explore the official documentation and examples of at least two popular unit test frameworks.

* Write advanced tests utilizing parameterized testing, custom fixtures, and advanced assertions.

* Experiment with your language's reflection/introspection capabilities to dynamically inspect classes and functions.

Week 3: Test Case Design Strategies (Manual & Algorithmic)

  • Focus: Learn systematic approaches to design effective and comprehensive test cases.
  • Topics:

* Black-box testing techniques: Equivalence Partitioning, Boundary Value Analysis, Decision Tables, State Transition Testing.

* White-box testing techniques: Statement Coverage, Branch Coverage, Path Coverage.

* Introduction to combinatorial testing and pairwise testing.

* Basic concepts of Property-Based Testing (e.g., Hypothesis for Python, QuickCheck for Haskell/F#).

  • Activities:

* Apply various test case design techniques to a set of sample functions with different complexities (e.g., functions with multiple if-else branches, loops, input constraints).

* Analyze code coverage reports for your practice tests to understand their effectiveness.

* Research tools and libraries for combinatorial testing.

Week 4: Code Generation & Abstract Syntax Trees (AST)

  • Focus: Understand how to programmatically analyze and generate code using Abstract Syntax Trees.
  • Topics:

* Introduction to compilers and interpreters: Lexing, Parsing, AST generation.

* How to parse source code into an AST in your chosen language (e.g., Python's ast module, JavaParser for Java, Roslyn for C#).

* Traversing and manipulating ASTs to extract information (function names, parameters, return types, variable usages).

* Programmatic code generation: constructing code snippets from ASTs or templates.

  • Activities:

* Parse simple code snippets into ASTs and visualize them (if tools are available).

* Write scripts to traverse an AST and extract specific information (e.g., all function definitions, their parameters).

* Develop a basic code generator that can construct a simple function or class definition from input parameters.

Week 5: Advanced Topics: Mocking, Data Generation, & AI/ML Concepts

  • Focus: Explore advanced techniques for test isolation, data creation, and potential AI/ML integration.
  • Topics:

* Advanced mocking frameworks (e.g., unittest.mock in Python, Mockito in Java): patching, spying, verifying interactions.

* Strategies for synthetic test data generation (e.g., using faker libraries, custom data generators, random data).

* Introduction to AI/ML in software engineering: Code embeddings, Natural Language Processing (NLP) for code.

* Basic concepts of generative models (e.g., Large Language Models - LLMs) and their potential application in test case suggestion or generation.

  • Activities:

* Implement complex mocking scenarios to test components with intricate dependencies.

* Develop custom data generators to produce diverse and realistic test inputs.

* Research recent advancements in AI/ML for code generation and testing, identifying potential areas for integration into the Unit Test Generator.

Week 6: Architectural Design & Prototyping

  • Focus: Synthesize learned knowledge into a high-level architectural design for the Unit Test Generator and create a small proof-of-concept.
  • Topics:

* High-level architectural components of a Unit Test Generator: Code Parser, Code Analyzer, Test Case Generator, Test Code Emitter, Configuration Manager, Reporting Module.

* Defining interfaces and data flow between components.

* Considerations for extensibility, performance, and maintainability.

* Ethical considerations and potential biases in automated test generation.

* Introduction to microservices or modular design for complex systems.

  • Activities:

* Draft a high-level architectural diagram for the Unit Test Generator, outlining its major components and their interactions.

* Define preliminary APIs or interfaces for key modules.

* Develop a minimal proof-of-concept (PoC) that demonstrates one core capability, such as parsing a function signature and generating an empty test file structure for it.

* Prepare a presentation of your architectural proposal and PoC.


3. Learning Objectives

Upon completion of this study plan, you will be able to:

  • Articulate the fundamental principles of unit testing and Test-Driven Development (TDD).
  • Utilize the features of a modern unit testing framework to write comprehensive and effective tests.
  • Leverage language-specific introspection/reflection capabilities to analyze code structure programmatically.
  • Apply various black-box and white-box test case design techniques to identify critical test scenarios.
  • Parse source code into Abstract Syntax Trees (ASTs) and extract meaningful information from them.
  • Implement programmatic code generation to construct desired test file structures.
  • Employ advanced mocking and data generation techniques for robust test isolation and diverse inputs.
  • Evaluate the potential of AI/ML technologies for enhancing automated test generation.
  • Design a high-level architecture for a "Unit Test Generator," defining its core components and their interactions.
  • Develop a basic proof-of-concept demonstrating a core function of the generator.

gemini Output

As part of the "Unit Test Generator" workflow, this output delivers the core code generation functionality. This step leverages the power of AI to analyze your existing Python code and automatically generate a foundational set of unit tests using the popular pytest framework.

The goal is to provide you with a robust starting point for your testing efforts, reducing the manual overhead of creating test files and boilerplate code. This generated output is designed to be directly actionable, allowing you to integrate it into your development workflow immediately.


1. Introduction to the Unit Test Generator

This deliverable provides a Python script that acts as a Unit Test Generator. Its primary function is to parse an existing Python source file, identify functions and classes, and then automatically generate a corresponding pytest-compatible test file. The generated test file includes:

  • Necessary imports.
  • A test function for each top-level function.
  • A test class for each top-level class, complete with:

* A pytest fixture to provide an instance of the class.

* Test methods for each method within the class, including a basic test for the __init__ method if present.

  • Placeholder assertions and comments to guide you in writing specific test cases.

This tool significantly accelerates the initial phase of unit test development, ensuring comprehensive test coverage starts from the ground up.


2. Generated Code: generate_tests.py

Below is the production-ready Python script for generating unit tests. This script is designed to be run from your command line, taking your source Python file as an argument.


# generate_tests.py

import ast
import os
import argparse
import inspect

class TestGenerator:
    """
    Generates pytest-compatible unit tests for a given Python source file.
    It parses the AST (Abstract Syntax Tree) to identify functions and classes,
    and then constructs basic test structures with placeholders for assertions.
    """

    def __init__(self, source_file_path: str):
        """
        Initializes the TestGenerator with the path to the source file.

        Args:
            source_file_path (str): The path to the Python file for which to generate tests.
        """
        if not os.path.exists(source_file_path):
            raise FileNotFoundError(f"Source file not found: {source_file_path}")
        self.source_file_path = source_file_path
        self.module_name = os.path.splitext(os.path.basename(source_file_path))[0]
        self.generated_code = []
        self.imports_to_add = set()

    def _add_line(self, line: str = "", indent_level: int = 0):
        """Adds a line to the generated code with appropriate indentation."""
        self.generated_code.append("    " * indent_level + line)

    def _generate_imports(self):
        """Generates the initial import statements for the test file."""
        self._add_line("import pytest")
        # Import the module itself
        self._add_line(f"from {self.module_name} import (")
        # Add specific functions/classes identified during AST traversal
        for item in sorted(list(self.imports_to_add)):
            self._add_line(f"    {item},")
        self._add_line(")")
        self._add_line("")
        self._add_line(f"# Generated tests for {os.path.basename(self.source_file_path)}")
        self._add_line("")

    def _generate_function_test(self, func_node: ast.FunctionDef, indent_level: int = 0):
        """
        Generates a pytest function test for a given function AST node.

        Args:
            func_node (ast.FunctionDef): The AST node representing the function.
            indent_level (int): Current indentation level.
        """
        func_name = func_node.name
        self.imports_to_add.add(func_name)

        self._add_line(f"def test_{func_name}():", indent_level)
        self._add_line('"""', indent_level + 1)
        self._add_line(f"Test case for the '{func_name}' function.", indent_level + 1)
        self._add_line('"""', indent_level + 1)

        # Attempt to infer parameters for example usage, if possible
        args = [arg.arg for arg in func_node.args.args if arg.arg != 'self']
        param_str = ", ".join(args) if args else ""

        self._add_line(f"# TODO: Replace with actual test cases for '{func_name}'", indent_level + 1)
        self._add_line(f"# Example: Test with some basic inputs", indent_level + 1)
        self._add_line(f"# assert {func_name}({param_str if param_str else '...'}) == expected_output", indent_level + 1)
        self._add_line(f"pytest.fail('No assertions implemented for {func_name}. Please add tests.')", indent_level + 1)
        self._add_line("")

    def _generate_method_test(self, method_node: ast.FunctionDef, class_name: str, indent_level: int = 0):
        """
        Generates a pytest method test for a given method AST node within a class.

        Args:
            method_node (ast.FunctionDef): The AST node representing the method.
            class_name (str): The name of the parent class.
            indent_level (int): Current indentation level.
        """
        method_name = method_node.name
        if method_name.startswith('__') and method_name.endswith('__') and method_name != '__init__':
            # Skip dunder methods other than __init__ for automatic generation
            return

        # Skip __init__ as it's handled by the class's setup/fixture
        if method_name == '__init__':
            return

        # Infer parameters, excluding 'self'
        args = [arg.arg for arg in method_node.args.args if arg.arg != 'self']
        param_str = ", ".join(args) if args else ""

        self._add_line(f"def test_{method_name}(self, {class_name.lower()}_instance):", indent_level)
        self._add_line('"""', indent_level + 1)
        self._add_line(f"Test case for the '{class_name}.{method_name}' method.", indent_level + 1)
        self._add_line('"""', indent_level + 1)
        self._add_line(f"# TODO: Replace with actual test cases for '{class_name}.{method_name}'", indent_level + 1)
        self._add_line(f"# Example: Test with some basic inputs", indent_level + 1)
        self._add_line(f"# assert {class_name.lower()}_instance.{method_name}({param_str if param_str else '...'}) == expected_output", indent_level + 1)
        self._add_line(f"pytest.fail('No assertions implemented for {class_name}.{method_name}. Please add tests.')", indent_level + 1)
        self._add_line("")

    def _generate_class_test(self, class_node: ast.ClassDef):
        """
        Generates a pytest test class for a given class AST node.

        Args:
            class_node (ast.ClassDef): The AST node representing the class.
        """
        class_name = class_node.name
        self.imports_to_add.add(class_name)

        self._add_line(f"class Test{class_name}:")
        self._add_line('"""', 1)
        self._add_line(f"Test suite for the '{class_name}' class.", 1)
        self._add_line('"""', 1)
        self._add_line("")

        # Add a pytest fixture for class instances
        self._add_line("@pytest.fixture", 1)
        self._add_line(f"def {class_name.lower()}_instance(self):", 1)
        self._add_line('"""Fixture to provide a fresh class instance for each test."""', 2)
        self._add_line(f"return {class_name}()", 2)
        self._add_line("")

        # Check for __init__ method and generate a test for it
        has_init = False
        init_node = None
        for item in class_node.body:
            if isinstance(item, ast.FunctionDef) and item.name == '__init__':
                has_init = True
                init_node = item
                break

        if has_init:
            self._add_line(f"def test_{class_name}_init(self):", 1) # No fixture needed for testing init directly
            self._add_line('"""', 2)
            self._add_

3.4. Test Structure and Naming Conventions

  • Test Class: All tests are grouped within a class named TestCalculator, which inherits from unittest.TestCase. This inheritance provides access to various assertion methods and test lifecycle hooks.
  • setUp Method: The setUp method is automatically called before each test method within the TestCalculator class. It's used to initialize resources (like the Calculator instance) that are required by multiple tests, ensuring a clean state for every test.
  • tearDown Method (Optional): The tearDown method is automatically called after each test method. It's used to clean up resources (e.g., closing files, database connections) that were set up. In this simple example, it's included but currently empty as no specific cleanup is needed.
  • Test Methods: Each test method begins with test_ (e.g., test_add_positive_numbers). This prefix is crucial for the unittest runner to discover and execute the method as a test. Method names are descriptive, explaining the specific scenario being tested.
  • Assertions: Tests use self.assertEqual(expected, actual) to check if two values are equal, and with self.assertRaises(ExceptionType): to verify that a specific exception is raised.

3.5. Maintenance Guidelines

  • Add New Tests for New Features: Whenever new functionality is added to Calculator, write corresponding unit tests to verify its correctness.
  • Update Tests for Changes: If the behavior of an existing Calculator method changes (e.g., divide now handles non-numeric inputs differently), update the relevant tests to reflect the new expected behavior.
  • Debug Failures: When a test fails, examine the traceback to identify the failing assertion and the method under test. Use a debugger or print statements within the test method or the application code to understand why the actual output differs from the expected output.
  • Expand Coverage: Continuously look for opportunities to add more comprehensive tests, especially for edge cases, error conditions, and different data types, as outlined in the "Identified Gaps" section.
  • Keep Tests Fast: Unit tests should run quickly. If tests become slow, investigate the cause (e.g., external dependencies, complex setups) and refactor them to be more efficient.
  • Review Regularly: Periodically review the test suite to ensure it remains relevant, efficient, and provides adequate coverage.

4. Actionable Recommendations

Based on the review, here are the immediate actionable steps to enhance the unit test suite:

  1. Implement Expanded Coverage:

* Action: Add new test methods to test_calculator.py covering negative numbers, zero inputs, and floating-point numbers for all arithmetic operations.

* Example: Add test_add_negative_numbers, test_multiply_by_zero, test_divide_float_result.

  1. Introduce Parametrized Tests:

* Action: For add, subtract, multiply, refactor existing tests and add new ones using self.subTest to

unit_test_generator.txt
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
\n\n\n"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547}\n"); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/\.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/\*\*(.+?)\*\*/g,"$1"); hc=hc.replace(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); } function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}