Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,19 @@ function serializeElementNode(
attributes.checked = checked;
}
}
if (
(tagName === 'input' || tagName === 'textarea') &&
attributes.placeholder
) {
attributes.placeholder = maskInputValue({
element: n,
type: getInputType(n),
tagName,
value: attributes.placeholder as string,
maskInputOptions,
maskInputFn,
});
}
if (tagName === 'option') {
if ((n as HTMLOptionElement).selected && !maskInputOptions['select']) {
attributes.selected = true;
Expand Down
2 changes: 1 addition & 1 deletion packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ export default class MutationBuffer {
let attributeName = m.attributeName as string;
let value = (m.target as HTMLElement).getAttribute(attributeName);

if (attributeName === 'value') {
if (attributeName === 'value' || attributeName === 'placeholder') {
const type = getInputType(target);

value = maskInputValue({
Expand Down
30 changes: 20 additions & 10 deletions packages/rrweb/test/__snapshots__/integration.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2665,7 +2665,8 @@ exports[`record integration tests > can record form interactions 1`] = `
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\"
\\"type\\": \\"text\\",
\\"placeholder\\": \\"Enter your email\\"
},
\\"childNodes\\": [],
\\"id\\": 22
Expand Down Expand Up @@ -2806,7 +2807,8 @@ exports[`record integration tests > can record form interactions 1`] = `
\\"id\\": \\"\\",
\\"cols\\": \\"30\\",
\\"rows\\": \\"10\\",
\\"data-unmask-example\\": \\"true\\"
\\"data-unmask-example\\": \\"true\\",
\\"placeholder\\": \\"Tell us about yourself\\"
},
\\"childNodes\\": [],
\\"id\\": 42
Expand Down Expand Up @@ -4649,7 +4651,8 @@ exports[`record integration tests > can use maskInputOptions to configure which
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\"
\\"type\\": \\"text\\",
\\"placeholder\\": \\"Enter your email\\"
},
\\"childNodes\\": [],
\\"id\\": 22
Expand Down Expand Up @@ -4790,7 +4793,8 @@ exports[`record integration tests > can use maskInputOptions to configure which
\\"id\\": \\"\\",
\\"cols\\": \\"30\\",
\\"rows\\": \\"10\\",
\\"data-unmask-example\\": \\"true\\"
\\"data-unmask-example\\": \\"true\\",
\\"placeholder\\": \\"Tell us about yourself\\"
},
\\"childNodes\\": [],
\\"id\\": 42
Expand Down Expand Up @@ -6477,7 +6481,8 @@ exports[`record integration tests > should mask inputs via function call 1`] = `
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\"
\\"type\\": \\"text\\",
\\"placeholder\\": \\"****************\\"
},
\\"childNodes\\": [],
\\"id\\": 22
Expand Down Expand Up @@ -6618,7 +6623,8 @@ exports[`record integration tests > should mask inputs via function call 1`] = `
\\"id\\": \\"\\",
\\"cols\\": \\"30\\",
\\"rows\\": \\"10\\",
\\"data-unmask-example\\": \\"true\\"
\\"data-unmask-example\\": \\"true\\",
\\"placeholder\\": \\"Tell us about yourself\\"
},
\\"childNodes\\": [],
\\"id\\": 42
Expand Down Expand Up @@ -10305,7 +10311,8 @@ exports[`record integration tests > should not record input values if maskAllInp
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\"
\\"type\\": \\"text\\",
\\"placeholder\\": \\"****************\\"
},
\\"childNodes\\": [],
\\"id\\": 22
Expand Down Expand Up @@ -10446,7 +10453,8 @@ exports[`record integration tests > should not record input values if maskAllInp
\\"id\\": \\"\\",
\\"cols\\": \\"30\\",
\\"rows\\": \\"10\\",
\\"data-unmask-example\\": \\"true\\"
\\"data-unmask-example\\": \\"true\\",
\\"placeholder\\": \\"**********************\\"
},
\\"childNodes\\": [],
\\"id\\": 42
Expand Down Expand Up @@ -13418,7 +13426,8 @@ exports[`record integration tests > should record input userTriggered values if
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\"
\\"type\\": \\"text\\",
\\"placeholder\\": \\"Enter your email\\"
},
\\"childNodes\\": [],
\\"id\\": 22
Expand Down Expand Up @@ -13559,7 +13568,8 @@ exports[`record integration tests > should record input userTriggered values if
\\"id\\": \\"\\",
\\"cols\\": \\"30\\",
\\"rows\\": \\"10\\",
\\"data-unmask-example\\": \\"true\\"
\\"data-unmask-example\\": \\"true\\",
\\"placeholder\\": \\"Tell us about yourself\\"
},
\\"childNodes\\": [],
\\"id\\": 42
Expand Down
4 changes: 2 additions & 2 deletions packages/rrweb/test/html/form.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<body>
<form>
<label for="text">
<input type="text" />
<input type="text" placeholder="Enter your email" />
</label>
<label>
<input type="radio" name="toggle" value="on" />
Expand All @@ -22,7 +22,7 @@
<input type="checkbox" />
</label>
<label for="textarea">
<textarea name="" id="" cols="30" rows="10" data-unmask-example="true"></textarea>
<textarea name="" id="" cols="30" rows="10" data-unmask-example="true" placeholder="Tell us about yourself"></textarea>
</label>
<label for="select">
<select name="" id="">
Expand Down
44 changes: 43 additions & 1 deletion packages/rrweb/test/integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ import {
ISuite,
} from './utils';
import type { recordOptions } from '../src/types';
import { eventWithTime, NodeType, EventType } from '@rrweb/types';
import {
eventWithTime,
NodeType,
EventType,
serializedNodeWithId,
} from '@rrweb/types';
import { visitSnapshot } from 'rrweb-snapshot';

describe('record integration tests', function (this: ISuite) {
Expand Down Expand Up @@ -617,6 +622,43 @@ describe('record integration tests', function (this: ISuite) {
await assertSnapshot(snapshots);
});

it('should mask placeholder values if maskAllInputs is enabled', async () => {
const page: puppeteer.Page = await browser.newPage();
await page.goto('about:blank');
await page.setContent(
getHtml.call(this, 'form.html', { maskAllInputs: true }),
);

const snapshots = (await page.evaluate(
'window.snapshots',
)) as eventWithTime[];

const fullSnapshot = snapshots.find(
(s) => s.type === EventType.FullSnapshot,
);
expect(fullSnapshot).toBeDefined();

let foundMaskedPlaceholder = false;
visitSnapshot(
(fullSnapshot as eventWithTime & { data: { node: serializedNodeWithId } })
.data.node,
(node) => {
if (
node.type === NodeType.Element &&
(node.tagName === 'input' || node.tagName === 'textarea') &&
node.attributes.placeholder
) {
const placeholder = node.attributes.placeholder as string;
expect(placeholder).not.toContain('Enter your email');
expect(placeholder).not.toContain('Tell us about yourself');
expect(placeholder).toMatch(/^\*+$/);
foundMaskedPlaceholder = true;
}
},
);
expect(foundMaskedPlaceholder).toBe(true);
});

it('should record input userTriggered values if userTriggeredOnInput is enabled', async () => {
const page: puppeteer.Page = await browser.newPage();
await page.goto('about:blank');
Expand Down