Merged PR 3562: Visual level filters
Visual level filters update
This commit is contained in:
Родитель
7fe67bd0a2
Коммит
4efb122f4e
|
@ -419,6 +419,7 @@ declare module "ifilterable" {
|
|||
}
|
||||
declare module "visualDescriptor" {
|
||||
import * as models from 'powerbi-models';
|
||||
import { IFilterable } from "ifilterable";
|
||||
import { IPageNode } from "page";
|
||||
/**
|
||||
* A Visual node within a report hierarchy
|
||||
|
@ -440,7 +441,7 @@ declare module "visualDescriptor" {
|
|||
* @class VisualDescriptor
|
||||
* @implements {IVisualNode}
|
||||
*/
|
||||
export class VisualDescriptor implements IVisualNode {
|
||||
export class VisualDescriptor implements IVisualNode, IFilterable {
|
||||
/**
|
||||
* The visual name
|
||||
*
|
||||
|
@ -472,6 +473,39 @@ declare module "visualDescriptor" {
|
|||
*/
|
||||
page: IPageNode;
|
||||
constructor(page: IPageNode, name: string, title: string, type: string, layout: models.IVisualLayout);
|
||||
/**
|
||||
* Gets all visual level filters of the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.getFilters()
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
*/
|
||||
getFilters(): Promise<models.IFilter[]>;
|
||||
/**
|
||||
* Removes all filters from the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.removeFilters();
|
||||
* ```
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
removeFilters(): Promise<void>;
|
||||
/**
|
||||
* Sets the filters on the current visual to 'filters'.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.setFilters(filters);
|
||||
* .catch(errors => { ... });
|
||||
* ```
|
||||
*
|
||||
* @param {(models.IFilter[])} filters
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
setFilters(filters: models.IFilter[]): Promise<void>;
|
||||
}
|
||||
}
|
||||
declare module "page" {
|
||||
|
@ -536,7 +570,7 @@ declare module "page" {
|
|||
*
|
||||
* ```javascript
|
||||
* page.getFilters()
|
||||
* .then(pages => { ... });
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
|
|
|
@ -142,6 +142,15 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
};
|
||||
_this.handleEvent(event);
|
||||
});
|
||||
this.router.post("/reports/:uniqueId/pages/:pageName/visuals/:visualName/events/:eventName", function (req, res) {
|
||||
var event = {
|
||||
type: 'report',
|
||||
id: req.params.uniqueId,
|
||||
name: req.params.eventName,
|
||||
value: req.body
|
||||
};
|
||||
_this.handleEvent(event);
|
||||
});
|
||||
this.router.post("/dashboards/:uniqueId/events/:eventName", function (req, res) {
|
||||
var event = {
|
||||
type: 'dashboard',
|
||||
|
@ -3509,7 +3518,7 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
*
|
||||
* ```javascript
|
||||
* page.getFilters()
|
||||
* .then(pages => { ... });
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
|
@ -3615,6 +3624,51 @@ return /******/ (function(modules) { // webpackBootstrap
|
|||
this.layout = layout;
|
||||
this.page = page;
|
||||
}
|
||||
/**
|
||||
* Gets all visual level filters of the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.getFilters()
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
*/
|
||||
VisualDescriptor.prototype.getFilters = function () {
|
||||
return this.page.report.service.hpm.get("/report/pages/" + this.page.name + "/visuals/" + this.name + "/filters", { uid: this.page.report.config.uniqueId }, this.page.report.iframe.contentWindow)
|
||||
.then(function (response) { return response.body; }, function (response) {
|
||||
throw response.body;
|
||||
});
|
||||
};
|
||||
/**
|
||||
* Removes all filters from the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.removeFilters();
|
||||
* ```
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
VisualDescriptor.prototype.removeFilters = function () {
|
||||
return this.setFilters([]);
|
||||
};
|
||||
/**
|
||||
* Sets the filters on the current visual to 'filters'.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.setFilters(filters);
|
||||
* .catch(errors => { ... });
|
||||
* ```
|
||||
*
|
||||
* @param {(models.IFilter[])} filters
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
VisualDescriptor.prototype.setFilters = function (filters) {
|
||||
return this.page.report.service.hpm.put("/report/pages/" + this.page.name + "/visuals/" + this.name + "/filters", filters, { uid: this.page.report.config.uniqueId }, this.page.report.iframe.contentWindow)
|
||||
.catch(function (response) {
|
||||
throw response.body;
|
||||
});
|
||||
};
|
||||
return VisualDescriptor;
|
||||
}());
|
||||
exports.VisualDescriptor = VisualDescriptor;
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -70,7 +70,7 @@ export class Page implements IPageNode, IFilterable {
|
|||
*
|
||||
* ```javascript
|
||||
* page.getFilters()
|
||||
* .then(pages => { ... });
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
|
|
|
@ -145,6 +145,17 @@ export class Service implements IService {
|
|||
this.handleEvent(event);
|
||||
});
|
||||
|
||||
this.router.post(`/reports/:uniqueId/pages/:pageName/visuals/:visualName/events/:eventName`, (req, res) => {
|
||||
const event: IEvent<any> = {
|
||||
type: 'report',
|
||||
id: req.params.uniqueId,
|
||||
name: req.params.eventName,
|
||||
value: req.body
|
||||
};
|
||||
|
||||
this.handleEvent(event);
|
||||
});
|
||||
|
||||
this.router.post(`/dashboards/:uniqueId/events/:eventName`, (req, res) => {
|
||||
const event: IEvent<any> = {
|
||||
type: 'dashboard',
|
||||
|
|
|
@ -23,7 +23,7 @@ export interface IVisualNode {
|
|||
* @class VisualDescriptor
|
||||
* @implements {IVisualNode}
|
||||
*/
|
||||
export class VisualDescriptor implements IVisualNode {
|
||||
export class VisualDescriptor implements IVisualNode, IFilterable {
|
||||
/**
|
||||
* The visual name
|
||||
*
|
||||
|
@ -66,4 +66,53 @@ export class VisualDescriptor implements IVisualNode {
|
|||
this.layout = layout;
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all visual level filters of the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.getFilters()
|
||||
* .then(filters => { ... });
|
||||
* ```
|
||||
*
|
||||
* @returns {(Promise<models.IFilter[]>)}
|
||||
*/
|
||||
getFilters(): Promise<models.IFilter[]> {
|
||||
return this.page.report.service.hpm.get<models.IFilter[]>(`/report/pages/${this.page.name}/visuals/${this.name}/filters`, { uid: this.page.report.config.uniqueId }, this.page.report.iframe.contentWindow)
|
||||
.then(response => response.body,
|
||||
response => {
|
||||
throw response.body;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all filters from the current visual.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.removeFilters();
|
||||
* ```
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
removeFilters(): Promise<void> {
|
||||
return this.setFilters([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the filters on the current visual to 'filters'.
|
||||
*
|
||||
* ```javascript
|
||||
* visual.setFilters(filters);
|
||||
* .catch(errors => { ... });
|
||||
* ```
|
||||
*
|
||||
* @param {(models.IFilter[])} filters
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
setFilters(filters: models.IFilter[]): Promise<void> {
|
||||
return this.page.report.service.hpm.put<models.IError[]>(`/report/pages/${this.page.name}/visuals/${this.name}/filters`, filters, { uid: this.page.report.config.uniqueId }, this.page.report.iframe.contentWindow)
|
||||
.catch(response => {
|
||||
throw response.body;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import * as visual from '../src/visual';
|
|||
import * as create from '../src/create';
|
||||
import * as dashboard from '../src/dashboard';
|
||||
import * as page from '../src/page';
|
||||
import * as visualDescriptor from '../src/visualDescriptor';
|
||||
import * as Wpmp from 'window-post-message-proxy';
|
||||
import * as Hpm from 'http-post-message';
|
||||
import * as Router from 'powerbi-router';
|
||||
|
@ -862,6 +863,11 @@ describe('Protocol', function () {
|
|||
res.send(202);
|
||||
});
|
||||
|
||||
router.post('/reports/:uniqueId/pages/:pageName/visuals/:visualName/events/:eventName', (req, res) => {
|
||||
handler.handle(req);
|
||||
res.send(202);
|
||||
});
|
||||
|
||||
handler = {
|
||||
test: jasmine.createSpy("testSpy").and.returnValue(true),
|
||||
handle: jasmine.createSpy("handleSpy").and.callFake(function (message: any) {
|
||||
|
@ -1805,6 +1811,7 @@ describe('Protocol', function () {
|
|||
expect(spyApp.setFilters).not.toHaveBeenCalled();
|
||||
expect(response.statusCode).toEqual(400);
|
||||
// Cleanup
|
||||
spyApp.validatePage.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
done();
|
||||
});
|
||||
|
@ -1833,6 +1840,7 @@ describe('Protocol', function () {
|
|||
expect(spyApp.setFilters).toHaveBeenCalledWith(testData.filters);
|
||||
expect(response.statusCode).toEqual(202);
|
||||
// Cleanup
|
||||
spyApp.validatePage.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
spyApp.setFilters.calls.reset();
|
||||
done();
|
||||
|
@ -1870,6 +1878,164 @@ describe('Protocol', function () {
|
|||
expect(response.statusCode).toEqual(202);
|
||||
expect(spyHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining(testExpectedEvent));
|
||||
// Cleanup
|
||||
spyApp.validatePage.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
spyApp.setFilters.calls.reset();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('filters (visual level)', function () {
|
||||
it('GET /report/pages/xyz/visuals/uvw/filters returns 200 with body as array of filters', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
filters: [
|
||||
{
|
||||
name: "fakeFilter1"
|
||||
},
|
||||
{
|
||||
name: "fakeFilter2"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
spyApp.getFilters.and.returnValue(Promise.resolve(testData.filters));
|
||||
|
||||
// Act
|
||||
hpm.get<models.IFilter[]>('/report/pages/xyz/visuals/uvw/filters')
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(spyApp.getFilters).toHaveBeenCalled();
|
||||
expect(response.statusCode).toEqual(200);
|
||||
expect(response.body).toEqual(testData.filters);
|
||||
// Cleanup
|
||||
spyApp.getFilters.calls.reset();
|
||||
spyApp.validateVisual.calls.reset();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('GET /report/pages/xyz/visuals/uvw/filters returns 500 with body as error', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
error: {
|
||||
message: "internal error"
|
||||
}
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
spyApp.getFilters.and.returnValue(Promise.reject(testData.error));
|
||||
|
||||
// Act
|
||||
hpm.get<models.IFilter[]>('/report/pages/xyz/visuals/uvw/filters')
|
||||
.catch(response => {
|
||||
// Assert
|
||||
expect(spyApp.getFilters).toHaveBeenCalled();
|
||||
expect(response.statusCode).toEqual(500);
|
||||
expect(response.body).toEqual(testData.error);
|
||||
// Cleanup
|
||||
spyApp.getFilters.calls.reset();
|
||||
spyApp.validateVisual.calls.reset();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('PUT /report/pages/xyz/visuals/uvw/filters returns 400 if request is invalid', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
uniqueId: 'uniqueId',
|
||||
filters: [
|
||||
{
|
||||
name: "fakeFilter"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
spyApp.validateFilter.and.returnValue(Promise.reject(null));
|
||||
|
||||
// Act
|
||||
hpm.put<models.IError>('/report/pages/xyz/visuals/uvw/filters', testData.filters, { uid: testData.uniqueId })
|
||||
.catch(response => {
|
||||
// Assert
|
||||
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
|
||||
expect(spyApp.setFilters).not.toHaveBeenCalled();
|
||||
expect(response.statusCode).toEqual(400);
|
||||
// Cleanup
|
||||
spyApp.validateVisual.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('PUT /report/pages/xyz/visuals/uvw/filters returns 202 if request is valid', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
uniqueId: 'uniqueId',
|
||||
filters: [
|
||||
{
|
||||
name: "fakeFilter"
|
||||
}
|
||||
],
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
spyApp.validateFilter.and.returnValue(Promise.resolve(null));
|
||||
|
||||
// Act
|
||||
hpm.put<void>('/report/pages/xyz/visuals/uvw/filters', testData.filters, { uid: testData.uniqueId })
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
|
||||
expect(spyApp.setFilters).toHaveBeenCalledWith(testData.filters);
|
||||
expect(response.statusCode).toEqual(202);
|
||||
// Cleanup
|
||||
spyApp.validateVisual.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
spyApp.setFilters.calls.reset();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('PUT /report/:uniqueId/pages/xyz/visuals/uvw/filters will cause POST /reports/:uniqueId/pages/xyz/visuals/uvw/events/filtersApplied', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
uniqueId: 'uniqueId',
|
||||
filters: [
|
||||
{
|
||||
name: "fakeFilter"
|
||||
}
|
||||
]
|
||||
};
|
||||
const testExpectedEvent = {
|
||||
method: 'POST',
|
||||
url: `/reports/${testData.uniqueId}/pages/xyz/visuals/uvw/events/filtersApplied`
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
|
||||
// Act
|
||||
hpm.put<void>('/report/pages/xyz/visuals/uvw/filters', testData.filters, { uid: testData.uniqueId })
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(spyApp.validateFilter).toHaveBeenCalledWith(testData.filters[0]);
|
||||
expect(spyApp.setFilters).toHaveBeenCalledWith(testData.filters);
|
||||
expect(response.statusCode).toEqual(202);
|
||||
expect(spyHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining(testExpectedEvent));
|
||||
// Cleanup
|
||||
spyApp.validateVisual.calls.reset();
|
||||
spyApp.validateFilter.calls.reset();
|
||||
spyApp.setFilters.calls.reset();
|
||||
done();
|
||||
|
@ -2098,6 +2264,46 @@ describe('Protocol', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('filters (visual level)', function () {
|
||||
it('POST /reports/:uniqueId/pages/xyz/visuals/uvw/events/filtersApplied when user changes filter', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
uniqueId: 'uniqueId',
|
||||
reportId: 'fakeReportId',
|
||||
event: {
|
||||
initiator: 'user',
|
||||
filters: [
|
||||
{
|
||||
name: "fakeFilter"
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
const testExpectedRequest = {
|
||||
method: 'POST',
|
||||
url: `/reports/${testData.uniqueId}/pages/xyz/visuals/uvw/events/filtersApplied`,
|
||||
body: testData.event
|
||||
};
|
||||
|
||||
iframeLoaded
|
||||
.then(() => {
|
||||
spyHandler.handle.calls.reset();
|
||||
|
||||
// Act
|
||||
iframeHpm.post(testExpectedRequest.url, testData.event)
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(response.statusCode).toBe(202);
|
||||
expect(spyHandler.handle).toHaveBeenCalledWith(jasmine.objectContaining(testExpectedRequest));
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('settings', function () {
|
||||
it('POST /reports/:uniqueId/events/settingsUpdated when user changes settings', function (done) {
|
||||
// Arrange
|
||||
|
@ -2187,6 +2393,7 @@ describe('SDK-to-HPM', function () {
|
|||
let dashboard: dashboard.Dashboard;
|
||||
let embeddedVisual: visual.Visual;
|
||||
let page1: page.Page;
|
||||
let visual1: visualDescriptor.VisualDescriptor;
|
||||
let uniqueId = 'uniqueId';
|
||||
let createUniqueId = 'uniqueId';
|
||||
let dashboardUniqueId = 'uniqueId';
|
||||
|
@ -2253,6 +2460,7 @@ describe('SDK-to-HPM', function () {
|
|||
dashboard = <dashboard.Dashboard>powerbi.embed($dashboardElement[0], dashboardEmbedConfiguration);
|
||||
embeddedVisual = <visual.Visual>powerbi.embed($visualElement[0], visualEmbedConfiguration);
|
||||
page1 = new page.Page(report, 'xyz');
|
||||
visual1 = new visualDescriptor.VisualDescriptor(page1, 'uvw', 'title', 'type', {});
|
||||
uniqueId = report.config.uniqueId;
|
||||
createUniqueId = create.config.uniqueId;
|
||||
dashboardUniqueId = dashboard.config.uniqueId;
|
||||
|
@ -3317,6 +3525,159 @@ describe('SDK-to-HPM', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('visual', function () {
|
||||
describe('filters', function () {
|
||||
it('visual.getFilters() sends GET /report/pages/xyz/visuals/uvw/filters', function () {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
visual1.getFilters();
|
||||
|
||||
// Assert
|
||||
expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, { uid: uniqueId }, iframe.contentWindow);
|
||||
});
|
||||
|
||||
it('visual.getFilters() return promise that rejects with server error if there was error getting filters', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
expectedError: {
|
||||
body: {
|
||||
message: 'internal server error'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
spyHpm.get.and.returnValue(Promise.reject(testData.expectedError));
|
||||
|
||||
// Act
|
||||
visual1.getFilters()
|
||||
.catch(error => {
|
||||
// Assert
|
||||
expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, { uid: uniqueId }, iframe.contentWindow);
|
||||
expect(error).toEqual(testData.expectedError.body);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('visual.getFilters() returns promise that resolves with list of filters', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
expectedResponse: {
|
||||
body: [
|
||||
{ x: 'fakeFilter1' },
|
||||
{ x: 'fakeFilter2' }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
spyHpm.get.and.returnValue(Promise.resolve(testData.expectedResponse));
|
||||
|
||||
// Act
|
||||
visual1.getFilters()
|
||||
.then(filters => {
|
||||
// Assert
|
||||
expect(spyHpm.get).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, { uid: uniqueId }, iframe.contentWindow);
|
||||
expect(filters).toEqual(testData.expectedResponse.body);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('visual.setFilters(filters) sends PUT /report/pages/xyz/visuals/uvw/filters', function () {
|
||||
// Arrange
|
||||
const testData = {
|
||||
filters: [
|
||||
(new models.BasicFilter({ table: "Cars", measure: "Make" }, "In", ["subaru", "honda"])).toJSON(),
|
||||
(new models.AdvancedFilter({ table: "Cars", measure: "Make" }, "And", [{ value: "subaru", operator: "None" }, { value: "honda", operator: "Contains" }])).toJSON()
|
||||
],
|
||||
response: {
|
||||
body: []
|
||||
}
|
||||
};
|
||||
|
||||
spyHpm.put.and.returnValue(Promise.resolve(testData.response));
|
||||
|
||||
// Act
|
||||
visual1.setFilters(testData.filters);
|
||||
|
||||
// Assert
|
||||
expect(spyHpm.put).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, testData.filters, { uid: uniqueId }, iframe.contentWindow);
|
||||
});
|
||||
|
||||
it('visual.setFilters(filters) returns promise that rejects with validation errors if filter is invalid', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
filters: [
|
||||
(new models.BasicFilter({ table: "Cars", measure: "Make" }, "In", ["subaru", "honda"])).toJSON(),
|
||||
(new models.AdvancedFilter({ table: "Cars", measure: "Make" }, "And", [{ value: "subaru", operator: "None" }, { value: "honda", operator: "Contains" }])).toJSON()
|
||||
],
|
||||
expectedErrors: {
|
||||
body: [
|
||||
{
|
||||
message: 'target is invalid, missing property x'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
spyHpm.put.and.returnValue(Promise.reject(testData.expectedErrors));
|
||||
|
||||
// Act
|
||||
visual1.setFilters(testData.filters)
|
||||
.catch(errors => {
|
||||
// Assert
|
||||
expect(spyHpm.put).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, testData.filters, { uid: uniqueId }, iframe.contentWindow);
|
||||
expect(errors).toEqual(jasmine.objectContaining(testData.expectedErrors.body));
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('visual.setFilters(filters) returns promise that resolves with null if filter was valid and request is accepted', function (done) {
|
||||
// Arrange
|
||||
const testData = {
|
||||
filters: [
|
||||
(new models.BasicFilter({ table: "Cars", measure: "Make" }, "In", ["subaru", "honda"])).toJSON(),
|
||||
(new models.AdvancedFilter({ table: "Cars", measure: "Make" }, "And", [{ value: "subaru", operator: "None" }, { value: "honda", operator: "Contains" }])).toJSON()
|
||||
]
|
||||
};
|
||||
|
||||
spyHpm.put.and.returnValue(Promise.resolve(null));
|
||||
|
||||
// Act
|
||||
visual1.setFilters(testData.filters)
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(spyHpm.put).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, testData.filters, { uid: uniqueId }, iframe.contentWindow);
|
||||
expect(response).toEqual(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('visual.removeFilters() sends PUT /report/pages/xyz/visuals/uvw/filters', function () {
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
visual1.removeFilters();
|
||||
|
||||
// Assert
|
||||
expect(spyHpm.put).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, [], { uid: uniqueId }, iframe.contentWindow);
|
||||
});
|
||||
|
||||
it('visual.removeFilters() returns promise that resolves with null if request is accepted', function (done) {
|
||||
// Arrange
|
||||
spyHpm.put.and.returnValue(Promise.resolve(null));
|
||||
|
||||
// Act
|
||||
visual1.removeFilters()
|
||||
.then(response => {
|
||||
// Assert
|
||||
expect(spyHpm.put).toHaveBeenCalledWith(`/report/pages/${page1.name}/visuals/${visual1.name}/filters`, [], { uid: uniqueId }, iframe.contentWindow);
|
||||
expect(response).toEqual(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SDK-to-Router (Event subscription)', function () {
|
||||
/**
|
||||
* This test should likely be moved to mock app section or removed since it is already covered.
|
||||
|
|
|
@ -14,6 +14,8 @@ export interface IApp {
|
|||
getPages(): Promise<models.IPage>;
|
||||
setPage(pageName: string): Promise<void>;
|
||||
validatePage(page: models.IPage): Promise<models.IError[]>;
|
||||
// Visuals
|
||||
validateVisual(page: models.IPage, visual: models.IVisual): Promise<models.IError[]>;
|
||||
// Filters
|
||||
getFilters(): Promise<models.IFilter[]>;
|
||||
setFilters(filters: models.IFilter[]): Promise<void>;
|
||||
|
@ -43,6 +45,8 @@ export const mockAppSpyObj = {
|
|||
getPages: jasmine.createSpy("getPages").and.returnValue(Promise.resolve(null)),
|
||||
setPage: jasmine.createSpy("setPage").and.returnValue(Promise.resolve(null)),
|
||||
validatePage: jasmine.createSpy("validatePage").and.returnValue(Promise.resolve(null)),
|
||||
// Visuals
|
||||
validateVisual: jasmine.createSpy("validateVisual").and.returnValue(Promise.resolve(null)),
|
||||
// Filters
|
||||
getFilters: jasmine.createSpy("getFilters").and.returnValue(Promise.resolve(null)),
|
||||
setFilters: jasmine.createSpy("setFilters").and.returnValue(Promise.resolve(null)),
|
||||
|
@ -67,6 +71,7 @@ export const mockAppSpyObj = {
|
|||
mockAppSpyObj.getPages.calls.reset();
|
||||
mockAppSpyObj.setPage.calls.reset();
|
||||
mockAppSpyObj.validatePage.calls.reset();
|
||||
mockAppSpyObj.validateVisual.calls.reset();
|
||||
mockAppSpyObj.getFilters.calls.reset();
|
||||
mockAppSpyObj.setFilters.calls.reset();
|
||||
mockAppSpyObj.validateFilter.calls.reset();
|
||||
|
|
|
@ -259,6 +259,67 @@ export function setupEmbedMockApp(iframeContentWindow: Window, parentWindow: Win
|
|||
});
|
||||
});
|
||||
|
||||
router.get('/report/pages/:pageName/visuals/:visualName/filters', (req, res) => {
|
||||
const page = {
|
||||
name: req.params.pageName,
|
||||
displayName: null
|
||||
};
|
||||
const visual: models.IVisual = {
|
||||
name: req.params.visualName,
|
||||
title: 'title',
|
||||
type: 'type',
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
router.put('/report/pages/:pageName/visuals/:visualName/filters', (req, res) => {
|
||||
const pageName = req.params.pageName;
|
||||
const visualName = req.params.visualName;
|
||||
const uniqueId = req.headers['uid'];
|
||||
const filters = req.body;
|
||||
const page: models.IPage = {
|
||||
name: pageName,
|
||||
displayName: null
|
||||
};
|
||||
const visual: models.IVisual = {
|
||||
name: visualName,
|
||||
title: 'title',
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
router.patch('/report/settings', (req, res) => {
|
||||
const uniqueId = req.headers['uid'];
|
||||
const settings = req.body;
|
||||
|
|
Загрузка…
Ссылка в новой задаче