Expose SDKContext on the window & avoid using singleton store .instance (#34098)

* Expose SDKContextClass via window for debugging

* Remove stores from window if they are exposed via sdkContext

* Avoid usages of global store instance where React context is accessible

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Fix tests by adding SDKContext.Provider

* Iterate

* Discard changes to apps/web/src/components/views/elements/AppTile.tsx
This commit is contained in:
Michael Telatynski
2026-07-10 09:51:38 +00:00
committed by GitHub
parent 15c85ec50f
commit aeea53dfde
36 changed files with 613 additions and 232 deletions
@@ -20,6 +20,7 @@ import { CommandPartCreator } from "../../../../../src/editor/parts";
import DocumentOffset from "../../../../../src/editor/offset";
import { SDKContextClass } from "../../../../../src/contexts/SDKContextClass";
import SettingsStore from "../../../../../src/settings/SettingsStore";
import { SDKContext } from "../../../../../src/contexts/SDKContext.ts";
describe("BasicMessageComposer", () => {
const renderer = createRenderer();
@@ -35,7 +36,11 @@ describe("BasicMessageComposer", () => {
it("should allow a user to paste a URL without it being mangled", async () => {
const model = new EditorModel([], pc, renderer);
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const testUrl = "https://element.io";
const mockDataTransfer = generateMockDataTransferForString(testUrl);
await userEvent.paste(mockDataTransfer);
@@ -51,7 +56,11 @@ describe("BasicMessageComposer", () => {
});
userEvent.setup();
const model = new EditorModel([], pc, renderer);
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const tranformations = [
{ before: "4:3 video", after: "4:3 video" },
@@ -81,7 +90,11 @@ describe("BasicMessageComposer", () => {
it("should not mangle shift-enter when the autocomplete is open", async () => {
const model = new EditorModel([], pc, renderer);
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const input = screen.getByRole("textbox");
@@ -93,7 +106,11 @@ describe("BasicMessageComposer", () => {
it("should escape single quote in placeholder", async () => {
const model = new EditorModel([], pc, renderer);
const composer = render(<BasicMessageComposer placeholder="Don't" model={model} room={room} />);
const composer = render(<BasicMessageComposer placeholder="Don't" model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const input = composer.queryAllByRole("textbox");
const placeholder = input[0].style.getPropertyValue("--placeholder");
expect(placeholder).toMatch("'Don\\'t'");
@@ -101,7 +118,11 @@ describe("BasicMessageComposer", () => {
it("should escape backslash in placeholder", async () => {
const model = new EditorModel([], pc, renderer);
const composer = render(<BasicMessageComposer placeholder={"w\\e"} model={model} room={room} />);
const composer = render(<BasicMessageComposer placeholder={"w\\e"} model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const input = composer.queryAllByRole("textbox");
const placeholder = input[0].style.getPropertyValue("--placeholder");
expect(placeholder).toMatch("'w\\\\e'");
@@ -116,7 +137,11 @@ describe("BasicMessageComposer", () => {
// spy on typingStore.setSelfTyping
const spy = jest.spyOn(SDKContextClass.instance.typingStore, "setSelfTyping");
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
// simulate typing by updating the model - this will call the component's update callback
await model.update(commandPart.text, "insertText", new DocumentOffset(commandPart.text.length, true));
@@ -128,7 +153,11 @@ describe("BasicMessageComposer", () => {
it("should ignore keydown events during IME composition", () => {
const model = new EditorModel([], pc, renderer);
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const input = screen.getByRole("textbox");
// Start IME composition
@@ -167,7 +196,11 @@ describe("BasicMessageComposer", () => {
it("should handle keydown events normally when not composing", () => {
const model = new EditorModel([], pc, renderer);
render(<BasicMessageComposer model={model} room={room} />);
render(<BasicMessageComposer model={model} room={room} />, {
wrapper: ({ children }) => (
<SDKContext.Provider value={SDKContextClass.instance}>{children}</SDKContext.Provider>
),
});
const input = screen.getByRole("textbox");
// Simulate Tab key when NOT composing