Skip to content

Commit

Permalink
Merge pull request #11 from preset-io/replace_children_polyfill
Browse files Browse the repository at this point in the history
replaceChildren: Polyfill with tests
  • Loading branch information
Antonio-RiveroMartnez authored Apr 14, 2023
2 parents fb8a075 + d103bd6 commit c9d89cd
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 4 deletions.
3 changes: 3 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
testEnvironment: 'jsdom',
};
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@preset-sdk/embedded",
"version": "0.1.5",
"version": "0.1.6",
"description": "Frontend SDK for embedding Preset data analytics into your own application",
"access": "public",
"keywords": [
Expand Down
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Switchboard } from '@superset-ui/switchboard';
import { IFRAME_COMMS_MESSAGE_TYPE } from './const';
import { getGuestTokenRefreshTiming } from './guestTokenRefresh';
import { applyReplaceChildrenPolyfill } from './polyfills';

/**
* The function to fetch a guest token from your Host App's backend server.
Expand Down Expand Up @@ -57,6 +58,8 @@ export async function embedDashboard({
}

log('embedding');
// Polyfill replaceChildren
applyReplaceChildrenPolyfill()

function calculateConfig() {
let configNumber = 0
Expand Down Expand Up @@ -96,7 +99,7 @@ export async function embedDashboard({
});

iframe.src = `${supersetDomain}/embedded/${id}${dashboardConfig}`;
mountPoint.replaceChildren(iframe);
mountPoint?.replaceChildren(iframe);
log('placed the iframe')
});
}
Expand All @@ -119,7 +122,7 @@ export async function embedDashboard({

function unmount() {
log('unmounting');
mountPoint.replaceChildren();
mountPoint?.replaceChildren();
}

const getScrollSize = () => ourPort.get<Size>('getScrollSize');
Expand Down
44 changes: 44 additions & 0 deletions src/polyfills.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { applyReplaceChildrenPolyfill } from './polyfills';

describe('replaceChildren polyfill', () => {
it('should add replaceChildren method to the prototype', () => {
const originalReplaceChildren = Element.prototype.replaceChildren;
// Remove the replaceChildren implementation from the Element prototype
delete (Element.prototype as any).replaceChildren;

// Check that the replaceChildren method does not exist
expect(HTMLElement.prototype.replaceChildren).toBeUndefined();

// Apply the polyfill
applyReplaceChildrenPolyfill();

// Check that the replaceChildren method has been added to the HTMLElement prototype
expect(HTMLElement.prototype.replaceChildren).toBeDefined();
expect(HTMLElement.prototype.replaceChildren).not.toEqual(originalReplaceChildren);

// Restore the original replaceChildren implementation
Object.defineProperty(Element.prototype, 'replaceChildren', {
configurable: true,
enumerable: true,
value: originalReplaceChildren,
writable: true,
});
});

it('should replace children correctly', () => {
// Create a parent element with two child elements
const parent = document.createElement('div');
const child1 = document.createElement('p');
const child2 = document.createElement('span');
parent.appendChild(child1);
parent.appendChild(child2);

// Replace the children with a new child element
parent.replaceChildren(document.createElement('a'));

// Check that the parent element only has one child
expect(parent.children.length).toBe(1);
// Check that the child element has been replaced with a new one
expect(parent.children[0].tagName).toBe('A');
});
});
28 changes: 28 additions & 0 deletions src/polyfills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export function applyReplaceChildrenPolyfill() {
(function (prototype) {
// If the prototype already has a replaceChildren method, skip it
if (prototype.hasOwnProperty('replaceChildren')) {
return;
}
// Otherwise, define a new replaceChildren method on the prototype
Object.defineProperty(prototype, 'replaceChildren', {
configurable: true,
enumerable: true,
// The replaceChildren method takes any number of arguments
value: function (...nodes: (Element | Text)[]) {
// Remove all existing child nodes
while (this.firstChild) {
this.removeChild(this.firstChild);
}
// Add the new child nodes
nodes.forEach((node) => {
// If the node is a string, create a new text node
// Otherwise, assume it's a DOM element and use it directly
this.appendChild(
typeof node === 'string' ? document.createTextNode(node) : node
);
});
},
});
})(Element.prototype);
}

0 comments on commit c9d89cd

Please sign in to comment.