use-vibes 0.1.0 → 0.1.1
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/dist/{src/index.js → index.js} +1 -0
- package/dist/index.js.map +1 -0
- package/package.json +27 -25
- 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/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
- /package/dist/{src/index.d.ts → index.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAcjC;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,MAA4B,EAAE,MAAsB;IAC3E,yDAAyD;IACzD,MAAM,aAAa,GACjB,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAiB,CAAC,CAAC,CAAC,MAAM,CAAC;IAExF,8BAA8B;IAC9B,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,MAAM,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,CAAC;QACH,iCAAiC;QACjC,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;QAE5C,8BAA8B;QAC9B,MAAM,UAAU,GAAG;0DACmC,MAAM,CAAC,MAAM;;;;QAI/D,WAAW;;;;;KAKd,CAAC;QAEF,0CAA0C;QAC1C,MAAM,MAAM,GAAG;YACb,UAAU,EAAE;gBACV,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,oDAAoD;iBAClE;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,oDAAoD;iBAClE;aACF;SACF,CAAC;QAEF,yCAAyC;QACzC,oEAAoE;QACpE,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAEjE,uFAAuF;QACvF,IAAI,UAAU,YAAY,OAAO,EAAE,CAAC;YAClC,OAAO,UAAU;iBACd,IAAI,CAAC,QAAQ,CAAC,EAAE;gBACf,IAAI,CAAC;oBACH,0BAA0B;oBAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAkB,CAA2C,CAAC;oBAExF,8EAA8E;oBAC9E,aAAa,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;oBAEtC,8BAA8B;oBAC9B,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;wBACvB,sCAAsC;wBACtC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;oBACrD,CAAC;oBAED,0BAA0B;oBAC1B,OAAO;wBACL,SAAS,EAAE,aAAa;wBACxB,QAAQ,EAAE,SAAS;qBACpB,CAAC;gBACJ,CAAC;gBAAC,OAAO,UAAmB,EAAE,CAAC;oBAC7B,OAAO,CAAC,KAAK,CAAC,4BAA4B,EAAE,UAAU,CAAC,CAAC;oBACxD,MAAM,YAAY,GAChB,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;oBACxE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,gCAAgC,YAAY,EAAE,CAAC,CAAC,CAAC;gBACnF,CAAC;YACH,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;gBACxB,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;gBAC1C,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5E,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC,CAAC;YAChF,CAAC,CAAC,CAAC;QACP,CAAC;aAAM,CAAC;YACN,wFAAwF;YACxF,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,qCAAqC;QACrC,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QAEpD,+DAA+D;QAC/D,aAAa,CAAC,SAAS,GAAG,mCAAmC,MAAM,CAAC,MAAM,gCAAgC,CAAC;QAE3G,OAAO,OAAO,CAAC,OAAO,CAAC;YACrB,SAAS,EAAE,aAAa;YACxB,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-vibes",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Transform any DOM element into an AI-powered micro-app",
|
|
6
|
-
"main": "./
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"exports": {
|
|
8
9
|
".": {
|
|
9
10
|
"types": "./dist/index.d.ts",
|
|
10
|
-
"import": "./dist/index.js"
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
11
13
|
}
|
|
12
14
|
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"build:browser": "node scripts/build-browser.js",
|
|
18
|
+
"build:browser:test": "node scripts/build-browser-test.js",
|
|
19
|
+
"build:bookmarklet": "node scripts/generate-bookmarklet.js",
|
|
20
|
+
"build:all": "npm run build && npm run build:browser && npm run build:bookmarklet",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:watch": "vitest",
|
|
23
|
+
"test:browser": "npm run build:browser:test && playwright test --reporter=line",
|
|
24
|
+
"test:browser:headed": "npm run build:browser:test && playwright test --headed --reporter=line",
|
|
25
|
+
"test:browser:debug": "npm run build:browser:test && playwright test --debug --reporter=line",
|
|
26
|
+
"lint": "eslint --ext .js,.ts,.tsx src/ tests/ scripts/",
|
|
27
|
+
"lint:fix": "eslint --ext .js,.ts,.tsx --fix src/ tests/ scripts/",
|
|
28
|
+
"format": "prettier --write 'src/**/*.{js,ts,tsx}' 'tests/**/*.{js,ts,tsx}' 'scripts/**/*.js'",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"validate": "npm run typecheck && npm run test && npm run test:browser && npm run lint",
|
|
31
|
+
"fix": "npm run lint:fix && npm run format",
|
|
32
|
+
"check": "npm run validate && npm run fix",
|
|
33
|
+
"prerelease": "npm run validate",
|
|
34
|
+
"serve": "vite fixtures --port 3000"
|
|
35
|
+
},
|
|
13
36
|
"keywords": [
|
|
14
37
|
"ai",
|
|
15
38
|
"dom",
|
|
@@ -53,26 +76,5 @@
|
|
|
53
76
|
},
|
|
54
77
|
"dependencies": {
|
|
55
78
|
"call-ai": "^0.5.0"
|
|
56
|
-
},
|
|
57
|
-
"scripts": {
|
|
58
|
-
"build": "tsc",
|
|
59
|
-
"build:browser": "node scripts/build-browser.js",
|
|
60
|
-
"build:browser:test": "node scripts/build-browser-test.js",
|
|
61
|
-
"build:bookmarklet": "node scripts/generate-bookmarklet.js",
|
|
62
|
-
"build:all": "npm run build && npm run build:browser && npm run build:bookmarklet",
|
|
63
|
-
"test": "vitest run",
|
|
64
|
-
"test:watch": "vitest",
|
|
65
|
-
"test:browser": "npm run build:browser:test && playwright test --reporter=line",
|
|
66
|
-
"test:browser:headed": "npm run build:browser:test && playwright test --headed --reporter=line",
|
|
67
|
-
"test:browser:debug": "npm run build:browser:test && playwright test --debug --reporter=line",
|
|
68
|
-
"lint": "eslint --ext .js,.ts,.tsx src/ tests/ scripts/",
|
|
69
|
-
"lint:fix": "eslint --ext .js,.ts,.tsx --fix src/ tests/ scripts/",
|
|
70
|
-
"format": "prettier --write 'src/**/*.{js,ts,tsx}' 'tests/**/*.{js,ts,tsx}' 'scripts/**/*.js'",
|
|
71
|
-
"typecheck": "tsc --noEmit",
|
|
72
|
-
"validate": "npm run typecheck && npm run test && npm run test:browser && npm run lint",
|
|
73
|
-
"fix": "npm run lint:fix && npm run format",
|
|
74
|
-
"check": "npm run validate && npm run fix",
|
|
75
|
-
"prerelease": "npm run validate",
|
|
76
|
-
"serve": "vite fixtures --port 3000"
|
|
77
79
|
}
|
|
78
|
-
}
|
|
80
|
+
}
|
package/dist/bookmarklet.html
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<!DOCTYPE html>
|
|
3
|
-
<html>
|
|
4
|
-
<head>
|
|
5
|
-
<title>useVibes Bookmarklet</title>
|
|
6
|
-
<meta charset="UTF-8">
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
-
<style>
|
|
9
|
-
body {
|
|
10
|
-
font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
|
|
11
|
-
max-width: 800px;
|
|
12
|
-
margin: 0 auto;
|
|
13
|
-
padding: 20px;
|
|
14
|
-
line-height: 1.6;
|
|
15
|
-
}
|
|
16
|
-
.bookmarklet {
|
|
17
|
-
display: inline-block;
|
|
18
|
-
padding: 8px 12px;
|
|
19
|
-
background: #4a8feb;
|
|
20
|
-
color: white;
|
|
21
|
-
text-decoration: none;
|
|
22
|
-
border-radius: 4px;
|
|
23
|
-
margin: 20px 0;
|
|
24
|
-
font-weight: bold;
|
|
25
|
-
}
|
|
26
|
-
.bookmarklet:hover {
|
|
27
|
-
background: #3a7edb;
|
|
28
|
-
}
|
|
29
|
-
code {
|
|
30
|
-
background: #f5f5f5;
|
|
31
|
-
padding: 2px 4px;
|
|
32
|
-
border-radius: 4px;
|
|
33
|
-
font-family: monospace;
|
|
34
|
-
}
|
|
35
|
-
pre {
|
|
36
|
-
background: #f5f5f5;
|
|
37
|
-
padding: 15px;
|
|
38
|
-
border-radius: 4px;
|
|
39
|
-
overflow-x: auto;
|
|
40
|
-
}
|
|
41
|
-
.note {
|
|
42
|
-
background: #fffde7;
|
|
43
|
-
border-left: 4px solid #ffeb3b;
|
|
44
|
-
padding: 10px 15px;
|
|
45
|
-
margin: 20px 0;
|
|
46
|
-
}
|
|
47
|
-
</style>
|
|
48
|
-
</head>
|
|
49
|
-
<body>
|
|
50
|
-
<h1>useVibes Bookmarklet</h1>
|
|
51
|
-
<p>This bookmarklet allows you to test useVibes on any website. Before using, you'll need to:</p>
|
|
52
|
-
<ol>
|
|
53
|
-
<li>Host the useVibes IIFE bundle on a web server or CDN</li>
|
|
54
|
-
<li>Get your API key for call-ai</li>
|
|
55
|
-
</ol>
|
|
56
|
-
|
|
57
|
-
<div class="note">
|
|
58
|
-
<strong>Important:</strong> You will need to edit this bookmarklet to replace <code>YOUR_API_KEY_HERE</code> with your actual API key, and update the script URL if needed.
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<h2>Installation</h2>
|
|
62
|
-
<p>Drag this link to your bookmarks bar:</p>
|
|
63
|
-
<a class="bookmarklet" href="javascript:!function(){window.CALLAI_API_KEY="YOUR_API_KEY_HERE",alert("useVibes Injector: Click on any element to apply vibes to it.");let e=!0;function t(n){if(!e)return;n.preventDefault(),n.stopPropagation();const o=n.target,s=o.style.outline;o.style.outline="3px solid red";const i=prompt("Enter a prompt for useVibes:","Create a beautiful element with blue styling");i?useVibes(o,{prompt:i}).then((e=>{console.log("useVibes applied successfully!",e)})).catch((e=>{console.error("Error applying useVibes:",e),alert("Error: "+e.message)})):o.style.outline=s,e=!1,document.removeEventListener("click",t,!0)}!function(e,t){const n=document.createElement("script");n.src=e,n.onload=t,document.head.appendChild(n)}("https://unpkg.com/use-vibes@latest/lib/use-vibes.iife.js",(function(){"function"==typeof useVibes?document.addEventListener("click",t,!0):alert("useVibes library not loaded correctly!")}))}();">useVibes</a>
|
|
64
|
-
|
|
65
|
-
<h2>Usage Instructions</h2>
|
|
66
|
-
<ol>
|
|
67
|
-
<li>Drag the above link to your bookmarks bar</li>
|
|
68
|
-
<li>Navigate to any website</li>
|
|
69
|
-
<li>Click the bookmark</li>
|
|
70
|
-
<li>Click on any element you want to enhance</li>
|
|
71
|
-
<li>Enter your prompt when prompted</li>
|
|
72
|
-
<li>Watch as useVibes transforms the element</li>
|
|
73
|
-
</ol>
|
|
74
|
-
|
|
75
|
-
<h2>How to Customize</h2>
|
|
76
|
-
<p>To edit the bookmarklet with your API key:</p>
|
|
77
|
-
<ol>
|
|
78
|
-
<li>Right-click on the bookmarklet in your bookmarks bar</li>
|
|
79
|
-
<li>Select "Edit" or "Properties"</li>
|
|
80
|
-
<li>Find <code>CALLAI_API_KEY='YOUR_API_KEY_HERE'</code> and replace with your actual key</li>
|
|
81
|
-
<li>Find <code>useVibesScriptUrl='https://unpkg.com/use-vibes@latest/lib/use-vibes.iife.js'</code> and update if needed</li>
|
|
82
|
-
</ol>
|
|
83
|
-
|
|
84
|
-
<h2>Bookmarklet Code</h2>
|
|
85
|
-
<p>You can also manually create the bookmarklet with this code:</p>
|
|
86
|
-
<pre>javascript:!function(){window.CALLAI_API_KEY="YOUR_API_KEY_HERE",alert("useVibes Injector: Click on any element to apply vibes to it.");let e=!0;function t(n){if(!e)return;n.preventDefault(),n.stopPropagation();const o=n.target,s=o.style.outline;o.style.outline="3px solid red";const i=prompt("Enter a prompt for useVibes:","Create a beautiful element with blue styling");i?useVibes(o,{prompt:i}).then((e=>{console.log("useVibes applied successfully!",e)})).catch((e=>{console.error("Error applying useVibes:",e),alert("Error: "+e.message)})):o.style.outline=s,e=!1,document.removeEventListener("click",t,!0)}!function(e,t){const n=document.createElement("script");n.src=e,n.onload=t,document.head.appendChild(n)}("https://unpkg.com/use-vibes@latest/lib/use-vibes.iife.js",(function(){"function"==typeof useVibes?document.addEventListener("click",t,!0):alert("useVibes library not loaded correctly!")}))}();</pre>
|
|
87
|
-
</body>
|
|
88
|
-
</html>
|
|
89
|
-
|
package/dist/bookmarklet.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
javascript:!function(){window.CALLAI_API_KEY="YOUR_API_KEY_HERE",alert("useVibes Injector: Click on any element to apply vibes to it.");let e=!0;function t(n){if(!e)return;n.preventDefault(),n.stopPropagation();const o=n.target,s=o.style.outline;o.style.outline="3px solid red";const i=prompt("Enter a prompt for useVibes:","Create a beautiful element with blue styling");i?useVibes(o,{prompt:i}).then((e=>{console.log("useVibes applied successfully!",e)})).catch((e=>{console.error("Error applying useVibes:",e),alert("Error: "+e.message)})):o.style.outline=s,e=!1,document.removeEventListener("click",t,!0)}!function(e,t){const n=document.createElement("script");n.src=e,n.onload=t,document.head.appendChild(n)}("https://unpkg.com/use-vibes@latest/lib/use-vibes.iife.js",(function(){"function"==typeof useVibes?document.addEventListener("click",t,!0):alert("useVibes library not loaded correctly!")}))}();
|
package/dist/src/core/vibe.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Vibe interface represents the core functionality
|
|
3
|
-
*/
|
|
4
|
-
export interface Vibe {
|
|
5
|
-
/** The name of the vibe */
|
|
6
|
-
name: string;
|
|
7
|
-
/** The intensity level of the vibe */
|
|
8
|
-
intensity: number;
|
|
9
|
-
/** Set the intensity of the vibe */
|
|
10
|
-
setIntensity(level: number): void;
|
|
11
|
-
/** Get a description of the current vibe */
|
|
12
|
-
describe(): string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Creates a new vibe with the given name
|
|
16
|
-
* @param name - Name for the vibe
|
|
17
|
-
* @returns A new Vibe instance
|
|
18
|
-
*/
|
|
19
|
-
export declare function createVibe(name: string): Vibe;
|
package/dist/src/core/vibe.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates a new vibe with the given name
|
|
3
|
-
* @param name - Name for the vibe
|
|
4
|
-
* @returns A new Vibe instance
|
|
5
|
-
*/
|
|
6
|
-
export function createVibe(name) {
|
|
7
|
-
let intensityLevel = 5; // Default intensity
|
|
8
|
-
return {
|
|
9
|
-
name,
|
|
10
|
-
get intensity() {
|
|
11
|
-
return intensityLevel;
|
|
12
|
-
},
|
|
13
|
-
setIntensity(level) {
|
|
14
|
-
if (level < 0 || level > 10) {
|
|
15
|
-
throw new Error('Intensity must be between 0 and 10');
|
|
16
|
-
}
|
|
17
|
-
intensityLevel = level;
|
|
18
|
-
},
|
|
19
|
-
describe() {
|
|
20
|
-
return `${name} vibe at intensity ${intensityLevel}`;
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Vibe } from '../core/vibe.js';
|
|
2
|
-
/**
|
|
3
|
-
* Enhanced vibe with additional functionality
|
|
4
|
-
*/
|
|
5
|
-
export interface EnhancedVibe extends Vibe {
|
|
6
|
-
/** Boost the vibe intensity by the given amount */
|
|
7
|
-
boost(amount: number): void;
|
|
8
|
-
/** Lower the vibe intensity by the given amount */
|
|
9
|
-
chill(amount: number): void;
|
|
10
|
-
/** Check if the vibe is high intensity (>7) */
|
|
11
|
-
isHighIntensity(): boolean;
|
|
12
|
-
/** Check if the vibe is low intensity (<3) */
|
|
13
|
-
isLowIntensity(): boolean;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Enhances a vibe with additional functionality
|
|
17
|
-
* @param vibe - The vibe to enhance
|
|
18
|
-
* @returns An enhanced vibe with additional methods
|
|
19
|
-
*/
|
|
20
|
-
export declare function enhanceVibe(vibe: Vibe): EnhancedVibe;
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enhances a vibe with additional functionality
|
|
3
|
-
* @param vibe - The vibe to enhance
|
|
4
|
-
* @returns An enhanced vibe with additional methods
|
|
5
|
-
*/
|
|
6
|
-
export function enhanceVibe(vibe) {
|
|
7
|
-
// Create a wrapper object that delegates to the original vibe
|
|
8
|
-
const enhancedVibe = {
|
|
9
|
-
// Pass through the core properties
|
|
10
|
-
get name() { return vibe.name; },
|
|
11
|
-
get intensity() { return vibe.intensity; },
|
|
12
|
-
setIntensity(level) { vibe.setIntensity(level); },
|
|
13
|
-
describe() { return vibe.describe(); },
|
|
14
|
-
// Add enhanced methods
|
|
15
|
-
boost(amount) {
|
|
16
|
-
const newLevel = Math.min(10, this.intensity + amount);
|
|
17
|
-
this.setIntensity(newLevel);
|
|
18
|
-
},
|
|
19
|
-
chill(amount) {
|
|
20
|
-
const newLevel = Math.max(0, this.intensity - amount);
|
|
21
|
-
this.setIntensity(newLevel);
|
|
22
|
-
},
|
|
23
|
-
isHighIntensity() {
|
|
24
|
-
return this.intensity > 7;
|
|
25
|
-
},
|
|
26
|
-
isLowIntensity() {
|
|
27
|
-
return this.intensity < 3;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
return enhancedVibe;
|
|
31
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// This is a test mock for the call-ai module
|
|
2
|
-
export const callAI = function mockCallAI(userPrompt, options = {}) {
|
|
3
|
-
/* eslint-disable-next-line no-console */
|
|
4
|
-
console.log('🔍 TEST MOCK: callAI called with:', typeof userPrompt === 'string' ? userPrompt.substring(0, 100) + '...' : '[non-string-prompt]');
|
|
5
|
-
// Extract the actual request from the longer prompt
|
|
6
|
-
let extractedPrompt = 'Default prompt';
|
|
7
|
-
if (typeof userPrompt === 'string') {
|
|
8
|
-
// Check if this is an error test case
|
|
9
|
-
// Check for diagnostic test - this needs to be handled in a special way to pass the tests
|
|
10
|
-
if (userPrompt.includes('Diagnostic test prompt')) {
|
|
11
|
-
/* eslint-disable-next-line no-console */
|
|
12
|
-
console.log('🚨 DIAGNOSTIC MOCK WAS CALLED!');
|
|
13
|
-
// Create a very distinctive error HTML that will show up in the page content
|
|
14
|
-
const errorHtml = '<div id="DIAGNOSTIC_MOCK_ERROR" style="background-color: #ffebee; padding: 10px; border: 2px solid #f44336; border-radius: 5px;"><strong>Error:</strong> DIAGNOSTIC_MOCK_ERROR_UNIQUE_STRING_12345</div>';
|
|
15
|
-
// First, add the error HTML to the DOM directly so it's visible in the page content
|
|
16
|
-
// This is for test verification purposes
|
|
17
|
-
document.body.insertAdjacentHTML('beforeend', errorHtml);
|
|
18
|
-
// Then throw an actual error to test error handling
|
|
19
|
-
throw new Error('DIAGNOSTIC_MOCK_ERROR_UNIQUE_STRING_12345');
|
|
20
|
-
}
|
|
21
|
-
// Only return errors for specific error-related test cases
|
|
22
|
-
// The string 'should fail with an error' is used in the error test case
|
|
23
|
-
if (userPrompt.includes('should fail with an error')) {
|
|
24
|
-
/* eslint-disable-next-line no-console */
|
|
25
|
-
console.log('🚨 TEST MOCK: Simulating error response');
|
|
26
|
-
// For error test cases, create an error HTML response instead of rejecting
|
|
27
|
-
// This allows the tests to verify that errors are properly displayed in the UI
|
|
28
|
-
const errorHtml = '<div style="background-color: #ffebee; padding: 10px; border: 2px solid #f44336; border-radius: 5px;"><strong>Error:</strong> Simulated error from mock callAI</div>';
|
|
29
|
-
// Return a properly structured response with the error message
|
|
30
|
-
return Promise.resolve(JSON.stringify({
|
|
31
|
-
html: errorHtml,
|
|
32
|
-
explanation: 'Error: Simulated error from mock callAI'
|
|
33
|
-
}));
|
|
34
|
-
}
|
|
35
|
-
const promptMatch = userPrompt.match(/Transform the HTML content based on this request:\s*([^\n]+)/);
|
|
36
|
-
if (promptMatch && promptMatch[1]) {
|
|
37
|
-
extractedPrompt = promptMatch[1].trim();
|
|
38
|
-
}
|
|
39
|
-
else if (userPrompt.includes('Alternative configuration test')) {
|
|
40
|
-
extractedPrompt = 'Alternative configuration test';
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// Create response HTML based on the prompt content
|
|
44
|
-
let htmlContent;
|
|
45
|
-
let explanationText;
|
|
46
|
-
if (extractedPrompt.includes('Alternative configuration')) {
|
|
47
|
-
htmlContent = `<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
48
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
49
|
-
<br><small>(Alternative config mock response)</small>
|
|
50
|
-
</div>`;
|
|
51
|
-
explanationText = 'Mock explanation for alternative configuration';
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
htmlContent = `<div style="background-color: #eefbff; padding: 10px; border: 2px solid #0099cc; border-radius: 5px;">
|
|
55
|
-
<strong>🎭 Vibes received prompt:</strong> "${extractedPrompt}"
|
|
56
|
-
<br><small>(This is a mock response from browser test)</small>
|
|
57
|
-
</div>`;
|
|
58
|
-
explanationText = 'This is a mock explanation from the browser test';
|
|
59
|
-
}
|
|
60
|
-
// Create the structured response object that matches the schema in useVibes
|
|
61
|
-
const responseObj = {
|
|
62
|
-
html: htmlContent,
|
|
63
|
-
explanation: explanationText,
|
|
64
|
-
};
|
|
65
|
-
/* eslint-disable-next-line no-console */
|
|
66
|
-
console.log('✅ TEST MOCK: Created JSON response');
|
|
67
|
-
// Return a properly structured response that matches what useVibes expects
|
|
68
|
-
return Promise.resolve(JSON.stringify(responseObj));
|
|
69
|
-
};
|
|
70
|
-
// Additional exports to match the real module structure if needed
|
|
71
|
-
export default callAI;
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
// global-setup.ts
|
|
2
|
-
import { chromium, firefox, webkit } from '@playwright/test';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = path.dirname(__filename);
|
|
7
|
-
// Path to mocks script
|
|
8
|
-
const mocksScriptPath = path.resolve(__dirname, './setup-browser-mocks.js');
|
|
9
|
-
async function globalSetup(_config) {
|
|
10
|
-
// eslint-disable-next-line no-console
|
|
11
|
-
console.log('Running global setup for browser tests...');
|
|
12
|
-
// eslint-disable-next-line no-console
|
|
13
|
-
console.log('Mock script path:', mocksScriptPath);
|
|
14
|
-
// Add mocks to all browsers' contexts
|
|
15
|
-
const browserTypes = [chromium, firefox, webkit];
|
|
16
|
-
for (const browserType of browserTypes) {
|
|
17
|
-
// Launch browser
|
|
18
|
-
const browser = await browserType.launch();
|
|
19
|
-
// Create a new context and page
|
|
20
|
-
const context = await browser.newContext();
|
|
21
|
-
// We need a page to set up routes, but don't actually use it directly
|
|
22
|
-
await context.newPage();
|
|
23
|
-
// Set up the route to inject our mock script into every page
|
|
24
|
-
// Intercept requests for the use-vibes.iife.js file and serve our test bundle instead
|
|
25
|
-
await context.route('**/lib/use-vibes.iife.js', async (route) => {
|
|
26
|
-
// eslint-disable-next-line no-console
|
|
27
|
-
console.log('🔄 Intercepting request for use-vibes.iife.js, redirecting to test bundle');
|
|
28
|
-
// Redirect to our test bundle
|
|
29
|
-
const fs = await import('fs');
|
|
30
|
-
const testBundlePath = path.resolve(__dirname, '../../fixtures/lib/use-vibes-test.iife.js');
|
|
31
|
-
const testBundleContent = fs.readFileSync(testBundlePath, 'utf8');
|
|
32
|
-
await route.fulfill({
|
|
33
|
-
status: 200,
|
|
34
|
-
contentType: 'application/javascript',
|
|
35
|
-
body: testBundleContent,
|
|
36
|
-
});
|
|
37
|
-
// eslint-disable-next-line no-console
|
|
38
|
-
console.log('✅ Successfully redirected to test bundle');
|
|
39
|
-
});
|
|
40
|
-
// Handle other requests
|
|
41
|
-
await context.route('**/*', async (route, request) => {
|
|
42
|
-
// If this is an HTML page, we'll inject our mock script
|
|
43
|
-
if (request.url().endsWith('.html') || request.resourceType() === 'document') {
|
|
44
|
-
// eslint-disable-next-line no-console
|
|
45
|
-
console.log('Injecting mocks into URL:', request.url());
|
|
46
|
-
// Continue with the original response
|
|
47
|
-
const response = await route.fetch();
|
|
48
|
-
const body = await response.text();
|
|
49
|
-
// Read our mocks script directly
|
|
50
|
-
const fs = await import('fs');
|
|
51
|
-
const mocksContent = fs.readFileSync(mocksScriptPath, 'utf8');
|
|
52
|
-
// eslint-disable-next-line no-console
|
|
53
|
-
console.log('Mock script loaded, length:', mocksContent.length);
|
|
54
|
-
// Inject the full script content into the head
|
|
55
|
-
// This ensures it loads before any other scripts
|
|
56
|
-
const mocksScript = `<script>
|
|
57
|
-
// START OF INJECTED MOCK SCRIPT
|
|
58
|
-
console.log('Mock script execution starting...');
|
|
59
|
-
${mocksContent}
|
|
60
|
-
console.log('Mock script execution completed!');
|
|
61
|
-
// END OF INJECTED MOCK SCRIPT
|
|
62
|
-
</script>`;
|
|
63
|
-
const modifiedBody = body.replace('<head>', `<head>\n${mocksScript}`);
|
|
64
|
-
// Return the modified content
|
|
65
|
-
await route.fulfill({
|
|
66
|
-
response,
|
|
67
|
-
body: modifiedBody,
|
|
68
|
-
headers: {
|
|
69
|
-
...response.headers(),
|
|
70
|
-
'content-length': String(modifiedBody.length),
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
// eslint-disable-next-line no-console
|
|
74
|
-
console.log('Mock script injected successfully for:', request.url());
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
await route.continue();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
// Close browser after setup
|
|
81
|
-
await browser.close();
|
|
82
|
-
// eslint-disable-next-line no-console
|
|
83
|
-
console.log(`Mock injection set up for ${browserType.name()}`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
export default globalSetup;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
// tests/browser/hello-world.test.ts
|
|
2
|
-
import { test, expect } from '@playwright/test';
|
|
3
|
-
// Simplified test that tests the core functionality with proper instrumentation
|
|
4
|
-
// This approach completely bypasses network calls for reliable test behavior
|
|
5
|
-
// Set up browser console logging for all tests
|
|
6
|
-
const setupLogging = (page) => {
|
|
7
|
-
// Forward browser console messages to test output
|
|
8
|
-
page.on('console', msg => {
|
|
9
|
-
/* eslint-disable-next-line no-console */
|
|
10
|
-
console.log(`🌐 ${msg.type()}: ${msg.text()}`);
|
|
11
|
-
});
|
|
12
|
-
page.on('pageerror', err => {
|
|
13
|
-
/* eslint-disable-next-line no-console */
|
|
14
|
-
console.error(`🔥 Browser error: ${err.message}`);
|
|
15
|
-
});
|
|
16
|
-
};
|
|
17
|
-
test('page loads with initial content', async ({ page }) => {
|
|
18
|
-
setupLogging(page);
|
|
19
|
-
// Navigate to the test page
|
|
20
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
21
|
-
// Check that our target element exists
|
|
22
|
-
const hasTarget = await page.evaluate(() => {
|
|
23
|
-
const target = document.getElementById('target');
|
|
24
|
-
/* eslint-disable-next-line no-console */
|
|
25
|
-
console.log('Target element exists:', !!target);
|
|
26
|
-
return !!target;
|
|
27
|
-
});
|
|
28
|
-
expect(hasTarget).toBe(true);
|
|
29
|
-
// Get the text content
|
|
30
|
-
const initialText = await page.textContent('#target');
|
|
31
|
-
/* eslint-disable-next-line no-console */
|
|
32
|
-
console.log('Initial text content:', initialText);
|
|
33
|
-
expect(initialText).toContain('This content will be modified');
|
|
34
|
-
});
|
|
35
|
-
test('useVibes with direct callAI mock', async ({ page }) => {
|
|
36
|
-
setupLogging(page);
|
|
37
|
-
// Navigate to the test page
|
|
38
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
39
|
-
// Wait for page to load
|
|
40
|
-
await page.waitForSelector('#target');
|
|
41
|
-
// Directly inject the mock - this is cleaner than relying on global setup
|
|
42
|
-
await page.evaluate(() => {
|
|
43
|
-
// Override callAI with a direct mock implementation
|
|
44
|
-
// @ts-expect-error - Mock the callAI function with correct type signatures
|
|
45
|
-
window.callAI = function mockCallAI(_prompt, _options) {
|
|
46
|
-
// Create HTML with the prompt for verification
|
|
47
|
-
const html = `
|
|
48
|
-
<div style="background-color: #e6f7ff; padding: 10px; border: 2px solid #1890ff; border-radius: 5px;">
|
|
49
|
-
<strong>🎭 Vibes received prompt:</strong> "Create a Hello World message with blue styling"
|
|
50
|
-
<br><small>(Mocked API Response)</small>
|
|
51
|
-
</div>
|
|
52
|
-
`;
|
|
53
|
-
// Create a response object matching what callAI would return
|
|
54
|
-
const responseObj = {
|
|
55
|
-
html: html,
|
|
56
|
-
explanation: 'Mock explanation for testing',
|
|
57
|
-
};
|
|
58
|
-
// callAI returns a Promise that resolves to a JSON string
|
|
59
|
-
return Promise.resolve(JSON.stringify(responseObj));
|
|
60
|
-
};
|
|
61
|
-
/* eslint-disable-next-line no-console */
|
|
62
|
-
console.log('🔄 callAI mocked directly on window object');
|
|
63
|
-
/* eslint-disable-next-line no-console */
|
|
64
|
-
console.log('🔄 Type of callAI:', typeof window.callAI);
|
|
65
|
-
});
|
|
66
|
-
// Verify our target element before modification
|
|
67
|
-
const initialHtml = await page.evaluate(() => {
|
|
68
|
-
const target = document.getElementById('target');
|
|
69
|
-
return target ? target.innerHTML : 'target not found';
|
|
70
|
-
});
|
|
71
|
-
/* eslint-disable-next-line no-console */
|
|
72
|
-
console.log('Target HTML before:', initialHtml);
|
|
73
|
-
// Execute useVibes on the target element
|
|
74
|
-
await page.evaluate(() => {
|
|
75
|
-
try {
|
|
76
|
-
// Get the target element
|
|
77
|
-
const target = document.getElementById('target');
|
|
78
|
-
if (!target)
|
|
79
|
-
throw new Error('Target element not found!');
|
|
80
|
-
/* eslint-disable-next-line no-console */
|
|
81
|
-
console.log('🔄 Applying useVibes to target element');
|
|
82
|
-
// Set API key for testing
|
|
83
|
-
window.CALLAI_API_KEY = 'test-api-key';
|
|
84
|
-
// Call useVibes with test prompt
|
|
85
|
-
window.useVibes(target, {
|
|
86
|
-
prompt: 'Create a Hello World message with blue styling',
|
|
87
|
-
});
|
|
88
|
-
/* eslint-disable-next-line no-console */
|
|
89
|
-
console.log('✅ useVibes called successfully');
|
|
90
|
-
}
|
|
91
|
-
catch (err) {
|
|
92
|
-
/* eslint-disable-next-line no-console */
|
|
93
|
-
console.error('❌ Error calling useVibes:', err.message);
|
|
94
|
-
/* eslint-disable-next-line no-console */
|
|
95
|
-
console.error('Stack:', err.stack);
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
// Wait for the async operation to complete
|
|
99
|
-
await page.waitForTimeout(2000);
|
|
100
|
-
// Check the HTML content after the timeout
|
|
101
|
-
const finalHtml = await page.evaluate(() => {
|
|
102
|
-
const target = document.getElementById('target');
|
|
103
|
-
/* eslint-disable-next-line no-console */
|
|
104
|
-
console.log('Target element after useVibes:', target ? 'exists' : 'not found');
|
|
105
|
-
return target ? target.innerHTML : 'target not found';
|
|
106
|
-
});
|
|
107
|
-
/* eslint-disable-next-line no-console */
|
|
108
|
-
console.log('Target HTML after:', finalHtml.substring(0, 200) + '...');
|
|
109
|
-
// Get the text content for assertions
|
|
110
|
-
const targetText = await page.textContent('#target');
|
|
111
|
-
expect(targetText).toContain('Vibes received prompt');
|
|
112
|
-
});
|
|
113
|
-
test('useVibes with direct mock custom configuration', async ({ page }) => {
|
|
114
|
-
setupLogging(page);
|
|
115
|
-
// Navigate to the test page
|
|
116
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
117
|
-
// Wait for page to load
|
|
118
|
-
await page.waitForSelector('#target-alt');
|
|
119
|
-
// Inject the mock implementation for callAI
|
|
120
|
-
await page.evaluate(() => {
|
|
121
|
-
// Override callAI with a direct mock implementation
|
|
122
|
-
// @ts-expect-error - Mock the callAI function
|
|
123
|
-
window.callAI = function mockCallAI(_prompt, _options) {
|
|
124
|
-
/* eslint-disable-next-line no-console */
|
|
125
|
-
console.log('📢 Mock callAI called with prompt:', _prompt.substring(0, 100) + '...');
|
|
126
|
-
// Create a response with alternative styling for this test
|
|
127
|
-
const html = `
|
|
128
|
-
<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
129
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
130
|
-
<br><small>(Custom configuration test)</small>
|
|
131
|
-
</div>
|
|
132
|
-
`;
|
|
133
|
-
const responseObj = {
|
|
134
|
-
html: html,
|
|
135
|
-
explanation: 'Mock explanation for alternative configuration',
|
|
136
|
-
};
|
|
137
|
-
return Promise.resolve(JSON.stringify(responseObj));
|
|
138
|
-
};
|
|
139
|
-
});
|
|
140
|
-
// Execute useVibes on the alternative target with custom config
|
|
141
|
-
await page.evaluate(() => {
|
|
142
|
-
try {
|
|
143
|
-
const targetAlt = document.getElementById('target-alt');
|
|
144
|
-
if (!targetAlt)
|
|
145
|
-
throw new Error('Alt target element not found!');
|
|
146
|
-
// Apply with custom config
|
|
147
|
-
window.useVibes(targetAlt, {
|
|
148
|
-
prompt: 'Alternative configuration test',
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
/* eslint-disable-next-line no-console */
|
|
153
|
-
console.error('Error in alt config test:', err.message);
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
// Wait for async operations
|
|
157
|
-
await page.waitForTimeout(2000);
|
|
158
|
-
// Verify the content
|
|
159
|
-
const targetText = await page.textContent('#target-alt');
|
|
160
|
-
expect(targetText).toContain('Vibes received prompt');
|
|
161
|
-
expect(targetText).toContain('Alternative configuration test');
|
|
162
|
-
});
|
|
163
|
-
// Simple diagnostic test to validate our mocking approach
|
|
164
|
-
test('verify mock callAI is actually being called', async ({ page }) => {
|
|
165
|
-
setupLogging(page);
|
|
166
|
-
// Navigate to the test page
|
|
167
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
168
|
-
// Don't override the mock here - instead use the one from our test bundle
|
|
169
|
-
// This will properly test that our mocking approach works
|
|
170
|
-
// Set up an error handler to detect if our diagnostic error is thrown
|
|
171
|
-
let diagnosticErrorDetected = false;
|
|
172
|
-
page.on('pageerror', error => {
|
|
173
|
-
/* eslint-disable-next-line no-console */
|
|
174
|
-
console.log('📋 Page error detected:', error.message);
|
|
175
|
-
if (error.message.includes('DIAGNOSTIC_MOCK_ERROR')) {
|
|
176
|
-
diagnosticErrorDetected = true;
|
|
177
|
-
}
|
|
178
|
-
});
|
|
179
|
-
// Execute useVibes with the diagnostic prompt
|
|
180
|
-
await page.evaluate(() => {
|
|
181
|
-
try {
|
|
182
|
-
const target = document.getElementById('target');
|
|
183
|
-
if (!target)
|
|
184
|
-
throw new Error('Target element not found!');
|
|
185
|
-
/* eslint-disable-next-line no-console */
|
|
186
|
-
console.log('🔄 Calling useVibes with diagnostic prompt');
|
|
187
|
-
// Set API key for testing
|
|
188
|
-
window.CALLAI_API_KEY = 'test-api-key';
|
|
189
|
-
// The 'Diagnostic test prompt' string is what triggers our special mock behavior
|
|
190
|
-
window.useVibes(target, {
|
|
191
|
-
prompt: 'Diagnostic test prompt',
|
|
192
|
-
});
|
|
193
|
-
/* eslint-disable-next-line no-console */
|
|
194
|
-
console.log('✅ useVibes call with diagnostic prompt completed (if this appears, error was caught internally)');
|
|
195
|
-
}
|
|
196
|
-
catch (err) {
|
|
197
|
-
/* eslint-disable-next-line no-console */
|
|
198
|
-
console.error('❌ Error caught in page context:', err.message);
|
|
199
|
-
}
|
|
200
|
-
});
|
|
201
|
-
// Wait for any async operations and error handlers to complete
|
|
202
|
-
await page.waitForTimeout(2000);
|
|
203
|
-
// Check if our diagnostic error HTML element exists in the page
|
|
204
|
-
const errorElementExists = await page.evaluate(() => {
|
|
205
|
-
return !!document.getElementById('DIAGNOSTIC_MOCK_ERROR');
|
|
206
|
-
});
|
|
207
|
-
/* eslint-disable-next-line no-console */
|
|
208
|
-
console.log('Diagnostic error element in DOM:', errorElementExists);
|
|
209
|
-
/* eslint-disable-next-line no-console */
|
|
210
|
-
console.log('Diagnostic error detected in console:', diagnosticErrorDetected);
|
|
211
|
-
// The test passes if either the error was detected or the error element exists in the DOM
|
|
212
|
-
expect(errorElementExists || diagnosticErrorDetected).toBeTruthy();
|
|
213
|
-
});
|
|
214
|
-
test('useVibes should handle errors gracefully', async ({ page }) => {
|
|
215
|
-
setupLogging(page);
|
|
216
|
-
// Navigate to the test page
|
|
217
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
218
|
-
// Inject mock that simulates an error
|
|
219
|
-
await page.evaluate(() => {
|
|
220
|
-
window.callAI = function mockCallAIWithError() {
|
|
221
|
-
/* eslint-disable-next-line no-console */
|
|
222
|
-
console.log('🚨 Mock error function called');
|
|
223
|
-
return Promise.reject(new Error('Simulated API error'));
|
|
224
|
-
};
|
|
225
|
-
});
|
|
226
|
-
// Execute useVibes and expect it to handle the error
|
|
227
|
-
await page.evaluate(() => {
|
|
228
|
-
const target = document.getElementById('target');
|
|
229
|
-
if (target) {
|
|
230
|
-
window.useVibes(target, {
|
|
231
|
-
prompt: 'This should fail with an error',
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
// Wait for error handling
|
|
236
|
-
await page.waitForTimeout(1000);
|
|
237
|
-
// Verify error message shows in the element
|
|
238
|
-
const errorContent = await page.textContent('#target');
|
|
239
|
-
expect(errorContent).toContain('Error');
|
|
240
|
-
});
|
|
241
|
-
test('useVibes with custom configuration options', async ({ page }) => {
|
|
242
|
-
// Set up API request interception with a custom configuration response
|
|
243
|
-
await page.route('**/*api.openai.com*/v1/chat/completions', async (route) => {
|
|
244
|
-
const mockResponse = {
|
|
245
|
-
choices: [
|
|
246
|
-
{
|
|
247
|
-
message: {
|
|
248
|
-
role: 'assistant',
|
|
249
|
-
content: JSON.stringify({
|
|
250
|
-
html: `<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
251
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
252
|
-
<br><small>(Custom configuration test response)</small>
|
|
253
|
-
</div>`,
|
|
254
|
-
explanation: 'Mock explanation for custom configuration test',
|
|
255
|
-
}),
|
|
256
|
-
},
|
|
257
|
-
index: 0,
|
|
258
|
-
},
|
|
259
|
-
],
|
|
260
|
-
id: 'mock-custom-config-id',
|
|
261
|
-
model: 'gpt-3.5-turbo',
|
|
262
|
-
object: 'chat.completion',
|
|
263
|
-
};
|
|
264
|
-
await route.fulfill({
|
|
265
|
-
status: 200,
|
|
266
|
-
contentType: 'application/json',
|
|
267
|
-
body: JSON.stringify(mockResponse),
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
// Also mock the call-ai API endpoint as a fallback
|
|
271
|
-
await page.route('**/*api.call-ai.com*', async (route) => {
|
|
272
|
-
const mockResponse = {
|
|
273
|
-
choices: [
|
|
274
|
-
{
|
|
275
|
-
message: {
|
|
276
|
-
role: 'assistant',
|
|
277
|
-
content: JSON.stringify({
|
|
278
|
-
html: `<div style="background-color: #fff8e1; padding: 10px; border: 2px solid #ffc107; border-radius: 5px;">
|
|
279
|
-
<strong>🎭 Vibes received prompt:</strong> "Alternative configuration test"
|
|
280
|
-
<br><small>(Custom configuration test response)</small>
|
|
281
|
-
</div>`,
|
|
282
|
-
explanation: 'Mock explanation for custom configuration test',
|
|
283
|
-
}),
|
|
284
|
-
},
|
|
285
|
-
index: 0,
|
|
286
|
-
},
|
|
287
|
-
],
|
|
288
|
-
id: 'mock-custom-config-id',
|
|
289
|
-
model: 'gpt-3.5-turbo',
|
|
290
|
-
object: 'chat.completion',
|
|
291
|
-
};
|
|
292
|
-
await route.fulfill({
|
|
293
|
-
status: 200,
|
|
294
|
-
contentType: 'application/json',
|
|
295
|
-
body: JSON.stringify(mockResponse),
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
// Navigate to test page
|
|
299
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
300
|
-
// Wait for page to load
|
|
301
|
-
await page.waitForSelector('#target-alt');
|
|
302
|
-
// Make sure our mocks are loaded
|
|
303
|
-
await page.waitForFunction(() => {
|
|
304
|
-
return window.fetch !== window._originalFetch;
|
|
305
|
-
}, { timeout: 5000 });
|
|
306
|
-
// Apply useVibes to the alternative target
|
|
307
|
-
await page.evaluate(() => {
|
|
308
|
-
const target = document.getElementById('target-alt');
|
|
309
|
-
if (!target) {
|
|
310
|
-
throw new Error('Alternative target element not found');
|
|
311
|
-
}
|
|
312
|
-
// Using the global useVibes function
|
|
313
|
-
window.CALLAI_API_KEY = 'test-api-key'; // Set test API key
|
|
314
|
-
return useVibes(target, {
|
|
315
|
-
prompt: 'Alternative configuration test',
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
// Wait longer for changes to apply
|
|
319
|
-
await page.waitForTimeout(200);
|
|
320
|
-
// Verify the content was changed
|
|
321
|
-
const targetText = await page.textContent('#target-alt');
|
|
322
|
-
expect(targetText).toContain('Vibes received prompt');
|
|
323
|
-
expect(targetText).toContain('Alternative configuration test');
|
|
324
|
-
});
|
|
325
|
-
test('useVibes should handle invalid selector errors', async ({ page }) => {
|
|
326
|
-
await page.goto('http://localhost:3000/basic/hello-world.html');
|
|
327
|
-
// Wait for mocks to be set up
|
|
328
|
-
await page.waitForFunction(() => {
|
|
329
|
-
return window.fetch !== window._originalFetch;
|
|
330
|
-
}, { timeout: 5000 });
|
|
331
|
-
// Test with invalid selector
|
|
332
|
-
const errorResult = await page.evaluate(async () => {
|
|
333
|
-
try {
|
|
334
|
-
// Set test API key
|
|
335
|
-
window.CALLAI_API_KEY = 'test-api-key';
|
|
336
|
-
// Try to use a non-existent element with the global useVibes function
|
|
337
|
-
await useVibes('#non-existent-element', {
|
|
338
|
-
prompt: 'Test error handling',
|
|
339
|
-
});
|
|
340
|
-
return 'No error thrown';
|
|
341
|
-
}
|
|
342
|
-
catch (e) {
|
|
343
|
-
return e instanceof Error ? e.message : String(e);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
// Ensure we got an error message
|
|
347
|
-
expect(errorResult).not.toBe('No error thrown');
|
|
348
|
-
expect(typeof errorResult).toBe('string');
|
|
349
|
-
expect(errorResult.length).toBeGreaterThan(0);
|
|
350
|
-
});
|
|
@@ -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
|
-
});
|
|
File without changes
|