Merge pull request #380 from aliabufoul/release-2.18.7

Release 2.18.7
This commit is contained in:
submarine-launched 2021-12-12 11:49:55 +02:00 коммит произвёл GitHub
Родитель 9ae72e5a89 5a90d7d630
Коммит 70119ae752
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
29 изменённых файлов: 6194 добавлений и 6623 удалений

Просмотреть файл

@ -1,2 +1,5 @@
# Task 512388: Fix eslint warnings and errors in tests
test/*
/node_modules/*
demo/*
/**/*.js
dist/*

Просмотреть файл

@ -21,14 +21,9 @@ module.exports = {
],
"rules": {
"@typescript-eslint/adjacent-overload-signatures": "warn",
"@typescript-eslint/array-type": [
"warn",
{
"default": "array-simple"
}
],
"@typescript-eslint/array-type": "off",
"@typescript-eslint/await-thenable": "warn",
"@typescript-eslint/ban-ts-comment": "warn",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": [
"warn",
{
@ -36,9 +31,8 @@ module.exports = {
"Object": {
"message": "Avoid using the `Object` type. Did you mean `object`?"
},
"Function": {
"message": "Avoid using the `Function` type. Prefer a specific function type, like `() => void`."
},
"Function": false,
"object": false,
"Boolean": {
"message": "Avoid using the `Boolean` type. Did you mean `boolean`?"
},
@ -54,16 +48,18 @@ module.exports = {
}
}
],
"@typescript-eslint/consistent-type-assertions": "warn",
"@typescript-eslint/consistent-type-definitions": "warn",
"@typescript-eslint/dot-notation": "warn",
"@typescript-eslint/dot-notation": "off",
"@typescript-eslint/explicit-member-accessibility": [
"off",
{
"accessibility": "explicit"
}
],
"@typescript-eslint/explicit-module-boundary-types": "warn",
"@typescript-eslint/explicit-module-boundary-types": [
"warn",
{ "allowArgumentsExplicitlyTypedAsAny": true }
],
"@typescript-eslint/indent": [
"warn",
2,
@ -90,6 +86,13 @@ module.exports = {
}
}
],
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true,
"allowDirectConstAssertionInArrowFunctions": true
}
],
"@typescript-eslint/member-ordering": "off",
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-array-constructor": "warn",
@ -98,29 +101,33 @@ module.exports = {
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-extra-non-null-assertion": "warn",
"@typescript-eslint/no-extra-semi": "warn",
"@typescript-eslint/no-floating-promises": "warn",
"@typescript-eslint/no-floating-promises": "off",
"@typescript-eslint/no-for-in-array": "warn",
"@typescript-eslint/no-implied-eval": "warn",
"@typescript-eslint/no-inferrable-types": "warn",
"@typescript-eslint/no-inferrable-types": "off",
"@typescript-eslint/no-misused-new": "warn",
"@typescript-eslint/no-misused-promises": "warn",
"@typescript-eslint/no-misused-promises": "off",
"@typescript-eslint/no-namespace": "warn",
"@typescript-eslint/no-non-null-asserted-optional-chain": "warn",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-parameter-properties": "off",
"@typescript-eslint/no-this-alias": "warn",
"@typescript-eslint/no-unnecessary-type-assertion": "warn",
"@typescript-eslint/no-unsafe-assignment": "warn",
"@typescript-eslint/no-unsafe-call": "warn",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-return": "warn",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unused-expressions": "warn",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": [
"warn",
{
"args": "after-used", "argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/no-var-requires": "warn",
"@typescript-eslint/prefer-as-const": "warn",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-namespace-keyword": "warn",
"@typescript-eslint/prefer-regexp-exec": "off",
"@typescript-eslint/quotes": [
@ -131,10 +138,9 @@ module.exports = {
],
"@typescript-eslint/require-await": "warn",
"@typescript-eslint/restrict-plus-operands": "warn",
"@typescript-eslint/restrict-template-expressions": "warn",
"@typescript-eslint/restrict-template-expressions": "off",
"@typescript-eslint/semi": [
"warn",
"always"
"error",
],
"@typescript-eslint/triple-slash-reference": [
"warn",
@ -145,13 +151,9 @@ module.exports = {
}
],
"@typescript-eslint/type-annotation-spacing": "warn",
"@typescript-eslint/unbound-method": "warn",
"@typescript-eslint/unbound-method": "off",
"@typescript-eslint/unified-signatures": "warn",
"arrow-body-style": "warn",
"arrow-parens": [
"warn",
"always"
],
"arrow-parens": "off",
"brace-style": [
"off",
"1tbs"
@ -159,7 +161,6 @@ module.exports = {
"comma-dangle": "off",
"complexity": "off",
"constructor-super": "warn",
"curly": "warn",
"eol-last": "warn",
"eqeqeq": [
"warn",
@ -178,7 +179,7 @@ module.exports = {
"Undefined",
],
"id-match": "warn",
"import/order": "warn",
"import/order": "off",
"jsdoc/check-alignment": "warn",
"jsdoc/check-indentation": "warn",
"jsdoc/newline-after-description": "warn",
@ -189,7 +190,6 @@ module.exports = {
"max-len": "off",
"new-parens": "warn",
"no-array-constructor": "off",
"no-bitwise": "warn",
"no-caller": "warn",
"no-cond-assign": "warn",
"no-console": "off",
@ -201,29 +201,18 @@ module.exports = {
"no-fallthrough": "off",
"no-implied-eval": "off",
"no-invalid-this": "off",
"no-multiple-empty-lines": "warn",
"no-multiple-empty-lines": ["error", { "max": 1 }],
"no-new-wrappers": "warn",
"no-shadow": [
"warn",
{
"hoist": "all"
}
],
"no-throw-literal": "warn",
"no-shadow": "off",
"no-trailing-spaces": "warn",
"no-undef-init": "warn",
"no-underscore-dangle": "warn",
"no-underscore-dangle": "off",
"no-unsafe-finally": "warn",
"no-unused-labels": "warn",
"no-unused-vars": "off",
"no-var": "warn",
"object-shorthand": ["warn", "never"],
"one-var": [
"warn",
"never"
],
"prefer-arrow/prefer-arrow-functions": "off",
"prefer-const": "warn",
"object-shorthand": "off",
"one-var": "off",
"prefer-const": "off",
"prefer-rest-params": "warn",
"quote-props": [
"warn",
@ -231,14 +220,7 @@ module.exports = {
],
"radix": "warn",
"require-await": "off",
"space-before-function-paren": [
"warn",
{
"anonymous": "never",
"asyncArrow": "always",
"named": "never"
}
],
"space-before-function-paren": "off",
"spaced-comment": [
"warn",
"always",

28
dist/powerbi-client.d.ts поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
// powerbi-client v2.18.6
// powerbi-client v2.18.7
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
declare module "config" {
@ -780,7 +780,7 @@ declare module "visualDescriptor" {
}
declare module "page" {
import { IHttpPostMessageResponse } from 'http-post-message';
import { DisplayOption, FiltersOperations, ICustomPageSize, IFilter, IVisual, LayoutType, PageSizeType, SectionVisibility, VisualContainerDisplayMode } from 'powerbi-models';
import { DisplayOption, FiltersOperations, ICustomPageSize, IFilter, IVisual, LayoutType, PageSizeType, SectionVisibility, VisualContainerDisplayMode, IPageBackground, IPageWallpaper } from 'powerbi-models';
import { IFilterable } from "ifilterable";
import { IReportNode } from "report";
import { VisualDescriptor } from "visualDescriptor";
@ -853,6 +853,18 @@ declare module "page" {
* @type {ICustomPageSize}
*/
defaultDisplayOption: DisplayOption;
/**
* Page background color.
*
* @type {IPageBackground}
*/
background: IPageBackground;
/**
* Page wallpaper color.
*
* @type {IPageWallpaper}
*/
wallpaper: IPageWallpaper;
/**
* Creates an instance of a Power BI report page.
*
@ -863,7 +875,7 @@ declare module "page" {
* @param {SectionVisibility} [visibility]
* @hidden
*/
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize);
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize, background?: IPageBackground, wallpaper?: IPageWallpaper);
/**
* Gets all page level filters within the report.
*
@ -1368,6 +1380,14 @@ declare module "report" {
* ```
*/
resetTheme(): Promise<void>;
/**
* get the theme of the report
*
* ```javascript
* report.getTheme();
* ```
*/
getTheme(): Promise<IReportTheme>;
/**
* Reset user's filters, slicers, and other data view changes to the default state of the report
*
@ -1566,11 +1586,13 @@ declare module "report" {
private isMobileSettings;
/**
* Return the current zoom level of the report.
*
* @returns {Promise<number>}
*/
getZoom(): Promise<number>;
/**
* Sets the report's zoom level.
*
* @param zoomLevel zoom level to set
*/
setZoom(zoomLevel: number): Promise<void>;

194
dist/powerbi.js поставляемый
Просмотреть файл

@ -1,4 +1,4 @@
// powerbi-client v2.18.6
// powerbi-client v2.18.7
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
(function webpackUniversalModuleDefinition(root, factory) {
@ -290,7 +290,7 @@ return /******/ (function(modules) { // webpackBootstrap
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
// powerbi-models v1.9.5
// powerbi-models v1.9.7
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
(function webpackUniversalModuleDefinition(root, factory) {
@ -797,9 +797,6 @@ var AdvancedFilter = /** @class */ (function (_super) {
else {
extractedConditions = conditions;
}
if (extractedConditions.length === 0) {
throw new Error("conditions must be a non-empty array. You passed: " + conditions);
}
if (extractedConditions.length > 2) {
throw new Error("AdvancedFilters may not have more than two conditions. You passed: " + conditions.length);
}
@ -2915,7 +2912,7 @@ var AdvancedFilterValidator = /** @class */ (function (_super) {
},
{
field: "conditions",
validators: [validator_1.Validators.fieldRequiredValidator, validator_1.Validators.filterConditionsValidator]
validators: [validator_1.Validators.filterConditionsValidator]
},
{
field: "filterType",
@ -6990,7 +6987,7 @@ var BookmarksManager = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -7024,7 +7021,7 @@ var BookmarksManager = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
request = {
@ -7060,7 +7057,7 @@ var BookmarksManager = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
playBookmarkRequest = {
@ -7095,7 +7092,7 @@ var BookmarksManager = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
request = {
@ -7132,7 +7129,7 @@ var BookmarksManager = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
request = {
@ -7170,7 +7167,7 @@ exports.BookmarksManager = BookmarksManager;
Object.defineProperty(exports, "__esModule", { value: true });
/** @ignore */ /** */
var config = {
version: '2.18.6',
version: '2.18.7',
type: 'js'
};
exports.default = config;
@ -7274,7 +7271,7 @@ var Create = /** @class */ (function (_super) {
* Validate create report configuration.
*/
Create.prototype.validate = function (config) {
return (0, powerbi_models_1.validateCreateReport)(config);
return powerbi_models_1.validateCreateReport(config);
};
/**
* Handle config changes.
@ -7441,7 +7438,7 @@ var Dashboard = /** @class */ (function (_super) {
*/
Dashboard.prototype.validate = function (baseConfig) {
var config = baseConfig;
var error = (0, powerbi_models_1.validateDashboardLoad)(config);
var error = powerbi_models_1.validateDashboardLoad(config);
return error ? error : this.validatePageView(config.pageView);
};
/**
@ -7563,7 +7560,7 @@ var Embed = /** @class */ (function () {
function Embed(service, element, config, iframe, phasedRender, isBootstrap) {
/** @hidden */
this.allowedEvents = [];
if ((0, util_1.autoAuthInEmbedUrl)(config.embedUrl)) {
if (util_1.autoAuthInEmbedUrl(config.embedUrl)) {
throw new Error(errors_1.EmbedUrlNotSupported);
}
Array.prototype.push.apply(this.allowedEvents, Embed.allowedEvents);
@ -7749,7 +7746,7 @@ var Embed = /** @class */ (function () {
sdkVersion: sdkConfig.default.version
};
timeNow = new Date();
if (this.lastLoadRequest && (0, util_1.getTimeDiffInMilliseconds)(this.lastLoadRequest, timeNow) < 100) {
if (this.lastLoadRequest && util_1.getTimeDiffInMilliseconds(this.lastLoadRequest, timeNow) < 100) {
console.debug("Power BI SDK sent more than two /report/load requests in the last 100ms interval.");
return [2 /*return*/];
}
@ -7794,7 +7791,7 @@ var Embed = /** @class */ (function () {
var _this = this;
var fakeEvent = { name: eventName, type: null, id: null, value: null };
if (handler) {
(0, util_1.remove)(function (eventHandler) { return eventHandler.test(fakeEvent) && (eventHandler.handle === handler); }, this.eventHandlers);
util_1.remove(function (eventHandler) { return eventHandler.test(fakeEvent) && (eventHandler.handle === handler); }, this.eventHandlers);
this.element.removeEventListener(eventName, handler);
}
else {
@ -7802,7 +7799,7 @@ var Embed = /** @class */ (function () {
.filter(function (eventHandler) { return eventHandler.test(fakeEvent); });
eventHandlersToRemove
.forEach(function (eventHandlerToRemove) {
(0, util_1.remove)(function (eventHandler) { return eventHandler === eventHandlerToRemove; }, _this.eventHandlers);
util_1.remove(function (eventHandler) { return eventHandler === eventHandlerToRemove; }, _this.eventHandlers);
_this.element.removeEventListener(eventName, eventHandlerToRemove.handle);
});
}
@ -7908,14 +7905,14 @@ var Embed = /** @class */ (function () {
var _this = this;
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
if (this.bootstrapConfig) {
this.config = (0, util_1.assign)({}, this.bootstrapConfig, config);
this.config = util_1.assign({}, this.bootstrapConfig, config);
// reset bootstrapConfig because we do not want to merge it in re-embed scenario.
this.bootstrapConfig = null;
}
else {
// Copy config - important for multiple iframe scenario.
// Otherwise, if a user uses the same config twice, same unique Id which will be used in different iframes.
this.config = (0, util_1.assign)({}, config);
this.config = util_1.assign({}, config);
}
this.config.embedUrl = this.getEmbedUrl(isBootstrap);
this.config.groupId = this.getGroupId();
@ -7944,7 +7941,7 @@ var Embed = /** @class */ (function () {
var registerQueryCallback = !!((_k = this.config.eventHooks) === null || _k === void 0 ? void 0 : _k.applicationContextProvider);
delete this.config.eventHooks;
if (registerQueryCallback && this.embedtype === "report")
this.config.embedUrl = (0, util_1.addParamToUrl)(this.config.embedUrl, "registerQueryCallback", "true");
this.config.embedUrl = util_1.addParamToUrl(this.config.embedUrl, "registerQueryCallback", "true");
this.configChanged(isBootstrap);
};
/**
@ -7960,10 +7957,10 @@ var Embed = /** @class */ (function () {
}
var localeSettings = config.settings.localeSettings;
if (localeSettings && localeSettings.language) {
this.config.embedUrl = (0, util_1.addParamToUrl)(this.config.embedUrl, 'language', localeSettings.language);
this.config.embedUrl = util_1.addParamToUrl(this.config.embedUrl, 'language', localeSettings.language);
}
if (localeSettings && localeSettings.formatLocale) {
this.config.embedUrl = (0, util_1.addParamToUrl)(this.config.embedUrl, 'formatLocale', localeSettings.formatLocale);
this.config.embedUrl = util_1.addParamToUrl(this.config.embedUrl, 'formatLocale', localeSettings.formatLocale);
}
};
/**
@ -8011,7 +8008,7 @@ var Embed = /** @class */ (function () {
* @hidden
*/
Embed.prototype.getUniqueId = function () {
return this.config.uniqueId || this.element.getAttribute(Embed.nameAttribute) || (0, util_1.createRandomString)();
return this.config.uniqueId || this.element.getAttribute(Embed.nameAttribute) || util_1.createRandomString();
};
/**
* Gets the group ID from the first available location: options, embeddedUrl.
@ -8058,11 +8055,11 @@ var Embed = /** @class */ (function () {
*
* @hidden
*/
Embed.prototype.setIframe = function (isLoad, phasedRender, isBootstrap, registerQueryCallback) {
Embed.prototype.setIframe = function (isLoad, phasedRender, isBootstrap) {
var _this = this;
if (!this.iframe) {
var iframeContent = document.createElement("iframe");
var embedUrl = this.config.uniqueId ? (0, util_1.addParamToUrl)(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl;
var embedUrl = this.config.uniqueId ? util_1.addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl;
iframeContent.style.width = '100%';
iframeContent.style.height = '100%';
iframeContent.setAttribute("src", embedUrl);
@ -8343,7 +8340,7 @@ var Page = /** @class */ (function () {
* @param {SectionVisibility} [visibility]
* @hidden
*/
function Page(report, name, displayName, isActivePage, visibility, defaultSize, defaultDisplayOption, mobileSize) {
function Page(report, name, displayName, isActivePage, visibility, defaultSize, defaultDisplayOption, mobileSize, background, wallpaper) {
this.report = report;
this.name = name;
this.displayName = displayName;
@ -8352,6 +8349,8 @@ var Page = /** @class */ (function () {
this.defaultSize = defaultSize;
this.mobileSize = mobileSize;
this.defaultDisplayOption = defaultDisplayOption;
this.background = background;
this.wallpaper = wallpaper;
}
/**
* Gets all page level filters within the report.
@ -8574,7 +8573,7 @@ var Page = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.report.config.embedUrl)) {
if (util_1.isRDLEmbed(this.report.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -8612,7 +8611,7 @@ var Page = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.report.config.embedUrl)) {
if (util_1.isRDLEmbed(this.report.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -8747,7 +8746,7 @@ var Page = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.report.config.embedUrl)) {
if (util_1.isRDLEmbed(this.report.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -8783,7 +8782,7 @@ var Page = /** @class */ (function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.report.config.embedUrl)) {
if (util_1.isRDLEmbed(this.report.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
layoutTypeEnum = powerbi_models_1.LayoutType[layoutType];
@ -9000,7 +8999,7 @@ var Qna = /** @class */ (function (_super) {
* Validate load configuration.
*/
Qna.prototype.validate = function (config) {
return (0, powerbi_models_1.validateLoadQnaConfiguration)(config);
return powerbi_models_1.validateLoadQnaConfiguration(config);
};
/** @hidden */
Qna.type = "Qna";
@ -9073,14 +9072,10 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
to[j] = from[i];
return to;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Report = void 0;
@ -9291,7 +9286,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9355,7 +9350,7 @@ var Report = /** @class */ (function (_super) {
Report.prototype.removeFilters = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
return [2 /*return*/, this.updateFilters(powerbi_models_1.FiltersOperations.RemoveAll)];
@ -9385,7 +9380,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9433,7 +9428,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9443,7 +9438,7 @@ var Report = /** @class */ (function (_super) {
case 2:
response = _a.sent();
return [2 /*return*/, response.body
.map(function (page) { return new page_1.Page(_this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize); })];
.map(function (page) { return new page_1.Page(_this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize, page.background, page.wallpaper); })];
case 3:
response_8 = _a.sent();
throw response_8.body;
@ -9471,7 +9466,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9484,7 +9479,7 @@ var Report = /** @class */ (function (_super) {
if (!page) {
return [2 /*return*/, Promise.reject(powerbi_models_1.CommonErrorCodes.NotFound)];
}
return [2 /*return*/, new page_1.Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize)];
return [2 /*return*/, new page_1.Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize, page.background, page.wallpaper)];
case 3:
response_9 = _a.sent();
throw response_9.body;
@ -9511,7 +9506,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9521,7 +9516,7 @@ var Report = /** @class */ (function (_super) {
case 2:
response = _a.sent();
activePage = response.body.find(function (page) { return page.isActive; });
return [2 /*return*/, new page_1.Page(this, activePage.name, activePage.displayName, activePage.isActive, activePage.visibility, activePage.defaultSize, activePage.defaultDisplayOption, activePage.mobileSize)];
return [2 /*return*/, new page_1.Page(this, activePage.name, activePage.displayName, activePage.isActive, activePage.visibility, activePage.defaultSize, activePage.defaultDisplayOption, activePage.mobileSize, activePage.background, activePage.wallpaper)];
case 3:
response_10 = _a.sent();
throw response_10.body;
@ -9557,7 +9552,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
@ -9592,7 +9587,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
page = {
@ -9640,7 +9635,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl) && settings.customLayout != null) {
if (util_1.isRDLEmbed(this.config.embedUrl) && settings.customLayout != null) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_c.label = 1;
@ -9674,10 +9669,10 @@ var Report = /** @class */ (function (_super) {
* @hidden
*/
Report.prototype.validate = function (config) {
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
return (0, powerbi_models_1.validatePaginatedReportLoad)(config);
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return powerbi_models_1.validatePaginatedReportLoad(config);
}
return (0, powerbi_models_1.validateReportLoad)(config);
return powerbi_models_1.validateReportLoad(config);
};
/**
* Handle config changes.
@ -9687,7 +9682,7 @@ var Report = /** @class */ (function (_super) {
Report.prototype.configChanged = function (isBootstrap) {
var config = this.config;
if (this.isMobileSettings(config.settings)) {
config.embedUrl = (0, util_1.addParamToUrl)(config.embedUrl, "isMobile", "true");
config.embedUrl = util_1.addParamToUrl(config.embedUrl, "isMobile", "true");
}
// Calculate settings from HTML element attributes if available.
var filterPaneEnabledAttribute = this.element.getAttribute(Report.filterPaneEnabledAttribute);
@ -9697,7 +9692,7 @@ var Report = /** @class */ (function (_super) {
navContentPaneEnabled: (navContentPaneEnabledAttribute == null) ? undefined : (navContentPaneEnabledAttribute !== "false")
};
// Set the settings back into the config.
this.config.settings = (0, util_1.assign)({}, elementAttrSettings, config.settings);
this.config.settings = util_1.assign({}, elementAttrSettings, config.settings);
if (isBootstrap) {
return;
}
@ -9783,10 +9778,10 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
return [4 /*yield*/, (0, util_1.isSavedInternal)(this.service.hpm, this.config.uniqueId, this.iframe.contentWindow)];
return [4 /*yield*/, util_1.isSavedInternal(this.service.hpm, this.config.uniqueId, this.iframe.contentWindow)];
case 1: return [2 /*return*/, _a.sent()];
}
});
@ -9804,7 +9799,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
return [4 /*yield*/, this.applyThemeInternal(theme)];
@ -9825,7 +9820,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
return [4 /*yield*/, this.applyThemeInternal({})];
@ -9834,6 +9829,37 @@ var Report = /** @class */ (function (_super) {
});
});
};
/**
* get the theme of the report
*
* ```javascript
* report.getTheme();
* ```
*/
Report.prototype.getTheme = function () {
return __awaiter(this, void 0, void 0, function () {
var response, response_16;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.service.hpm.get("/report/theme", { uid: this.config.uniqueId }, this.iframe.contentWindow)];
case 2:
response = _a.sent();
return [2 /*return*/, response.body];
case 3:
response_16 = _a.sent();
throw response_16.body;
case 4: return [2 /*return*/];
}
});
});
};
/**
* Reset user's filters, slicers, and other data view changes to the default state of the report
*
@ -9843,7 +9869,7 @@ var Report = /** @class */ (function (_super) {
*/
Report.prototype.resetPersistentFilters = function () {
return __awaiter(this, void 0, void 0, function () {
var response_16;
var response_17;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -9851,8 +9877,8 @@ var Report = /** @class */ (function (_super) {
return [4 /*yield*/, this.service.hpm.delete("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)];
case 1: return [2 /*return*/, _a.sent()];
case 2:
response_16 = _a.sent();
throw response_16.body;
response_17 = _a.sent();
throw response_17.body;
case 3: return [2 /*return*/];
}
});
@ -9867,7 +9893,7 @@ var Report = /** @class */ (function (_super) {
*/
Report.prototype.savePersistentFilters = function () {
return __awaiter(this, void 0, void 0, function () {
var response_17;
var response_18;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -9875,8 +9901,8 @@ var Report = /** @class */ (function (_super) {
return [4 /*yield*/, this.service.hpm.post("/report/userState", null, { uid: this.config.uniqueId }, this.iframe.contentWindow)];
case 1: return [2 /*return*/, _a.sent()];
case 2:
response_17 = _a.sent();
throw response_17.body;
response_18 = _a.sent();
throw response_18.body;
case 3: return [2 /*return*/];
}
});
@ -9894,7 +9920,7 @@ var Report = /** @class */ (function (_super) {
*/
Report.prototype.arePersistentFiltersApplied = function () {
return __awaiter(this, void 0, void 0, function () {
var response, response_18;
var response, response_19;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -9904,8 +9930,8 @@ var Report = /** @class */ (function (_super) {
response = _a.sent();
return [2 /*return*/, response.body];
case 2:
response_18 = _a.sent();
throw response_18.body;
response_19 = _a.sent();
throw response_19.body;
case 3: return [2 /*return*/];
}
});
@ -9931,7 +9957,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
commandCopy = JSON.parse(JSON.stringify(this.commands));
@ -9982,7 +10008,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
newCommands = this.createMenuCommand("visualContextMenu", commandName, commandTitle, contextMenuTitle, menuLocation, visualName, visualType, groupName);
@ -10018,7 +10044,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
commandCopy = JSON.parse(JSON.stringify(this.commands));
@ -10073,7 +10099,7 @@ var Report = /** @class */ (function (_super) {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if ((0, util_1.isRDLEmbed)(this.config.embedUrl)) {
if (util_1.isRDLEmbed(this.config.embedUrl)) {
return [2 /*return*/, Promise.reject(errors_1.APINotSupportedForRDLError)];
}
newCommands = this.createMenuCommand("visualOptionsMenu", commandName, commandTitle, optionsMenuTitle, menuLocation, visualName, visualType, groupName, commandIcon);
@ -10296,7 +10322,7 @@ var Report = /** @class */ (function (_super) {
visualType: visualType
};
}
return __spreadArray(__spreadArray([], this.commands, true), [newCommandObj], false);
return __spreadArray(__spreadArray([], this.commands), [newCommandObj]);
};
/**
* @hidden
@ -10347,7 +10373,7 @@ var Report = /** @class */ (function (_super) {
*/
Report.prototype.applyThemeInternal = function (theme) {
return __awaiter(this, void 0, void 0, function () {
var response, response_19;
var response, response_20;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -10357,8 +10383,8 @@ var Report = /** @class */ (function (_super) {
response = _a.sent();
return [2 /*return*/, response.body];
case 2:
response_19 = _a.sent();
throw response_19.body;
response_20 = _a.sent();
throw response_20.body;
case 3: return [2 /*return*/];
}
});
@ -10387,11 +10413,12 @@ var Report = /** @class */ (function (_super) {
};
/**
* Return the current zoom level of the report.
*
* @returns {Promise<number>}
*/
Report.prototype.getZoom = function () {
return __awaiter(this, void 0, void 0, function () {
var response, response_20;
var response, response_21;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -10401,8 +10428,8 @@ var Report = /** @class */ (function (_super) {
response = _a.sent();
return [2 /*return*/, response.body];
case 2:
response_20 = _a.sent();
throw response_20.body;
response_21 = _a.sent();
throw response_21.body;
case 3: return [2 /*return*/];
}
});
@ -10410,6 +10437,7 @@ var Report = /** @class */ (function (_super) {
};
/**
* Sets the report's zoom level.
*
* @param zoomLevel zoom level to set
*/
Report.prototype.setZoom = function (zoomLevel) {
@ -11043,7 +11071,7 @@ var Tile = /** @class */ (function (_super) {
*/
Tile.prototype.validate = function (config) {
var embedConfig = config;
return (0, powerbi_models_1.validateTileLoad)(embedConfig);
return powerbi_models_1.validateTileLoad(embedConfig);
};
/**
* Handle config changes.
@ -11260,7 +11288,7 @@ function generateUUID() {
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now();
}
return 'xxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
return 'xxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (_c) {
// Generate a random number, scaled from 0 to 15.
var r = (getRandomValue() % 16);
// Shift 4 times to divide by 16

4
dist/powerbi.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -210,7 +210,7 @@ gulp.task('compile:dts', 'Generate one dts file from modules', function () {
});
gulp.task('compile:spec', 'Compile spec tests', function () {
return gulp.src(['./test/test.spec.ts'])
return gulp.src(['./test/**/*.ts'])
.pipe(webpackStream(webpackTestConfig))
.pipe(gulp.dest('./tmp'));
});

Просмотреть файл

@ -26,6 +26,7 @@ module.exports = function (config) {
reporters: argv.debug ? ['spec', 'kjhtml'] : ['spec', 'coverage', 'kjhtml'],
autoWatch: true,
browsers: [browserName],
browserNoActivityTimeout: 300000,
plugins: [
'karma-firefox-launcher',
'karma-chrome-launcher',
@ -37,7 +38,7 @@ module.exports = function (config) {
],
customLaunchers: {
'Chrome_headless': {
base: 'Chrome',
base: argv.debug ? 'Chrome' : 'ChromeHeadless',
flags: flags.concat("--no-sandbox", "--window-size=800,800"),
},
},

Просмотреть файл

@ -1,6 +1,6 @@
{
"name": "powerbi-client",
"version": "2.18.6",
"version": "2.18.7",
"description": "JavaScript library for embedding Power BI into your apps. Provides service which makes it easy to embed different types of components and an object model which allows easy interaction with these components such as changing pages, applying filters, and responding to data selection.",
"main": "dist/powerbi.js",
"types": "dist/powerbi-client.d.ts",
@ -59,15 +59,15 @@
"gulp4-run-sequence": "^1.0.0",
"http-server": "^0.12.1",
"ignore-loader": "^0.1.1",
"jasmine-core": "^2.99.1",
"jasmine-core": "3.10.1",
"jquery": "^3.3.1",
"json-loader": "^0.5.4",
"karma": "^5.2.3",
"karma": "6.3.5",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage": "^2.0.3",
"karma-firefox-launcher": "^1.2.0",
"karma-jasmine": "^0.3.8",
"karma-jasmine-html-reporter": "^0.2.2",
"karma-jasmine": "4.0.1",
"karma-jasmine-html-reporter": "1.7.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-spec-reporter": "0.0.32",
"moment": "^2.14.1",
@ -81,7 +81,7 @@
},
"dependencies": {
"http-post-message": "^0.2",
"powerbi-models": "^1.9.5",
"powerbi-models": "^1.9.7",
"powerbi-router": "^0.1",
"window-post-message-proxy": "^0.2"
},

Просмотреть файл

@ -5,7 +5,7 @@ import { IFilterTarget } from "powerbi-models";
/**
* Generic filter builder for BasicFilter, AdvancedFilter, RelativeDate, RelativeTime and TopN
*
*
* @class
*/
export class FilterBuilder {
@ -26,21 +26,21 @@ export class FilterBuilder {
*
* @returns {FilterBuilder}
*/
withTargetObject(target: IFilterTarget) {
withTargetObject(target: IFilterTarget): this {
this.target = target;
return this;
}
/**
* Sets target property for filter with column target object
*
*
* ```
* const filterBuilder = new FilterBuilder().withColumnTarget(tableName, columnName);
* ```
*
* @returns {FilterBuilder}
*/
withColumnTarget(tableName: string, columnName: string) {
withColumnTarget(tableName: string, columnName: string): this {
this.target = { table: tableName, column: columnName };
return this;
}
@ -54,7 +54,7 @@ export class FilterBuilder {
*
* @returns {FilterBuilder}
*/
withMeasureTarget(tableName: string, measure: string) {
withMeasureTarget(tableName: string, measure: string): this {
this.target = { table: tableName, measure: measure };
return this;
}
@ -68,7 +68,7 @@ export class FilterBuilder {
*
* @returns {FilterBuilder}
*/
withHierarchyLevelTarget(tableName: string, hierarchy: string, hierarchyLevel: string) {
withHierarchyLevelTarget(tableName: string, hierarchy: string, hierarchyLevel: string): this {
this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel };
return this;
}
@ -82,7 +82,7 @@ export class FilterBuilder {
*
* @returns {FilterBuilder}
*/
withColumnAggregation(tableName: string, columnName: string, aggregationFunction: string) {
withColumnAggregation(tableName: string, columnName: string, aggregationFunction: string): this {
this.target = { table: tableName, column: columnName, aggregationFunction: aggregationFunction };
return this;
}
@ -96,7 +96,7 @@ export class FilterBuilder {
*
* @returns {FilterBuilder}
*/
withHierarchyLevelAggregationTarget(tableName: string, hierarchy: string, hierarchyLevel: string, aggregationFunction: string) {
withHierarchyLevelAggregationTarget(tableName: string, hierarchy: string, hierarchyLevel: string, aggregationFunction: string): this {
this.target = { table: tableName, hierarchy: hierarchy, hierarchyLevel: hierarchyLevel, aggregationFunction: aggregationFunction };
return this;
}

Просмотреть файл

@ -3,7 +3,7 @@
/** @ignore *//** */
const config = {
version: '2.18.6',
version: '2.18.7',
type: 'js'
};

Просмотреть файл

@ -525,7 +525,7 @@ export abstract class Embed {
const extensionsArray = this.config?.settings?.extensions as models.IExtension[];
if (Array.isArray(extensionsArray)) {
this.commands = [];
extensionsArray.map((extension: models.IExtension) => { if (extension?.command) { this.commands.push(extension.command) } });
extensionsArray.map((extension: models.IExtension) => { if (extension?.command) { this.commands.push(extension.command); } });
}
if (isBootstrap) {
@ -707,10 +707,10 @@ export abstract class Embed {
*
* @hidden
*/
private setIframe(isLoad: boolean, phasedRender?: boolean, isBootstrap?: boolean, registerQueryCallback?: boolean): void {
private setIframe(isLoad: boolean, phasedRender?: boolean, isBootstrap?: boolean): void {
if (!this.iframe) {
const iframeContent = document.createElement("iframe");
let embedUrl = this.config.uniqueId ? addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl;
const embedUrl = this.config.uniqueId ? addParamToUrl(this.config.embedUrl, 'uid', this.config.uniqueId) : this.config.embedUrl;
iframeContent.style.width = '100%';
iframeContent.style.height = '100%';

Просмотреть файл

@ -15,7 +15,9 @@ import {
PageLevelFilters,
PageSizeType,
SectionVisibility,
VisualContainerDisplayMode
VisualContainerDisplayMode,
IPageBackground,
IPageWallpaper,
} from 'powerbi-models';
import { IFilterable } from './ifilterable';
import { IReportNode, Report } from './report';
@ -91,7 +93,7 @@ export class Page implements IPageNode, IFilterable {
*
* @type {ICustomPageSize}
*/
mobileSize: ICustomPageSize;
mobileSize: ICustomPageSize;
/**
* Page display options as saved in the report.
@ -100,6 +102,20 @@ export class Page implements IPageNode, IFilterable {
*/
defaultDisplayOption: DisplayOption;
/**
* Page background color.
*
* @type {IPageBackground}
*/
background: IPageBackground;
/**
* Page wallpaper color.
*
* @type {IPageWallpaper}
*/
wallpaper: IPageWallpaper;
/**
* Creates an instance of a Power BI report page.
*
@ -110,7 +126,7 @@ export class Page implements IPageNode, IFilterable {
* @param {SectionVisibility} [visibility]
* @hidden
*/
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize) {
constructor(report: IReportNode, name: string, displayName?: string, isActivePage?: boolean, visibility?: SectionVisibility, defaultSize?: ICustomPageSize, defaultDisplayOption?: DisplayOption, mobileSize?: ICustomPageSize, background?: IPageBackground, wallpaper?: IPageWallpaper) {
this.report = report;
this.name = name;
this.displayName = displayName;
@ -119,6 +135,8 @@ export class Page implements IPageNode, IFilterable {
this.defaultSize = defaultSize;
this.mobileSize = mobileSize;
this.defaultDisplayOption = defaultDisplayOption;
this.background = background;
this.wallpaper = wallpaper;
}
/**

Просмотреть файл

@ -119,7 +119,6 @@ export class Report extends Embed implements IReportNode, IFilterable {
return reportId;
}
/**
* Render a preloaded report, using phased embedding API
*
@ -343,7 +342,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
try {
const response = await this.service.hpm.get<IPage[]>('/report/pages', { uid: this.config.uniqueId }, this.iframe.contentWindow);
return response.body
.map((page) => new Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize));
.map((page) => new Page(this, page.name, page.displayName, page.isActive, page.visibility, page.defaultSize, page.defaultDisplayOption, page.mobileSize, page.background, page.wallpaper));
} catch (response) {
throw response.body;
}
@ -383,7 +382,9 @@ export class Report extends Embed implements IReportNode, IFilterable {
page.visibility,
page.defaultSize,
page.defaultDisplayOption,
page.mobileSize
page.mobileSize,
page.background,
page.wallpaper,
);
} catch (response) {
throw response.body;
@ -418,7 +419,9 @@ export class Report extends Embed implements IReportNode, IFilterable {
activePage.visibility,
activePage.defaultSize,
activePage.defaultDisplayOption,
activePage.mobileSize
activePage.mobileSize,
activePage.background,
activePage.wallpaper,
);
} catch (response) {
throw response.body;
@ -567,7 +570,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
};
// Set the settings back into the config.
this.config.settings = assign({}, elementAttrSettings, config.settings);
this.config.settings = assign({}, elementAttrSettings, config.settings) as ISettings;
if (isBootstrap) {
return;
@ -670,6 +673,26 @@ export class Report extends Embed implements IReportNode, IFilterable {
return await this.applyThemeInternal(<IReportTheme>{});
}
/**
* get the theme of the report
*
* ```javascript
* report.getTheme();
* ```
*/
async getTheme(): Promise<IReportTheme> {
if (isRDLEmbed(this.config.embedUrl)) {
return Promise.reject(APINotSupportedForRDLError);
}
try {
const response = await this.service.hpm.get<IReportTheme>(`/report/theme`, { uid: this.config.uniqueId }, this.iframe.contentWindow);
return response.body;
} catch (response) {
throw response.body;
}
}
/**
* Reset user's filters, slicers, and other data view changes to the default state of the report
*
@ -738,7 +761,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
return Promise.reject(APINotSupportedForRDLError);
}
const commandCopy: ICommandExtension[] = JSON.parse(JSON.stringify(this.commands));
const commandCopy = JSON.parse(JSON.stringify(this.commands)) as ICommandExtension[];
const indexOfCommand: number = this.findCommandMenuIndex("visualContextMenu", commandCopy, commandName, contextMenuTitle);
if (indexOfCommand === -1) {
throw CommonErrorCodes.NotFound;
@ -808,7 +831,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
return Promise.reject(APINotSupportedForRDLError);
}
const commandCopy: ICommandExtension[] = JSON.parse(JSON.stringify(this.commands));
const commandCopy = JSON.parse(JSON.stringify(this.commands)) as ICommandExtension[];
const indexOfCommand: number = this.findCommandMenuIndex("visualOptionsMenu", commandCopy, commandName, optionsMenuTitle);
if (indexOfCommand === -1) {
@ -1115,6 +1138,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
/**
* Return the current zoom level of the report.
*
* @returns {Promise<number>}
*/
async getZoom(): Promise<number> {
@ -1128,6 +1152,7 @@ export class Report extends Embed implements IReportNode, IFilterable {
/**
* Sets the report's zoom level.
*
* @param zoomLevel zoom level to set
*/
async setZoom(zoomLevel: number): Promise<void> {

Просмотреть файл

@ -462,7 +462,7 @@ export class Service implements IService {
this.router.post(`preQuery`, async (req, _res) => {
try {
let result = await applicationContextProvider(req.body);
const result = await applicationContextProvider(req.body);
_res.send(200, result);
} catch (error) {
_res.send(400, null);
@ -589,7 +589,7 @@ export class Service implements IService {
* @hidden
*/
private handleEvent(event: IEvent<any>): void {
let embed = utils.find(embed => {
const embed = utils.find(embed => {
return (embed.config.uniqueId === event.id);
}, this.embeds);

Просмотреть файл

@ -80,7 +80,7 @@ export function remove<T>(predicate: (x: T) => boolean, xs: T[]): void {
* @param {any} args
* @returns
*/
export function assign(...args) {
export function assign(...args): any {
var target = args[0];
'use strict';
@ -123,7 +123,7 @@ export function generateUUID(): string {
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
d += performance.now();
}
return 'xxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
return 'xxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (_c) {
// Generate a random number, scaled from 0 to 15.
const r = (getRandomValue() % 16);

2559
test/SDK-to-HPM.spec.ts Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

598
test/SDK-to-MockApp.spec.ts Normal file
Просмотреть файл

@ -0,0 +1,598 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import * as utils from '../src/util';
import * as service from '../src/service';
import * as embed from '../src/embed';
import * as report from '../src/report';
import * as page from '../src/page';
import * as Hpm from 'http-post-message';
import * as models from 'powerbi-models';
import * as factories from '../src/factories';
import * as util from '../src/util';
import { spyApp, setupEmbedMockApp } from './utility/mockEmbed';
import { logMessages, iframeSrc } from './constsants';
describe('SDK-to-MockApp', function () {
let element: HTMLDivElement;
let iframe: HTMLIFrameElement;
let iframeHpm: Hpm.HttpPostMessage;
let powerbi: service.Service;
let report: report.Report;
let page1: page.Page;
const embedConfiguration: embed.IEmbedConfiguration = {
type: "report",
id: "fakeReportIdInitialEmbed",
accessToken: 'fakeTokenInitialEmbed',
embedUrl: iframeSrc
};
beforeEach(async function () {
powerbi = new service.Service(factories.hpmFactory, factories.wpmpFactory, factories.routerFactory, {
wpmpName: 'SDK-to-MockApp HostWpmp',
logMessages
});
element = document.createElement('div');
element.id = "reportContainer1";
element.className = 'powerbi-report-container2';
document.body.appendChild(element);
report = <report.Report>powerbi.embed(element, embedConfiguration);
page1 = report.page('ReportSection1');
iframe = element.getElementsByTagName('iframe')[0];
/**
* Note: For testing we need to configure the eventSourceOverrideWindow to allow the host to respond to
* the iframe window; however, the iframe window doesn't exist until the first embed is created.
*
* To work around this we create a service for the initial embed, embed a report, then set the private variable
*/
(<any>powerbi.wpmp).eventSourceOverrideWindow = iframe.contentWindow;
// Register Iframe side
let hpmPostSpy = spyOn(powerbi.hpm, "post").and.returnValue(Promise.resolve(<any>{}));
iframeHpm = setupEmbedMockApp(iframe.contentWindow, window, logMessages, 'SDK-to-MockApp IframeWpmp');
await new Promise<void>((resolve, _reject) => {
iframe.addEventListener('load', () => {
resolve(null);
});
});
hpmPostSpy.and.callThrough();
});
afterEach(function () {
powerbi.reset(element);
element.remove();
powerbi.wpmp?.stop();
spyApp.reset();
});
describe('report', function () {
beforeEach(function () {
spyOn(utils, "getTimeDiffInMilliseconds").and.callFake(() => 700); // Prevent requests from being throttled.
});
describe('load', function () {
it('report.load() returns promise that resolves with null if the report load successful', async function () {
try {
const response = await report.load(undefined);
// Assert
expect(response).toEqual({} as any);
} catch (error) {
fail("lod shouldn't fail");
}
});
});
describe('pages', function () {
it('report.getPages() return promise that rejects with server error if there was error getting pages', async function () {
// Arrange
const testData = {
expectedError: {
message: 'internal server error'
}
};
try {
spyApp.getPages.and.callFake(() => Promise.reject(testData.expectedError));
// Act
await report.getPages();
fail("getPagesshouldn't succeed");
} catch (error) {
// Assert
expect(spyApp.getPages).toHaveBeenCalled();
expect(error).toEqual(jasmine.objectContaining(testData.expectedError));
}
});
it('report.getPages() returns promise that resolves with list of page names', async function () {
// Arrange
const testData = {
pages: [
{
name: "page1",
displayName: "Page 1",
isActive: true
}
]
};
try {
spyApp.getPages.and.returnValue(Promise.resolve(testData.pages));
const pages = await report.getPages();
// Assert
expect(spyApp.getPages).toHaveBeenCalled();
// Workaround to compare pages
pages.forEach(page => {
const testPage = util.find(p => p.name === page.name, testData.pages);
if (testPage) {
expect(page.name).toEqual(testPage.name);
expect(page.isActive).toEqual(testPage.isActive);
}
else {
expect(true).toBe(false);
}
});
} catch (error) {
console.log("getPages failed with", error);
fail("getPages failed");
}
});
});
describe('filters', function () {
it('report.getFilters() returns promise that rejects with server error if there was problem getting filters', async function () {
// Arrange
const testData = {
expectedError: {
message: 'could not serialize filters'
}
};
try {
spyApp.getFilters.and.callFake(() => Promise.reject(testData.expectedError));
await report.getFilters();
fail("getFilters shouldn't succeed");
} catch (error) {
// Assert
expect(spyApp.getFilters).toHaveBeenCalled();
expect(error).toEqual(jasmine.objectContaining(testData.expectedError));
}
});
it('report.getFilters() returns promise that resolves with filters is request is successful', async function () {
// Arrange
const testData = {
filters: [
{ x: 'fakeFilter' }
]
};
spyApp.getFilters.and.returnValue(Promise.resolve(testData.filters));
try {
// Act
const filters = await report.getFilters();
// Assert
expect(spyApp.getFilters).toHaveBeenCalled();
// @ts-ignore as testData is not of type IFilter
expect(filters).toEqual(testData.filters);
} catch (error) {
fail("get filtershousln't fails");
}
});
it('report.setFilters(filters) returns promise that rejects with validation errors if filter is invalid', async function () {
// Arrange
const testData = {
filters: [
(new models.BasicFilter({ table: "cars", column: "make" }, "In", ["subaru", "honda"])).toJSON()
],
expectedErrors: [
{
message: 'invalid filter'
}
]
};
spyApp.validateFilter.and.callFake(() => Promise.reject(testData.expectedErrors));
try {
// Act
await report.setFilters(testData.filters);
fail("et filter should fail");
} catch (error) {
// Assert
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
expect(spyApp.setFilters).not.toHaveBeenCalled();
expect(error).toEqual(jasmine.objectContaining(testData.expectedErrors));
}
});
it('report.setFilters(filters) returns promise that resolves with null if filter was valid and request is accepted', async function () {
// Arrange
const testData = {
filters: [(new models.BasicFilter({ table: "cars", column: "make" }, "In", ["subaru", "honda"])).toJSON()]
};
spyApp.validateFilter.and.returnValue(Promise.resolve(null));
spyApp.setFilters.and.returnValue(Promise.resolve(null));
try {
// Act
await report.setFilters(testData.filters);
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
expect(spyApp.setFilters).toHaveBeenCalledWith(testData.filters);
} catch (error) {
fail("why fail");
}
});
it('report.removeFilters() returns promise that resolves with null if the request was accepted', async function () {
// Arrange
let spy = spyOn(report, 'updateFilters').and.callFake(() => Promise.resolve(null));
try {
// Act
await report.removeFilters();
// Assert
expect(spy).toHaveBeenCalledWith(models.FiltersOperations.RemoveAll);
} catch (error) {
fail("remove fialter shouldn't fail");
}
});
});
describe('print', function () {
it('report.print() returns promise that resolves with null if the report print command was accepted', async function () {
// Arrange
spyApp.print.and.returnValue(Promise.resolve({}));
// Act
const response = await report.print();
// Assert
expect(spyApp.print).toHaveBeenCalled();
expect(response).toEqual();
});
});
describe('refresh', function () {
it('report.refresh() returns promise that resolves with null if the report refresh command was accepted', async function () {
// Arrange
spyApp.refreshData.and.returnValue(Promise.resolve(null));
// Act
const response = await report.refresh();
// Assert
expect(spyApp.refreshData).toHaveBeenCalled();
expect(response).toEqual(undefined);
});
});
describe('settings', function () {
it('report.updateSettings(setting) returns promise that rejects with validation error if object is invalid', async function () {
// Arrange
const testData = {
settings: {
filterPaneEnabled: false
},
expectedErrors: [
{
message: 'invalid target'
}
]
};
spyApp.validateSettings.and.callFake(() => Promise.reject(testData.expectedErrors));
try {
// Act
await report.updateSettings(testData.settings);
fail("shouldfail");
} catch (errors) {
// Assert
expect(spyApp.validateSettings).toHaveBeenCalledWith(testData.settings);
expect(spyApp.updateSettings).not.toHaveBeenCalled();
expect(errors).toEqual(jasmine.objectContaining(testData.expectedErrors));
}
});
it('report.updateSettings(settings) returns promise that resolves with null if requst is valid and accepted', async function () {
// Arrange
const testData = {
settings: {
filterPaneEnabled: false
},
expectedErrors: [
{
message: 'invalid target'
}
]
};
try {
spyApp.validateSettings.and.returnValue(Promise.resolve(null));
spyApp.updateSettings.and.returnValue(Promise.resolve(null));
// Act
await report.updateSettings(testData.settings);
// Assert
expect(spyApp.validateSettings).toHaveBeenCalledWith(testData.settings);
expect(spyApp.updateSettings).toHaveBeenCalledWith(testData.settings);
} catch (error) {
console.log("updateSettings failed with", error);
fail("updateSettings failed");
}
});
});
describe('page', function () {
describe('filters', function () {
beforeEach(() => {
spyApp.validatePage.and.returnValue(Promise.resolve(null));
});
it('page.getFilters() returns promise that rejects with server error if there was problem getting filters', async function () {
// Arrange
const testData = {
expectedError: {
message: 'could not serialize filters'
}
};
try {
spyApp.getFilters.and.callFake(() => Promise.reject(testData.expectedError));
await page1.getFilters();
} catch (error) {
// Assert
expect(spyApp.getFilters).toHaveBeenCalled();
expect(error).toEqual(jasmine.objectContaining(testData.expectedError));
}
});
it('page.getFilters() returns promise that resolves with filters is request is successful', async function () {
// Arrange
const testData = {
filters: [
{ x: 'fakeFilter' }
]
};
try {
spyApp.getFilters.and.returnValue(Promise.resolve(testData.filters));
const filters = await page1.getFilters();
// Assert
expect(spyApp.getFilters).toHaveBeenCalled();
// @ts-ignore as testData is not of type IFilter as testData is not of type IFilter
expect(filters).toEqual(testData.filters);
} catch (error) {
fail("getFilters shouldn't fail");
}
});
it('page.setFilters(filters) returns promise that rejects with validation errors if filter is invalid', async function () {
// Arrange
const testData = {
filters: [
(new models.BasicFilter({ table: "cars", column: "make" }, "In", ["subaru", "honda"])).toJSON()
],
expectedErrors: [
{
message: 'invalid filter'
}
]
};
// await iframeLoaded;
try {
spyApp.validateFilter.and.callFake(() => Promise.reject(testData.expectedErrors));
await page1.setFilters(testData.filters);
fail("setilters shouldn't fail");
} catch (error) {
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
expect(spyApp.setFilters).not.toHaveBeenCalled();
expect(error).toEqual(jasmine.objectContaining(testData.expectedErrors));
}
});
it('page.setFilters(filters) returns promise that resolves with null if filter was valid and request is accepted', async function () {
// Arrange
const testData = {
filters: [(new models.BasicFilter({ table: "cars", column: "make" }, "In", ["subaru", "honda"])).toJSON()]
};
spyApp.validateFilter.and.returnValue(Promise.resolve(null));
spyApp.setFilters.and.returnValue(Promise.resolve(null));
try {
await page1.setFilters(testData.filters);
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
expect(spyApp.setFilters).toHaveBeenCalledWith(testData.filters);
} catch (error) {
console.log("setFilters failed with", error);
fail("setilters failed");
}
});
it('page.removeFilters() returns promise that resolves with null if the request was accepted', async function () {
// Arrange
try {
spyApp.updateFilters.and.returnValue(Promise.resolve(null));
// Act
await page1.removeFilters();
} catch (error) {
console.log("removeFilters failed with", error);
fail("removeFilters failed");
}
// Assert
expect(spyApp.updateFilters).toHaveBeenCalledWith(models.FiltersOperations.RemoveAll, undefined);
});
describe('setActive', function () {
it('page.setActive() returns promise that rejects if page is invalid', async function () {
// Arrange
const testData = {
errors: [
{
message: 'page xyz was not found in report'
}
]
};
spyApp.validatePage.and.callFake(() => Promise.reject(testData.errors));
try {
// Act
await page1.setActive();
fail("setActive shouldn't succeed");
} catch (errors) {
expect(spyApp.validatePage).toHaveBeenCalled();
expect(spyApp.setPage).not.toHaveBeenCalled();
expect(errors).toEqual(jasmine.objectContaining(testData.errors));
}
spyApp.validatePage.and.callThrough();
});
it('page.setActive() returns promise that resolves with null if request is successful', async function () {
// Act
spyApp.validatePage.and.returnValue(Promise.resolve(null));
spyApp.setPage.and.returnValue(Promise.resolve(null));
try {
await page1.setActive();
expect(spyApp.validatePage).toHaveBeenCalled();
expect(spyApp.setPage).toHaveBeenCalled();
} catch (error) {
console.log("setActive failed with ", error);
fail("setActive failed");
}
});
});
});
});
describe('SDK-to-Router (Event subscription)', function () {
it(`report.on(eventName, handler) should throw error if eventName is not supported`, function () {
// Arrange
const testData = {
eventName: 'xyz',
handler: jasmine.createSpy('handler')
};
try {
report.on(testData.eventName, testData.handler);
fail("should throw exception");
} catch (error) {
expect(1).toEqual(1);
}
});
it(`report.on(eventName, handler) should register handler and be called when POST /report/:uniqueId/events/:eventName is received`, async function () {
// Arrange
const testData = {
reportId: 'fakeReportId',
eventName: 'pageChanged',
handler: jasmine.createSpy('handler'),
simulatedPageChangeBody: {
initiator: 'sdk',
newPage: {
name: 'page1',
displayName: 'Page 1'
}
},
expectedEvent: {
detail: {
initiator: 'sdk',
newPage: report.page('page1')
}
}
};
report.on(testData.eventName, testData.handler);
try {
// Act
await iframeHpm.post(`/reports/${report.config.uniqueId}/events/${testData.eventName}`, testData.simulatedPageChangeBody);
} catch (error) {
fail("testshouldn't fail");
}
// Assert
expect(testData.handler).toHaveBeenCalledWith(jasmine.any(CustomEvent));
// Workaround to compare pages which prevents recursive loop in jasmine equals
// expect(testData.handler2).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.simulatedPageChangeBody }));
expect(testData.handler.calls.mostRecent().args[0].detail.newPage.name).toEqual(testData.expectedEvent.detail.newPage.name);
});
it(`if multiple reports with the same id are loaded into the host, and event occurs on one of them, only one report handler should be called`, async function () {
// Arrange
const testData = {
reportId: 'fakeReportId',
eventName: 'pageChanged',
handler: jasmine.createSpy('handler'),
handler2: jasmine.createSpy('handler2'),
simulatedPageChangeBody: {
initiator: 'sdk',
newPage: {
name: 'page1',
displayName: 'Page 1'
}
}
};
// Create a second iframe and report
const element2 = document.createElement('div');
element2.id = "reportContainer2";
element2.className = 'powerbi-report-container3';
document.body.appendChild(element2);
const report2 = <report.Report>powerbi.embed(element2, embedConfiguration);
const iframe2 = element2.getElementsByTagName('iframe')[0];
setupEmbedMockApp(iframe2.contentWindow, window, logMessages, 'SDK-to-MockApp IframeWpmp2');
await new Promise<void>((resolve, _reject) => {
iframe2.addEventListener('load', () => {
resolve(null);
});
});
report.on(testData.eventName, testData.handler);
report2.on(testData.eventName, testData.handler2);
try {
await iframeHpm.post(`/reports/${report2.config.uniqueId}/events/${testData.eventName}`, testData.simulatedPageChangeBody);
} catch (error) {
powerbi.reset(element2);
element2.remove();
fail("hpm post shouldn't fail");
}
// Act
expect(testData.handler).not.toHaveBeenCalled();
expect(testData.handler2).toHaveBeenCalledWith(jasmine.any(CustomEvent));
// Workaround to compare pages which prevents recursive loop in jasmine equals
// expect(testData.handler).toHaveBeenCalledWith(jasmine.objectContaining(testData.expectedEvent));
expect(testData.handler2.calls.mostRecent().args[0].detail.newPage.name).toEqual(testData.simulatedPageChangeBody.newPage.name);
powerbi.reset(element2);
element2.remove();
});
it(`ensure load event is allowed`, async function () {
// Arrange
const testData = {
reportId: 'fakeReportId',
eventName: 'loaded',
handler: jasmine.createSpy('handler3'),
simulatedBody: {
initiator: 'sdk'
}
};
report.on(testData.eventName, testData.handler);
// Act
try {
await iframeHpm.post(`/reports/${report.config.uniqueId}/events/${testData.eventName}`, testData.simulatedBody);
} catch (error) {
fail("ensure load event is allowed failed");
}
// Assert
expect(testData.handler).toHaveBeenCalledWith(jasmine.any(CustomEvent));
expect(testData.handler).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.simulatedBody }));
});
});
});
});

196
test/SDK-to-WPMP.spec.ts Normal file
Просмотреть файл

@ -0,0 +1,196 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import * as service from '../src/service';
import * as report from '../src/report';
import * as Wpmp from 'window-post-message-proxy';
import * as factories from '../src/factories';
import { spyWpmp } from './utility/mockWpmp';
import { spyHpm } from './utility/mockHpm';
import { spyRouter } from './utility/mockRouter';
import { iframeSrc } from './constsants';
describe('SDK-to-WPMP', function () {
let element: HTMLDivElement;
let powerbi: service.Service;
let report: report.Report;
let uniqueId: string;
beforeEach(function () {
const spyWpmpFactory: factories.IWpmpFactory = (_name?: string, _logMessages?: boolean) => {
return <Wpmp.WindowPostMessageProxy>spyWpmp;
};
powerbi = new service.Service(factories.hpmFactory, spyWpmpFactory, factories.routerFactory);
element = document.createElement('div');
element.className = 'powerbi-report-container';
const embedConfiguration = {
type: "report",
id: "fakeReportId",
accessToken: 'fakeToken',
embedUrl: iframeSrc,
wpmpName: 'SDK-to-WPMP report wpmp'
};
const hpmPostpy = spyOn(powerbi.hpm, "post").and.callFake(() => Promise.resolve(<any>{}));
report = <report.Report>powerbi.embed(element, embedConfiguration);
hpmPostpy.and.callThrough();
uniqueId = report.config.uniqueId;
spyHpm.post.calls.reset();
});
afterEach(function () {
powerbi.reset(element);
element.remove();
spyWpmp.stop();
spyWpmp.addHandler.calls.reset();
spyWpmp.clearHandlers();
spyHpm.get.calls.reset();
spyHpm.post.calls.reset();
spyHpm.patch.calls.reset();
spyHpm.put.calls.reset();
spyHpm.delete.calls.reset();
spyRouter.get.calls.reset();
spyRouter.post.calls.reset();
spyRouter.patch.calls.reset();
spyRouter.put.calls.reset();
spyRouter.delete.calls.reset();
});
describe('Event handlers', function () {
it(`handler passed to report.on(eventName, handler) is called when POST /report/:uniqueId/events/:eventName is received`, function () {
// Arrange
const testData = {
eventName: 'filtersApplied',
handler: jasmine.createSpy('handler'),
filtersAppliedEvent: {
data: {
method: 'POST',
url: `/reports/${uniqueId}/events/filtersApplied`,
body: {
initiator: 'sdk',
filters: [
{
x: 'fakeFilter'
}
]
}
}
}
};
report.on(testData.eventName, testData.handler);
// Act
spyWpmp.onMessageReceived(testData.filtersAppliedEvent);
// Assert
expect(testData.handler).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.filtersAppliedEvent.data.body }));
});
it(`off('eventName', handler) will remove single handler which matches function reference for that event`, function () {
// Arrange
const testData = {
eventName: 'filtersApplied',
handler: jasmine.createSpy('handler1'),
simulatedEvent: {
data: {
method: 'POST',
url: `/reports/${uniqueId}/events/filtersApplied`,
body: {
initiator: 'sdk',
filter: {
x: '1',
y: '2'
}
}
}
}
};
report.on(testData.eventName, testData.handler);
report.off(testData.eventName, testData.handler);
// Act
spyWpmp.onMessageReceived(testData.simulatedEvent);
// Assert
expect(testData.handler).not.toHaveBeenCalled();
});
it('if multiple handlers for the same event are registered they will all be called', function () {
// Arrange
const testData = {
eventName: 'filtersApplied',
handler: jasmine.createSpy('handler1'),
handler2: jasmine.createSpy('handler2'),
handler3: jasmine.createSpy('handler3'),
simulatedEvent: {
data: {
method: 'POST',
url: `/reports/${uniqueId}/events/filtersApplied`,
body: {
initiator: 'sdk',
filter: {
x: '1',
y: '2'
}
}
}
}
};
report.on(testData.eventName, testData.handler);
report.on(testData.eventName, testData.handler2);
report.on(testData.eventName, testData.handler3);
// Act
spyWpmp.onMessageReceived(testData.simulatedEvent);
// Assert
expect(testData.handler).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.simulatedEvent.data.body }));
expect(testData.handler2).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.simulatedEvent.data.body }));
expect(testData.handler3).toHaveBeenCalledWith(jasmine.objectContaining({ detail: testData.simulatedEvent.data.body }));
});
it(`off('eventName') will remove all handlers which matches event name`, function () {
// Arrange
const testData = {
eventName: 'filtersApplied',
handler: jasmine.createSpy('handler1'),
handler2: jasmine.createSpy('handler2'),
handler3: jasmine.createSpy('handler3'),
simulatedEvent: {
data: {
method: 'POST',
url: '/reports/fakeReportId/events/filtersApplied',
body: {
initiator: 'sdk',
filter: {
x: '1',
y: '2'
}
}
}
}
};
report.on(testData.eventName, testData.handler);
report.on(testData.eventName, testData.handler2);
report.on(testData.eventName, testData.handler3);
report.off(testData.eventName);
// Act
spyWpmp.onMessageReceived(testData.simulatedEvent);
// Assert
expect(testData.handler).not.toHaveBeenCalled();
expect(testData.handler2).not.toHaveBeenCalled();
expect(testData.handler3).not.toHaveBeenCalled();
});
});
});

14
test/constsants.ts Normal file
Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
declare global {
interface Window {
__karma__: any;
}
}
export const logMessages = (window.__karma__.config.args[0] === 'logMessages');
export const iframeSrc = "base/test/utility/noop.html";
window.onbeforeunload = null;

Просмотреть файл

@ -439,7 +439,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(target, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withTargetObject(target)
@ -460,7 +459,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(columnTarget, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withColumnTarget('table', 'column')
@ -481,7 +479,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(measureTarget, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withMeasureTarget('table', 'measure')
@ -502,7 +499,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(hierarchyLevelTarget, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name')
@ -523,7 +519,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(columnAggregationTarget, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withColumnAggregation('table', 'column', 'Avg')
@ -544,7 +539,6 @@ describe('filter builders', function () {
const includeToday = true;
const relativeDateFilter: models.RelativeDateFilter = new models.RelativeDateFilter(hierarchyLevelAggregationTarget, operator, timeUnitsCount, timeUnitType, includeToday);
// Act
const relativeDateFilterWithBuilder: models.RelativeDateFilter = new RelativeDateFilterBuilder()
.withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg')
@ -567,7 +561,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(target, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withTargetObject(target)
@ -586,7 +579,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(columnTarget, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withColumnTarget('table', 'column')
@ -605,7 +597,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(measureTarget, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withMeasureTarget('table', 'measure')
@ -624,7 +615,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(hierarchyLevelTarget, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withHierarchyLevelTarget('table', 'hierarchy', 'hierarchy level name')
@ -643,7 +633,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(columnAggregationTarget, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withColumnAggregation('table', 'column', 'Avg')
@ -662,7 +651,6 @@ describe('filter builders', function () {
const timeUnitType = models.RelativeDateFilterTimeUnit.Hours;
const relativeTimeFilter: models.RelativeTimeFilter = new models.RelativeTimeFilter(hierarchyLevelAggregationTarget, operator, timeUnitsCount, timeUnitType);
// Act
const relativeTimeFilterWithBuilder: models.RelativeTimeFilter = new RelativeTimeFilterBuilder()
.withHierarchyLevelAggregationTarget('table', 'hierarchy', 'hierarchy level name', 'Avg')
@ -674,4 +662,4 @@ describe('filter builders', function () {
expect(relativeTimeFilterWithBuilder).toEqual(relativeTimeFilter);
});
});
});
});

1194
test/protocol.spec.ts Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

1044
test/service.spec.ts Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -90,42 +90,77 @@ export const mockAppSpyObj = {
setAccessToken: jasmine.createSpy("setAccessToken").and.returnValue(Promise.resolve(null)),
switchLayout: jasmine.createSpy("switchLayout").and.returnValue(Promise.resolve(null)),
reset() {
reset(): void {
mockAppSpyObj.dashboardLoad.calls.reset();
mockAppSpyObj.dashboardLoad.and.callThrough();
mockAppSpyObj.validateDashboardLoad.calls.reset();
mockAppSpyObj.validateDashboardLoad.and.callThrough();
mockAppSpyObj.reportLoad.calls.reset();
mockAppSpyObj.reportLoad.and.callThrough();
mockAppSpyObj.render.calls.reset();
mockAppSpyObj.render.and.callThrough();
mockAppSpyObj.validateReportLoad.calls.reset();
mockAppSpyObj.validateReportLoad.and.callThrough();
mockAppSpyObj.updateSettings.calls.reset();
mockAppSpyObj.updateSettings.and.callThrough();
mockAppSpyObj.validateSettings.calls.reset();
mockAppSpyObj.validateSettings.and.callThrough();
mockAppSpyObj.setVisualDisplayState.calls.reset();
mockAppSpyObj.setVisualDisplayState.and.callThrough();
mockAppSpyObj.resizeVisual.calls.reset();
mockAppSpyObj.resizeVisual.and.callThrough();
mockAppSpyObj.resizeActivePage.calls.reset();
mockAppSpyObj.resizeActivePage.and.callThrough();
mockAppSpyObj.moveVisual.calls.reset();
mockAppSpyObj.moveVisual.and.callThrough();
mockAppSpyObj.getPages.calls.reset();
mockAppSpyObj.getPages.and.callThrough();
mockAppSpyObj.getPageByName.calls.reset();
mockAppSpyObj.getPageByName.and.callThrough();
mockAppSpyObj.getActivePage.calls.reset();
mockAppSpyObj.getActivePage.and.callThrough();
mockAppSpyObj.setPage.calls.reset();
mockAppSpyObj.setPage.and.callThrough();
mockAppSpyObj.validatePage.calls.reset();
mockAppSpyObj.validatePage.and.callThrough();
mockAppSpyObj.validateVisual.calls.reset();
mockAppSpyObj.validateVisual.and.callThrough();
mockAppSpyObj.getVisualByName.calls.reset();
mockAppSpyObj.getVisualByName.and.callThrough();
mockAppSpyObj.getFilters.calls.reset();
mockAppSpyObj.getFilters.and.callThrough();
mockAppSpyObj.updateFilters.calls.reset();
mockAppSpyObj.updateFilters.and.callThrough();
mockAppSpyObj.setFilters.calls.reset();
mockAppSpyObj.setFilters.and.callThrough();
mockAppSpyObj.validateFilter.calls.reset();
mockAppSpyObj.validateFilter.and.callThrough();
mockAppSpyObj.addContextMenuCommand.calls.reset();
mockAppSpyObj.addContextMenuCommand.and.callThrough();
mockAppSpyObj.addOptionsMenuCommand.calls.reset();
mockAppSpyObj.addOptionsMenuCommand.and.callThrough();
mockAppSpyObj.removeContextMenuCommand.calls.reset();
mockAppSpyObj.removeContextMenuCommand.and.callThrough();
mockAppSpyObj.removeOptionsMenuCommand.calls.reset();
mockAppSpyObj.removeOptionsMenuCommand.and.callThrough();
mockAppSpyObj.print.calls.reset();
mockAppSpyObj.print.and.callThrough();
mockAppSpyObj.refreshData.calls.reset();
mockAppSpyObj.refreshData.and.callThrough();
mockAppSpyObj.exportData.calls.reset();
mockAppSpyObj.exportData.and.callThrough();
mockAppSpyObj.validateCreateReport.calls.reset();
mockAppSpyObj.validateCreateReport.and.callThrough();
mockAppSpyObj.switchMode.calls.reset();
mockAppSpyObj.switchMode.and.callThrough();
mockAppSpyObj.save.calls.reset();
mockAppSpyObj.save.and.callThrough();
mockAppSpyObj.saveAs.calls.reset();
mockAppSpyObj.saveAs.and.callThrough();
mockAppSpyObj.setAccessToken.calls.reset();
mockAppSpyObj.setAccessToken.and.callThrough();
mockAppSpyObj.switchLayout.calls.reset();
mockAppSpyObj.switchLayout.and.callThrough();
}
};

Просмотреть файл

@ -1,293 +1,271 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import * as Wpmp from 'window-post-message-proxy';
import * as Hpm from 'http-post-message';
import * as Router from 'powerbi-router';
import * as models from 'powerbi-models';
import { WindowPostMessageProxy } from 'window-post-message-proxy';
import { HttpPostMessage } from 'http-post-message';
import { Router } from 'powerbi-router';
import { mockAppSpyObj, mockApp } from './mockApp';
import * as models from 'powerbi-models';
export const spyApp = mockAppSpyObj;
export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Window, logMessages: boolean, name: string = 'MockAppWindowPostMessageProxy'): Hpm.HttpPostMessage {
export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Window, logMessages: boolean, name: string = 'MockAppWindowPostMessageProxy'): HttpPostMessage {
const parent = parentWindow || iframeContentWindow.parent;
const wpmp = new Wpmp.WindowPostMessageProxy({
const wpmp = new WindowPostMessageProxy({
processTrackingProperties: {
addTrackingProperties: Hpm.HttpPostMessage.addTrackingProperties,
getTrackingProperties: Hpm.HttpPostMessage.getTrackingProperties,
addTrackingProperties: HttpPostMessage.addTrackingProperties,
getTrackingProperties: HttpPostMessage.getTrackingProperties,
},
isErrorMessage: Hpm.HttpPostMessage.isErrorMessage,
isErrorMessage: HttpPostMessage.isErrorMessage,
receiveWindow: iframeContentWindow,
name,
logMessages
});
const hpm = new Hpm.HttpPostMessage(wpmp, {
const hpm = new HttpPostMessage(wpmp, {
'origin': 'reportEmbedMock',
'x-version': '1.0.0'
}, parent);
const router = new Router.Router(wpmp);
const router = new Router(wpmp);
const app = mockApp;
/**
* Setup not found handlers.
*/
function notFoundHandler(req, res) {
function notFoundHandler(req, res): void {
res.send(404, `Not Found. Url: ${req.params.notfound} was not found.`);
};
}
router.get('*notfound', notFoundHandler);
router.post('*notfound', notFoundHandler);
router.patch('*notfound', notFoundHandler);
router.put('*notfound', notFoundHandler);
router.delete('*notfound', notFoundHandler);
/**
* Phase 1
*/
/**
* Dashboard Embed
*/
router.post('/dashboard/load', (req, res) => {
router.post('/dashboard/load', async (req, res) => {
const uniqueId = req.headers['uid'];
const loadConfig = req.body;
return app.validateDashboardLoad(loadConfig)
.then(() => {
app.dashboardLoad(loadConfig)
.then(() => {
const initiator = "sdk";
hpm.post(`/dashboards/${uniqueId}/events/loaded`, {
initiator
});
}, error => {
hpm.post(`/dashboards/${uniqueId}/events/error`, error);
});
res.send(202);
}, error => {
res.send(400, error);
});
try {
await app.validateDashboardLoad(loadConfig);
try {
await app.dashboardLoad(loadConfig);
hpm.post(`/dashboards/${uniqueId}/events/loaded`, {
initiator: "sdk"
});
} catch (error) {
hpm.post(`/dashboards/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
/**
* Create Report
*/
router.post('/report/create', (req, res) => {
router.post('/report/create', async (req, res) => {
const uniqueId = req.headers['uid'];
const createConfig = req.body;
return app.validateCreateReport(createConfig)
.then(() => {
app.reportLoad(createConfig)
.then(() => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, error => {
res.send(400, error);
});
try {
await app.validateCreateReport(createConfig);
try {
await app.reportLoad(createConfig);
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator: "sdk"
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
/**
* Report Embed
*/
router.post('/report/load', (req, res) => {
router.post('/report/load', async (req, res) => {
const uniqueId = req.headers['uid'];
const loadConfig = req.body;
return app.validateReportLoad(loadConfig)
.then(() => {
app.reportLoad(loadConfig)
.then(() => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
try {
await app.validateReportLoad(loadConfig);
try {
await app.reportLoad(loadConfig);
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator: "sdk"
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
res.send(202);
}, error => {
res.send(400, error);
});
} catch (error) {
res.send(400, error);
}
});
/**
* Report Embed
*/
router.post('/report/prepare', (req, res) => {
router.post('/report/prepare', async (req, res) => {
const uniqueId = req.headers['uid'];
const loadConfig = req.body;
return app.validateReportLoad(loadConfig)
.then(() => {
app.reportLoad(loadConfig)
.then(() => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
try {
await app.validateReportLoad(loadConfig);
try {
await app.reportLoad(loadConfig);
hpm.post(`/reports/${uniqueId}/events/loaded`, {
initiator: "sdk"
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
res.send(202);
}, error => {
res.send(400, error);
});
} catch (error) {
res.send(400, error);
}
});
router.post('/report/render', (req, res) => {
app.render();
res.send(202);
res.send(202, {});
});
router.get('/report/pages', (req, res) => {
return app.getPages()
.then(pages => {
res.send(200, pages);
}, error => {
res.send(500, error);
});
router.get('/report/pages', async (req, res) => {
try {
const pages = await app.getPages();
res.send(200, pages);
} catch (error) {
res.send(500, error);
}
});
router.put('/report/pages/active', (req, res) => {
router.put('/report/pages/active', async (req, res) => {
const uniqueId = req.headers['uid'];
const page = req.body;
return app.validatePage(page)
.then(() => {
app.setPage(page)
.then(() => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/pageChanged`, {
initiator,
newPage: page
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, errors => {
res.send(400, errors);
});
try {
await app.validatePage(page);
try {
await app.setPage(page);
hpm.post(`/reports/${uniqueId}/events/pageChanged`, {
initiator: "sdk",
newPage: page
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202);
} catch (error) {
res.send(400, error);
}
});
/**
* Phase 2
*/
router.get('/report/filters', (req, res) => {
return app.getFilters()
.then(filters => {
res.send(200, filters);
}, error => {
res.send(500, error);
});
router.get('/report/filters', async (req, res) => {
try {
const filters = await app.getFilters();
res.send(200, filters);
} catch (error) {
res.send(500, error);
}
});
router.put('/report/filters', (req, res) => {
router.put('/report/filters', async (req, res) => {
const uniqueId = req.headers['uid'];
const filters = req.body;
return Promise.all(filters.map(filter => app.validateFilter(filter)))
.then(() => {
app.setFilters(filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, error => {
res.send(400, error);
});
try {
await Promise.all(filters.map(filter => app.validateFilter(filter)));
try {
const filter = await app.setFilters(filters);
hpm.post(`/reports/${uniqueId}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
router.post('/report/filters', (req, res) => {
router.post('/report/filters', async (req, res) => {
const uniqueId = req.headers['uid'];
const operation = req.body.filtersOperation
const operation = req.body.filtersOperation;
const filters = req.body.filters;
return Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)])
.then(() => {
app.updateFilters(operation, filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, error => {
res.send(400, error);
});
try {
Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)]);
try {
const filter = await app.updateFilters(operation, filters);
hpm.post(`/reports/${uniqueId}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
/**
* Phase 3
*/
router.get('/report/pages/:pageName/filters', (req, res) => {
router.get('/report/pages/:pageName/filters', async (req, res) => {
const page = {
name: req.params.pageName,
displayName: null
};
return app.validatePage(page)
.then(() => {
return app.getFilters()
.then(filters => {
res.send(200, filters);
}, error => {
res.send(500, error);
});
}, errors => {
res.send(400, errors);
});
try {
await app.validatePage(page);
try {
const filters = await app.getFilters();
res.send(200, filters);
} catch (error) {
res.send(500, error);
}
} catch (error) {
res.send(400, error);
}
});
router.post('/report/pages/:pageName/filters', (req, res) => {
router.post('/report/pages/:pageName/filters', async (req, res) => {
const pageName = req.params.pageName;
const uniqueId = req.headers['uid'];
const operation = req.body.filtersOperation
const operation = req.body.filtersOperation;
const filters = req.body.filters;
const page: models.IPage = {
name: pageName,
displayName: null
};
return app.validatePage(page)
.then(() => Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)]))
.then(() => {
app.updateFilters(operation, filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/pages/${pageName}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
try {
await app.validatePage(page);
await Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)]);
try {
const filter = await app.updateFilters(operation, filters);
hpm.post(`/reports/${uniqueId}/pages/${pageName}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
res.send(202);
}, errors => {
res.send(400, errors);
});
} catch (error) {
res.send(400, error);
}
});
router.put('/report/pages/:pageName/filters', (req, res) => {
router.put('/report/pages/:pageName/filters', async (req, res) => {
const pageName = req.params.pageName;
const uniqueId = req.headers['uid'];
const filters = req.body;
@ -295,28 +273,25 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
name: pageName,
displayName: null
};
return app.validatePage(page)
.then(() => Promise.all(filters.map(filter => app.validateFilter(filter))))
.then(() => {
app.setFilters(filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/pages/${pageName}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, errors => {
res.send(400, errors);
});
try {
await app.validatePage(page);
await Promise.all(filters.map(filter => app.validateFilter(filter)));
try {
const filter = await app.setFilters(filters);
hpm.post(`/reports/${uniqueId}/pages/${pageName}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
router.get('/report/pages/:pageName/visuals/:visualName/filters', (req, res) => {
router.get('/report/pages/:pageName/visuals/:visualName/filters', async (req, res) => {
const page = {
name: req.params.pageName,
displayName: null
@ -328,24 +303,24 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
layout: {},
};
return app.validateVisual(page, visual)
.then(() => {
return app.getFilters()
.then(filters => {
res.send(200, filters);
}, error => {
res.send(500, error);
});
}, errors => {
res.send(400, errors);
});
try {
await app.validateVisual(page, visual);
try {
const filters = await app.getFilters();
res.send(200, filters);
} catch (error) {
res.send(500, error);
}
} catch (error) {
res.send(400, error);
}
});
router.post('/report/pages/:pageName/visuals/:visualName/filters', (req, res) => {
router.post('/report/pages/:pageName/visuals/:visualName/filters', async (req, res) => {
const pageName = req.params.pageName;
const visualName = req.params.visualName;
const uniqueId = req.headers['uid'];
const operation = req.body.filtersOperation
const operation = req.body.filtersOperation;
const filters = req.body.filters; const page: models.IPage = {
name: pageName,
displayName: null
@ -357,27 +332,25 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
layout: {},
};
return app.validateVisual(page, visual)
.then(() => Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)]))
.then(() => {
app.updateFilters(operation, filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/pages/${pageName}/visuals/${visualName}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, errors => {
res.send(400, errors);
});
try {
await app.validateVisual(page, visual);
await Promise.all(filters ? filters.map(filter => app.validateFilter(filter)) : [Promise.resolve(null)]);
try {
const filter = await app.updateFilters(operation, filters);
hpm.post(`/reports/${uniqueId}/pages/${pageName}/visuals/${visualName}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
router.put('/report/pages/:pageName/visuals/:visualName/filters', (req, res) => {
router.put('/report/pages/:pageName/visuals/:visualName/filters', async (req, res) => {
const pageName = req.params.pageName;
const visualName = req.params.visualName;
const uniqueId = req.headers['uid'];
@ -392,58 +365,48 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
type: 'type',
layout: {},
};
return app.validateVisual(page, visual)
.then(() => Promise.all(filters.map(filter => app.validateFilter(filter))))
.then(() => {
app.setFilters(filters)
.then(filter => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/pages/${pageName}/visuals/${visualName}/events/filtersApplied`, {
initiator,
filter
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, errors => {
res.send(400, errors);
});
try {
await app.validateVisual(page, visual);
await Promise.all(filters.map(filter => app.validateFilter(filter)));
try {
const filter = await app.setFilters(filters);
hpm.post(`/reports/${uniqueId}/pages/${pageName}/visuals/${visualName}/events/filtersApplied`, {
initiator: "sdk",
filter
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
} catch (error) {
res.send(400, error);
}
});
router.patch('/report/settings', (req, res) => {
router.patch('/report/settings', async (req, res) => {
const uniqueId = req.headers['uid'];
const settings = req.body;
return app.validateSettings(settings)
.then(() => {
app.updateSettings(settings)
.then(updatedSettings => {
const initiator = "sdk";
hpm.post(`/reports/${uniqueId}/events/settingsUpdated`, {
initiator,
settings: updatedSettings
});
}, error => {
hpm.post(`/reports/${uniqueId}/events/error`, error);
});
res.send(202);
}, errors => {
res.send(400, errors);
});
try {
await app.validateSettings(settings);
try {
const updatedSettings = await app.updateSettings(settings);
hpm.post(`/reports/${uniqueId}/events/settingsUpdated`, {
initiator: "sdk",
settings: updatedSettings
});
} catch (error) {
hpm.post(`/reports/${uniqueId}/events/error`, error);
}
res.send(202, {});
}
catch (error) {
res.send(400, error);
}
});
/**
* Phase 4
*/
router.get('/report/data', (req, res) => {
return app.exportData()
.then(data => {
res.send(200, data);
});
router.get('/report/data', async (req, res) => {
const data = await app.exportData();
res.send(200, data);
});
router.post('/report/refresh', (req, res) => {
@ -477,6 +440,5 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
app.setAccessToken(settings);
res.send(202);
});
return hpm;
}
}

Просмотреть файл

@ -2,9 +2,9 @@
// Licensed under the MIT License.
export const spyHpm = {
get: jasmine.createSpy("get").and.returnValue(Promise.resolve(null)),
post: jasmine.createSpy("post").and.returnValue(Promise.resolve(null)),
patch: jasmine.createSpy("patch").and.returnValue(Promise.resolve(null)),
put: jasmine.createSpy("put").and.returnValue(Promise.resolve(null)),
delete: jasmine.createSpy("delete").and.returnValue(Promise.resolve(null))
};
get: jasmine.createSpy("get").and.returnValue(Promise.resolve({})),
post: jasmine.createSpy("post").and.returnValue(Promise.resolve({})),
patch: jasmine.createSpy("patch").and.returnValue(Promise.resolve({})),
put: jasmine.createSpy("put").and.returnValue(Promise.resolve({})),
delete: jasmine.createSpy("delete").and.returnValue(Promise.resolve({}))
};

Просмотреть файл

@ -7,4 +7,4 @@ export const spyRouter = {
patch: jasmine.createSpy("patch"),
put: jasmine.createSpy("put"),
delete: jasmine.createSpy("delete")
};
};

Просмотреть файл

@ -4,18 +4,18 @@
export const spyWpmp = {
handlers: [],
clearHandlers() {
clearHandlers(): void {
spyWpmp.handlers.length = 0;
},
addHandlerSpy(handler) {
addHandlerSpy(handler: any): void {
spyWpmp.handlers.push(handler);
},
addHandler: jasmine.createSpy("addHandler").and.callFake((x) => spyWpmp.addHandlerSpy(x)),
postMessageSpy: jasmine.createSpy("postMessage"),
postMessage<T>(message): Promise<T> {
postMessage<T>(message: any): Promise<T> {
spyWpmp.postMessageSpy(message);
return Promise.resolve(null);
},
@ -23,12 +23,12 @@ export const spyWpmp = {
start: jasmine.createSpy("start"),
stop: jasmine.createSpy("stop"),
onMessageReceived(event) {
onMessageReceived(event: any): void {
let message: any = event.data;
const handled = spyWpmp.handlers.some(handler => {
if (handler.test(message)) {
Promise.resolve(handler.handle(message))
Promise.resolve(handler.handle(message));
return true;
}
@ -38,4 +38,4 @@ export const spyWpmp = {
throw Error(`nothing handled message`);
}
}
};
};

Просмотреть файл

@ -3,7 +3,7 @@ const glob = require("glob");
module.exports = {
mode: 'development',
entry: glob.sync('./test/*.spec.ts'),
entry: glob.sync('./test/**/*.spec.ts'),
output: {
path: __dirname + "/tmp",
filename: 'test.spec.js'