Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
78849f3
WIP dialog recording
Juice10 Jun 10, 2024
c1d850f
chore: its important to run `yarn build:all` before running `yarn dev`
Juice10 Jun 10, 2024
b657233
feat: trigger showModal from rrdom and rrweb
Juice10 Jun 10, 2024
337b4c4
feat: Add support for replaying modal and non modal dialog elements
Juice10 Jun 11, 2024
29d4827
chore: Update dev script to remove CLEAR_DIST_DIR flag
Juice10 Jun 11, 2024
dcc867c
Get modal recording and replay working
Juice10 Jun 12, 2024
1144c9d
DRY up dialog test and dedupe snapshot images
Juice10 Jun 12, 2024
7507f4d
Fix eslint error
Juice10 Jun 12, 2024
b8679a0
feat: Refactor dialog test to use updated attribute name
Juice10 Jun 12, 2024
6ec4727
feat: Update dialog test to include rr_open attribute
Juice10 Jun 12, 2024
f7db71c
chore: Add npm dependency [email protected]
Juice10 Jun 12, 2024
b300674
Fix dialog test
Juice10 Jun 12, 2024
178ec1f
Add more test cases for dialog
Juice10 Jun 12, 2024
4229391
Add changesets
Juice10 Jun 12, 2024
b0065ce
Clean up naming
Juice10 Jun 12, 2024
25678f4
Apply formatting changes
Juice10 Jun 12, 2024
b71c8b7
Refactor dialog open code
Juice10 Jun 12, 2024
05d4cf0
Merge branch 'juice10/record-dialog' of https://github.com/rrweb-io/r…
Juice10 Jun 12, 2024
e731636
Revert changed code that doesn't do anything
Juice10 Jun 12, 2024
184e4fa
Add documentation for unimplemented type
Juice10 Jun 12, 2024
6a58edc
chore: Remove unnecessary comments in dialog.test.ts
Juice10 Jun 12, 2024
8c51129
Merge branch 'master' of https://github.com/rrweb-io/rrweb into juice…
Juice10 Jun 26, 2024
0df7994
rename rr_open to rr_openMode
Juice10 Jun 26, 2024
1ce8f70
Replace todo with a skipped test
Juice10 Jun 26, 2024
8aeb47f
Add better logging for CI
Juice10 Jun 26, 2024
985ac9f
Rename rr_openMode to rr_open_mode
Juice10 Jun 26, 2024
d693da9
Remove unused images
Juice10 Jun 26, 2024
760908f
Move after iframe append based on @YunFeng0817's comment
Juice10 Jul 9, 2024
2dfeb01
Remove redundant dialog handling from rrdom.
Juice10 Jul 9, 2024
63c0def
Merge branch 'master' into juice10/record-dialog
Juice10 Jul 9, 2024
21c4826
Rename variables for dialog handling in rrweb replay module
Juice10 Jul 9, 2024
424e4c8
Merge branch 'juice10/record-dialog' of https://github.com/rrweb-io/r…
Juice10 Jul 9, 2024
30c7780
Merge branch 'master' into juice10/record-dialog
eoghanmurray Jul 31, 2024
9f2a27c
Update packages/rrdom/src/document.ts
Juice10 Aug 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
WIP dialog recording
  • Loading branch information
Juice10 committed Jun 10, 2024
commit 78849f3997e27690f2b6a3a026911329cf9e35ed
11 changes: 11 additions & 0 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
MaskInputOptions,
SlimDOMOptions,
DataURLOptions,
DialogAttributes,
MaskTextFn,
MaskInputFn,
KeepIframeSrcFn,
Expand Down Expand Up @@ -704,6 +705,16 @@ function serializeElementNode(
delete attributes.selected;
}
}

if (
tagName === 'dialog' &&
(n as HTMLDialogElement).open &&
n.matches('dialog:modal')
) {
(attributes as DialogAttributes).rr_open = 'modal';
delete attributes.open; // prevent default `show()` behavior which blocks `showModal()` from working
}

// canvas image data
if (tagName === 'canvas' && recordCanvas) {
if ((n as ICanvas).__context === '2d') {
Expand Down
9 changes: 9 additions & 0 deletions packages/rrweb-snapshot/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ export type mediaAttributes = {
rr_mediaVolume?: number;
};

export type DialogAttributes =
// | {
// open: '';
// }
{
rr_open: 'modal';
// rr_open_index?: number;
};

// @deprecated
export interface INode extends Node {
__sn: serializedNodeWithId;
Expand Down
122 changes: 122 additions & 0 deletions packages/rrweb-snapshot/test/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,121 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`dialog integration tests > should capture open attribute for modal dialogs 1`] = `
"{
\\"type\\": 0,
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"html\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"head\\",
\\"attributes\\": {},
\\"childNodes\\": [],
\\"id\\": 3
},
{
\\"type\\": 2,
\\"tagName\\": \\"body\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\",
\\"id\\": 5
},
{
\\"type\\": 2,
\\"tagName\\": \\"dialog\\",
\\"attributes\\": {
\\"rr_open\\": \\"modal\\"
},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"I'm a dialog\\",
\\"id\\": 7
}
],
\\"id\\": 6
},
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\\\n\\\\n\\",
\\"id\\": 8
}
],
\\"id\\": 4
}
],
\\"id\\": 2
}
],
\\"compatMode\\": \\"BackCompat\\",
\\"id\\": 1
}"
`;

exports[`dialog integration tests > should capture open attribute for non modal dialogs 1`] = `
"{
\\"type\\": 0,
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"html\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"head\\",
\\"attributes\\": {},
\\"childNodes\\": [],
\\"id\\": 3
},
{
\\"type\\": 2,
\\"tagName\\": \\"body\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\",
\\"id\\": 5
},
{
\\"type\\": 2,
\\"tagName\\": \\"dialog\\",
\\"attributes\\": {
\\"open\\": \\"\\"
},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"I'm a dialog\\",
\\"id\\": 7
}
],
\\"id\\": 6
},
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\\\n\\\\n\\",
\\"id\\": 8
}
],
\\"id\\": 4
}
],
\\"id\\": 2
}
],
\\"compatMode\\": \\"BackCompat\\",
\\"id\\": 1
}"
`;

exports[`iframe integration tests > snapshot async iframes 1`] = `
"{
\\"type\\": 0,
Expand Down Expand Up @@ -214,6 +330,12 @@ exports[`integration tests > [html file]: cors-style-sheet.html 1`] = `
<body></body></html>"
`;

exports[`integration tests > [html file]: dialog.html 1`] = `
"<html><head></head><body>
<dialog>I'm a dialog</dialog>
</body></html>"
`;

exports[`integration tests > [html file]: dynamic-stylesheet.html 1`] = `
"<!DOCTYPE html><html lang=\\"en\\"><head>
<meta charset=\\"UTF-8\\" />
Expand Down
5 changes: 5 additions & 0 deletions packages/rrweb-snapshot/test/html/dialog.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<html>
<body>
<dialog>I'm a dialog</dialog>
</body>
</html>
75 changes: 71 additions & 4 deletions packages/rrweb-snapshot/test/integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import * as fs from 'fs';
import * as path from 'path';
import * as http from 'http';
import * as url from 'url';
import * as path from 'path';
import * as puppeteer from 'puppeteer';
import { vi, assert, describe, it, beforeAll, afterAll, expect } from 'vitest';
import { waitForRAF, getServerURL } from './utils';
import * as url from 'url';
import {
afterAll,
assert,
beforeAll,
beforeEach,
describe,
expect,
it,
vi,
} from 'vitest';

import { getServerURL, waitForRAF } from './utils';

const htmlFolder = path.join(__dirname, 'html');
const htmls = fs.readdirSync(htmlFolder).map((filePath) => {
Expand Down Expand Up @@ -60,6 +70,15 @@ function sanitizeSnapshot(snapshot: string): string {
return snapshot.replace(/localhost:[0-9]+/g, 'localhost:3030');
}

async function snapshot(page: puppeteer.Page, code: string): Promise<string> {
await waitForRAF(page);
const result = (await page.evaluate(`${code}
const snapshot = rrwebSnapshot.snapshot(document);
JSON.stringify(snapshot, null, 2);
`)) as string;
return result;
}

function assertSnapshot(snapshot: string): void {
expect(sanitizeSnapshot(snapshot)).toMatchSnapshot();
}
Expand All @@ -68,6 +87,7 @@ interface ISuite {
server: http.Server;
serverURL: string;
browser: puppeteer.Browser;
page: puppeteer.Page;
code: string;
}

Expand Down Expand Up @@ -431,6 +451,53 @@ describe('iframe integration tests', function (this: ISuite) {
});
});

describe('dialog integration tests', function (this: ISuite) {
vi.setConfig({ testTimeout: 30_000 });
let server: ISuite['server'];
let serverURL: ISuite['serverURL'];
let browser: ISuite['browser'];
let code: ISuite['code'];
let page: ISuite['page'];

beforeAll(async () => {
server = await startServer();
serverURL = getServerURL(server);
browser = await puppeteer.launch({
// headless: false,
});

code = fs.readFileSync(
path.resolve(__dirname, '../dist/rrweb-snapshot.umd.cjs'),
'utf-8',
);
});

beforeEach(async () => {
page = await browser.newPage();
page.on('console', (msg) => console.log(msg.text()));
await page.goto(`${serverURL}/html/dialog.html`, {
waitUntil: 'load',
});
});

afterAll(async () => {
await browser.close();
await server.close();
});

it('should capture open attribute for non modal dialogs', async () => {
page.evaluate('document.querySelector("dialog").show()');
const snapshotResult = await snapshot(page, code);
assertSnapshot(snapshotResult);
});

it('should capture open attribute for modal dialogs', async () => {
await page.evaluate('document.querySelector("dialog").showModal()');
const snapshotResult = await snapshot(page, code);
assertSnapshot(snapshotResult);
});
});

describe('shadow DOM integration tests', function (this: ISuite) {
vi.setConfig({ testTimeout: 30_000 });
let server: ISuite['server'];
Expand Down
28 changes: 27 additions & 1 deletion packages/rrweb-snapshot/test/rebuild.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
*/
import * as fs from 'fs';
import * as path from 'path';
import { describe, it, beforeEach, expect } from 'vitest';
import { beforeEach, describe, expect, it } from 'vitest';

import {
adaptCssForReplay,
buildNodeWithSN,
Expand Down Expand Up @@ -52,6 +53,31 @@ describe('rebuild', function () {
});
});

// this doesn't really test anything, maybe remove it?
// contemplate if rrweb-snapshot should trigger .showModal() on dialog elements on rebuild...
describe('rr_open', function () {
it('should call `show` on non-modal dialog', function () {
const node = buildNodeWithSN(
{
id: 1,
tagName: 'dialog',
type: NodeType.Element,
attributes: {
open: '',
},
childNodes: [],
},
{
doc: document,
mirror,
hackCss: false,
cache,
},
) as HTMLDialogElement;
expect(node?.open).toBe(true);
});
});

describe('shadowDom', function () {
it('rebuild shadowRoot without siblings', function () {
const node = buildNodeWithSN(
Expand Down
Loading