use-vibes 0.1.0 → 0.2.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/package.json +13 -4
- package/src/components/ImgGen.tsx +242 -0
- package/src/index.ts +7 -114
- package/src/useVibes.ts +116 -0
- package/dist/bookmarklet.html +0 -89
- package/dist/bookmarklet.js +0 -1
- package/dist/src/core/vibe.d.ts +0 -19
- package/dist/src/core/vibe.js +0 -23
- package/dist/src/index.d.ts +0 -14
- package/dist/src/index.js +0 -93
- package/dist/src/utils/enhancer.d.ts +0 -20
- package/dist/src/utils/enhancer.js +0 -31
- package/dist/tests/browser/call-ai-mock.d.ts +0 -2
- package/dist/tests/browser/call-ai-mock.js +0 -71
- package/dist/tests/browser/global-setup.d.ts +0 -3
- package/dist/tests/browser/global-setup.js +0 -86
- package/dist/tests/browser/hello-world.test.d.ts +0 -1
- package/dist/tests/browser/hello-world.test.js +0 -350
- package/dist/tests/browser/helpers.d.ts +0 -15
- package/dist/tests/browser/helpers.js +0 -32
- package/dist/tests/browser/setup-browser-mocks.d.ts +0 -1
- package/dist/tests/browser/setup-browser-mocks.js +0 -242
- package/dist/tests/vibe.test.d.ts +0 -1
- package/dist/tests/vibe.test.js +0 -60
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Page } from '@playwright/test';
|
|
2
|
-
/**
|
|
3
|
-
* Helper function to inject and test the useVibes module in a browser context
|
|
4
|
-
* This avoids the TypeScript errors from directly importing browser modules in Node.js
|
|
5
|
-
*/
|
|
6
|
-
interface UseVibesConfig {
|
|
7
|
-
prompt: string;
|
|
8
|
-
[key: string]: unknown;
|
|
9
|
-
}
|
|
10
|
-
export declare function applyUseVibes(page: Page, selector: string, config: UseVibesConfig): Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Helper function to apply custom effects in a browser context
|
|
13
|
-
*/
|
|
14
|
-
export declare function applyCustomEffect(page: Page, selector: string, effectFn: string): Promise<void>;
|
|
15
|
-
export {};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
export async function applyUseVibes(page, selector, config) {
|
|
2
|
-
await page.evaluate(({ selector, config }) => {
|
|
3
|
-
return new Promise((resolve, reject) => {
|
|
4
|
-
// Dynamically import the module within the browser context
|
|
5
|
-
import('../../src/index.js')
|
|
6
|
-
.then(({ useVibes }) => {
|
|
7
|
-
const element = document.querySelector(selector);
|
|
8
|
-
if (!element) {
|
|
9
|
-
reject(new Error(`Element not found: ${selector}`));
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
useVibes(element, config)
|
|
13
|
-
.then(() => resolve())
|
|
14
|
-
.catch((err) => reject(err));
|
|
15
|
-
})
|
|
16
|
-
.catch((err) => reject(err));
|
|
17
|
-
});
|
|
18
|
-
}, { selector, config });
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Helper function to apply custom effects in a browser context
|
|
22
|
-
*/
|
|
23
|
-
export async function applyCustomEffect(page, selector, effectFn) {
|
|
24
|
-
await page.evaluate(({ selector, effectFn }) => {
|
|
25
|
-
const element = document.querySelector(selector);
|
|
26
|
-
if (!element)
|
|
27
|
-
return;
|
|
28
|
-
// Execute the string function in the browser context
|
|
29
|
-
const fn = new Function('element', effectFn);
|
|
30
|
-
fn(element);
|
|
31
|
-
}, { selector, effectFn });
|
|
32
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
// Mock implementation for the browser tests
|
|
2
|
-
// This script will be injected into the test page before any tests run
|
|
3
|
-
(function setupMocks() {
|
|
4
|
-
// Module interception - CRITICAL: This must run before any other scripts
|
|
5
|
-
// Create a module-level interception that redirects 'call-ai' imports to our mock
|
|
6
|
-
// Debug indicator that helps us verify our mock is working
|
|
7
|
-
window.__MOCK_STATUS__ = {
|
|
8
|
-
initialized: true,
|
|
9
|
-
moduleIntercepted: false,
|
|
10
|
-
callCount: 0,
|
|
11
|
-
lastPrompt: null,
|
|
12
|
-
lastOptions: null,
|
|
13
|
-
lastResponse: null,
|
|
14
|
-
errors: [],
|
|
15
|
-
};
|
|
16
|
-
// Log that we're starting the mock setup
|
|
17
|
-
/* eslint-disable-next-line no-console */
|
|
18
|
-
console.log('🔄 MOCK SETUP: Initializing module interception for call-ai');
|
|
19
|
-
try {
|
|
20
|
-
// Define our mock implementation that will replace the real callAI
|
|
21
|
-
const mockCallAI = function (userPrompt, options = {}) {
|
|
22
|
-
// Track usage
|
|
23
|
-
window.__MOCK_STATUS__.callCount++;
|
|
24
|
-
window.__MOCK_STATUS__.lastPrompt = userPrompt;
|
|
25
|
-
window.__MOCK_STATUS__.lastOptions = options;
|
|
26
|
-
/* eslint-disable-next-line no-console */
|
|
27
|
-
console.log(`🔍 MOCK CALL #${window.__MOCK_STATUS__.callCount}: callAI invoked with:`, typeof userPrompt === 'string'
|
|
28
|
-
? userPrompt.substring(0, 100) + '...'
|
|
29
|
-
: '[non-string-prompt]');
|
|
30
|
-
// Check if this is an error test case
|
|
31
|
-
if (typeof userPrompt === 'string' &&
|
|
32
|
-
(userPrompt.includes('error') || userPrompt.includes('fail'))) {
|
|
33
|
-
/* eslint-disable-next-line no-console */
|
|
34
|
-
console.log('🚨 MOCK: Simulating error response');
|
|
35
|
-
return Promise.reject(new Error('Simulated error from mock callAI'));
|
|
36
|
-
}
|
|
37
|
-
// Extract the actual request from the longer prompt
|
|
38
|
-
let extractedPrompt = 'Default prompt';
|
|
39
|
-
if (typeof userPrompt === 'string') {
|
|
40
|
-
const promptMatch = userPrompt.match(/Transform the HTML content based on this request:\s*([^\n]+)/);
|
|
41
|
-
if (promptMatch && promptMatch[1]) {
|
|
42
|
-
extractedPrompt = promptMatch[1].trim();
|
|
43
|
-
}
|
|
44
|
-
else if (userPrompt.includes('Alternative configuration test')) {
|
|
45
|
-
extractedPrompt = 'Alternative configuration test';
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Create response HTML based on the prompt content
|
|
49
|
-
let htmlContent;
|
|
50
|
-
let explanationText;
|
|
51
|
-
if (extractedPrompt.includes('Alternative configuration')) {
|
|
52
|
-
htmlContent = `<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
53
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
54
|
-
<br><small>(Alternative config mock response)</small>
|
|
55
|
-
</div>`;
|
|
56
|
-
explanationText = 'Mock explanation for alternative configuration';
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
htmlContent = `<div style="background-color: #eefbff; padding: 10px; border: 2px solid #0099cc; border-radius: 5px;">
|
|
60
|
-
<strong>🎭 Vibes received prompt:</strong> "${extractedPrompt}"
|
|
61
|
-
<br><small>(This is a mock response from browser test)</small>
|
|
62
|
-
</div>`;
|
|
63
|
-
explanationText = 'This is a mock explanation from the browser test';
|
|
64
|
-
}
|
|
65
|
-
// Create the structured response object that matches the schema in useVibes
|
|
66
|
-
const responseObj = {
|
|
67
|
-
html: htmlContent,
|
|
68
|
-
explanation: explanationText,
|
|
69
|
-
};
|
|
70
|
-
// Store for debugging
|
|
71
|
-
window.__MOCK_STATUS__.lastResponse = responseObj;
|
|
72
|
-
/* eslint-disable-next-line no-console */
|
|
73
|
-
console.log('✅ MOCK: Created JSON response:', JSON.stringify(responseObj).substring(0, 100) + '...');
|
|
74
|
-
// Return a properly structured response that matches what useVibes expects
|
|
75
|
-
return Promise.resolve(JSON.stringify(responseObj));
|
|
76
|
-
};
|
|
77
|
-
// Create a mock module object that matches the structure of the real call-ai module
|
|
78
|
-
const mockModule = {
|
|
79
|
-
callAI: mockCallAI,
|
|
80
|
-
__isMock: true,
|
|
81
|
-
};
|
|
82
|
-
// Attempt multiple interception strategies for maximum browser compatibility
|
|
83
|
-
// Strategy 1: Intercept dynamic imports
|
|
84
|
-
// This works with newer module bundlers like Vite, Webpack, etc.
|
|
85
|
-
const originalImport = window.import;
|
|
86
|
-
window.import = function (specifier) {
|
|
87
|
-
if (specifier === 'call-ai') {
|
|
88
|
-
/* eslint-disable-next-line no-console */
|
|
89
|
-
console.log('🎯 MOCK: Import intercepted for call-ai module');
|
|
90
|
-
window.__MOCK_STATUS__.moduleIntercepted = true;
|
|
91
|
-
return Promise.resolve(mockModule);
|
|
92
|
-
}
|
|
93
|
-
return originalImport.apply(this, arguments);
|
|
94
|
-
};
|
|
95
|
-
// Strategy 2: Define the module globally for ESM imports to find
|
|
96
|
-
// Helps with static imports which can't be intercepted directly
|
|
97
|
-
window.mockCallAI = mockCallAI;
|
|
98
|
-
// Also set window.callAI for direct access tests
|
|
99
|
-
window.callAI = mockCallAI;
|
|
100
|
-
/* eslint-disable-next-line no-console */
|
|
101
|
-
console.log('✅ MOCK SETUP: Module interception complete - callAI has been mocked');
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
console.error('❌ MOCK SETUP ERROR:', error);
|
|
105
|
-
window.__MOCK_STATUS__.errors.push(error.message);
|
|
106
|
-
}
|
|
107
|
-
// Flag to indicate mocks are initialized
|
|
108
|
-
window.mockInitialized = true;
|
|
109
|
-
// eslint-disable-next-line no-console
|
|
110
|
-
console.log('-----------------------------------------------------------');
|
|
111
|
-
// eslint-disable-next-line no-console
|
|
112
|
-
console.log('🔧 MOCK SETUP: Setting up call-ai mocks for browser tests...');
|
|
113
|
-
// eslint-disable-next-line no-console
|
|
114
|
-
console.log('-----------------------------------------------------------');
|
|
115
|
-
// Create a global debug flag to track what's happening with our mocks
|
|
116
|
-
window.MOCK_DEBUG = {
|
|
117
|
-
mockCallsCount: 0,
|
|
118
|
-
lastPrompt: null,
|
|
119
|
-
lastResponse: null,
|
|
120
|
-
};
|
|
121
|
-
// Mock the callAI function directly to ensure tests work correctly
|
|
122
|
-
// This is the most reliable way to mock the call-ai module
|
|
123
|
-
window.callAI = function mockCallAI(userPrompt, options = {}) {
|
|
124
|
-
window.MOCK_DEBUG.mockCallsCount++;
|
|
125
|
-
// eslint-disable-next-line no-console
|
|
126
|
-
console.log('🔄 MOCK INTERCEPTED: callAI invoked - call #', window.MOCK_DEBUG.mockCallsCount);
|
|
127
|
-
// eslint-disable-next-line no-console
|
|
128
|
-
console.log('📝 MOCK PROMPT:', typeof userPrompt === 'string' ? userPrompt.substring(0, 100) + '...' : 'Non-string prompt');
|
|
129
|
-
// eslint-disable-next-line no-console
|
|
130
|
-
console.log('⚙️ MOCK OPTIONS:', JSON.stringify(options));
|
|
131
|
-
// Store the prompt for debugging
|
|
132
|
-
window.MOCK_DEBUG.lastPrompt = userPrompt;
|
|
133
|
-
window.MOCK_DEBUG.lastOptions = options;
|
|
134
|
-
// Extract the actual request from the longer prompt - more robust regex handling
|
|
135
|
-
let extractedPrompt = 'Default prompt';
|
|
136
|
-
if (typeof userPrompt === 'string') {
|
|
137
|
-
const promptMatch = userPrompt.match(/Transform the HTML content based on this request:\s*([^\n]+)/);
|
|
138
|
-
if (promptMatch && promptMatch[1]) {
|
|
139
|
-
extractedPrompt = promptMatch[1].trim();
|
|
140
|
-
}
|
|
141
|
-
else if (userPrompt.includes('Alternative configuration test')) {
|
|
142
|
-
extractedPrompt = 'Alternative configuration test';
|
|
143
|
-
}
|
|
144
|
-
else if (userPrompt.includes('error') || userPrompt.includes('fail')) {
|
|
145
|
-
extractedPrompt = 'Error simulation test';
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
// Just use a substring as a fallback - don't let tests fail because of regex
|
|
149
|
-
extractedPrompt = userPrompt.length > 50 ? userPrompt.substring(0, 50) + '...' : userPrompt;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
// eslint-disable-next-line no-console
|
|
153
|
-
console.log('🔍 EXTRACTED PROMPT:', extractedPrompt);
|
|
154
|
-
// Check if this is an error test case
|
|
155
|
-
if (extractedPrompt.includes('error') || extractedPrompt.includes('fail')) {
|
|
156
|
-
// eslint-disable-next-line no-console
|
|
157
|
-
console.log('🚨 SIMULATING ERROR RESPONSE');
|
|
158
|
-
return Promise.reject(new Error('Simulated error from mock callAI'));
|
|
159
|
-
}
|
|
160
|
-
// Create response based on the prompt content
|
|
161
|
-
let htmlContent;
|
|
162
|
-
let explanationText;
|
|
163
|
-
if (extractedPrompt.includes('Alternative configuration')) {
|
|
164
|
-
// Custom response for alternative config test
|
|
165
|
-
htmlContent = `<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
166
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
167
|
-
<br><small>(Alternative config mock response)</small>
|
|
168
|
-
</div>`;
|
|
169
|
-
explanationText = 'Mock explanation for alternative configuration';
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
// Default response
|
|
173
|
-
htmlContent = `<div style="background-color: #eefbff; padding: 10px; border: 2px solid #0099cc; border-radius: 5px;">
|
|
174
|
-
<strong>🎭 Vibes received prompt:</strong> "${extractedPrompt}"
|
|
175
|
-
<br><small>(This is a mock response from browser test)</small>
|
|
176
|
-
</div>`;
|
|
177
|
-
explanationText = 'This is a mock explanation from the browser test';
|
|
178
|
-
}
|
|
179
|
-
// Create the response object in the exact format that useVibes expects
|
|
180
|
-
const responseObj = {
|
|
181
|
-
html: htmlContent,
|
|
182
|
-
explanation: explanationText,
|
|
183
|
-
};
|
|
184
|
-
// Store the response for debugging
|
|
185
|
-
window.MOCK_DEBUG.lastResponse = responseObj;
|
|
186
|
-
// eslint-disable-next-line no-console
|
|
187
|
-
console.log('✅ MOCK RESPONSE CREATED:', JSON.stringify(responseObj).substring(0, 100) + '...');
|
|
188
|
-
// useVibes expects a Promise that resolves to a string (JSON)
|
|
189
|
-
return Promise.resolve(JSON.stringify(responseObj));
|
|
190
|
-
};
|
|
191
|
-
// As a fallback, also mock fetch for any direct API calls
|
|
192
|
-
// Store the original fetch
|
|
193
|
-
window._originalFetch = window.fetch;
|
|
194
|
-
// Mock the fetch API for call-ai
|
|
195
|
-
window.fetch = async function mockedFetch(url, options) {
|
|
196
|
-
// Check if this is a call to the AI API
|
|
197
|
-
if (url && (url.includes('api.call-ai.com') || url.includes('api/v1/chat/completions'))) {
|
|
198
|
-
// eslint-disable-next-line no-console
|
|
199
|
-
console.log('Intercepted fetch call to:', url);
|
|
200
|
-
// Parse the request body to get the prompt
|
|
201
|
-
const requestBody = JSON.parse(options.body);
|
|
202
|
-
let promptText = '';
|
|
203
|
-
// Extract prompt from messages
|
|
204
|
-
if (requestBody.messages && requestBody.messages.length > 0) {
|
|
205
|
-
const lastMessage = requestBody.messages[requestBody.messages.length - 1];
|
|
206
|
-
promptText = lastMessage.content || '';
|
|
207
|
-
}
|
|
208
|
-
// Create a properly formatted mock response
|
|
209
|
-
const mockResponse = {
|
|
210
|
-
choices: [
|
|
211
|
-
{
|
|
212
|
-
message: {
|
|
213
|
-
role: 'assistant',
|
|
214
|
-
content: JSON.stringify({
|
|
215
|
-
html: `<div>🎭 Vibes received prompt: "${promptText}"</div>`,
|
|
216
|
-
explanation: 'This is a mock explanation from the browser test',
|
|
217
|
-
}),
|
|
218
|
-
},
|
|
219
|
-
index: 0,
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
id: 'mock-response-id',
|
|
223
|
-
model: 'gpt-3.5-turbo',
|
|
224
|
-
object: 'chat.completion',
|
|
225
|
-
};
|
|
226
|
-
// Return a Response object with the mock data
|
|
227
|
-
return new Response(JSON.stringify(mockResponse), {
|
|
228
|
-
status: 200,
|
|
229
|
-
headers: { 'Content-Type': 'application/json' },
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
// For any other fetch calls, use the original implementation
|
|
233
|
-
return window._originalFetch(url, options);
|
|
234
|
-
};
|
|
235
|
-
// eslint-disable-next-line no-console
|
|
236
|
-
console.log('-----------------------------------------------------------');
|
|
237
|
-
// eslint-disable-next-line no-console
|
|
238
|
-
console.log('✅ MOCK SETUP COMPLETE: All mocks for callAI and fetch API ready!');
|
|
239
|
-
// eslint-disable-next-line no-console
|
|
240
|
-
console.log('-----------------------------------------------------------');
|
|
241
|
-
})();
|
|
242
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/tests/vibe.test.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
|
-
import { useVibes } from '../src/index.js';
|
|
3
|
-
// Mock the call-ai module for testing
|
|
4
|
-
vi.mock('call-ai', () => {
|
|
5
|
-
return {
|
|
6
|
-
callAI: vi.fn().mockImplementation((prompt, options) => {
|
|
7
|
-
if (options?.stream === false) {
|
|
8
|
-
// Extract prompt content for the mock response
|
|
9
|
-
let promptText = 'Test prompt';
|
|
10
|
-
if (typeof prompt === 'string' && prompt.includes('request:')) {
|
|
11
|
-
promptText = prompt.split('request:')[1].split('\n')[0].trim();
|
|
12
|
-
}
|
|
13
|
-
// Create a properly formatted mock response that matches the schema
|
|
14
|
-
const mockResponse = JSON.stringify({
|
|
15
|
-
html: `<div>🎭 Vibes received prompt: "${promptText}"</div>`,
|
|
16
|
-
explanation: 'This is a mock explanation from the test',
|
|
17
|
-
});
|
|
18
|
-
return Promise.resolve(mockResponse);
|
|
19
|
-
}
|
|
20
|
-
// For any other case
|
|
21
|
-
return 'Direct response';
|
|
22
|
-
}),
|
|
23
|
-
};
|
|
24
|
-
});
|
|
25
|
-
// Setup test DOM elements before each test
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
// Reset the body content
|
|
28
|
-
document.body.innerHTML = '';
|
|
29
|
-
// Create test elements
|
|
30
|
-
const target = document.createElement('div');
|
|
31
|
-
target.id = 'target';
|
|
32
|
-
document.body.appendChild(target);
|
|
33
|
-
const targetAlt = document.createElement('div');
|
|
34
|
-
targetAlt.id = 'target-alt';
|
|
35
|
-
document.body.appendChild(targetAlt);
|
|
36
|
-
});
|
|
37
|
-
describe('useVibes function', () => {
|
|
38
|
-
it('should accept a string selector and apply changes to the target element', async () => {
|
|
39
|
-
const result = await useVibes('#target', { prompt: 'Test prompt' });
|
|
40
|
-
expect(result.container).toBeDefined();
|
|
41
|
-
expect(result.container.innerHTML).toContain('Vibes received prompt: "Test prompt"');
|
|
42
|
-
});
|
|
43
|
-
it('should accept an HTMLElement directly', async () => {
|
|
44
|
-
const targetElement = document.getElementById('target');
|
|
45
|
-
if (!targetElement)
|
|
46
|
-
throw new Error('Test setup failed: target element not found');
|
|
47
|
-
const result = await useVibes(targetElement, { prompt: 'Direct element test' });
|
|
48
|
-
expect(result.container).toBe(targetElement);
|
|
49
|
-
expect(result.container.innerHTML).toContain('Vibes received prompt: "Direct element test"');
|
|
50
|
-
});
|
|
51
|
-
it('should reject with an error when target element not found', async () => {
|
|
52
|
-
await expect(useVibes('#non-existent', { prompt: 'Test' })).rejects.toThrow('Target element not found: #non-existent');
|
|
53
|
-
});
|
|
54
|
-
it('should return an object with the expected interface properties', async () => {
|
|
55
|
-
const result = await useVibes('#target', { prompt: 'Interface test' });
|
|
56
|
-
expect(result).toHaveProperty('container');
|
|
57
|
-
expect(result).toHaveProperty('database');
|
|
58
|
-
expect(result.database).toBeUndefined(); // Currently undefined in the implementation
|
|
59
|
-
});
|
|
60
|
-
});
|