Skip to content

Commit 997b41f

Browse files
committed
Add error box middleware
1 parent 0758b57 commit 997b41f

21 files changed

Lines changed: 647 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script type="importmap">
6+
{
7+
"imports": {
8+
"@testduet/wait-for": "https://esm.sh/@testduet/wait-for",
9+
"expect": "https://esm.sh/expect?bundle=true",
10+
"jest-mock": "https://esm.sh/jest-mock",
11+
"react": "https://esm.sh/react@18.3.1",
12+
"react-dom": "https://esm.sh/react-dom@18.3.1",
13+
"react-dom/": "https://esm.sh/react-dom@18.3.1/"
14+
}
15+
}
16+
</script>
17+
<script type="module">
18+
import React from 'react';
19+
20+
window.React = React;
21+
</script>
22+
<script defer crossorigin="anonymous" src="/test-harness.js"></script>
23+
<script defer crossorigin="anonymous" src="/test-page-object.js"></script>
24+
<script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
25+
<style type="text/css">
26+
.my-activity {
27+
border: solid 2px red;
28+
}
29+
</style>
30+
</head>
31+
<body>
32+
<main id="webchat"></main>
33+
<script defer type="module">
34+
import { waitFor } from '@testduet/wait-for';
35+
import { expect } from 'expect';
36+
import { fn, spyOn } from 'jest-mock';
37+
import React, { createElement, memo } from 'react';
38+
import { createRoot } from 'react-dom/client';
39+
40+
run(async function () {
41+
const {
42+
testHelpers: { createDirectLineEmulator },
43+
WebChat: {
44+
Components: { Composer },
45+
hooks: { useActivities, useBuildRenderActivityCallback },
46+
middleware: { activityComponent, createActivityPolymiddleware },
47+
ReactWebChat
48+
}
49+
} = window;
50+
51+
const { directLine, store } = createDirectLineEmulator();
52+
53+
const rootElement = document.getElementsByTagName('main')[0];
54+
const polymiddleware = [
55+
createActivityPolymiddleware(next => request => ({
56+
render: () => createElement('div', {}, 'Should not render because this is not under activityComponent()')
57+
}))
58+
];
59+
60+
// WHEN: Web Chat is being rendered.
61+
createRoot(rootElement).render(
62+
createElement(ReactWebChat, {
63+
directLine,
64+
polymiddleware,
65+
store
66+
})
67+
);
68+
69+
// WHEN: Web Chat is connected.
70+
await pageConditions.uiConnected();
71+
72+
const consoleError = fn((...args) => console.warn(...args));
73+
74+
spyOn(console, 'error').mockImplementationOnce(consoleError);
75+
76+
// WHEN: A message "Hello, World!" arrives.
77+
await directLine.emulateIncomingActivity({
78+
text: 'Hello, World!',
79+
type: 'message'
80+
});
81+
82+
// THEN: Should show the activity as a red box.
83+
await pageConditions.numActivitiesShown(1);
84+
85+
// THEN: Should have error log.
86+
expect(consoleError).toHaveBeenCalledTimes(1);
87+
expect(consoleError.mock.calls[0][0].cause.name).toBe('ValiError');
88+
expect(consoleError.mock.calls[0][0].message).toBe(
89+
'botframework-webchat: middleware must return value constructed by their corresponding factory function'
90+
);
91+
92+
// THEN: Should show a red box.
93+
await host.snapshot('local');
94+
});
95+
</script>
96+
</body>
97+
</html>
Loading
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<!doctype html>
2+
<html lang="en-US">
3+
<head>
4+
<link href="/assets/index.css" rel="stylesheet" type="text/css" />
5+
<script type="importmap">
6+
{
7+
"imports": {
8+
"@testduet/wait-for": "https://esm.sh/@testduet/wait-for",
9+
"jest-mock": "https://esm.sh/jest-mock",
10+
"react": "https://esm.sh/react@18.3.1",
11+
"react-dom": "https://esm.sh/react-dom@18.3.1",
12+
"react-dom/": "https://esm.sh/react-dom@18.3.1/"
13+
}
14+
}
15+
</script>
16+
<script type="module">
17+
import React from 'react';
18+
19+
window.React = React;
20+
</script>
21+
<script defer crossorigin="anonymous" src="/test-harness.js"></script>
22+
<script defer crossorigin="anonymous" src="/test-page-object.js"></script>
23+
<script defer crossorigin="anonymous" src="/__dist__/webchat-es5.js"></script>
24+
<style type="text/css">
25+
.my-activity {
26+
border: solid 2px red;
27+
}
28+
</style>
29+
</head>
30+
<body>
31+
<main id="webchat"></main>
32+
<script defer type="module">
33+
import { waitFor } from '@testduet/wait-for';
34+
import { fn, spyOn } from 'jest-mock';
35+
import React, { createElement, memo } from 'react';
36+
import { createRoot } from 'react-dom/client';
37+
38+
run(async function () {
39+
const {
40+
testHelpers: { createDirectLineEmulator },
41+
WebChat: {
42+
Components: { Composer },
43+
hooks: { useActivities, useBuildRenderActivityCallback },
44+
middleware: { activityComponent, createActivityPolymiddleware },
45+
ReactWebChat
46+
}
47+
} = window;
48+
49+
const { directLine, store } = createDirectLineEmulator();
50+
51+
function ThrowOnRender() {
52+
throw new Error('Throw on render');
53+
}
54+
55+
const rootElement = document.getElementsByTagName('main')[0];
56+
const polymiddleware = [createActivityPolymiddleware(next => request => activityComponent(ThrowOnRender))];
57+
58+
// WHEN: Web Chat is being rendered.
59+
createRoot(rootElement).render(
60+
createElement(ReactWebChat, {
61+
directLine,
62+
polymiddleware,
63+
store
64+
})
65+
);
66+
67+
// WHEN: Web Chat is connected.
68+
await pageConditions.uiConnected();
69+
70+
const consoleError = fn((...args) => console.warn(...args));
71+
72+
spyOn(console, 'error').mockImplementationOnce(consoleError);
73+
74+
// WHEN: A message "Hello, World!" arrives.
75+
await directLine.emulateIncomingActivity({
76+
text: 'Hello, World!',
77+
type: 'message'
78+
});
79+
80+
// THEN: Should show the activity as a red box.
81+
await pageConditions.numActivitiesShown(1);
82+
83+
// THEN: Should have error log.
84+
expect(consoleError).toHaveBeenCalledTimes(1);
85+
expect(consoleError.mock.calls[0][0]).toBeInstanceOf(Error);
86+
expect(consoleError.mock.calls[0][0].message).toBe('Throw on render');
87+
88+
// THEN: Should show a red box.
89+
await host.snapshot('local');
90+
});
91+
</script>
92+
</body>
93+
</html>
11.7 KB
Loading

package-lock.json

Lines changed: 69 additions & 68 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/api-middleware/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
"precommit:eslint": "../../node_modules/.bin/eslint --report-unused-disable-directives --max-warnings 0",
7171
"precommit:typecheck": "tsc --project ./src --emitDeclarationOnly false --esModuleInterop true --noEmit --pretty false",
7272
"preversion": "cat package.json | jq '(.localDependencies // {} | to_entries | map([if .value == \"production\" then \"dependencies\" else \"devDependencies\" end, .key])) as $P | delpaths($P)' > package-temp.json && mv package-temp.json package.json",
73-
"start": "npm run build -- --onSuccess=\"touch ../api/src/index.ts ../component/src/index.ts\" --watch"
73+
"start": "npm run build -- --onSuccess=\"touch ../api/src/index.ts\" --watch"
7474
},
7575
"devDependencies": {
7676
"@jridgewell/sourcemap-codec": "^1.5.0",
@@ -88,6 +88,7 @@
8888
"dependencies": {
8989
"handler-chain": "^0.1.0",
9090
"react-chain-of-responsibility": "^0.4.0-main.9e06f00",
91+
"react-wrap-with": "0.1.0",
9192
"valibot": "1.1.0"
9293
}
9394
}

0 commit comments

Comments
 (0)