Compare commits
No commits in common. '7dbc947abd7596a10bc7625a0443417acefe6403' and 'a5044cdb44ad548755bd7c866a93cf61e944109a' have entirely different histories.
7dbc947abd
...
a5044cdb44
@ -1,79 +0,0 @@ |
|||||||
import { defineConfig, devices } from "@playwright/test"; |
|
||||||
|
|
||||||
/** |
|
||||||
* Read environment variables from file. |
|
||||||
* https://github.com/motdotla/dotenv
|
|
||||||
*/ |
|
||||||
// import dotenv from 'dotenv';
|
|
||||||
// import path from 'path';
|
|
||||||
// dotenv.config({ path: path.resolve(__dirname, '.env') });
|
|
||||||
|
|
||||||
/** |
|
||||||
* See https://playwright.dev/docs/test-configuration.
|
|
||||||
*/ |
|
||||||
export default defineConfig({ |
|
||||||
testDir: "./src/frontends/tests", |
|
||||||
/* Run tests in files in parallel */ |
|
||||||
fullyParallel: true, |
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */ |
|
||||||
forbidOnly: !!process.env.CI, |
|
||||||
/* Retry on CI only */ |
|
||||||
retries: process.env.CI ? 2 : 0, |
|
||||||
/* Opt out of parallel tests on CI. */ |
|
||||||
workers: process.env.CI ? 1 : undefined, |
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */ |
|
||||||
reporter: "html", |
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ |
|
||||||
use: { |
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */ |
|
||||||
baseURL: "http://localhost:4321", |
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ |
|
||||||
trace: "on-first-retry", |
|
||||||
}, |
|
||||||
|
|
||||||
/* Configure projects for major browsers */ |
|
||||||
projects: [ |
|
||||||
{ |
|
||||||
name: "chromium", |
|
||||||
use: { ...devices["Desktop Chrome"] }, |
|
||||||
}, |
|
||||||
|
|
||||||
{ |
|
||||||
name: "firefox", |
|
||||||
use: { ...devices["Desktop Firefox"] }, |
|
||||||
}, |
|
||||||
|
|
||||||
{ |
|
||||||
name: "webkit", |
|
||||||
use: { ...devices["Desktop Safari"] }, |
|
||||||
}, |
|
||||||
|
|
||||||
/* Test against mobile viewports. */ |
|
||||||
// {
|
|
||||||
// name: 'Mobile Chrome',
|
|
||||||
// use: { ...devices['Pixel 5'] },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Safari',
|
|
||||||
// use: { ...devices['iPhone 12'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against branded browsers. */ |
|
||||||
// {
|
|
||||||
// name: 'Microsoft Edge',
|
|
||||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Google Chrome',
|
|
||||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
|
||||||
// },
|
|
||||||
], |
|
||||||
|
|
||||||
/* Run your local dev server before starting the tests */ |
|
||||||
webServer: { |
|
||||||
command: "npm run dev", |
|
||||||
url: "http://localhost:4321", |
|
||||||
reuseExistingServer: !process.env.CI, |
|
||||||
}, |
|
||||||
}); |
|
@ -1,10 +0,0 @@ |
|||||||
import { test, expect } from "@playwright/test"; |
|
||||||
|
|
||||||
test("components load", async ({ page }) => { |
|
||||||
await page.goto("/"); |
|
||||||
await page.waitForSelector(".vue astro-island"); |
|
||||||
|
|
||||||
await expect(page.locator(".vue .title")).toHaveText("vue"); |
|
||||||
await expect(page.locator(".react .title")).toHaveText("react"); |
|
||||||
await expect(page.locator(".svelte .title")).toHaveText("svelte"); |
|
||||||
}); |
|
@ -1,84 +0,0 @@ |
|||||||
import updateShape from "src/ng-mock/wasm-land/updateShape"; |
|
||||||
import type { Connection, Diff, Scope, Shape } from "../types"; |
|
||||||
import requestShape from "src/ng-mock/wasm-land/requestShape"; |
|
||||||
import { applyDiff } from "./applyDiff"; |
|
||||||
import { batch, deepSignal, watch } from "alien-deepsignals"; |
|
||||||
import { signal as createSignal, computed } from "alien-signals"; |
|
||||||
|
|
||||||
type ReactiveShapeObject = object; |
|
||||||
|
|
||||||
type ShapeObjectSignal = ReturnType< |
|
||||||
typeof createSignal<{ |
|
||||||
content: ReactiveShapeObject | null; |
|
||||||
}> |
|
||||||
>; |
|
||||||
|
|
||||||
const openConnections: Partial<Record<Shape, ShapeObjectSignal>> = {}; |
|
||||||
|
|
||||||
/** |
|
||||||
* Create a signal for a shape object. |
|
||||||
* The function returns a signal of a shape object in the form: |
|
||||||
* `{content: <shapeObject>}` |
|
||||||
**/ |
|
||||||
export function createSignalObjectForShape( |
|
||||||
shape: Shape, |
|
||||||
scope?: Scope, |
|
||||||
poolSignal = true |
|
||||||
) { |
|
||||||
if (poolSignal && openConnections[shape]) return openConnections[shape]; |
|
||||||
|
|
||||||
// DeepSignal has a different API to alien-signals.
|
|
||||||
// Therefore, we need to create a "root signal" wrapper that is
|
|
||||||
// triggered on deepSignal changes.
|
|
||||||
const rootSignal = createSignal<{ |
|
||||||
content: ReactiveShapeObject | null; |
|
||||||
}>({ content: null }); |
|
||||||
|
|
||||||
// State
|
|
||||||
let stopWatcher: any = null; |
|
||||||
let suspendDeepWatcher = false; |
|
||||||
|
|
||||||
const onUpdateFromDb = (diff: Diff, connectionId: Connection["id"]) => { |
|
||||||
const rootSignalValue = rootSignal(); |
|
||||||
console.log("Update received", connectionId, diff); |
|
||||||
// Set new value from applying the diffs to the old value.
|
|
||||||
|
|
||||||
suspendDeepWatcher = true; |
|
||||||
// We need to replace the root signal for now, so this is redundant.
|
|
||||||
batch(() => { |
|
||||||
if (!rootSignalValue) return; // This shouldn't happen but we make the compiler happy.
|
|
||||||
const { content: proxiedShapeObj } = rootSignalValue; |
|
||||||
applyDiff(proxiedShapeObj, diff); |
|
||||||
|
|
||||||
// We put the proxied object into a new object for the root signal to trigger.
|
|
||||||
rootSignal({ content: proxiedShapeObj }); |
|
||||||
}); |
|
||||||
suspendDeepWatcher = false; |
|
||||||
}; |
|
||||||
|
|
||||||
// Do the actual db request.
|
|
||||||
requestShape(shape, scope, onUpdateFromDb).then( |
|
||||||
({ connectionId, shapeObject }) => { |
|
||||||
// Create a deepSignal to put into the vanilla alien-signal.
|
|
||||||
const proxiedShapeObj = deepSignal(shapeObject); |
|
||||||
|
|
||||||
// Notify DB on changes.
|
|
||||||
stopWatcher = watch( |
|
||||||
proxiedShapeObj, |
|
||||||
(newVal, oldVal, onCleanup) => { |
|
||||||
// Don't update when applying changes from db diffs from the db.
|
|
||||||
if (!suspendDeepWatcher) updateShape(connectionId, newVal); |
|
||||||
}, |
|
||||||
{ deep: true } |
|
||||||
); |
|
||||||
|
|
||||||
// Update the root signal.
|
|
||||||
rootSignal({ content: proxiedShapeObj }); |
|
||||||
} |
|
||||||
); |
|
||||||
|
|
||||||
if (poolSignal) openConnections[shape] = rootSignal; |
|
||||||
|
|
||||||
// TODO: Dispose deepSignal root signal disposal.
|
|
||||||
return rootSignal; |
|
||||||
} |
|
@ -0,0 +1,75 @@ |
|||||||
|
import updateShape from "src/ng-mock/wasm-land/updateShape"; |
||||||
|
import type { Connection, Diff, Scope, Shape } from "../types"; |
||||||
|
import requestShape from "src/ng-mock/wasm-land/requestShape"; |
||||||
|
import { applyDiff } from "./applyDiff"; |
||||||
|
import { batch, deepSignal, watch } from "alien-deepsignals"; |
||||||
|
import { signal } from "alien-signals"; |
||||||
|
|
||||||
|
const openConnections: Record<Shape, ReturnType<typeof signal>> = {}; |
||||||
|
|
||||||
|
// TODO: The code is horrible.
|
||||||
|
export function createSignalObjectForShape(shape: Shape, scope?: Scope) { |
||||||
|
if (openConnections[shape]) return openConnections[shape]; |
||||||
|
|
||||||
|
// TODO:
|
||||||
|
// DeepSignal has a different API to alien-signals.
|
||||||
|
// Therefore, we need to create a "root signal" wrapper that is
|
||||||
|
// triggered on deepSignal changes.
|
||||||
|
const rootSignal = signal<null | object>(null); |
||||||
|
|
||||||
|
// State
|
||||||
|
let stopWatcher: any = null; |
||||||
|
let suspendWatcher = false; |
||||||
|
|
||||||
|
// To update the root signal
|
||||||
|
const setUpDeepSignal = ( |
||||||
|
newSignal: ReturnType<typeof deepSignal>, |
||||||
|
connectionId: Connection["id"] |
||||||
|
) => { |
||||||
|
stopWatcher?.(); |
||||||
|
|
||||||
|
// Notify DB on changes.
|
||||||
|
stopWatcher = watch( |
||||||
|
newSignal, |
||||||
|
(newVal, oldVal, onCleanup) => { |
||||||
|
if (!suspendWatcher) updateShape(connectionId, newVal); |
||||||
|
}, |
||||||
|
{ deep: true } |
||||||
|
); |
||||||
|
|
||||||
|
// Update the root signal.
|
||||||
|
rootSignal(newSignal); |
||||||
|
}; |
||||||
|
|
||||||
|
const onUpdateFromDb = (diff: Diff, connectionId: Connection["id"]) => { |
||||||
|
const nestedObj = rootSignal(); |
||||||
|
console.log("Update received", connectionId, diff); |
||||||
|
// Set new value from applying the diffs to the old value.
|
||||||
|
|
||||||
|
// suspendWatcher = true;
|
||||||
|
// We need to replace the root signal for now, so this is redundant.
|
||||||
|
// batch(() => {
|
||||||
|
// if (!nestedObj) return; // This shouldn't happen but we make the compiler happy.
|
||||||
|
// applyDiff(nestedObj, diff);
|
||||||
|
// });
|
||||||
|
// suspendWatcher = false;nestedObj
|
||||||
|
|
||||||
|
// Create a new deep signal.
|
||||||
|
// We need to do that because the deepSignals ref hasn't changed otherwise
|
||||||
|
// and no update is triggered.
|
||||||
|
const newDeepSignal = deepSignal(JSON.parse(JSON.stringify(diff))); |
||||||
|
setUpDeepSignal(newDeepSignal, connectionId); |
||||||
|
}; |
||||||
|
|
||||||
|
// Do the actual db request.
|
||||||
|
requestShape(shape, scope, onUpdateFromDb).then( |
||||||
|
({ connectionId, shapeObject }) => { |
||||||
|
// Create a deepSignal to put into the vanilla alien-signal.
|
||||||
|
const deepSignalFromDb = deepSignal(shapeObject); |
||||||
|
setUpDeepSignal(deepSignalFromDb, connectionId); |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
openConnections[shape] = rootSignal; |
||||||
|
return rootSignal; |
||||||
|
} |
@ -1,14 +1,13 @@ |
|||||||
import { useSignal } from "@gn8/alien-signals-vue"; |
import { useSignal } from "@gn8/alien-signals-vue"; |
||||||
import { createSignalObjectForShape } from "src/ng-mock/js-land/connector/createSignalObjectForShape"; |
import { createSignalObjectForShape } from "src/ng-mock/js-land/connector/ngSignals"; |
||||||
import type { Scope, Shape } from "src/ng-mock/js-land/types"; |
import type { Scope, Shape } from "src/ng-mock/js-land/types"; |
||||||
import { computed } from "vue"; |
|
||||||
const useShape = (shape: Shape, scope: Scope) => { |
const useShape = (shape: Shape, scope: Scope) => { |
||||||
const signalOfShape = createSignalObjectForShape(shape, scope); |
const signalOfShape = createSignalObjectForShape(shape, scope); |
||||||
|
|
||||||
const refOfShape = useSignal(signalOfShape); |
const refOfShape = useSignal(signalOfShape); |
||||||
|
|
||||||
// TODO: Maybe `refOfShape.value.content` works too?
|
return refOfShape; |
||||||
return computed(() => refOfShape.value.content); |
|
||||||
}; |
}; |
||||||
|
|
||||||
export default useShape; |
export default useShape; |
||||||
|
Loading…
Reference in new issue