diff --git a/browser/index.html b/browser/index.html index 08e4cce..713caf5 100644 --- a/browser/index.html +++ b/browser/index.html @@ -8,6 +8,7 @@ +
diff --git a/browser/index.ts b/browser/index.ts index d5b9ae5..ee2cea0 100644 --- a/browser/index.ts +++ b/browser/index.ts @@ -8,23 +8,4 @@ declare global { window.simpleLoadScript = simpleLoadScript; -// // example stuff -// (() => { -// const root = document.createElement('div'); -// const button = document.createElement('button'); -// button.id = 'btn'; - -// let count = 0; - -// button.textContent = `Clicked ${count} time(s)`; - -// button.onclick = () => { -// count++; -// button.textContent = `Clicked ${count} time(s)`; -// }; - -// root.appendChild(button); -// document.body.appendChild(root); -// })(); - export {}; diff --git a/package.json b/package.json index 1915a4d..33e3b1b 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,9 @@ "watch": "npm run build -- -w", "lint": "eslint --ext .ts . -f tap", "vite:build-and-preview": "vite build && vite preview", - "test:run": "vite build && vitest run", - "test:ui": "vite build && vitest --ui", - "test:watch": "vite build && vitest", + "test:run": "vite build && vitest run --reporter=verbose", + "test:ui": "vite build && vitest --reporter=verbose --ui", + "test:watch": "vite build && vitest --reporter=verbose", "format-check": "prettier --check ./**/*.ts", "format-write": "prettier --write ./**/*.ts", "check-types": "echo 'checking types…' && tsc && echo '…no type problems'" diff --git a/src/index.ts b/src/index.ts index 118fa2d..3b9f2a1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -76,7 +76,7 @@ export default function simpleLoadScript( if (removeScript) { where.removeChild(script); } - reject(new Error('Loading script')); + reject(new Error('Loading script error')); }); script.src = url; where.appendChild(script); diff --git a/test/attrs.spec.ts b/test/attrs.spec.ts new file mode 100644 index 0000000..0ff70d9 --- /dev/null +++ b/test/attrs.spec.ts @@ -0,0 +1,79 @@ +import { afterAll, beforeAll, expect, test } from 'vitest'; +import { preview } from 'vite'; +import type { PreviewServer } from 'vite'; +import { Browser, Page, chromium } from 'playwright'; +import { TIMEOUT } from './constants'; + +let browser: Browser; +let server: PreviewServer; +let page: Page; + +beforeAll(async () => { + browser = await chromium.launch({ headless: true }); + server = await preview({ preview: { port: 3000 } }); + page = await browser.newPage(); +}); + +afterAll(async () => { + await browser.close(); + await new Promise((resolve, reject) => { + server.httpServer.close((error) => (error ? reject(error) : resolve())); + }); +}); + +test( + 'add attrs', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery', 'data-test': 'test' }, + }); + }); + const jquery = await page.$('script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + const dataTest = await page.evaluate( + (script) => script?.dataset.test, + jquery, + ); + + expect(id).toBe('jquery'); + expect(dataTest).toBe('test'); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); + +test( + 'dom not add attrs', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + }); + }); + const jquery = await page.$('script'); + const jqueryWithId = await page.$('script#jquery'); + const nodeType = await page.evaluate( + (script) => script?.nodeType, + jquery, + ); + const nodeTypeWithId = await page.evaluate( + (script) => script?.nodeType, + jqueryWithId, + ); + + expect(nodeType).toBe(1); + expect(nodeTypeWithId).toBeUndefined(); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); diff --git a/test/basic.spec.ts b/test/basic.spec.ts index 5ced1d1..d2ee651 100644 --- a/test/basic.spec.ts +++ b/test/basic.spec.ts @@ -1,7 +1,8 @@ -import { afterAll, beforeAll, expect, test } from 'vitest'; +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; import { preview } from 'vite'; import type { PreviewServer } from 'vite'; import { Browser, Page, chromium } from 'playwright'; +import { TIMEOUT } from './constants'; // https://github.com/vitest-dev/vitest/blob/main/examples/puppeteer/test/basic.test.ts // https://gist.github.com/mizchi/5f67109d0719ef6dd57695e1f528ce8d @@ -23,54 +24,100 @@ afterAll(async () => { }); }); -// test('example stuff', async () => { -// try { -// await page.goto('http://localhost:3000'); -// const button = await page.$('#btn'); -// expect(button).toBeDefined(); +test( + 'proper load', + async () => { + try { + await page.goto('http://localhost:3000'); + const ref = await page.evaluate(async () => { + const scriptRef = await window.simpleLoadScript( + '//code.jquery.com/jquery-2.2.3.js', + ); + return scriptRef; + }); + expect(ref).toBeDefined(); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); -// let text = await page.evaluate((btn) => btn?.textContent, button); -// expect(text).toBe('Clicked 0 time(s)'); +test( + 'proper load config', + async () => { + try { + await page.goto('http://localhost:3000'); + const ref = await page.evaluate(async () => { + const scriptRef = await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + }); + return scriptRef; + }); + expect(ref).toBeDefined(); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); -// await button?.click(); -// text = await page.evaluate((btn) => btn?.textContent, button); -// expect(text).toBe('Clicked 1 time(s)'); -// } catch (err) { -// console.error(err); -// expect(err).toBeUndefined(); -// } -// }, 60_000); +test( + 'error wrong url', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript('//wrong.domain/jquery-2.2.3.js'); + }); + } catch (err) { + expect( + (err as Error).message.includes('Error: Loading script error'), + ).toBe(true); + } + }, + TIMEOUT, +); -test('proper load', async () => { - try { - await page.goto('http://localhost:3000'); - - const ref = await page.evaluate(async () => { - const scriptRef = await window.simpleLoadScript( - '//code.jquery.com/jquery-2.2.3.js', - ); - return scriptRef; - }); - - expect(ref).toBeDefined(); // HTMLScriptElement - } catch (err) { - expect(err).toBeUndefined(); - } -}, 60_000); - -test('error load', async () => { - try { - await page.goto('http://localhost:3000'); - - const ref = await page.evaluate(async () => { - const scriptRef = await window.simpleLoadScript( - '//wrong.domain/jquery-2.2.3.js', - ); - return scriptRef; - }); - - expect(ref).toBeDefined(); - } catch (err) { - expect((err as Error).message.includes('Error: Loading script')).toBe(true); - } -}, 60_000); +describe('error wrong config', () => { + test( + 'no param', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + // @ts-expect-error Testing wrong config + await window.simpleLoadScript(); + }); + } catch (err) { + expect( + (err as Error).message.includes( + 'Error: Object with url or url string needed', + ), + ).toBe(true); + } + }, + TIMEOUT, + ); + test( + 'bad config', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + // @ts-expect-error Testing wrong config + elo: '//code.jquery.com/jquery-2.2.3.js', + }); + }); + } catch (err) { + expect( + (err as Error).message.includes( + 'Error: Object with url or url string needed', + ), + ).toBe(true); + } + }, + TIMEOUT, + ); +}); diff --git a/test/constants.ts b/test/constants.ts new file mode 100644 index 0000000..3f6a0a3 --- /dev/null +++ b/test/constants.ts @@ -0,0 +1 @@ +export const TIMEOUT = 60_000; diff --git a/test/placement.spec.ts b/test/placement.spec.ts new file mode 100644 index 0000000..c852fb8 --- /dev/null +++ b/test/placement.spec.ts @@ -0,0 +1,108 @@ +import { afterAll, beforeAll, expect, test } from 'vitest'; +import { preview } from 'vite'; +import type { PreviewServer } from 'vite'; +import { Browser, Page, chromium } from 'playwright'; +import { TIMEOUT } from './constants'; + +let browser: Browser; +let server: PreviewServer; +let page: Page; + +beforeAll(async () => { + browser = await chromium.launch({ headless: true }); + server = await preview({ preview: { port: 3000 } }); + page = await browser.newPage(); +}); + +afterAll(async () => { + await browser.close(); + await new Promise((resolve, reject) => { + server.httpServer.close((error) => (error ? reject(error) : resolve())); + }); +}); + +test( + 'placement head', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery' }, + }); + }); + const jquery = await page.$('head script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + expect(id).toBe('jquery'); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); + +test( + 'placement body', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery' }, + inBody: true, + }); + }); + const jquery = await page.$('body script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + expect(id).toBe('jquery'); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); + +test( + 'insertInto ok', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery' }, + insertInto: '#insert', + }); + }); + const jquery = await page.$('#insert script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + expect(id).toBe('jquery'); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); + +test( + 'insertInto error', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery' }, + insertInto: '#insert1', + }); + }); + } catch (err) { + expect( + (err as Error).message.includes('No DOM element to append script'), + ).toBe(true); + } + }, + TIMEOUT, +); diff --git a/test/removeScript.spec.ts b/test/removeScript.spec.ts new file mode 100644 index 0000000..230a25f --- /dev/null +++ b/test/removeScript.spec.ts @@ -0,0 +1,70 @@ +import { afterAll, beforeAll, expect, test } from 'vitest'; +import { preview } from 'vite'; +import type { PreviewServer } from 'vite'; +import { Browser, Page, chromium } from 'playwright'; +import { TIMEOUT } from './constants'; + +let browser: Browser; +let server: PreviewServer; +let page: Page; + +beforeAll(async () => { + browser = await chromium.launch({ headless: true }); + server = await preview({ preview: { port: 3000 } }); + page = await browser.newPage(); +}); + +afterAll(async () => { + await browser.close(); + await new Promise((resolve, reject) => { + server.httpServer.close((error) => (error ? reject(error) : resolve())); + }); +}); + +test( + 'removeScript true', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + removeScript: true, + attrs: { id: 'jquery' }, + }); + }); + const jquery = await page.$('script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + const nodeType = await page.evaluate( + (script) => script?.nodeType, + jquery, + ); + expect(id).toBeUndefined(); + expect(nodeType).toBeUndefined(); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); + +test( + 'removeScript false', + async () => { + try { + await page.goto('http://localhost:3000'); + await page.evaluate(async () => { + await window.simpleLoadScript({ + url: '//code.jquery.com/jquery-2.2.3.js', + attrs: { id: 'jquery' }, + }); + }); + const jquery = await page.$('script#jquery'); + const id = await page.evaluate((script) => script?.id, jquery); + expect(id).toBe('jquery'); + } catch (err) { + expect(err).toBeUndefined(); + } + }, + TIMEOUT, +); diff --git a/vitest.config.ts b/vitest.config.ts index e514588..7fa5a55 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,10 +1,11 @@ /// import { UserConfigExport, defineConfig } from 'vite'; +import { TIMEOUT } from './test/constants'; export default defineConfig({ test: { - testTimeout: 60_000, - hookTimeout: 60_000, + testTimeout: TIMEOUT, + hookTimeout: TIMEOUT, }, }) satisfies UserConfigExport;