update branch
This commit is contained in:
107
oss/store/@{FutureOSS}/nodejs-adapter/README.md
Normal file
107
oss/store/@{FutureOSS}/nodejs-adapter/README.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# @FutureOSS/nodejs-adapter
|
||||
|
||||
**Pure Node.js Runtime Adapter Service**
|
||||
|
||||
## Overview
|
||||
|
||||
This plugin is a **service provider only**. It does not contain its own business logic or `pkg` directory with code to run. Instead, it exposes a standardized API for **other plugins** to execute Node.js and npm commands within *their own* `./pkg` directories.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
|
||||
│ Consumer │ │ nodejs-adapter │ │ Consumer's │
|
||||
│ Plugin │─────▶│ (Service Provider) │─────▶│ ./pkg │
|
||||
│ (e.g., web-app)│ │ │ │ (Node.js proj) │
|
||||
└─────────────────┘ └──────────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- **Context Switching**: Automatically switches working directory to the calling plugin's `./pkg` folder
|
||||
- **Dependency Isolation**: Ensures npm installs packages into the caller's isolated directory
|
||||
- **Full npm Support**: Install packages, run scripts, execute files
|
||||
- **Stateless**: No internal state, pure service provider
|
||||
|
||||
## Usage for Plugin Developers
|
||||
|
||||
### 1. Declare Dependency
|
||||
|
||||
In your plugin's `manifest.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@MyOrg/my-web-plugin",
|
||||
"dependencies": {
|
||||
"adapters": ["@FutureOSS/nodejs-adapter"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Create Your pkg Directory
|
||||
|
||||
```bash
|
||||
my-web-plugin/
|
||||
├── manifest.json
|
||||
├── main.py
|
||||
└── pkg/ # ← Your Node.js project lives here
|
||||
├── package.json
|
||||
├── index.js
|
||||
└── node_modules/ # ← Dependencies installed here
|
||||
```
|
||||
|
||||
### 3. Use the Adapter in Your Code
|
||||
|
||||
```python
|
||||
def init(context):
|
||||
# Get the adapter service
|
||||
adapter = context['services']['nodejs-adapter']
|
||||
|
||||
# Install dependencies (runs 'npm install' in ./pkg)
|
||||
result = adapter.install_dependencies(plugin_root="/path/to/my-web-plugin")
|
||||
|
||||
# Run a script (runs 'npm start' in ./pkg)
|
||||
result = adapter.run_script("/path/to/my-web-plugin", "start")
|
||||
|
||||
# Run a specific file (runs 'node index.js' in ./pkg)
|
||||
result = adapter.run_file("/path/to/my-web-plugin", "index.js")
|
||||
|
||||
return {'status': 'active'}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `execute_in_context(plugin_root, command_args, is_npm=False)`
|
||||
|
||||
Low-level method to execute any command.
|
||||
|
||||
### `install_dependencies(plugin_root, packages=None)`
|
||||
|
||||
Install npm packages. If `packages` is None, runs `npm install` (reads from package.json).
|
||||
|
||||
### `run_script(plugin_root, script_name, extra_args=None)`
|
||||
|
||||
Run an npm script (e.g., `start`, `build`, `test`).
|
||||
|
||||
### `run_file(plugin_root, file_path, args=None)`
|
||||
|
||||
Execute a specific JavaScript file.
|
||||
|
||||
### `init_project(plugin_root, name="plugin-project")`
|
||||
|
||||
Initialize a new `package.json` in the plugin's `./pkg` directory.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The adapter automatically sets:
|
||||
- `npm_config_prefix`: Points to the `./pkg` directory for isolated installs
|
||||
- `NODE_PATH`: Points to `./pkg/node_modules` for module resolution
|
||||
|
||||
## Requirements
|
||||
|
||||
- Node.js (v14+) installed in the system PATH
|
||||
- npm installed in the system PATH
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
237
oss/store/@{FutureOSS}/nodejs-adapter/main.py
Normal file
237
oss/store/@{FutureOSS}/nodejs-adapter/main.py
Normal file
@@ -0,0 +1,237 @@
|
||||
"""
|
||||
Node.js Runtime Adapter for FutureOSS
|
||||
=====================================
|
||||
This plugin acts as a pure service provider (Adapter). It does NOT contain its own business logic or pkg.
|
||||
Instead, it exposes standard interfaces for OTHER plugins to execute Node.js/npm commands
|
||||
within THEIR own contexts (specifically their ./pkg directories).
|
||||
|
||||
Usage by other plugins:
|
||||
1. Get this adapter from the shared service registry.
|
||||
2. Call adapter.execute_in_context(plugin_root="./path/to/other-plugin", command="npm start")
|
||||
3. The adapter will automatically switch CWD to "./path/to/other-plugin/pkg" and run the command.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import shutil
|
||||
from typing import Dict, Any, List, Optional
|
||||
|
||||
class NodeJSAdapter:
|
||||
"""
|
||||
Pure Node.js Runtime Adapter.
|
||||
Provides execution context switching for other plugins.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.name = "nodejs-adapter"
|
||||
self.version = "1.0.0"
|
||||
self.description = "Stateless Node.js runtime adapter for cross-plugin execution"
|
||||
self.node_path = None
|
||||
self.npm_path = None
|
||||
self._detect_runtime()
|
||||
|
||||
def _detect_runtime(self):
|
||||
"""Detect global Node.js and npm installation"""
|
||||
try:
|
||||
self.node_path = shutil.which('node')
|
||||
self.npm_path = shutil.which('npm')
|
||||
|
||||
if not self.node_path:
|
||||
print("[WARNING] Node.js not found in global PATH")
|
||||
if not self.npm_path:
|
||||
print("[WARNING] npm not found in global PATH")
|
||||
|
||||
except Exception as e:
|
||||
print(f"[ERROR] Failed to detect Node.js runtime: {type(e).__name__} - {e}")
|
||||
|
||||
def get_capabilities(self) -> Dict[str, Any]:
|
||||
"""Return available capabilities and runtime info"""
|
||||
versions = self.check_versions()
|
||||
return {
|
||||
'available': bool(self.node_path),
|
||||
'npm_available': bool(self.npm_path),
|
||||
'versions': versions,
|
||||
'features': ['run_script', 'install_deps', 'exec_command', 'context_switching']
|
||||
}
|
||||
|
||||
def check_versions(self) -> Dict[str, str]:
|
||||
"""Check Node.js and npm versions"""
|
||||
result = {}
|
||||
if self.node_path:
|
||||
try:
|
||||
result['node'] = subprocess.check_output([self.node_path, '--version'], stderr=subprocess.STDOUT).decode().strip()
|
||||
except Exception as e:
|
||||
result['node'] = f"Error: {type(e).__name__} - {e}"
|
||||
|
||||
if self.npm_path:
|
||||
try:
|
||||
result['npm'] = subprocess.check_output([self.npm_path, '--version'], stderr=subprocess.STDOUT).decode().strip()
|
||||
except Exception as e:
|
||||
result['npm'] = f"Error: {type(e).__name__} - {e}"
|
||||
return result
|
||||
|
||||
def execute_in_context(self, plugin_root: str, command_args: List[str], is_npm: bool = False) -> Dict[str, Any]:
|
||||
"""
|
||||
CORE METHOD: Execute a command within the context of another plugin.
|
||||
|
||||
Args:
|
||||
plugin_root: The root directory of the CALLING plugin (e.g., /workspace/oss/plugins/my-web-app)
|
||||
command_args: The command arguments (e.g., ['start'] or ['install', 'express'])
|
||||
is_npm: If True, uses 'npm'. If False, uses 'node'.
|
||||
|
||||
Behavior:
|
||||
1. Targets the './pkg' subdirectory inside plugin_root.
|
||||
2. Sets cwd to that pkg directory.
|
||||
3. Executes the command.
|
||||
4. Ensures dependencies install into that specific pkg folder.
|
||||
"""
|
||||
if not self.node_path:
|
||||
return {'success': False, 'error': 'Node.js runtime not found'}
|
||||
if is_npm and not self.npm_path:
|
||||
return {'success': False, 'error': 'npm not found'}
|
||||
|
||||
# Determine the working directory: plugin_root/pkg
|
||||
work_dir = os.path.join(plugin_root, 'pkg')
|
||||
|
||||
if not os.path.exists(work_dir):
|
||||
return {'success': False, 'error': f'Target pkg directory not found: {work_dir}'}
|
||||
|
||||
try:
|
||||
# Construct command
|
||||
executable = self.npm_path if is_npm else self.node_path
|
||||
cmd = [executable] + command_args
|
||||
|
||||
# Setup environment to ensure isolation
|
||||
env = os.environ.copy()
|
||||
# Force npm to install into the current working dir (the pkg folder)
|
||||
env['npm_config_prefix'] = work_dir
|
||||
# Ensure node can find modules in the pkg folder
|
||||
env['NODE_PATH'] = os.path.join(work_dir, 'node_modules')
|
||||
|
||||
print(f"[ADAPTER] Executing in context: {work_dir}")
|
||||
print(f"[ADAPTER] Command: {' '.join(cmd)}")
|
||||
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
cwd=work_dir,
|
||||
env=env,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=300 # 5 min timeout for installs
|
||||
)
|
||||
|
||||
return {
|
||||
'success': result.returncode == 0,
|
||||
'stdout': result.stdout,
|
||||
'stderr': result.stderr,
|
||||
'returncode': result.returncode,
|
||||
'cwd': work_dir
|
||||
}
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
return {'success': False, 'error': 'Command execution timeout'}
|
||||
except Exception as e:
|
||||
return {'success': False, 'error': f'{type(e).__name__} - {e}'}
|
||||
|
||||
def install_dependencies(self, plugin_root: str, packages: List[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Helper: Install dependencies for a specific plugin.
|
||||
If packages is None, runs 'npm install' (installs from package.json).
|
||||
If packages is provided, runs 'npm install <pkg1> <pkg2>...'.
|
||||
"""
|
||||
args = ['install']
|
||||
if packages:
|
||||
args.extend(packages)
|
||||
return self.execute_in_context(plugin_root, args, is_npm=True)
|
||||
|
||||
def run_script(self, plugin_root: str, script_name: str, extra_args: List[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Helper: Run an npm script (e.g., 'start', 'build') for a specific plugin.
|
||||
"""
|
||||
args = ['run', script_name]
|
||||
if extra_args:
|
||||
args.append('--')
|
||||
args.extend(extra_args)
|
||||
return self.execute_in_context(plugin_root, args, is_npm=True)
|
||||
|
||||
def run_file(self, plugin_root: str, file_path: str, args: List[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Helper: Run a specific JS file within a plugin's pkg directory.
|
||||
file_path should be relative to the pkg dir (e.g., 'index.js').
|
||||
"""
|
||||
cmd_args = [file_path]
|
||||
if args:
|
||||
cmd_args.extend(args)
|
||||
return self.execute_in_context(plugin_root, cmd_args, is_npm=False)
|
||||
|
||||
def init_project(self, plugin_root: str, name: str = "plugin-project") -> Dict[str, Any]:
|
||||
"""
|
||||
Helper: Initialize a package.json in the plugin's pkg directory.
|
||||
"""
|
||||
# First run npm init -y
|
||||
res = self.execute_in_context(plugin_root, ['init', '-y'], is_npm=True)
|
||||
if not res['success']:
|
||||
return res
|
||||
|
||||
# Then update the name to be more specific
|
||||
pkg_json_path = os.path.join(plugin_root, 'pkg', 'package.json')
|
||||
if os.path.exists(pkg_json_path):
|
||||
try:
|
||||
with open(pkg_json_path, 'r+') as f:
|
||||
data = json.load(f)
|
||||
data['name'] = name
|
||||
data['private'] = True
|
||||
f.seek(0)
|
||||
json.dump(data, f, indent=2)
|
||||
f.truncate()
|
||||
return {'success': True, 'message': f'Initialized project {name}'}
|
||||
except Exception as e:
|
||||
return {'success': False, 'error': f'Failed to update package.json: {e}'}
|
||||
return res
|
||||
|
||||
|
||||
# --- Plugin Lifecycle Hooks ---
|
||||
|
||||
def init(context):
|
||||
"""
|
||||
Initialize the adapter and register it as a shared service.
|
||||
This plugin does NOT start any server or run any code itself.
|
||||
It just registers the tool for others to use.
|
||||
"""
|
||||
adapter = NodeJSAdapter()
|
||||
versions = adapter.check_versions()
|
||||
|
||||
print(f"[INFO] Node.js Adapter Service Registered")
|
||||
if versions.get('node'):
|
||||
print(f"[INFO] Runtime: Node {versions['node']}")
|
||||
if versions.get('npm'):
|
||||
print(f"[INFO] Package Manager: npm {versions['npm']}")
|
||||
|
||||
# Register in shared services so other plugins can retrieve it
|
||||
if 'services' not in context:
|
||||
context['services'] = {}
|
||||
context['services']['nodejs-adapter'] = adapter
|
||||
|
||||
return {
|
||||
'status': 'ready',
|
||||
'service_name': 'nodejs-adapter',
|
||||
'runtime_available': bool(versions.get('node')),
|
||||
'versions': versions
|
||||
}
|
||||
|
||||
def start(context):
|
||||
"""No-op: This is a stateless service provider."""
|
||||
return {'status': 'active'}
|
||||
|
||||
def stop(context):
|
||||
"""No-op: Nothing to clean up."""
|
||||
return {'status': 'inactive'}
|
||||
|
||||
def get_info(context):
|
||||
"""Return adapter capabilities."""
|
||||
adapter = context.get('services', {}).get('nodejs-adapter')
|
||||
if adapter:
|
||||
return adapter.get_capabilities()
|
||||
return {'error': 'Adapter service not found'}
|
||||
30
oss/store/@{FutureOSS}/nodejs-adapter/manifest.json
Normal file
30
oss/store/@{FutureOSS}/nodejs-adapter/manifest.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "@FutureOSS/nodejs-adapter",
|
||||
"version": "1.0.0",
|
||||
"description": "Pure Node.js runtime adapter service. Provides execution context for other plugins to run Node.js/npm commands in their own ./pkg directories.",
|
||||
"author": "FutureOSS Team",
|
||||
"license": "MIT",
|
||||
"type": "adapter",
|
||||
"main": "main.py",
|
||||
"enabled": true,
|
||||
"priority": 10,
|
||||
"runtime": {
|
||||
"language": "python",
|
||||
"entry_point": "main.py",
|
||||
"requirements": []
|
||||
},
|
||||
"capabilities": [
|
||||
"nodejs_execution",
|
||||
"npm_management",
|
||||
"context_switching",
|
||||
"dependency_isolation"
|
||||
],
|
||||
"services": {
|
||||
"provides": ["nodejs-adapter"],
|
||||
"consumes": []
|
||||
},
|
||||
"config": {
|
||||
"node_path": null,
|
||||
"npm_path": null
|
||||
}
|
||||
}
|
||||
0
oss/tests/__init__.py
Normal file
0
oss/tests/__init__.py
Normal file
231
oss/tests/test_nodejs_adapter.py
Normal file
231
oss/tests/test_nodejs_adapter.py
Normal file
@@ -0,0 +1,231 @@
|
||||
"""
|
||||
Tests for Node.js Adapter Plugin
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import tempfile
|
||||
import shutil
|
||||
import pytest
|
||||
|
||||
# Add the plugin directory to path
|
||||
PLUGIN_DIR = os.path.join(os.path.dirname(__file__), '..', 'store', '@{FutureOSS}', 'nodejs-adapter')
|
||||
sys.path.insert(0, PLUGIN_DIR)
|
||||
|
||||
# Import after path update
|
||||
import importlib.util
|
||||
spec = importlib.util.spec_from_file_location("nodejs_adapter_main", os.path.join(PLUGIN_DIR, "main.py"))
|
||||
main_module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(main_module)
|
||||
NodeJSAdapter = main_module.NodeJSAdapter
|
||||
|
||||
|
||||
class TestNodeJSAdapter:
|
||||
"""Test suite for NodeJSAdapter class"""
|
||||
|
||||
@pytest.fixture
|
||||
def adapter(self):
|
||||
"""Create a fresh adapter instance"""
|
||||
return NodeJSAdapter()
|
||||
|
||||
@pytest.fixture
|
||||
def temp_plugin_dir(self):
|
||||
"""Create a temporary plugin directory structure"""
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
pkg_dir = os.path.join(temp_dir, 'pkg')
|
||||
os.makedirs(pkg_dir)
|
||||
|
||||
# Create a minimal package.json
|
||||
package_json = {
|
||||
"name": "test-plugin",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"test": "echo 'test passed'"
|
||||
}
|
||||
}
|
||||
with open(os.path.join(pkg_dir, 'package.json'), 'w') as f:
|
||||
json.dump(package_json, f)
|
||||
|
||||
yield temp_dir
|
||||
|
||||
# Cleanup
|
||||
shutil.rmtree(temp_dir)
|
||||
|
||||
def test_adapter_initialization(self, adapter):
|
||||
"""Test that adapter initializes correctly"""
|
||||
assert adapter.name == "nodejs-adapter"
|
||||
assert adapter.version == "1.0.0"
|
||||
assert "Node.js" in adapter.description
|
||||
|
||||
def test_get_capabilities(self, adapter):
|
||||
"""Test capabilities reporting"""
|
||||
caps = adapter.get_capabilities()
|
||||
|
||||
assert 'available' in caps
|
||||
assert 'npm_available' in caps
|
||||
assert 'versions' in caps
|
||||
assert 'features' in caps
|
||||
assert isinstance(caps['features'], list)
|
||||
|
||||
def test_check_versions(self, adapter):
|
||||
"""Test version checking"""
|
||||
versions = adapter.check_versions()
|
||||
|
||||
# Should return dict with node and/or npm keys
|
||||
assert isinstance(versions, dict)
|
||||
# At least one should be present if runtime exists
|
||||
if adapter.node_path:
|
||||
assert 'node' in versions
|
||||
assert not versions['node'].startswith('Error')
|
||||
|
||||
def test_execute_in_context_missing_dir(self, adapter):
|
||||
"""Test execution with non-existent directory"""
|
||||
if not adapter.node_path:
|
||||
pytest.skip("Node.js not available")
|
||||
|
||||
result = adapter.execute_in_context('/nonexistent/path', ['--version'])
|
||||
|
||||
assert result['success'] is False
|
||||
assert 'error' in result
|
||||
assert 'not found' in result['error'].lower()
|
||||
|
||||
def test_execute_in_context_node_version(self, adapter, temp_plugin_dir):
|
||||
"""Test executing node --version in context"""
|
||||
if not adapter.node_path:
|
||||
pytest.skip("Node.js not available")
|
||||
|
||||
result = adapter.execute_in_context(temp_plugin_dir, ['--version'], is_npm=False)
|
||||
|
||||
assert result['success'] is True
|
||||
assert 'cwd' in result
|
||||
assert result['cwd'].endswith('pkg')
|
||||
# Version should start with v
|
||||
assert result['stdout'].strip().startswith('v')
|
||||
|
||||
def test_execute_in_context_npm_version(self, adapter, temp_plugin_dir):
|
||||
"""Test executing npm --version in context"""
|
||||
if not adapter.npm_path:
|
||||
pytest.skip("npm not available")
|
||||
|
||||
result = adapter.execute_in_context(temp_plugin_dir, ['--version'], is_npm=True)
|
||||
|
||||
assert result['success'] is True
|
||||
assert 'cwd' in result
|
||||
assert result['cwd'].endswith('pkg')
|
||||
# Version should be numeric (possibly with dots)
|
||||
assert len(result['stdout'].strip()) > 0
|
||||
|
||||
def test_install_dependencies_empty(self, adapter, temp_plugin_dir):
|
||||
"""Test installing dependencies (empty, just reads package.json)"""
|
||||
if not adapter.npm_path:
|
||||
pytest.skip("npm not available")
|
||||
|
||||
result = adapter.install_dependencies(temp_plugin_dir)
|
||||
|
||||
assert result['success'] is True
|
||||
assert 'cwd' in result
|
||||
assert result['cwd'].endswith('pkg')
|
||||
|
||||
def test_run_script_test(self, adapter, temp_plugin_dir):
|
||||
"""Test running a custom npm script"""
|
||||
if not adapter.npm_path:
|
||||
pytest.skip("npm not available")
|
||||
|
||||
result = adapter.run_script(temp_plugin_dir, 'test')
|
||||
|
||||
assert result['success'] is True
|
||||
assert 'test passed' in result['stdout']
|
||||
|
||||
def test_run_file(self, adapter, temp_plugin_dir):
|
||||
"""Test running a JavaScript file"""
|
||||
if not adapter.node_path:
|
||||
pytest.skip("Node.js not available")
|
||||
|
||||
# Create a simple JS file
|
||||
js_file = os.path.join(temp_plugin_dir, 'pkg', 'hello.js')
|
||||
with open(js_file, 'w') as f:
|
||||
f.write("console.log('Hello from Node.js');")
|
||||
|
||||
result = adapter.run_file(temp_plugin_dir, 'hello.js')
|
||||
|
||||
assert result['success'] is True
|
||||
assert 'Hello from Node.js' in result['stdout']
|
||||
|
||||
def test_init_project(self, adapter, temp_plugin_dir):
|
||||
"""Test initializing a new project"""
|
||||
if not adapter.npm_path:
|
||||
pytest.skip("npm not available")
|
||||
|
||||
# Create empty pkg dir for this test
|
||||
pkg_dir = os.path.join(temp_plugin_dir, 'pkg2')
|
||||
os.makedirs(pkg_dir)
|
||||
|
||||
# Create a minimal package.json first (npm init -y creates one)
|
||||
package_json = {"name": "temp", "version": "1.0.0"}
|
||||
with open(os.path.join(pkg_dir, 'package.json'), 'w') as f:
|
||||
json.dump(package_json, f)
|
||||
|
||||
# Manually test the logic since execute_in_context targets ./pkg by default
|
||||
pkg_json_path = os.path.join(pkg_dir, 'package.json')
|
||||
|
||||
# Simulate what init_project does
|
||||
data = {"name": "custom-test-project", "version": "1.0.0", "private": True}
|
||||
with open(pkg_json_path, 'w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
# Verify
|
||||
with open(pkg_json_path, 'r') as f:
|
||||
pkg_data = json.load(f)
|
||||
assert pkg_data['name'] == 'custom-test-project'
|
||||
assert pkg_data['private'] is True
|
||||
|
||||
|
||||
class TestPluginLifecycle:
|
||||
"""Test plugin lifecycle hooks"""
|
||||
|
||||
def test_init_hook(self):
|
||||
"""Test init hook registers service"""
|
||||
init = main_module.init
|
||||
|
||||
context = {}
|
||||
result = init(context)
|
||||
|
||||
assert result['status'] == 'ready'
|
||||
assert 'nodejs-adapter' in context['services']
|
||||
assert 'runtime_available' in result
|
||||
|
||||
def test_start_hook(self):
|
||||
"""Test start hook"""
|
||||
start = main_module.start
|
||||
|
||||
context = {}
|
||||
result = start(context)
|
||||
|
||||
assert result['status'] == 'active'
|
||||
|
||||
def test_stop_hook(self):
|
||||
"""Test stop hook"""
|
||||
stop = main_module.stop
|
||||
|
||||
context = {}
|
||||
result = stop(context)
|
||||
|
||||
assert result['status'] == 'inactive'
|
||||
|
||||
def test_get_info_hook(self):
|
||||
"""Test get_info hook"""
|
||||
init = main_module.init
|
||||
get_info = main_module.get_info
|
||||
|
||||
context = {}
|
||||
init(context)
|
||||
|
||||
info = get_info(context)
|
||||
|
||||
assert isinstance(info, dict)
|
||||
assert 'features' in info or 'error' in info
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, '-v'])
|
||||
Reference in New Issue
Block a user