YARN-3334. [YARN-3368] Introduce REFRESH button in various UI pages (Sreenath Somarajapuram via Sunil G)

This commit is contained in:
sunilg 2016-08-10 06:53:13 +05:30 committed by Varun Saxena
parent 30d1839aa0
commit 3e0dab4bfd
43 changed files with 417 additions and 77 deletions

View File

@ -26,7 +26,6 @@ export default BaseUsageDonutChart.extend({
colors: d3.scale.category20().range(),
draw: function() {
this.initChart();
var usageByApps = [];
var avail = 100;
@ -60,8 +59,4 @@ export default BaseUsageDonutChart.extend({
this.renderDonutChart(usageByApps, this.get("title"), this.get("showLabels"),
this.get("middleLabel"), "100%", "%");
},
didInsertElement: function() {
this.draw();
},
})

View File

@ -112,16 +112,16 @@ export default BaseChartComponent.extend({
},
draw: function() {
this.initChart();
this.renderBarChart(this.get("data"), this.get("title"), this.get("textWidth"));
},
_dataChange: Ember.observer("data", function() {
this.chart.g.selectAll("*").remove();
this.renderBarChart(this.get("data"), this.get("title"), this.get("textWidth"));
this.draw();
}),
didInsertElement: function() {
this.initChart();
this.draw();
},
})

View File

@ -0,0 +1,31 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Ember from 'ember';
export default Ember.Component.extend({
breadcrumbs: null,
actions:{
refresh: function () {
this.get("targetObject").send("refresh");
}
}
});

View File

@ -169,13 +169,12 @@ export default BaseChartComponent.extend({
_dataChange: Ember.observer("data", function() {
this.chart.g.selectAll("*").remove();
this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"),
this.get("middleLabel"), this.get("middleValue"));
if(this.get("data")) {
this.draw();
}
}),
draw: function() {
this.initChart();
var colorTargets = this.get("colorTargets");
if (colorTargets) {
var colorTargetReverse = Boolean(this.get("colorTargetReverse"));
@ -188,6 +187,7 @@ export default BaseChartComponent.extend({
},
didInsertElement: function() {
this.initChart();
this.draw();
},
})

View File

@ -26,7 +26,6 @@ export default BaseUsageDonutChart.extend({
colors: d3.scale.category20().range(),
draw: function() {
this.initChart();
var usageByQueues = [];
var avail = 100;
@ -64,6 +63,7 @@ export default BaseUsageDonutChart.extend({
},
didInsertElement: function() {
this.initChart();
this.draw();
},
})

View File

@ -0,0 +1,40 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Ember from 'ember';
export default Ember.Controller.extend({
breadcrumbs: Ember.computed('model.nodeInfo', 'model.containerInfo', function () {
var nodeInfo = this.get('model.nodeInfo'),
containerInfo = this.get('model.containerInfo');
return [{
text: "Home",
routeName: 'application'
}, {
text: `Node [ ${nodeInfo.id} ]`,
href: `/#/yarn-node/${nodeInfo.id}/${nodeInfo.addr}`,
}, {
text: `Container [ ${containerInfo.id} ]`,
href: `/#/yarn-node-container/${nodeInfo.id}/${nodeInfo.addr}/${containerInfo.id}`,
}, {
text: "Log",
}];
})
});

View File

@ -0,0 +1,36 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Ember from 'ember';
export default Ember.Controller.extend({
breadcrumbs: Ember.computed('model.nodeInfo', function () {
var nodeInfo = this.get('model.nodeInfo');
return [{
text: "Home",
routeName: 'application'
}, {
text: `Node [ ${nodeInfo.id} ]`,
href: `/#/yarn-node/${nodeInfo.id}/${nodeInfo.addr}`,
}, {
text: "Application",
}];
})
});

View File

@ -0,0 +1,32 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 Ember from 'ember';
export default Ember.Route.extend({
unloadAll() {
// Must be implemented by inheriting classes
},
actions: {
refresh: function () {
this.unloadAll();
this.refresh();
}
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model() {
return Ember.RSVP.hash({
clusterMetrics: this.store.findAll('ClusterMetric'),
@ -26,11 +28,17 @@ export default Ember.Route.extend({
{
state: "RUNNING"
}),
queues: this.store.findAll('yarn-queue'),
queues: this.store.query('yarn-queue', {}),
});
},
afterModel() {
this.controllerFor("ClusterOverview").set("loading", false);
},
unloadAll() {
this.store.unloadAll('ClusterMetric');
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-queue');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
attempt: this.store.findRecord('yarn-app-attempt', param.app_attempt_id),
@ -39,5 +41,10 @@ export default Ember.Route.extend({
return [];
})
});
},
unloadAll() {
this.store.unloadAll('yarn-app-attempt');
this.store.unloadAll('yarn-container');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return this.store.query('yarn-app-attempt', { appId: param.app_id}).then(function (attempts) {
return {
@ -26,5 +28,9 @@ export default Ember.Route.extend({
attempts: attempts
};
});
},
unloadAll() {
this.store.unloadAll('yarn-app-attempt');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
app: this.store.find('yarn-app', param.app_id),
@ -39,5 +41,12 @@ export default Ember.Route.extend({
nodes: this.store.findAll('yarn-rm-node'),
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('yarn-app-attempt');
this.store.unloadAll('yarn-container');
this.store.unloadAll('yarn-rm-node');
}
});

View File

@ -18,11 +18,18 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model() {
return Ember.RSVP.hash({
apps: this.store.findAll('yarn-app'),
clusterMetrics: this.store.findAll('ClusterMetric'),
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('ClusterMetric');
}
});

View File

@ -19,12 +19,15 @@
import Ember from 'ember';
import Constants from 'yarn-ui/constants';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
var id = param.node_addr + Constants.PARAM_SEPARATOR + param.container_id +
Constants.PARAM_SEPARATOR + param.filename;
return Ember.RSVP.hash({
containerLog: this.store.findRecord('yarn-container-log', id),
containerInfo: { id: param.container_id },
nodeInfo: { id: param.node_id, addr: param.node_addr }
}).then(function(hash) {
// Just return as its success.
@ -36,6 +39,7 @@ export default Ember.Route.extend({
} else {
// Assume empty response received from server.
return { nodeInfo: { id: param.node_id, addr: param.node_addr },
containerInfo: { id: param.container_id },
containerLog: { logs: "", containerID: param.container_id,
logFileName: param.filename}};
}
@ -51,5 +55,9 @@ export default Ember.Route.extend({
this.replaceWith('/error');
}
}
},
unloadAll() {
this.store.unloadAll('yarn-container-log');
}
});

View File

@ -18,12 +18,18 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
nodeApp: this.store.queryRecord('yarn-node-app',
{ nodeAddr : param.node_addr, appId: param.app_id }),
nodeInfo: { id: param.node_id, addr: param.node_addr }
});
},
unloadAll() {
this.store.unloadAll('yarn-node-app');
}
});

View File

@ -18,12 +18,18 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
// Get all apps running on a specific node. Node is contacted by using node_addr.
return Ember.RSVP.hash({
apps: this.store.query('yarn-node-app', { nodeAddr: param.node_addr }),
nodeInfo: { id: param.node_id, addr: param.node_addr }
});
},
unloadAll() {
this.store.unloadAll('yarn-node-app');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
// Get a specific container running on a specific node.
return Ember.RSVP.hash({
@ -26,5 +28,9 @@ export default Ember.Route.extend({
{ nodeHttpAddr: param.node_addr, containerId: param.container_id }),
nodeInfo: { id: param.node_id, addr: param.node_addr }
});
},
unloadAll() {
this.store.unloadAll('yarn-node-container');
}
});

View File

@ -17,12 +17,18 @@
*/
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
// Get all containers running on specific node.
return Ember.RSVP.hash({
containers: this.store.query('yarn-node-container', { nodeHttpAddr: param.node_addr }),
nodeInfo: { id: param.node_id, addr: param.node_addr }
});
},
unloadAll() {
this.store.unloadAll('yarn-node-container');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
// Fetches data from both NM and RM. RM is queried to get node usage info.
return Ember.RSVP.hash({
@ -26,5 +28,10 @@ export default Ember.Route.extend({
node: this.store.findRecord('yarn-node', param.node_addr),
rmNode: this.store.findRecord('yarn-rm-node', param.node_id)
});
},
unloadAll() {
this.store.unloadAll('yarn-node');
this.store.unloadAll('yarn-rm-node');
}
});

View File

@ -18,11 +18,18 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model() {
return Ember.RSVP.hash({
nodes: this.store.findAll('yarn-rm-node'),
clusterMetrics: this.store.findAll('ClusterMetric'),
});
},
unloadAll() {
this.store.unloadAll('yarn-rm-node');
this.store.unloadAll('ClusterMetric');
}
});

View File

@ -18,7 +18,9 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
selected : param.queue_name,
@ -29,8 +31,12 @@ export default Ember.Route.extend({
},
afterModel(model) {
var store = this.store;
model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected);
model.apps = store.findAll('yarn-app');
model.apps = this.store.findAll('yarn-app');
},
unloadAll() {
this.store.unloadAll('yarn-queue');
this.store.unloadAll('yarn-app');
}
});

View File

@ -18,11 +18,13 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
selected : param.queue_name,
queues: this.store.findAll('yarn-queue'),
queues: this.store.query('yarn-queue', {}),
selectedQueue : undefined,
apps: undefined, // apps of selected queue
});
@ -31,8 +33,10 @@ export default Ember.Route.extend({
afterModel(model) {
model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected);
model.apps = this.store.findAll('yarn-app');
model.apps.forEach(function(o) {
console.log(o);
})
},
unloadAll() {
this.store.unloadAll('yarn-queue');
this.store.unloadAll('yarn-app');
}
});

View File

@ -18,11 +18,13 @@
import Ember from 'ember';
export default Ember.Route.extend({
import AbstractRoute from './abstract';
export default AbstractRoute.extend({
model(param) {
return Ember.RSVP.hash({
selected : param.queue_name,
queues: this.store.findAll('yarn-queue'),
queues: this.store.query('yarn-queue', {}),
selectedQueue : undefined,
apps: undefined, // apps of selected queue
});
@ -31,8 +33,10 @@ export default Ember.Route.extend({
afterModel(model) {
model.selectedQueue = this.store.peekRecord('yarn-queue', model.selected);
model.apps = this.store.findAll('yarn-app');
model.apps.forEach(function(o) {
console.log(o);
})
},
unloadAll() {
this.store.unloadAll('yarn-queue');
this.store.unloadAll('yarn-app');
}
});

View File

@ -267,3 +267,9 @@ li a.navigation-link.ember-view {
color: #2196f3;
font-weight: bold;
}
.breadcrumb-bar .refresh {
position: absolute;
right: 20px;
top: 3px;
}

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
{{#if model}}

View File

@ -0,0 +1,22 @@
{{!
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 class="col-md-12 container-fluid breadcrumb-bar">
{{em-breadcrumbs items=breadcrumbs}}
<button type="button" class="btn btn-sm btn-primary refresh" {{action "refresh"}}>Refresh</button>
</div>

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<br/><br/><br/>
<div class="container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
{{#if model.app}}
<div class="col-md-12 container-fluid">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,6 +16,8 @@
limitations under the License.
--}}
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
{{node-menu path="yarn-container-log" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}
<div class="col-md-10">

View File

@ -16,6 +16,8 @@
limitations under the License.
--}}
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">
{{node-menu-panel path="yarn-node-app" nodeAddr=model.nodeInfo.addr nodeId=model.nodeInfo.id}}

View File

@ -16,9 +16,7 @@
limitations under the License.
--}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
limitations under the License.
--}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
limitations under the License.
--}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
limitations under the License.
--}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
limitations under the License.
--}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="row">
<div class="col-md-2 container-fluid">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid">
<div class="row">

View File

@ -16,9 +16,7 @@
* limitations under the License.
}}
<div class="col-md-12 container-fluid">
{{em-breadcrumbs items=breadcrumbs}}
</div>
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="container-fluid">
{{queue-navigator model=model.queues selected=model.selected}}

View File

@ -0,0 +1,43 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('breadcrumb-bar', 'Integration | Component | breadcrumb bar', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
this.render(hbs`{{breadcrumb-bar}}`);
assert.equal(this.$().text().trim(), '');
// Template block usage:" + EOL +
this.render(hbs`
{{#breadcrumb-bar}}
template block text
{{/breadcrumb-bar}}
`);
assert.equal(this.$().text().trim(), 'template block text');
});

View File

@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-container-log', 'Unit | Controller | yarn container log', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -0,0 +1,30 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-node-app', 'Unit | Controller | yarn node app', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});