summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Nystrom <sam@samnystrom.dev>2024-03-16 22:54:54 -0400
committerSam Nystrom <sam@samnystrom.dev>2024-03-16 22:54:54 -0400
commit1d5f74bca29c6bb28bef6035aa09a1e35884b40a (patch)
tree910801e8f2bf940f77438642f7a20448385d822a
parent7c37715afd7d9572a7f1a79552a187ab2a3e4184 (diff)
test: begin writing testsHEADmain
-rw-r--r--assembly/index.ts45
-rw-r--r--bunfig.toml2
-rw-r--r--package.json2
-rw-r--r--src/components/NodeEditor.tsx67
-rw-r--r--src/index.tsx3
-rw-r--r--src/pages/Editor.tsx6
-rw-r--r--src/pages/SignUp.test.tsx34
-rw-r--r--src/pages/SignUp.tsx9
-rw-r--r--src/test-preload.ts9
9 files changed, 119 insertions, 58 deletions
diff --git a/assembly/index.ts b/assembly/index.ts
index e94b0a8..8218a08 100644
--- a/assembly/index.ts
+++ b/assembly/index.ts
@@ -320,11 +320,12 @@ export function unzip(x: StaticArray<f32>): StaticArray<f32> {
}
function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): void {
- if (n == 1) {
+ //trace('x,n,s,X:', 4, <f64>x.length, <f64>n, <f64>s, <f64>out.length);
+ /*if (n == 1) {
out[0] = x[0];
out[1] = x[1];
return;
- } else if (n == 2) {
+ } /*else if (n == 2) {*/
for (let k = 0; k < out.length - out.length % 2; k += 2) {
for (let n = 0; n < x.length - x.length % 2; n += 2) {
const y = -<f32>2 * Mathf.PI * <f32>k / <f32>x.length * <f32>n;
@@ -334,11 +335,11 @@ function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): vo
out[k+1] += x[n] * v + x[n+1] * u;
}
}
- return;
- }
- ditfft2(x.slice<StaticArray<f32>>(0, n), n/2, 2*s, out.slice<StaticArray<f32>>(0, n));
- ditfft2(x.slice<StaticArray<f32>>(s * 2), n/2, 2*s, out.slice<StaticArray<f32>>(n));
- const outptr = changetype<usize>(out);
+ /*return;
+ }*/
+ // ditfft2(x, n/2, 2*s, out.slice<StaticArray<f32>>(0, n));
+ // ditfft2(x.slice<StaticArray<f32>>(s * 2), n/2, 2*s, out.slice<StaticArray<f32>>(n));
+ /*const outptr = changetype<usize>(out);
const twiddle = vf32(-<f32>2 * Mathf.PI / <f32>n);
let vk = f32x4(0,1,2,3);
for (let k = 0; k < n/2 - n/2 % 2; k += 4) {
@@ -349,22 +350,30 @@ function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): vo
v128.store(outptr + k*2 * 4, v128.add<f32>(p, q));
v128.store(outptr + (k*2 + n/2) * 4, v128.sub<f32>(p, q));
vk = v128.add<f32>(vk, vf32(1));
- }
- for (let k = n/2 - n/2 % 2; k < n/2; k++) {
+ }*/
+ //for (let k = n/2 - n/2 % 2; k < n/2; k++) {
+ /*for (let k = 0; k < n/2; k++) {
+ trace('n,s,k', 3, <f64>n, <f64>s, <f64>k);
const pr = unchecked(out[k*2]);
const pi = unchecked(out[k*2+1]);
- const y = -<f32>2 * Mathf.PI * <f32>k / <f32>n;
- const qr = Mathf.cos(y) * out[k*2+n/2]
- const qi = Mathf.sin(y) * out[k*2+n/2+1];
+ const tw = -<f32>2 * Mathf.PI / <f32>n * <f32>k;
+ const u = Mathf.cos(tw);
+ const v = Mathf.sin(tw);
+ const x = out[(k+n/2)*2];
+ const y = out[(k+n/2)*2+1];
+ const qr = x * u - y * v;
+ const qi = x * v + y * u;
unchecked(out[k*2] = pr + qr);
unchecked(out[k*2+1] = pi + qi);
- unchecked(out[k*2+n/2] = pr - qr);
- unchecked(out[k*2+n/2+1] = pi - qi);
- }
+ unchecked(out[(k+n/2)*2] = pr - qr);
+ unchecked(out[(k+n/2)*2+1] = pi - qi);
+ }*/
}
export function fft(x: StaticArray<f32>): StaticArray<f32> {
- const out = new StaticArray<f32>(x.length);
- ditfft2(x, x.length/2, 1, out);
+ const len = x.length - x.length % 2;
+ const out = new StaticArray<f32>(len);
+ if (len == 0) return out;
+ ditfft2(x.slice<StaticArray<f32>>(0, len), len/2, 1, out);
return out;
-} \ No newline at end of file
+}
diff --git a/bunfig.toml b/bunfig.toml
new file mode 100644
index 0000000..445a41d
--- /dev/null
+++ b/bunfig.toml
@@ -0,0 +1,2 @@
+[test]
+preload = "./src/test-preload.ts"
diff --git a/package.json b/package.json
index 5f00d1c..4cd959f 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,8 @@
"preact-router": "^4.1.2"
},
"devDependencies": {
+ "@happy-dom/global-registrator": "^13.8.6",
+ "@testing-library/preact": "^3.2.3",
"assemblyscript": "^0.27.24",
"esbuild": "^0.20.1",
"typescript": "^5.3.3"
diff --git a/src/components/NodeEditor.tsx b/src/components/NodeEditor.tsx
index 758fb76..4cb7011 100644
--- a/src/components/NodeEditor.tsx
+++ b/src/components/NodeEditor.tsx
@@ -87,7 +87,7 @@ const NodeEditor = ({ project }: NodeEditorProps) => {
const filter = pb.filter('project.id = {:id}', { id: project.id });
const projectNodes = await pb.collection('nodes').getFullList({ filter });
const projectLinks = await pb.collection('links').getFullList({ filter });
- const instances = projectNodes.map(node => instantiateNode(node.id, node.x, node.y, node.name));
+ const instances = projectNodes.map(node => instantiateNode(node.id, node.x, node.y, nodeRegistry[node.type]));
nodes.value = nodes.value.concat(instances);
})();
}, []);
@@ -237,14 +237,13 @@ const NodeEditor = ({ project }: NodeEditorProps) => {
scale.value *= 1 + delta;
}), []);
- const addNode = useCallback(async (name: string, info: NodeInfo<any, any>) => {
- const node = await pb.collection('nodes').create({ x: 100, y: 100, type: name, project: projectId, collapsed: false });
- alert(JSON.stringify(node));
+ const addNode = useCallback(async (type: string, info: NodeInfo<any, any>) => {
+ const node = await pb.collection('nodes').create({ x: 100, y: 100, type, project: project.id, collapsed: false });
nodes.value = nodes.value.concat(instantiateNode(node.id, node.x, node.y, info));
}, []);
return (
- <div class="__NodeEditor">
+ <>
<Toolbar title={project.name}>
<ButtonMenu label="Add">
{Object.entries(nodeRegistry).map(([name, node]) => (
@@ -252,34 +251,36 @@ const NodeEditor = ({ project }: NodeEditorProps) => {
))}
</ButtonMenu>
</Toolbar>
- <svg width="100vw" height="100vh" ref={svgRef} onMouseDown={onBgMouseDown} onWheel={onBgWheel}>
- <pattern
- id="bg-grid-major"
- patternUnits="userSpaceOnUse"
- x={offsetX} y={offsetY}
- width={120 * scale.value} height={120 * scale.value}
- >
- <pattern id="bg-grid-minor" patternUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
- <circle cx="2" cy="2" r="1" fill="var(--surface)" />
- </pattern>
- <g transform={`scale(${scale})`}>
- <rect fill="url(#bg-grid-minor)" x="0" y="0" width="100%" height="100%" />
- <circle cx="2" cy="2" r="2" fill="var(--surface)" />
- </g>
- </pattern>
- <rect fill="url(#bg-grid-major)" x="0" y="0" width="100%" height="100%" />
- <g transform={`translate(${offsetX},${offsetY}) scale(${scale})`}>
- {allLinks.value.map(({fromX, fromY, toX, toY}) => (
- <Link fromX={fromX} fromY={fromY} toX={toX} toY={toY} />
- ))}
- <SocketHandlers.Provider value={socketHandlers}>
- {nodes.value.map(node => (
- <node.component id={node.id} x={node.x} y={node.y} inputs={node.inputs} />
- ))}
- </SocketHandlers.Provider>
- </g>
- </svg>
- </div>
+ <main>
+ <svg class="__NodeEditor" width="100vw" height="100vh" ref={svgRef} onMouseDown={onBgMouseDown} onWheel={onBgWheel}>
+ <pattern
+ id="bg-grid-major"
+ patternUnits="userSpaceOnUse"
+ x={offsetX} y={offsetY}
+ width={120 * scale.value} height={120 * scale.value}
+ >
+ <pattern id="bg-grid-minor" patternUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
+ <circle cx="2" cy="2" r="1" fill="color-mix(in srgb, var(--overlay) 25%, var(--surface))" />
+ </pattern>
+ <g transform={`scale(${scale})`}>
+ <rect fill="url(#bg-grid-minor)" x="0" y="0" width="100%" height="100%" />
+ <circle cx="2" cy="2" r="2" fill="color-mix(in srgb, var(--overlay) 25%, var(--surface))" />
+ </g>
+ </pattern>
+ <rect fill="url(#bg-grid-major)" x="0" y="0" width="100%" height="100%" />
+ <g transform={`translate(${offsetX},${offsetY}) scale(${scale})`}>
+ {allLinks.value.map(({fromX, fromY, toX, toY}) => (
+ <Link fromX={fromX} fromY={fromY} toX={toX} toY={toY} />
+ ))}
+ <SocketHandlers.Provider value={socketHandlers}>
+ {nodes.value.map(node => (
+ <node.component id={node.id} x={node.x} y={node.y} inputs={node.inputs} />
+ ))}
+ </SocketHandlers.Provider>
+ </g>
+ </svg>
+ </main>
+ </>
);
};
diff --git a/src/index.tsx b/src/index.tsx
index cd8c870..a67fd94 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,3 +1,4 @@
+import 'preact/debug';
import { render } from 'preact';
import { useMemo } from 'preact/hooks';
import { Router } from 'preact-router';
@@ -7,7 +8,7 @@ import { Home, SignUp, LogIn, ProjectsList, Editor } from './pages';
import './index.css';
export const App = () => {
- const pb = useMemo(() => new PocketBase(`/`), []);
+ const pb = useMemo(() => new PocketBase('http://localhost:8090/'), []);
return (
<Pb.Provider value={pb}>
<Router>
diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx
index c929595..c5b369f 100644
--- a/src/pages/Editor.tsx
+++ b/src/pages/Editor.tsx
@@ -20,11 +20,7 @@ const Editor = ({ user, project }: EditorProps) => {
})();
}, []);
- return (
- <>
- {!!projectData.value && <NodeEditor project={projectData.value} />}
- </>
- );
+ return projectData.value ? <NodeEditor project={projectData.value} /> : null;
};
export default Editor;
diff --git a/src/pages/SignUp.test.tsx b/src/pages/SignUp.test.tsx
new file mode 100644
index 0000000..3029beb
--- /dev/null
+++ b/src/pages/SignUp.test.tsx
@@ -0,0 +1,34 @@
+import { expect, test } from 'bun:test';
+import { render, fireEvent } from '@testing-library/preact';
+import { Pb } from '../context.ts';
+import { pb } from '../preload.ts';
+import SignUp from './SignUp.tsx';
+
+test('has a link to log in', () => {
+ const { getAllByText, getByLabelText, getByText } = render(
+ <SignUp />
+ );
+
+ expect(getAllByText(/log in/i)).not.toHaveLength(0);
+});
+
+test('can sign up', () => {
+ const username = 'foo';
+ const email = 'foo@example.com';
+ const password = '12345678';
+
+ const { getByText, getByLabelText } = render(
+ <Pb.Provider value={pb}>
+ <SignUp />
+ </Pb.Provider>
+ );
+
+ fireEvent.change(getByLabelText(/username/i), {target: {value: username}});
+ fireEvent.change(getByLabelText(/email/i), {target: {value: email}});
+ fireEvent.change(getByLabelText(/password/i), {target: {value: password}});
+ fireEvent.change(getByLabelText(/confirm password/i), {target: {value: password}});
+
+ fireEvent.click(getByText(/continue/i));
+
+ expect(pb.authStore.isValid()).toBeTrue();
+});
diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx
index e1cee3c..755c180 100644
--- a/src/pages/SignUp.tsx
+++ b/src/pages/SignUp.tsx
@@ -2,7 +2,14 @@ import { useContext, useCallback } from 'preact/hooks';
import { useSignal } from '@preact/signals';
import { route } from 'preact-router';
import { Pb } from '../context.ts';
-import { Header, Content, Form, FormLabel, TextInput, Button, ArrowButton } from '../components';
+
+import Header from '../components/Header.tsx';
+import Content from '../components/Content.tsx';
+import Form from '../components/Form.tsx';
+import FormLabel from '../components/FormLabel.tsx';
+import TextInput from '../components/TextInput.tsx';
+import Button from '../components/Button.tsx';
+import ArrowButton from '../components/ArrowButton.tsx';
const SignUp = () => {
const pb = useContext(Pb)!;
diff --git a/src/test-preload.ts b/src/test-preload.ts
new file mode 100644
index 0000000..3ec72a1
--- /dev/null
+++ b/src/test-preload.ts
@@ -0,0 +1,9 @@
+import { GlobalRegistrator } from '@happy-dom/global-registrator';
+import PocketBase from 'pocketbase';
+
+GlobalRegistrator.register();
+
+const proc = Bun.spawn(['./pocketbase', 'serve', '--http', '127.0.0.1:8090']);
+
+const pb = new PocketBase('http://localhost:8090/');
+export { pb };