onairos 2.2.1 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LARAVEL_INTEGRATION_GUIDE.md +643 -0
- package/LARAVEL_TECHNICAL_EXPLANATION.md +465 -0
- package/README.md +122 -43
- package/dist/onairos-laravel.js +2 -0
- package/dist/onairos-laravel.js.map +1 -0
- package/laravel.txt +430 -0
- package/package.json +31 -2
- package/src/laravel/OnairosVue.vue +398 -0
- package/src/laravel/blade-helpers.js +263 -0
- package/src/laravel/vite-plugin.js +179 -0
- package/tests/laravel/examples/blade-example.test.js +283 -0
- package/tests/laravel/laravel-integration.test.js +647 -0
- package/tests/laravel/setup.js +84 -0
- package/tests/laravel/vitest.config.js +20 -0
- package/webpack.config.js +46 -13
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onairos Vite Plugin for Laravel
|
|
3
|
+
*
|
|
4
|
+
* This plugin provides seamless integration of Onairos components
|
|
5
|
+
* within Laravel Vite applications, handling both development and
|
|
6
|
+
* production builds.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { resolve } from 'path';
|
|
10
|
+
|
|
11
|
+
export function onairosLaravelPlugin(options = {}) {
|
|
12
|
+
const defaultOptions = {
|
|
13
|
+
autoImport: true,
|
|
14
|
+
injectGlobals: true,
|
|
15
|
+
optimizeDeps: true,
|
|
16
|
+
enableHMR: true,
|
|
17
|
+
bladeSupport: true
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const config = { ...defaultOptions, ...options };
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
name: 'onairos-laravel',
|
|
24
|
+
config(viteConfig, { command }) {
|
|
25
|
+
// Optimize dependencies for faster dev server startup
|
|
26
|
+
if (config.optimizeDeps) {
|
|
27
|
+
viteConfig.optimizeDeps = viteConfig.optimizeDeps || {};
|
|
28
|
+
viteConfig.optimizeDeps.include = viteConfig.optimizeDeps.include || [];
|
|
29
|
+
viteConfig.optimizeDeps.include.push('onairos');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Add alias for easier imports
|
|
33
|
+
viteConfig.resolve = viteConfig.resolve || {};
|
|
34
|
+
viteConfig.resolve.alias = viteConfig.resolve.alias || {};
|
|
35
|
+
viteConfig.resolve.alias['@onairos'] = resolve('node_modules/onairos');
|
|
36
|
+
|
|
37
|
+
// Configure for Laravel Blade support
|
|
38
|
+
if (config.bladeSupport && command === 'serve') {
|
|
39
|
+
viteConfig.server = viteConfig.server || {};
|
|
40
|
+
viteConfig.server.watch = viteConfig.server.watch || {};
|
|
41
|
+
viteConfig.server.watch.include = viteConfig.server.watch.include || [];
|
|
42
|
+
viteConfig.server.watch.include.push('resources/views/**/*.blade.php');
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
configureServer(server) {
|
|
47
|
+
if (config.enableHMR) {
|
|
48
|
+
// Add custom HMR handling for Onairos components
|
|
49
|
+
server.ws.on('onairos:reload', () => {
|
|
50
|
+
server.ws.send({
|
|
51
|
+
type: 'full-reload'
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
transformIndexHtml: {
|
|
58
|
+
enforce: 'pre',
|
|
59
|
+
transform(html, context) {
|
|
60
|
+
if (config.injectGlobals && context.server) {
|
|
61
|
+
// Inject Onairos initialization script for development
|
|
62
|
+
const initScript = `
|
|
63
|
+
<script type="module">
|
|
64
|
+
import { initializeOnairosForBlade } from '/node_modules/onairos/src/laravel/blade-helpers.js';
|
|
65
|
+
|
|
66
|
+
// Initialize Onairos for Laravel Blade templates
|
|
67
|
+
initializeOnairosForBlade({
|
|
68
|
+
testMode: true,
|
|
69
|
+
autoDetectMobile: true,
|
|
70
|
+
globalStyles: true
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Enable HMR for Onairos components
|
|
74
|
+
if (import.meta.hot) {
|
|
75
|
+
import.meta.hot.on('onairos:update', () => {
|
|
76
|
+
console.log('🔥 Onairos components updated');
|
|
77
|
+
window.location.reload();
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
</script>
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
return html.replace('<head>', `<head>${initScript}`);
|
|
84
|
+
}
|
|
85
|
+
return html;
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
generateBundle(options, bundle) {
|
|
90
|
+
// Add Onairos assets to the build output
|
|
91
|
+
if (config.autoImport) {
|
|
92
|
+
// Create a separate chunk for Laravel integration
|
|
93
|
+
this.emitFile({
|
|
94
|
+
type: 'chunk',
|
|
95
|
+
id: 'onairos-laravel-integration',
|
|
96
|
+
fileName: 'onairos-laravel.js'
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
writeBundle(options, bundle) {
|
|
102
|
+
// Create Laravel-specific integration files
|
|
103
|
+
const laravelIntegrationCode = `
|
|
104
|
+
// Onairos Laravel Integration
|
|
105
|
+
import { initializeOnairosForBlade, createOnairosButton } from 'onairos/blade';
|
|
106
|
+
|
|
107
|
+
// Auto-initialize for production
|
|
108
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
109
|
+
initializeOnairosForBlade({
|
|
110
|
+
testMode: false,
|
|
111
|
+
autoDetectMobile: true,
|
|
112
|
+
globalStyles: true
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Export for manual usage
|
|
117
|
+
window.Onairos = {
|
|
118
|
+
init: initializeOnairosForBlade,
|
|
119
|
+
createButton: createOnairosButton
|
|
120
|
+
};
|
|
121
|
+
`;
|
|
122
|
+
|
|
123
|
+
// Write the integration file
|
|
124
|
+
this.emitFile({
|
|
125
|
+
type: 'asset',
|
|
126
|
+
fileName: 'onairos-laravel-integration.js',
|
|
127
|
+
source: laravelIntegrationCode
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Vue.js specific plugin for Laravel
|
|
134
|
+
export function onairosVuePlugin(options = {}) {
|
|
135
|
+
return {
|
|
136
|
+
name: 'onairos-vue-laravel',
|
|
137
|
+
config(viteConfig) {
|
|
138
|
+
// Add Vue-specific optimizations for Onairos
|
|
139
|
+
viteConfig.optimizeDeps = viteConfig.optimizeDeps || {};
|
|
140
|
+
viteConfig.optimizeDeps.include = viteConfig.optimizeDeps.include || [];
|
|
141
|
+
viteConfig.optimizeDeps.include.push('onairos', 'vue');
|
|
142
|
+
},
|
|
143
|
+
|
|
144
|
+
transform(code, id) {
|
|
145
|
+
// Auto-import Onairos in Vue components
|
|
146
|
+
if (id.endsWith('.vue') && options.autoImport) {
|
|
147
|
+
if (code.includes('OnairosButton') && !code.includes('import.*OnairosButton')) {
|
|
148
|
+
return `import { OnairosButton } from 'onairos';\n${code}`;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// React specific plugin for Laravel
|
|
157
|
+
export function onairosReactPlugin(options = {}) {
|
|
158
|
+
return {
|
|
159
|
+
name: 'onairos-react-laravel',
|
|
160
|
+
config(viteConfig) {
|
|
161
|
+
// Add React-specific optimizations for Onairos
|
|
162
|
+
viteConfig.optimizeDeps = viteConfig.optimizeDeps || {};
|
|
163
|
+
viteConfig.optimizeDeps.include = viteConfig.optimizeDeps.include || [];
|
|
164
|
+
viteConfig.optimizeDeps.include.push('onairos', 'react', 'react-dom');
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
transform(code, id) {
|
|
168
|
+
// Auto-import Onairos in React components
|
|
169
|
+
if ((id.endsWith('.jsx') || id.endsWith('.tsx')) && options.autoImport) {
|
|
170
|
+
if (code.includes('OnairosButton') && !code.includes('import.*OnairosButton')) {
|
|
171
|
+
return `import { OnairosButton } from 'onairos';\n${code}`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export default onairosLaravelPlugin;
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Laravel Blade Integration Example Test
|
|
3
|
+
*
|
|
4
|
+
* This test simulates a real Laravel application using Blade templates
|
|
5
|
+
* with Onairos integration.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, test, expect, beforeEach } from 'vitest';
|
|
9
|
+
import { JSDOM } from 'jsdom';
|
|
10
|
+
import { initializeOnairosForBlade, createOnairosButton } from '../../../src/laravel/blade-helpers.js';
|
|
11
|
+
|
|
12
|
+
describe('Laravel Blade Real-World Example', () => {
|
|
13
|
+
let dom;
|
|
14
|
+
let window;
|
|
15
|
+
let document;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
// Create a DOM that mimics a Laravel Blade template
|
|
19
|
+
dom = new JSDOM(`
|
|
20
|
+
<!DOCTYPE html>
|
|
21
|
+
<html lang="en">
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="UTF-8">
|
|
24
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
25
|
+
<title>Laravel App with Onairos</title>
|
|
26
|
+
<meta name="csrf-token" content="fake-csrf-token">
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<div class="container">
|
|
30
|
+
<nav class="navbar">
|
|
31
|
+
<h1>My Laravel App</h1>
|
|
32
|
+
</nav>
|
|
33
|
+
|
|
34
|
+
<main class="content">
|
|
35
|
+
<div class="dashboard">
|
|
36
|
+
<h2>User Dashboard</h2>
|
|
37
|
+
<p>Connect your social accounts to enhance your experience:</p>
|
|
38
|
+
|
|
39
|
+
<!-- Onairos button will be inserted here -->
|
|
40
|
+
<div id="social-connect-button" class="mt-4"></div>
|
|
41
|
+
|
|
42
|
+
<div class="user-profile mt-6">
|
|
43
|
+
<h3>Profile Enhancement</h3>
|
|
44
|
+
<p>Let AI analyze your data for better recommendations:</p>
|
|
45
|
+
|
|
46
|
+
<!-- Another Onairos button for advanced features -->
|
|
47
|
+
<div id="profile-enhancement-button" class="mt-2"></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</main>
|
|
51
|
+
</div>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
window = dom.window;
|
|
57
|
+
document = dom.window.document;
|
|
58
|
+
|
|
59
|
+
// Set globals for testing
|
|
60
|
+
global.window = window;
|
|
61
|
+
global.document = document;
|
|
62
|
+
global.navigator = window.navigator;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test('should integrate Onairos into Laravel dashboard page', () => {
|
|
66
|
+
// 1. Initialize Onairos as would be done in Laravel app.js
|
|
67
|
+
initializeOnairosForBlade({
|
|
68
|
+
testMode: true,
|
|
69
|
+
baseUrl: 'https://api2.onairos.uk',
|
|
70
|
+
autoDetectMobile: true,
|
|
71
|
+
globalStyles: true
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// 2. Verify initialization worked
|
|
75
|
+
expect(window.OnairosConfig).toBeDefined();
|
|
76
|
+
expect(window.OnairosConfig.testMode).toBe(true);
|
|
77
|
+
expect(document.getElementById('onairos-styles')).not.toBeNull();
|
|
78
|
+
|
|
79
|
+
// 3. Create social connect button (as would be in Blade template script)
|
|
80
|
+
createOnairosButton('social-connect-button', {
|
|
81
|
+
requestData: ['email', 'profile', 'social'],
|
|
82
|
+
webpageName: 'Laravel Dashboard',
|
|
83
|
+
buttonType: 'pill',
|
|
84
|
+
textColor: 'white',
|
|
85
|
+
onComplete: function(result) {
|
|
86
|
+
console.log('Social connection completed:', result);
|
|
87
|
+
// In real Laravel app, this might update the UI or make AJAX calls
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// 4. Create profile enhancement button
|
|
92
|
+
createOnairosButton('profile-enhancement-button', {
|
|
93
|
+
requestData: {
|
|
94
|
+
basic: { type: "basic", reward: "10 tokens" },
|
|
95
|
+
personality: { type: "personality", reward: "25 tokens" },
|
|
96
|
+
preferences: { type: "preferences", reward: "15 tokens" }
|
|
97
|
+
},
|
|
98
|
+
webpageName: 'Laravel Profile Enhancement',
|
|
99
|
+
buttonType: 'rounded',
|
|
100
|
+
textColor: 'black',
|
|
101
|
+
onComplete: function(result) {
|
|
102
|
+
console.log('Profile enhancement completed:', result);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// 5. Verify both buttons were created successfully
|
|
107
|
+
const socialButton = document.getElementById('social-connect-button-btn');
|
|
108
|
+
const profileButton = document.getElementById('profile-enhancement-button-btn');
|
|
109
|
+
|
|
110
|
+
expect(socialButton).not.toBeNull();
|
|
111
|
+
expect(profileButton).not.toBeNull();
|
|
112
|
+
|
|
113
|
+
// 6. Verify button configurations
|
|
114
|
+
const socialConfig = JSON.parse(socialButton.getAttribute('data-onairos-config'));
|
|
115
|
+
const profileConfig = JSON.parse(profileButton.getAttribute('data-onairos-config'));
|
|
116
|
+
|
|
117
|
+
expect(socialConfig.requestData).toEqual(['email', 'profile', 'social']);
|
|
118
|
+
expect(socialConfig.webpageName).toBe('Laravel Dashboard');
|
|
119
|
+
expect(socialConfig.buttonType).toBe('pill');
|
|
120
|
+
|
|
121
|
+
expect(profileConfig.requestData).toHaveProperty('basic');
|
|
122
|
+
expect(profileConfig.requestData).toHaveProperty('personality');
|
|
123
|
+
expect(profileConfig.webpageName).toBe('Laravel Profile Enhancement');
|
|
124
|
+
expect(profileConfig.buttonType).toBe('rounded');
|
|
125
|
+
|
|
126
|
+
// 7. Verify styling was applied
|
|
127
|
+
expect(socialButton.className).toContain('onairos-btn-pill');
|
|
128
|
+
expect(profileButton.className).toContain('onairos-btn-rounded');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('should handle Laravel CSRF protection', () => {
|
|
132
|
+
// Laravel apps typically have CSRF tokens in meta tags
|
|
133
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
|
|
134
|
+
expect(csrfToken).toBe('fake-csrf-token');
|
|
135
|
+
|
|
136
|
+
// Initialize Onairos with CSRF handling
|
|
137
|
+
initializeOnairosForBlade({
|
|
138
|
+
csrfToken: csrfToken,
|
|
139
|
+
testMode: true
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(window.OnairosConfig.csrfToken).toBe('fake-csrf-token');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('should support Laravel environment variables pattern', () => {
|
|
146
|
+
// Mock Laravel Vite environment variables
|
|
147
|
+
global.import = {
|
|
148
|
+
meta: {
|
|
149
|
+
env: {
|
|
150
|
+
DEV: false,
|
|
151
|
+
PROD: true,
|
|
152
|
+
VITE_APP_NAME: 'Laravel App',
|
|
153
|
+
VITE_ONAIROS_API_KEY: 'prod-api-key',
|
|
154
|
+
VITE_ONAIROS_TEST_MODE: 'false'
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Initialize using Laravel environment pattern
|
|
160
|
+
initializeOnairosForBlade({
|
|
161
|
+
testMode: global.import.meta.env.VITE_ONAIROS_TEST_MODE === 'true',
|
|
162
|
+
apiKey: global.import.meta.env.VITE_ONAIROS_API_KEY,
|
|
163
|
+
appName: global.import.meta.env.VITE_APP_NAME
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect(window.OnairosConfig.testMode).toBe(false);
|
|
167
|
+
expect(window.OnairosConfig.apiKey).toBe('prod-api-key');
|
|
168
|
+
expect(window.OnairosConfig.appName).toBe('Laravel App');
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('should handle mobile responsive behavior in Laravel context', () => {
|
|
172
|
+
// Mock mobile user agent (iPhone)
|
|
173
|
+
Object.defineProperty(window.navigator, 'userAgent', {
|
|
174
|
+
writable: true,
|
|
175
|
+
value: 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15'
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Mock mobile viewport
|
|
179
|
+
Object.defineProperty(window, 'innerWidth', {
|
|
180
|
+
writable: true,
|
|
181
|
+
value: 375
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
initializeOnairosForBlade({
|
|
185
|
+
autoDetectMobile: true
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
expect(window.OnairosUtils.isMobile).toBe(true);
|
|
189
|
+
|
|
190
|
+
// Create a button and verify mobile-specific behavior
|
|
191
|
+
createOnairosButton('mobile-test-button', {
|
|
192
|
+
requestData: ['email'],
|
|
193
|
+
webpageName: 'Mobile Laravel App'
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
const button = document.getElementById('mobile-test-button-btn');
|
|
197
|
+
expect(button).not.toBeNull();
|
|
198
|
+
|
|
199
|
+
// In mobile context, button should have mobile-optimized styling
|
|
200
|
+
const styles = window.getComputedStyle ? window.getComputedStyle(button) : {};
|
|
201
|
+
// Note: JSDOM doesn't compute styles, but we can verify the classes are applied
|
|
202
|
+
expect(button.className).toContain('onairos-btn');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('should simulate Laravel Ajax integration', async () => {
|
|
206
|
+
// Mock Laravel AJAX setup (similar to what Laravel includes by default)
|
|
207
|
+
window.axios = {
|
|
208
|
+
defaults: {
|
|
209
|
+
headers: {
|
|
210
|
+
common: {
|
|
211
|
+
'X-CSRF-TOKEN': 'fake-csrf-token',
|
|
212
|
+
'X-Requested-With': 'XMLHttpRequest'
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
post: vi.fn(() => Promise.resolve({ data: { success: true } }))
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
initializeOnairosForBlade({
|
|
220
|
+
testMode: true,
|
|
221
|
+
onAuthComplete: async function(result) {
|
|
222
|
+
// Simulate Laravel AJAX call to store Onairos data
|
|
223
|
+
try {
|
|
224
|
+
const response = await window.axios.post('/onairos/callback', {
|
|
225
|
+
user_hash: result.userHash,
|
|
226
|
+
connections: result.connectedAccounts,
|
|
227
|
+
data_types: result.requestData
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (response.data.success) {
|
|
231
|
+
console.log('Laravel backend updated successfully');
|
|
232
|
+
}
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error('Laravel integration error:', error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Trigger a simulated auth completion
|
|
240
|
+
const mockResult = {
|
|
241
|
+
userHash: 'test-hash-123',
|
|
242
|
+
connectedAccounts: ['youtube', 'linkedin'],
|
|
243
|
+
requestData: ['email', 'profile']
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
// Simulate the callback
|
|
247
|
+
if (window.OnairosConfig.onAuthComplete) {
|
|
248
|
+
await window.OnairosConfig.onAuthComplete(mockResult);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Verify Laravel AJAX was called
|
|
252
|
+
expect(window.axios.post).toHaveBeenCalledWith('/onairos/callback', {
|
|
253
|
+
user_hash: 'test-hash-123',
|
|
254
|
+
connections: ['youtube', 'linkedin'],
|
|
255
|
+
data_types: ['email', 'profile']
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('should work with Laravel Blade @vite directive pattern', () => {
|
|
260
|
+
// Simulate what happens when Laravel's @vite directive loads assets
|
|
261
|
+
const viteScript = document.createElement('script');
|
|
262
|
+
viteScript.type = 'module';
|
|
263
|
+
viteScript.textContent = `
|
|
264
|
+
// Simulate Vite module loading
|
|
265
|
+
import { initializeOnairosForBlade } from '/resources/js/onairos-setup.js';
|
|
266
|
+
|
|
267
|
+
// Auto-initialize when loaded via Vite
|
|
268
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
269
|
+
initializeOnairosForBlade({
|
|
270
|
+
testMode: import.meta.env.DEV,
|
|
271
|
+
baseUrl: import.meta.env.VITE_ONAIROS_BASE_URL
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
`;
|
|
275
|
+
|
|
276
|
+
document.head.appendChild(viteScript);
|
|
277
|
+
|
|
278
|
+
// Verify script was added (simulating Vite asset injection)
|
|
279
|
+
const addedScript = document.querySelector('script[type="module"]');
|
|
280
|
+
expect(addedScript).not.toBeNull();
|
|
281
|
+
expect(addedScript.textContent).toContain('initializeOnairosForBlade');
|
|
282
|
+
});
|
|
283
|
+
});
|