Best Python code snippet using localstack_python
main.js
Source:main.js
1/*!2@fullcalendar/resource-common v4.0.13Docs & License: https://fullcalendar.io/scheduler/4(c) 2019 Adam Shaw5*/6(function (global, factory) {7 typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fullcalendar/core')) :8 typeof define === 'function' && define.amd ? define(['exports', '@fullcalendar/core'], factory) :9 (global = global || self, factory(global.FullCalendarResourceCommon = {}, global.FullCalendar));10}(this, function (exports, core) { 'use strict';11 /*! *****************************************************************************12 Copyright (c) Microsoft Corporation. All rights reserved.13 Licensed under the Apache License, Version 2.0 (the "License"); you may not use14 this file except in compliance with the License. You may obtain a copy of the15 License at http://www.apache.org/licenses/LICENSE-2.016 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY17 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED18 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,19 MERCHANTABLITY OR NON-INFRINGEMENT.20 See the Apache Version 2.0 License for specific language governing permissions21 and limitations under the License.22 ***************************************************************************** */23 /* global Reflect, Promise */24 var extendStatics = function(d, b) {25 extendStatics = Object.setPrototypeOf ||26 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||27 function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };28 return extendStatics(d, b);29 };30 function __extends(d, b) {31 extendStatics(d, b);32 function __() { this.constructor = d; }33 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());34 }35 var __assign = function() {36 __assign = Object.assign || function __assign(t) {37 for (var s, i = 1, n = arguments.length; i < n; i++) {38 s = arguments[i];39 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];40 }41 return t;42 };43 return __assign.apply(this, arguments);44 };45 var ResourceDataAdder = /** @class */ (function () {46 function ResourceDataAdder() {47 this.filterResources = core.memoize(filterResources);48 }49 ResourceDataAdder.prototype.transform = function (viewProps, viewSpec, calendarProps, view) {50 if (viewSpec.class.needsResourceData) {51 return {52 resourceStore: this.filterResources(calendarProps.resourceStore, view.opt('filterResourcesWithEvents'), calendarProps.eventStore, calendarProps.dateProfile.activeRange),53 resourceEntityExpansions: calendarProps.resourceEntityExpansions54 };55 }56 };57 return ResourceDataAdder;58 }());59 function filterResources(resourceStore, doFilterResourcesWithEvents, eventStore, activeRange) {60 if (doFilterResourcesWithEvents) {61 var instancesInRange = filterEventInstancesInRange(eventStore.instances, activeRange);62 var hasEvents_1 = computeHasEvents(instancesInRange, eventStore.defs);63 __assign(hasEvents_1, computeAncestorHasEvents(hasEvents_1, resourceStore));64 return core.filterHash(resourceStore, function (resource, resourceId) {65 return hasEvents_1[resourceId];66 });67 }68 else {69 return resourceStore;70 }71 }72 function filterEventInstancesInRange(eventInstances, activeRange) {73 return core.filterHash(eventInstances, function (eventInstance) {74 return core.rangesIntersect(eventInstance.range, activeRange);75 });76 }77 function computeHasEvents(eventInstances, eventDefs) {78 var hasEvents = {};79 for (var instanceId in eventInstances) {80 var instance = eventInstances[instanceId];81 for (var _i = 0, _a = eventDefs[instance.defId].resourceIds; _i < _a.length; _i++) {82 var resourceId = _a[_i];83 hasEvents[resourceId] = true;84 }85 }86 return hasEvents;87 }88 /*89 mark resources as having events if any of their ancestors have them90 NOTE: resourceStore might not have all the resources that hasEvents{} has keyed91 */92 function computeAncestorHasEvents(hasEvents, resourceStore) {93 var res = {};94 for (var resourceId in hasEvents) {95 var resource = void 0;96 while ((resource = resourceStore[resourceId])) {97 resourceId = resource.parentId; // now functioning as the parentId98 if (resourceId) {99 res[resourceId] = true;100 }101 else {102 break;103 }104 }105 }106 return res;107 }108 // for when non-resource view should be given EventUi info (for event coloring/constraints based off of resource data)109 var ResourceEventConfigAdder = /** @class */ (function () {110 function ResourceEventConfigAdder() {111 this.buildResourceEventUis = core.memoizeOutput(buildResourceEventUis, core.isPropsEqual);112 this.injectResourceEventUis = core.memoize(injectResourceEventUis);113 }114 ResourceEventConfigAdder.prototype.transform = function (viewProps, viewSpec, calendarProps) {115 if (!viewSpec.class.needsResourceData) { // is a non-resource view?116 return {117 eventUiBases: this.injectResourceEventUis(viewProps.eventUiBases, viewProps.eventStore.defs, this.buildResourceEventUis(calendarProps.resourceStore))118 };119 }120 };121 return ResourceEventConfigAdder;122 }());123 function buildResourceEventUis(resourceStore) {124 return core.mapHash(resourceStore, function (resource) {125 return resource.ui;126 });127 }128 function injectResourceEventUis(eventUiBases, eventDefs, resourceEventUis) {129 return core.mapHash(eventUiBases, function (eventUi, defId) {130 if (defId) { // not the '' key131 return injectResourceEventUi(eventUi, eventDefs[defId], resourceEventUis);132 }133 else {134 return eventUi;135 }136 });137 }138 function injectResourceEventUi(origEventUi, eventDef, resourceEventUis) {139 var parts = [];140 // first resource takes precedence, which fights with the ordering of combineEventUis, thus the unshifts141 for (var _i = 0, _a = eventDef.resourceIds; _i < _a.length; _i++) {142 var resourceId = _a[_i];143 if (resourceEventUis[resourceId]) {144 parts.unshift(resourceEventUis[resourceId]);145 }146 }147 parts.unshift(origEventUi);148 return core.combineEventUis(parts);149 }150 var RESOURCE_SOURCE_PROPS = {151 id: String152 };153 var defs = [];154 var uid = 0;155 function registerResourceSourceDef(def) {156 defs.push(def);157 }158 function getResourceSourceDef(id) {159 return defs[id];160 }161 function doesSourceIgnoreRange(source) {162 return Boolean(defs[source.sourceDefId].ignoreRange);163 }164 function parseResourceSource(input) {165 for (var i = defs.length - 1; i >= 0; i--) { // later-added plugins take precedence166 var def = defs[i];167 var meta = def.parseMeta(input);168 if (meta) {169 return parseResourceSourceProps((typeof input === 'object' && input) ? input : {}, meta, i);170 }171 }172 return null;173 }174 function parseResourceSourceProps(input, meta, sourceDefId) {175 var props = core.refineProps(input, RESOURCE_SOURCE_PROPS);176 props.sourceId = String(uid++);177 props.sourceDefId = sourceDefId;178 props.meta = meta;179 props.publicId = props.id;180 props.isFetching = false;181 props.latestFetchId = '';182 props.fetchRange = null;183 delete props.id;184 return props;185 }186 function reduceResourceSource (source, action, dateProfile, calendar) {187 switch (action.type) {188 case 'INIT':189 return createInitialSource(calendar);190 case 'PREV': // TODO: how do we track all actions that affect dateProfile :(191 case 'NEXT':192 case 'SET_DATE':193 case 'SET_VIEW_TYPE':194 return handleRange(source, dateProfile.activeRange, calendar);195 case 'RECEIVE_RESOURCES':196 case 'RECEIVE_RESOURCE_ERROR':197 return receiveResponse(source, action.fetchId, action.fetchRange);198 case 'REFETCH_RESOURCES':199 return fetchSource(source, dateProfile.activeRange, calendar);200 default:201 return source;202 }203 }204 var uid$1 = 0;205 function createInitialSource(calendar) {206 var input = calendar.opt('resources');207 if (input) {208 var source = parseResourceSource(input);209 if (!calendar.opt('refetchResourcesOnNavigate')) {210 source = fetchSource(source, null, calendar);211 }212 return source;213 }214 return null;215 }216 function handleRange(source, activeRange, calendar) {217 if (calendar.opt('refetchResourcesOnNavigate') &&218 !doesSourceIgnoreRange(source) &&219 (!source.fetchRange || !core.rangesEqual(source.fetchRange, activeRange))) {220 return fetchSource(source, activeRange, calendar);221 }222 else {223 return source;224 }225 }226 function fetchSource(source, fetchRange, calendar) {227 var sourceDef = getResourceSourceDef(source.sourceDefId);228 var fetchId = String(uid$1++);229 sourceDef.fetch({230 resourceSource: source,231 calendar: calendar,232 range: fetchRange233 }, function (res) {234 // HACK235 // do before calling dispatch in case dispatch renders synchronously236 calendar.afterSizingTriggers._resourcesRendered = [null]; // fire once237 calendar.dispatch({238 type: 'RECEIVE_RESOURCES',239 fetchId: fetchId,240 fetchRange: fetchRange,241 rawResources: res.rawResources242 });243 }, function (error) {244 calendar.dispatch({245 type: 'RECEIVE_RESOURCE_ERROR',246 fetchId: fetchId,247 fetchRange: fetchRange,248 error: error249 });250 });251 return __assign({}, source, { isFetching: true, latestFetchId: fetchId });252 }253 function receiveResponse(source, fetchId, fetchRange) {254 if (fetchId === source.latestFetchId) {255 return __assign({}, source, { isFetching: false, fetchRange: fetchRange });256 }257 return source;258 }259 var RESOURCE_PROPS = {260 id: String,261 title: String,262 parentId: String,263 businessHours: null,264 children: null265 };266 var PRIVATE_ID_PREFIX = '_fc:';267 var uid$2 = 0;268 /*269 needs a full store so that it can populate children too270 */271 function parseResource(input, parentId, store, calendar) {272 if (parentId === void 0) { parentId = ''; }273 var leftovers0 = {};274 var props = core.refineProps(input, RESOURCE_PROPS, {}, leftovers0);275 var leftovers1 = {};276 var ui = core.processScopedUiProps('event', leftovers0, calendar, leftovers1);277 if (!props.id) {278 props.id = PRIVATE_ID_PREFIX + (uid$2++);279 }280 if (!props.parentId) { // give precedence to the parentId property281 props.parentId = parentId;282 }283 props.businessHours = props.businessHours ? core.parseBusinessHours(props.businessHours, calendar) : null;284 props.ui = ui;285 props.extendedProps = __assign({}, leftovers1, props.extendedProps);286 // help out ResourceApi from having user modify props287 Object.freeze(ui.classNames);288 Object.freeze(props.extendedProps);289 if (store[props.id]) ;290 else {291 store[props.id] = props;292 if (props.children) {293 for (var _i = 0, _a = props.children; _i < _a.length; _i++) {294 var childInput = _a[_i];295 parseResource(childInput, props.id, store, calendar);296 }297 delete props.children;298 }299 }300 return props;301 }302 /*303 TODO: use this in more places304 */305 function getPublicId(id) {306 if (id.indexOf(PRIVATE_ID_PREFIX) === 0) {307 return '';308 }309 return id;310 }311 function reduceResourceStore (store, action, source, calendar) {312 switch (action.type) {313 case 'INIT':314 return {};315 case 'RECEIVE_RESOURCES':316 return receiveRawResources(store, action.rawResources, action.fetchId, source, calendar);317 case 'ADD_RESOURCE':318 return addResource(store, action.resourceHash);319 case 'REMOVE_RESOURCE':320 return removeResource(store, action.resourceId);321 case 'SET_RESOURCE_PROP':322 return setResourceProp(store, action.resourceId, action.propName, action.propValue);323 case 'RESET_RESOURCES':324 // must make the calendar think each resource is a new object :/325 return core.mapHash(store, function (resource) {326 return __assign({}, resource);327 });328 default:329 return store;330 }331 }332 function receiveRawResources(existingStore, inputs, fetchId, source, calendar) {333 if (source.latestFetchId === fetchId) {334 var nextStore = {};335 for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {336 var input = inputs_1[_i];337 parseResource(input, '', nextStore, calendar);338 }339 return nextStore;340 }341 else {342 return existingStore;343 }344 }345 function addResource(existingStore, additions) {346 // TODO: warn about duplicate IDs347 return __assign({}, existingStore, additions);348 }349 function removeResource(existingStore, resourceId) {350 var newStore = __assign({}, existingStore);351 delete newStore[resourceId];352 // promote children353 for (var childResourceId in newStore) { // a child, *maybe* but probably not354 if (newStore[childResourceId].parentId === resourceId) {355 newStore[childResourceId] = __assign({}, newStore[childResourceId], { parentId: '' });356 }357 }358 return newStore;359 }360 function setResourceProp(existingStore, resourceId, name, value) {361 var _a, _b;362 var existingResource = existingStore[resourceId];363 // TODO: sanitization364 if (existingResource) {365 return __assign({}, existingStore, (_a = {}, _a[resourceId] = __assign({}, existingResource, (_b = {}, _b[name] = value, _b)), _a));366 }367 else {368 return existingStore;369 }370 }371 function reduceResourceEntityExpansions(expansions, action) {372 var _a;373 switch (action.type) {374 case 'INIT':375 return {};376 case 'SET_RESOURCE_ENTITY_EXPANDED':377 return __assign({}, expansions, (_a = {}, _a[action.id] = action.isExpanded, _a));378 default:379 return expansions;380 }381 }382 function resourcesReducers (state, action, calendar) {383 var resourceSource = reduceResourceSource(state.resourceSource, action, state.dateProfile, calendar);384 var resourceStore = reduceResourceStore(state.resourceStore, action, resourceSource, calendar);385 var resourceEntityExpansions = reduceResourceEntityExpansions(state.resourceEntityExpansions, action);386 return __assign({}, state, { resourceSource: resourceSource,387 resourceStore: resourceStore,388 resourceEntityExpansions: resourceEntityExpansions });389 }390 var RESOURCE_RELATED_PROPS = {391 resourceId: String,392 resourceIds: function (items) {393 return (items || []).map(function (item) {394 return String(item);395 });396 },397 resourceEditable: Boolean398 };399 function parseEventDef(def, props, leftovers) {400 var resourceRelatedProps = core.refineProps(props, RESOURCE_RELATED_PROPS, {}, leftovers);401 var resourceIds = resourceRelatedProps.resourceIds;402 if (resourceRelatedProps.resourceId) {403 resourceIds.push(resourceRelatedProps.resourceId);404 }405 def.resourceIds = resourceIds;406 def.resourceEditable = resourceRelatedProps.resourceEditable;407 }408 function massageEventDragMutation(eventMutation, hit0, hit1) {409 var resource0 = hit0.dateSpan.resourceId;410 var resource1 = hit1.dateSpan.resourceId;411 if (resource0 && resource1 &&412 resource0 !== resource1) {413 eventMutation.resourceMutation = {414 matchResourceId: resource0,415 setResourceId: resource1416 };417 }418 }419 /*420 TODO: all this would be much easier if we were using a hash!421 */422 function applyEventDefMutation(eventDef, mutation, calendar) {423 var resourceMutation = mutation.resourceMutation;424 if (resourceMutation && computeResourceEditable(eventDef, calendar)) {425 var index = eventDef.resourceIds.indexOf(resourceMutation.matchResourceId);426 if (index !== -1) {427 var resourceIds = eventDef.resourceIds.slice(); // copy428 resourceIds.splice(index, 1); // remove429 if (resourceIds.indexOf(resourceMutation.setResourceId) === -1) { // not already in there430 resourceIds.push(resourceMutation.setResourceId); // add431 }432 eventDef.resourceIds = resourceIds;433 }434 }435 }436 /*437 HACK438 TODO: use EventUi system instead of this439 */440 function computeResourceEditable(eventDef, calendar) {441 var resourceEditable = eventDef.resourceEditable;442 if (resourceEditable == null) {443 var source = eventDef.sourceId && calendar.state.eventSources[eventDef.sourceId];444 if (source) {445 resourceEditable = source.extendedProps.resourceEditable; // used the Source::extendedProps hack446 }447 if (resourceEditable == null) {448 resourceEditable = calendar.opt('eventResourceEditable');449 if (resourceEditable == null) {450 resourceEditable = calendar.opt('editable'); // TODO: use defaults system instead451 }452 }453 }454 return resourceEditable;455 }456 function transformEventDrop(mutation, calendar) {457 var resourceMutation = mutation.resourceMutation;458 if (resourceMutation) {459 return {460 oldResource: calendar.getResourceById(resourceMutation.matchResourceId),461 newResource: calendar.getResourceById(resourceMutation.setResourceId)462 };463 }464 else {465 return {466 oldResource: null,467 newResource: null468 };469 }470 }471 function transformDateSelectionJoin(hit0, hit1) {472 var resourceId0 = hit0.dateSpan.resourceId;473 var resourceId1 = hit1.dateSpan.resourceId;474 if (resourceId0 && resourceId1) {475 if (hit0.component.allowAcrossResources === false &&476 resourceId0 !== resourceId1) {477 return false;478 }479 else {480 return { resourceId: resourceId0 };481 }482 }483 }484 var ResourceApi = /** @class */ (function () {485 function ResourceApi(calendar, rawResource) {486 this._calendar = calendar;487 this._resource = rawResource;488 }489 ResourceApi.prototype.setProp = function (name, value) {490 this._calendar.dispatch({491 type: 'SET_RESOURCE_PROP',492 resourceId: this._resource.id,493 propName: name,494 propValue: value495 });496 };497 ResourceApi.prototype.remove = function () {498 this._calendar.dispatch({499 type: 'REMOVE_RESOURCE',500 resourceId: this._resource.id501 });502 };503 ResourceApi.prototype.getParent = function () {504 var calendar = this._calendar;505 var parentId = this._resource.parentId;506 if (parentId) {507 return new ResourceApi(calendar, calendar.state.resourceSource[parentId]);508 }509 else {510 return null;511 }512 };513 ResourceApi.prototype.getChildren = function () {514 var thisResourceId = this._resource.id;515 var calendar = this._calendar;516 var resourceStore = calendar.state.resourceStore;517 var childApis = [];518 for (var resourceId in resourceStore) {519 if (resourceStore[resourceId].parentId === thisResourceId) {520 childApis.push(new ResourceApi(calendar, resourceStore[resourceId]));521 }522 }523 return childApis;524 };525 /*526 this is really inefficient!527 TODO: make EventApi::resourceIds a hash or keep an index in the Calendar's state528 */529 ResourceApi.prototype.getEvents = function () {530 var thisResourceId = this._resource.id;531 var calendar = this._calendar;532 var _a = calendar.state.eventStore, defs = _a.defs, instances = _a.instances;533 var eventApis = [];534 for (var instanceId in instances) {535 var instance = instances[instanceId];536 var def = defs[instance.defId];537 if (def.resourceIds.indexOf(thisResourceId) !== -1) { // inefficient!!!538 eventApis.push(new core.EventApi(calendar, def, instance));539 }540 }541 return eventApis;542 };543 Object.defineProperty(ResourceApi.prototype, "id", {544 get: function () { return this._resource.id; },545 enumerable: true,546 configurable: true547 });548 Object.defineProperty(ResourceApi.prototype, "title", {549 get: function () { return this._resource.title; },550 enumerable: true,551 configurable: true552 });553 Object.defineProperty(ResourceApi.prototype, "eventConstraint", {554 get: function () { return this._resource.ui.constraints[0] || null; },555 enumerable: true,556 configurable: true557 });558 Object.defineProperty(ResourceApi.prototype, "eventOverlap", {559 get: function () { return this._resource.ui.overlap; },560 enumerable: true,561 configurable: true562 });563 Object.defineProperty(ResourceApi.prototype, "eventAllow", {564 get: function () { return this._resource.ui.allows[0] || null; },565 enumerable: true,566 configurable: true567 });568 Object.defineProperty(ResourceApi.prototype, "eventBackgroundColor", {569 get: function () { return this._resource.ui.backgroundColor; },570 enumerable: true,571 configurable: true572 });573 Object.defineProperty(ResourceApi.prototype, "eventBorderColor", {574 get: function () { return this._resource.ui.borderColor; },575 enumerable: true,576 configurable: true577 });578 Object.defineProperty(ResourceApi.prototype, "eventTextColor", {579 get: function () { return this._resource.ui.textColor; },580 enumerable: true,581 configurable: true582 });583 Object.defineProperty(ResourceApi.prototype, "eventClassNames", {584 // NOTE: user can't modify these because Object.freeze was called in event-def parsing585 get: function () { return this._resource.ui.classNames; },586 enumerable: true,587 configurable: true588 });589 Object.defineProperty(ResourceApi.prototype, "extendedProps", {590 get: function () { return this._resource.extendedProps; },591 enumerable: true,592 configurable: true593 });594 return ResourceApi;595 }());596 core.Calendar.prototype.addResource = function (input, scrollTo) {597 if (scrollTo === void 0) { scrollTo = true; }598 var _a;599 var resourceHash;600 var resource;601 if (input instanceof ResourceApi) {602 resource = input._resource;603 resourceHash = (_a = {}, _a[resource.id] = resource, _a);604 }605 else {606 resourceHash = {};607 resource = parseResource(input, '', resourceHash, this);608 }609 // HACK610 if (scrollTo) {611 this.component.view.addScroll({ forcedRowId: resource.id });612 }613 this.dispatch({614 type: 'ADD_RESOURCE',615 resourceHash: resourceHash616 });617 return new ResourceApi(this, resource);618 };619 core.Calendar.prototype.getResourceById = function (id) {620 id = String(id);621 if (this.state.resourceStore) { // guard against calendar with no resource functionality622 var rawResource = this.state.resourceStore[id];623 if (rawResource) {624 return new ResourceApi(this, rawResource);625 }626 }627 return null;628 };629 core.Calendar.prototype.getResources = function () {630 var resourceStore = this.state.resourceStore;631 var resourceApis = [];632 if (resourceStore) { // guard against calendar with no resource functionality633 for (var resourceId in resourceStore) {634 resourceApis.push(new ResourceApi(this, resourceStore[resourceId]));635 }636 }637 return resourceApis;638 };639 core.Calendar.prototype.getTopLevelResources = function () {640 var resourceStore = this.state.resourceStore;641 var resourceApis = [];642 if (resourceStore) { // guard against calendar with no resource functionality643 for (var resourceId in resourceStore) {644 if (!resourceStore[resourceId].parentId) {645 resourceApis.push(new ResourceApi(this, resourceStore[resourceId]));646 }647 }648 }649 return resourceApis;650 };651 core.Calendar.prototype.rerenderResources = function () {652 this.dispatch({653 type: 'RESET_RESOURCES'654 });655 };656 core.Calendar.prototype.refetchResources = function () {657 this.dispatch({658 type: 'REFETCH_RESOURCES'659 });660 };661 function transformDatePoint(dateSpan, calendar) {662 return dateSpan.resourceId ?663 { resource: calendar.getResourceById(dateSpan.resourceId) } :664 {};665 }666 function transformDateSpan(dateSpan, calendar) {667 return dateSpan.resourceId ?668 { resource: calendar.getResourceById(dateSpan.resourceId) } :669 {};670 }671 /*672 splits things BASED OFF OF which resources they are associated with.673 creates a '' entry which is when something has NO resource.674 */675 var ResourceSplitter = /** @class */ (function (_super) {676 __extends(ResourceSplitter, _super);677 function ResourceSplitter() {678 return _super !== null && _super.apply(this, arguments) || this;679 }680 ResourceSplitter.prototype.getKeyInfo = function (props) {681 return __assign({ '': {} }, props.resourceStore // already has `ui` and `businessHours` keys!682 );683 };684 ResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) {685 return [dateSpan.resourceId || ''];686 };687 ResourceSplitter.prototype.getKeysForEventDef = function (eventDef) {688 var resourceIds = eventDef.resourceIds;689 if (!resourceIds.length) {690 return [''];691 }692 return resourceIds;693 };694 return ResourceSplitter;695 }(core.Splitter));696 function isPropsValidWithResources(props, calendar) {697 var splitter = new ResourceSplitter();698 var sets = splitter.splitProps(__assign({}, props, { resourceStore: calendar.state.resourceStore }));699 for (var resourceId in sets) {700 var props_1 = sets[resourceId];701 // merge in event data from the non-resource segment702 if (resourceId && sets['']) { // current segment is not the non-resource one, and there IS a non-resource one703 props_1 = __assign({}, props_1, { eventStore: core.mergeEventStores(sets[''].eventStore, props_1.eventStore), eventUiBases: __assign({}, sets[''].eventUiBases, props_1.eventUiBases) });704 }705 if (!core.isPropsValid(props_1, calendar, { resourceId: resourceId }, filterConfig.bind(null, resourceId))) {706 return false;707 }708 }709 return true;710 }711 function filterConfig(resourceId, config) {712 return __assign({}, config, { constraints: filterConstraints(resourceId, config.constraints) });713 }714 function filterConstraints(resourceId, constraints) {715 return constraints.map(function (constraint) {716 var defs = constraint.defs;717 if (defs) { // we are dealing with an EventStore718 // if any of the events define constraints to resources that are NOT this resource,719 // then this resource is unconditionally prohibited, which is what a `false` value does.720 for (var defId in defs) {721 var resourceIds = defs[defId].resourceIds;722 if (resourceIds.length && resourceIds.indexOf(resourceId) === -1) { // TODO: use a hash?!!! (for other reasons too)723 return false;724 }725 }726 }727 return constraint;728 });729 }730 function transformExternalDef(dateSpan) {731 return dateSpan.resourceId ?732 { resourceId: dateSpan.resourceId } :733 {};734 }735 function transformEventResizeJoin(hit0, hit1) {736 var component = hit0.component;737 if (component.allowAcrossResources === false &&738 hit0.dateSpan.resourceId !== hit1.dateSpan.resourceId) {739 return false;740 }741 }742 core.EventApi.prototype.getResources = function () {743 var calendar = this._calendar;744 return this._def.resourceIds.map(function (resourceId) {745 return calendar.getResourceById(resourceId);746 });747 };748 var RELEASE_DATE = '2019-03-18'; // for Scheduler749 var UPGRADE_WINDOW = 365 + 7; // days. 1 week leeway, for tz shift reasons too750 var LICENSE_INFO_URL = 'http://fullcalendar.io/scheduler/license/';751 var PRESET_LICENSE_KEYS = [752 'GPL-My-Project-Is-Open-Source',753 'CC-Attribution-NonCommercial-NoDerivatives'754 ];755 var CSS = {756 position: 'absolute',757 'z-index': 99999,758 bottom: '1px',759 left: '1px',760 background: '#eee',761 'border-color': '#ddd',762 'border-style': 'solid',763 'border-width': '1px 1px 0 0',764 padding: '2px 4px',765 'font-size': '12px',766 'border-top-right-radius': '3px'767 };768 function injectLicenseWarning(containerEl, calendar) {769 var key = calendar.opt('schedulerLicenseKey');770 if (!isImmuneUrl(window.location.href) && !isValidKey(key)) {771 core.appendToElement(containerEl, '<div class="fc-license-message" style="' + core.htmlEscape(core.cssToStr(CSS)) + '">' +772 'Please use a valid license key. <a href="' + LICENSE_INFO_URL + '">More Info</a>' +773 '</div>');774 }775 }776 /*777 This decryption is not meant to be bulletproof. Just a way to remind about an upgrade.778 */779 function isValidKey(key) {780 if (PRESET_LICENSE_KEYS.indexOf(key) !== -1) {781 return true;782 }783 var parts = (key || '').match(/^(\d+)\-fcs\-(\d+)$/);784 if (parts && (parts[1].length === 10)) {785 var purchaseDate = new Date(parseInt(parts[2], 10) * 1000);786 var releaseDate = new Date(core.config.mockSchedulerReleaseDate || RELEASE_DATE);787 if (core.isValidDate(releaseDate)) { // token won't be replaced in dev mode788 var minPurchaseDate = core.addDays(releaseDate, -UPGRADE_WINDOW);789 if (minPurchaseDate < purchaseDate) {790 return true;791 }792 }793 }794 return false;795 }796 function isImmuneUrl(url) {797 return /\w+\:\/\/fullcalendar\.io\/|\/demos\/[\w-]+\.html$/.test(url);798 }799 registerResourceSourceDef({800 ignoreRange: true,801 parseMeta: function (raw) {802 if (Array.isArray(raw)) {803 return raw;804 }805 else if (Array.isArray(raw.resources)) {806 return raw.resources;807 }808 return null;809 },810 fetch: function (arg, successCallback) {811 successCallback({812 rawResources: arg.resourceSource.meta813 });814 }815 });816 registerResourceSourceDef({817 parseMeta: function (raw) {818 if (typeof raw === 'function') {819 return raw;820 }821 else if (typeof raw.resources === 'function') {822 return raw.resources;823 }824 return null;825 },826 fetch: function (arg, success, failure) {827 var dateEnv = arg.calendar.dateEnv;828 var func = arg.resourceSource.meta;829 var publicArg = {};830 if (arg.range) {831 publicArg = {832 start: dateEnv.toDate(arg.range.start),833 end: dateEnv.toDate(arg.range.end),834 startStr: dateEnv.formatIso(arg.range.start),835 endStr: dateEnv.formatIso(arg.range.end),836 timeZone: dateEnv.timeZone837 };838 }839 // TODO: make more dry with EventSourceFunc840 // TODO: accept a response?841 core.unpromisify(func.bind(null, publicArg), function (rawResources) {842 success({ rawResources: rawResources }); // needs an object response843 }, failure // send errorObj directly to failure callback844 );845 }846 });847 registerResourceSourceDef({848 parseMeta: function (raw) {849 if (typeof raw === 'string') {850 raw = { url: raw };851 }852 else if (!raw || typeof raw !== 'object' || !raw.url) {853 return null;854 }855 return {856 url: raw.url,857 method: (raw.method || 'GET').toUpperCase(),858 extraParams: raw.extraParams859 };860 },861 fetch: function (arg, successCallback, failureCallback) {862 var meta = arg.resourceSource.meta;863 var requestParams = buildRequestParams(meta, arg.range, arg.calendar);864 core.requestJson('GET', meta.url, requestParams, function (rawResources, xhr) {865 successCallback({ rawResources: rawResources, xhr: xhr });866 }, function (message, xhr) {867 failureCallback({ message: message, xhr: xhr });868 });869 }870 });871 // TODO: somehow consolidate with event json feed872 function buildRequestParams(meta, range, calendar) {873 var dateEnv = calendar.dateEnv;874 var startParam;875 var endParam;876 var timeZoneParam;877 var customRequestParams;878 var params = {};879 if (range) {880 // startParam = meta.startParam881 // if (startParam == null) {882 startParam = calendar.opt('startParam');883 // }884 // endParam = meta.endParam885 // if (endParam == null) {886 endParam = calendar.opt('endParam');887 // }888 // timeZoneParam = meta.timeZoneParam889 // if (timeZoneParam == null) {890 timeZoneParam = calendar.opt('timeZoneParam');891 // }892 params[startParam] = dateEnv.formatIso(range.start);893 params[endParam] = dateEnv.formatIso(range.end);894 if (dateEnv.timeZone !== 'local') {895 params[timeZoneParam] = dateEnv.timeZone;896 }897 }898 // retrieve any outbound GET/POST data from the options899 if (typeof meta.extraParams === 'function') {900 // supplied as a function that returns a key/value object901 customRequestParams = meta.extraParams();902 }903 else {904 // probably supplied as a straight key/value object905 customRequestParams = meta.extraParams || {};906 }907 __assign(params, customRequestParams);908 return params;909 }910 function buildResourceTextFunc(resourceTextSetting, calendar) {911 if (typeof resourceTextSetting === 'function') {912 return function (resource) {913 return resourceTextSetting(new ResourceApi(calendar, resource));914 };915 }916 else {917 return function (resource) {918 return resource.title || getPublicId(resource.id);919 };920 }921 }922 var ResourceDayHeader = /** @class */ (function (_super) {923 __extends(ResourceDayHeader, _super);924 function ResourceDayHeader(context, parentEl) {925 var _this = _super.call(this, context) || this;926 _this.datesAboveResources = _this.opt('datesAboveResources');927 _this.resourceTextFunc = buildResourceTextFunc(_this.opt('resourceText'), _this.calendar);928 parentEl.innerHTML = ''; // because might be nbsp929 parentEl.appendChild(_this.el = core.htmlToElement('<div class="fc-row ' + _this.theme.getClass('headerRow') + '">' +930 '<table class="' + _this.theme.getClass('tableGrid') + '">' +931 '<thead></thead>' +932 '</table>' +933 '</div>'));934 _this.thead = _this.el.querySelector('thead');935 return _this;936 }937 ResourceDayHeader.prototype.destroy = function () {938 core.removeElement(this.el);939 };940 ResourceDayHeader.prototype.render = function (props) {941 var html;942 this.dateFormat = core.createFormatter(this.opt('columnHeaderFormat') ||943 core.computeFallbackHeaderFormat(props.datesRepDistinctDays, props.dates.length));944 if (props.dates.length === 1) {945 html = this.renderResourceRow(props.resources);946 }947 else {948 if (this.datesAboveResources) {949 html = this.renderDayAndResourceRows(props.dates, props.resources);950 }951 else {952 html = this.renderResourceAndDayRows(props.resources, props.dates);953 }954 }955 this.thead.innerHTML = html;956 this.processResourceEls(props.resources);957 };958 ResourceDayHeader.prototype.renderResourceRow = function (resources) {959 var _this = this;960 var cellHtmls = resources.map(function (resource) {961 return _this.renderResourceCell(resource, 1);962 });963 return this.buildTr(cellHtmls);964 };965 ResourceDayHeader.prototype.renderDayAndResourceRows = function (dates, resources) {966 var dateHtmls = [];967 var resourceHtmls = [];968 for (var _i = 0, dates_1 = dates; _i < dates_1.length; _i++) {969 var date = dates_1[_i];970 dateHtmls.push(this.renderDateCell(date, resources.length));971 for (var _a = 0, resources_1 = resources; _a < resources_1.length; _a++) {972 var resource = resources_1[_a];973 resourceHtmls.push(this.renderResourceCell(resource, 1, date));974 }975 }976 return this.buildTr(dateHtmls) +977 this.buildTr(resourceHtmls);978 };979 ResourceDayHeader.prototype.renderResourceAndDayRows = function (resources, dates) {980 var resourceHtmls = [];981 var dateHtmls = [];982 for (var _i = 0, resources_2 = resources; _i < resources_2.length; _i++) {983 var resource = resources_2[_i];984 resourceHtmls.push(this.renderResourceCell(resource, dates.length));985 for (var _a = 0, dates_2 = dates; _a < dates_2.length; _a++) {986 var date = dates_2[_a];987 dateHtmls.push(this.renderDateCell(date, 1, resource));988 }989 }990 return this.buildTr(resourceHtmls) +991 this.buildTr(dateHtmls);992 };993 // Cell Rendering Utils994 // ----------------------------------------------------------------------------------------------995 // a cell with the resource name. might be associated with a specific day996 ResourceDayHeader.prototype.renderResourceCell = function (resource, colspan, date) {997 var dateEnv = this.dateEnv;998 return '<th class="fc-resource-cell"' +999 ' data-resource-id="' + resource.id + '"' +1000 (date ?1001 ' data-date="' + dateEnv.formatIso(date, { omitTime: true }) + '"' :1002 '') +1003 (colspan > 1 ?1004 ' colspan="' + colspan + '"' :1005 '') +1006 '>' +1007 core.htmlEscape(this.resourceTextFunc(resource)) +1008 '</th>';1009 };1010 // a cell with date text. might have a resource associated with it1011 ResourceDayHeader.prototype.renderDateCell = function (date, colspan, resource) {1012 var props = this.props;1013 return core.renderDateCell(date, props.dateProfile, props.datesRepDistinctDays, props.dates.length * props.resources.length, this.dateFormat, this.context, colspan, resource ? 'data-resource-id="' + resource.id + '"' : '');1014 };1015 ResourceDayHeader.prototype.buildTr = function (cellHtmls) {1016 if (!cellHtmls.length) {1017 cellHtmls = ['<td> </td>'];1018 }1019 if (this.props.renderIntroHtml) {1020 cellHtmls = [this.props.renderIntroHtml()].concat(cellHtmls);1021 }1022 if (this.isRtl) {1023 cellHtmls.reverse();1024 }1025 return '<tr>' +1026 cellHtmls.join('') +1027 '</tr>';1028 };1029 // Post-rendering1030 // ----------------------------------------------------------------------------------------------1031 // given a container with already rendered resource cells1032 ResourceDayHeader.prototype.processResourceEls = function (resources) {1033 var _this = this;1034 var view = this.view;1035 core.findElements(this.thead, '.fc-resource-cell').forEach(function (node, col) {1036 col = col % resources.length;1037 if (_this.isRtl) {1038 col = resources.length - 1 - col;1039 }1040 var resource = resources[col];1041 view.publiclyTrigger('resourceRender', [1042 {1043 resource: new ResourceApi(_this.calendar, resource),1044 el: node,1045 view: view1046 }1047 ]);1048 });1049 };1050 return ResourceDayHeader;1051 }(core.Component));1052 var AbstractResourceDayTable = /** @class */ (function () {1053 function AbstractResourceDayTable(dayTable, resources) {1054 this.dayTable = dayTable;1055 this.resources = resources;1056 this.resourceIndex = new ResourceIndex(resources);1057 this.rowCnt = dayTable.rowCnt;1058 this.colCnt = dayTable.colCnt * resources.length;1059 this.cells = this.buildCells();1060 }1061 AbstractResourceDayTable.prototype.buildCells = function () {1062 var _a = this, rowCnt = _a.rowCnt, dayTable = _a.dayTable, resources = _a.resources;1063 var rows = [];1064 for (var row = 0; row < rowCnt; row++) {1065 var rowCells = [];1066 for (var dateCol = 0; dateCol < dayTable.colCnt; dateCol++) {1067 for (var resourceCol = 0; resourceCol < resources.length; resourceCol++) {1068 var resource = resources[resourceCol];1069 var htmlAttrs = 'data-resource-id="' + resource.id + '"';1070 rowCells[this.computeCol(dateCol, resourceCol)] = {1071 date: dayTable.cells[row][dateCol].date,1072 resource: resource,1073 htmlAttrs: htmlAttrs1074 };1075 }1076 }1077 rows.push(rowCells);1078 }1079 return rows;1080 };1081 return AbstractResourceDayTable;1082 }());1083 /*1084 resources over dates1085 */1086 var ResourceDayTable = /** @class */ (function (_super) {1087 __extends(ResourceDayTable, _super);1088 function ResourceDayTable() {1089 return _super !== null && _super.apply(this, arguments) || this;1090 }1091 ResourceDayTable.prototype.computeCol = function (dateI, resourceI) {1092 return resourceI * this.dayTable.colCnt + dateI;1093 };1094 /*1095 all date ranges are intact1096 */1097 ResourceDayTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) {1098 return [1099 {1100 firstCol: this.computeCol(dateStartI, resourceI),1101 lastCol: this.computeCol(dateEndI, resourceI),1102 isStart: true,1103 isEnd: true1104 }1105 ];1106 };1107 return ResourceDayTable;1108 }(AbstractResourceDayTable));1109 /*1110 dates over resources1111 */1112 var DayResourceTable = /** @class */ (function (_super) {1113 __extends(DayResourceTable, _super);1114 function DayResourceTable() {1115 return _super !== null && _super.apply(this, arguments) || this;1116 }1117 DayResourceTable.prototype.computeCol = function (dateI, resourceI) {1118 return dateI * this.resources.length + resourceI;1119 };1120 /*1121 every single day is broken up1122 */1123 DayResourceTable.prototype.computeColRanges = function (dateStartI, dateEndI, resourceI) {1124 var segs = [];1125 for (var i = dateStartI; i <= dateEndI; i++) {1126 var col = this.computeCol(i, resourceI);1127 segs.push({1128 firstCol: col,1129 lastCol: col,1130 isStart: i === dateStartI,1131 isEnd: i === dateEndI1132 });1133 }1134 return segs;1135 };1136 return DayResourceTable;1137 }(AbstractResourceDayTable));1138 var ResourceIndex = /** @class */ (function () {1139 function ResourceIndex(resources) {1140 var indicesById = {};1141 var ids = [];1142 for (var i = 0; i < resources.length; i++) {1143 var id = resources[i].id;1144 ids.push(id);1145 indicesById[id] = i;1146 }1147 this.ids = ids;1148 this.indicesById = indicesById;1149 this.length = resources.length;1150 }1151 return ResourceIndex;1152 }());1153 /*1154 TODO: just use ResourceHash somehow? could then use the generic ResourceSplitter1155 */1156 var VResourceSplitter = /** @class */ (function (_super) {1157 __extends(VResourceSplitter, _super);1158 function VResourceSplitter() {1159 return _super !== null && _super.apply(this, arguments) || this;1160 }1161 VResourceSplitter.prototype.getKeyInfo = function (props) {1162 var resourceDayTable = props.resourceDayTable;1163 var hash = core.mapHash(resourceDayTable.resourceIndex.indicesById, function (i) {1164 return resourceDayTable.resources[i]; // has `ui` AND `businessHours` keys!1165 }); // :(1166 hash[''] = {};1167 return hash;1168 };1169 VResourceSplitter.prototype.getKeysForDateSpan = function (dateSpan) {1170 return [dateSpan.resourceId || ''];1171 };1172 VResourceSplitter.prototype.getKeysForEventDef = function (eventDef) {1173 var resourceIds = eventDef.resourceIds;1174 if (!resourceIds.length) {1175 return [''];1176 }1177 return resourceIds;1178 };1179 return VResourceSplitter;1180 }(core.Splitter));1181 // joiner1182 var NO_SEGS = []; // for memoizing1183 var VResourceJoiner = /** @class */ (function () {1184 function VResourceJoiner() {1185 this.joinDateSelection = core.memoize(this.joinSegs);1186 this.joinBusinessHours = core.memoize(this.joinSegs);1187 this.joinFgEvents = core.memoize(this.joinSegs);1188 this.joinBgEvents = core.memoize(this.joinSegs);1189 this.joinEventDrags = core.memoize(this.joinInteractions);1190 this.joinEventResizes = core.memoize(this.joinInteractions);1191 }1192 /*1193 propSets also has a '' key for things with no resource1194 */1195 VResourceJoiner.prototype.joinProps = function (propSets, resourceDayTable) {1196 var dateSelectionSets = [];1197 var businessHoursSets = [];1198 var fgEventSets = [];1199 var bgEventSets = [];1200 var eventDrags = [];1201 var eventResizes = [];1202 var eventSelection = '';1203 var keys = resourceDayTable.resourceIndex.ids.concat(['']); // add in the all-resource key1204 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {1205 var key = keys_1[_i];1206 var props = propSets[key];1207 dateSelectionSets.push(props.dateSelectionSegs);1208 businessHoursSets.push(key ? props.businessHourSegs : NO_SEGS); // don't include redundant all-resource businesshours1209 fgEventSets.push(key ? props.fgEventSegs : NO_SEGS); // don't include fg all-resource segs1210 bgEventSets.push(props.bgEventSegs);1211 eventDrags.push(props.eventDrag);1212 eventResizes.push(props.eventResize);1213 eventSelection = eventSelection || props.eventSelection;1214 }1215 return {1216 dateSelectionSegs: this.joinDateSelection.apply(this, [resourceDayTable].concat(dateSelectionSets)),1217 businessHourSegs: this.joinBusinessHours.apply(this, [resourceDayTable].concat(businessHoursSets)),1218 fgEventSegs: this.joinFgEvents.apply(this, [resourceDayTable].concat(fgEventSets)),1219 bgEventSegs: this.joinBgEvents.apply(this, [resourceDayTable].concat(bgEventSets)),1220 eventDrag: this.joinEventDrags.apply(this, [resourceDayTable].concat(eventDrags)),1221 eventResize: this.joinEventResizes.apply(this, [resourceDayTable].concat(eventResizes)),1222 eventSelection: eventSelection1223 };1224 };1225 VResourceJoiner.prototype.joinSegs = function (resourceDayTable) {1226 var segGroups = [];1227 for (var _i = 1; _i < arguments.length; _i++) {1228 segGroups[_i - 1] = arguments[_i];1229 }1230 var resourceCnt = resourceDayTable.resources.length;1231 var transformedSegs = [];1232 for (var i = 0; i < resourceCnt; i++) {1233 for (var _a = 0, _b = segGroups[i]; _a < _b.length; _a++) {1234 var seg = _b[_a];1235 transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i));1236 }1237 for (var _c = 0, _d = segGroups[resourceCnt]; _c < _d.length; _c++) { // one beyond. the all-resource1238 var seg = _d[_c];1239 transformedSegs.push.apply(// one beyond. the all-resource1240 transformedSegs, this.transformSeg(seg, resourceDayTable, i));1241 }1242 }1243 return transformedSegs;1244 };1245 /*1246 for expanding non-resource segs to all resources.1247 only for public use.1248 no memoizing.1249 */1250 VResourceJoiner.prototype.expandSegs = function (resourceDayTable, segs) {1251 var resourceCnt = resourceDayTable.resources.length;1252 var transformedSegs = [];1253 for (var i = 0; i < resourceCnt; i++) {1254 for (var _i = 0, segs_1 = segs; _i < segs_1.length; _i++) {1255 var seg = segs_1[_i];1256 transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i));1257 }1258 }1259 return transformedSegs;1260 };1261 VResourceJoiner.prototype.joinInteractions = function (resourceDayTable) {1262 var interactions = [];1263 for (var _i = 1; _i < arguments.length; _i++) {1264 interactions[_i - 1] = arguments[_i];1265 }1266 var resourceCnt = resourceDayTable.resources.length;1267 var affectedInstances = {};1268 var transformedSegs = [];1269 var isEvent = false;1270 var sourceSeg = null;1271 for (var i = 0; i < resourceCnt; i++) {1272 var interaction = interactions[i];1273 if (interaction) {1274 for (var _a = 0, _b = interaction.segs; _a < _b.length; _a++) {1275 var seg = _b[_a];1276 transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs1277 );1278 }1279 __assign(affectedInstances, interaction.affectedInstances);1280 isEvent = isEvent || interaction.isEvent;1281 sourceSeg = sourceSeg || interaction.sourceSeg;1282 }1283 if (interactions[resourceCnt]) { // one beyond. the all-resource1284 for (var _c = 0, _d = interactions[resourceCnt].segs; _c < _d.length; _c++) {1285 var seg = _d[_c];1286 transformedSegs.push.apply(transformedSegs, this.transformSeg(seg, resourceDayTable, i) // TODO: templateify Interaction::segs1287 );1288 }1289 }1290 }1291 return {1292 affectedInstances: affectedInstances,1293 segs: transformedSegs,1294 isEvent: isEvent,1295 sourceSeg: sourceSeg1296 };1297 };1298 return VResourceJoiner;1299 }());1300 /*1301 doesn't accept grouping1302 */1303 function flattenResources(resourceStore, orderSpecs) {1304 return buildRowNodes(resourceStore, [], orderSpecs, false, {}, true)1305 .map(function (node) {1306 return node.resource;1307 });1308 }1309 function buildRowNodes(resourceStore, groupSpecs, orderSpecs, isVGrouping, expansions, expansionDefault) {1310 var complexNodes = buildHierarchy(resourceStore, isVGrouping ? -1 : 1, groupSpecs, orderSpecs);1311 var flatNodes = [];1312 flattenNodes(complexNodes, flatNodes, isVGrouping, [], 0, expansions, expansionDefault);1313 return flatNodes;1314 }1315 function flattenNodes(complexNodes, res, isVGrouping, rowSpans, depth, expansions, expansionDefault) {1316 for (var i = 0; i < complexNodes.length; i++) {1317 var complexNode = complexNodes[i];1318 var group = complexNode.group;1319 if (group) {1320 if (isVGrouping) {1321 var firstRowIndex = res.length;1322 var rowSpanIndex = rowSpans.length;1323 flattenNodes(complexNode.children, res, isVGrouping, rowSpans.concat(0), depth, expansions, expansionDefault);1324 if (firstRowIndex < res.length) {1325 var firstRow = res[firstRowIndex];1326 var firstRowSpans = firstRow.rowSpans = firstRow.rowSpans.slice();1327 firstRowSpans[rowSpanIndex] = res.length - firstRowIndex;1328 }1329 }1330 else {1331 var id = group.spec.field + ':' + group.value;1332 var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault;1333 res.push({ id: id, group: group, isExpanded: isExpanded });1334 if (isExpanded) {1335 flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault);1336 }1337 }1338 }1339 else if (complexNode.resource) {1340 var id = complexNode.resource.id;1341 var isExpanded = expansions[id] != null ? expansions[id] : expansionDefault;1342 res.push({1343 id: id,1344 rowSpans: rowSpans,1345 depth: depth,1346 isExpanded: isExpanded,1347 hasChildren: Boolean(complexNode.children.length),1348 resource: complexNode.resource,1349 resourceFields: complexNode.resourceFields1350 });1351 if (isExpanded) {1352 flattenNodes(complexNode.children, res, isVGrouping, rowSpans, depth + 1, expansions, expansionDefault);1353 }1354 }1355 }1356 }1357 function buildHierarchy(resourceStore, maxDepth, groupSpecs, orderSpecs) {1358 var resourceNodes = buildResourceNodes(resourceStore, orderSpecs);1359 var builtNodes = [];1360 for (var resourceId in resourceNodes) {1361 var resourceNode = resourceNodes[resourceId];1362 if (!resourceNode.resource.parentId) {1363 insertResourceNode(resourceNode, builtNodes, groupSpecs, 0, maxDepth, orderSpecs);1364 }1365 }1366 return builtNodes;1367 }1368 function buildResourceNodes(resourceStore, orderSpecs) {1369 var nodeHash = {};1370 for (var resourceId in resourceStore) {1371 var resource = resourceStore[resourceId];1372 nodeHash[resourceId] = {1373 resource: resource,1374 resourceFields: buildResourceFields(resource),1375 children: []1376 };1377 }1378 for (var resourceId in resourceStore) {1379 var resource = resourceStore[resourceId];1380 if (resource.parentId) {1381 var parentNode = nodeHash[resource.parentId];1382 if (parentNode) {1383 insertResourceNodeInSiblings(nodeHash[resourceId], parentNode.children, orderSpecs);1384 }1385 }1386 }1387 return nodeHash;1388 }1389 function insertResourceNode(resourceNode, nodes, groupSpecs, depth, maxDepth, orderSpecs) {1390 if (groupSpecs.length && (maxDepth === -1 || depth <= maxDepth)) {1391 var groupNode = ensureGroupNodes(resourceNode, nodes, groupSpecs[0]);1392 insertResourceNode(resourceNode, groupNode.children, groupSpecs.slice(1), depth + 1, maxDepth, orderSpecs);1393 }1394 else {1395 insertResourceNodeInSiblings(resourceNode, nodes, orderSpecs);1396 }1397 }1398 function ensureGroupNodes(resourceNode, nodes, groupSpec) {1399 var groupValue = resourceNode.resourceFields[groupSpec.field];1400 var groupNode;1401 var newGroupIndex;1402 // find an existing group that matches, or determine the position for a new group1403 if (groupSpec.order) {1404 for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) {1405 var node = nodes[newGroupIndex];1406 if (node.group) {1407 var cmp = core.flexibleCompare(groupValue, node.group.value) * groupSpec.order;1408 if (cmp === 0) {1409 groupNode = node;1410 break;1411 }1412 else if (cmp < 0) {1413 break;1414 }1415 }1416 }1417 }1418 else { // the groups are unordered1419 for (newGroupIndex = 0; newGroupIndex < nodes.length; newGroupIndex++) {1420 var node = nodes[newGroupIndex];1421 if (node.group && groupValue === node.group.value) {1422 groupNode = node;1423 break;1424 }1425 }1426 }1427 if (!groupNode) {1428 groupNode = {1429 group: {1430 value: groupValue,1431 spec: groupSpec1432 },1433 children: []1434 };1435 nodes.splice(newGroupIndex, 0, groupNode);1436 }1437 return groupNode;1438 }1439 function insertResourceNodeInSiblings(resourceNode, siblings, orderSpecs) {1440 var i;1441 for (i = 0; i < siblings.length; i++) {1442 var cmp = core.compareByFieldSpecs(siblings[i].resourceFields, resourceNode.resourceFields, orderSpecs);1443 if (cmp > 0) { // went 1 past. insert at i1444 break;1445 }1446 }1447 siblings.splice(i, 0, resourceNode);1448 }1449 function buildResourceFields(resource) {1450 var obj = __assign({}, resource.extendedProps, resource.ui, resource);1451 delete obj.ui;1452 delete obj.extendedProps;1453 return obj;1454 }1455 function isGroupsEqual(group0, group1) {1456 return group0.spec === group1.spec && group0.value === group1.value;1457 }1458 var main = core.createPlugin({1459 reducers: [resourcesReducers],1460 eventDefParsers: [parseEventDef],1461 eventDragMutationMassagers: [massageEventDragMutation],1462 eventDefMutationAppliers: [applyEventDefMutation],1463 dateSelectionTransformers: [transformDateSelectionJoin],1464 datePointTransforms: [transformDatePoint],1465 dateSpanTransforms: [transformDateSpan],1466 viewPropsTransformers: [ResourceDataAdder, ResourceEventConfigAdder],1467 isPropsValid: isPropsValidWithResources,1468 externalDefTransforms: [transformExternalDef],1469 eventResizeJoinTransforms: [transformEventResizeJoin],1470 viewContainerModifiers: [injectLicenseWarning],1471 eventDropTransformers: [transformEventDrop]1472 });1473 exports.default = main;1474 exports.ResourceDayHeader = ResourceDayHeader;1475 exports.VResourceJoiner = VResourceJoiner;1476 exports.AbstractResourceDayTable = AbstractResourceDayTable;1477 exports.ResourceDayTable = ResourceDayTable;1478 exports.DayResourceTable = DayResourceTable;1479 exports.VResourceSplitter = VResourceSplitter;1480 exports.flattenResources = flattenResources;1481 exports.isGroupsEqual = isGroupsEqual;1482 exports.buildRowNodes = buildRowNodes;1483 exports.buildResourceFields = buildResourceFields;1484 exports.buildResourceTextFunc = buildResourceTextFunc;1485 exports.ResourceApi = ResourceApi;1486 exports.computeResourceEditable = computeResourceEditable;1487 exports.ResourceSplitter = ResourceSplitter;1488 Object.defineProperty(exports, '__esModule', { value: true });...
factory.py
Source:factory.py
...385 along the instance's low-level `client` to the new resource386 class' constructor.387 """388 name = subresource_model.resource.type389 def create_resource(self, *args, **kwargs):390 # We need a new method here because we want access to the391 # instance's client.392 positional_args = []393 # We lazy-load the class to handle circular references.394 json_def = service_context.resource_json_definitions.get(name, {})395 resource_cls = factory_self.load_from_definition(396 resource_name=name,397 single_resource_json_definition=json_def,398 service_context=service_context399 )400 # Assumes that identifiers are in order, which lets you do401 # e.g. ``sqs.Queue('foo').Message('bar')`` to create a new message402 # linked with the ``foo`` queue and which has a ``bar`` receipt403 # handle. If we did kwargs here then future positional arguments...
testresources.py
Source:testresources.py
1# testresources: extensions to python unittest to allow declaritive use2# of resources by test cases.3# Copyright (C) 2005 Robert Collins <robertc@robertcollins.net>4#5# This program is free software; you can redistribute it and/or modify6# it under the terms of the GNU General Public License as published by7# the Free Software Foundation; either version 2 of the License, or8# (at your option) any later version.9#10# This program is distributed in the hope that it will be useful,11# but WITHOUT ANY WARRANTY; without even the implied warranty of12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13# GNU General Public License for more details.14#15# You should have received a copy of the GNU General Public License16# along with this program; if not, write to the Free Software17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18#19import inspect20import unittest21def test_suite():22 import testresources.tests23 return testresources.tests.test_suite()24def split_by_resources(tests):25 """Split a list of tests by the resources that the tests use.26 :return: a dictionary mapping sets of resources to lists of tests27 using that combination of resources. The dictionary always28 contains an entry for "no resources".29 """30 no_resources = frozenset()31 resource_set_tests = {no_resources: []}32 for test in tests:33 resources = getattr(test, "resources", ())34 all_resources = list(resource.neededResources() for _, resource in resources)35 resource_set = set()36 for resource_list in all_resources:37 resource_set.update(resource_list)38 resource_set_tests.setdefault(frozenset(resource_set), []).append(test)39 return resource_set_tests40class OptimisingTestSuite(unittest.TestSuite):41 """A resource creation optimising TestSuite."""42 def adsorbSuite(self, test_case_or_suite):43 """Deprecated. Use addTest instead."""44 self.addTest(test_case_or_suite)45 def addTest(self, test_case_or_suite):46 """Add `test_case_or_suite`, unwrapping standard TestSuites.47 This means that any containing unittest.TestSuites will be removed,48 while any custom test suites will be 'distributed' across their49 members. Thus addTest(CustomSuite([a, b])) will result in50 CustomSuite([a]) and CustomSuite([b]) being added to this suite.51 """52 try:53 tests = iter(test_case_or_suite)54 except TypeError:55 unittest.TestSuite.addTest(self, test_case_or_suite)56 return57 if test_case_or_suite.__class__ in (unittest.TestSuite, OptimisingTestSuite):58 for test in tests:59 self.adsorbSuite(test)60 else:61 for test in tests:62 unittest.TestSuite.addTest(63 self, test_case_or_suite.__class__([test]))64 def cost_of_switching(self, old_resource_set, new_resource_set):65 """Cost of switching from 'old_resource_set' to 'new_resource_set'.66 This is calculated by adding the cost of tearing down unnecessary67 resources to the cost of setting up the newly-needed resources.68 Note that resources which are always dirtied may skew the predicted69 skew the cost of switching because they are considered common, even70 when reusing them may actually be equivalent to a teardown+setup71 operation.72 """73 new_resources = new_resource_set - old_resource_set74 gone_resources = old_resource_set - new_resource_set75 return (sum(resource.setUpCost for resource in new_resources) +76 sum(resource.tearDownCost for resource in gone_resources))77 def switch(self, old_resource_set, new_resource_set, result):78 """Switch from 'old_resource_set' to 'new_resource_set'.79 Tear down resources in old_resource_set that aren't in80 new_resource_set and set up resources that are in new_resource_set but81 not in old_resource_set.82 :param result: TestResult object to report activity on.83 """84 new_resources = new_resource_set - old_resource_set85 old_resources = old_resource_set - new_resource_set86 for resource in old_resources:87 resource.finishedWith(resource._currentResource, result)88 for resource in new_resources:89 resource.getResource(result)90 def run(self, result):91 self.sortTests()92 current_resources = set()93 for test in self._tests:94 if result.shouldStop:95 break96 resources = getattr(test, 'resources', [])97 new_resources = set()98 for name, resource in resources:99 new_resources.update(resource.neededResources())100 self.switch(current_resources, new_resources, result)101 current_resources = new_resources102 test(result)103 self.switch(current_resources, set(), result)104 return result105 def _arrange(self, by_res_comb):106 """Sorts by_res_comb's values using a greedy cost-minimizing107 heuristic.108 by_res_comb maps sets of resources used to a list of the109 corresponding tests. The heuristic works by figuring out the110 test most expensive to set up and collecting all resource111 sets that contain it. It will then separately arrange112 this test subset and the set of tests not requiring this113 currently most expensive test.114 The recursion stops when only one (or less) resource set115 is left in by_res_comb.116 """117 if not by_res_comb:118 return []119 if len(by_res_comb)==1:120 return by_res_comb.values()[0]121 most_expensive_here = max(reduce(122 lambda a,b: a.union(b),123 by_res_comb),124 key=lambda res: res.setUpCost)125 126 with_most_expensive, not_handled = {}, {}127 for res_required in by_res_comb:128 if most_expensive_here in res_required:129 with_most_expensive[130 res_required-frozenset((most_expensive_here,))131 ] = by_res_comb[res_required]132 else:133 not_handled[res_required] = by_res_comb[res_required]134 135 return self._arrange(with_most_expensive136 )+self._arrange(not_handled)137 def sortTests(self):138 """Sorts _tests in some way that minimizes the total cost139 of creating and deleting resources.140 We're using a heuristic where we attempt to keep the most141 expensive resources unchanged for the longest time.142 """143 resource_set_tests = split_by_resources(self._tests)144 self._tests = self._arrange(resource_set_tests)145class TestLoader(unittest.TestLoader):146 """Custom TestLoader to set the right TestSuite class."""147 suiteClass = OptimisingTestSuite148class TestResource(object):149 """A resource that can be shared across tests.150 Resources can report activity to a TestResult. The methods151 - startCleanResource(resource)152 - stopCleanResource(resource)153 - startMakeResource(resource)154 - stopMakeResource(resource)155 will be looked for and if present invoked before and after cleaning or156 creation of resource objects takes place.157 :cvar resources: The same as the resources list on an instance, the default158 constructor will look for the class instance and copy it. This is a159 convenience to avoid needing to define __init__ solely to alter the160 dependencies list.161 :ivar resources: The resources that this resource needs. Calling162 neededResources will return the closure of this resource and its needed163 resources. The resources list is in the same format as resources on a 164 test case - a list of tuples (attribute_name, resource).165 :ivar setUpCost: The relative cost to construct a resource of this type.166 One good approach is to set this to the number of seconds it normally167 takes to set up the resource.168 :ivar tearDownCost: The relative cost to tear down a resource of this169 type. One good approach is to set this to the number of seconds it170 normally takes to tear down the resource.171 """172 setUpCost = 1173 tearDownCost = 1174 def __init__(self):175 """Create a TestResource object."""176 self._dirty = False177 self._uses = 0178 self._currentResource = None179 self.resources = list(getattr(self.__class__, "resources", []))180 def _call_result_method_if_exists(self, result, methodname, *args):181 """Call a method on a TestResult that may exist."""182 method = getattr(result, methodname, None)183 if callable(method):184 method(*args)185 def _clean_all(self, resource, result):186 """Clean the dependencies from resource, and then resource itself."""187 self._call_result_method_if_exists(result, "startCleanResource", self)188 self.clean(resource)189 for name, manager in self.resources:190 manager.finishedWith(getattr(self, name))191 self._call_result_method_if_exists(result, "stopCleanResource", self)192 def clean(self, resource):193 """Override this to class method to hook into resource removal."""194 def dirtied(self, resource):195 """Mark the resource as having been 'dirtied'.196 A resource is dirty when it is no longer suitable for use by other197 tests.198 e.g. a shared database that has had rows changed.199 """200 self._dirty = True201 def finishedWith(self, resource, result=None):202 """Indicate that 'resource' has one less user.203 If there are no more registered users of 'resource' then we trigger204 the `clean` hook, which should do any resource-specific205 cleanup.206 :param resource: A resource returned by `TestResource.getResource`.207 :param result: An optional TestResult to report resource changes to.208 """209 self._uses -= 1210 if self._uses == 0:211 self._clean_all(resource, result)212 self._setResource(None)213 def getResource(self, result=None):214 """Get the resource for this class and record that it's being used.215 The resource is constructed using the `make` hook.216 Once done with the resource, pass it to `finishedWith` to indicated217 that it is no longer needed.218 :param result: An optional TestResult to report resource changes to.219 """220 if self._uses == 0:221 self._setResource(self._make_all(result))222 elif self.isDirty():223 self._setResource(self.reset(self._currentResource, result))224 self._uses += 1225 return self._currentResource226 def isDirty(self):227 """Return True if this managers cached resource is dirty.228 229 Calling when the resource is not currently held has undefined230 behaviour.231 """232 if self._dirty:233 return True234 for name, mgr in self.resources:235 if mgr.isDirty():236 return True237 res = mgr.getResource()238 try:239 if res is not getattr(self, name):240 return True241 finally:242 mgr.finishedWith(res)243 def _make_all(self, result):244 """Make the dependencies of this resource and this resource."""245 self._call_result_method_if_exists(result, "startMakeResource", self)246 dependency_resources = {}247 for name, resource in self.resources:248 dependency_resources[name] = resource.getResource()249 resource = self.make(dependency_resources)250 for name, value in dependency_resources.items():251 setattr(self, name, value)252 self._call_result_method_if_exists(result, "stopMakeResource", self)253 return resource254 def make(self, dependency_resources):255 """Override this to construct resources.256 257 :param dependency_resources: A dict mapping name -> resource instance258 for the resources specified as dependencies.259 """260 raise NotImplementedError(261 "Override make to construct resources.")262 def neededResources(self):263 """Return the resources needed for this resource, including self.264 265 :return: A list of needed resources, in topological deepest-first266 order.267 """268 seen = set([self])269 result = []270 for name, resource in self.resources:271 for resource in resource.neededResources():272 if resource in seen:273 continue274 seen.add(resource)275 result.append(resource)276 result.append(self)277 return result278 def reset(self, old_resource, result=None):279 """Overridable method to return a clean version of old_resource.280 By default, the resource will be cleaned then remade if it had281 previously been `dirtied`. 282 This function needs to take the dependent resource stack into283 consideration as _make_all and _clean_all do.284 :return: The new resource.285 :param result: An optional TestResult to report resource changes to.286 """287 if self._dirty:288 self._clean_all(old_resource, result)289 resource = self._make_all(result)290 else:291 resource = old_resource292 return resource293 def _setResource(self, new_resource):294 """Set the current resource to a new value."""295 self._currentResource = new_resource296 self._dirty = False297class ResourcedTestCase(unittest.TestCase):298 """A TestCase parent or utility that enables cross-test resource usage.299 :ivar resources: A list of (name, resource) pairs, where 'resource' is a300 subclass of `TestResource` and 'name' is the name of the attribute301 that the resource should be stored on.302 """303 resources = []304 def __get_result(self):305 # unittest hides the result. This forces us to look up the stack.306 # The result is passed to a run() or a __call__ method 4 or more frames307 # up: that method is what calls setUp and tearDown, and they call their308 # parent setUp etc. Its not guaranteed that the parameter to run will309 # be calls result as its not required to be a keyword parameter in 310 # TestCase. However, in practice, this works.311 stack = inspect.stack()312 for frame in stack[3:]:313 if frame[3] in ('run', '__call__'):314 # Not all frames called 'run' will be unittest. It could be a315 # reactor in trial, for instance.316 result = frame[0].f_locals.get('result')317 if (result is not None and318 getattr(result, 'startTest', None) is not None):319 return result320 def setUp(self):321 unittest.TestCase.setUp(self)322 self.setUpResources()323 def setUpResources(self):324 """Set up any resources that this test needs."""325 result = self.__get_result()326 for resource in self.resources:327 setattr(self, resource[0], resource[1].getResource(result))328 def tearDown(self):329 self.tearDownResources()330 unittest.TestCase.tearDown(self)331 def tearDownResources(self):332 """Tear down any resources that this test declares."""333 result = self.__get_result()334 for resource in self.resources:335 resource[1].finishedWith(getattr(self, resource[0]), result)336 delattr(self, resource[0])...
IonResourceSpec.js
Source:IonResourceSpec.js
1import { Ion } from "../../Source/Cesium.js";2import { IonResource } from "../../Source/Cesium.js";3import { RequestErrorEvent } from "../../Source/Cesium.js";4import { Resource } from "../../Source/Cesium.js";5import { RuntimeError } from "../../Source/Cesium.js";6import { when } from "../../Source/Cesium.js";7describe("Core/IonResource", function () {8 var assetId = 123890213;9 var endpoint = {10 type: "3DTILES",11 url: "https://assets.cesium.com/" + assetId + "/tileset.json",12 accessToken: "not_really_a_refresh_token",13 attributions: [],14 };15 it("constructs with expected values", function () {16 spyOn(Resource, "call").and.callThrough();17 var endpointResource = IonResource._createEndpointResource(assetId);18 var resource = new IonResource(endpoint, endpointResource);19 expect(resource).toBeInstanceOf(Resource);20 expect(resource._ionEndpoint).toEqual(endpoint);21 expect(Resource.call).toHaveBeenCalledWith(resource, {22 url: endpoint.url,23 retryCallback: resource.retryCallback,24 retryAttempts: 1,25 });26 });27 it("clone works", function () {28 var endpointResource = IonResource._createEndpointResource(assetId);29 var resource = new IonResource(endpoint, endpointResource);30 var cloned = resource.clone();31 expect(cloned).not.toBe(resource);32 expect(cloned._ionRoot).toBe(resource);33 cloned._ionRoot = undefined;34 expect(cloned.retryCallback).toBe(resource.retryCallback);35 expect(cloned.headers.Authorization).toBe(resource.headers.Authorization);36 expect(cloned).toEqual(resource);37 });38 it("create creates the expected resource", function () {39 var endpointResource = IonResource._createEndpointResource(assetId);40 var resource = new IonResource(endpoint, endpointResource);41 expect(resource.getUrlComponent()).toEqual(endpoint.url);42 expect(resource._ionEndpoint).toBe(endpoint);43 expect(resource._ionEndpointResource).toEqual(endpointResource);44 expect(resource.retryCallback).toBeDefined();45 expect(resource.retryAttempts).toBe(1);46 });47 it("fromAssetId calls constructor for non-external endpoint with expected parameters", function () {48 var tilesAssetId = 123890213;49 var tilesEndpoint = {50 type: "3DTILES",51 url: "https://assets.cesium.com/" + tilesAssetId + "/tileset.json",52 accessToken: "not_really_a_refresh_token",53 attributions: [],54 };55 var options = {};56 var resourceEndpoint = IonResource._createEndpointResource(57 tilesAssetId,58 options59 );60 spyOn(IonResource, "_createEndpointResource").and.returnValue(61 resourceEndpoint62 );63 spyOn(resourceEndpoint, "fetchJson").and.returnValue(64 when.resolve(tilesEndpoint)65 );66 return IonResource.fromAssetId(tilesAssetId, options).then(function (67 resource68 ) {69 expect(IonResource._createEndpointResource).toHaveBeenCalledWith(70 tilesAssetId,71 options72 );73 expect(resourceEndpoint.fetchJson).toHaveBeenCalled();74 expect(resource._ionEndpointResource).toEqual(resourceEndpoint);75 expect(resource._ionEndpoint).toEqual(tilesEndpoint);76 });77 });78 function testNonImageryExternalResource(externalEndpoint) {79 var resourceEndpoint = IonResource._createEndpointResource(123890213);80 spyOn(IonResource, "_createEndpointResource").and.returnValue(81 resourceEndpoint82 );83 spyOn(resourceEndpoint, "fetchJson").and.returnValue(84 when.resolve(externalEndpoint)85 );86 return IonResource.fromAssetId(123890213).then(function (resource) {87 expect(resource.url).toEqual(externalEndpoint.options.url);88 expect(resource.headers.Authorization).toBeUndefined();89 expect(resource.retryCallback).toBeUndefined();90 });91 }92 it("fromAssetId returns basic Resource for external 3D tilesets", function () {93 return testNonImageryExternalResource({94 type: "3DTILES",95 externalType: "3DTILES",96 options: { url: "http://test.invalid/tileset.json" },97 attributions: [],98 });99 });100 it("fromAssetId returns basic Resource for external 3D tilesets", function () {101 return testNonImageryExternalResource({102 type: "TERRAIN",103 externalType: "STK_TERRAIN_SERVER",104 options: { url: "http://test.invalid/world" },105 attributions: [],106 });107 });108 it("fromAssetId rejects for external imagery", function () {109 return testNonImageryExternalResource({110 type: "IMAGERY",111 externalType: "URL_TEMPLATE",112 url: "http://test.invalid/world",113 attributions: [],114 })115 .then(fail)116 .otherwise(function (e) {117 expect(e).toBeInstanceOf(RuntimeError);118 });119 });120 it("createEndpointResource creates expected values with default parameters", function () {121 var assetId = 2348234;122 var resource = IonResource._createEndpointResource(assetId);123 expect(resource.url).toBe(124 Ion.defaultServer.url +125 "v1/assets/" +126 assetId +127 "/endpoint?access_token=" +128 Ion.defaultAccessToken129 );130 });131 it("createEndpointResource creates expected values with overridden options", function () {132 var serverUrl = "https://api.cesium.test/";133 var accessToken = "not_a_token";134 var assetId = 2348234;135 var resource = IonResource._createEndpointResource(assetId, {136 server: serverUrl,137 accessToken: accessToken,138 });139 expect(resource.url).toBe(140 serverUrl +141 "v1/assets/" +142 assetId +143 "/endpoint?access_token=" +144 accessToken145 );146 });147 it("createEndpointResource creates expected values with overridden defaults", function () {148 var defaultServer = Ion.defaultServer;149 var defaultAccessToken = Ion.defaultAccessToken;150 Ion.defaultServer = new Resource({ url: "https://api.cesium.test/" });151 Ion.defaultAccessToken = "not_a_token";152 var assetId = 2348234;153 var resource = IonResource._createEndpointResource(assetId);154 expect(resource.url).toBe(155 Ion.defaultServer.url +156 "v1/assets/" +157 assetId +158 "/endpoint?access_token=" +159 Ion.defaultAccessToken160 );161 Ion.defaultServer = defaultServer;162 Ion.defaultAccessToken = defaultAccessToken;163 });164 it("Calls base _makeRequest with expected options when resource no Authorization header is defined", function () {165 var originalOptions = {};166 var expectedOptions = {167 headers: {168 Authorization: "Bearer " + endpoint.accessToken,169 },170 };171 var _makeRequest = spyOn(Resource.prototype, "_makeRequest");172 var endpointResource = IonResource._createEndpointResource(assetId);173 var resource = new IonResource(endpoint, endpointResource);174 resource._makeRequest(originalOptions);175 expect(_makeRequest).toHaveBeenCalledWith(expectedOptions);176 });177 it("Calls base _makeRequest with expected options when resource Authorization header is already defined", function () {178 var originalOptions = {};179 var expectedOptions = {180 headers: {181 Authorization: "Bearer " + endpoint.accessToken,182 },183 };184 var _makeRequest = spyOn(Resource.prototype, "_makeRequest");185 var endpointResource = IonResource._createEndpointResource(assetId);186 var resource = new IonResource(endpoint, endpointResource);187 resource.headers.Authorization = "Not valid";188 resource._makeRequest(originalOptions);189 expect(_makeRequest).toHaveBeenCalledWith(expectedOptions);190 });191 it("Calls base _makeRequest with no changes for external assets", function () {192 var externalEndpoint = {193 type: "3DTILES",194 externalType: "3DTILES",195 options: { url: "http://test.invalid/tileset.json" },196 attributions: [],197 };198 var options = {};199 var _makeRequest = spyOn(Resource.prototype, "_makeRequest");200 var endpointResource = IonResource._createEndpointResource(assetId);201 var resource = new IonResource(externalEndpoint, endpointResource);202 resource._makeRequest(options);203 expect(_makeRequest.calls.argsFor(0)[0]).toBe(options);204 });205 it("Calls base _makeRequest with no changes for ion assets with external urls", function () {206 var originalOptions = {};207 var expectedOptions = {};208 var _makeRequest = spyOn(Resource.prototype, "_makeRequest");209 var endpointResource = IonResource._createEndpointResource(assetId);210 var resource = new IonResource(endpoint, endpointResource);211 resource.url = "http://test.invalid";212 resource._makeRequest(originalOptions);213 expect(_makeRequest).toHaveBeenCalledWith(expectedOptions);214 });215 it("Calls base fetchImage with preferBlob for ion assets", function () {216 var fetchImage = spyOn(Resource.prototype, "fetchImage");217 var endpointResource = IonResource._createEndpointResource(assetId);218 var resource = new IonResource(endpoint, endpointResource);219 resource.fetchImage();220 expect(fetchImage).toHaveBeenCalledWith({221 preferBlob: true,222 });223 });224 it("Calls base fetchImage with no changes for external assets", function () {225 var externalEndpoint = {226 type: "3DTILES",227 externalType: "3DTILES",228 options: { url: "http://test.invalid/tileset.json" },229 attributions: [],230 };231 var fetchImage = spyOn(Resource.prototype, "fetchImage");232 var endpointResource = IonResource._createEndpointResource(assetId);233 var resource = new IonResource(externalEndpoint, endpointResource);234 resource.fetchImage({235 preferBlob: false,236 });237 expect(fetchImage).toHaveBeenCalledWith({238 preferBlob: false,239 });240 });241 describe("retryCallback", function () {242 var endpointResource;243 var resource;244 var retryCallback;245 beforeEach(function () {246 endpointResource = new Resource({247 url: "https://api.test.invalid",248 access_token: "not_the_token",249 });250 resource = new IonResource(endpoint, endpointResource);251 retryCallback = resource.retryCallback;252 });253 it("returns false when error is undefined", function () {254 return retryCallback(resource, undefined).then(function (result) {255 expect(result).toBe(false);256 });257 });258 it("returns false when error is non-401", function () {259 var error = new RequestErrorEvent(404);260 return retryCallback(resource, error).then(function (result) {261 expect(result).toBe(false);262 });263 });264 it("returns false when error is event with non-Image target", function () {265 var event = { target: {} };266 return retryCallback(resource, event).then(function (result) {267 expect(result).toBe(false);268 });269 });270 function testCallback(resource, event) {271 var deferred = when.defer();272 spyOn(endpointResource, "fetchJson").and.returnValue(deferred.promise);273 var newEndpoint = {274 type: "3DTILES",275 url: "https://assets.cesium.com/" + assetId,276 accessToken: "not_not_really_a_refresh_token",277 };278 var promise = retryCallback(resource, event);279 var resultPromise = promise.then(function (result) {280 expect(result).toBe(true);281 expect(resource._ionEndpoint).toBe(newEndpoint);282 });283 expect(endpointResource.fetchJson).toHaveBeenCalledWith();284 //A second retry should re-use the same pending promise285 var promise2 = retryCallback(resource, event);286 expect(promise._pendingPromise).toBe(promise2._pendingPromise);287 deferred.resolve(newEndpoint);288 return resultPromise;289 }290 it("works when error is a 401", function () {291 var error = new RequestErrorEvent(401);292 return testCallback(resource, error);293 });294 it("works when error is event with Image target", function () {295 var event = { target: new Image() };296 return testCallback(resource, event);297 });298 it("works with derived resource and sets root access_token", function () {299 var derived = resource.getDerivedResource("1");300 var error = new RequestErrorEvent(401);301 return testCallback(derived, error).then(function () {302 expect(derived._ionEndpoint).toBe(resource._ionEndpoint);303 expect(derived.headers.Authorization).toEqual(304 resource.headers.Authorization305 );306 });307 });308 });...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!