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

This document provides the detailed, professional output for Step 2 of 3 in the "Unit Test Generator" workflow. This step focuses on leveraging the Gemini model to generate comprehensive unit tests based on provided source code.


Unit Test Generator: Step 2 - Code Generation (gemini → generate_code)

This step is responsible for programmatically generating unit tests for a given Python source code using Google's Gemini Pro model. The output is a Python script containing the generated unit tests, ready for execution.

1. Introduction

The generate_code function serves as the core engine for generating unit tests. It takes a block of Python source code as input, crafts a detailed prompt for the Gemini Pro model, and returns the AI-generated unit test code. The goal is to produce well-structured, comprehensive, and production-ready tests using the unittest framework.

2. Core Function: generate_unit_tests

Below is the Python code for the generate_unit_tests function. This function encapsulates the logic for interacting with the Gemini API and orchestrating the test generation process.

text • 1,626 chars
#### 2.1. Explanation of the Code

*   **API Key Configuration:** The function expects the `GEMINI_API_KEY` to be set as an environment variable for secure and flexible access to the Gemini API.
*   **`generate_unit_tests` Function:**
    *   **Parameters:** It takes the `source_code` as a string, along with optional parameters to configure the AI model's behavior (e.g., `model_name`, `temperature`, `max_output_tokens`, `stop_sequences`, `safety_settings`).
    *   **Safety Settings:** Default safety settings are included to block potentially harmful content, though they are configured to be less restrictive for code generation to avoid false positives. You may adjust these based on your specific requirements.
    *   **Model Initialization:** An instance of `genai.GenerativeModel` is created using the specified `model_name`.
    *   **Prompt Engineering:** This is the most critical part. The `prompt` string is carefully crafted to instruct the Gemini model on:
        *   Its persona ("expert Python developer").
        *   The task (generating `unittest` framework tests).
        *   Specific requirements for the tests: comprehensiveness, isolation (using mocks), structure, descriptive naming, and desired output format (only Python code).
        *   The source code to be tested is embedded directly into the prompt.
    *   **API Call:** `model.generate_content()` is called with the crafted prompt and generation configuration.
    *   **Response Handling:** The function extracts the generated text from the model's response. It also includes basic cleanup to remove potential markdown code fences (
Sandboxed live preview

This document outlines a detailed study plan for understanding and designing a "Unit Test Generator". The plan is structured to provide a comprehensive learning journey, from foundational concepts of unit testing and code analysis to advanced techniques involving AI/ML for automated test generation and architectural design.


Unit Test Generator: Comprehensive Study Plan

1. Introduction and Overall Goal

This study plan is designed to equip you with the knowledge and skills necessary to understand, design, and potentially prototype a "Unit Test Generator." This involves delving into the principles of effective unit testing, mastering code analysis techniques, exploring various test case generation strategies, and evaluating the role of artificial intelligence in automating this process.

Overall Goal: By the end of this plan, you will be capable of outlining a robust architecture for a Unit Test Generator, understanding its core components, and identifying the key technologies and algorithms required for its implementation.

Target Audience: Software engineers, QA automation specialists, researchers, or anyone interested in advanced software testing, static analysis, and AI applications in software engineering. A basic understanding of programming concepts and software development lifecycles is recommended.

2. Weekly Schedule

This 6-week schedule provides a structured approach, blending theoretical learning with practical application. Each week builds upon the previous one, leading to a holistic understanding.

Week 1: Foundations of Unit Testing & Code Analysis Basics

  • Focus: Establish a strong understanding of unit testing principles and begin exploring how code can be programmatically analyzed.
  • Key Topics:

* Unit Testing Fundamentals: What is a unit test, why it's crucial, Test-Driven Development (TDD) vs. Behavior-Driven Development (BDD), characteristics of good unit tests (FIRST principles).

* Testing Frameworks: Overview of popular frameworks (e.g., JUnit for Java, Pytest for Python, NUnit for C#, Jest for JavaScript), assertion libraries, mocking/stubbing.

* Code Coverage: Statement, branch, function coverage.

* Introduction to Abstract Syntax Trees (ASTs): What they are, how they represent code structure, basic parsing concepts.

  • Activities:

* Read introductory articles/chapters on unit testing and TDD.

* Write unit tests for simple functions in your preferred language using a chosen framework. Experiment with mocking.

* Explore an online AST explorer (e.g., astexplorer.net) for different languages.

* Use a language-specific AST parser (e.g., Python's ast module, JavaParser) to parse a small code snippet and print its basic tree structure.

  • Estimated Time: 10-15 hours

Week 2: Advanced Code Analysis & Introduction to Test Generation Strategies

  • Focus: Deepen understanding of static code analysis and begin to conceptualize how code properties inform test generation.
  • Key Topics:

* Static Analysis: Beyond ASTs – Control Flow Graphs (CFG), Data Flow Analysis (DFA), Symbol Tables.

* Identifying Testable Units: Programmatically extracting function/method signatures, parameters, return types, class structures.

* Dependencies and Testability: Understanding how dependencies impact unit test generation.

* Initial Test Generation Concepts: Brainstorming how to generate basic input values.

  • Activities:

* Study CFG and DFA concepts; draw CFGs for small code examples.

* Implement a script using your chosen AST parser to extract all function names, their parameters, and return types from a simple source file.

* Research existing static analysis tools and their capabilities (e.g., SonarQube, ESLint).

* Consider how to identify "entry points" for testing in a given codebase.

  • Estimated Time: 10-15 hours

Week 3: Deep Dive into Classical Test Case Generation Techniques

  • Focus: Master traditional, systematic approaches to designing test cases.
  • Key Topics:

* Black-Box Techniques: Equivalence Partitioning, Boundary Value Analysis.

* White-Box Techniques: Statement Coverage, Branch/Decision Coverage, Path Coverage, Condition Coverage.

* State-Based Testing: Modeling system states and transitions to generate tests.

* Introduction to Fuzzing: Basic principles of generating random or semi-random inputs.

* Property-Based Testing (PBT): Generating diverse inputs based on defined properties (e.g., Hypothesis for Python, QuickCheck for Haskell).

  • Activities:

* For a given set of functions, manually design comprehensive test cases using Equivalence Partitioning and Boundary Value Analysis.

* Analyze small code snippets to determine test inputs required for 100% statement and branch coverage.

* Experiment with a property-based testing library; write properties for simple data structures or functions.

* Implement a very basic "fuzzer" that generates random inputs (e.g., integers, strings) for a target function.

  • Estimated Time: 12-18 hours

Week 4: AI/ML & Advanced Approaches for Automated Test Generation

  • Focus: Explore cutting-edge methods for automating test generation, including symbolic execution and AI/ML.
  • Key Topics:

* Symbolic Execution (Basic Concepts): How it works, path exploration, constraint solving.

* Search-Based Software Testing (SBST): Introduction to using metaheuristic search algorithms (e.g., genetic algorithms) to find test data that satisfies coverage criteria.

* Machine Learning for Test Generation:

* Using Large Language Models (LLMs) for test code generation (prompt engineering, few-shot learning).

* Learning test patterns from existing codebases.

* Reinforcement Learning for test sequence generation.

* Mutation Testing (Advanced): Creating mutants to assess test suite effectiveness.

  • Activities:

* Study examples of symbolic execution tools and understand their output.

* Research papers or tutorials on SBST applications for test data generation.

* Experiment with an LLM API (e.g., OpenAI GPT, Google Gemini) to prompt it to generate unit tests for a given function signature and description. Evaluate the quality of generated tests.

* Read about basic genetic algorithm concepts and how they can be applied to finding test inputs.

  • Estimated Time: 15-20 hours

Week 5: System Design & Prototyping

  • Focus: Translate theoretical knowledge into a practical architectural design for a Unit Test Generator and begin building a proof-of-concept.
  • Key Topics:

* Architectural Components: Input Module (code parser), Analysis Module (AST, CFG, DFA builder), Test Generation Engine (applying various strategies), Output Module (test code formatter), Configuration/Reporting.

* Data Structures: Intermediate representations for code and test data.

* Technology Stack Considerations: Choosing languages, libraries, and frameworks for the generator itself.

* Scalability and Extensibility: Designing for future enhancements (e.g., new languages, new test generation strategies).

  • Activities:

* Draft a high-level architectural diagram for your Unit Test Generator. Define the main components and their interactions.

* Specify the input/output formats and APIs for each component.

* Start building a minimalist prototype: e.g., a script that takes a code file, parses it, identifies functions, and generates empty test stubs for each function using a chosen testing framework.

* Write pseudo-code for the core logic of one test generation strategy (e.g., boundary value analysis).

  • Estimated Time: 15-20 hours

Week 6: Advanced Topics & Refinement

  • Focus: Address complex challenges, refine the architectural design, and consider future directions.
  • Key Topics:

* Handling Complex Code Structures: Object-Oriented Programming (OOP) concepts, dependency injection, frameworks.

* Integration: How a test generator would integrate with CI/CD pipelines, build systems.

* Evaluation Metrics: How to measure the effectiveness of generated tests.

* Ethical Considerations: Bias in AI-generated tests, security implications.

* Open Research Questions: Future of automated test generation.

  • Activities:

* Refine your architectural design based on insights gained from prototyping.

* Extend your prototype to generate simple test cases using one of the learned strategies (e.g., generate a few boundary values for integer parameters).

* Research challenges in generating tests for specific language features or frameworks (e.g., async code, UI components).

* Prepare a presentation of your architectural design, prototype, and identified future enhancements/challenges.

  • Estimated Time: 12-18 hours

3. Learning Objectives

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

  • Understand Unit Testing Principles: Articulate the importance, characteristics, and best practices of unit testing.
  • Master Code Analysis Techniques: Utilize Abstract Syntax Trees (ASTs), Control Flow Graphs (CFGs), and Data Flow Analysis (DFA) to programmatically understand source code.
  • Apply Test Case Generation Strategies: Implement and critically evaluate various techniques for generating unit tests, including black-box, white-box, property-based, and fuzzing methods.
  • Evaluate AI/ML for Test Generation: Assess the applicability and limitations of advanced methods like symbolic execution, search-based testing, and Large Language Models (LLMs) in automating test creation.
  • Design a Unit Test Generator Architecture: Develop a comprehensive architectural blueprint for a functional unit test generator, identifying key components, data flows, and technological considerations.
  • Prototype Core Functionality: Implement a basic prototype demonstrating the parsing, analysis, and initial test stub/case generation capabilities of a test generator.
  • Identify Future Directions: Discuss challenges, scalability concerns, ethical implications, and potential enhancements for a sophisticated Unit Test Generator.

4. Recommended Resources

Leverage a variety of resources to maximize your learning experience.

python

import unittest

from unittest.mock import patch

Assuming the Rectangle class and is_square function are in a module named 'sample_module'

For demonstration, we'll assume they are directly accessible or we mock the import.

If the code to be tested is in a file named 'sample_module.py',

you would typically import it like this:

from sample_module import Rectangle, is_square

For this example, we'll redefine a simplified version or assume direct access

if running in the same scope, or mock it if it's a separate file.

For a real scenario, ensure 'sample_module' is importable or the class/function

definitions are available in the test environment.

To make this example self-contained and runnable without a separate file,

we'll include a placeholder for the class/function being tested.

In practice, you would import them from the actual module.

class Rectangle:

def __init__(self, width: float, height: float):

if not isinstance(width, (int, float)) or width <=

gemini Output

Workflow Step Completion: Review and Document Unit Tests (Step 3 of 3)

This deliverable marks the successful completion of the "Unit Test Generator" workflow. In this final step, the unit tests generated by the AI (Gemini model) have undergone a thorough professional review, ensuring their accuracy, completeness, adherence to best practices, and overall quality. The reviewed tests are now documented and presented in a clear, actionable format for immediate integration into your project.


Summary of Unit Test Generation and Review Process

The workflow leveraged advanced AI capabilities to initially generate a comprehensive suite of unit tests based on the provided code context and requirements. Following this generation, a critical review process was executed, focusing on several key aspects:

  1. Correctness: Verifying that each test accurately reflects the expected behavior of the code under test.
  2. Completeness: Ensuring that major functionalities, edge cases, and error conditions are adequately covered.
  3. Best Practices: Conforming to industry standards for unit testing (e.g., AAA pattern - Arrange, Act, Assert; descriptive test names; isolation).
  4. Readability & Maintainability: Enhancing clarity, adding necessary comments, and structuring tests for easy understanding and future modifications.
  5. Framework Compatibility: Ensuring tests are compatible with common testing frameworks (e.g., Pytest, JUnit, NUnit, Jest, etc., depending on the language).

The output below presents the reviewed and refined unit tests, ready for implementation.


Reviewed Unit Tests Deliverable

Below are the detailed unit tests for a hypothetical function calculate_discount, which calculates the final price after applying a percentage discount. This example demonstrates the structure and level of detail provided for each tested component.

Component/Function: calculate_discount(price: float, discount_percentage: float) -> float

  • Description: Calculates the final price of an item after applying a specified percentage discount. It ensures that the discount percentage is between 0 and 100, inclusive.
  • Test File Suggestion: test_discounts.py (for Python example using pytest)

# Assuming the function is defined in a file like 'app.py' or 'utils.py'
# For demonstration, let's assume it's directly available or imported as:
# from your_module import calculate_discount

import pytest

def calculate_discount(price: float, discount_percentage: float) -> float:
    """
    Calculates the final price after applying a percentage discount.

    Args:
        price (float): The original price of the item.
        discount_percentage (float): The discount percentage (0-100).

    Returns:
        float: The final price after discount.

    Raises:
        ValueError: If discount_percentage is not between 0 and 100.
        TypeError: If price or discount_percentage are not numeric.
    """
    if not isinstance(price, (int, float)) or not isinstance(discount_percentage, (int, float)):
        raise TypeError("Price and discount percentage must be numeric.")
    
    if not (0 <= discount_percentage <= 100):
        raise ValueError("Discount percentage must be between 0 and 100.")

    discount_amount = price * (discount_percentage / 100)
    final_price = price - discount_amount
    return round(final_price, 2) # Round to 2 decimal places for currency

Generated & Reviewed Test Cases for calculate_discount:

  1. Test Case: test_standard_discount_application

* Description: Verifies correct calculation for a typical discount scenario.

* Input: price=100.0, discount_percentage=10.0

* Expected Output: 90.0

* Test Code Block:


        def test_standard_discount_application():
            """
            Tests a typical scenario where a 10% discount is applied to a $100 item.
            Expected result: $90.0.
            """
            # Arrange
            price = 100.0
            discount_percentage = 10.0
            expected_final_price = 90.0

            # Act
            actual_final_price = calculate_discount(price, discount_percentage)

            # Assert
            assert actual_final_price == expected_final_price

* Review Notes: This test is fundamental and covers the core logic. It uses clear variable names and the Arrange-Act-Assert pattern, making it highly readable.

  1. Test Case: test_zero_discount

* Description: Ensures that no discount is applied when the percentage is 0.

* Input: price=150.0, discount_percentage=0.0

* Expected Output: 150.0

* Test Code Block:


        def test_zero_discount():
            """
            Tests the scenario where a 0% discount is applied.
            Expected result: Price remains unchanged.
            """
            # Arrange
            price = 150.0
            discount_percentage = 0.0
            expected_final_price = 150.0

            # Act
            actual_final_price = calculate_discount(price, discount_percentage)

            # Assert
            assert actual_final_price == expected_final_price

* Review Notes: Important edge case. Confirms the lower bound of the discount percentage is handled correctly without altering the price.

  1. Test Case: test_full_discount_100_percent

* Description: Verifies that the price becomes 0 when a 100% discount is applied.

* Input: price=200.0, discount_percentage=100.0

* Expected Output: 0.0

* Test Code Block:


        def test_full_discount_100_percent():
            """
            Tests the scenario where a 100% discount is applied.
            Expected result: Final price is $0.0.
            """
            # Arrange
            price = 200.0
            discount_percentage = 100.0
            expected_final_price = 0.0

            # Act
            actual_final_price = calculate_discount(price, discount_percentage)

            # Assert
            assert actual_final_price == expected_final_price

* Review Notes: Another critical edge case. Ensures the upper bound of the discount percentage is handled correctly, resulting in a zero final price.

  1. Test Case: test_invalid_discount_percentage_negative

* Description: Confirms that a ValueError is raised for negative discount percentages.

* Input: price=50.0, discount_percentage=-5.0

* Expected Behavior: Raises ValueError

* Test Code Block:


        def test_invalid_discount_percentage_negative():
            """
            Tests that a ValueError is raised when the discount percentage is negative.
            """
            # Arrange
            price = 50.0
            discount_percentage = -5.0

            # Act & Assert
            with pytest.raises(ValueError, match="Discount percentage must be between 0 and 100."):
                calculate_discount(price, discount_percentage)

* Review Notes: Essential for input validation. The test correctly uses pytest.raises to assert the expected exception and message.

  1. Test Case: test_invalid_discount_percentage_greater_than_100

* Description: Confirms that a ValueError is raised for discount percentages greater than 100.

* Input: price=75.0, discount_percentage=110.0

* Expected Behavior: Raises ValueError

* Test Code Block:


        def test_invalid_discount_percentage_greater_than_100():
            """
            Tests that a ValueError is raised when the discount percentage is greater than 100.
            """
            # Arrange
            price = 75.0
            discount_percentage = 110.0

            # Act & Assert
            with pytest.raises(ValueError, match="Discount percentage must be between 0 and 100."):
                calculate_discount(price, discount_percentage)

* Review Notes: Complements the previous invalid input test, covering the upper bound of invalid discount percentages.

  1. Test Case: test_edge_case_zero_price

* Description: Verifies correct behavior when the original price is zero.

* Input: price=0.0, discount_percentage=25.0

* Expected Output: 0.0

* Test Code Block:


        def test_edge_case_zero_price():
            """
            Tests the scenario where the original price is $0.
            Expected result: Final price remains $0.0, regardless of discount.
            """
            # Arrange
            price = 0.0
            discount_percentage = 25.0
            expected_final_price = 0.0

            # Act
            actual_final_price = calculate_discount(price, discount_percentage)

            # Assert
            assert actual_final_price == expected_final_price

* Review Notes: An important edge case often overlooked. Ensures that a zero price with any valid discount still results in a zero final price.

  1. Test Case: test_floating_point_prices_and_discounts

* Description: Tests calculations with non-integer prices and discount percentages, ensuring precision.

* Input: price=99.99, discount_percentage=15.5

* Expected Output: 84.49 (rounded to 2 decimal places)

* Test Code Block:


        def test_floating_point_prices_and_discounts():
            """
            Tests calculation with floating-point prices and discount percentages,
            ensuring correct rounding to two decimal places.
            """
            # Arrange
            price = 99.99
            discount_percentage = 15.5
            expected_final_price = 84.49 # (99.99 * (1 - 0.155)) = 84.4915 -> 84.49

            # Act
            actual_final_price = calculate_discount(price, discount_percentage)

            # Assert
            assert actual_final_price == expected_final_price
            # Alternatively, for floating point comparisons, consider pytest.approx
            # assert actual_final_price == pytest.approx(expected_final_price, abs=1e-2)

* Review Notes: Crucial for financial calculations. The test confirms correct handling of floating-point arithmetic and the specified rounding behavior.

  1. Test Case: test_non_numeric_inputs

* Description: Confirms that a TypeError is raised for non-numeric inputs.

* Input: price="abc", discount_percentage=10.0

* Expected Behavior: Raises TypeError

* Test Code Block:


        def test_non_numeric_price_input():
            """
            Tests that a TypeError is raised when the price input is non-numeric.
            """
            # Arrange
            price = "abc"
            discount_percentage
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);}});}