提交 3230343c 编写于 作者: P Piotr Bryk 提交者: Denis Poisson

Services and discovery category page (#1219)

上级 5402d926
......@@ -752,4 +752,7 @@
<translation id="6870889542203892242" key="MSG_ADMIN_PERSISTENT_VOLUMES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Persistent Volumes</translation>
<translation id="3195481899172694103" key="MSG_ACTION_BAR_CREATE_ACTION" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button.">Create</translation>
<translation id="6165413233411120289" key="MSG_ACTION_BAR_CREATE_ACTION_TOOLTIP" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button tooltip.">Create an application or any Kubernetes resource</translation>
<translation id="5207082267245498149" key="MSG_BREADCRUMBS_SERVICES_AND_DISCOVERY_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label 'Services and discovery' that appears as a breadcrumbs on the action bar.">Services and discovery</translation>
<translation id="352791570684627676" key="MSG_SERVICES_AND_DISCOVERY_INGRESS_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Ingress</translation>
<translation id="6306881076646050049" key="MSG_SERVICES_AND_DISCOVERY_SERVICES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Services</translation>
</translationbundle>
\ No newline at end of file
......@@ -945,4 +945,7 @@
<translation id="6870889542203892242" key="MSG_ADMIN_PERSISTENT_VOLUMES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Persistent Volumes</translation>
<translation id="3195481899172694103" key="MSG_ACTION_BAR_CREATE_ACTION" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button.">Create</translation>
<translation id="6165413233411120289" key="MSG_ACTION_BAR_CREATE_ACTION_TOOLTIP" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button tooltip.">Create an application or any Kubernetes resource</translation>
</translationbundle>
<translation id="5207082267245498149" key="MSG_BREADCRUMBS_SERVICES_AND_DISCOVERY_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label 'Services and discovery' that appears as a breadcrumbs on the action bar.">Services and discovery</translation>
<translation id="352791570684627676" key="MSG_SERVICES_AND_DISCOVERY_INGRESS_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Ingress</translation>
<translation id="6306881076646050049" key="MSG_SERVICES_AND_DISCOVERY_SERVICES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Services</translation>
</translationbundle>
\ No newline at end of file
......@@ -34,6 +34,7 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/event"
"github.com/kubernetes/dashboard/src/app/backend/resource/ingress"
"github.com/kubernetes/dashboard/src/app/backend/resource/job"
"github.com/kubernetes/dashboard/src/app/backend/resource/logs"
"github.com/kubernetes/dashboard/src/app/backend/resource/metric"
"github.com/kubernetes/dashboard/src/app/backend/resource/namespace"
"github.com/kubernetes/dashboard/src/app/backend/resource/node"
......@@ -46,12 +47,12 @@ import (
"github.com/kubernetes/dashboard/src/app/backend/resource/resourcequota"
"github.com/kubernetes/dashboard/src/app/backend/resource/secret"
resourceService "github.com/kubernetes/dashboard/src/app/backend/resource/service"
"github.com/kubernetes/dashboard/src/app/backend/resource/servicesanddiscovery"
"github.com/kubernetes/dashboard/src/app/backend/resource/workload"
"github.com/kubernetes/dashboard/src/app/backend/validation"
clientK8s "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/runtime"
"github.com/kubernetes/dashboard/src/app/backend/resource/logs"
)
const (
......@@ -188,6 +189,15 @@ func CreateHTTPAPIHandler(client *clientK8s.Client, heapsterClient client.Heapst
To(apiHandler.handleGetAdmin).
Writes(admin.Admin{}))
apiV1Ws.Route(
apiV1Ws.GET("/servicesanddiscovery").
To(apiHandler.handleGetServicesAndDiscovery).
Writes(servicesanddiscovery.ServicesAndDiscovery{}))
apiV1Ws.Route(
apiV1Ws.GET("/servicesanddiscovery/{namespace}").
To(apiHandler.handleGetServicesAndDiscovery).
Writes(servicesanddiscovery.ServicesAndDiscovery{}))
apiV1Ws.Route(
apiV1Ws.GET("/replicaset").
To(apiHandler.handleGetReplicaSets).
......@@ -782,6 +792,19 @@ func (apiHandler *APIHandler) handleGetWorkloads(
response.WriteHeaderAndEntity(http.StatusCreated, result)
}
func (apiHandler *APIHandler) handleGetServicesAndDiscovery(
request *restful.Request, response *restful.Response) {
namespace := parseNamespacePathParameter(request)
result, err := servicesanddiscovery.GetServicesAndDiscovery(apiHandler.client, namespace)
if err != nil {
handleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusCreated, result)
}
// Handles get Replica Sets list API call.
func (apiHandler *APIHandler) handleGetReplicaSets(
request *restful.Request, response *restful.Response) {
......@@ -1270,10 +1293,10 @@ func (apiHandler *APIHandler) handleLogs(request *restful.Request, response *res
logSelector = &logs.LogViewSelector{
ReferenceLogLineId: logs.LogLineId{
LogTimestamp: logs.LogTimestamp(refTimestamp),
LineNum: refLineNum,
LineNum: refLineNum,
},
RelativeFrom: relativeFrom,
RelativeTo: relativeTo,
RelativeTo: relativeTo,
}
}
......
......@@ -56,6 +56,9 @@ type ResourceChannels struct {
// List and error channels to Services.
ServiceList ServiceListChannel
// List and error channels to Ingresses.
IngressList IngressListChannel
// List and error channels to Pods.
PodList PodListChannel
......@@ -120,6 +123,39 @@ func GetServiceListChannel(client client.ServicesNamespacer,
return channel
}
// IngressListChannel is a list and error channels to Ingresss.
type IngressListChannel struct {
List chan *extensions.IngressList
Error chan error
}
// GetIngressListChannel returns a pair of channels to a Ingress list and errors that both
// must be read numReads times.
func GetIngressListChannel(client client.IngressNamespacer,
nsQuery *NamespaceQuery, numReads int) IngressListChannel {
channel := IngressListChannel{
List: make(chan *extensions.IngressList, numReads),
Error: make(chan error, numReads),
}
go func() {
list, err := client.Ingress(nsQuery.ToRequestParam()).List(listEverything)
var filteredItems []extensions.Ingress
for _, item := range list.Items {
if nsQuery.Matches(item.ObjectMeta.Namespace) {
filteredItems = append(filteredItems, item)
}
}
list.Items = filteredItems
for i := 0; i < numReads; i++ {
channel.List <- list
channel.Error <- err
}
}()
return channel
}
// NodeListChannel is a list and error channels to Nodes.
type NodeListChannel struct {
List chan *api.NodeList
......
......@@ -54,6 +54,17 @@ func GetIngressList(client client.Interface, namespace *common.NamespaceQuery,
return NewIngressList(ingressList.Items, dsQuery), err
}
// GetIngressListFromChannels - return all ingresses in the given namespace.
func GetIngressListFromChannels(channels *common.ResourceChannels,
dsQuery *dataselect.DataSelectQuery) (*IngressList, error) {
ingress := <-channels.IngressList.List
if err := <-channels.IngressList.Error; err != nil {
return nil, err
}
return NewIngressList(ingress.Items, dsQuery), nil
}
// NewIngress - creates a new instance of Ingress struct based on K8s Ingress.
func NewIngress(ingress *extensions.Ingress) *Ingress {
modelIngress := &Ingress{
......
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package servicesanddiscovery
import (
"log"
"github.com/kubernetes/dashboard/src/app/backend/resource/common"
"github.com/kubernetes/dashboard/src/app/backend/resource/dataselect"
"github.com/kubernetes/dashboard/src/app/backend/resource/ingress"
"github.com/kubernetes/dashboard/src/app/backend/resource/service"
k8sClient "k8s.io/kubernetes/pkg/client/unversioned"
)
// ServicesAndDiscovery structure contains all resource lists grouped into the servicesAndDiscovery category.
type ServicesAndDiscovery struct {
ServiceList service.ServiceList `json:"serviceList"`
IngressList ingress.IngressList `json:"ingressList"`
}
// GetServicesAndDiscovery returns a list of all servicesAndDiscovery resources in the cluster.
func GetServicesAndDiscovery(client *k8sClient.Client, nsQuery *common.NamespaceQuery) (
*ServicesAndDiscovery, error) {
log.Printf("Getting servicesAndDiscovery category")
channels := &common.ResourceChannels{
ServiceList: common.GetServiceListChannel(client, nsQuery, 1),
IngressList: common.GetIngressListChannel(client, nsQuery, 1),
}
return GetServicesAndDiscoveryFromChannels(channels)
}
// GetServicesAndDiscoveryFromChannels returns a list of all servicesAndDiscovery in the cluster, from the
// channel sources.
func GetServicesAndDiscoveryFromChannels(channels *common.ResourceChannels) (
*ServicesAndDiscovery, error) {
svcChan := make(chan *service.ServiceList)
ingressChan := make(chan *ingress.IngressList)
numErrs := 2
errChan := make(chan error, numErrs)
go func() {
items, err := service.GetServiceListFromChannels(channels,
dataselect.DefaultDataSelect)
errChan <- err
svcChan <- items
}()
go func() {
items, err := ingress.GetIngressListFromChannels(channels, dataselect.DefaultDataSelect)
errChan <- err
ingressChan <- items
}()
for i := 0; i < numErrs; i++ {
err := <-errChan
if err != nil {
return nil, err
}
}
servicesAndDiscovery := &ServicesAndDiscovery{
ServiceList: *(<-svcChan),
IngressList: *(<-ingressChan),
}
return servicesAndDiscovery, nil
}
......@@ -148,6 +148,14 @@ backendApi.Workloads;
*/
backendApi.Admin;
/**
* @typedef {{
* serviceList: !backendApi.ServiceList,
* ingressList: !backendApi.IngressList,
* }}
*/
backendApi.ServicesAndDiscovery;
/**
* @typedef {{
* timestamp: string,
......
......@@ -28,9 +28,9 @@ import {stateName as replicaSetState} from 'replicasetlist/replicasetlist_state'
import {stateName as replicationControllerState} from 'replicationcontrollerlist/replicationcontrollerlist_state';
import {stateName as secretState} from 'secretlist/list_state';
import {stateName as serviceState} from 'servicelist/servicelist_state';
import {stateName as servicesanddiscoveryState} from 'servicesanddiscovery/state';
import {stateName as workloadState} from 'workloads/workloads_state';
/**
* @final
*/
......@@ -65,6 +65,7 @@ export class NavController {
'secret': secretState,
'configMap': configMapState,
'ingress': ingressState,
'serviceDiscovery': servicesanddiscoveryState,
};
/** @export */
......
......@@ -46,6 +46,7 @@ import secretDetailModule from './secretdetail/module';
import secretListModule from './secretlist/module';
import serviceDetailModule from './servicedetail/servicedetail_module';
import serviceListModule from './servicelist/servicelist_module';
import servicesanddiscoveryModule from './servicesanddiscovery/module';
import workloadsModule from './workloads/workloads_module';
......@@ -89,6 +90,7 @@ export default angular
secretDetailModule.name,
ingressListModule.name,
ingressDetailModule.name,
servicesanddiscoveryModule.name,
])
.config(indexConfig)
.config(routeConfig);
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @final
*/
export class ServicesAndDiscoveryController {
/**
* @param {!backendApi.ServicesAndDiscovery} servicesAndDiscovery
* @param {!angular.Resource} kdServiceListResource
* @param {!angular.Resource} kdIngressListResource
* @ngInject
*/
constructor(servicesAndDiscovery, kdServiceListResource, kdIngressListResource) {
/** @export {!backendApi.ServicesAndDiscovery} */
this.servicesAndDiscovery = servicesAndDiscovery;
/** @export {!angular.Resource} */
this.kdServiceListResource = kdServiceListResource;
/** @export {!angular.Resource} */
this.kdIngressListResource = kdIngressListResource;
/** @export */
this.i18n = i18n;
}
/**
* @return {boolean}
* @export
*/
shouldShowZeroState() {
/** @type {number} */
let resourcesLength = this.servicesAndDiscovery.serviceList.listMeta.totalItems +
this.servicesAndDiscovery.ingressList.listMeta.totalItems;
return resourcesLength === 0;
}
}
const i18n = {
/** @export {string} @desc Label that appears above the list of resources. */
MSG_SERVICES_AND_DISCOVERY_INGRESS_LABEL: goog.getMsg('Ingress'),
/** @export {string} @desc Label that appears above the list of resources. */
MSG_SERVICES_AND_DISCOVERY_SERVICES_LABEL: goog.getMsg('Services'),
};
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import chromeModule from 'chrome/chrome_module';
import ingressListModule from 'ingresslist/module';
import serviceListModule from 'servicelist/servicelist_module';
import stateConfig from './stateconfig';
/**
* Module for the admin service sand discovery.
*/
export default angular
.module(
'kubernetesDashboard.servicesanddiscovery',
[
'ngMaterial',
'ngResource',
'ui.router',
chromeModule.name,
serviceListModule.name,
ingressListModule.name,
])
.config(stateConfig)
.factory('kdServicesAndDiscoveryResource', resource);
/**
* @param {!angular.$resource} $resource
* @return {!angular.Resource}
* @ngInject
*/
function resource($resource) {
return $resource('api/v1/servicesanddiscovery/:namespace');
}
<!--
Copyright 2015 Google Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div ng-if="!$ctrl.shouldShowZeroState()">
<kd-content-card ng-if="$ctrl.servicesAndDiscovery.serviceList.services.length">
<kd-title>
<a ui-sref="service">
{{::$ctrl.i18n.MSG_SERVICES_AND_DISCOVERY_SERVICES_LABEL}}
</a>
</kd-title>
<kd-content>
<kd-service-card-list service-list="$ctrl.servicesAndDiscovery.serviceList" with-statuses="true"
service-list-resource="$ctrl.serviceListResource">
</kd-service-card-list>
</kd-content>
</kd-content-card>
<kd-content-card ng-if="$ctrl.servicesAndDiscovery.ingressList.items.length">
<kd-title>
<a ui-sref="ingress">
{{::$ctrl.i18n.MSG_SERVICES_AND_DISCOVERY_INGRESS_LABEL}}
</a>
</kd-title>
<kd-content>
<kd-ingress-card-list ingress-list="$ctrl.servicesAndDiscovery.ingressList" with-statuses="true"
ingress-list-resource="$ctrl.ingressListResource">
</kd-ingress-card-list>
</kd-content>
</kd-content-card>
</div>
<kd-zero-state ng-if="$ctrl.shouldShowZeroState()"></kd-zero-state>
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/** Name of the state. Can be used in, e.g., $state.go method. */
export const stateName = 'servicesanddiscovery';
/** Absolute URL of the state. */
export const stateUrl = '/servicesanddiscovery';
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {stateName as chromeStateName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service';
import {ServicesAndDiscoveryController} from './controller';
import {stateName} from './state';
import {stateUrl} from './state';
/**
* @param {!ui.router.$stateProvider} $stateProvider
* @ngInject
*/
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
url: stateUrl,
parent: chromeStateName,
resolve: {
'servicesAndDiscovery': resolveResource,
},
data: {
[breadcrumbsConfig]: {
'label': i18n.MSG_BREADCRUMBS_SERVICES_AND_DISCOVERY_LABEL,
},
},
views: {
'': {
controller: ServicesAndDiscoveryController,
controllerAs: '$ctrl',
templateUrl: 'servicesanddiscovery/servicesanddiscovery.html',
},
},
});
}
/**
* @param {!angular.$resource} kdServicesAndDiscoveryResource
* @param {!./../chrome/chrome_state.StateParams} $stateParams
* @param {!./../common/pagination/pagination_service.PaginationService} kdPaginationService
* @return {!angular.$q.Promise}
* @ngInject
*/
export function resolveResource(kdServicesAndDiscoveryResource, $stateParams, kdPaginationService) {
let paginationQuery = kdPaginationService.getDefaultResourceQuery($stateParams.namespace);
return kdServicesAndDiscoveryResource.get(paginationQuery).$promise;
}
const i18n = {
/** @type {string} @desc Label 'Services and discovery' that appears as a breadcrumbs on the
action bar. */
MSG_BREADCRUMBS_SERVICES_AND_DISCOVERY_LABEL: goog.getMsg('Services and discovery'),
};
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import {ServicesAndDiscoveryController} from 'servicesanddiscovery/controller';
import module from 'servicesanddiscovery/module';
describe('ServicesAndDiscovery list controller', () => {
/** @type {!servicesanddiscovery/servicesanddiscovery_controller.ServicesAndDiscoveryController}
*/
let ctrl;
beforeEach(() => {
angular.mock.module(module.name);
angular.mock.inject(($controller) => {
ctrl = $controller(
ServicesAndDiscoveryController, {servicesAndDiscovery: {servicesAndDiscovery: []}});
});
});
it('should initialize servicesAndDiscovery', angular.mock.inject(($controller) => {
let servicesAndDiscovery = {servicesAndDiscovery: 'foo-bar'};
/** @type {!ServicesAndDiscoveryController} */
let ctrl =
$controller(ServicesAndDiscoveryController, {servicesAndDiscovery: servicesAndDiscovery});
expect(ctrl.servicesAndDiscovery).toBe(servicesAndDiscovery);
}));
it('should show zero state', () => {
// given
ctrl.servicesAndDiscovery = {
serviceList: {listMeta: {totalItems: 0}},
ingressList: {listMeta: {totalItems: 0}},
};
expect(ctrl.shouldShowZeroState()).toBe(true);
});
it('should hide zero state', () => {
// given
ctrl.servicesAndDiscovery = {
serviceList: {listMeta: {totalItems: 0}},
ingressList: {listMeta: {totalItems: 1}},
};
// then
expect(ctrl.shouldShowZeroState()).toBe(false);
});
});
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import module from 'servicesanddiscovery/module';
describe('ServicesAndDiscovery module ', () => {
beforeEach(() => { angular.mock.module(module.name); });
it('should provide kdServicesAndDiscoveryResource',
angular.mock.inject((kdServicesAndDiscoveryResource, $httpBackend) => {
kdServicesAndDiscoveryResource.get();
$httpBackend.expectGET('api/v1/servicesanddiscovery').respond();
$httpBackend.flush();
}));
});
// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import module from 'servicesanddiscovery/module';
import {resolveResource} from 'servicesanddiscovery/stateconfig';
describe('StateConfig for servicesanddiscovery list', () => {
/** @type {!common/pagination/pagination_service.PaginationService} */
let kdPaginationService;
beforeEach(() => {
angular.mock.module(module.name);
angular.mock.inject(
(_kdPaginationService_) => { kdPaginationService = _kdPaginationService_; });
});
it('should resolve servicesanddiscovery', angular.mock.inject(($q) => {
let promise = $q.defer().promise;
let resource = jasmine.createSpyObj('$resource', ['get']);
resource.get.and.callFake(function() { return {$promise: promise}; });
let actual = resolveResource(resource, {namespace: 'foo-ns'}, kdPaginationService);
expect(resource.get)
.toHaveBeenCalledWith(kdPaginationService.getDefaultResourceQuery('foo-ns'));
expect(actual).toBe(promise);
}));
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册