๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐ŸŒˆ Chapter 11: ์ƒŒ๋“œ๋ฐ•์Šค ํŒจํ„ด

๐Ÿ“š ๋‹จ์œ„ ํ…Œ์ŠคํŠธโ€‹

์š”๊ตฌ์‚ฌํ•ญ: ์ฝ˜ํผ๋Ÿฐ์Šค ํ–‰์‚ฌ์˜ ์ „๋ฐ˜์ ์ธ ์ง„ํ–‰ ์ƒํ™ฉ๊ณผ ์›น ์‚ฌ์ดํŠธ ์šด์˜ ์‹คํƒœ๋ฅผ ํ•œ๋ˆˆ์— ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š” ๋Œ€์‹œ๋ณด๋“œ๊ฐ€ ์žˆ์—ˆ์œผ๋ฉด ์ข‹๊ณ˜๋‹ค๊ณ  ์ฃผ์ตœ ๋‹ด๋‹น์ž๋Š” ๋งํ•œ๋‹ค.
ํ•ญ๋ชฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ฝ˜ํผ๋Ÿฐ์Šค ๋“ฑ๋ก์ž ์ˆ˜
  • ์ฝ˜ํผ๋Ÿฐ์Šค ๋“ฑ๋ก์ž ์„ฑ๋ช…
  • ์ฒดํฌ์ธํ•œ ์ฐธ๊ฐ€์ž ์ˆ˜
  • ์ฒดํฌ์ธํ•œ ์ฐธ๊ฐ€์ž ์„ฑ๋ช…
  • ์„œ๋“œํŒŒํ‹ฐ ์‹์žฅ API์˜ ํ˜ธ์ถœ ํšŸ์ˆ˜
  • ์ง€์—ญ ๊ณตํ•ญ ๊ธฐ์ƒ ์˜ˆ๋ณด

๐ŸŽˆ ์œ„์ ฏ ์ƒŒ๋“œ๋ฐ•์Šค ๋งŒ๋“ค๊ธฐโ€‹

์œ„์ ฏ ์ƒŒ๋“œ๋ฐ•์Šค์˜ ๋ชฉ์ ์€ ๊ฐ ์œ„์ ฏ์„ ๋ถ„๋ฆฌํ•˜์—ฌ ์•Œ์•„์„œ ์›€์ง์ด๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒŒ๋“œ๋ฐ•์Šค ํŒจํ„ด์„ ์ด์šฉํ•˜๋ฉด ์œ„์ ฏ๋งˆ๋‹ค ํ•œ์ •๋œ ์˜์กด์„ฑ ์„ ๋ฌผ ์„ธํŠธ๋ฅผ ์ฆ์ •ํ•˜์—ฌ ๊ฐ์ž ์ž„๋ฌด๋ฅผ ์™„์ˆ˜ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋„๊ตฌ๋ฅผ ๊ณต์ˆ˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„์ ฏ ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”โ€‹

WidgetSandbox ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋Š” new ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ , ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์ธ์ž, ์ฆ‰ ์ƒŒ๋“œ๋ฐ•์Šค์— ๊ฒฉ๋ฆฌํ•  ์œ„์ ฏ ์ƒ์„ฑ ํ•จ์ˆ˜๋ฅผ ๋ฐ›๋„๋ก ์ž‘์„ฑํ•œ๋‹ค. ๋จผ์ €, ๊ธฐ๋Šฅ ์ •๊ฒ€์šฉ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค.

describe('Conference.WidgetSandbox', () => {
'use strict';

describe('์ƒ์„ฑ์ž ํ•จ์ˆ˜', () => {
it('"new" ํ‚ค์›Œ๋“œ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
expect(function shouldThrow() {
var sandbox = Conference.WidgetSandbox();
}).toThrowError(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
});

it('์œ„์ ฏ ํ•จ์ˆ˜๊ฐ€ ๋ˆ„๋ฝ๋˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
[null, undefined, 1, 'SomeString', false].forEach(function testInvalid(notAFcn) {
expect(function shouldThrow() {
var sandbox = new Conference.WidgetSandbox(notAFcn);
}).toThrowError(Conference.WidgetSandbox.messages.fcnMustBeProvided);
});
});

it('sandbox๋ฅผ ์ธ์ž๋กœ ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค', () => {
var widgetFcn = jasmine.createSpy();
var sandbox = new Conference.WidgetSandbox(widgetFcn);

expect(widgetFcn).toHaveBeenCalledWith(sandbox);
});
});
});

WidgetSandbox ๊ตฌํ˜„๋ถ€๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

var Conference = Conference || {};

Conference.WidgetSandbox = function() {
'use strict';

// Conference.WidgetSandbox(...)๋ฅผ new๋กœ ์‹คํ–‰ํ–ˆ๋Š”์ง€ ๋ณด์žฅํ•œ๋‹ค.
if (!(this instanceof Conference.WidgetSandbox)) {
throw new Error(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
}

var widgetFunction = arguments[0];

if (typeof widgetFunction !== 'function') {
throw new Error(Conference.WidgetSandbox.messages.fcnMustBeProvided);
}

widgetFunction(this);
};

Conference.WidgetSandbox.messages = {
mustBeCalledWithNew: 'WidgetSandbox ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ new๋กœ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค',
fcnMustBeProvided: '์œ„์ ฏ ํ•จ์ˆ˜๋Š” ํ•„์ˆ˜ ์ž…๋ ฅ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค',
};

์ƒŒ๋“œ๋ฐ•์Šค๋กœ ์œ„์ ฏ์— ๋„๊ตฌ๋ฅผ ์ œ๊ณตโ€‹

WidgetSandbox์˜ ๋ชฉํ‘œ๋Š” ๋Œ€์‹œ๋ณด๋“œ ์œ„์ ฏ ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ๋–ผ์–ด๋†“๋Š” ์ผ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ DOM ์กฐ์ž‘, ๋˜๋Š” ์›น ์„œ๋น„์Šค๋ฅผ ์ด์šฉํ•œ ๋ฐ์ดํ„ฐ ์กฐํšŒ ๊ฐ™์€ ๊ธฐ๋Šฅ์ด ์•ˆ ๋œ๋‹ค๋ฉด ์•„๋ฌด๋Ÿฐ ์“ธ๋ชจ๊ฐ€ ์—†๋‹ค.

์–ด๋–ค ์œ„์ ฏ์—์„œ ์–ด๋–ค ๋„๊ตฌ๊ฐ€ ํ•„์š”ํ•œ์ง€ ์•Œ๊ณ  ์žˆ์œผ๋ฉด ๋˜๋ฏ€๋กœ ๋„๊ตฌ ์„ธํŠธ๋ฅผ ๊ณ ์ •ํ•˜์ง€ ๋ง๊ณ  ์ƒˆ ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ WidgetSandbox ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๋Š” ํŽธ์ด ๋‚ซ๋‹ค๊ณ  ํŒ๋‹จํ•œ๋‹ค. ๋˜ํ•œ, ์œ„์ ฏ๋งˆ๋‹ค ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋„๊ตฌ๋ฅผ ์ œํ•œํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์›น ์„œ๋น„์Šค ์—ฐ๋™์ด ์ „ํ˜€ ํ•„์š” ์—†๋Š” ์œ„์ ฏ์— ๊ตณ์ด AJAX ํ†ต์‹  ๊ด€๋ จ ๋„๊ตฌ์— ์ ‘๊ทผํ•  ๊ถŒํ•œ์„ ์ค„ ์ด์œ ๋Š” ์—†๋‹ค.

์œ„์™€ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „์— ๊ฒฐ์ •ํ•ด์•ผ ํ•  ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

  1. ๋„๊ตฌ๋Š” ์–ด๋””์— ์ •์˜ํ•˜๋‚˜?
    • Conference.WidgetTools ์ด๋ฆ„๊ณต๊ฐ„ ๋‚ด์— ๋„๊ตฌ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒŒ ๋งž๋‹ค.
  2. ๋„๊ตฌ๋ฅผ ์–ด๋–ป๊ฒŒ WidgetSandbox ์ธ์Šคํ„ด์Šค์— ์ถ”๊ฐ€ํ•˜๋‚˜?
    • ๋„๊ตฌ๋ฅผ ๋ชจ๋“ˆ๋กœ ์ •์˜ํ•˜๋ฉด ๋„๊ตฌ๋งˆ๋‹ค ๋ชจ๋“ˆ ํ•จ์ˆ˜๊ฐ€ WidgetSandbox ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ›๊ณ , ๋‹ค์Œ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋„๊ตฌ๊ฐ€ ์Šค์Šค๋กœ๋ฅผ WidgetSandbox ํ”„๋กœํผํ‹ฐ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
Conference.WidgetTools.toolA = function(sandbox) {
// toolA๋ฅผ sandbox์— ์ถ”๊ฐ€ํ•œ๋‹ค.
sandbox.toolA = {
function1: function() {
// function1 ๊ตฌํ˜„๋ถ€
},
function2: function() {
// function2 ๊ตฌํ˜„๋ถ€
},
};
};
  1. WidgetSandbox ์ƒ์„ฑ์ž๋Š” ๋‹ค์Œ ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ฐ›๋Š”๋‹ค.
    • ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋Š” ์œ„์ ฏ์—์„œ ์“ธ ๋„๊ตฌ๋ช…์ด ๋‹ด๊ธด ๋ฐฐ์—ด, ๋‘ ๋ฒˆ์งธ ์ธ์ž๋Š” ์œ„์ ฏ ํ•จ์ˆ˜๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.
    var weatherSandbox = new Conference.WidgetSandbox(
    ['toolA', 'toolB'],
    Conference.widgets.weatherWidget,
    );
    • ๋„๊ตฌ๋ช…์  ๊ฐœ๋ณ„ ์ธ์ž๋กœ ๋‚˜์—ดํ•˜๊ณ  ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์ œ์ผ ๋งˆ์ง€๋ง‰ ์ธ์ž์— ๋„ฃ๋Š”๋‹ค.
    var weatherSandbox = new Conference.WidgetSandbox(
    'toolA', 'toolB', Conference.widgets.weatherWidget,
    );

์–ด๋Š ์ชฝ์ด๋“  WidgetSandbox ์ƒ์„ฑ์ž์— ๋„๊ตฌ๋ช… ๋ชฉ๋ก์„ ๊ฑด๋„ค์ฃผ๋ฉด ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์ œ๋Œ€๋กœ ์ฐพ๋Š”์ง€๋ถ€ํ„ฐ ํ™•์ธํ•˜์ž.

describe('Conference.WidgetSandbox', () => {
'use strict';

describe('์ƒ์„ฑ์ž ํ•จ์ˆ˜', () => {
it('"new" ํ‚ค์›Œ๋“œ๋กœ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
expect(function shouldThrow() {
var sandbox = Conference.WidgetSandbox();
}).toThrowError(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
});

describe('new WidgetSandbox(toolsArray, widgetModule)', () => {
// ๋„๊ตฌ ๋ชฉ๋ก์„ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋„˜๊ฒผ์„ ๋•Œ ์ž‘๋™ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

it('์œ„์ ฏ ํ•จ์ˆ˜๊ฐ€ ๋ˆ„๋ฝ๋˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
[null, undefined, 1, 'SomeString', false].forEach(function testInvalid(val) {
expect(function shouldThrow() {
var sandbox = new Conference.WidgetSandbox(['tool1', 'tool2'], val);
}).toThrowError(Conference.WidgetSandbox.messages.fcnMustBeProvided);
});
});

it('sandbox๋ฅผ ์ธ์ž๋กœ ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค', () => {
var widgetFcn = jasmine.createSpy();
var sandbox = new Conference.WidgetSandbox(['too1', 'too2'], widgetFcn);

expect(widgetFcn).toHaveBeenCalledWith(sandbox);
});
});

describe("new WidgetSandbox('too1', ..., 'toolN', widgetModule)", () => {
// ๋„๊ตฌ ๋ชฉ๋ก์„ ๊ฐœ๋ณ„ ์ธ์ž ํ˜•ํƒœ๋กœ ๋„˜๊ฒผ์„ ๋•Œ ์ž‘๋™ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

it('์œ„์ ฏ ํ•จ์ˆ˜๊ฐ€ ๋ˆ„๋ฝ๋˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
[null, undefined, 1, 'SomeString', false].forEach(function testInvalid(val) {
expect(function shouldThrow() {
var sandbox = new Conference.WidgetSandbox('tool1', 'tool2', val);
}).toThrowError(Conference.WidgetSandbox.messages.fcnMustBeProvided);
});
});

it('sandbox๋ฅผ ์ธ์ž๋กœ ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค', () => {
var widgetFcn = jasmine.createSpy();
var sandbox = new Conference.WidgetSandbox('too1', 'too2', widgetFcn);

expect(widgetFcn).toHaveBeenCalledWith(sandbox);
});
});
});
});

์ด์ œ ์œ„์ ฏ ํ•จ์ˆ˜๋ฅผ ์ •ํ™•ํžˆ ๊ณจ๋ผ๋‚ด๋„๋ก WidgetSandbox ๊ตฌํ˜„๋ถ€๋ฅผ ์ˆ˜์ •ํ•˜์ž. WidgetTools ์ด๋ฆ„๊ณต๊ฐ„์€ ์ผ๋‹จ ๋นˆ ๊ฐ์ฒด๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

var Conference = Conference || {};

Conference.WidgetSandbox = function() {
'use strict';

// Conference.WidgetSandbox(...)๋ฅผ new๋กœ ์‹คํ–‰ํ–ˆ๋Š”์ง€ ๋ณด์žฅํ•œ๋‹ค.
if (!(this instanceof Conference.WidgetSandbox)) {
throw new Error(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
}

var widgetFunction = arguments[arguments.length - 1];

if (typeof widgetFunction !== 'function') {
throw new Error(Conference.WidgetSandbox.messages.fcnMustBeProvided);
}

widgetFunction(this);
};

// ๋นˆ ๋„๊ตฌ ์ด๋ฆ„๊ณต๊ฐ„์„ ์ƒ์„ฑํ•œ๋‹ค.
Conference.WidgetTools = {};

Conference.WidgetSandbox.messages = {
mustBeCalledWithNew: 'WidgetSandbox ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ new๋กœ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค',
fcnMustBeProvided: '์œ„์ ฏ ํ•จ์ˆ˜๋Š” ํ•„์ˆ˜ ์ž…๋ ฅ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค',
};

๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๋ชจ๋‘ ์„ฑ๊ณตํ•œ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„๋Š” WidgetSandbox ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์ „๋‹ฌํ•œ ๋„๊ตฌ๋ช…์—์„œ ๋„๊ตฌ ๋ชจ๋“ˆ ํ•จ์ˆ˜๋ฅผ ์ฐพ์•„ ๋„๊ตฌ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ผ์ด๋‹ค. ๋จผ์ € ๋„๊ตฌ๋ช… ๋ชฉ๋ก์„ ๋ฐฐ์—ด๋กœ ๋„˜๊ธฐ๋Š” ํ˜•ํƒœ๋ฅผ ํ•ด๋ณธ๋‹ค. ์ „๋‹ฌ๋œ ๋„๊ตฌ๋ช…์€ ๊ฐ๊ฐ Conference.WidgetTools ํ”„๋กœํผํ‹ฐ์— ๋Œ€์‘๋œ๋‹ค. ์ด ์ด๋ฆ„๊ณต๊ฐ„์— ๋„๊ตฌ๋ช…์— ํ•ด๋‹นํ•˜๋Š” ํ”„๋กœํผํ‹ฐ๊ฐ€ ์—†์œผ๋ฉด ๋ฉ”์‹œ์ง€๋งŒ ๋ด๋„ ์˜๋ฏธ๊ฐ€ ๋ถ„๋ช…ํ•œ ์—๋Ÿฌ๋ฅผ ๋˜์ ธ์•ผ ํ•œ๋‹ค.

๋„๊ตฌ๋ช…์ด ์œ ํšจํ•œ ๋„๊ตฌ๋ช… WidgetSandbox ์ธ์Šคํ„ด์Šค๋ฅผ ์œ ์ผํ•œ ์ธ์ž๋กœ ํ•ด๋‹น ๋„๊ตฌ ๋ชจ๋“ˆ ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋  ๊ฒƒ์ด๋‹ค.

describe('Conference.WidgetSandbox', () => {
'use strict';

describe('์ƒ์„ฑ์ž ํ•จ์ˆ˜', () => {
var widgetFcnSpy;

beforeEach(() => {
// ํ…Œ์ŠคํŠธ๊ฐ€ ์‹ค์ œ ๋„๊ตฌ์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๊ฒŒ ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
Conference.WidgetTools.tool1 = function(sandbox) {
return {};
};
Conference.WidgetTools.tool2 = function(sandbox) {
return {};
};

// ์œ„์ ฏ ํ•จ์ˆ˜ ์—ญํ• ์€ ๋Œ€์‹ ํ•  ์ŠคํŒŒ์ด๋ฅผ ๋งŒ๋“ ๋‹ค.
widgetFcnSpy = jasmine.createSpy();
});

afterEach(() => {
// ํ…Œ์ŠคํŠธ ๋„๊ตฌ๋ฅผ ์‚ญ์ œํ•œ๋‹ค.
delete Conference.WidgetTools.tool1;
delete Conference.WidgetTools.tool2;
});

/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/

describe('new WidgetSandbox(toolsArray, widgetFnc)', () => {
// ๋„๊ตฌ ๋ชฉ๋ก์„ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋„˜๊ฒผ์„ ๋•Œ ์ž‘๋™ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/

it('์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ๋„๊ตฌ๋ฅผ ์ง€์ •ํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
var badTool = 'badTool';

expect(function shouldThrow() {
var sandbox = new Conference.WidgetSandbox(['tool1', badTool], widgetFcnSpy);
}).toThrowError(Conference.WidgetSandbox.messages.unknownTool + badTool);
});

it('๋„๊ตฌ ๋ชจ๋“ˆ ํ•จ์ˆ˜๋ฅผ sandbox์—์„œ ์‹คํ–‰ํ•œ๋‹ค', () => {
spyOn(Conference.WidgetTools, 'tool1');
spyOn(Conference.WidgetTools, 'tool2');

var sandbox = new Conference.WidgetSandbox(['tool1', 'tool2'], widgetFcnSpy);

expect(Conference.WidgetTools.tool1).toHaveBeenCalledWith(sandbox);
expect(Conference.WidgetTools.tool2).toHaveBeenCalledWith(sandbox);
});
});

describe("new WidgetSandbox('tool1', ..., 'toolN', widgetFcn)", () => {
/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/
});
});
});

๋‹ค์Œ๊ณผ ๊ฐ™์ด WidgetSandbox๋ฅผ ์ˆ˜์ •ํ•˜๋ฉด ์œ„ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์„ฑ๊ณตํ•œ๋‹ค.

var Conference = Conference || {};

Conference.WidgetSandbox = function() {
'use strict';

// Conference.WidgetSandbox(...)๋ฅผ new๋กœ ์‹คํ–‰ํ–ˆ๋Š”์ง€ ๋ณด์žฅํ•œ๋‹ค.
if (!(this instanceof Conference.WidgetSandbox)) {
throw new Error(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
}

var widgetFunction = arguments[arguments.length - 1];
var toolsToLoad = [];

if (typeof widgetFunction !== 'function') {
throw new Error(Conference.WidgetSandbox.messages.fcnMustBeProvided);
}

if (arguments[0] instanceof Array) {
toolsToLoad = arguments[0];
}

toolsToLoad.forEach(function loadTool(toolName) {
if (!Conference.WidgetTools.hasOwnProperty(toolName)) {
throw new Error(Conference.WidgetSandbox.messages.unKnownTool + toolName);
}

Conference.WidgetTools[toolName](this);
}, this); // ์ฝœ๋ฐฑ ๋‚ด์—์„œ this๊ฐ€ sandbox ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

widgetFunction(this);
};

// ๋นˆ ๋„๊ตฌ ์ด๋ฆ„๊ณต๊ฐ„์„ ์ƒ์„ฑํ•œ๋‹ค.
Conference.WidgetTools = {};

Conference.WidgetSandbox.messages = {
mustBeCalledWithNew: 'WidgetSandbox ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ new๋กœ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค',
fcnMustBeProvided: '์œ„์ ฏ ํ•จ์ˆ˜๋Š” ํ•„์ˆ˜ ์ž…๋ ฅ ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค',
unknownTool: '์•Œ ์ˆ˜ ์—†๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค',
};

์ด์ œ ๋งˆ์ง€๋ง‰์œผ๋กœ ์—ฌ๋Ÿฌ ๋„๊ตฌ๋ช…์„ ๊ฐœ๋ณ„ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋‚จ์•˜๋‹ค. ๋ฐฐ์—ด ์ผ€์ด์Šค์™€ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ๊ฑฐ์˜ ๊ฐ™์ง€๋งŒ, ์ง€๊ธˆ์€ ์‹คํŒจํ•œ๋‹ค.

describe('Conference.WidgetSandbox', () => {
'use strict';

describe('์ƒ์„ฑ์ž ํ•จ์ˆ˜', () => {
var widgetFcnSpy;

/** ์ด์ „ beforeEach/afterEach ๋ธ”๋ก์„ ์ค„์ž„ **/

/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/

describe('new WidgetSandbox(toolsArray, widgetFcn)', () => {
// ๋„๊ตฌ ๋ชฉ๋ก์„ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ๋„˜๊ฒผ์„ ๋•Œ ์ž‘๋™ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/
});


describe("new WidgetSandbox('tool1', ..., 'toolN', widgetFcn)", () => {
// ๋„๊ตฌ ๋ชฉ๋ก์„ ๊ฐœ๋ณ„ ์ธ์ž ํ˜•ํƒœ๋กœ ๋„˜๊ฒผ์„ ๋•Œ ์ž‘๋™ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธ

/** ์ด์ „ ํ…Œ์ŠคํŠธ ์ค„์ž„ **/

it('์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์€ ๋„๊ตฌ๋ฅผ ์ง€์ •ํ•˜๋ฉด ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค', () => {
var badTool = 'badTool';

expect(function shouldThrow() {
var sandbox = new Conference.WidgetSandbox('tool1', badTool, widgetFcnSpy);
}).toThrowError(Conference.WidgetSandbox.messages.unknownTool + badTool);
});

it('๋„๊ตฌ ๋ชจ๋“ˆ ํ•จ์ˆ˜๋ฅผ sandbox์—์„œ ์‹คํ–‰ํ•œ๋‹ค', () => {
spyOn(Conference.WidgetTools, 'tool1');
spyOn(Conference.WidgetTools, 'tool2');

var sandbox = new Conference.WidgetSandbox('tool1', 'tool2', widgetFcnSpy);

expect(Conference.WidgetTools.tool1).toHaveBeenCalledWith(sandbox);
expect(Conference.WidgetTools.tool2).toHaveBeenCalledWith(sandbox);
});
});
});
});

์ด์ œ ๋‹ค์Œ์ฒ˜๋Ÿผ WidgetSandbox ์ƒ์„ฑ์ž ํ•จ์ˆ˜๋ฅผ ๊ณ ์น˜๋ฉด ๊ฐœ๋ณ„ ์ธ์ž๋กœ ๋„๊ตฌ๋ช…์„ ๋„˜๊ฒจ๋„ ๋ฌธ์ œ์—†์ด ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

var Conference = Conference || {};

Conference.WidgetSandbox = function() {
'use strict';

// Conference.WidgetSandbox(...)๋ฅผ new๋กœ ์‹คํ–‰ํ–ˆ๋Š”์ง€ ๋ณด์žฅํ•œ๋‹ค.
if (!(this instanceof Conference.WidgetSandbox)) {
throw new Error(Conference.WidgetSandbox.messages.mustBeCalledWithNew);
}

var widgetFunction;
var toolsToLoad = [];
var argsArray;

// arguments์—์„œ ์ง„์งœ ๋ฐฐ์—ด์„ ์ถ”์ถœํ•œ๋‹ค.
argsArray = Array.prototype.slice.call(arguments);

// ๋ฐฐ์—ด ๋งˆ์ง€๋ง‰ ์›์†Œ๋Š” widgetFunction์ผ ๊ฒƒ์ด๋‹ค. ๋ฝ‘์•„๋‚ธ๋‹ค.
widgetFunction = argsArray.pop();

if (typeof widgetFunction !== 'function') {
throw new Error(Conference.WidgetSandbox.messages.fcnMustBeProvided);
}

toolsToLoad = (argsArray[0] instanceof Array) ? argsArray[0] : argsArray;

toolsToLoad.forEach(function loadTool(toolName) {
if (!Conference.WidgetTools.hasOwnProperty(toolName)) {
throw new Error(Conference.WidgetSandbox.messages.unKnownTool + toolName);
}

Conference.WidgetTools[toolName](this);
}, this); // ์ฝœ๋ฐฑ ๋‚ด์—์„œ this๊ฐ€ sandbox ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ๋ณด์žฅํ•œ๋‹ค.

var widget = widgetFunction(this);
};

/** ์ด์ „ ์ฝ”๋“œ ์ค„์ž„ **/

๐ŸŽˆ ์ƒŒ๋“œ๋ฐ•์Šค ๋„๊ตฌ ์ƒ์„ฑ๊ณผ ํ…Œ์ŠคํŒ…โ€‹

WidgetSandbox ์ž์ฒด๋Š” ์‚ฌ์‹ค ๋ณ„๋กœ ํšจ์šฉ์„ฑ์ด ์—†๋‹ค. ์œ„์ ฏ ์ธ์Šคํ„ด์Šค๋Š” ๊นจ๋—ํ•˜๊ฒŒ ๋–ผ์–ด ๋†“์•˜์ง€๋งŒ, ์œ„์ ฏ๋“ค์ด ๋ญ”๊ฐ€ ์ผ์„ ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋„๊ตฌ๊ฐ€ ์ „ํ˜€ ์—†๋‹ค.

๋Œ€์‹œ๋ณด๋“œ์—์„œ ๋ด์•ผ ํ•  ๋ฐ์ดํ„ฐ ์ค‘ ์ฝ˜ํผ๋Ÿฐ์Šค ๋“ฑ๋ก์ž ๋ช…๋‹จ์€ ์•„๋งˆ ๋ชจ๋“  ๋‹ด๋‹น์ž์—๊ฒŒ ๊ณตํ†ต์ผ ๊ฒƒ์ด๋‹ค. ์Šนํ˜„์€ ๋“ฑ๋ก์ž ์„ฑ๋ช…์„ ์œ„์ ฏ์— ๋ณด์—ฌ์ค„ ๋„๊ตฌ ๊ฐœ๋ฐœ์„ ์ฐฉ์ˆ˜ํ•œ๋‹ค.

์ฐธ๊ฐ€์ž ๋“ฑ๋ก ์ฒ˜๋ฆฌ๋ฅผ ๊ด€์žฅํ•˜๋Š” attendeeWebApi ๊ฐ์ฒด๋Š” ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ์ƒํƒœ์ธ๋ฐ, ๊ทธ์ค‘ getAll() ๋ฉ”์„œ๋“œ๋Š” attendee ๊ฐ์ฒด์˜ ๋ฐฐ์—ด๋กœ ๊ท€๊ฒฐํ•˜๋Š” ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์Šนํ˜„์€ attendeeNames๋ผ๋Š” ๋„๊ตฌ๋ฅผ ๋งŒ๋“ค์–ด์„œ attendeeWebApi์˜ ํผ์‚ฌ๋“œ๋กœ ์‚ผ์•„ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ํ‘œ์‹œํ•˜๊ธฐ๋กœ ํ•œ๋‹ค.

attendeeNames ๋„๊ตฌ์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ž

describe('Conference.WidgetTools.attendeeNames', () => {
'use strict';

var attendeeWebApi;
var sandbox;

beforeEach(() => {
attendeeWebApi = Conference.attendeeWebApi();

// post ๋ฉ”์„œ๋“œ๋Š” ํ˜ธ์ถœ๋˜๋ฉด ์•ˆ ๋œ๋‹ค.
// ๊ทธ๋ž˜๋„ ํ˜น์‹œ ๋ชจ๋ฅด๋‹ˆ ์ŠคํŒŒ์ด๋ฅผ ์‹ฌ์–ด๋‘์–ด ํ™•์ธํ•œ๋‹ค.
spyOn(attendeeWebApi, 'post');

// attendeeNames๋ฅผ ๋‹จ์œ„ ํ…Œ์ŠคํŠธํ•˜๊ณ ์ž sandbox๋Š” ๋นˆ ๊ฐ์ฒด๋กœ ์ง€์ •ํ•œ๋‹ค.
sandbox = {};
});

afterEach(() => {
// ํ…Œ์ŠคํŠธํ•  ๋•Œ๋งˆ๋‹ค post๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
expect(attendeeWebApi.post).not.toHaveBeenCalled();
});

it('์ฃผ์–ด์ง„ sandbox ๊ฐ์ฒด์— ์ž์‹ ์„ ์ถ”๊ฐ€ํ•œ๋‹ค', () => {
Conference.WidgetTools.attendeeNames(sandbox, attendeeWebApi);

expect(sandbox.attendeeNames).not.toBeUndefined();
});

describe('attendeeNames.getAll()', () => {
var attendees;
var attendeeNames;

beforeEach(() => {
Conference.WidgetTools.attendeeNames(sandbox, attendeeWebApi);

// ํ…Œ์ŠคํŠธ ์ฐธ๊ฐ€์ž ๋ฐฐ์—ด์„ ์ฑ„์›Œ๋„ฃ๋Š”๋‹ค.
attendees = [
Conference.attendee('ํƒœํฌ', '๊น€');
Conference.attendee('์œค์ง€', '๊น€');
Conference.attendee('์ •์œค', '์ตœ');
];

// ํ…Œ์ŠคํŠธ ์ฐธ๊ฐ€์ž ๋ฐฐ์—ด์—์„œ ์ด๋ฆ„์„ ์ถ”์ถœํ•œ๋‹ค.
attendeeNames = [];
attendees.forEach(function getNames(attendee) {
attendeeNames.push(attendee.getFullName());
});
});

it('์ฐธ๊ฐ€์ž๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ๋นˆ ๋ฐฐ์—ด๋กœ ๊ท€๊ฒฐํ•œ๋‹ค', (done) => {
spyOn(attendeeWebApi, 'getAll').and.returnValue(
new Promise(function(resolve, reject) {
resolve([]);
}),
);

sandbox.attendeeNames.getAll().then(function resolved(names) {
expect(names).toEqual([]);
done();
}, function rejected(reason) {
expect('์‹คํŒจํ•จ').toBe(false);
done();
});
});

it('์ฐธ๊ฐ€์ž๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ํ•ด๋‹น ์ด๋ฆ„์œผ๋กœ ๊ท€๊ฒฐํ•œ๋‹ค', (done) => {
spyOn(attendeeWebApi, 'getAll').and.returnValue(
new Promise(function(resolve, reject) {
resolve(attendees);
}),
);

sandbox.attendeeNames.getAll().then(function resolved(names) {
expect(names).toEqual(attendeeNames);
done();
}, function rejected(reason) {
expect('์‹คํŒจํ•จ').toBe(false);
done();
});
});

it('์–ด๋–ค ์‚ฌ์œ ๋กœ ์ธํ•ด ๋ฒ„๋ ค์ง„๋‹ค', (done) => {
var rejectionReason = '๋ฒ„๋ฆผ๋ฐ›๋Š” ์ด์œ ';

spyOn(attendeeWebApi, 'getAll').and.returnValue(
new Promise(function(resolve, reject) {
reject(rejectionReason);
}),
);

sandbox.attendeeNames.getAll().then(function resolved(names) {
expect('๊ท€๊ฒฐ๋จ').toBe(false);
done();
}, function rejected(reason) {
expect(reason).toBe(rejectionReason);
done();
});
});
});
});

attendeeWebApi.getAll()๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ”„๋ผ๋ฏธ์Šค๊ฐ€ attendeeNames.getAll() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ œ๋Œ€๋กœ ํ˜๋Ÿฌ๊ฐ€๋Š”์ง€ ์ฒดํฌํ•˜๋ฉด ๋œ๋‹ค. ๋˜ํ•œ, attendeeNames.getAll()์ด ๊ฐ attendee ๊ฐ์ฒด์˜ ์ „๋ถ€๊ฐ€ ์•„๋‹Œ, ์ฐธ๊ฐ€์ž ์„ฑ๋ช…๋งŒ ์ถ”์ถœํ•ด์„œ ์ ์ ˆํžˆ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

๋‹ค์Œ์€ attendeeNames ๋„๊ตฌ์˜ ๊ตฌํ˜„๋ถ€์ด๋‹ค.

var Conference = Conference || {};

Conference.WidgetTools = Conference.WidgetTools || {};

Conference.WidgetTools.attendeeNames = function(sandbox, injectedAttendeeWebApi) {
'use strict';

// attendeeWebApi๋ฅผ ์„ ํƒ์ ์œผ๋กœ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ฝ”๋”ฉํ•œ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์œ ์šฉํ•˜๋‹ค.
var attendeeWebApi = injectedAttendeeWebApi || Conference.attendeeWebApi();

sandbox.attendeeNames = {
// ์ฐธ๊ฐ€์ž ์ด๋ฆ„ ๋ฐฐ์—ด๋กœ ๊ท€๊ฒฐํ•˜๋Š” ํ”„๋ผ๋ฏธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
getAll: function getAll() {
return attendeeWebApi.getAll().then(function extractNames(attendees) {
// ๊ฐ ์ฐธ๊ฐ€์ž์˜ ์ „์ฒด ์„ฑ๋ช…๋งŒ ์ถ”์ถœํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
var names = [];
attendees.forEach(function addName(attendee) {
names.push(attendee.getFullName());
});

return names;
});
}
};
};

๐ŸŽˆ ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ์“ธ ํ•จ์ˆ˜ ๋งŒ๋“ค๊ธฐโ€‹

์ƒŒ๋“œ๋ฐ•์Šค์— ๋†“๊ณ  ์‚ฌ์šฉํ•  ๋ชจ๋“ˆ์˜ ์ƒ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ๋Š” ๋น„๊ต์  ๊ฐ„๋‹จํ•˜๋‹ค. ์ƒŒ๋“œ๋ฐ•์Šค ํŒจํ„ด์—์„œ๋Š” ๋ถ„๋ฆฌํ•œ ๋ชจ๋“ˆ์€ ์˜ค์ง ์ƒŒ๋“œ๋ฐ•์Šค ์ธ์Šคํ„ด์Šค์—๋งŒ ์˜์กดํ•˜๋ฉฐ ์ด ์ธ์Šคํ„ด์Šค๋Š” ๋ฐ˜๋“œ์‹œ ๋ชจ๋“ˆ์— ์ฃผ์ž…ํ•˜๋„๋ก ๋ช…์‹œ๋˜์–ด ์žˆ๋‹ค. ์˜์กด์„ฑ์„ ์ฃผ์ž…ํ•˜๋ฉด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ์˜ ํ…Œ์ŠคํŠธ์„ฑ๊ณผ ๋ฏฟ์Œ์„ฑ์ด ์ข‹์•„์ง„๋‹ค.

์Šนํ˜„์ด attendeeNames ๋„๊ตฌ ๊ฐœ๋ฐœ์— ๋ชฐ๋‘ํ•  ์ฆˆ์Œ, ์ƒฌ๋Ÿฟ์€ ์œ„์ ฏ์—์„œ ๋ธŒ๋ผ์šฐ์ € ๋ฌธ์„œ ๊ฐ์ฒด ๋ชจ๋ธ(DOM)์„ ์—ฐ๋™ํ•  ๋•Œ ์“ธ dom ๋„๊ตฌ๋ฅผ ๊ฐœ๋ฐœ ์ค‘์ด๋‹ค. ์Šนํ˜„์ด ๊ฐœ๋ฐœํ•œ attendeeNames์™€ ์ƒฌ๋Ÿฟ์ด ์ž‘์„ฑํ•œ dom, ๋‘ ๋„๊ตฌ๋ฅผ ํ•ฉํ•˜๋ฉด ๋น„๋กœ์†Œ ์ฐธ๊ฐ€์ž ์„ฑ๋ช…์„ ๋ณด์—ฌ์ฃผ๋Š” ์œ„์ ฏ์ด ์™„์„ฑ๋œ๋‹ค. ๋‹ค์Œ ์˜ˆ์ œ๋Š” ์œ„์ ฏ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ์ผ๋ถ€๋ฅผ ๋ฐœ์ทŒํ•œ ์ฝ”๋“œ๋‹ค.

describe('Conference.Widgets.attendeeNamesWidget(sandbox)', () => {
'use strict';

var sandbox;
beforeEach(() => {
sandbox = {};
});

it('dom ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋˜์ง„๋‹ค', () => {
expect(function shouldThrow() {
Conference.Widgets.attendeeNamesWidget(sandbox);
}).toThrowError(Conference.Widgets.messages.missingTool + 'dom');
});

it('attendeeNames ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋˜์ง„๋‹ค', () => {
expect(function shouldThrow() {
sandbox.dom = {};
Conference.Widgets.attendeeNamesWidget(sandbox);
}).toThrowError(Conference.Widgets.messages.missingTool + 'attendeeNames');
});

// attendeeNamesWidget์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋‹ค๋ฅธ ํ…Œ์ŠคํŠธ
});

์ƒŒ๋“œ๋ฐ•์Šค ๊ฐ์ฒด๋กœ ์œ„์ ฏ ์‚ฌ์šฉ ๋ถ€๋ถ„์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ์ฝ”๋“œ ์™ธ์—, ๋‹ค๋ฅธ ์œ„์ ฏ ๊ธฐ๋Šฅ์„ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ๋Š” ๋ณ„๋กœ ์ƒˆ๋กœ์šธ ๊ฒŒ ์—†๋‹ค. ํ…Œ์ŠคํŠธํ•  ๋•Œ ๊ผญ WidgetSandbox ์ธ์Šคํ„ด์Šค๋ฅผ ์จ์•ผ ํ•˜๋Š” ๊ฑด ์•„๋‹ˆ๋‹ค. ์œ„์ ฏ์— ๊ด€ํ•œ ํ•œ ์ƒŒ๋“œ๋ฐ•์Šค ๊ธฐ๋Šฅ์€ ๋„๊ตฌ๋ฅผ ์ฃผ๋Š” ์ผ์ด ์ „๋ถ€๋ผ ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด ์ •๋„๋ฉด ํ…Œ์ŠคํŠธ ์šฉ๋„๋กœ ์ถฉ๋ถ„ํ•˜๋‹ค.

var Conference = Conference || {};
Conference.Widgets = Conference.Widgets || {};

Conference.Widgets.attendeeNamesWidget = function(sandbox) {
'use strict';

// ํ•ด๋‹น ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉด ์ฆ‰์‹œ ์‹คํŒจ ์ฒ˜๋ฆฌํ•œ๋‹ค.
if (!sandbox.dom) {
throw new Error(Conference.Widgets.messages.missingTool + 'dom');
}

if (!sandbox.attendeeNames) {
throw new Error(Conference.Widgets.messages.missingTool + 'attendeeNames');
}

// attendeeNames๋ฅผ ์กฐํšŒํ•˜์—ฌ ๋Œ€์‹œ๋ณด๋“œ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
sandbox.attendeeNames.getAll().then(function resolved(names) {
// sandbox.dom์œผ๋กœ ์ด๋ฆ„ ๋ชฉ๋ก์„ ํ‘œ์‹œํ•œ๋‹ค.
}, function rejected(reason) {
// sandbox.dom์œผ๋กœ ์œ„์ ฏ ๋Œ€์‹  ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.
});
};

Conference.Widgets.messages = {
missingTool: '๋ˆ„๋ฝ๋œ ๋„๊ตฌ: ',
};

๐Ÿ“š ์ •๋ฆฌํ•˜๊ธฐโ€‹

์ƒŒ๋“œ๋ฐ•์Šค ํŒจํ„ด์€ ๋ชจ๋“ˆ ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ์˜์กด์„ฑ์„ ์—„๊ฒฉํ•˜๊ฒŒ ๋‹ค์Šค๋ฆฌ๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

์ƒŒ๋“œ๋ฐ•์Šค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋Š” ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๊ผญ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค.

  • ์ƒŒ๋“œ๋ฐ•์Šค ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ์œ„์ ฏ ๋ชจ๋“ˆ ํ•จ์ˆ˜๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.
  • ๋„๊ตฌ๋Š” ์ƒŒ๋“œ๋ฐ•์Šค ์ƒ์„ฑ์ž ํ•จ์ˆ˜์— ๋ฐฐ์—ด ๋˜๋Š” ๊ฐœ๋ณ„ ์ธ์ž ํ˜•ํƒœ๋กœ ๋„˜๊ธด๋‹ค.
  • ์ƒŒ๋“œ๋ฐ•์Šค์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ์ง€์ •ํ•œ ๋„๊ตฌ๊ฐ€ ์œ ํšจํ•˜๋‹ค.
  • ์ƒŒ๋“œ๋ฐ•์Šค ์•ˆ์—์„œ ์‹คํ–‰ํ•  ์œ„์ ฏ์ด ์š”์ฒญํ•œ ๋„๊ตฌ๋Š” ์ƒŒ๋“œ๋ฐ•์Šค๊ฐ€ ์ œ๊ณตํ•œ๋‹ค.