@tosspayments/sdk-loader
Advanced tools
Comparing version 1.2.1-alpha.3.0 to 2.0.0
@@ -1,1 +0,1 @@ | ||
export { loadScript, NamespaceNotAvailableError, ScriptLoadFailedError } from './loadScript'; | ||
export * from './loadScript'; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ScriptLoadFailedError = exports.NamespaceNotAvailableError = exports.loadScript = void 0; | ||
var loadScript_1 = require("./loadScript"); | ||
Object.defineProperty(exports, "loadScript", { enumerable: true, get: function () { return loadScript_1.loadScript; } }); | ||
Object.defineProperty(exports, "NamespaceNotAvailableError", { enumerable: true, get: function () { return loadScript_1.NamespaceNotAvailableError; } }); | ||
Object.defineProperty(exports, "ScriptLoadFailedError", { enumerable: true, get: function () { return loadScript_1.ScriptLoadFailedError; } }); | ||
__exportStar(require("./loadScript"), exports); |
@@ -5,8 +5,2 @@ interface LoadOptions { | ||
export declare function loadScript<Namespace>(src: string, namespace: string, options?: LoadOptions): Promise<Namespace>; | ||
export declare class NamespaceNotAvailableError extends Error { | ||
constructor(namespace: string); | ||
} | ||
export declare class ScriptLoadFailedError extends Error { | ||
constructor(src: string); | ||
} | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ScriptLoadFailedError = exports.NamespaceNotAvailableError = exports.loadScript = void 0; | ||
exports.loadScript = void 0; | ||
let cachedPromise = null; | ||
@@ -65,11 +65,2 @@ function loadScript(src, namespace, options = {}) { | ||
} | ||
// TODO: test용 유틸을 export 하는 대신 다른 방식을 사용해야함 | ||
// Test용 | ||
// export function clearCache() { | ||
// cachedPromise = null; | ||
// } | ||
// // Test용 | ||
// export function getCachedPromise() { | ||
// return cachedPromise; | ||
// } | ||
class NamespaceNotAvailableError extends Error { | ||
@@ -81,3 +72,2 @@ constructor(namespace) { | ||
} | ||
exports.NamespaceNotAvailableError = NamespaceNotAvailableError; | ||
class ScriptLoadFailedError extends Error { | ||
@@ -89,2 +79,1 @@ constructor(src) { | ||
} | ||
exports.ScriptLoadFailedError = ScriptLoadFailedError; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
@@ -13,35 +36,17 @@ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
const vitest_1 = require("vitest"); | ||
const loadScript_1 = require("./loadScript"); | ||
vitest_1.describe.todo('loadScript', () => { | ||
// NOTE: load, error 이벤트를 임의로 발생시키기 위해 이벤트 리스터를 모킹합니다 | ||
let eventListeners1; | ||
let eventListeners2; | ||
let script1; | ||
let script2; | ||
(0, vitest_1.beforeEach)(() => { | ||
(0, vitest_1.describe)('loadScript', () => { | ||
(0, vitest_1.afterEach)(() => { | ||
vitest_1.vi.resetModules(); | ||
delete window.TossPayments; | ||
document.head.innerHTML = ''; | ||
document.head.appendChild = vitest_1.vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
delete window.TossPayments; | ||
// 캐시 초기화 | ||
// clearCache(); | ||
eventListeners1 = {}; | ||
eventListeners2 = {}; | ||
script1 = document.createElement('script'); | ||
script2 = document.createElement('script'); | ||
script1.addEventListener = (event, listener) => { | ||
eventListeners1[event] = listener; | ||
}; | ||
script2.addEventListener = (event, listener) => { | ||
eventListeners2[event] = listener; | ||
}; | ||
vitest_1.vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script1) | ||
.mockReturnValueOnce(script2); | ||
}); | ||
(0, vitest_1.describe)('기본 동작', () => { | ||
(0, vitest_1.test)('script 로드가 완료되면, 주어진 namespace에 생성된 인스턴스와 동일한 인스턴스를 resolve 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/example.js', 'TossPayments'); | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
window.TossPayments = vitest_1.vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
@@ -51,15 +56,21 @@ (0, vitest_1.expect)(promise).resolves.toBe(window.TossPayments); | ||
(0, vitest_1.test)('script 로드를 실패하면, cachedPromise가 null로 설정되고 에러를 throw 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.error(new Event('error')); // script 로드가 실패함 | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
script.dispatchEvent(new Event('error')); // script 로드가 실패함 | ||
// then | ||
yield (0, vitest_1.expect)(promise).rejects.toThrowError('[TossPayments SDK] Failed to load script: [http://example.com/example.js]'); | ||
// expect(getCachedPromise()).toBeNull(); // TODO: 주석 살리기 | ||
const promise2 = (0, loadScript_1.loadScript)('http://example.com/example.js', 'TossPayments'); | ||
// 이전 promise의 제거 검증을 위해 재호출하고 promise 객체를 비교 | ||
const promise2 = loadScript('http://example.com/example.js', 'TossPayments'); | ||
(0, vitest_1.expect)(promise2).not.toBe(promise); | ||
})); | ||
(0, vitest_1.test)('script 로드를 성공했지만 namespace에 인스턴스가 존재하지 않으면, 에러를 throw 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
@@ -69,8 +80,11 @@ (0, vitest_1.expect)(promise).rejects.toThrowError('[TossPayments SDK] TossPayments is not available'); | ||
(0, vitest_1.test)('priority 옵션을 설정하면, script element의 fetchPriority 속성이 설정되어야 한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/example.js', 'TossPayments', { priority: 'high' }); | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments', { priority: 'high' }); | ||
window.TossPayments = vitest_1.vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
(0, vitest_1.expect)(script1.fetchPriority).toBe('high'); | ||
(0, vitest_1.expect)(script.fetchPriority).toBe('high'); | ||
yield (0, vitest_1.expect)(promise).resolves.toBe(window.TossPayments); | ||
@@ -81,7 +95,10 @@ })); | ||
(0, vitest_1.test)('해당 Promise를 반환해야 한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise1 = (0, loadScript_1.loadScript)('http://example.com/script.js', 'TossPayments'); | ||
const promise1 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
window.TossPayments = vitest_1.vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
const promise2 = (0, loadScript_1.loadScript)('http://example.com/script.js', 'TossPayments'); | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
const promise2 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
// then | ||
@@ -94,2 +111,3 @@ (0, vitest_1.expect)(promise1).toBe(promise2); | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
const originalWindow = window; | ||
@@ -100,3 +118,3 @@ const originalDocument = document; | ||
// when | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/script.js', 'TossPayments'); | ||
const promise = loadScript('http://example.com/script.js', 'TossPayments'); | ||
// then | ||
@@ -108,5 +126,7 @@ (0, vitest_1.expect)(promise).resolves.toBeNull(); | ||
(0, vitest_1.test)('주어진 namespace에 인스턴스가 존재하면, 해당 인스턴스를 resolve 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield Promise.resolve().then(() => __importStar(require('./loadScript'))); | ||
// when | ||
window.TossPayments = vitest_1.vi.fn(); | ||
const promise = (0, loadScript_1.loadScript)('http://example.com/script.js', 'TossPayments'); | ||
const promise = loadScript('http://example.com/script.js', 'TossPayments'); | ||
// then | ||
@@ -118,1 +138,8 @@ (0, vitest_1.expect)(promise).resolves.toBe(window.TossPayments); | ||
}); | ||
function mockScriptElement() { | ||
document.head.appendChild = vitest_1.vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
const script = document.createElement('script'); | ||
vitest_1.vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script); | ||
return { script }; | ||
} |
@@ -1,1 +0,1 @@ | ||
export { loadScript, NamespaceNotAvailableError, ScriptLoadFailedError } from './loadScript'; | ||
export * from './loadScript'; |
@@ -1,1 +0,1 @@ | ||
export { loadScript, NamespaceNotAvailableError, ScriptLoadFailedError } from './loadScript'; | ||
export * from './loadScript'; |
@@ -5,8 +5,2 @@ interface LoadOptions { | ||
export declare function loadScript<Namespace>(src: string, namespace: string, options?: LoadOptions): Promise<Namespace>; | ||
export declare class NamespaceNotAvailableError extends Error { | ||
constructor(namespace: string); | ||
} | ||
export declare class ScriptLoadFailedError extends Error { | ||
constructor(src: string); | ||
} | ||
export {}; |
@@ -61,12 +61,3 @@ let cachedPromise = null; | ||
} | ||
// TODO: test용 유틸을 export 하는 대신 다른 방식을 사용해야함 | ||
// Test용 | ||
// export function clearCache() { | ||
// cachedPromise = null; | ||
// } | ||
// // Test용 | ||
// export function getCachedPromise() { | ||
// return cachedPromise; | ||
// } | ||
export class NamespaceNotAvailableError extends Error { | ||
class NamespaceNotAvailableError extends Error { | ||
constructor(namespace) { | ||
@@ -77,3 +68,3 @@ super(`[TossPayments SDK] ${namespace} is not available`); | ||
} | ||
export class ScriptLoadFailedError extends Error { | ||
class ScriptLoadFailedError extends Error { | ||
constructor(src) { | ||
@@ -80,0 +71,0 @@ super(`[TossPayments SDK] Failed to load script: [${src}]`); |
@@ -10,36 +10,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
}; | ||
import { beforeEach, describe, expect, test, vi } from 'vitest'; | ||
import { loadScript } from './loadScript'; | ||
describe.todo('loadScript', () => { | ||
// NOTE: load, error 이벤트를 임의로 발생시키기 위해 이벤트 리스터를 모킹합니다 | ||
let eventListeners1; | ||
let eventListeners2; | ||
let script1; | ||
let script2; | ||
beforeEach(() => { | ||
import { afterEach, describe, expect, test, vi } from 'vitest'; | ||
describe('loadScript', () => { | ||
afterEach(() => { | ||
vi.resetModules(); | ||
delete window.TossPayments; | ||
document.head.innerHTML = ''; | ||
document.head.appendChild = vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
delete window.TossPayments; | ||
// 캐시 초기화 | ||
// clearCache(); | ||
eventListeners1 = {}; | ||
eventListeners2 = {}; | ||
script1 = document.createElement('script'); | ||
script2 = document.createElement('script'); | ||
script1.addEventListener = (event, listener) => { | ||
eventListeners1[event] = listener; | ||
}; | ||
script2.addEventListener = (event, listener) => { | ||
eventListeners2[event] = listener; | ||
}; | ||
vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script1) | ||
.mockReturnValueOnce(script2); | ||
}); | ||
describe('기본 동작', () => { | ||
test('script 로드가 완료되면, 주어진 namespace에 생성된 인스턴스와 동일한 인스턴스를 resolve 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
@@ -49,8 +31,11 @@ expect(promise).resolves.toBe(window.TossPayments); | ||
test('script 로드를 실패하면, cachedPromise가 null로 설정되고 에러를 throw 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.error(new Event('error')); // script 로드가 실패함 | ||
script.dispatchEvent(new Event('error')); // script 로드가 실패함 | ||
// then | ||
yield expect(promise).rejects.toThrowError('[TossPayments SDK] Failed to load script: [http://example.com/example.js]'); | ||
// expect(getCachedPromise()).toBeNull(); // TODO: 주석 살리기 | ||
// 이전 promise의 제거 검증을 위해 재호출하고 promise 객체를 비교 | ||
const promise2 = loadScript('http://example.com/example.js', 'TossPayments'); | ||
@@ -60,5 +45,8 @@ expect(promise2).not.toBe(promise); | ||
test('script 로드를 성공했지만 namespace에 인스턴스가 존재하지 않으면, 에러를 throw 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
@@ -68,8 +56,11 @@ expect(promise).rejects.toThrowError('[TossPayments SDK] TossPayments is not available'); | ||
test('priority 옵션을 설정하면, script element의 fetchPriority 속성이 설정되어야 한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments', { priority: 'high' }); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
expect(script1.fetchPriority).toBe('high'); | ||
expect(script.fetchPriority).toBe('high'); | ||
yield expect(promise).resolves.toBe(window.TossPayments); | ||
@@ -80,6 +71,9 @@ })); | ||
test('해당 Promise를 반환해야 한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise1 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
const promise2 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
@@ -93,2 +87,3 @@ // then | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
const originalWindow = window; | ||
@@ -106,2 +101,4 @@ const originalDocument = document; | ||
test('주어진 namespace에 인스턴스가 존재하면, 해당 인스턴스를 resolve 해야한다', () => __awaiter(void 0, void 0, void 0, function* () { | ||
// given | ||
const { loadScript } = yield import('./loadScript'); | ||
// when | ||
@@ -116,1 +113,8 @@ window.TossPayments = vi.fn(); | ||
}); | ||
function mockScriptElement() { | ||
document.head.appendChild = vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
const script = document.createElement('script'); | ||
vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script); | ||
return { script }; | ||
} |
{ | ||
"name": "@tosspayments/sdk-loader", | ||
"description": "JavaScript SDK Loader by <script> tag injection", | ||
"version": "1.2.1-alpha.3.0", | ||
"version": "2.0.0", | ||
"main": "dist/index.js", | ||
@@ -25,4 +25,4 @@ "publishConfig": { | ||
}, | ||
"gitHead": "c558cf206d744750971a2323308b024ff120809a", | ||
"gitHead": "3b92018d70af028b11f55a9e03f771ceb5bd9dab", | ||
"module": "esm/index.js" | ||
} |
@@ -1,1 +0,1 @@ | ||
export { loadScript, NamespaceNotAvailableError, ScriptLoadFailedError } from './loadScript' | ||
export * from './loadScript' |
@@ -1,3 +0,2 @@ | ||
import { beforeEach, describe, expect, test, vi } from 'vitest'; | ||
import { loadScript } from './loadScript'; | ||
import { afterEach, describe, expect, test, vi } from 'vitest'; | ||
@@ -10,36 +9,9 @@ declare global { | ||
describe.todo('loadScript', () => { | ||
// NOTE: load, error 이벤트를 임의로 발생시키기 위해 이벤트 리스터를 모킹합니다 | ||
let eventListeners1: { [key: string]: EventListener }; | ||
let eventListeners2: { [key: string]: EventListener }; | ||
describe('loadScript', () => { | ||
afterEach(() => { | ||
vi.resetModules(); | ||
let script1: HTMLScriptElement; | ||
let script2: HTMLScriptElement; | ||
delete window.TossPayments; | ||
beforeEach(() => { | ||
document.head.innerHTML = ''; | ||
document.head.appendChild = vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
delete window.TossPayments; | ||
// 캐시 초기화 | ||
// clearCache(); | ||
eventListeners1 = {}; | ||
eventListeners2 = {}; | ||
script1 = document.createElement('script'); | ||
script2 = document.createElement('script'); | ||
script1.addEventListener = (event: string, listener: EventListener) => { | ||
eventListeners1[event] = listener; | ||
}; | ||
script2.addEventListener = (event: string, listener: EventListener) => { | ||
eventListeners2[event] = listener; | ||
}; | ||
vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script1) | ||
.mockReturnValueOnce(script2); | ||
}); | ||
@@ -49,6 +21,11 @@ | ||
test('script 로드가 완료되면, 주어진 namespace에 생성된 인스턴스와 동일한 인스턴스를 resolve 해야한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
@@ -59,10 +36,14 @@ // then | ||
test('script 로드를 실패하면, cachedPromise가 null로 설정되고 에러를 throw 해야한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.error(new Event('error')); // script 로드가 실패함 | ||
script.dispatchEvent(new Event('error')); // script 로드가 실패함 | ||
// then | ||
await expect(promise).rejects.toThrowError('[TossPayments SDK] Failed to load script: [http://example.com/example.js]'); | ||
// expect(getCachedPromise()).toBeNull(); // TODO: 주석 살리기 | ||
// 이전 promise의 제거 검증을 위해 재호출하고 promise 객체를 비교 | ||
const promise2 = loadScript('http://example.com/example.js', 'TossPayments'); | ||
@@ -73,5 +54,9 @@ expect(promise2).not.toBe(promise); | ||
test('script 로드를 성공했지만 namespace에 인스턴스가 존재하지 않으면, 에러를 throw 해야한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments'); | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
@@ -82,9 +67,13 @@ // then | ||
test('priority 옵션을 설정하면, script element의 fetchPriority 속성이 설정되어야 한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise = loadScript('http://example.com/example.js', 'TossPayments', { priority: 'high' }); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
// then | ||
expect((script1 as any).fetchPriority).toBe('high'); | ||
expect((script as any).fetchPriority).toBe('high'); | ||
await expect(promise).resolves.toBe(window.TossPayments); | ||
@@ -96,6 +85,11 @@ }); | ||
test('해당 Promise를 반환해야 한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const { script } = mockScriptElement(); | ||
// when | ||
const promise1 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
window.TossPayments = vi.fn(); // SDK는 주어진 namespace에 인스턴스를 생성함 | ||
eventListeners1.load(new Event('load')); // script 로드가 완료됨 | ||
script.dispatchEvent(new Event('load')); // script 로드가 완료됨 | ||
@@ -112,2 +106,4 @@ const promise2 = loadScript('http://example.com/script.js', 'TossPayments'); | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
const originalWindow = window; | ||
@@ -128,2 +124,5 @@ const originalDocument = document; | ||
test('주어진 namespace에 인스턴스가 존재하면, 해당 인스턴스를 resolve 해야한다', async () => { | ||
// given | ||
const { loadScript } = await import('./loadScript'); | ||
// when | ||
@@ -138,2 +137,13 @@ window.TossPayments = vi.fn(); | ||
}); | ||
}); | ||
}); | ||
function mockScriptElement() { | ||
document.head.appendChild = vi.fn(); // NOTE: 테스트 환경에서 script inject 방지 | ||
const script = document.createElement('script'); | ||
vi.spyOn(document, 'createElement') | ||
.mockReturnValueOnce(script); | ||
return { script }; | ||
} |
@@ -75,14 +75,3 @@ let cachedPromise: Promise<any> | null = null; | ||
// TODO: test용 유틸을 export 하는 대신 다른 방식을 사용해야함 | ||
// Test용 | ||
// export function clearCache() { | ||
// cachedPromise = null; | ||
// } | ||
// // Test용 | ||
// export function getCachedPromise() { | ||
// return cachedPromise; | ||
// } | ||
export class NamespaceNotAvailableError extends Error { | ||
class NamespaceNotAvailableError extends Error { | ||
constructor(namespace: string) { | ||
@@ -94,3 +83,3 @@ super(`[TossPayments SDK] ${namespace} is not available`); | ||
export class ScriptLoadFailedError extends Error { | ||
class ScriptLoadFailedError extends Error { | ||
constructor(src: string) { | ||
@@ -97,0 +86,0 @@ super(`[TossPayments SDK] Failed to load script: [${src}]`); |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
33382
691
1