Skip to content

Commit

Permalink
refactor: added script processing inside the script, tests tag
Browse files Browse the repository at this point in the history
  • Loading branch information
PKulkoRaccoonGang committed Jun 20, 2024
1 parent 29b15a8 commit 2f5723f
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 15 deletions.
50 changes: 35 additions & 15 deletions src/scripts/ScriptInserter.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,57 @@ class ScriptInserter {
* @param {string} content - The content to insert into the head section.
*/
insertToHead(content) {
const { head } = document;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
while (tempDiv.firstChild) {
head.appendChild(tempDiv.firstChild);
}
this.createAndAppendScript(content, document.head);
}

/**
* Inserts content at the start of the body section.
* @param {string} content - The content to insert at the top of the body section.
*/
insertToBodyTop(content) {
const { body } = document;
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
while (tempDiv.firstChild) {
body.insertBefore(tempDiv.firstChild, body.firstChild);
}
this.createAndAppendScript(content, document.body, true);
}

/**
* Inserts content at the end of the body section.
* @param {string} content - The content to insert at the bottom of the body section.
*/
insertToBodyBottom(content) {
const { body } = document;
this.createAndAppendScript(content, document.body);
}

/**
* Creates a script element and appends it to the specified location.
* @param {string} content - The content of the script.
* @param {Element} parent - The parent element to insert the script into (head or body).
* @param {boolean} atStart - Whether to insert the script at the start of the parent element.
*/
createAndAppendScript(content, parent, atStart = false) {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = content;
while (tempDiv.firstChild) {
body.appendChild(tempDiv.firstChild);
const scriptElement = tempDiv.querySelector('script');

if (scriptElement && scriptElement.src) {
// If the script has a src attribute, create a new script element with the same src
const newScriptElement = document.createElement('script');
newScriptElement.src = scriptElement.src;
newScriptElement.async = true;

if (atStart && parent.firstChild) {
parent.insertBefore(newScriptElement, parent.firstChild);
} else {
parent.appendChild(newScriptElement);
}
} else {
// If the script does not have a src attribute, insert its inner content as inline script
const newScriptElement = document.createElement('script');
newScriptElement.text = scriptElement ? scriptElement.innerHTML : content;

if (atStart && parent.firstChild) {
parent.insertBefore(newScriptElement, parent.firstChild);
} else {
parent.appendChild(newScriptElement);
}
}
}
}
Expand Down
94 changes: 94 additions & 0 deletions src/scripts/ScriptInserter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import ScriptInserter from './ScriptInserter';

describe('ScriptInserter', () => {
let data;

beforeEach(() => {
document.head.innerHTML = '';
document.body.innerHTML = '';
});

function loadScripts(scriptData) {
const scriptInserter = new ScriptInserter(scriptData);
scriptInserter.loadScript();
}

describe('with multiple scripts', () => {
beforeEach(() => {
data = {
config: {
EXTERNAL_SCRIPTS: [
{
head: '<script>console.log("First head script");</script>',
body: {
top: '<script>console.log("First body top script");</script>',
bottom: '<script>console.log("First body bottom script");</script>',
},
},
{
head: '<script src="https://example.com/second-script.js"></script>',
},
{
body: {
top: '<script>console.log("Third body top script");</script>',
},
},
],
},
};
loadScripts(data);
});

it('should insert all head scripts', () => {
const headScripts = document.head.querySelectorAll('script');
expect(headScripts.length).toBe(2);

const inlineHeadScript = Array.from(headScripts)
.find(script => script.src === '' && script.innerHTML.includes('console.log("First head script")'));
const srcHeadScript = document.head
.querySelector('script[src="https://example.com/second-script.js"]');

expect(inlineHeadScript).not.toBeNull();
expect(srcHeadScript).not.toBeNull();
expect(srcHeadScript.async).toBe(true);
});

it('should insert all body top scripts in correct order', () => {
const bodyTopScripts = document.body.querySelectorAll('script');
expect(bodyTopScripts.length).toBe(3); // Top scripts + Bottom script

const firstTopScript = Array.from(bodyTopScripts)
.find(script => script.innerHTML.includes('console.log("First body top script")'));
const thirdTopScript = Array.from(bodyTopScripts)
.find(script => script.innerHTML.includes('console.log("Third body top script")'));

expect(firstTopScript).not.toBeNull();
expect(thirdTopScript).not.toBeNull();
});

it('should insert all body bottom scripts', () => {
const bodyBottomScripts = Array.from(document.body.querySelectorAll('script'))
.filter(script => script.innerHTML.includes('First body bottom script'));
expect(bodyBottomScripts.length).toBe(1);

const firstBottomScript = bodyBottomScripts[0];
expect(firstBottomScript.innerHTML).toBe('console.log("First body bottom script");');
});
});

describe('with no external scripts', () => {
beforeEach(() => {
data = {
config: {
EXTERNAL_SCRIPTS: [],
},
};
loadScripts(data);
});

it('should not insert any scripts', () => {
expect(document.head.querySelectorAll('script').length).toBe(0);
expect(document.body.querySelectorAll('script').length).toBe(0);
});
});
});

0 comments on commit 2f5723f

Please sign in to comment.