У меня есть следующий код AngularJS, который я пытаюсь протестировать с помощью jasmine ad karma:
(function() {
"use strict";
angular
.module("beckon.steel.beckonstandard.directives.templateDetails", [
// "beckon.steel.grid.services.beckonGridFactory",
// "beckon.steel.connectorTemplate.services.connectorTemplateService",
// "beckon.steel.dashboardTemplate.services.dashboardTemplateService",
// "beckon.steel.scorecards.services.scorecardTemplateService",
// "beckon.steel.channel.services.channelService",
// "beckon.steel.beckonstandard.services.beckonStandardEntityEnum",
// "beckon.steel.dimensions.dimensionService",
// "beckon.steel.formulabuilder.services.formulaTemplateService",
])
.directive("templateDetails", function(
beckonStandardEntityEnum,
connectorTemplateService,
dashboardTemplateService,
scorecardTemplateService,
channelService,
dimensionTemplateService,
formulaTemplateService,
$stateParams,
svg,
bnModalAlertService
) {
return {
templateUrl: "templateDetails",
restrict: "E",
scope: {
entity: "@",
baseState: "@",
},
controller: function($scope) {
$scope.backArrow = svg.ARROW_LEFT;
$scope.connector = null;
$scope.dashboard = null;
$scope.scorecard = null;
$scope.icon = svg.ARROW_LEFT;
const showAlert = function(successType, message) {
bnModalAlertService.clearAlerts().setAlert({
type: successType,
msgSafeHtml: message,
});
};
const onSuccess = () => showAlert("success", "Update successful");
const onFail = (err) => {
if (err.data && err.data.message) {
showAlert("error", `Update unsuccessful: ${err.data.message}`);
return;
}
showAlert("error", `Update unsuccessful: ${err.statusText}`);
};
if ($scope.entity === beckonStandardEntityEnum.CONNECTOR.type) {
$scope.backState = beckonStandardEntityEnum.CONNECTOR.uiRefState;
connectorTemplateService
.fetch($stateParams.id)
.$promise.then(function(connector) {
$scope.connector = connector;
});
$scope.updateConnector = function(connector) {
connectorTemplateService
.update($stateParams.id, connector)
.$promise.then(onSuccess)
.catch(onFail);
};
}
},
};
});
})();
Пока что я смоделировал большинство зависимостей, но у меня возникли проблемы с издевательством над обещанием connectorTemplateService.
fdescribe("templateDetails", () => {
"use strict";
let $scope;
let $compile;
let $rootScope;
let beckonStandardEntityEnum;
let connectorTemplateService;
let dashboardTemplateService;
let scorecardTemplateService;
let channelService;
let dimensionTemplateService;
let formulaTemplateService;
let $stateParams;
let svg;
let bnModalAlertService;
let $q;
let resolvedValue;
let deferred;
const getIsolatedScope = (element) => element.isolateScope() || element.scope();
beforeEach(module("beckon.steel.beckonstandard.directives.templateDetails"));
beforeEach(
module(($provide) => {
svg = jasmine.createSpy();
beckonStandardEntityEnum = {
CONNECTOR: {
type: "connectortype",
uiRefState: "connectorUiRefState",
},
DASHBOARD: {
type: "dashboardtype",
uiRefState: "dashboardUiRefState",
},
SCORECARD: {
type: "scorecardtype",
uiRefState: "scorecardUiRefState",
},
CHANNEL: {
type: "channeltype",
uiRefState: "channelUiRefState",
},
DIMENSION: {
type: "dimensiontype",
uiRefState: "dimensionUiRefState",
},
FORMULA: {
type: "formulatype",
uiRefState: "formulaUiRefState",
},
};
connectorTemplateService = {
fetch: () => {},
update: () => {},
}
bnModalAlertService = {
clearAlerts: () => ({
setAlert: jasmine.createSpy()
}),
};
$stateParams = {
id: "dummyid",
};
$provide.value("svg", svg);
$provide.value("beckonStandardEntityEnum", beckonStandardEntityEnum);
$provide.value("$stateParams", $stateParams);
$provide.value("connectorTemplateService", connectorTemplateService);
$provide.value("formulaTemplateService", formulaTemplateService);
$provide.value("scorecardTemplateService", scorecardTemplateService);
$provide.value("dimensionTemplateService", dimensionTemplateService);
$provide.value("channelService", channelService);
$provide.value("dashboardTemplateService", dashboardTemplateService);
$provide.value("bnModalAlertService", bnModalAlertService);
})
);
beforeEach(
inject((_$rootScope_, _$compile_, _$q_) => {
$compile = _$compile_;
$rootScope = _$rootScope_;
$scope = $rootScope.$new(true);
$q = _$q_;
})
);
describe("when entity matches CONNECTOR type", () => {
it("initializes correctly", () => {
// Arrange
const element = angular.element(
"<template-details entity='connectortype'>Here goes the template</template-details>"
);
spyOn(connectorTemplateService, "fetch").and.callFake((id) => {
let deferred = $q.defer();
deferred.resolve("the connector");
return deferred.promise;
});
spyOn(connectorTemplateService, "update").and.callFake((id) => {
let deferred = $q.defer();
deferred.resolve("success");
return deferred.promise;
});
// Act
$compile(element)($scope);
$scope.$digest();
const isolatedScope = getIsolatedScope(element);
isolatedScope.uiRefState = "connectorUiRefState";
const expectedValue = "the connector";
isolatedScope.updateConnector();
isolatedScope.$apply();
// Assertions
});
});
});
При способе, которым я издевался над ним (как видно в угловых документах $ q), я получаю ошибку cannot read property '.then' of undefined
Я пытался смоделировать этокак это
connectorTemplateService = {
update: (id, connector) => ({
$promise: {
then: (fn) => {
fn();
},
},
}),
fetch: (id) => ({
$promise: {
then: (fn) => {
fn("the connector");
},
},
}),
};
Он работал для метода fetch
, но не для метода update
, потому что это не фактическое обещание, а метод update
имеет блок catch
,Может кто-нибудь показать, как издеваться над этим обещанием?