Unit Test Generator
Run ID: 69bca4e077c0421c0bf496372026-03-29Development
PantheraHive BOS
BOS Dashboard

Workflow Execution Summary

Workflow Name: Unit Test Generator

Category: Development

Execution Step: 1 of 2 (generate)

Status: Completed (Conceptual Generation)

The "Unit Test Generator" workflow has processed your request. Given that the code_input provided was a descriptive sentence rather than executable code, the system has generated a conceptual unit test structure for the specified framework (Jest), demonstrating what a typical output would look like with valid code input. This output provides a blueprint for effective unit testing and outlines the types of tests that would be automatically generated for actual code.

Input Analysis and Interpretation

code_input: "This is a test input for the Unit Test Generator workflow. Please generate comprehensive output."

framework: Jest

The provided code_input is a natural language sentence, not a recognizable code block (e.g., JavaScript, Python, TypeScript). For the "Unit Test Generator" to produce functional and executable unit tests, it requires actual source code (functions, classes, modules).

System Interpretation:

  1. Code Parsing: The system was unable to parse the input as executable code to identify functions, classes, or methods.
  2. Test Scenario Identification: Without parsable code, the system could not automatically determine testable units, parameters, return types, or potential edge cases.
  3. Framework Application: The framework: Jest parameter was correctly identified and will be used to structure the conceptual output.

Therefore, instead of generating specific tests for non-existent code, the workflow has generated a comprehensive example of what a Jest test file would contain for a hypothetical JavaScript function, along with detailed explanations and best practices.

Conceptual Unit Test Generation (Jest)

Below is a conceptual Jest unit test file structure. This example demonstrates the typical components and types of tests the generator would produce for a well-defined JavaScript function or module. It serves as a template and guide for writing robust unit tests using Jest.

text • 2,630 chars
### Explanation of Jest Concepts Demonstrated:

*   **`import` statements:** To bring the code under test into the test file.
*   **`describe('ComponentName', ...)`:** Groups related tests. It's good practice to name this after the component or function being tested.
*   **`it('should do something', ...)` or `test('should do something', ...)`:** Defines an individual test case. The description should clearly state what the test is verifying.
*   **`expect(actual).toBe(expected)`:** A core Jest assertion. `toBe` is used for primitive value equality or to check if two objects are the *exact same instance*.
*   **`expect(actual).toEqual(expected)`:** Used for deep equality comparison of objects or arrays.
*   **`expect(actual).toThrow(ErrorType)`:** Used to test if a function throws an error. The function under test must be wrapped in another function (`() => ...`).
*   **`async/await`:** Essential for testing asynchronous code (e.g., Promises).
*   **`jest.fn()` and `jest.mock()`:** Powerful features for creating mock functions and mocking entire modules to isolate the unit under test from its dependencies.
*   **`beforeEach()`/`afterEach()` / `beforeAll()`/`afterAll()`:** Hooks for setting up and tearing down test environments.

## Key Considerations for Test Generation

When providing actual code for the "Unit Test Generator," consider the following for optimal results:

1.  **Modularity:** Ensure your code is broken down into small, testable units (functions, classes). This makes it easier for the generator to identify distinct test cases.
2.  **Clear Inputs/Outputs:** Functions with clearly defined inputs and predictable outputs are ideal for unit testing.
3.  **Dependency Injection:** If your code has external dependencies (e.g., API calls, database access), consider using dependency injection patterns. This allows the generator (or you manually) to easily mock these dependencies during testing, isolating the unit.
4.  **Error Handling:** Explicitly define and handle error conditions in your code. This allows the generator to create tests specifically for these error paths.
5.  **Asynchronous Operations:** Clearly mark asynchronous functions (e.g., `async`/`await`, Promises). The generator can then structure appropriate `async` tests.

## Actionable Recommendations for Next Steps

To fully leverage the "Unit Test Generator" workflow, please follow these recommendations:

1.  **Provide Actual Code Input:** Rerun the workflow with valid JavaScript/TypeScript code. Copy and paste your function, class, or module code directly into the `code_input` field.
    *   **Example:**
        
Sandboxed live preview
Step 2: projectmanager

Unit Test Generator Workflow Output

Workflow Execution Summary:

The "Unit Test Generator" workflow was executed with the provided inputs. Due to the code_input being a descriptive sentence ("This is a test input for the Unit Test Generator workflow. Please generate comprehensive output.") rather than actual executable code, the workflow has generated a demonstrative Jest unit test for a common, simple utility function. This approach ensures you receive a comprehensive example of the workflow's capabilities and how it would function with valid code.

The generated output includes a Jest test file structure, common assertion patterns, and best practices, providing a clear template for your future unit testing needs.


Generated Unit Test (Demonstrative Example)

Below is an example of a Jest unit test for a hypothetical capitalizeFirstLetter utility function. This demonstrates the structure and content you would receive when providing actual JavaScript code as input.

Context:

  • Hypothetical Code (e.g., src/utils.js):

    // src/utils.js
    function capitalizeFirstLetter(string) {
      if (typeof string !== 'string' || string === null || string === undefined) {
        return '';
      }
      if (string.length === 0) {
        return '';
      }
      return string.charAt(0).toUpperCase() + string.slice(1);
    }

    module.exports = { capitalizeFirstLetter };
  • Framework: Jest

// test/utils.test.js

const { capitalizeFirstLetter } = require('../src/utils');

describe('capitalizeFirstLetter', () => {

  // Test Case 1: Standard string input
  test('should capitalize the first letter of a valid string', () => {
    const input = 'hello world';
    const expected = 'Hello world';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 2: String with already capitalized first letter
  test('should return the string unchanged if the first letter is already capitalized', () => {
    const input = 'World';
    const expected = 'World';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 3: Empty string input
  test('should return an empty string for an empty input string', () => {
    const input = '';
    const expected = '';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 4: Single character string
  test('should capitalize a single character string', () => {
    const input = 'a';
    const expected = 'A';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 5: String with leading spaces (should not trim)
  test('should capitalize the first letter even if there are leading spaces', () => {
    const input = '  hello';
    const expected = '  hello'; // Assumes the function does not trim
    // Note: If your function *should* trim, the test and expected output would change.
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 6: Numeric input (invalid type)
  test('should return an empty string for numeric input', () => {
    const input = 123;
    const expected = '';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 7: Null input
  test('should return an empty string for null input', () => {
    const input = null;
    const expected = '';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 8: Undefined input
  test('should return an empty string for undefined input', () => {
    const input = undefined;
    const expected = '';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });

  // Test Case 9: Object input (invalid type)
  test('should return an empty string for object input', () => {
    const input = { key: 'value' };
    const expected = '';
    expect(capitalizeFirstLetter(input)).toBe(expected);
  });
});

Explanation of Generated Test

This section breaks down the components and best practices demonstrated in the generated Jest unit test.

1. Module Import


const { capitalizeFirstLetter } = require('../src/utils');
  • Purpose: This line imports the function(s) you intend to test from their respective file paths.
  • Actionable Detail: Always ensure the path ../src/utils correctly points to the file containing the code under test relative to your test file. If you're using ES Modules (import/export), Jest supports this with proper configuration (e.g., babel-jest or Node.js's native ES module support).

2. Test Suite Definition (describe)


describe('capitalizeFirstLetter', () => {
  // ... tests go here ...
});
  • Purpose: describe blocks group related tests together. The string argument describes the test suite (e.g., the name of the function or module being tested).
  • Actionable Detail: Use describe to organize your tests logically. A good practice is to have one describe block per function or class, or per major feature area. This improves readability and test reporting.

3. Individual Test Cases (test or it)


test('should capitalize the first letter of a valid string', () => {
  // ... test logic ...
});
  • Purpose: test (or its alias it) defines a single, independent test case. The string argument is a human-readable description of what this specific test verifies.
  • Actionable Detail: Write clear, concise test descriptions that explain what is being tested and why (e.g., "should handle edge case X," "should return Y for input Z").

4. Arrange, Act, Assert (AAA Pattern)

Each test case follows the AAA pattern for clarity and maintainability:

  • Arrange: Set up the test data, inputs, and environment.

    const input = 'hello world';
    const expected = 'Hello world';
  • Act: Execute the code under test with the arranged inputs.

    capitalizeFirstLetter(input)
  • Assert: Verify that the output or side effects of the action match the expected outcome.

    expect(capitalizeFirstLetter(input)).toBe(expected);
  • Actionable Detail: Consistently apply the AAA pattern. It makes tests easy to read, understand, and debug.

5. Jest Matchers (expect and .toBe)


expect(capitalizeFirstLetter(input)).toBe(expected);
  • Purpose: expect creates an expectation object, and .toBe is a Jest "matcher" that performs a strict equality check (like ===). Jest provides a rich set of matchers for various assertion types (e.g., .toEqual for deep equality of objects/arrays, .not.toBe for negative assertions, .toThrow for error handling).
  • Actionable Detail: Familiarize yourself with Jest's comprehensive list of matchers. Choose the most appropriate matcher for the type of assertion you need to make. For example, use .toEqual when comparing objects or arrays, as .toBe will only compare references.

6. Comprehensive Test Coverage

The example includes tests for:

  • Standard valid inputs.
  • Edge cases (empty strings, single characters).
  • Invalid inputs (numbers, null, undefined, objects) to ensure robust error handling or graceful degradation.
  • Inputs that might expose common bugs (e.g., already capitalized strings).
  • Inputs with leading spaces (to clarify function behavior regarding trimming).
  • Actionable Detail: Aim for high test coverage that includes not just happy paths, but also edge cases, error conditions, and various types of invalid input. This ensures your code is resilient.

How to Use This Workflow Effectively

To generate useful and accurate unit tests, provide the code_input in the following manner:

  1. Provide Actual Code: The code_input should contain the JavaScript/TypeScript code of the function(s), class(es), or module(s) you want to test.

* Good Example:


        // code_input
        function calculateDiscount(price, discountPercentage) {
          if (discountPercentage < 0 || discountPercentage > 100) {
            throw new Error("Discount percentage must be between 0 and 100.");
          }
          return price * (1 - discountPercentage / 100);
        }
        module.exports = { calculateDiscount };

* Bad Example (current input): "This is a test input..."

  1. Specify the Framework: Always provide the framework (e.g., Jest, Mocha, Vitest) to ensure the generated tests adhere to the correct syntax and conventions.
  1. Context is Key (Optional but Recommended): If your code has external dependencies or specific environmental requirements that influence how it should be tested, you can sometimes include comments or a brief description within the code_input to provide this context. However, for generating unit tests, the focus is typically on isolated functions.

Recommendations for Unit Testing with Jest

  1. Isolate Units: Unit tests should test a single "unit" of code in isolation (e.g., a function, a method). Use mocking and spying to control dependencies and prevent external factors from affecting your tests.
  2. Fast and Reliable: Unit tests should run quickly and produce consistent results every time. Avoid reliance on external services, databases, or network calls in unit tests.
  3. Descriptive Test Names: Write clear, concise, and descriptive names for your test suites (describe) and individual test cases (test/it). They should explain what is being tested and what the expected outcome is.

Good:* test('should return 0 for an empty array')

Bad:* test('empty array')

  1. Test Edge Cases: Beyond "happy path" scenarios, ensure you test:

* Empty inputs ('', [], {})

* Null/Undefined inputs

* Invalid inputs (wrong data types)

* Boundary conditions (e.g., min/max values, first/last elements)

* Error handling

  1. One Assertion Per Test (Guideline): While not a strict rule, aiming for one logical assertion per test case can make tests easier to understand and debug. If a test fails, you know exactly which expectation was not met.
  2. Use beforeEach/afterEach for Setup/Teardown: For common setup or cleanup logic that applies to multiple tests within a describe block, use beforeEach and afterEach hooks to keep your test cases clean.
  3. Snapshot Testing for UI Components: Jest's snapshot testing is excellent for React components or large configuration objects to ensure UI doesn't unexpectedly change.
  4. Mocking Dependencies: Use jest.mock() or jest.spyOn() to mock external modules, functions, or API calls, ensuring your unit tests only focus on the code under test.
  5. Continuously Integrate: Integrate your unit tests into your CI/CD pipeline to automatically run tests on every code push, catching regressions early.

Next Steps & Further Assistance

  1. Provide Actual Code: The most crucial next step is to provide actual JavaScript/TypeScript code as code_input to the "Unit Test Generator" workflow.
  2. Execute Tests: Once you have generated test files, you can run them using Jest.

* Installation: If not already installed, run npm install --save-dev jest or yarn add --dev jest.

* package.json script: Add "test": "jest" to your scripts section in package.json.

* Run: Execute npm test or yarn test in your terminal.

  1. Refine & Expand: Review the generated tests. While comprehensive, they serve as a starting point. You may need to add more specific tests based on your domain logic, complex edge cases, or specific requirements.
  2. Consult Jest Documentation: For advanced testing scenarios (e.g., asynchronous code, mocking, snapshot testing), refer to the official Jest documentation: [https://jestjs.io/docs/](https://jestjs.io/docs/)

If you have a specific code snippet you'd like to test, please provide it, and I will generate a tailored unit test for you.

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);}});}