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

This document details the output for Step 2 of 3: "gemini → generate_code" for the "Unit Test Generator" workflow. In this step, the system leverages the Gemini model to analyze a given piece of source code and generate comprehensive unit tests for it.


Step 2 Deliverable: Generated Unit Test Code

The core deliverable of this step is the production-ready unit test code. Below, we present an example demonstrating how the Gemini model generates tests for a sample Python function.

Sample Input Code (for demonstration)

Let's assume the user provides the following Python function, calculate_discount, for which unit tests are to be generated:

text • 3,355 chars
---

## Explanation of the Generated Code

The generated unit test file (`test_calculate_discount.py`) is structured to provide comprehensive coverage for the `calculate_discount` function:

1.  **Import Statements**:
    *   `unittest`: The standard Python library for writing unit tests.
    *   `calculate_discount`: The function under test, imported from its assumed location (`original_code.py`).

2.  **`TestCalculateDiscount` Class**:
    *   Inherits from `unittest.TestCase`, providing access to various assertion methods.
    *   The class docstring clearly states the purpose and scope of the tests.

3.  **Test Categories**: The tests are logically grouped into distinct categories for readability and maintainability:
    *   **Happy Path Tests**:
        *   `test_positive_price_and_discount`: Verifies correct calculation for typical valid inputs.
        *   `test_zero_discount`: Checks the scenario where no discount is applied.
        *   `test_full_discount`: Tests the scenario where a 100% discount results in a price of 0.
    *   **Edge Case Tests**:
        *   `test_zero_price_with_discount`: Ensures correct behavior when the initial price is zero.
        *   `test_small_price_and_discount`: Handles very small numerical inputs, paying attention to floating-point precision and rounding.
        *   `test_large_price_and_discount`: Verifies functionality with large numerical inputs.
    *   **Error Handling Tests (ValueError)**:
        *   `test_negative_price_raises_value_error`: Confirms that a `ValueError` is raised for invalid negative prices.
        *   `test_discount_below_zero_raises_value_error`: Checks for `ValueError` when `discount_percentage` is less than 0.
        *   `test_discount_above_hundred_raises_value_error`: Checks for `ValueError` when `discount_percentage` is greater than 100.
    *   **Error Handling Tests (TypeError)**:
        *   `test_non_numeric_price_raises_type_error`: Ensures `TypeError` is raised for non-numeric `price` inputs.
        *   `test_non_numeric_discount_raises_type_error`: Ensures `TypeError` is raised for non-numeric `discount_percentage` inputs.
        *   `test_mixed_non_numeric_types_raises_type_error`: Tests scenarios where both inputs are non-numeric.

4.  **Assertion Methods**:
    *   `self.assertAlmostEqual(a, b, places=2)`: Used for comparing floating-point numbers, accounting for potential precision issues, and specifically for checking results rounded to 2 decimal places as per the function's return.
    *   `with self.assertRaisesRegex(ExceptionType, "regex_pattern")`: This context manager is crucial for testing that specific exceptions are raised with particular error messages, ensuring robust error handling.

5.  **`if __name__ == '__main__':` block**:
    *   Allows the test file to be run directly using `python test_calculate_discount.py`.
    *   `unittest.main(argv=['first-arg-is-ignored'], exit=False)`: This setup ensures that the tests can be run from an IDE or other test runner without issues with command-line arguments.

---

## How to Use the Generated Code

To integrate and run these unit tests, follow these steps:

1.  **Save the Original Code**: Save your original function (e.g., `calculate_discount`) in a Python file. For this example, we assume it's saved as `original_code.py` in the same directory.
    
Sandboxed live preview

Comprehensive Study Plan: Unit Test Generator

This document outlines a detailed and professional study plan designed to equip individuals with the knowledge and skills required to understand, design, and potentially build a "Unit Test Generator." This plan is structured to provide a deep dive into the principles of unit testing, code analysis, test case generation strategies, and advanced automation techniques, including potential AI integration.


1. Introduction & Overall Goal

Introduction:

The ability to automatically generate unit tests is a powerful asset in modern software development, significantly enhancing code quality, accelerating development cycles, and improving maintainability. This study plan provides a structured pathway to master the underlying concepts and practical implementation techniques necessary for creating or contributing to a robust Unit Test Generator.

Overall Goal:

To acquire a comprehensive understanding of unit testing principles, code analysis techniques, test case generation methodologies, and advanced automation strategies, enabling the design and development of a functional Unit Test Generator.


2. Target Audience & Assumed Prerequisites

Target Audience:

This study plan is ideal for software engineers, quality assurance professionals, technical leads, and developers interested in test automation, code quality, and leveraging advanced techniques (including AI) for software testing.

Assumed Prerequisites:

  • Intermediate Programming Skills: Proficiency in at least one modern programming language (e.g., Python, Java, C#, JavaScript).
  • Basic Understanding of Software Testing: Familiarity with concepts like debugging, integration testing, and common testing terminology.
  • Object-Oriented Programming (OOP) Concepts: Understanding of classes, objects, inheritance, polymorphism, and encapsulation.
  • Version Control (Git): Basic comfort with Git operations (clone, commit, push, pull).

3. Weekly Schedule

This 4-week schedule is designed to build knowledge progressively, from foundational concepts to advanced implementation.

| Week | Focus Area | Key Activities TBD: The Unit Test Generator will be developed using Python for its robust capabilities in text processing and broad ecosystem for software development. The choice of Python allows for future integration with AI models for sophisticated test generation.


4. Learning Objectives

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

  • Define Unit Testing: Clearly articulate the purpose, benefits, and common pitfalls of unit testing.
  • Identify Testable Units: Systematically identify and isolate units of code suitable for unit testing within a given codebase.
  • Master a Unit Testing Framework: Demonstrate proficiency in writing, running, and debugging tests using a modern unit testing framework (e.g., pytest for Python, JUnit for Java).
  • Apply Test Doubles: Effectively utilize mocks, stubs, and fakes to manage external dependencies and isolate units under test.
  • Understand Code Structure Programmatically: Describe how to parse source code (e.g., using Abstract Syntax Trees - AST) to extract relevant information like function/method signatures, parameters, and return types.
  • Implement Test Case Generation Strategies: Develop logic to automatically generate diverse test cases, including happy path, edge cases, boundary conditions, and error conditions.
  • Explore Property-Based Testing: Understand the principles

bash

python -m unittest test_calculate_discount.py

gemini Output

This document outlines the comprehensive review and detailed documentation for the unit tests generated by the "Unit Test Generator" workflow. This final step (3 of 3) ensures the quality, correctness, and usability of the generated tests, providing actionable insights for their integration and long-term maintenance.


Step 3 of 3: Review and Document Generated Unit Tests

This deliverable provides a thorough review and comprehensive documentation of the unit tests produced by the "Unit Test Generator" workflow's gemini step. The aim is to validate the generated tests against best practices, ensure their accuracy and comprehensiveness, and offer clear guidance for their immediate use and future maintenance.

1. Overview of Generated Unit Tests

  • Purpose: The "Unit Test Generator" automates the creation of foundational unit tests for your source code, significantly reducing manual effort and accelerating the development lifecycle.
  • Methodology: The preceding gemini step utilized advanced AI capabilities to analyze the provided source code (e.g., Python, Java, JavaScript, etc.), understand its functionality, and produce corresponding unit test cases tailored to common testing frameworks.
  • Output Focus: This review focuses on assessing the generated tests for functional correctness, coverage, readability, maintainability, and adherence to industry best practices.

2. Review Methodology and Criteria

Our review process systematically evaluates the generated unit tests across several critical dimensions to ensure they are high-quality, immediately usable, and easily maintainable.

  • Functional Correctness:

* Do the tests accurately verify the expected behavior of the functions, methods, or components under test?

* Are assertions precise and specific enough to catch subtle bugs?

* Do tests reliably pass when the code is correct and fail appropriately when defects are introduced?

  • Test Coverage:

* Do the tests cover a significant portion of the code's logical paths, including various input combinations?

* Are positive, negative, and edge cases adequately considered and tested?

* Are all public interfaces and critical internal components sufficiently covered?

  • Readability and Maintainability:

* Are test names clear, descriptive, and indicative of the specific scenario being tested?

* Is the test code clean, well-structured, and easy for other developers to understand?

* Are setup and teardown procedures handled effectively (e.g., using fixtures, setUp/tearDown methods)?

* Is test logic DRY (Don't Repeat Yourself) with minimal duplication?

  • Adherence to Best Practices:

* Do tests follow established patterns like "Arrange-Act-Assert" for clarity?

* Are tests independent and isolated, preventing one test's outcome from affecting others?

* Are magic numbers or strings avoided in favor of meaningful constants or variables?

* Are mocks, stubs, or fakes used appropriately for external dependencies to ensure true unit isolation?

  • Edge Case and Error Handling:

* Are specific tests included for common edge cases (e.g., empty inputs, null values, boundary conditions, invalid formats)?

* Are error paths and exception handling mechanisms properly tested to ensure robustness?

3. Generated Unit Tests Summary and Analysis

(This section would contain specific details about the generated tests. As an AI, I do not have the actual output from the gemini step. The following content provides a structured template and illustrative examples of the kind of analysis you would receive.)

3.1. Overview of Generated Test Files

  • Source Code Analyzed: [e.g., src/data_processor.py]
  • Generated Test File(s): [e.g., tests/test_data_processor.py]
  • Testing Framework Detected/Used: [e.g., pytest (Python), JUnit 5 (Java), Jest (JavaScript)]
  • Overall Structure:

* Test files are logically organized, mirroring the structure of the source code.

* Each test function/method typically focuses on a single aspect of the functionality.

* Appropriate imports for the source module and the testing framework are included.

* Utilizes framework-specific features like parameterization, fixtures, or @Test annotations.

3.2. Detailed Review Findings & Recommendations

(This is the core of the review, providing specific observations and actionable recommendations. Examples below assume a Python pytest context for a hypothetical data_processor.py module with functions like clean_text, process_numbers, validate_config.)


Module: data_processor.py

Function: clean_text(text: str) -> str

  • Finding (Functional Correctness): The test_clean_text_basic_string and test_clean_text_with_punctuation correctly assert expected cleaned outputs.
  • Recommendation: None needed for these specific cases.
  • Finding (Edge Cases): test_clean_text_empty_string correctly handles an empty input.
  • Recommendation: Add a test case for None input to ensure robust error handling (e.g., pytest.raises(TypeError) or specific handling within the function).
  • Finding (Coverage): test_clean_text_with_numbers is missing, which could be relevant if numbers should also be removed or treated differently.
  • Recommendation: Add test_clean_text_numbers_and_text to verify behavior with mixed content.

Function: process_numbers(numbers: list[int]) -> float

  • Finding (Functional Correctness): test_process_numbers_positive_list and test_process_numbers_mixed_list correctly calculate the average.
  • Recommendation: None.
  • Finding (Edge Cases): test_process_numbers_empty_list correctly raises ValueError.
  • Recommendation: Consider adding a test for a list containing non-numeric types if the function is expected to handle or reject such inputs gracefully.
  • Finding (Adherence to Best Practices): The tests for this function effectively use @pytest.mark.parametrize to test multiple input lists, demonstrating good practice for reducing test boilerplate.
  • Recommendation: Continue this pattern where applicable.

Function: validate_config(config: dict) -> bool

  • Finding (Functional Correctness): test_validate_config_valid passes for a well-formed configuration.
  • **Recommendation
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);}});}