diff --git a/.gitignore b/.gitignore
index b934545b0..f19433b97 100644
--- a/.gitignore
+++ b/.gitignore
@@ -89,6 +89,7 @@ rkt-*
# misc
/ui/.sass-cache
+/ui/.eslintcache
/ui/.storybook/preview-head.html
/ui/connect.lock
/ui/coverage/*
diff --git a/ui/.eslintrc.js b/ui/.eslintrc.js
index 99a0745c2..19fd1e1dc 100644
--- a/ui/.eslintrc.js
+++ b/ui/.eslintrc.js
@@ -2,17 +2,6 @@
module.exports = {
root: true,
- globals: {
- server: true,
- },
- env: {
- browser: true,
- es6: true,
- },
- extends: [
- 'eslint:recommended',
- 'plugin:ember/recommended',
- ],
parser: 'babel-eslint',
parserOptions: {
ecmaVersion: 2018,
@@ -21,37 +10,42 @@ module.exports = {
legacyDecorators: true,
},
},
- plugins: [
- 'ember'
+ globals: {
+ server: true,
+ },
+ env: {
+ browser: true,
+ },
+ plugins: ['ember'],
+ extends: [
+ 'eslint:recommended',
+ 'plugin:ember/recommended',
+ 'plugin:prettier/recommended',
],
rules: {
- indent: ['error', 2, { SwitchCase: 1 }],
- 'linebreak-style': ['error', 'unix'],
- quotes: ['error', 'single', 'avoid-escape'],
- semi: ['error', 'always'],
- 'no-constant-condition': [
- 'error',
- {
- checkLoops: false,
- },
- ],
'ember/classic-decorator-hooks': 'error',
'ember/classic-decorator-no-classic-methods': 'error',
'ember/no-get': 'off',
'ember/no-mixins': 'off',
+ 'ember/no-classic-classes': 'off',
+ 'ember/no-computed-properties-in-native-classes': 'off',
+ 'ember/no-classic-components': 'off',
+ 'ember/no-component-lifecycle-hooks': 'off',
+ 'ember/require-tagless-components': 'off',
},
overrides: [
// node files
{
files: [
'.eslintrc.js',
+ '.prettierrc.js',
'.template-lintrc.js',
'ember-cli-build.js',
'testem.js',
'blueprints/*/index.js',
'config/**/*.js',
- 'server/**/*.js',
'lib/*/index.js',
+ 'server/**/*.js',
],
parserOptions: {
sourceType: 'script',
@@ -61,14 +55,15 @@ module.exports = {
node: true,
},
plugins: ['node'],
+ extends: ['plugin:node/recommended'],
rules: {
- 'node/no-unpublished-require': 'off'
+ // this can be removed once the following is fixed
+ // https://github.com/mysticatea/eslint-plugin-node/issues/77
+ 'node/no-unpublished-require': 'off',
},
},
{
- files: [
- 'stories/**/*.js'
- ],
+ files: ['stories/**/*.js'],
parserOptions: {
sourceType: 'module',
},
diff --git a/ui/.prettierignore b/ui/.prettierignore
new file mode 100644
index 000000000..922165552
--- /dev/null
+++ b/ui/.prettierignore
@@ -0,0 +1,21 @@
+# unconventional js
+/blueprints/*/files/
+/vendor/
+
+# compiled output
+/dist/
+/tmp/
+
+# dependencies
+/bower_components/
+/node_modules/
+
+# misc
+/coverage/
+!.*
+.eslintcache
+
+# ember-try
+/.node_modules.ember-try/
+/bower.json.ember-try
+/package.json.ember-try
diff --git a/ui/.prettierrc b/ui/.prettierrc
index 546369158..5938b36b5 100644
--- a/ui/.prettierrc
+++ b/ui/.prettierrc
@@ -1,7 +1,5 @@
{
- "printWidth": 100,
"singleQuote": true,
- "trailingComma": "es5",
"overrides": [
{
"files": "*.hbs",
diff --git a/ui/.prettierrc.js b/ui/.prettierrc.js
new file mode 100644
index 000000000..534e6d35a
--- /dev/null
+++ b/ui/.prettierrc.js
@@ -0,0 +1,5 @@
+'use strict';
+
+module.exports = {
+ singleQuote: true,
+};
diff --git a/ui/.storybook/babel.config.js b/ui/.storybook/babel.config.js
index 5dd544f2a..b69a0355e 100644
--- a/ui/.storybook/babel.config.js
+++ b/ui/.storybook/babel.config.js
@@ -14,7 +14,11 @@ module.exports = {
shippedProposals: true,
useBuiltIns: 'usage',
corejs: '3',
- targets: ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'],
+ targets: [
+ 'last 1 Chrome versions',
+ 'last 1 Firefox versions',
+ 'last 1 Safari versions',
+ ],
},
],
],
@@ -27,7 +31,10 @@ module.exports = {
],
['@babel/plugin-proposal-class-properties', { loose: true }],
'@babel/plugin-syntax-dynamic-import',
- ['@babel/plugin-proposal-object-rest-spread', { loose: true, useBuiltIns: true }],
+ [
+ '@babel/plugin-proposal-object-rest-spread',
+ { loose: true, useBuiltIns: true },
+ ],
'babel-plugin-macros',
['emotion', { sourceMap: true, autoLabel: true }],
[
diff --git a/ui/.storybook/preview.js b/ui/.storybook/preview.js
index 7352c15a4..82c50d189 100644
--- a/ui/.storybook/preview.js
+++ b/ui/.storybook/preview.js
@@ -10,7 +10,7 @@ addParameters({
},
});
-addDecorator(storyFn => {
+addDecorator((storyFn) => {
let { template, context } = storyFn();
let wrapperElementStyle = {
diff --git a/ui/.storybook/theme.js b/ui/.storybook/theme.js
index ff67962d0..92d425093 100644
--- a/ui/.storybook/theme.js
+++ b/ui/.storybook/theme.js
@@ -18,7 +18,8 @@ export default create({
// Typography
// From variables.scss
- fontBase: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
+ fontBase:
+ "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
// From Bulma
fontCode: 'monospace',
diff --git a/ui/.storybook/webpack.config.js b/ui/.storybook/webpack.config.js
index 98e79973f..02e11248c 100644
--- a/ui/.storybook/webpack.config.js
+++ b/ui/.storybook/webpack.config.js
@@ -1,5 +1,5 @@
/* eslint-env node */
-module.exports = function({ config }) {
+module.exports = function ({ config }) {
config.module.rules.push({
test: /\.stories\.jsx?$/,
loaders: [require.resolve('@storybook/source-loader')],
diff --git a/ui/app/abilities/abstract.js b/ui/app/abilities/abstract.js
index 9dcf5c717..d1bccf543 100644
--- a/ui/app/abilities/abstract.js
+++ b/ui/app/abilities/abstract.js
@@ -26,17 +26,26 @@ export default class Abstract extends Ability {
get rulesForNamespace() {
let namespace = this._namespace;
- return (this.get('token.selfTokenPolicies') || []).toArray().reduce((rules, policy) => {
- let policyNamespaces = get(policy, 'rulesJSON.Namespaces') || [];
+ return (this.get('token.selfTokenPolicies') || [])
+ .toArray()
+ .reduce((rules, policy) => {
+ let policyNamespaces = get(policy, 'rulesJSON.Namespaces') || [];
- let matchingNamespace = this._findMatchingNamespace(policyNamespaces, namespace);
+ let matchingNamespace = this._findMatchingNamespace(
+ policyNamespaces,
+ namespace
+ );
- if (matchingNamespace) {
- rules.push(policyNamespaces.find(namespace => namespace.Name === matchingNamespace));
- }
+ if (matchingNamespace) {
+ rules.push(
+ policyNamespaces.find(
+ (namespace) => namespace.Name === matchingNamespace
+ )
+ );
+ }
- return rules;
- }, []);
+ return rules;
+ }, []);
}
@computed('token.selfTokenPolicies.[]')
@@ -44,15 +53,17 @@ export default class Abstract extends Ability {
return (this.get('token.selfTokenPolicies') || [])
.toArray()
.reduce((allCapabilities, policy) => {
- (get(policy, 'rulesJSON.Namespaces') || []).forEach(({ Capabilities }) => {
- allCapabilities = allCapabilities.concat(Capabilities);
- });
+ (get(policy, 'rulesJSON.Namespaces') || []).forEach(
+ ({ Capabilities }) => {
+ allCapabilities = allCapabilities.concat(Capabilities);
+ }
+ );
return allCapabilities;
}, []);
}
namespaceIncludesCapability(capability) {
- return this.rulesForNamespace.some(rules => {
+ return this.rulesForNamespace.some((rules) => {
let capabilities = get(rules, 'Capabilities') || [];
return capabilities.includes(capability);
});
@@ -76,12 +87,16 @@ export default class Abstract extends Ability {
return namespace;
}
- let globNamespaceNames = namespaceNames.filter(namespaceName => namespaceName.includes('*'));
+ let globNamespaceNames = namespaceNames.filter((namespaceName) =>
+ namespaceName.includes('*')
+ );
let matchingNamespaceName = globNamespaceNames.reduce(
(mostMatching, namespaceName) => {
// Convert * wildcards to .* for regex matching
- let namespaceNameRegExp = new RegExp(namespaceName.replace(/\*/g, '.*'));
+ let namespaceNameRegExp = new RegExp(
+ namespaceName.replace(/\*/g, '.*')
+ );
let characterDifference = namespace.length - namespaceName.length;
if (
@@ -96,7 +111,10 @@ export default class Abstract extends Ability {
return mostMatching;
}
},
- { mostMatchingNamespaceName: null, mostMatchingCharacterDifference: Number.MAX_SAFE_INTEGER }
+ {
+ mostMatchingNamespaceName: null,
+ mostMatchingCharacterDifference: Number.MAX_SAFE_INTEGER,
+ }
).mostMatchingNamespaceName;
if (matchingNamespaceName) {
diff --git a/ui/app/abilities/agent.js b/ui/app/abilities/agent.js
index 53450482e..21e65fce3 100644
--- a/ui/app/abilities/agent.js
+++ b/ui/app/abilities/agent.js
@@ -3,16 +3,20 @@ import { computed, get } from '@ember/object';
import { or } from '@ember/object/computed';
export default class Client extends AbstractAbility {
- @or('bypassAuthorization', 'selfTokenIsManagement', 'policiesIncludeAgentReadOrWrite')
+ @or(
+ 'bypassAuthorization',
+ 'selfTokenIsManagement',
+ 'policiesIncludeAgentReadOrWrite'
+ )
canRead;
@computed('token.selfTokenPolicies.[]')
get policiesIncludeAgentReadOrWrite() {
const policies = (get(this, 'token.selfTokenPolicies') || [])
.toArray()
- .map(policy => get(policy, 'rulesJSON.Agent.Policy'))
+ .map((policy) => get(policy, 'rulesJSON.Agent.Policy'))
.compact();
- return policies.some(policy => policy === 'read' || policy === 'write');
+ return policies.some((policy) => policy === 'read' || policy === 'write');
}
}
diff --git a/ui/app/abilities/allocation.js b/ui/app/abilities/allocation.js
index 7f288b03c..ed46d781f 100644
--- a/ui/app/abilities/allocation.js
+++ b/ui/app/abilities/allocation.js
@@ -8,7 +8,7 @@ export default class Allocation extends AbstractAbility {
@computed('rulesForNamespace.@each.capabilities')
get policiesSupportExec() {
- return this.rulesForNamespace.some(rules => {
+ return this.rulesForNamespace.some((rules) => {
let capabilities = get(rules, 'Capabilities') || [];
return capabilities.includes('alloc-exec');
});
diff --git a/ui/app/abilities/client.js b/ui/app/abilities/client.js
index f48eeb93e..cd1fc8ed1 100644
--- a/ui/app/abilities/client.js
+++ b/ui/app/abilities/client.js
@@ -10,17 +10,26 @@ export default class Client extends AbstractAbility {
@or('bypassAuthorization', 'selfTokenIsManagement', 'policiesIncludeNodeRead')
canRead;
- @or('bypassAuthorization', 'selfTokenIsManagement', 'policiesIncludeNodeWrite')
+ @or(
+ 'bypassAuthorization',
+ 'selfTokenIsManagement',
+ 'policiesIncludeNodeWrite'
+ )
canWrite;
@computed('token.selfTokenPolicies.[]')
get policiesIncludeNodeRead() {
- return policiesIncludePermissions(this.get('token.selfTokenPolicies'), ['read', 'write']);
+ return policiesIncludePermissions(this.get('token.selfTokenPolicies'), [
+ 'read',
+ 'write',
+ ]);
}
@computed('token.selfTokenPolicies.[]')
get policiesIncludeNodeWrite() {
- return policiesIncludePermissions(this.get('token.selfTokenPolicies'), ['write']);
+ return policiesIncludePermissions(this.get('token.selfTokenPolicies'), [
+ 'write',
+ ]);
}
}
@@ -28,9 +37,9 @@ function policiesIncludePermissions(policies = [], permissions = []) {
// For each policy record, extract the Node policy
const nodePolicies = policies
.toArray()
- .map(policy => get(policy, 'rulesJSON.Node.Policy'))
+ .map((policy) => get(policy, 'rulesJSON.Node.Policy'))
.compact();
// Check for requested permissions
- return nodePolicies.some(policy => permissions.includes(policy));
+ return nodePolicies.some((policy) => permissions.includes(policy));
}
diff --git a/ui/app/abilities/job.js b/ui/app/abilities/job.js
index 02e175cb4..fbc8d982c 100644
--- a/ui/app/abilities/job.js
+++ b/ui/app/abilities/job.js
@@ -20,7 +20,11 @@ export default class Job extends AbstractAbility {
@or('bypassAuthorization', 'selfTokenIsManagement')
canListAll;
- @or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportDispatching')
+ @or(
+ 'bypassAuthorization',
+ 'selfTokenIsManagement',
+ 'policiesSupportDispatching'
+ )
canDispatch;
@computed('rulesForNamespace.@each.capabilities')
diff --git a/ui/app/abilities/recommendation.js b/ui/app/abilities/recommendation.js
index 11decdb43..ce6f03f1d 100644
--- a/ui/app/abilities/recommendation.js
+++ b/ui/app/abilities/recommendation.js
@@ -6,7 +6,11 @@ export default class Recommendation extends AbstractAbility {
@and('dynamicApplicationSizingIsPresent', 'hasPermissions')
canAccept;
- @or('bypassAuthorization', 'selfTokenIsManagement', 'policiesSupportAcceptingOnAnyNamespace')
+ @or(
+ 'bypassAuthorization',
+ 'selfTokenIsManagement',
+ 'policiesSupportAcceptingOnAnyNamespace'
+ )
hasPermissions;
@computed('capabilitiesForAllNamespaces.[]')
diff --git a/ui/app/adapters/allocation.js b/ui/app/adapters/allocation.js
index 3fcfb6128..64c1ef7da 100644
--- a/ui/app/adapters/allocation.js
+++ b/ui/app/adapters/allocation.js
@@ -14,13 +14,17 @@ export default class AllocationAdapter extends Watchable {
ls(model, path) {
return this.token
- .authorizedRequest(`/v1/client/fs/ls/${model.id}?path=${encodeURIComponent(path)}`)
+ .authorizedRequest(
+ `/v1/client/fs/ls/${model.id}?path=${encodeURIComponent(path)}`
+ )
.then(handleFSResponse);
}
stat(model, path) {
return this.token
- .authorizedRequest(`/v1/client/fs/stat/${model.id}?path=${encodeURIComponent(path)}`)
+ .authorizedRequest(
+ `/v1/client/fs/stat/${model.id}?path=${encodeURIComponent(path)}`
+ )
.then(handleFSResponse);
}
}
@@ -39,8 +43,11 @@ async function handleFSResponse(response) {
}
function adapterAction(path, verb = 'POST') {
- return function(allocation) {
- const url = addToPath(this.urlForFindRecord(allocation.id, 'allocation'), path);
+ return function (allocation) {
+ const url = addToPath(
+ this.urlForFindRecord(allocation.id, 'allocation'),
+ path
+ );
return this.ajax(url, verb);
};
}
diff --git a/ui/app/adapters/application.js b/ui/app/adapters/application.js
index 9250f72b2..efe4efb0b 100644
--- a/ui/app/adapters/application.js
+++ b/ui/app/adapters/application.js
@@ -35,7 +35,7 @@ export default class ApplicationAdapter extends RESTAdapter {
}
findAll() {
- return super.findAll(...arguments).catch(error => {
+ return super.findAll(...arguments).catch((error) => {
const errorCodes = codesForError(error);
const isNotImplemented = errorCodes.includes('501');
@@ -66,14 +66,14 @@ export default class ApplicationAdapter extends RESTAdapter {
// In order to remove stale records from the store, findHasMany has to unload
// all records related to the request in question.
findHasMany(store, snapshot, link, relationship) {
- return super.findHasMany(...arguments).then(payload => {
+ return super.findHasMany(...arguments).then((payload) => {
const relationshipType = relationship.type;
const inverse = snapshot.record.inverseFor(relationship.key);
if (inverse) {
store
.peekAll(relationshipType)
- .filter(record => record.get(`${inverse.name}.id`) === snapshot.id)
- .forEach(record => {
+ .filter((record) => record.get(`${inverse.name}.id`) === snapshot.id)
+ .forEach((record) => {
removeRecord(store, record);
});
}
@@ -96,6 +96,7 @@ export default class ApplicationAdapter extends RESTAdapter {
let prefix = this.urlPrefix();
if (modelName) {
+ /* eslint-disable-next-line ember/no-string-prototype-extensions */
path = modelName.camelize();
if (path) {
url.push(path);
@@ -124,5 +125,7 @@ export default class ApplicationAdapter extends RESTAdapter {
}
function associateRegion(url, region) {
- return url.indexOf('?') !== -1 ? `${url}®ion=${region}` : `${url}?region=${region}`;
+ return url.indexOf('?') !== -1
+ ? `${url}®ion=${region}`
+ : `${url}?region=${region}`;
}
diff --git a/ui/app/adapters/deployment.js b/ui/app/adapters/deployment.js
index d24628c36..8904038d0 100644
--- a/ui/app/adapters/deployment.js
+++ b/ui/app/adapters/deployment.js
@@ -13,7 +13,10 @@ export default class DeploymentAdapter extends Watchable {
promote(deployment) {
const id = deployment.get('id');
- const url = urlForAction(this.urlForFindRecord(id, 'deployment'), '/promote');
+ const url = urlForAction(
+ this.urlForFindRecord(id, 'deployment'),
+ '/promote'
+ );
return this.ajax(url, 'POST', {
data: {
DeploymentId: id,
diff --git a/ui/app/adapters/job-version.js b/ui/app/adapters/job-version.js
index eb2393a94..fb9eba821 100644
--- a/ui/app/adapters/job-version.js
+++ b/ui/app/adapters/job-version.js
@@ -5,7 +5,10 @@ export default class JobVersionAdapter extends ApplicationAdapter {
revertTo(jobVersion) {
const jobAdapter = this.store.adapterFor('job');
- const url = addToPath(jobAdapter.urlForFindRecord(jobVersion.get('job.id'), 'job'), '/revert');
+ const url = addToPath(
+ jobAdapter.urlForFindRecord(jobVersion.get('job.id'), 'job'),
+ '/revert'
+ );
const [jobName] = JSON.parse(jobVersion.get('job.id'));
return this.ajax(url, 'POST', {
diff --git a/ui/app/adapters/job.js b/ui/app/adapters/job.js
index 7ff6027ff..94995fd8e 100644
--- a/ui/app/adapters/job.js
+++ b/ui/app/adapters/job.js
@@ -14,7 +14,10 @@ export default class JobAdapter extends WatchableNamespaceIDs {
forcePeriodic(job) {
if (job.get('periodic')) {
- const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/periodic/force');
+ const url = addToPath(
+ this.urlForFindRecord(job.get('id'), 'job'),
+ '/periodic/force'
+ );
return this.ajax(url, 'POST');
}
}
@@ -44,7 +47,7 @@ export default class JobAdapter extends WatchableNamespaceIDs {
Job: job.get('_newDefinitionJSON'),
Diff: true,
},
- }).then(json => {
+ }).then((json) => {
json.ID = jobId;
store.pushPayload('job-plan', { jobPlans: [json] });
return store.peekRecord('job-plan', jobId);
@@ -71,7 +74,10 @@ export default class JobAdapter extends WatchableNamespaceIDs {
}
scale(job, group, count, message) {
- const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/scale');
+ const url = addToPath(
+ this.urlForFindRecord(job.get('id'), 'job'),
+ '/scale'
+ );
return this.ajax(url, 'POST', {
data: {
Count: count,
@@ -87,7 +93,10 @@ export default class JobAdapter extends WatchableNamespaceIDs {
}
dispatch(job, meta, payload) {
- const url = addToPath(this.urlForFindRecord(job.get('id'), 'job'), '/dispatch');
+ const url = addToPath(
+ this.urlForFindRecord(job.get('id'), 'job'),
+ '/dispatch'
+ );
return this.ajax(url, 'POST', {
data: {
Payload: base64EncodeString(payload),
diff --git a/ui/app/adapters/namespace.js b/ui/app/adapters/namespace.js
index 9594862d2..8e91ea90c 100644
--- a/ui/app/adapters/namespace.js
+++ b/ui/app/adapters/namespace.js
@@ -3,7 +3,7 @@ import codesForError from '../utils/codes-for-error';
export default class NamespaceAdapter extends Watchable {
findRecord(store, modelClass, id) {
- return super.findRecord(...arguments).catch(error => {
+ return super.findRecord(...arguments).catch((error) => {
const errorCodes = codesForError(error);
if (errorCodes.includes('501')) {
return { Name: id };
diff --git a/ui/app/adapters/node.js b/ui/app/adapters/node.js
index 746f51f6e..fdb085a2c 100644
--- a/ui/app/adapters/node.js
+++ b/ui/app/adapters/node.js
@@ -11,7 +11,10 @@ export default class NodeAdapter extends Watchable {
}
setEligibility(node, isEligible) {
- const url = addToPath(this.urlForFindRecord(node.id, 'node'), '/eligibility');
+ const url = addToPath(
+ this.urlForFindRecord(node.id, 'node'),
+ '/eligibility'
+ );
return this.ajax(url, 'POST', {
data: {
NodeID: node.id,
diff --git a/ui/app/adapters/recommendation-summary.js b/ui/app/adapters/recommendation-summary.js
index 42754d80b..71b807749 100644
--- a/ui/app/adapters/recommendation-summary.js
+++ b/ui/app/adapters/recommendation-summary.js
@@ -9,13 +9,20 @@ export default class RecommendationSummaryAdapter extends ApplicationAdapter {
}
updateRecord(store, type, snapshot) {
- const url = `${super.urlForCreateRecord('recommendations', snapshot)}/apply`;
+ const url = `${super.urlForCreateRecord(
+ 'recommendations',
+ snapshot
+ )}/apply`;
- const allRecommendationIds = snapshot.hasMany('recommendations').mapBy('id');
- const excludedRecommendationIds = (snapshot.hasMany('excludedRecommendations') || []).mapBy(
- 'id'
+ const allRecommendationIds = snapshot
+ .hasMany('recommendations')
+ .mapBy('id');
+ const excludedRecommendationIds = (
+ snapshot.hasMany('excludedRecommendations') || []
+ ).mapBy('id');
+ const includedRecommendationIds = allRecommendationIds.removeObjects(
+ excludedRecommendationIds
);
- const includedRecommendationIds = allRecommendationIds.removeObjects(excludedRecommendationIds);
const data = {
Apply: includedRecommendationIds,
diff --git a/ui/app/adapters/token.js b/ui/app/adapters/token.js
index 09ea316af..253673534 100644
--- a/ui/app/adapters/token.js
+++ b/ui/app/adapters/token.js
@@ -8,7 +8,7 @@ export default class TokenAdapter extends ApplicationAdapter {
namespace = namespace + '/acl';
findSelf() {
- return this.ajax(`${this.buildURL()}/token/self`, 'GET').then(token => {
+ return this.ajax(`${this.buildURL()}/token/self`, 'GET').then((token) => {
const store = this.store;
store.pushPayload('token', {
tokens: [token],
@@ -23,15 +23,20 @@ export default class TokenAdapter extends ApplicationAdapter {
data: {
OneTimeSecretID: oneTimeToken,
},
- }).then(({ Token: token }) => {
- const store = this.store;
- store.pushPayload('token', {
- tokens: [token],
- });
+ })
+ .then(({ Token: token }) => {
+ const store = this.store;
+ store.pushPayload('token', {
+ tokens: [token],
+ });
- return store.peekRecord('token', store.normalize('token', token).data.id);
- }).catch(() => {
- throw new OTTExchangeError();
- });
+ return store.peekRecord(
+ 'token',
+ store.normalize('token', token).data.id
+ );
+ })
+ .catch(() => {
+ throw new OTTExchangeError();
+ });
}
}
diff --git a/ui/app/adapters/watchable-namespace-ids.js b/ui/app/adapters/watchable-namespace-ids.js
index 11219deb9..ffee65fcc 100644
--- a/ui/app/adapters/watchable-namespace-ids.js
+++ b/ui/app/adapters/watchable-namespace-ids.js
@@ -7,8 +7,8 @@ export default class WatchableNamespaceIDs extends Watchable {
@service system;
findAll() {
- return super.findAll(...arguments).then(data => {
- data.forEach(record => {
+ return super.findAll(...arguments).then((data) => {
+ data.forEach((record) => {
record.Namespace = 'default';
});
return data;
@@ -16,8 +16,8 @@ export default class WatchableNamespaceIDs extends Watchable {
}
query(store, type, { namespace }) {
- return super.query(...arguments).then(data => {
- data.forEach(record => {
+ return super.query(...arguments).then((data) => {
+ data.forEach((record) => {
if (!record.Namespace) record.Namespace = namespace;
});
return data;
@@ -26,7 +26,8 @@ export default class WatchableNamespaceIDs extends Watchable {
findRecord(store, type, id, snapshot) {
const [, namespace] = JSON.parse(id);
- const namespaceQuery = namespace && namespace !== 'default' ? { namespace } : {};
+ const namespaceQuery =
+ namespace && namespace !== 'default' ? { namespace } : {};
return super.findRecord(store, type, id, snapshot, namespaceQuery);
}
diff --git a/ui/app/adapters/watchable.js b/ui/app/adapters/watchable.js
index 456f2a2bc..b8eff658e 100644
--- a/ui/app/adapters/watchable.js
+++ b/ui/app/adapters/watchable.js
@@ -40,7 +40,10 @@ export default class Watchable extends ApplicationAdapter {
params.index = this.watchList.getIndexFor(url);
}
- const signal = get(snapshotRecordArray || {}, 'adapterOptions.abortController.signal');
+ const signal = get(
+ snapshotRecordArray || {},
+ 'adapterOptions.abortController.signal'
+ );
return this.ajax(url, 'GET', {
signal,
data: params,
@@ -48,9 +51,18 @@ export default class Watchable extends ApplicationAdapter {
}
findRecord(store, type, id, snapshot, additionalParams = {}) {
- const originalUrl = this.buildURL(type.modelName, id, snapshot, 'findRecord');
+ const originalUrl = this.buildURL(
+ type.modelName,
+ id,
+ snapshot,
+ 'findRecord'
+ );
let [url, params] = originalUrl.split('?');
- params = assign(queryString.parse(params) || {}, this.buildQuery(), additionalParams);
+ params = assign(
+ queryString.parse(params) || {},
+ this.buildQuery(),
+ additionalParams
+ );
if (get(snapshot || {}, 'adapterOptions.watch')) {
params.index = this.watchList.getIndexFor(originalUrl);
@@ -60,7 +72,7 @@ export default class Watchable extends ApplicationAdapter {
return this.ajax(url, 'GET', {
signal,
data: params,
- }).catch(error => {
+ }).catch((error) => {
if (error instanceof AbortError || error.name == 'AbortError') {
return;
}
@@ -68,27 +80,43 @@ export default class Watchable extends ApplicationAdapter {
});
}
- query(store, type, query, snapshotRecordArray, options, additionalParams = {}) {
+ query(
+ store,
+ type,
+ query,
+ snapshotRecordArray,
+ options,
+ additionalParams = {}
+ ) {
const url = this.buildURL(type.modelName, null, null, 'query', query);
let [urlPath, params] = url.split('?');
- params = assign(queryString.parse(params) || {}, this.buildQuery(), additionalParams, query);
+ params = assign(
+ queryString.parse(params) || {},
+ this.buildQuery(),
+ additionalParams,
+ query
+ );
if (get(options, 'adapterOptions.watch')) {
// The intended query without additional blocking query params is used
// to track the appropriate query index.
- params.index = this.watchList.getIndexFor(`${urlPath}?${queryString.stringify(query)}`);
+ params.index = this.watchList.getIndexFor(
+ `${urlPath}?${queryString.stringify(query)}`
+ );
}
const signal = get(options, 'adapterOptions.abortController.signal');
return this.ajax(urlPath, 'GET', {
signal,
data: params,
- }).then(payload => {
+ }).then((payload) => {
const adapter = store.adapterFor(type.modelName);
// Query params may not necessarily map one-to-one to attribute names.
// Adapters are responsible for declaring param mappings.
- const queryParamsToAttrs = Object.keys(adapter.queryParamsToAttrs || {}).map(key => ({
+ const queryParamsToAttrs = Object.keys(
+ adapter.queryParamsToAttrs || {}
+ ).map((key) => ({
queryParam: key,
attr: adapter.queryParamsToAttrs[key],
}));
@@ -97,12 +125,12 @@ export default class Watchable extends ApplicationAdapter {
// deletes have occurred, the store won't have stale records.
store
.peekAll(type.modelName)
- .filter(record =>
+ .filter((record) =>
queryParamsToAttrs.some(
- mapping => get(record, mapping.attr) === query[mapping.queryParam]
+ (mapping) => get(record, mapping.attr) === query[mapping.queryParam]
)
)
- .forEach(record => {
+ .forEach((record) => {
removeRecord(store, record);
});
@@ -110,7 +138,11 @@ export default class Watchable extends ApplicationAdapter {
});
}
- reloadRelationship(model, relationshipName, options = { watch: false, abortController: null }) {
+ reloadRelationship(
+ model,
+ relationshipName,
+ options = { watch: false, abortController: null }
+ ) {
const { watch, abortController } = options;
const relationship = model.relationshipFor(relationshipName);
if (relationship.kind !== 'belongsTo' && relationship.kind !== 'hasMany') {
@@ -129,7 +161,7 @@ export default class Watchable extends ApplicationAdapter {
// in the URL and in options.data
if (url.includes('?')) {
const paramsInUrl = queryString.parse(url.split('?')[1]);
- Object.keys(paramsInUrl).forEach(key => {
+ Object.keys(paramsInUrl).forEach((key) => {
delete params[key];
});
}
@@ -138,7 +170,7 @@ export default class Watchable extends ApplicationAdapter {
signal: abortController && abortController.signal,
data: params,
}).then(
- json => {
+ (json) => {
const store = this.store;
const normalizeMethod =
relationship.kind === 'belongsTo'
@@ -146,10 +178,14 @@ export default class Watchable extends ApplicationAdapter {
: 'normalizeFindHasManyResponse';
const serializer = store.serializerFor(relationship.type);
const modelClass = store.modelFor(relationship.type);
- const normalizedData = serializer[normalizeMethod](store, modelClass, json);
+ const normalizedData = serializer[normalizeMethod](
+ store,
+ modelClass,
+ json
+ );
store.push(normalizedData);
},
- error => {
+ (error) => {
if (error instanceof AbortError || error.name === 'AbortError') {
return relationship.kind === 'belongsTo' ? {} : [];
}
diff --git a/ui/app/components/agent-monitor.js b/ui/app/components/agent-monitor.js
index fe596e220..4c511322e 100644
--- a/ui/app/components/agent-monitor.js
+++ b/ui/app/components/agent-monitor.js
@@ -46,6 +46,7 @@ export default class AgentMonitor extends Component {
}
didInsertElement() {
+ super.didInsertElement(...arguments);
this.updateLogger();
}
@@ -57,7 +58,7 @@ export default class AgentMonitor extends Component {
this.set(
'logger',
Log.create({
- logFetch: url => this.token.authorizedRequest(url),
+ logFetch: (url) => this.token.authorizedRequest(url),
params: this.monitorParams,
url: this.monitorUrl,
tail: currentTail,
diff --git a/ui/app/components/allocation-row.js b/ui/app/components/allocation-row.js
index 4ef9a5680..4eaddb3fd 100644
--- a/ui/app/components/allocation-row.js
+++ b/ui/app/components/allocation-row.js
@@ -33,7 +33,7 @@ export default class AllocationRow extends Component {
if (!this.get('allocation.isRunning')) return undefined;
return AllocationStatsTracker.create({
- fetch: url => this.token.authorizedRequest(url),
+ fetch: (url) => this.token.authorizedRequest(url),
allocation: this.allocation,
});
}
@@ -48,6 +48,7 @@ export default class AllocationRow extends Component {
}
didReceiveAttrs() {
+ super.didReceiveAttrs();
this.updateStatsTracker();
}
@@ -61,13 +62,11 @@ export default class AllocationRow extends Component {
}
}
- @(task(function*() {
+ @(task(function* () {
do {
if (this.stats) {
try {
- yield this.get('stats.poll')
- .linked()
- .perform();
+ yield this.get('stats.poll').linked().perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
@@ -86,7 +85,9 @@ async function qualifyAllocation() {
// Make sure the allocation is a complete record and not a partial so we
// can show information such as preemptions and rescheduled allocation.
if (allocation.isPartial) {
- await this.store.findRecord('allocation', allocation.id, { backgroundReload: false });
+ await this.store.findRecord('allocation', allocation.id, {
+ backgroundReload: false,
+ });
}
if (allocation.get('job.isPending')) {
diff --git a/ui/app/components/allocation-stat.js b/ui/app/components/allocation-stat.js
index b53531070..efac3ad62 100644
--- a/ui/app/components/allocation-stat.js
+++ b/ui/app/components/allocation-stat.js
@@ -42,8 +42,10 @@ export default class AllocationStat extends Component {
@computed('metric', 'statsTracker.{reservedMemory,reservedCPU}')
get formattedReserved() {
- if (this.metric === 'memory') return formatBytes(this.statsTracker.reservedMemory, 'MiB');
- if (this.metric === 'cpu') return formatHertz(this.statsTracker.reservedCPU, 'MHz');
+ if (this.metric === 'memory')
+ return formatBytes(this.statsTracker.reservedMemory, 'MiB');
+ if (this.metric === 'cpu')
+ return formatHertz(this.statsTracker.reservedCPU, 'MHz');
return undefined;
}
}
diff --git a/ui/app/components/chart-primitives/area.js b/ui/app/components/chart-primitives/area.js
index c8e033ae6..ec4e21945 100644
--- a/ui/app/components/chart-primitives/area.js
+++ b/ui/app/components/chart-primitives/area.js
@@ -7,7 +7,9 @@ export default class ChartPrimitiveArea extends Component {
get colorClass() {
if (this.args.colorClass) return this.args.colorClass;
if (this.args.colorScale && this.args.index != null)
- return `${this.args.colorScale} ${this.args.colorScale}-${this.args.index + 1}`;
+ return `${this.args.colorScale} ${this.args.colorScale}-${
+ this.args.index + 1
+ }`;
return 'is-primary';
}
@@ -31,9 +33,9 @@ export default class ChartPrimitiveArea extends Component {
const builder = line()
.curve(d3Shape[this.curveMethod])
- .defined(d => d[yProp] != null)
- .x(d => xScale(d[xProp]))
- .y(d => yScale(d[yProp]));
+ .defined((d) => d[yProp] != null)
+ .x((d) => xScale(d[xProp]))
+ .y((d) => yScale(d[yProp]));
return builder(this.args.data);
}
@@ -43,10 +45,10 @@ export default class ChartPrimitiveArea extends Component {
const builder = area()
.curve(d3Shape[this.curveMethod])
- .defined(d => d[yProp] != null)
- .x(d => xScale(d[xProp]))
+ .defined((d) => d[yProp] != null)
+ .x((d) => xScale(d[xProp]))
.y0(yScale(0))
- .y1(d => yScale(d[yProp]));
+ .y1((d) => yScale(d[yProp]));
return builder(this.args.data);
}
diff --git a/ui/app/components/chart-primitives/h-annotations.js b/ui/app/components/chart-primitives/h-annotations.js
index e189fc23c..29afab595 100644
--- a/ui/app/components/chart-primitives/h-annotations.js
+++ b/ui/app/components/chart-primitives/h-annotations.js
@@ -19,7 +19,7 @@ export default class ChartPrimitiveVAnnotations extends Component {
let sortedAnnotations = annotations.sortBy(prop).reverse();
- return sortedAnnotations.map(annotation => {
+ return sortedAnnotations.map((annotation) => {
const y = scale(annotation[prop]);
const x = 0;
const formattedY = format()(annotation[prop]);
diff --git a/ui/app/components/chart-primitives/v-annotations.js b/ui/app/components/chart-primitives/v-annotations.js
index ce6df6238..5f76690ed 100644
--- a/ui/app/components/chart-primitives/v-annotations.js
+++ b/ui/app/components/chart-primitives/v-annotations.js
@@ -33,7 +33,7 @@ export default class ChartPrimitiveVAnnotations extends Component {
let prevX = 0;
let prevHigh = false;
- return sortedAnnotations.map(annotation => {
+ return sortedAnnotations.map((annotation) => {
const x = scale(annotation[prop]);
if (prevX && !prevHigh && Math.abs(x - prevX) < 30) {
prevHigh = true;
diff --git a/ui/app/components/children-status-bar.js b/ui/app/components/children-status-bar.js
index 5ea7d6eb7..b64cbb351 100644
--- a/ui/app/components/children-status-bar.js
+++ b/ui/app/components/children-status-bar.js
@@ -16,10 +16,22 @@ export default class ChildrenStatusBar extends DistributionBar {
return [];
}
- const children = this.job.getProperties('pendingChildren', 'runningChildren', 'deadChildren');
+ const children = this.job.getProperties(
+ 'pendingChildren',
+ 'runningChildren',
+ 'deadChildren'
+ );
return [
- { label: 'Pending', value: children.pendingChildren, className: 'queued' },
- { label: 'Running', value: children.runningChildren, className: 'running' },
+ {
+ label: 'Pending',
+ value: children.pendingChildren,
+ className: 'queued',
+ },
+ {
+ label: 'Running',
+ value: children.runningChildren,
+ className: 'running',
+ },
{ label: 'Dead', value: children.deadChildren, className: 'complete' },
];
}
diff --git a/ui/app/components/client-node-row.js b/ui/app/components/client-node-row.js
index 2127b5930..013ffb4be 100644
--- a/ui/app/components/client-node-row.js
+++ b/ui/app/components/client-node-row.js
@@ -10,7 +10,9 @@ import classic from 'ember-classic-decorator';
@classic
@tagName('tr')
@classNames('client-node-row', 'is-interactive')
-export default class ClientNodeRow extends Component.extend(WithVisibilityDetection) {
+export default class ClientNodeRow extends Component.extend(
+ WithVisibilityDetection
+) {
@service store;
node = null;
@@ -22,6 +24,7 @@ export default class ClientNodeRow extends Component.extend(WithVisibilityDetect
}
didReceiveAttrs() {
+ super.didReceiveAttrs();
// Reload the node in order to get detail information
const node = this.node;
if (node) {
diff --git a/ui/app/components/copy-button.js b/ui/app/components/copy-button.js
index 107786d73..979ecd701 100644
--- a/ui/app/components/copy-button.js
+++ b/ui/app/components/copy-button.js
@@ -9,7 +9,7 @@ export default class CopyButton extends Component {
clipboardText = null;
state = null;
- @(task(function*() {
+ @(task(function* () {
this.set('state', 'success');
yield timeout(2000);
diff --git a/ui/app/components/das/dismissed.js b/ui/app/components/das/dismissed.js
index 85fa8e9f1..3fdefa6ec 100644
--- a/ui/app/components/das/dismissed.js
+++ b/ui/app/components/das/dismissed.js
@@ -4,7 +4,8 @@ import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
export default class DasDismissedComponent extends Component {
- @localStorageProperty('nomadRecommendationDismssalUnderstood', false) explanationUnderstood;
+ @localStorageProperty('nomadRecommendationDismssalUnderstood', false)
+ explanationUnderstood;
@tracked dismissInTheFuture = false;
diff --git a/ui/app/components/das/recommendation-accordion.js b/ui/app/components/das/recommendation-accordion.js
index 1270a0d27..75c0e1f13 100644
--- a/ui/app/components/das/recommendation-accordion.js
+++ b/ui/app/components/das/recommendation-accordion.js
@@ -11,9 +11,11 @@ export default class DasRecommendationAccordionComponent extends Component {
@tracked closing = false;
@tracked animationContainerStyle = htmlSafe('');
- @(task(function*() {
+ @(task(function* () {
this.closing = true;
- this.animationContainerStyle = htmlSafe(`height: ${this.accordionElement.clientHeight}px`);
+ this.animationContainerStyle = htmlSafe(
+ `height: ${this.accordionElement.clientHeight}px`
+ );
yield timeout(10);
diff --git a/ui/app/components/das/recommendation-card.js b/ui/app/components/das/recommendation-card.js
index 29f203e13..7ab471631 100644
--- a/ui/app/components/das/recommendation-card.js
+++ b/ui/app/components/das/recommendation-card.js
@@ -93,35 +93,39 @@ export default class DasRecommendationCardComponent extends Component {
get taskToggleRows() {
const taskNameToTaskToggles = {};
- return this.args.summary.recommendations.reduce((taskToggleRows, recommendation) => {
- let taskToggleRow = taskNameToTaskToggles[recommendation.task.name];
+ return this.args.summary.recommendations.reduce(
+ (taskToggleRows, recommendation) => {
+ let taskToggleRow = taskNameToTaskToggles[recommendation.task.name];
- if (!taskToggleRow) {
- taskToggleRow = {
- recommendations: [],
- task: recommendation.task,
+ if (!taskToggleRow) {
+ taskToggleRow = {
+ recommendations: [],
+ task: recommendation.task,
+ };
+
+ taskNameToTaskToggles[recommendation.task.name] = taskToggleRow;
+ taskToggleRows.push(taskToggleRow);
+ }
+
+ const isCpu = recommendation.resource === 'CPU';
+ const rowResourceProperty = isCpu ? 'cpu' : 'memory';
+
+ taskToggleRow[rowResourceProperty] = {
+ recommendation,
+ isActive:
+ !this.args.summary.excludedRecommendations.includes(recommendation),
};
- taskNameToTaskToggles[recommendation.task.name] = taskToggleRow;
- taskToggleRows.push(taskToggleRow);
- }
+ if (isCpu) {
+ taskToggleRow.recommendations.unshift(recommendation);
+ } else {
+ taskToggleRow.recommendations.push(recommendation);
+ }
- const isCpu = recommendation.resource === 'CPU';
- const rowResourceProperty = isCpu ? 'cpu' : 'memory';
-
- taskToggleRow[rowResourceProperty] = {
- recommendation,
- isActive: !this.args.summary.excludedRecommendations.includes(recommendation),
- };
-
- if (isCpu) {
- taskToggleRow.recommendations.unshift(recommendation);
- } else {
- taskToggleRow.recommendations.push(recommendation);
- }
-
- return taskToggleRows;
- }, []);
+ return taskToggleRows;
+ },
+ []
+ );
}
get showToggleAllToggles() {
@@ -129,23 +133,30 @@ export default class DasRecommendationCardComponent extends Component {
}
get allCpuToggleDisabled() {
- return !this.args.summary.recommendations.filterBy('resource', 'CPU').length;
+ return !this.args.summary.recommendations.filterBy('resource', 'CPU')
+ .length;
}
get allMemoryToggleDisabled() {
- return !this.args.summary.recommendations.filterBy('resource', 'MemoryMB').length;
+ return !this.args.summary.recommendations.filterBy('resource', 'MemoryMB')
+ .length;
}
get cannotAccept() {
return (
- this.args.summary.excludedRecommendations.length == this.args.summary.recommendations.length
+ this.args.summary.excludedRecommendations.length ==
+ this.args.summary.recommendations.length
);
}
get copyButtonLink() {
- const path = this.router.urlFor('optimize.summary', this.args.summary.slug, {
- queryParams: { namespace: this.args.summary.jobNamespace },
- });
+ const path = this.router.urlFor(
+ 'optimize.summary',
+ this.args.summary.slug,
+ {
+ queryParams: { namespace: this.args.summary.jobNamespace },
+ }
+ );
const { origin } = window.location;
return `${origin}${path}`;
@@ -173,9 +184,9 @@ export default class DasRecommendationCardComponent extends Component {
.save()
.then(
() => this.onApplied.perform(),
- e => this.onError.perform(e)
+ (e) => this.onError.perform(e)
)
- .catch(e => {
+ .catch((e) => {
if (!didCancel(e)) {
throw e;
}
@@ -185,21 +196,23 @@ export default class DasRecommendationCardComponent extends Component {
@action
dismiss() {
this.storeCardHeight();
- this.args.summary.excludedRecommendations.pushObjects(this.args.summary.recommendations);
+ this.args.summary.excludedRecommendations.pushObjects(
+ this.args.summary.recommendations
+ );
this.args.summary
.save()
.then(
() => this.onDismissed.perform(),
- e => this.onError.perform(e)
+ (e) => this.onError.perform(e)
)
- .catch(e => {
+ .catch((e) => {
if (!didCancel(e)) {
throw e;
}
});
}
- @(task(function*() {
+ @(task(function* () {
this.interstitialComponent = 'accepted';
yield timeout(Ember.testing ? 0 : 2000);
@@ -208,8 +221,8 @@ export default class DasRecommendationCardComponent extends Component {
}).drop())
onApplied;
- @(task(function*() {
- const { manuallyDismissed } = yield new Promise(resolve => {
+ @(task(function* () {
+ const { manuallyDismissed } = yield new Promise((resolve) => {
this.proceedPromiseResolve = resolve;
this.interstitialComponent = 'dismissed';
});
@@ -223,8 +236,8 @@ export default class DasRecommendationCardComponent extends Component {
}).drop())
onDismissed;
- @(task(function*(error) {
- yield new Promise(resolve => {
+ @(task(function* (error) {
+ yield new Promise((resolve) => {
this.proceedPromiseResolve = resolve;
this.interstitialComponent = 'error';
this.error = error.toString();
diff --git a/ui/app/components/das/recommendation-chart.js b/ui/app/components/das/recommendation-chart.js
index d9e0fc515..9fb82c8a1 100644
--- a/ui/app/components/das/recommendation-chart.js
+++ b/ui/app/components/das/recommendation-chart.js
@@ -64,10 +64,12 @@ export default class RecommendationChartComponent extends Component {
edgeTickHeight = 23;
centerTickOffset = 6;
- centerY = this.tickTextHeight + this.centerTickOffset + this.edgeTickHeight / 2;
+ centerY =
+ this.tickTextHeight + this.centerTickOffset + this.edgeTickHeight / 2;
edgeTickY1 = this.tickTextHeight + this.centerTickOffset;
- edgeTickY2 = this.tickTextHeight + this.edgeTickHeight + this.centerTickOffset;
+ edgeTickY2 =
+ this.tickTextHeight + this.edgeTickHeight + this.centerTickOffset;
deltaTextY = this.edgeTickY2;
@@ -129,7 +131,10 @@ export default class RecommendationChartComponent extends Component {
},
rect: {
x: this.gutterWidthLeft,
- y: (this.edgeTickHeight - rectHeight) / 2 + this.centerTickOffset + this.tickTextHeight,
+ y:
+ (this.edgeTickHeight - rectHeight) / 2 +
+ this.centerTickOffset +
+ this.tickTextHeight,
width: rectWidth,
height: rectHeight,
},
@@ -145,7 +150,10 @@ export default class RecommendationChartComponent extends Component {
}
get maximumX() {
- return Math.max(this.higherValue, get(this.args.stats, 'max') || Number.MIN_SAFE_INTEGER);
+ return Math.max(
+ this.higherValue,
+ get(this.args.stats, 'max') || Number.MIN_SAFE_INTEGER
+ );
}
get lowerValue() {
@@ -212,9 +220,13 @@ export default class RecommendationChartComponent extends Component {
let translateX;
if (this.shown) {
- translateX = this.isIncrease ? this.higherValueWidth : this.lowerValueWidth;
+ translateX = this.isIncrease
+ ? this.higherValueWidth
+ : this.lowerValueWidth;
} else {
- translateX = this.isIncrease ? this.lowerValueWidth : this.higherValueWidth;
+ translateX = this.isIncrease
+ ? this.lowerValueWidth
+ : this.higherValueWidth;
}
return {
@@ -222,7 +234,9 @@ export default class RecommendationChartComponent extends Component {
points: `
0,${this.center.y1}
0,${this.center.y1 - this.deltaTriangleHeight / 2}
- ${(directionXMultiplier * this.deltaTriangleHeight) / 2},${this.center.y1}
+ ${(directionXMultiplier * this.deltaTriangleHeight) / 2},${
+ this.center.y1
+ }
0,${this.center.y1 + this.deltaTriangleHeight / 2}
`,
};
@@ -236,7 +250,9 @@ export default class RecommendationChartComponent extends Component {
},
delta: {
style: htmlSafe(
- `transform: translateX(${this.shown ? this.higherValueWidth : this.lowerValueWidth}px)`
+ `transform: translateX(${
+ this.shown ? this.higherValueWidth : this.lowerValueWidth
+ }px)`
),
},
};
@@ -247,7 +263,9 @@ export default class RecommendationChartComponent extends Component {
},
delta: {
style: htmlSafe(
- `transform: translateX(${this.shown ? this.lowerValueWidth : this.higherValueWidth}px)`
+ `transform: translateX(${
+ this.shown ? this.lowerValueWidth : this.higherValueWidth
+ }px)`
),
},
};
@@ -271,7 +289,8 @@ export default class RecommendationChartComponent extends Component {
};
const percentText = formatPercent(
- (this.args.recommendedValue - this.args.currentValue) / this.args.currentValue
+ (this.args.recommendedValue - this.args.currentValue) /
+ this.args.currentValue
);
const percent = {
@@ -316,7 +335,10 @@ export default class RecommendationChartComponent extends Component {
};
return Object.keys(statsWithCurrentAndRecommended)
- .map(key => ({ label: statsKeyToLabel[key], value: statsWithCurrentAndRecommended[key] }))
+ .map((key) => ({
+ label: statsKeyToLabel[key],
+ value: statsWithCurrentAndRecommended[key],
+ }))
.sortBy('value');
} else {
return [];
diff --git a/ui/app/components/distribution-bar.js b/ui/app/components/distribution-bar.js
index fa681b8b6..a33c48f3e 100644
--- a/ui/app/components/distribution-bar.js
+++ b/ui/app/components/distribution-bar.js
@@ -34,24 +34,24 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
const data = copy(this.data, true);
const sum = data.mapBy('value').reduce(sumAggregate, 0);
- return data.map(({ label, value, className, layers, legendLink, help }, index) => ({
- label,
- value,
- className,
- layers,
- legendLink,
- help,
- index,
- percent: value / sum,
- offset:
- data
- .slice(0, index)
- .mapBy('value')
- .reduce(sumAggregate, 0) / sum,
- }));
+ return data.map(
+ ({ label, value, className, layers, legendLink, help }, index) => ({
+ label,
+ value,
+ className,
+ layers,
+ legendLink,
+ help,
+ index,
+ percent: value / sum,
+ offset:
+ data.slice(0, index).mapBy('value').reduce(sumAggregate, 0) / sum,
+ })
+ );
}
didInsertElement() {
+ super.didInsertElement(...arguments);
const svg = this.element.querySelector('svg');
const chart = d3.select(svg);
const maskId = `dist-mask-${guidFor(this)}`;
@@ -74,6 +74,7 @@ export default class DistributionBar extends Component.extend(WindowResizable) {
}
didUpdateAttrs() {
+ super.didUpdateAttrs();
this.renderChart();
}
diff --git a/ui/app/components/drain-popover.js b/ui/app/components/drain-popover.js
index 764147396..94f666538 100644
--- a/ui/app/components/drain-popover.js
+++ b/ui/app/components/drain-popover.js
@@ -26,6 +26,7 @@ export default class DrainPopover extends Component {
@localStorageProperty('nomadDrainOptions', {}) drainOptions;
didReceiveAttrs() {
+ super.didReceiveAttrs();
// Load drain config values from local storage if availabe.
[
'deadlineEnabled',
@@ -33,14 +34,14 @@ export default class DrainPopover extends Component {
'forceDrain',
'drainSystemJobs',
'selectedDurationQuickOption',
- ].forEach(k => {
+ ].forEach((k) => {
if (k in this.drainOptions) {
this[k] = this.drainOptions[k];
}
});
}
- @overridable(function() {
+ @overridable(function () {
return this.durationQuickOptions[0];
})
selectedDurationQuickOption;
@@ -72,7 +73,7 @@ export default class DrainPopover extends Component {
return this.selectedDurationQuickOption.value;
}
- @task(function*(close) {
+ @task(function* (close) {
if (!this.client) return;
const isUpdating = this.client.isDraining;
diff --git a/ui/app/components/exec-terminal.js b/ui/app/components/exec-terminal.js
index e396677a7..18cf3d1b3 100644
--- a/ui/app/components/exec-terminal.js
+++ b/ui/app/components/exec-terminal.js
@@ -8,6 +8,7 @@ import classic from 'ember-classic-decorator';
@classNames('terminal-container')
export default class ExecTerminal extends Component.extend(WindowResizable) {
didInsertElement() {
+ super.didInsertElement(...arguments);
let fitAddon = new FitAddon();
this.fitAddon = fitAddon;
this.terminal.loadAddon(fitAddon);
diff --git a/ui/app/components/exec/task-group-parent.js b/ui/app/components/exec/task-group-parent.js
index 3d0b584b0..762616be5 100644
--- a/ui/app/components/exec/task-group-parent.js
+++ b/ui/app/components/exec/task-group-parent.js
@@ -31,7 +31,9 @@ export default class TaskGroupParent extends Component {
@computed('taskGroup.allocations.@each.clientStatus')
get hasPendingAllocations() {
- return this.taskGroup.allocations.any(allocation => allocation.clientStatus === 'pending');
+ return this.taskGroup.allocations.any(
+ (allocation) => allocation.clientStatus === 'pending'
+ );
}
@mapBy('taskGroup.allocations', 'states') allocationTaskStatesRecordArrays;
@@ -39,7 +41,10 @@ export default class TaskGroupParent extends Component {
get allocationTaskStates() {
const flattenRecordArrays = (accumulator, recordArray) =>
accumulator.concat(recordArray.toArray());
- return this.allocationTaskStatesRecordArrays.reduce(flattenRecordArrays, []);
+ return this.allocationTaskStatesRecordArrays.reduce(
+ flattenRecordArrays,
+ []
+ );
}
@filterBy('allocationTaskStates', 'isActive') activeTaskStates;
@@ -55,12 +60,17 @@ export default class TaskGroupParent extends Component {
)
get tasksWithRunningStates() {
const activeTaskStateNames = this.activeTaskStates
- .filter(taskState => {
- return taskState.task && taskState.task.taskGroup.name === this.taskGroup.name;
+ .filter((taskState) => {
+ return (
+ taskState.task &&
+ taskState.task.taskGroup.name === this.taskGroup.name
+ );
})
.mapBy('name');
- return this.taskGroup.tasks.filter(task => activeTaskStateNames.includes(task.name));
+ return this.taskGroup.tasks.filter((task) =>
+ activeTaskStateNames.includes(task.name)
+ );
}
taskSorting = ['name'];
diff --git a/ui/app/components/flex-masonry.js b/ui/app/components/flex-masonry.js
index ff3776afc..29b32501a 100644
--- a/ui/app/components/flex-masonry.js
+++ b/ui/app/components/flex-masonry.js
@@ -18,7 +18,9 @@ export default class FlexMasonry extends Component {
// There's nothing to do if there is no element
if (!this.element) return;
- const items = this.element.querySelectorAll(':scope > .flex-masonry-item');
+ const items = this.element.querySelectorAll(
+ ':scope > .flex-masonry-item'
+ );
// Clear out specified order and flex-basis values in case this was once a multi-column layout
if (this.args.columns === 1 || !this.args.columns) {
@@ -43,7 +45,7 @@ export default class FlexMasonry extends Component {
const height = item.clientHeight;
// Pick the shortest column accounting for margins
- const column = columns[minIndex(columns, c => c.height)];
+ const column = columns[minIndex(columns, (c) => c.height)];
// Add the new element's height to the column height
column.height += marginTop + height + marginBottom;
@@ -62,10 +64,12 @@ export default class FlexMasonry extends Component {
// beteen the height of the column and the previous column, then flexbox will naturally place the first
// item at the end of the previous column).
columns.forEach((column, index) => {
- const nextHeight = index < columns.length - 1 ? columns[index + 1].height : 0;
+ const nextHeight =
+ index < columns.length - 1 ? columns[index + 1].height : 0;
const item = column.elements.lastObject;
if (item) {
- item.style.flexBasis = item.clientHeight + Math.max(0, nextHeight - column.height) + 'px';
+ item.style.flexBasis =
+ item.clientHeight + Math.max(0, nextHeight - column.height) + 'px';
}
});
diff --git a/ui/app/components/fs/browser.js b/ui/app/components/fs/browser.js
index 751f60f65..a57365667 100644
--- a/ui/app/components/fs/browser.js
+++ b/ui/app/components/fs/browser.js
@@ -39,11 +39,18 @@ export default class Browser extends Component {
@filterBy('directoryEntries', 'IsDir') directories;
@filterBy('directoryEntries', 'IsDir', false) files;
- @computed('directories', 'directoryEntries.[]', 'files', 'sortDescending', 'sortProperty')
+ @computed(
+ 'directories',
+ 'directoryEntries.[]',
+ 'files',
+ 'sortDescending',
+ 'sortProperty'
+ )
get sortedDirectoryEntries() {
const sortProperty = this.sortProperty;
- const directorySortProperty = sortProperty === 'Size' ? 'Name' : sortProperty;
+ const directorySortProperty =
+ sortProperty === 'Size' ? 'Name' : sortProperty;
const sortedDirectories = this.directories.sortBy(directorySortProperty);
const sortedFiles = this.files.sortBy(sortProperty);
diff --git a/ui/app/components/fs/file.js b/ui/app/components/fs/file.js
index 15be2642f..1af183478 100644
--- a/ui/app/components/fs/file.js
+++ b/ui/app/components/fs/file.js
@@ -39,7 +39,10 @@ export default class File extends Component {
if (contentType.startsWith('image/')) {
return 'image';
- } else if (contentType.startsWith('text/') || contentType.startsWith('application/json')) {
+ } else if (
+ contentType.startsWith('text/') ||
+ contentType.startsWith('application/json')
+ ) {
return 'stream';
} else {
return 'unknown';
@@ -108,7 +111,14 @@ export default class File extends Component {
}
}
- @computed('clientTimeout', 'fileParams', 'fileUrl', 'mode', 'serverTimeout', 'useServer')
+ @computed(
+ 'clientTimeout',
+ 'fileParams',
+ 'fileUrl',
+ 'mode',
+ 'serverTimeout',
+ 'useServer'
+ )
get logger() {
// The cat and readat APIs are in plainText while the stream API is always encoded.
const plainText = this.mode === 'head' || this.mode === 'tail';
@@ -116,15 +126,15 @@ export default class File extends Component {
// If the file request can't settle in one second, the client
// must be unavailable and the server should be used instead
const timing = this.useServer ? this.serverTimeout : this.clientTimeout;
- const logFetch = url =>
+ const logFetch = (url) =>
RSVP.race([this.token.authorizedRequest(url), timeout(timing)]).then(
- response => {
+ (response) => {
if (!response || !response.ok) {
this.nextErrorState(response);
}
return response;
},
- error => this.nextErrorState(error)
+ (error) => this.nextErrorState(error)
);
return Log.create({
diff --git a/ui/app/components/gauge-chart.js b/ui/app/components/gauge-chart.js
index 9625dbff2..bbd98bfde 100644
--- a/ui/app/components/gauge-chart.js
+++ b/ui/app/components/gauge-chart.js
@@ -78,6 +78,7 @@ export default class GaugeChart extends Component.extend(WindowResizable) {
}
didInsertElement() {
+ super.didInsertElement(...arguments);
this.updateDimensions();
}
diff --git a/ui/app/components/global-search/control.js b/ui/app/components/global-search/control.js
index 8f3967cca..e68e5c7be 100644
--- a/ui/app/components/global-search/control.js
+++ b/ui/app/components/global-search/control.js
@@ -32,23 +32,28 @@ export default class GlobalSearchControl extends Component {
}
didInsertElement() {
+ super.didInsertElement(...arguments);
set(this, '_keyDownHandler', this.keyDownHandler.bind(this));
document.addEventListener('keydown', this._keyDownHandler);
}
willDestroyElement() {
+ super.willDestroyElement(...arguments);
document.removeEventListener('keydown', this._keyDownHandler);
}
- @task(function*(string) {
- const searchResponse = yield this.token.authorizedRequest('/v1/search/fuzzy', {
- method: 'POST',
- body: JSON.stringify({
- Text: string,
- Context: 'all',
- Namespace: '*',
- }),
- });
+ @task(function* (string) {
+ const searchResponse = yield this.token.authorizedRequest(
+ '/v1/search/fuzzy',
+ {
+ method: 'POST',
+ body: JSON.stringify({
+ Text: string,
+ Context: 'all',
+ Namespace: '*',
+ }),
+ }
+ );
const results = yield searchResponse.json();
@@ -93,11 +98,13 @@ export default class GlobalSearchControl extends Component {
label: `${namespace} > ${jobId} > ${id}`,
}));
- const csiPluginResults = allCSIPluginResults.slice(0, MAXIMUM_RESULTS).map(({ ID: id }) => ({
- type: 'plugin',
- id,
- label: id,
- }));
+ const csiPluginResults = allCSIPluginResults
+ .slice(0, MAXIMUM_RESULTS)
+ .map(({ ID: id }) => ({
+ type: 'plugin',
+ id,
+ label: id,
+ }));
const {
jobs: jobsTruncated,
@@ -109,11 +116,21 @@ export default class GlobalSearchControl extends Component {
return [
{
- groupName: resultsGroupLabel('Jobs', jobResults, allJobResults, jobsTruncated),
+ groupName: resultsGroupLabel(
+ 'Jobs',
+ jobResults,
+ allJobResults,
+ jobsTruncated
+ ),
options: jobResults,
},
{
- groupName: resultsGroupLabel('Clients', nodeResults, allNodeResults, nodesTruncated),
+ groupName: resultsGroupLabel(
+ 'Clients',
+ nodeResults,
+ allNodeResults,
+ nodesTruncated
+ ),
options: nodeResults,
},
{
@@ -189,10 +206,14 @@ export default class GlobalSearchControl extends Component {
openOnClickOrTab(select, { target }) {
// Bypass having to press enter to access search after clicking/tabbing
const targetClassList = target.classList;
- const targetIsTrigger = targetClassList.contains('ember-power-select-trigger');
+ const targetIsTrigger = targetClassList.contains(
+ 'ember-power-select-trigger'
+ );
// Allow tabbing out of search
- const triggerIsNotActive = !targetClassList.contains('ember-power-select-trigger--active');
+ const triggerIsNotActive = !targetClassList.contains(
+ 'ember-power-select-trigger--active'
+ );
if (targetIsTrigger && triggerIsNotActive) {
debounce(this, this.open, 150);
diff --git a/ui/app/components/gutter-menu.js b/ui/app/components/gutter-menu.js
index 469ac039b..e73f58da3 100644
--- a/ui/app/components/gutter-menu.js
+++ b/ui/app/components/gutter-menu.js
@@ -44,7 +44,9 @@ export default class GutterMenu extends Component {
// an intent to reset context, but where to reset to depends on where the namespace
// is being switched from. Jobs take precedence, but if the namespace is switched from
// a storage-related page, context should be reset to volumes.
- const destination = this.router.currentRouteName.startsWith('csi.') ? 'csi.volumes' : 'jobs';
+ const destination = this.router.currentRouteName.startsWith('csi.')
+ ? 'csi.volumes'
+ : 'jobs';
this.router.transitionTo(destination, {
queryParams: { namespace: namespace.get('id') },
diff --git a/ui/app/components/hamburger-menu.js b/ui/app/components/hamburger-menu.js
index 133c7241b..9f1bbeabd 100644
--- a/ui/app/components/hamburger-menu.js
+++ b/ui/app/components/hamburger-menu.js
@@ -2,5 +2,4 @@ import Component from '@ember/component';
import { tagName } from '@ember-decorators/component';
@tagName('')
-export default class HamburgerMenu extends Component {
-}
+export default class HamburgerMenu extends Component {}
diff --git a/ui/app/components/job-diff.js b/ui/app/components/job-diff.js
index 2f7a6921c..505350877 100644
--- a/ui/app/components/job-diff.js
+++ b/ui/app/components/job-diff.js
@@ -5,7 +5,11 @@ import classic from 'ember-classic-decorator';
@classic
@classNames('job-diff')
-@classNameBindings('isEdited:is-edited', 'isAdded:is-added', 'isDeleted:is-deleted')
+@classNameBindings(
+ 'isEdited:is-edited',
+ 'isAdded:is-added',
+ 'isDeleted:is-deleted'
+)
export default class JobDiff extends Component {
diff = null;
diff --git a/ui/app/components/job-dispatch.js b/ui/app/components/job-dispatch.js
index e7ea1392c..d0a5af2d2 100644
--- a/ui/app/components/job-dispatch.js
+++ b/ui/app/components/job-dispatch.js
@@ -49,7 +49,7 @@ export default class JobDispatch extends Component {
// Helper for mapping the params into a useable form.
const mapper = (values, required) =>
values.map(
- x =>
+ (x) =>
new MetaField({
name: x,
required,
@@ -59,8 +59,14 @@ export default class JobDispatch extends Component {
);
// Fetch the different types of parameters.
- const required = mapper(this.args.job.parameterizedDetails.MetaRequired || [], true);
- const optional = mapper(this.args.job.parameterizedDetails.MetaOptional || [], false);
+ const required = mapper(
+ this.args.job.parameterizedDetails.MetaRequired || [],
+ true
+ );
+ const optional = mapper(
+ this.args.job.parameterizedDetails.MetaOptional || [],
+ false
+ );
// Merge them, required before optional.
this.metaFields = required.concat(optional);
@@ -94,7 +100,7 @@ export default class JobDispatch extends Component {
// Try to create the dispatch.
try {
let paramValues = {};
- this.metaFields.forEach(m => (paramValues[m.name] = m.value));
+ this.metaFields.forEach((m) => (paramValues[m.name] = m.value));
const dispatch = yield this.args.job.dispatch(paramValues, this.payload);
// Navigate to the newly created instance.
@@ -123,7 +129,7 @@ export default class JobDispatch extends Component {
this.resetErrors();
// Make sure that we have all of the meta fields that we need.
- this.metaFields.forEach(f => {
+ this.metaFields.forEach((f) => {
f.validate();
if (f.error) {
this.errors.pushObject(f.error);
diff --git a/ui/app/components/job-editor.js b/ui/app/components/job-editor.js
index bfa8bba3e..0e9426851 100644
--- a/ui/app/components/job-editor.js
+++ b/ui/app/components/job-editor.js
@@ -25,7 +25,10 @@ export default class JobEditor extends Component {
set context(value) {
const allowedValues = ['new', 'edit'];
- assert(`context must be one of: ${allowedValues.join(', ')}`, allowedValues.includes(value));
+ assert(
+ `context must be one of: ${allowedValues.join(', ')}`,
+ allowedValues.includes(value)
+ );
this.set('_context', value);
}
@@ -45,7 +48,7 @@ export default class JobEditor extends Component {
return this.planOutput ? 'plan' : 'editor';
}
- @(task(function*() {
+ @(task(function* () {
this.reset();
try {
@@ -68,7 +71,7 @@ export default class JobEditor extends Component {
}).drop())
plan;
- @task(function*() {
+ @task(function* () {
try {
if (this.context === 'new') {
yield this.job.run();
diff --git a/ui/app/components/job-page/parts/job-client-status-summary.js b/ui/app/components/job-page/parts/job-client-status-summary.js
index 515f08568..7e923dacf 100644
--- a/ui/app/components/job-page/parts/job-client-status-summary.js
+++ b/ui/app/components/job-page/parts/job-client-status-summary.js
@@ -24,6 +24,7 @@ export default class JobClientStatusSummary extends Component {
@action
onSliceClick(ev, slice) {
+ /* eslint-disable-next-line ember/no-string-prototype-extensions */
this.gotoClients([slice.className.camelize()]);
}
diff --git a/ui/app/components/job-page/parts/latest-deployment.js b/ui/app/components/job-page/parts/latest-deployment.js
index 75d37ae11..8b993ab81 100644
--- a/ui/app/components/job-page/parts/latest-deployment.js
+++ b/ui/app/components/job-page/parts/latest-deployment.js
@@ -13,7 +13,7 @@ export default class LatestDeployment extends Component {
isShowingDeploymentDetails = false;
- @task(function*() {
+ @task(function* () {
try {
yield this.get('job.latestDeployment.content').promote();
} catch (err) {
@@ -25,7 +25,7 @@ export default class LatestDeployment extends Component {
})
promote;
- @task(function*() {
+ @task(function* () {
try {
yield this.get('job.latestDeployment.content').fail();
} catch (err) {
diff --git a/ui/app/components/job-page/parts/recent-allocations.js b/ui/app/components/job-page/parts/recent-allocations.js
index 507a0fc0f..3afd9f37d 100644
--- a/ui/app/components/job-page/parts/recent-allocations.js
+++ b/ui/app/components/job-page/parts/recent-allocations.js
@@ -16,11 +16,8 @@ export default class RecentAllocations extends Component {
@computed('job.allocations.@each.modifyIndex')
get sortedAllocations() {
return PromiseArray.create({
- promise: this.get('job.allocations').then(allocations =>
- allocations
- .sortBy('modifyIndex')
- .reverse()
- .slice(0, 5)
+ promise: this.get('job.allocations').then((allocations) =>
+ allocations.sortBy('modifyIndex').reverse().slice(0, 5)
),
});
}
diff --git a/ui/app/components/job-page/parts/summary.js b/ui/app/components/job-page/parts/summary.js
index 51aace4a4..ca7e92931 100644
--- a/ui/app/components/job-page/parts/summary.js
+++ b/ui/app/components/job-page/parts/summary.js
@@ -24,6 +24,7 @@ export default class Summary extends Component {
@action
onSliceClick(ev, slice) {
+ /* eslint-disable-next-line ember/no-string-prototype-extensions */
this.gotoAllocations([slice.label.camelize()]);
}
diff --git a/ui/app/components/job-page/parts/title.js b/ui/app/components/job-page/parts/title.js
index cd713938d..24d8fc073 100644
--- a/ui/app/components/job-page/parts/title.js
+++ b/ui/app/components/job-page/parts/title.js
@@ -12,7 +12,7 @@ export default class Title extends Component {
handleError() {}
- @task(function*() {
+ @task(function* () {
try {
const job = this.job;
yield job.stop();
@@ -27,7 +27,7 @@ export default class Title extends Component {
})
stopJob;
- @task(function*() {
+ @task(function* () {
const job = this.job;
const definition = yield job.fetchRawDefinition();
diff --git a/ui/app/components/job-page/periodic.js b/ui/app/components/job-page/periodic.js
index 622b18e40..8a3783bb7 100644
--- a/ui/app/components/job-page/periodic.js
+++ b/ui/app/components/job-page/periodic.js
@@ -12,7 +12,7 @@ export default class Periodic extends AbstractJobPage {
@action
forceLaunch() {
- this.job.forcePeriodic().catch(err => {
+ this.job.forcePeriodic().catch((err) => {
this.set('errorMessage', {
title: 'Could Not Force Launch',
description: messageForError(err, 'submit jobs'),
diff --git a/ui/app/components/job-subnav.js b/ui/app/components/job-subnav.js
index 5e180f67b..6fb945a00 100644
--- a/ui/app/components/job-subnav.js
+++ b/ui/app/components/job-subnav.js
@@ -2,5 +2,4 @@ import Component from '@ember/component';
import { tagName } from '@ember-decorators/component';
@tagName('')
-export default class JobSubnav extends Component {
-}
+export default class JobSubnav extends Component {}
diff --git a/ui/app/components/job-version.js b/ui/app/components/job-version.js
index d3ba75a75..3e5ad74af 100644
--- a/ui/app/components/job-version.js
+++ b/ui/app/components/job-version.js
@@ -31,7 +31,9 @@ export default class JobVersion extends Component {
return (
fieldChanges(diff) +
taskGroups.reduce(arrayOfFieldChanges, 0) +
- (taskGroups.mapBy('Tasks') || []).reduce(flatten, []).reduce(arrayOfFieldChanges, 0)
+ (taskGroups.mapBy('Tasks') || [])
+ .reduce(flatten, [])
+ .reduce(arrayOfFieldChanges, 0)
);
}
@@ -45,7 +47,7 @@ export default class JobVersion extends Component {
this.toggleProperty('isOpen');
}
- @task(function*() {
+ @task(function* () {
try {
const versionBeforeReversion = this.get('version.job.version');
@@ -58,7 +60,8 @@ export default class JobVersion extends Component {
this.handleError({
level: 'warn',
title: 'Reversion Had No Effect',
- description: 'Reverting to an identical older version doesn’t produce a new version',
+ description:
+ 'Reverting to an identical older version doesn’t produce a new version',
});
} else {
const job = this.get('version.job');
@@ -79,7 +82,8 @@ export default class JobVersion extends Component {
}
const flatten = (accumulator, array) => accumulator.concat(array);
-const countChanges = (total, field) => (changeTypes.includes(field.Type) ? total + 1 : total);
+const countChanges = (total, field) =>
+ changeTypes.includes(field.Type) ? total + 1 : total;
function fieldChanges(diff) {
return (
diff --git a/ui/app/components/job-versions-stream.js b/ui/app/components/job-versions-stream.js
index 5497565e5..88f7e9668 100644
--- a/ui/app/components/job-versions-stream.js
+++ b/ui/app/components/job-versions-stream.js
@@ -24,7 +24,9 @@ export default class JobVersionsStream extends Component {
meta.showDate = true;
} else {
const previousVersion = versions.objectAt(index - 1);
- const previousStart = moment(previousVersion.get('submitTime')).startOf('day');
+ const previousStart = moment(previousVersion.get('submitTime')).startOf(
+ 'day'
+ );
const currentStart = moment(version.get('submitTime')).startOf('day');
if (previousStart.diff(currentStart, 'days') > 0) {
meta.showDate = true;
diff --git a/ui/app/components/lifecycle-chart.js b/ui/app/components/lifecycle-chart.js
index 07a938109..6e2f6116a 100644
--- a/ui/app/components/lifecycle-chart.js
+++ b/ui/app/components/lifecycle-chart.js
@@ -22,7 +22,7 @@ export default class LifecycleChart extends Component {
mains: [],
};
- tasksOrStates.forEach(taskOrState => {
+ tasksOrStates.forEach((taskOrState) => {
const task = taskOrState.task || taskOrState;
if (task.lifecycleName) {
@@ -31,7 +31,7 @@ export default class LifecycleChart extends Component {
});
const phases = [];
- const stateActiveIterator = state => state.state === 'running';
+ const stateActiveIterator = (state) => state.state === 'running';
if (lifecycles.mains.length < tasksOrStates.length) {
phases.push({
@@ -60,12 +60,12 @@ export default class LifecycleChart extends Component {
return phases;
}
- @sort('taskStates', function(a, b) {
+ @sort('taskStates', function (a, b) {
return getTaskSortPrefix(a.task).localeCompare(getTaskSortPrefix(b.task));
})
sortedLifecycleTaskStates;
- @sort('tasks', function(a, b) {
+ @sort('tasks', function (a, b) {
return getTaskSortPrefix(a).localeCompare(getTaskSortPrefix(b));
})
sortedLifecycleTasks;
diff --git a/ui/app/components/line-chart.js b/ui/app/components/line-chart.js
index e9d7e08b5..8f7bb19f1 100644
--- a/ui/app/components/line-chart.js
+++ b/ui/app/components/line-chart.js
@@ -23,11 +23,11 @@ const lerp = ([low, high], numPoints) => {
};
// Round a number or an array of numbers
-const nice = val => (val instanceof Array ? val.map(nice) : Math.round(val));
+const nice = (val) => (val instanceof Array ? val.map(nice) : Math.round(val));
const defaultXScale = (data, yAxisOffset, xProp, timeseries) => {
const scale = timeseries ? d3Scale.scaleTime() : d3Scale.scaleLinear();
- const domain = data.length ? d3Array.extent(data, d => d[xProp]) : [0, 1];
+ const domain = data.length ? d3Array.extent(data, (d) => d[xProp]) : [0, 1];
scale.rangeRound([10, yAxisOffset]).domain(domain);
@@ -35,15 +35,12 @@ const defaultXScale = (data, yAxisOffset, xProp, timeseries) => {
};
const defaultYScale = (data, xAxisOffset, yProp) => {
- let max = d3Array.max(data, d => d[yProp]) || 1;
+ let max = d3Array.max(data, (d) => d[yProp]) || 1;
if (max > 1) {
max = nice(max);
}
- return d3Scale
- .scaleLinear()
- .rangeRound([xAxisOffset, 10])
- .domain([0, max]);
+ return d3Scale.scaleLinear().rangeRound([xAxisOffset, 10]).domain([0, max]);
};
export default class LineChart extends Component {
@@ -95,7 +92,9 @@ export default class LineChart extends Component {
@action
xFormat(timeseries) {
if (this.args.xFormat) return this.args.xFormat;
- return timeseries ? d3TimeFormat.timeFormat('%b %d, %H:%M') : d3Format.format(',');
+ return timeseries
+ ? d3TimeFormat.timeFormat('%b %d, %H:%M')
+ : d3Format.format(',');
}
@action
@@ -134,7 +133,7 @@ export default class LineChart extends Component {
get xRange() {
const { xProp, data } = this;
- const range = d3Array.extent(data, d => d[xProp]);
+ const range = d3Array.extent(data, (d) => d[xProp]);
const formatter = this.xFormat(this.args.timeseries);
return range.map(formatter);
@@ -142,7 +141,7 @@ export default class LineChart extends Component {
get yRange() {
const yProp = this.yProp;
- const range = d3Array.extent(this.data, d => d[yProp]);
+ const range = d3Array.extent(this.data, (d) => d[yProp]);
const formatter = this.yFormat();
return range.map(formatter);
@@ -232,14 +231,14 @@ export default class LineChart extends Component {
const updateActiveDatum = this.updateActiveDatum.bind(this);
const chart = this;
- canvas.on('mouseenter', function(ev) {
+ canvas.on('mouseenter', function (ev) {
const mouseX = d3.pointer(ev, this)[0];
chart.latestMouseX = mouseX;
updateActiveDatum(mouseX);
run.schedule('afterRender', chart, () => (chart.isActive = true));
});
- canvas.on('mousemove', function(ev) {
+ canvas.on('mousemove', function (ev) {
const mouseX = d3.pointer(ev, this)[0];
chart.latestMouseX = mouseX;
updateActiveDatum(mouseX);
@@ -264,7 +263,7 @@ export default class LineChart extends Component {
}
// Map screen coordinates to data domain
- const bisector = d3Array.bisector(d => d[xProp]).left;
+ const bisector = d3Array.bisector((d) => d[xProp]).left;
const x = xScale.invert(mouseX);
// Find the closest datum to the cursor for each series
@@ -308,13 +307,17 @@ export default class LineChart extends Component {
// Of the selected data, determine which is closest
const closestDatum = activeData
.slice()
- .sort((a, b) => Math.abs(a.datum.datum[xProp] - x) - Math.abs(b.datum.datum[xProp] - x))[0];
+ .sort(
+ (a, b) =>
+ Math.abs(a.datum.datum[xProp] - x) -
+ Math.abs(b.datum.datum[xProp] - x)
+ )[0];
// If any other selected data are beyond a distance threshold, drop them from the list
// xScale is used here to measure distance in screen-space rather than data-space.
const dist = Math.abs(xScale(closestDatum.datum.datum[xProp]) - mouseX);
const filteredData = activeData.filter(
- d => Math.abs(xScale(d.datum.datum[xProp]) - mouseX) < dist + 10
+ (d) => Math.abs(xScale(d.datum.datum[xProp]) - mouseX) < dist + 10
);
this.activeData = filteredData;
@@ -351,7 +354,9 @@ export default class LineChart extends Component {
if (!this.isDestroyed && !this.isDestroying) {
d3.select(this.element.querySelector('.x-axis')).call(this.xAxis);
d3.select(this.element.querySelector('.y-axis')).call(this.yAxis);
- d3.select(this.element.querySelector('.y-gridlines')).call(this.yGridlines);
+ d3.select(this.element.querySelector('.y-gridlines')).call(
+ this.yGridlines
+ );
}
}
diff --git a/ui/app/components/list-accordion.js b/ui/app/components/list-accordion.js
index 9674d7a15..030c6f02a 100644
--- a/ui/app/components/list-accordion.js
+++ b/ui/app/components/list-accordion.js
@@ -20,7 +20,7 @@ export default class ListAccordion extends Component {
const deepKey = `item.${key}`;
const startExpanded = this.startExpanded;
- const decoratedSource = this.source.map(item => {
+ const decoratedSource = this.source.map((item) => {
const cacheItem = stateCache.findBy(deepKey, get(item, key));
return {
item,
diff --git a/ui/app/components/list-table.js b/ui/app/components/list-table.js
index aa9c8fad6..a5851040f 100644
--- a/ui/app/components/list-table.js
+++ b/ui/app/components/list-table.js
@@ -13,7 +13,7 @@ export default class ListTable extends Component {
// Plan for a future with metadata (e.g., isSelected)
@computed('source.[]')
get decoratedSource() {
- return (this.source || []).map(row => ({
+ return (this.source || []).map((row) => ({
model: row,
}));
}
diff --git a/ui/app/components/multi-select-dropdown.js b/ui/app/components/multi-select-dropdown.js
index a2783f736..692ea7c9f 100644
--- a/ui/app/components/multi-select-dropdown.js
+++ b/ui/app/components/multi-select-dropdown.js
@@ -30,6 +30,7 @@ export default class MultiSelectDropdown extends Component {
}
didReceiveAttrs() {
+ super.didReceiveAttrs();
const dropdown = this.dropdown;
if (this.isOpen && dropdown) {
run.scheduleOnce('afterRender', this, this.repositionDropdown);
@@ -59,8 +60,12 @@ export default class MultiSelectDropdown extends Component {
dropdown.actions.open(e);
e.preventDefault();
} else if (this.isOpen && (e.keyCode === TAB || e.keyCode === ARROW_DOWN)) {
- const optionsId = this.element.querySelector('.dropdown-trigger').getAttribute('aria-owns');
- const firstElement = document.querySelector(`#${optionsId} .dropdown-option`);
+ const optionsId = this.element
+ .querySelector('.dropdown-trigger')
+ .getAttribute('aria-owns');
+ const firstElement = document.querySelector(
+ `#${optionsId} .dropdown-option`
+ );
if (firstElement) {
firstElement.focus();
diff --git a/ui/app/components/popover-menu.js b/ui/app/components/popover-menu.js
index 939e940b7..a6498a9aa 100644
--- a/ui/app/components/popover-menu.js
+++ b/ui/app/components/popover-menu.js
@@ -32,6 +32,7 @@ export default class PopoverMenu extends Component {
}
didReceiveAttrs() {
+ super.didReceiveAttrs();
const dropdown = this.dropdown;
if (this.isOpen && dropdown) {
run.scheduleOnce('afterRender', this, this.repositionDropdown);
@@ -48,7 +49,9 @@ export default class PopoverMenu extends Component {
dropdown.actions.open(e);
e.preventDefault();
} else if (this.isOpen && (e.keyCode === TAB || e.keyCode === ARROW_DOWN)) {
- const optionsId = this.element.querySelector('.popover-trigger').getAttribute('aria-owns');
+ const optionsId = this.element
+ .querySelector('.popover-trigger')
+ .getAttribute('aria-owns');
const popoverContentEl = document.querySelector(`#${optionsId}`);
const firstFocusableElement = popoverContentEl.querySelector(FOCUSABLE);
diff --git a/ui/app/components/primary-metric/allocation.js b/ui/app/components/primary-metric/allocation.js
index d57c58d01..96da05a97 100644
--- a/ui/app/components/primary-metric/allocation.js
+++ b/ui/app/components/primary-metric/allocation.js
@@ -37,7 +37,7 @@ export default class AllocationPrimaryMetric extends Component {
@computed('tracker.tasks.[]', 'metric')
get series() {
const ret = this.tracker.tasks
- .map(task => ({
+ .map((task) => ({
name: task.task,
data: task[this.metric],
}))
@@ -64,7 +64,7 @@ export default class AllocationPrimaryMetric extends Component {
return 'ordinal';
}
- @task(function*() {
+ @task(function* () {
do {
this.tracker.poll.perform();
yield timeout(100);
@@ -78,6 +78,7 @@ export default class AllocationPrimaryMetric extends Component {
}
willDestroy() {
+ super.willDestroy(...arguments);
this.poller.cancelAll();
this.tracker.signalPause.perform();
}
diff --git a/ui/app/components/primary-metric/node.js b/ui/app/components/primary-metric/node.js
index 781d3e38e..a4a7102b9 100644
--- a/ui/app/components/primary-metric/node.js
+++ b/ui/app/components/primary-metric/node.js
@@ -4,7 +4,10 @@ import { task, timeout } from 'ember-concurrency';
import { assert } from '@ember/debug';
import { inject as service } from '@ember/service';
import { action, get } from '@ember/object';
-import { formatScheduledBytes, formatScheduledHertz } from 'nomad-ui/utils/units';
+import {
+ formatScheduledBytes,
+ formatScheduledHertz,
+} from 'nomad-ui/utils/units';
export default class NodePrimaryMetric extends Component {
@service('stats-trackers-registry') statsTrackersRegistry;
@@ -64,7 +67,7 @@ export default class NodePrimaryMetric extends Component {
return [];
}
- @task(function*() {
+ @task(function* () {
do {
this.tracker.poll.perform();
yield timeout(100);
@@ -78,6 +81,7 @@ export default class NodePrimaryMetric extends Component {
}
willDestroy() {
+ super.willDestroy(...arguments);
this.poller.cancelAll();
this.tracker.signalPause.perform();
}
diff --git a/ui/app/components/primary-metric/task.js b/ui/app/components/primary-metric/task.js
index b7c348d04..20d987caf 100644
--- a/ui/app/components/primary-metric/task.js
+++ b/ui/app/components/primary-metric/task.js
@@ -42,7 +42,7 @@ export default class TaskPrimaryMetric extends Component {
return 'is-primary';
}
- @task(function*() {
+ @task(function* () {
do {
this.tracker.poll.perform();
yield timeout(100);
@@ -53,11 +53,14 @@ export default class TaskPrimaryMetric extends Component {
@action
start() {
this.taskState = this.args.taskState;
- this.tracker = this.statsTrackersRegistry.getTracker(this.args.taskState.allocation);
+ this.tracker = this.statsTrackersRegistry.getTracker(
+ this.args.taskState.allocation
+ );
this.poller.perform();
}
willDestroy() {
+ super.willDestroy(...arguments);
this.poller.cancelAll();
this.tracker.signalPause.perform();
}
diff --git a/ui/app/components/region-switcher.js b/ui/app/components/region-switcher.js
index 34fc3c98e..e99aec7ab 100644
--- a/ui/app/components/region-switcher.js
+++ b/ui/app/components/region-switcher.js
@@ -11,9 +11,7 @@ export default class RegionSwitcher extends Component {
@computed('system.regions')
get sortedRegions() {
- return this.get('system.regions')
- .toArray()
- .sort();
+ return this.get('system.regions').toArray().sort();
}
gotoRegion(region) {
diff --git a/ui/app/components/reschedule-event-row.js b/ui/app/components/reschedule-event-row.js
index e6a187478..30eee17c2 100644
--- a/ui/app/components/reschedule-event-row.js
+++ b/ui/app/components/reschedule-event-row.js
@@ -13,7 +13,7 @@ export default class RescheduleEventRow extends Component {
allocationId = null;
// An allocation can also be provided directly
- @overridable('allocationId', function() {
+ @overridable('allocationId', function () {
if (this.allocationId) {
return this.store.findRecord('allocation', this.allocationId);
}
diff --git a/ui/app/components/scale-events-chart.js b/ui/app/components/scale-events-chart.js
index f45509319..8a687f139 100644
--- a/ui/app/components/scale-events-chart.js
+++ b/ui/app/components/scale-events-chart.js
@@ -32,7 +32,7 @@ export default class ScaleEventsChart extends Component {
}
get annotations() {
- return this.args.events.rejectBy('hasCount').map(ev => ({
+ return this.args.events.rejectBy('hasCount').map((ev) => ({
type: ev.error ? 'error' : 'info',
time: ev.time,
event: copy(ev),
@@ -40,7 +40,10 @@ export default class ScaleEventsChart extends Component {
}
toggleEvent(ev) {
- if (this.activeEvent && get(this.activeEvent, 'event.uid') === get(ev, 'event.uid')) {
+ if (
+ this.activeEvent &&
+ get(this.activeEvent, 'event.uid') === get(ev, 'event.uid')
+ ) {
this.closeEventDetails();
} else {
this.activeEvent = ev;
diff --git a/ui/app/components/server-agent-row.js b/ui/app/components/server-agent-row.js
index 3c5ee4632..e0cc0ede2 100644
--- a/ui/app/components/server-agent-row.js
+++ b/ui/app/components/server-agent-row.js
@@ -3,7 +3,11 @@ import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import { computed } from '@ember/object';
import { lazyClick } from '../helpers/lazy-click';
-import { classNames, classNameBindings, tagName } from '@ember-decorators/component';
+import {
+ classNames,
+ classNameBindings,
+ tagName,
+} from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
@classic
@@ -38,7 +42,8 @@ export default class ServerAgentRow extends Component {
}
click() {
- const transition = () => this.router.transitionTo('servers.server', this.agent);
+ const transition = () =>
+ this.router.transitionTo('servers.server', this.agent);
lazyClick([transition, event]);
}
}
diff --git a/ui/app/components/stats-time-series.js b/ui/app/components/stats-time-series.js
index 6df134b3a..f530fb7af 100644
--- a/ui/app/components/stats-time-series.js
+++ b/ui/app/components/stats-time-series.js
@@ -22,8 +22,8 @@ export default class StatsTimeSeries extends Component {
// Specific a11y descriptors
get description() {
const data = this.args.data;
- const yRange = d3Array.extent(data, d => d.percent);
- const xRange = d3Array.extent(data, d => d.timestamp);
+ const yRange = d3Array.extent(data, (d) => d.percent);
+ const xRange = d3Array.extent(data, (d) => d.timestamp);
const yFormatter = this.yFormat;
const duration = formatDuration(xRange[1] - xRange[0], 'ms', true);
@@ -36,19 +36,21 @@ export default class StatsTimeSeries extends Component {
xScale(data, yAxisOffset) {
const scale = scaleTime();
- const [low, high] = d3Array.extent(data, d => d.timestamp);
- const minLow = moment(high)
- .subtract(5, 'minutes')
- .toDate();
+ const [low, high] = d3Array.extent(data, (d) => d.timestamp);
+ const minLow = moment(high).subtract(5, 'minutes').toDate();
- const extent = data.length ? [Math.min(low, minLow), high] : [minLow, new Date()];
+ const extent = data.length
+ ? [Math.min(low, minLow), high]
+ : [minLow, new Date()];
scale.rangeRound([10, yAxisOffset]).domain(extent);
return scale;
}
yScale(data, xAxisOffset) {
- const yValues = (data || []).mapBy(this.args.dataProp ? 'percentStack' : 'percent');
+ const yValues = (data || []).mapBy(
+ this.args.dataProp ? 'percentStack' : 'percent'
+ );
let [low, high] = [0, 1];
if (yValues.compact().length) {
diff --git a/ui/app/components/stepper-input.js b/ui/app/components/stepper-input.js
index 8509c3534..f1993144c 100644
--- a/ui/app/components/stepper-input.js
+++ b/ui/app/components/stepper-input.js
@@ -9,7 +9,12 @@ const ESC = 27;
@classic
@classNames('stepper-input')
-@classNameBindings('class', 'disabled:is-disabled', 'disabled:tooltip', 'disabled:multiline')
+@classNameBindings(
+ 'class',
+ 'disabled:is-disabled',
+ 'disabled:tooltip',
+ 'disabled:multiline'
+)
export default class StepperInput extends Component {
min = 0;
max = 10;
@@ -41,7 +46,9 @@ export default class StepperInput extends Component {
@action
setValue(e) {
if (e.target.value !== '') {
- const newValue = Math.floor(Math.min(this.max, Math.max(this.min, e.target.value)));
+ const newValue = Math.floor(
+ Math.min(this.max, Math.max(this.min, e.target.value))
+ );
this.set('internalValue', newValue);
this.update(this.internalValue);
} else {
diff --git a/ui/app/components/streaming-file.js b/ui/app/components/streaming-file.js
index 9d82dda50..b19dea125 100644
--- a/ui/app/components/streaming-file.js
+++ b/ui/app/components/streaming-file.js
@@ -22,6 +22,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
requestFrame = true;
didReceiveAttrs() {
+ super.didReceiveAttrs();
if (!this.logger) {
return;
}
@@ -58,7 +59,10 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
if (this.requestFrame) {
window.requestAnimationFrame(() => {
// If the scroll position is close enough to the bottom, autoscroll to the bottom
- this.set('follow', cli.scrollHeight - cli.scrollTop - cli.clientHeight < 20);
+ this.set(
+ 'follow',
+ cli.scrollHeight - cli.scrollTop - cli.clientHeight < 20
+ );
this.requestFrame = true;
});
}
@@ -79,6 +83,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
}
didInsertElement() {
+ super.didInsertElement(...arguments);
this.fillAvailableHeight();
this.set('_scrollHandler', this.scrollHandler.bind(this));
@@ -89,6 +94,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
}
willDestroyElement() {
+ super.willDestroyElement(...arguments);
this.element.removeEventListener('scroll', this._scrollHandler);
document.removeEventListener('keydown', this._keyDownHandler);
}
@@ -102,10 +108,12 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
// of having the log window fill available height is worth the hack.
const margins = 30; // Account for padding and margin on either side of the CLI
const cliWindow = this.element;
- cliWindow.style.height = `${window.innerHeight - cliWindow.offsetTop - margins}px`;
+ cliWindow.style.height = `${
+ window.innerHeight - cliWindow.offsetTop - margins
+ }px`;
}
- @task(function*() {
+ @task(function* () {
yield this.get('logger.gotoHead').perform();
run.scheduleOnce('afterRender', this, this.scrollToTop);
})
@@ -115,7 +123,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
this.element.scrollTop = 0;
}
- @task(function*() {
+ @task(function* () {
yield this.get('logger.gotoTail').perform();
})
tail;
@@ -126,7 +134,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
}
}
- @task(function*() {
+ @task(function* () {
// Follow the log if the scroll position is near the bottom of the cli window
this.logger.on('tick', this, 'scheduleScrollSynchronization');
@@ -140,6 +148,7 @@ export default class StreamingFile extends Component.extend(WindowResizable) {
}
willDestroy() {
+ super.willDestroy(...arguments);
this.logger.stop();
}
}
diff --git a/ui/app/components/task-group-row.js b/ui/app/components/task-group-row.js
index 57d9e9336..3346fe8be 100644
--- a/ui/app/components/task-group-row.js
+++ b/ui/app/components/task-group-row.js
@@ -27,7 +27,8 @@ export default class TaskGroupRow extends Component {
get tooltipText() {
if (this.can.cannot('scale job', null, { namespace: this.namespace }))
return "You aren't allowed to scale task groups";
- if (this.runningDeployment) return 'You cannot scale task groups during a deployment';
+ if (this.runningDeployment)
+ return 'You cannot scale task groups during a deployment';
return undefined;
}
diff --git a/ui/app/components/task-log.js b/ui/app/components/task-log.js
index fc744129d..2ed7325d0 100644
--- a/ui/app/components/task-log.js
+++ b/ui/app/components/task-log.js
@@ -58,21 +58,23 @@ export default class TaskLog extends Component {
// If the log request can't settle in one second, the client
// must be unavailable and the server should be used instead
- const aborter = window.AbortController ? new AbortController() : new MockAbortController();
+ const aborter = window.AbortController
+ ? new AbortController()
+ : new MockAbortController();
const timing = this.useServer ? this.serverTimeout : this.clientTimeout;
// Capture the state of useServer at logger create time to avoid a race
// between the stdout logger and stderr logger running at once.
const useServer = this.useServer;
- return url =>
+ return (url) =>
RSVP.race([
this.token.authorizedRequest(url, { signal: aborter.signal }),
timeout(timing),
]).then(
- response => {
+ (response) => {
return response;
},
- error => {
+ (error) => {
aborter.abort();
if (useServer) {
this.set('noConnection', true);
diff --git a/ui/app/components/task-row.js b/ui/app/components/task-row.js
index e47ff8588..63183a57a 100644
--- a/ui/app/components/task-row.js
+++ b/ui/app/components/task-row.js
@@ -50,13 +50,11 @@ export default class TaskRow extends Component {
lazyClick([this.onClick, event]);
}
- @(task(function*() {
+ @(task(function* () {
do {
if (this.stats) {
try {
- yield this.get('stats.poll')
- .linked()
- .perform();
+ yield this.get('stats.poll').linked().perform();
this.set('statsError', false);
} catch (error) {
this.set('statsError', true);
@@ -69,6 +67,7 @@ export default class TaskRow extends Component {
fetchStats;
didReceiveAttrs() {
+ super.didReceiveAttrs();
const allocation = this.get('task.allocation');
if (allocation) {
diff --git a/ui/app/components/toggle.js b/ui/app/components/toggle.js
index 6701f64f9..efa1ed87d 100644
--- a/ui/app/components/toggle.js
+++ b/ui/app/components/toggle.js
@@ -1,5 +1,9 @@
import Component from '@ember/component';
-import { classNames, classNameBindings, tagName } from '@ember-decorators/component';
+import {
+ classNames,
+ classNameBindings,
+ tagName,
+} from '@ember-decorators/component';
import classic from 'ember-classic-decorator';
@classic
diff --git a/ui/app/components/tooltip.js b/ui/app/components/tooltip.js
index fa1420c62..a9fb3120c 100644
--- a/ui/app/components/tooltip.js
+++ b/ui/app/components/tooltip.js
@@ -8,7 +8,9 @@ export default class Tooltip extends Component {
}
const prefix = inputText.substr(0, 15).trim();
- const suffix = inputText.substr(inputText.length - 10, inputText.length).trim();
+ const suffix = inputText
+ .substr(inputText.length - 10, inputText.length)
+ .trim();
return `${prefix}...${suffix}`;
}
}
diff --git a/ui/app/components/topo-viz.js b/ui/app/components/topo-viz.js
index 9c9ac0fab..48faa6b7f 100644
--- a/ui/app/components/topo-viz.js
+++ b/ui/app/components/topo-viz.js
@@ -26,11 +26,14 @@ export default class TopoViz extends Component {
@styleStringProperty('tooltipProps') tooltipStyle;
get isSingleColumn() {
- if (this.topology.datacenters.length <= 1 || this.viewportColumns === 1) return true;
+ if (this.topology.datacenters.length <= 1 || this.viewportColumns === 1)
+ return true;
// Compute the coefficient of variance to determine if it would be
// better to stack datacenters or place them in columns
- const nodeCounts = this.topology.datacenters.map(datacenter => datacenter.nodes.length);
+ const nodeCounts = this.topology.datacenters.map(
+ (datacenter) => datacenter.nodes.length
+ );
const variationCoefficient = deviation(nodeCounts) / mean(nodeCounts);
// The point at which the varation is too extreme for a two column layout
@@ -43,7 +46,10 @@ export default class TopoViz extends Component {
// If there are enough nodes, use two columns of nodes within
// a single column layout of datacenters to increase density.
if (this.viewportColumns === 1) return true;
- return !this.isSingleColumn || (this.isSingleColumn && this.args.nodes.length <= 20);
+ return (
+ !this.isSingleColumn ||
+ (this.isSingleColumn && this.args.nodes.length <= 20)
+ );
}
// Once a cluster is large enough, the exact details of a node are
@@ -89,7 +95,7 @@ export default class TopoViz extends Component {
// Wrap nodes in a topo viz specific data structure and build an index to speed up allocation assignment
const nodeContainers = [];
const nodeIndex = {};
- nodes.forEach(node => {
+ nodes.forEach((node) => {
if (!node.resources) {
badNodes.push(node);
return;
@@ -103,14 +109,17 @@ export default class TopoViz extends Component {
// Wrap allocations in a topo viz specific data structure, assign allocations to nodes, and build an allocation
// index keyed off of job and task group
const allocationIndex = {};
- allocations.forEach(allocation => {
+ allocations.forEach((allocation) => {
const nodeId = allocation.belongsTo('node').id();
const nodeContainer = nodeIndex[nodeId];
// Ignore orphaned allocations and allocations on nodes with an old Nomad agent version.
if (!nodeContainer) return;
- const allocationContainer = this.dataForAllocation(allocation, nodeContainer);
+ const allocationContainer = this.dataForAllocation(
+ allocation,
+ nodeContainer
+ );
nodeContainer.allocations.push(allocationContainer);
const key = allocationContainer.groupKey;
@@ -119,15 +128,19 @@ export default class TopoViz extends Component {
});
// Group nodes into datacenters
- const datacentersMap = nodeContainers.reduce((datacenters, nodeContainer) => {
- if (!datacenters[nodeContainer.datacenter]) datacenters[nodeContainer.datacenter] = [];
- datacenters[nodeContainer.datacenter].push(nodeContainer);
- return datacenters;
- }, {});
+ const datacentersMap = nodeContainers.reduce(
+ (datacenters, nodeContainer) => {
+ if (!datacenters[nodeContainer.datacenter])
+ datacenters[nodeContainer.datacenter] = [];
+ datacenters[nodeContainer.datacenter].push(nodeContainer);
+ return datacenters;
+ },
+ {}
+ );
// Turn hash of datacenters into a sorted array
const datacenters = Object.keys(datacentersMap)
- .map(key => ({ name: key, nodes: datacentersMap[key] }))
+ .map((key) => ({ name: key, nodes: datacentersMap[key] }))
.sortBy('name');
const topology = {
@@ -191,9 +204,10 @@ export default class TopoViz extends Component {
this.activeEdges = [];
if (this.topology.selectedKey) {
- const selectedAllocations = this.topology.allocationIndex[this.topology.selectedKey];
+ const selectedAllocations =
+ this.topology.allocationIndex[this.topology.selectedKey];
if (selectedAllocations) {
- selectedAllocations.forEach(allocation => {
+ selectedAllocations.forEach((allocation) => {
set(allocation, 'isSelected', false);
});
}
@@ -205,30 +219,37 @@ export default class TopoViz extends Component {
}
this.activeNode = null;
this.activeAllocation = allocation;
- const selectedAllocations = this.topology.allocationIndex[this.topology.selectedKey];
+ const selectedAllocations =
+ this.topology.allocationIndex[this.topology.selectedKey];
if (selectedAllocations) {
- selectedAllocations.forEach(allocation => {
+ selectedAllocations.forEach((allocation) => {
set(allocation, 'isSelected', false);
});
}
set(this.topology, 'selectedKey', allocation.groupKey);
- const newAllocations = this.topology.allocationIndex[this.topology.selectedKey];
+ const newAllocations =
+ this.topology.allocationIndex[this.topology.selectedKey];
if (newAllocations) {
- newAllocations.forEach(allocation => {
+ newAllocations.forEach((allocation) => {
set(allocation, 'isSelected', true);
});
}
// Only show the lines if the selected allocations are sparse (low count relative to the client count or low count generally).
- if (newAllocations.length < 10 || newAllocations.length < this.args.nodes.length * 0.75) {
+ if (
+ newAllocations.length < 10 ||
+ newAllocations.length < this.args.nodes.length * 0.75
+ ) {
this.computedActiveEdges();
} else {
this.activeEdges = [];
}
}
if (this.args.onAllocationSelect)
- this.args.onAllocationSelect(this.activeAllocation && this.activeAllocation.allocation);
+ this.args.onAllocationSelect(
+ this.activeAllocation && this.activeAllocation.allocation
+ );
if (this.args.onNodeSelect) this.args.onNodeSelect(this.activeNode);
}
@@ -251,24 +272,28 @@ export default class TopoViz extends Component {
const path = line().curve(curveBasis);
// 1. Get the active element
const allocation = this.activeAllocation.allocation;
- const activeEl = this.element.querySelector(`[data-allocation-id="${allocation.id}"]`);
+ const activeEl = this.element.querySelector(
+ `[data-allocation-id="${allocation.id}"]`
+ );
const activePoint = centerOfBBox(activeEl.getBoundingClientRect());
// 2. Collect the mem and cpu pairs for all selected allocs
- const selectedMem = Array.from(this.element.querySelectorAll('.memory .bar.is-selected'));
- const selectedPairs = selectedMem.map(mem => {
+ const selectedMem = Array.from(
+ this.element.querySelectorAll('.memory .bar.is-selected')
+ );
+ const selectedPairs = selectedMem.map((mem) => {
const id = mem.closest('[data-allocation-id]').dataset.allocationId;
const cpu = mem
.closest('.topo-viz-node')
.querySelector(`.cpu .bar[data-allocation-id="${id}"]`);
return [mem, cpu];
});
- const selectedPoints = selectedPairs.map(pair => {
- return pair.map(el => centerOfBBox(el.getBoundingClientRect()));
+ const selectedPoints = selectedPairs.map((pair) => {
+ return pair.map((el) => centerOfBBox(el.getBoundingClientRect()));
});
// 3. For each pair, compute the midpoint of the truncated triangle of points [Mem, Cpu, Active]
- selectedPoints.forEach(points => {
+ selectedPoints.forEach((points) => {
const d1 = pointBetween(points[0], activePoint, 100, 0.5);
const d2 = pointBetween(points[1], activePoint, 100, 0.5);
points.push(midpoint(d1, d2));
@@ -281,14 +306,20 @@ export default class TopoViz extends Component {
const stepsMain = [0, 0.8, 1.0];
// The second prong the fork does not need to retrace the entire path from the activePoint
const stepsSecondary = [0.8, 1.0];
- selectedPoints.forEach(points => {
+ selectedPoints.forEach((points) => {
curves.push(
- curveFromPoints(...pointsAlongPath(activePoint, points[2], stepsMain), points[0]),
- curveFromPoints(...pointsAlongPath(activePoint, points[2], stepsSecondary), points[1])
+ curveFromPoints(
+ ...pointsAlongPath(activePoint, points[2], stepsMain),
+ points[0]
+ ),
+ curveFromPoints(
+ ...pointsAlongPath(activePoint, points[2], stepsSecondary),
+ points[1]
+ )
);
});
- this.activeEdges = curves.map(curve => path(curve));
+ this.activeEdges = curves.map((curve) => path(curve));
this.edgeOffset = { x: window.scrollX, y: window.scrollY };
});
}
@@ -319,7 +350,7 @@ function pointBetweenPct(p1, p2, pct) {
}
function pointsAlongPath(p1, p2, pcts) {
- return pcts.map(pct => pointBetweenPct(p1, p2, pct));
+ return pcts.map((pct) => pointBetweenPct(p1, p2, pct));
}
function midpoint(p1, p2) {
@@ -327,5 +358,5 @@ function midpoint(p1, p2) {
}
function curveFromPoints(...points) {
- return points.map(p => [p.x, p.y]);
+ return points.map((p) => [p.x, p.y]);
}
diff --git a/ui/app/components/topo-viz/datacenter.js b/ui/app/components/topo-viz/datacenter.js
index 0750fc1eb..965af2f77 100644
--- a/ui/app/components/topo-viz/datacenter.js
+++ b/ui/app/components/topo-viz/datacenter.js
@@ -3,7 +3,8 @@ import Component from '@glimmer/component';
export default class TopoVizDatacenter extends Component {
get scheduledAllocations() {
return this.args.datacenter.nodes.reduce(
- (all, node) => all.concat(node.allocations.filterBy('allocation.isScheduled')),
+ (all, node) =>
+ all.concat(node.allocations.filterBy('allocation.isScheduled')),
[]
);
}
diff --git a/ui/app/components/topo-viz/node.js b/ui/app/components/topo-viz/node.js
index 43ed0da90..400b69c0b 100644
--- a/ui/app/components/topo-viz/node.js
+++ b/ui/app/components/topo-viz/node.js
@@ -10,7 +10,9 @@ export default class TopoVizNode extends Component {
@tracked activeAllocation = null;
get height() {
- return this.args.heightScale ? this.args.heightScale(this.args.node.memory) : 15;
+ return this.args.heightScale
+ ? this.args.heightScale(this.args.node.memory)
+ : 15;
}
get labelHeight() {
@@ -57,11 +59,13 @@ export default class TopoVizNode extends Component {
get allocations() {
// Sort by the delta between memory and cpu percent. This creates the least amount of
// drift between the positional alignment of an alloc's cpu and memory representations.
- return this.args.node.allocations.filterBy('allocation.isScheduled').sort((a, b) => {
- const deltaA = Math.abs(a.memoryPercent - a.cpuPercent);
- const deltaB = Math.abs(b.memoryPercent - b.cpuPercent);
- return deltaA - deltaB;
- });
+ return this.args.node.allocations
+ .filterBy('allocation.isScheduled')
+ .sort((a, b) => {
+ const deltaA = Math.abs(a.memoryPercent - a.cpuPercent);
+ const deltaB = Math.abs(b.memoryPercent - b.cpuPercent);
+ return deltaA - deltaB;
+ });
}
@action
@@ -91,7 +95,8 @@ export default class TopoVizNode extends Component {
@action
highlightAllocation(allocation, { target }) {
this.activeAllocation = allocation;
- this.args.onAllocationFocus && this.args.onAllocationFocus(allocation, target);
+ this.args.onAllocationFocus &&
+ this.args.onAllocationFocus(allocation, target);
}
@action
@@ -118,7 +123,7 @@ export default class TopoVizNode extends Component {
containsActiveTaskGroup() {
return this.args.node.allocations.some(
- allocation =>
+ (allocation) =>
allocation.taskGroupName === this.args.activeTaskGroup &&
allocation.belongsTo('job').id() === this.args.activeJobId
);
diff --git a/ui/app/components/trigger.js b/ui/app/components/trigger.js
index 17f981b87..d141e6c33 100644
--- a/ui/app/components/trigger.js
+++ b/ui/app/components/trigger.js
@@ -49,7 +49,7 @@ export default class Trigger extends Component {
this.error = null;
}
- @task(function*() {
+ @task(function* () {
this._reset();
try {
this.result = yield this.args.do();
diff --git a/ui/app/components/two-step-button.js b/ui/app/components/two-step-button.js
index 70ff34010..cd29dd8aa 100644
--- a/ui/app/components/two-step-button.js
+++ b/ui/app/components/two-step-button.js
@@ -9,7 +9,10 @@ import classic from 'ember-classic-decorator';
@classic
@classNames('two-step-button')
-@classNameBindings('inlineText:has-inline-text', 'fadingBackground:has-fading-background')
+@classNameBindings(
+ 'inlineText:has-inline-text',
+ 'fadingBackground:has-fading-background'
+)
export default class TwoStepButton extends Component {
idleText = '';
cancelText = '';
@@ -26,7 +29,7 @@ export default class TwoStepButton extends Component {
@equal('state', 'idle') isIdle;
@equal('state', 'prompt') isPendingConfirmation;
- @task(function*() {
+ @task(function* () {
while (true) {
let ev = yield waitForEvent(document.body, 'click');
if (!this.element.contains(ev.target) && !this.awaitingConfirmation) {
diff --git a/ui/app/controllers/allocations/allocation.js b/ui/app/controllers/allocations/allocation.js
index b29d7b6cb..142c9f3ff 100644
--- a/ui/app/controllers/allocations/allocation.js
+++ b/ui/app/controllers/allocations/allocation.js
@@ -35,7 +35,12 @@ export default class AllocationsAllocationController extends Controller {
{
title: 'Task Group',
label: allocation.taskGroupName,
- args: ['jobs.job.task-group', job.plainId, allocation.taskGroupName, jobQueryParams],
+ args: [
+ 'jobs.job.task-group',
+ job.plainId,
+ allocation.taskGroupName,
+ jobQueryParams,
+ ],
},
{
title: 'Allocation',
diff --git a/ui/app/controllers/allocations/allocation/index.js b/ui/app/controllers/allocations/allocation/index.js
index 4068de300..3fdc17216 100644
--- a/ui/app/controllers/allocations/allocation/index.js
+++ b/ui/app/controllers/allocations/allocation/index.js
@@ -34,7 +34,7 @@ export default class IndexController extends Controller.extend(Sortable) {
// Set in the route
preempter = null;
- @overridable(function() {
+ @overridable(function () {
// { title, description }
return null;
})
@@ -66,7 +66,7 @@ export default class IndexController extends Controller.extend(Sortable) {
}
}
- @task(function*() {
+ @task(function* () {
try {
yield this.model.stop();
// Eagerly update the allocation clientStatus to avoid flickering
@@ -80,7 +80,7 @@ export default class IndexController extends Controller.extend(Sortable) {
})
stopAllocation;
- @task(function*() {
+ @task(function* () {
try {
yield this.model.restart();
} catch (err) {
diff --git a/ui/app/controllers/allocations/allocation/task.js b/ui/app/controllers/allocations/allocation/task.js
index 3e3c9a034..7ebc8b67a 100644
--- a/ui/app/controllers/allocations/allocation/task.js
+++ b/ui/app/controllers/allocations/allocation/task.js
@@ -9,7 +9,11 @@ export default class AllocationsAllocationTaskController extends Controller {
return {
title: 'Task',
label: this.task.get('name'),
- args: ['allocations.allocation.task', this.task.get('allocation'), this.task],
+ args: [
+ 'allocations.allocation.task',
+ this.task.get('allocation'),
+ this.task,
+ ],
};
}
}
diff --git a/ui/app/controllers/allocations/allocation/task/index.js b/ui/app/controllers/allocations/allocation/task/index.js
index 73f0f208f..f880ece05 100644
--- a/ui/app/controllers/allocations/allocation/task/index.js
+++ b/ui/app/controllers/allocations/allocation/task/index.js
@@ -16,7 +16,7 @@ export default class IndexController extends Controller {
this.set('error', null);
}
- @task(function*() {
+ @task(function* () {
try {
yield this.model.restart();
} catch (err) {
diff --git a/ui/app/controllers/clients/client/index.js b/ui/app/controllers/clients/client/index.js
index bc4eeec79..6a9b2475c 100644
--- a/ui/app/controllers/clients/client/index.js
+++ b/ui/app/controllers/clients/client/index.js
@@ -10,11 +10,17 @@ import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
-export default class ClientController extends Controller.extend(Sortable, Searchable) {
+export default class ClientController extends Controller.extend(
+ Sortable,
+ Searchable
+) {
queryParams = [
{
currentPage: 'page',
@@ -66,18 +72,32 @@ export default class ClientController extends Controller.extend(Sortable, Search
return this.onlyPreemptions ? this.preemptions : this.model.allocations;
}
- @computed('visibleAllocations.[]', 'selectionNamespace', 'selectionJob', 'selectionStatus')
+ @computed(
+ 'visibleAllocations.[]',
+ 'selectionNamespace',
+ 'selectionJob',
+ 'selectionStatus'
+ )
get filteredAllocations() {
const { selectionNamespace, selectionJob, selectionStatus } = this;
- return this.visibleAllocations.filter(alloc => {
- if (selectionNamespace.length && !selectionNamespace.includes(alloc.get('namespace'))) {
+ return this.visibleAllocations.filter((alloc) => {
+ if (
+ selectionNamespace.length &&
+ !selectionNamespace.includes(alloc.get('namespace'))
+ ) {
return false;
}
- if (selectionJob.length && !selectionJob.includes(alloc.get('plainJobId'))) {
+ if (
+ selectionJob.length &&
+ !selectionJob.includes(alloc.get('plainJobId'))
+ ) {
return false;
}
- if (selectionStatus.length && !selectionStatus.includes(alloc.clientStatus)) {
+ if (
+ selectionStatus.length &&
+ !selectionStatus.includes(alloc.clientStatus)
+ ) {
return false;
}
return true;
@@ -106,9 +126,7 @@ export default class ClientController extends Controller.extend(Sortable, Search
@computed('model.events.@each.time')
get sortedEvents() {
- return this.get('model.events')
- .sortBy('time')
- .reverse();
+ return this.get('model.events').sortBy('time').reverse();
}
@computed('model.drivers.@each.name')
@@ -121,7 +139,7 @@ export default class ClientController extends Controller.extend(Sortable, Search
return this.model.hostVolumes.sortBy('name');
}
- @(task(function*(value) {
+ @(task(function* (value) {
try {
yield value ? this.model.setEligible() : this.model.setIneligible();
} catch (err) {
@@ -131,7 +149,7 @@ export default class ClientController extends Controller.extend(Sortable, Search
}).drop())
setEligibility;
- @(task(function*() {
+ @(task(function* () {
try {
this.set('flagAsDraining', false);
yield this.model.cancelDrain();
@@ -144,7 +162,7 @@ export default class ClientController extends Controller.extend(Sortable, Search
}).drop())
stopDrain;
- @(task(function*() {
+ @(task(function* () {
try {
yield this.model.forceDrain({
IgnoreSystemJobs: this.model.drainStrategy.ignoreSystemJobs,
@@ -203,7 +221,7 @@ export default class ClientController extends Controller.extend(Sortable, Search
const jobs = Array.from(
new Set(
this.model.allocations
- .filter(a => ns.length === 0 || ns.includes(a.namespace))
+ .filter((a) => ns.length === 0 || ns.includes(a.namespace))
.mapBy('plainJobId')
)
).compact();
@@ -214,20 +232,25 @@ export default class ClientController extends Controller.extend(Sortable, Search
this.set('qpJob', serialize(intersection(jobs, this.selectionJob)));
});
- return jobs.sort().map(job => ({ key: job, label: job }));
+ return jobs.sort().map((job) => ({ key: job, label: job }));
}
@computed('model.allocations.[]', 'selectionNamespace')
get optionsNamespace() {
- const ns = Array.from(new Set(this.model.allocations.mapBy('namespace'))).compact();
+ const ns = Array.from(
+ new Set(this.model.allocations.mapBy('namespace'))
+ ).compact();
// Update query param when the list of namespaces changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpNamespace', serialize(intersection(ns, this.selectionNamespace)));
+ this.set(
+ 'qpNamespace',
+ serialize(intersection(ns, this.selectionNamespace))
+ );
});
- return ns.sort().map(n => ({ key: n, label: n }));
+ return ns.sort().map((n) => ({ key: n, label: n }));
}
setFacetQueryParam(queryParam, selection) {
diff --git a/ui/app/controllers/clients/index.js b/ui/app/controllers/clients/index.js
index f801bc8fe..3ed795c69 100644
--- a/ui/app/controllers/clients/index.js
+++ b/ui/app/controllers/clients/index.js
@@ -7,14 +7,17 @@ import { scheduleOnce } from '@ember/runloop';
import intersection from 'lodash.intersection';
import SortableFactory from 'nomad-ui/mixins/sortable-factory';
import Searchable from 'nomad-ui/mixins/searchable';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
export default class IndexController extends Controller.extend(
- SortableFactory(['id', 'name', 'compositeStatus', 'datacenter', 'version']),
- Searchable
- ) {
+ SortableFactory(['id', 'name', 'compositeStatus', 'datacenter', 'version']),
+ Searchable
+) {
@service userSettings;
@controller('clients') clientsController;
@@ -83,10 +86,13 @@ export default class IndexController extends Controller.extend(
// Remove any invalid node classes from the query param/selection
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpClass', serialize(intersection(classes, this.selectionClass)));
+ this.set(
+ 'qpClass',
+ serialize(intersection(classes, this.selectionClass))
+ );
});
- return classes.sort().map(dc => ({ key: dc, label: dc }));
+ return classes.sort().map((dc) => ({ key: dc, label: dc }));
}
@computed
@@ -102,15 +108,20 @@ export default class IndexController extends Controller.extend(
@computed('nodes.[]', 'selectionDatacenter')
get optionsDatacenter() {
- const datacenters = Array.from(new Set(this.nodes.mapBy('datacenter'))).compact();
+ const datacenters = Array.from(
+ new Set(this.nodes.mapBy('datacenter'))
+ ).compact();
// Remove any invalid datacenters from the query param/selection
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpDatacenter', serialize(intersection(datacenters, this.selectionDatacenter)));
+ this.set(
+ 'qpDatacenter',
+ serialize(intersection(datacenters, this.selectionDatacenter))
+ );
});
- return datacenters.sort().map(dc => ({ key: dc, label: dc }));
+ return datacenters.sort().map((dc) => ({ key: dc, label: dc }));
}
@computed('nodes.[]', 'selectionVersion')
@@ -120,10 +131,13 @@ export default class IndexController extends Controller.extend(
// Remove any invalid versions from the query param/selection
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpVersion', serialize(intersection(versions, this.selectionVersion)));
+ this.set(
+ 'qpVersion',
+ serialize(intersection(versions, this.selectionVersion))
+ );
});
- return versions.sort().map(v => ({ key: v, label: v }));
+ return versions.sort().map((v) => ({ key: v, label: v }));
}
@computed('nodes.[]', 'selectionVolume')
@@ -135,10 +149,13 @@ export default class IndexController extends Controller.extend(
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpVolume', serialize(intersection(volumes, this.selectionVolume)));
+ this.set(
+ 'qpVolume',
+ serialize(intersection(volumes, this.selectionVolume))
+ );
});
- return volumes.sort().map(volume => ({ key: volume, label: volume }));
+ return volumes.sort().map((volume) => ({ key: volume, label: volume }));
}
@computed(
@@ -164,12 +181,19 @@ export default class IndexController extends Controller.extend(
// states is a composite of node status and other node states
const statuses = states.without('ineligible').without('draining');
- return this.nodes.filter(node => {
- if (classes.length && !classes.includes(node.get('nodeClass'))) return false;
- if (statuses.length && !statuses.includes(node.get('status'))) return false;
- if (datacenters.length && !datacenters.includes(node.get('datacenter'))) return false;
- if (versions.length && !versions.includes(node.get('version'))) return false;
- if (volumes.length && !node.hostVolumes.find(volume => volumes.includes(volume.name)))
+ return this.nodes.filter((node) => {
+ if (classes.length && !classes.includes(node.get('nodeClass')))
+ return false;
+ if (statuses.length && !statuses.includes(node.get('status')))
+ return false;
+ if (datacenters.length && !datacenters.includes(node.get('datacenter')))
+ return false;
+ if (versions.length && !versions.includes(node.get('version')))
+ return false;
+ if (
+ volumes.length &&
+ !node.hostVolumes.find((volume) => volumes.includes(volume.name))
+ )
return false;
if (onlyIneligible && node.get('isEligible')) return false;
diff --git a/ui/app/controllers/csi/plugins/index.js b/ui/app/controllers/csi/plugins/index.js
index bd9b3d2e5..b4c88ad9c 100644
--- a/ui/app/controllers/csi/plugins/index.js
+++ b/ui/app/controllers/csi/plugins/index.js
@@ -9,14 +9,14 @@ import classic from 'ember-classic-decorator';
@classic
export default class IndexController extends Controller.extend(
- SortableFactory([
- 'plainId',
- 'controllersHealthyProportion',
- 'nodesHealthyProportion',
- 'provider',
- ]),
- Searchable
- ) {
+ SortableFactory([
+ 'plainId',
+ 'controllersHealthyProportion',
+ 'nodesHealthyProportion',
+ 'provider',
+ ]),
+ Searchable
+) {
@service userSettings;
@controller('csi/plugins') pluginsController;
@@ -59,6 +59,9 @@ export default class IndexController extends Controller.extend(
@action
gotoPlugin(plugin, event) {
- lazyClick([() => this.transitionToRoute('csi.plugins.plugin', plugin.plainId), event]);
+ lazyClick([
+ () => this.transitionToRoute('csi.plugins.plugin', plugin.plainId),
+ event,
+ ]);
}
}
diff --git a/ui/app/controllers/csi/plugins/plugin/allocations.js b/ui/app/controllers/csi/plugins/plugin/allocations.js
index 53f7712a4..32c5ba669 100644
--- a/ui/app/controllers/csi/plugins/plugin/allocations.js
+++ b/ui/app/controllers/csi/plugins/plugin/allocations.js
@@ -4,13 +4,16 @@ import { action, computed } from '@ember/object';
import { alias, readOnly } from '@ember/object/computed';
import SortableFactory from 'nomad-ui/mixins/sortable-factory';
import { lazyClick } from 'nomad-ui/helpers/lazy-click';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
export default class AllocationsController extends Controller.extend(
- SortableFactory(['updateTime', 'healthy'])
- ) {
+ SortableFactory(['updateTime', 'healthy'])
+) {
@service userSettings;
queryParams = [
@@ -45,12 +48,18 @@ export default class AllocationsController extends Controller.extend(
@computed
get optionsType() {
- return [{ key: 'controller', label: 'Controller' }, { key: 'node', label: 'Node' }];
+ return [
+ { key: 'controller', label: 'Controller' },
+ { key: 'node', label: 'Node' },
+ ];
}
@computed
get optionsHealth() {
- return [{ key: 'true', label: 'Healthy' }, { key: 'false', label: 'Unhealthy' }];
+ return [
+ { key: 'true', label: 'Healthy' },
+ { key: 'false', label: 'Unhealthy' },
+ ];
}
@computed('model.{controllers.[],nodes.[]}')
@@ -76,7 +85,8 @@ export default class AllocationsController extends Controller.extend(
listToFilter = this.model.nodes;
}
- if (healths.length === 1 && healths[0] === 'true') return listToFilter.filterBy('healthy');
+ if (healths.length === 1 && healths[0] === 'true')
+ return listToFilter.filterBy('healthy');
if (healths.length === 1 && healths[0] === 'false')
return listToFilter.filterBy('healthy', false);
return listToFilter;
@@ -97,6 +107,9 @@ export default class AllocationsController extends Controller.extend(
@action
gotoAllocation(allocation, event) {
- lazyClick([() => this.transitionToRoute('allocations.allocation', allocation), event]);
+ lazyClick([
+ () => this.transitionToRoute('allocations.allocation', allocation),
+ event,
+ ]);
}
}
diff --git a/ui/app/controllers/csi/volumes/index.js b/ui/app/controllers/csi/volumes/index.js
index eb3b12e78..a7ca5b9ef 100644
--- a/ui/app/controllers/csi/volumes/index.js
+++ b/ui/app/controllers/csi/volumes/index.js
@@ -1,3 +1,4 @@
+import { set } from '@ember/object';
import { inject as service } from '@ember/service';
import { action, computed } from '@ember/object';
import { alias, readOnly } from '@ember/object/computed';
@@ -11,15 +12,15 @@ import classic from 'ember-classic-decorator';
@classic
export default class IndexController extends Controller.extend(
- SortableFactory([
- 'id',
- 'schedulable',
- 'controllersHealthyProportion',
- 'nodesHealthyProportion',
- 'provider',
- ]),
- Searchable
- ) {
+ SortableFactory([
+ 'id',
+ 'schedulable',
+ 'controllersHealthyProportion',
+ 'nodesHealthyProportion',
+ 'provider',
+ ]),
+ Searchable
+) {
@service system;
@service userSettings;
@controller('csi/volumes') volumesController;
@@ -65,7 +66,7 @@ export default class IndexController extends Controller.extend(
@computed('qpNamespace', 'model.namespaces.[]', 'system.cachedNamespace')
get optionsNamespaces() {
- const availableNamespaces = this.model.namespaces.map(namespace => ({
+ const availableNamespaces = this.model.namespaces.map((namespace) => ({
key: namespace.name,
label: namespace.name,
}));
@@ -102,7 +103,7 @@ export default class IndexController extends Controller.extend(
@action
cacheNamespace(namespace) {
- this.system.cachedNamespace = namespace;
+ set(this, 'system.cachedNamespace', namespace);
}
setFacetQueryParam(queryParam, selection) {
diff --git a/ui/app/controllers/csi/volumes/volume.js b/ui/app/controllers/csi/volumes/volume.js
index c151e5dec..46bf9a235 100644
--- a/ui/app/controllers/csi/volumes/volume.js
+++ b/ui/app/controllers/csi/volumes/volume.js
@@ -25,7 +25,9 @@ export default class VolumeController extends Controller {
label: 'Volumes',
args: [
'csi.volumes',
- qpBuilder({ volumeNamespace: volume.get('namespace.name') || 'default' }),
+ qpBuilder({
+ volumeNamespace: volume.get('namespace.name') || 'default',
+ }),
],
},
{
@@ -33,7 +35,9 @@ export default class VolumeController extends Controller {
args: [
'csi.volumes.volume',
volume.plainId,
- qpBuilder({ volumeNamespace: volume.get('namespace.name') || 'default' }),
+ qpBuilder({
+ volumeNamespace: volume.get('namespace.name') || 'default',
+ }),
],
},
];
diff --git a/ui/app/controllers/exec.js b/ui/app/controllers/exec.js
index 9e2691527..1738300d8 100644
--- a/ui/app/controllers/exec.js
+++ b/ui/app/controllers/exec.js
@@ -25,18 +25,25 @@ export default class ExecController extends Controller {
@computed('model.allocations.@each.clientStatus')
get pendingAndRunningAllocations() {
return this.model.allocations.filter(
- allocation => allocation.clientStatus === 'pending' || allocation.clientStatus === 'running'
+ (allocation) =>
+ allocation.clientStatus === 'pending' ||
+ allocation.clientStatus === 'running'
);
}
- @mapBy('pendingAndRunningAllocations', 'taskGroup') pendingAndRunningTaskGroups;
+ @mapBy('pendingAndRunningAllocations', 'taskGroup')
+ pendingAndRunningTaskGroups;
@uniq('pendingAndRunningTaskGroups') uniquePendingAndRunningTaskGroups;
taskGroupSorting = ['name'];
- @sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting') sortedTaskGroups;
+ @sort('uniquePendingAndRunningTaskGroups', 'taskGroupSorting')
+ sortedTaskGroups;
setUpTerminal(Terminal) {
- this.terminal = new Terminal({ fontFamily: 'monospace', fontWeight: '400' });
+ this.terminal = new Terminal({
+ fontFamily: 'monospace',
+ fontWeight: '400',
+ });
window.execTerminal = this.terminal; // Issue to improve: https://github.com/hashicorp/nomad/issues/7457
this.terminal.write(ANSI_UI_GRAY_400);
@@ -63,7 +70,7 @@ export default class ExecController extends Controller {
if (this.allocationShortId) {
allocation = this.allocations.findBy('shortId', this.allocationShortId);
} else {
- allocation = this.allocations.find(allocation =>
+ allocation = this.allocations.find((allocation) =>
allocation.states
.filterBy('isActive')
.mapBy('name')
@@ -72,7 +79,7 @@ export default class ExecController extends Controller {
}
if (allocation) {
- return allocation.states.find(state => state.name === this.taskName);
+ return allocation.states.find((state) => state.name === this.taskName);
}
return undefined;
@@ -97,7 +104,9 @@ export default class ExecController extends Controller {
this.terminal.writeln('');
}
- this.terminal.writeln('Customize your command, then hit ‘return’ to run.');
+ this.terminal.writeln(
+ 'Customize your command, then hit ‘return’ to run.'
+ );
this.terminal.writeln('');
this.terminal.write(
`$ nomad alloc exec -i -t -task ${escapeTaskName(taskName)} ${
@@ -129,7 +138,9 @@ export default class ExecController extends Controller {
new ExecSocketXtermAdapter(this.terminal, this.socket, this.token.secret);
} else {
- this.terminal.writeln(`Failed to open a socket because task ${this.taskName} is not active.`);
+ this.terminal.writeln(
+ `Failed to open a socket because task ${this.taskName} is not active.`
+ );
}
}
}
diff --git a/ui/app/controllers/jobs/index.js b/ui/app/controllers/jobs/index.js
index 0fb9e0288..ff38e023b 100644
--- a/ui/app/controllers/jobs/index.js
+++ b/ui/app/controllers/jobs/index.js
@@ -1,4 +1,5 @@
/* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
+import { set } from '@ember/object';
import { inject as service } from '@ember/service';
import { alias, readOnly } from '@ember/object/computed';
import Controller from '@ember/controller';
@@ -7,11 +8,17 @@ import { scheduleOnce } from '@ember/runloop';
import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
-export default class IndexController extends Controller.extend(Sortable, Searchable) {
+export default class IndexController extends Controller.extend(
+ Sortable,
+ Searchable
+) {
@service system;
@service userSettings;
@@ -99,7 +106,9 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
@computed('selectionDatacenter', 'visibleJobs.[]')
get optionsDatacenter() {
const flatten = (acc, val) => acc.concat(val);
- const allDatacenters = new Set(this.visibleJobs.mapBy('datacenters').reduce(flatten, []));
+ const allDatacenters = new Set(
+ this.visibleJobs.mapBy('datacenters').reduce(flatten, [])
+ );
// Remove any invalid datacenters from the query param/selection
const availableDatacenters = Array.from(allDatacenters).compact();
@@ -111,7 +120,7 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
);
});
- return availableDatacenters.sort().map(dc => ({ key: dc, label: dc }));
+ return availableDatacenters.sort().map((dc) => ({ key: dc, label: dc }));
}
@computed('selectionPrefix', 'visibleJobs.[]')
@@ -131,23 +140,26 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
}, {});
// Convert to an array
- const nameTable = Object.keys(nameHistogram).map(key => ({
+ const nameTable = Object.keys(nameHistogram).map((key) => ({
prefix: key,
count: nameHistogram[key],
}));
// Only consider prefixes that match more than one name
- const prefixes = nameTable.filter(name => name.count > 1);
+ const prefixes = nameTable.filter((name) => name.count > 1);
// Remove any invalid prefixes from the query param/selection
const availablePrefixes = prefixes.mapBy('prefix');
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpPrefix', serialize(intersection(availablePrefixes, this.selectionPrefix)));
+ this.set(
+ 'qpPrefix',
+ serialize(intersection(availablePrefixes, this.selectionPrefix))
+ );
});
// Sort, format, and include the count in the label
- return prefixes.sortBy('prefix').map(name => ({
+ return prefixes.sortBy('prefix').map((name) => ({
key: name.prefix,
label: `${name.prefix} (${name.count})`,
}));
@@ -155,7 +167,7 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
@computed('qpNamespace', 'model.namespaces.[]', 'system.cachedNamespace')
get optionsNamespaces() {
- const availableNamespaces = this.model.namespaces.map(namespace => ({
+ const availableNamespaces = this.model.namespaces.map((namespace) => ({
key: namespace.name,
label: namespace.name,
}));
@@ -185,8 +197,8 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
if (!this.model || !this.model.jobs) return [];
return this.model.jobs
.compact()
- .filter(job => !job.isNew)
- .filter(job => !job.get('parent.content'));
+ .filter((job) => !job.isNew)
+ .filter((job) => !job.get('parent.content'));
}
@computed(
@@ -206,7 +218,7 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
// A job must match ALL filter facets, but it can match ANY selection within a facet
// Always return early to prevent unnecessary facet predicates.
- return this.visibleJobs.filter(job => {
+ return this.visibleJobs.filter((job) => {
if (types.length && !types.includes(job.get('displayType'))) {
return false;
}
@@ -215,12 +227,18 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
return false;
}
- if (datacenters.length && !job.get('datacenters').find(dc => datacenters.includes(dc))) {
+ if (
+ datacenters.length &&
+ !job.get('datacenters').find((dc) => datacenters.includes(dc))
+ ) {
return false;
}
const name = job.get('name');
- if (prefixes.length && !prefixes.find(prefix => name.startsWith(prefix))) {
+ if (
+ prefixes.length &&
+ !prefixes.find((prefix) => name.startsWith(prefix))
+ ) {
return false;
}
@@ -236,7 +254,7 @@ export default class IndexController extends Controller.extend(Sortable, Searcha
@action
cacheNamespace(namespace) {
- this.system.cachedNamespace = namespace;
+ set(this, 'system.cachedNamespace', namespace);
}
setFacetQueryParam(queryParam, selection) {
diff --git a/ui/app/controllers/jobs/job/allocations.js b/ui/app/controllers/jobs/job/allocations.js
index d6ec836c4..466b7567d 100644
--- a/ui/app/controllers/jobs/job/allocations.js
+++ b/ui/app/controllers/jobs/job/allocations.js
@@ -7,15 +7,18 @@ import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
export default class AllocationsController extends Controller.extend(
- Sortable,
- Searchable,
- WithNamespaceResetting
- ) {
+ Sortable,
+ Searchable,
+ WithNamespaceResetting
+) {
queryParams = [
{
currentPage: 'page',
@@ -61,18 +64,32 @@ export default class AllocationsController extends Controller.extend(
return this.get('model.allocations') || [];
}
- @computed('allocations.[]', 'selectionStatus', 'selectionClient', 'selectionTaskGroup')
+ @computed(
+ 'allocations.[]',
+ 'selectionStatus',
+ 'selectionClient',
+ 'selectionTaskGroup'
+ )
get filteredAllocations() {
const { selectionStatus, selectionClient, selectionTaskGroup } = this;
- return this.allocations.filter(alloc => {
- if (selectionStatus.length && !selectionStatus.includes(alloc.clientStatus)) {
+ return this.allocations.filter((alloc) => {
+ if (
+ selectionStatus.length &&
+ !selectionStatus.includes(alloc.clientStatus)
+ ) {
return false;
}
- if (selectionClient.length && !selectionClient.includes(alloc.get('node.shortId'))) {
+ if (
+ selectionClient.length &&
+ !selectionClient.includes(alloc.get('node.shortId'))
+ ) {
return false;
}
- if (selectionTaskGroup.length && !selectionTaskGroup.includes(alloc.taskGroupName)) {
+ if (
+ selectionTaskGroup.length &&
+ !selectionTaskGroup.includes(alloc.taskGroupName)
+ ) {
return false;
}
return true;
@@ -104,28 +121,38 @@ export default class AllocationsController extends Controller.extend(
@computed('model.allocations.[]', 'selectionClient')
get optionsClients() {
- const clients = Array.from(new Set(this.model.allocations.mapBy('node.shortId'))).compact();
+ const clients = Array.from(
+ new Set(this.model.allocations.mapBy('node.shortId'))
+ ).compact();
// Update query param when the list of clients changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpClient', serialize(intersection(clients, this.selectionClient)));
+ this.set(
+ 'qpClient',
+ serialize(intersection(clients, this.selectionClient))
+ );
});
- return clients.sort().map(c => ({ key: c, label: c }));
+ return clients.sort().map((c) => ({ key: c, label: c }));
}
@computed('model.allocations.[]', 'selectionTaskGroup')
get optionsTaskGroups() {
- const taskGroups = Array.from(new Set(this.model.allocations.mapBy('taskGroupName'))).compact();
+ const taskGroups = Array.from(
+ new Set(this.model.allocations.mapBy('taskGroupName'))
+ ).compact();
// Update query param when the list of task groups changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpTaskGroup', serialize(intersection(taskGroups, this.selectionTaskGroup)));
+ this.set(
+ 'qpTaskGroup',
+ serialize(intersection(taskGroups, this.selectionTaskGroup))
+ );
});
- return taskGroups.sort().map(tg => ({ key: tg, label: tg }));
+ return taskGroups.sort().map((tg) => ({ key: tg, label: tg }));
}
setFacetQueryParam(queryParam, selection) {
diff --git a/ui/app/controllers/jobs/job/clients.js b/ui/app/controllers/jobs/job/clients.js
index 2e14798bf..a4b7f05df 100644
--- a/ui/app/controllers/jobs/job/clients.js
+++ b/ui/app/controllers/jobs/job/clients.js
@@ -8,15 +8,18 @@ import SortableFactory from 'nomad-ui/mixins/sortable-factory';
import Searchable from 'nomad-ui/mixins/searchable';
import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting';
import jobClientStatus from 'nomad-ui/utils/properties/job-client-status';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
export default class ClientsController extends Controller.extend(
- SortableFactory(['id', 'name', 'jobStatus']),
- Searchable,
- WithNamespaceResetting
- ) {
+ SortableFactory(['id', 'name', 'jobStatus']),
+ Searchable,
+ WithNamespaceResetting
+) {
queryParams = [
{
currentPage: 'page',
@@ -71,7 +74,7 @@ export default class ClientsController extends Controller.extend(
@computed('allNodes', 'jobClientStatus.byNode')
get nodes() {
- return this.allNodes.filter(node => this.jobClientStatus.byNode[node.id]);
+ return this.allNodes.filter((node) => this.jobClientStatus.byNode[node.id]);
}
@computed
@@ -95,8 +98,11 @@ export default class ClientsController extends Controller.extend(
} = this;
return this.nodes
- .filter(node => {
- if (statuses.length && !statuses.includes(this.jobClientStatus.byNode[node.id])) {
+ .filter((node) => {
+ if (
+ statuses.length &&
+ !statuses.includes(this.jobClientStatus.byNode[node.id])
+ ) {
return false;
}
if (datacenters.length && !datacenters.includes(node.datacenter)) {
@@ -108,8 +114,10 @@ export default class ClientsController extends Controller.extend(
return true;
})
- .map(node => {
- const allocations = this.job.allocations.filter(alloc => alloc.get('node.id') == node.id);
+ .map((node) => {
+ const allocations = this.job.allocations.filter(
+ (alloc) => alloc.get('node.id') == node.id
+ );
return {
node,
@@ -137,28 +145,40 @@ export default class ClientsController extends Controller.extend(
@computed('selectionDatacenter', 'nodes')
get optionsDatacenter() {
- const datacenters = Array.from(new Set(this.nodes.mapBy('datacenter'))).compact();
+ const datacenters = Array.from(
+ new Set(this.nodes.mapBy('datacenter'))
+ ).compact();
// Update query param when the list of datacenters changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpDatacenter', serialize(intersection(datacenters, this.selectionDatacenter)));
+ this.set(
+ 'qpDatacenter',
+ serialize(intersection(datacenters, this.selectionDatacenter))
+ );
});
- return datacenters.sort().map(dc => ({ key: dc, label: dc }));
+ return datacenters.sort().map((dc) => ({ key: dc, label: dc }));
}
@computed('selectionClientClass', 'nodes')
get optionsClientClass() {
- const clientClasses = Array.from(new Set(this.nodes.mapBy('nodeClass'))).compact();
+ const clientClasses = Array.from(
+ new Set(this.nodes.mapBy('nodeClass'))
+ ).compact();
// Update query param when the list of datacenters changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpClientClass', serialize(intersection(clientClasses, this.selectionClientClass)));
+ this.set(
+ 'qpClientClass',
+ serialize(intersection(clientClasses, this.selectionClientClass))
+ );
});
- return clientClasses.sort().map(clientClass => ({ key: clientClass, label: clientClass }));
+ return clientClasses
+ .sort()
+ .map((clientClass) => ({ key: clientClass, label: clientClass }));
}
@action
diff --git a/ui/app/controllers/jobs/job/definition.js b/ui/app/controllers/jobs/job/definition.js
index faa94d92f..a428f941b 100644
--- a/ui/app/controllers/jobs/job/definition.js
+++ b/ui/app/controllers/jobs/job/definition.js
@@ -4,7 +4,9 @@ import { alias } from '@ember/object/computed';
import classic from 'ember-classic-decorator';
@classic
-export default class DefinitionController extends Controller.extend(WithNamespaceResetting) {
+export default class DefinitionController extends Controller.extend(
+ WithNamespaceResetting
+) {
@alias('model.job') job;
@alias('model.definition') definition;
diff --git a/ui/app/controllers/jobs/job/deployments.js b/ui/app/controllers/jobs/job/deployments.js
index cbce847e2..f6b71c167 100644
--- a/ui/app/controllers/jobs/job/deployments.js
+++ b/ui/app/controllers/jobs/job/deployments.js
@@ -4,6 +4,8 @@ import { alias } from '@ember/object/computed';
import classic from 'ember-classic-decorator';
@classic
-export default class DeploymentsController extends Controller.extend(WithNamespaceResetting) {
+export default class DeploymentsController extends Controller.extend(
+ WithNamespaceResetting
+) {
@alias('model') job;
}
diff --git a/ui/app/controllers/jobs/job/evaluations.js b/ui/app/controllers/jobs/job/evaluations.js
index 831cb3f7c..475038f8d 100644
--- a/ui/app/controllers/jobs/job/evaluations.js
+++ b/ui/app/controllers/jobs/job/evaluations.js
@@ -6,9 +6,9 @@ import classic from 'ember-classic-decorator';
@classic
export default class EvaluationsController extends Controller.extend(
- WithNamespaceResetting,
- Sortable
- ) {
+ WithNamespaceResetting,
+ Sortable
+) {
queryParams = [
{
sortProperty: 'sort',
diff --git a/ui/app/controllers/jobs/job/index.js b/ui/app/controllers/jobs/job/index.js
index b57a44343..9feccefa5 100644
--- a/ui/app/controllers/jobs/job/index.js
+++ b/ui/app/controllers/jobs/job/index.js
@@ -6,7 +6,9 @@ import { action } from '@ember/object';
import classic from 'ember-classic-decorator';
@classic
-export default class IndexController extends Controller.extend(WithNamespaceResetting) {
+export default class IndexController extends Controller.extend(
+ WithNamespaceResetting
+) {
@service system;
queryParams = [
@@ -38,7 +40,11 @@ export default class IndexController extends Controller.extend(WithNamespaceRese
@action
gotoTaskGroup(taskGroup) {
- this.transitionToRoute('jobs.job.task-group', taskGroup.get('job'), taskGroup);
+ this.transitionToRoute(
+ 'jobs.job.task-group',
+ taskGroup.get('job'),
+ taskGroup
+ );
}
@action
diff --git a/ui/app/controllers/jobs/job/task-group.js b/ui/app/controllers/jobs/job/task-group.js
index 8a2c39ed9..592f1508e 100644
--- a/ui/app/controllers/jobs/job/task-group.js
+++ b/ui/app/controllers/jobs/job/task-group.js
@@ -9,15 +9,18 @@ import { qpBuilder } from 'nomad-ui/utils/classes/query-params';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
import WithNamespaceResetting from 'nomad-ui/mixins/with-namespace-resetting';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import classic from 'ember-classic-decorator';
@classic
export default class TaskGroupController extends Controller.extend(
- Sortable,
- Searchable,
- WithNamespaceResetting
- ) {
+ Sortable,
+ Searchable,
+ WithNamespaceResetting
+) {
@service userSettings;
@service can;
@@ -64,11 +67,17 @@ export default class TaskGroupController extends Controller.extend(
get filteredAllocations() {
const { selectionStatus, selectionClient } = this;
- return this.allocations.filter(alloc => {
- if (selectionStatus.length && !selectionStatus.includes(alloc.clientStatus)) {
+ return this.allocations.filter((alloc) => {
+ if (
+ selectionStatus.length &&
+ !selectionStatus.includes(alloc.clientStatus)
+ ) {
return false;
}
- if (selectionClient.length && !selectionClient.includes(alloc.get('node.shortId'))) {
+ if (
+ selectionClient.length &&
+ !selectionClient.includes(alloc.get('node.shortId'))
+ ) {
return false;
}
@@ -83,7 +92,7 @@ export default class TaskGroupController extends Controller.extend(
@selection('qpStatus') selectionStatus;
@selection('qpClient') selectionClient;
- @computed('model.scaleState.events.@each.time', function() {
+ @computed('model.scaleState.events.@each.time', function () {
const events = get(this, 'model.scaleState.events');
if (events) {
return events.sortBy('time').reverse();
@@ -92,17 +101,25 @@ export default class TaskGroupController extends Controller.extend(
})
sortedScaleEvents;
- @computed('sortedScaleEvents.@each.hasCount', function() {
+ @computed('sortedScaleEvents.@each.hasCount', function () {
const countEventsCount = this.sortedScaleEvents.filterBy('hasCount').length;
- return countEventsCount > 1 && countEventsCount >= this.sortedScaleEvents.length / 2;
+ return (
+ countEventsCount > 1 &&
+ countEventsCount >= this.sortedScaleEvents.length / 2
+ );
})
shouldShowScaleEventTimeline;
@computed('model.job.{namespace,runningDeployment}')
get tooltipText() {
- if (this.can.cannot('scale job', null, { namespace: this.model.job.namespace.get('name') }))
+ if (
+ this.can.cannot('scale job', null, {
+ namespace: this.model.job.namespace.get('name'),
+ })
+ )
return "You aren't allowed to scale task groups";
- if (this.model.job.runningDeployment) return 'You cannot scale task groups during a deployment';
+ if (this.model.job.runningDeployment)
+ return 'You cannot scale task groups during a deployment';
return undefined;
}
@@ -128,15 +145,20 @@ export default class TaskGroupController extends Controller.extend(
@computed('model.allocations.[]', 'selectionClient')
get optionsClients() {
- const clients = Array.from(new Set(this.model.allocations.mapBy('node.shortId'))).compact();
+ const clients = Array.from(
+ new Set(this.model.allocations.mapBy('node.shortId'))
+ ).compact();
// Update query param when the list of clients changes.
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.set('qpClient', serialize(intersection(clients, this.selectionClient)));
+ this.set(
+ 'qpClient',
+ serialize(intersection(clients, this.selectionClient))
+ );
});
- return clients.sort().map(dc => ({ key: dc, label: dc }));
+ return clients.sort().map((dc) => ({ key: dc, label: dc }));
}
setFacetQueryParam(queryParam, selection) {
diff --git a/ui/app/controllers/jobs/job/versions.js b/ui/app/controllers/jobs/job/versions.js
index 087100ea0..195f73619 100644
--- a/ui/app/controllers/jobs/job/versions.js
+++ b/ui/app/controllers/jobs/job/versions.js
@@ -12,14 +12,18 @@ const errorLevelToAlertClass = {
};
@classic
-export default class VersionsController extends Controller.extend(WithNamespaceResetting) {
+export default class VersionsController extends Controller.extend(
+ WithNamespaceResetting
+) {
error = null;
@alias('model') job;
@computed('error.level')
get errorLevelClass() {
- return errorLevelToAlertClass[this.get('error.level')] || alertClassFallback;
+ return (
+ errorLevelToAlertClass[this.get('error.level')] || alertClassFallback
+ );
}
onDismiss() {
diff --git a/ui/app/controllers/optimize.js b/ui/app/controllers/optimize.js
index b5c438a99..53331cc8f 100644
--- a/ui/app/controllers/optimize.js
+++ b/ui/app/controllers/optimize.js
@@ -7,7 +7,10 @@ import { inject as service } from '@ember/service';
import { scheduleOnce } from '@ember/runloop';
import { task } from 'ember-concurrency';
import intersection from 'lodash.intersection';
-import { serialize, deserializedQueryParam as selection } from 'nomad-ui/utils/qp-serialize';
+import {
+ serialize,
+ deserializedQueryParam as selection,
+} from 'nomad-ui/utils/qp-serialize';
import EmberObject, { computed } from '@ember/object';
import { alias } from '@ember/object/computed';
@@ -70,7 +73,7 @@ export default class OptimizeController extends Controller {
@selection('qpPrefix') selectionPrefix;
get optionsNamespaces() {
- const availableNamespaces = this.namespaces.map(namespace => ({
+ const availableNamespaces = this.namespaces.map((namespace) => ({
key: namespace.name,
label: namespace.name,
}));
@@ -104,16 +107,20 @@ export default class OptimizeController extends Controller {
get optionsDatacenter() {
const flatten = (acc, val) => acc.concat(val);
- const allDatacenters = new Set(this.summaries.mapBy('job.datacenters').reduce(flatten, []));
+ const allDatacenters = new Set(
+ this.summaries.mapBy('job.datacenters').reduce(flatten, [])
+ );
// Remove any invalid datacenters from the query param/selection
const availableDatacenters = Array.from(allDatacenters).compact();
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.qpDatacenter = serialize(intersection(availableDatacenters, this.selectionDatacenter));
+ this.qpDatacenter = serialize(
+ intersection(availableDatacenters, this.selectionDatacenter)
+ );
});
- return availableDatacenters.sort().map(dc => ({ key: dc, label: dc }));
+ return availableDatacenters.sort().map((dc) => ({ key: dc, label: dc }));
}
get optionsPrefix() {
@@ -132,23 +139,25 @@ export default class OptimizeController extends Controller {
}, {});
// Convert to an array
- const nameTable = Object.keys(nameHistogram).map(key => ({
+ const nameTable = Object.keys(nameHistogram).map((key) => ({
prefix: key,
count: nameHistogram[key],
}));
// Only consider prefixes that match more than one name
- const prefixes = nameTable.filter(name => name.count > 1);
+ const prefixes = nameTable.filter((name) => name.count > 1);
// Remove any invalid prefixes from the query param/selection
const availablePrefixes = prefixes.mapBy('prefix');
scheduleOnce('actions', () => {
// eslint-disable-next-line ember/no-side-effects
- this.qpPrefix = serialize(intersection(availablePrefixes, this.selectionPrefix));
+ this.qpPrefix = serialize(
+ intersection(availablePrefixes, this.selectionPrefix)
+ );
});
// Sort, format, and include the count in the label
- return prefixes.sortBy('prefix').map(name => ({
+ return prefixes.sortBy('prefix').map((name) => ({
key: name.prefix,
label: `${name.prefix} (${name.count})`,
}));
@@ -164,14 +173,17 @@ export default class OptimizeController extends Controller {
// A summary’s job must match ALL filter facets, but it can match ANY selection within a facet
// Always return early to prevent unnecessary facet predicates.
- return this.summarySearch.listSearched.filter(summary => {
+ return this.summarySearch.listSearched.filter((summary) => {
const job = summary.get('job');
if (job.isDestroying) {
return false;
}
- if (this.qpNamespace !== '*' && job.get('namespace.name') !== this.qpNamespace) {
+ if (
+ this.qpNamespace !== '*' &&
+ job.get('namespace.name') !== this.qpNamespace
+ ) {
return false;
}
@@ -183,12 +195,18 @@ export default class OptimizeController extends Controller {
return false;
}
- if (datacenters.length && !job.get('datacenters').find(dc => datacenters.includes(dc))) {
+ if (
+ datacenters.length &&
+ !job.get('datacenters').find((dc) => datacenters.includes(dc))
+ ) {
return false;
}
const name = job.get('name');
- if (prefixes.length && !prefixes.find(prefix => name.startsWith(prefix))) {
+ if (
+ prefixes.length &&
+ !prefixes.find((prefix) => name.startsWith(prefix))
+ ) {
return false;
}
@@ -206,9 +224,13 @@ export default class OptimizeController extends Controller {
// This is a task because the accordion uses timeouts for animation
// eslint-disable-next-line require-yield
- @(task(function*() {
- const currentSummaryIndex = this.filteredSummaries.indexOf(this.activeRecommendationSummary);
- const nextSummary = this.filteredSummaries.objectAt(currentSummaryIndex + 1);
+ @(task(function* () {
+ const currentSummaryIndex = this.filteredSummaries.indexOf(
+ this.activeRecommendationSummary
+ );
+ const nextSummary = this.filteredSummaries.objectAt(
+ currentSummaryIndex + 1
+ );
if (nextSummary) {
this.transitionToSummary(nextSummary);
diff --git a/ui/app/controllers/servers/server/index.js b/ui/app/controllers/servers/server/index.js
index 1b511c22f..861a82f97 100644
--- a/ui/app/controllers/servers/server/index.js
+++ b/ui/app/controllers/servers/server/index.js
@@ -10,7 +10,7 @@ export default class ServerController extends Controller {
get sortedTags() {
const tags = this.get('model.tags') || {};
return Object.keys(tags)
- .map(name => ({
+ .map((name) => ({
name,
value: tags[name],
}))
diff --git a/ui/app/controllers/settings/tokens.js b/ui/app/controllers/settings/tokens.js
index 3ac048863..7fe6df52f 100644
--- a/ui/app/controllers/settings/tokens.js
+++ b/ui/app/controllers/settings/tokens.js
@@ -48,9 +48,7 @@ export default class Tokens extends Controller {
this.resetStore();
// Refetch the token and associated policies
- this.get('token.fetchSelfTokenAndPolicies')
- .perform()
- .catch();
+ this.get('token.fetchSelfTokenAndPolicies').perform().catch();
this.setProperties({
tokenIsValid: true,
diff --git a/ui/app/controllers/topology.js b/ui/app/controllers/topology.js
index 4b9a38b06..c3866eb5e 100644
--- a/ui/app/controllers/topology.js
+++ b/ui/app/controllers/topology.js
@@ -31,13 +31,17 @@ export default class TopologyControllers extends Controller {
@computed('model.nodes.@each.resources')
get totalMemory() {
- const mibs = this.model.nodes.mapBy('resources.memory').reduce(sumAggregator, 0);
+ const mibs = this.model.nodes
+ .mapBy('resources.memory')
+ .reduce(sumAggregator, 0);
return mibs * 1024 * 1024;
}
@computed('model.nodes.@each.resources')
get totalCPU() {
- return this.model.nodes.mapBy('resources.cpu').reduce((sum, cpu) => sum + (cpu || 0), 0);
+ return this.model.nodes
+ .mapBy('resources.cpu')
+ .reduce((sum, cpu) => sum + (cpu || 0), 0);
}
@computed('totalMemory')
@@ -70,7 +74,9 @@ export default class TopologyControllers extends Controller {
@computed('scheduledAllocations.@each.allocatedResources')
get totalReservedCPU() {
- return this.scheduledAllocations.mapBy('allocatedResources.cpu').reduce(sumAggregator, 0);
+ return this.scheduledAllocations
+ .mapBy('allocatedResources.cpu')
+ .reduce(sumAggregator, 0);
}
@computed('totalMemory', 'totalReservedMemory')
@@ -85,23 +91,35 @@ export default class TopologyControllers extends Controller {
return this.totalReservedCPU / this.totalCPU;
}
- @computed('activeAllocation.taskGroupName', 'scheduledAllocations.@each.{job,taskGroupName}')
+ @computed(
+ 'activeAllocation.taskGroupName',
+ 'scheduledAllocations.@each.{job,taskGroupName}'
+ )
get siblingAllocations() {
if (!this.activeAllocation) return [];
const taskGroup = this.activeAllocation.taskGroupName;
const jobId = this.activeAllocation.belongsTo('job').id();
- return this.scheduledAllocations.filter(allocation => {
- return allocation.taskGroupName === taskGroup && allocation.belongsTo('job').id() === jobId;
+ return this.scheduledAllocations.filter((allocation) => {
+ return (
+ allocation.taskGroupName === taskGroup &&
+ allocation.belongsTo('job').id() === jobId
+ );
});
}
@computed('activeNode')
get nodeUtilization() {
const node = this.activeNode;
- const [formattedMemory, memoryUnits] = reduceBytes(node.memory * 1024 * 1024);
- const totalReservedMemory = node.allocations.mapBy('memory').reduce(sumAggregator, 0);
- const totalReservedCPU = node.allocations.mapBy('cpu').reduce(sumAggregator, 0);
+ const [formattedMemory, memoryUnits] = reduceBytes(
+ node.memory * 1024 * 1024
+ );
+ const totalReservedMemory = node.allocations
+ .mapBy('memory')
+ .reduce(sumAggregator, 0);
+ const totalReservedCPU = node.allocations
+ .mapBy('cpu')
+ .reduce(sumAggregator, 0);
return {
totalMemoryFormatted: formattedMemory.toFixed(2),
diff --git a/ui/app/helpers/bind.js b/ui/app/helpers/bind.js
index 36e3bf4e2..d48dab528 100644
--- a/ui/app/helpers/bind.js
+++ b/ui/app/helpers/bind.js
@@ -9,7 +9,10 @@ import { assert } from '@ember/debug';
* Returns a version of a function bound to the template target (e.g., component or controller)
*/
export function bind([func, target]) {
- assert('A function is required as the first argument', typeof func === 'function');
+ assert(
+ 'A function is required as the first argument',
+ typeof func === 'function'
+ );
assert('A context is required as the second argument', target);
return func.bind(target);
}
diff --git a/ui/app/helpers/css-class.js b/ui/app/helpers/css-class.js
index d7f30127c..ca4748ed9 100644
--- a/ui/app/helpers/css-class.js
+++ b/ui/app/helpers/css-class.js
@@ -9,6 +9,7 @@ import { helper } from '@ember/component/helper';
* Differs from dasherize by handling slashes.
*/
export function cssClass([updateType]) {
+ /* eslint-disable-next-line ember/no-string-prototype-extensions */
return updateType.replace(/\//g, '-').dasherize();
}
diff --git a/ui/app/helpers/is-object.js b/ui/app/helpers/is-object.js
index 97dd42e65..53804c904 100644
--- a/ui/app/helpers/is-object.js
+++ b/ui/app/helpers/is-object.js
@@ -1,7 +1,8 @@
import Helper from '@ember/component/helper';
export function isObject([value]) {
- const isObject = !Array.isArray(value) && value !== null && typeof value === 'object';
+ const isObject =
+ !Array.isArray(value) && value !== null && typeof value === 'object';
return isObject;
}
diff --git a/ui/app/helpers/x-icon.js b/ui/app/helpers/x-icon.js
index f53a50543..770428299 100644
--- a/ui/app/helpers/x-icon.js
+++ b/ui/app/helpers/x-icon.js
@@ -13,7 +13,9 @@ import SVGs from '../svgs';
*/
export function xIcon(params, options) {
const name = params[0];
- const classes = [options.class, 'icon', `icon-is-${name}`].compact().join(' ');
+ const classes = [options.class, 'icon', `icon-is-${name}`]
+ .compact()
+ .join(' ');
return inlineSvg(SVGs, name, { class: classes });
}
diff --git a/ui/app/mixins/searchable.js b/ui/app/mixins/searchable.js
index 8ef120731..04cc7ef3a 100644
--- a/ui/app/mixins/searchable.js
+++ b/ui/app/mixins/searchable.js
@@ -25,7 +25,7 @@ import Fuse from 'fuse.js';
// eslint-disable-next-line ember/no-new-mixins
export default Mixin.create({
searchTerm: '',
- listToSearch: computed(function() {
+ listToSearch: computed(function () {
return [];
}),
@@ -50,23 +50,28 @@ export default Mixin.create({
}
},
- fuse: computed('fuzzySearchProps.[]', 'includeFuzzySearchMatches', 'listToSearch.[]', function() {
- return new Fuse(this.listToSearch, {
- shouldSort: true,
- threshold: 0.4,
- location: 0,
- distance: 100,
- tokenize: true,
- matchAllTokens: true,
- maxPatternLength: 32,
- minMatchCharLength: 1,
- includeMatches: this.includeFuzzySearchMatches,
- keys: this.fuzzySearchProps || [],
- getFn(item, key) {
- return get(item, key);
- },
- });
- }),
+ fuse: computed(
+ 'fuzzySearchProps.[]',
+ 'includeFuzzySearchMatches',
+ 'listToSearch.[]',
+ function () {
+ return new Fuse(this.listToSearch, {
+ shouldSort: true,
+ threshold: 0.4,
+ location: 0,
+ distance: 100,
+ tokenize: true,
+ matchAllTokens: true,
+ maxPatternLength: 32,
+ minMatchCharLength: 1,
+ includeMatches: this.includeFuzzySearchMatches,
+ keys: this.fuzzySearchProps || [],
+ getFn(item, key) {
+ return get(item, key);
+ },
+ });
+ }
+ ),
listSearched: computed(
'exactMatchEnabled',
@@ -79,7 +84,7 @@ export default Mixin.create({
'regexEnabled',
'regexSearchProps.[]',
'searchTerm',
- function() {
+ function () {
const searchTerm = this.searchTerm.trim();
if (!searchTerm || !searchTerm.length) {
@@ -90,7 +95,11 @@ export default Mixin.create({
if (this.exactMatchEnabled) {
results.push(
- ...exactMatchSearch(searchTerm, this.listToSearch, this.exactMatchSearchProps)
+ ...exactMatchSearch(
+ searchTerm,
+ this.listToSearch,
+ this.exactMatchSearchProps
+ )
);
}
@@ -98,7 +107,7 @@ export default Mixin.create({
let fuseSearchResults = this.fuse.search(searchTerm);
if (this.includeFuzzySearchMatches) {
- fuseSearchResults = fuseSearchResults.map(result => {
+ fuseSearchResults = fuseSearchResults.map((result) => {
const item = result.item;
item.set('fuzzySearchMatches', result.matches);
return item;
@@ -109,7 +118,9 @@ export default Mixin.create({
}
if (this.regexEnabled) {
- results.push(...regexSearch(searchTerm, this.listToSearch, this.regexSearchProps));
+ results.push(
+ ...regexSearch(searchTerm, this.listToSearch, this.regexSearchProps)
+ );
}
return results.uniq();
@@ -119,7 +130,7 @@ export default Mixin.create({
function exactMatchSearch(term, list, keys) {
if (term.length) {
- return list.filter(item => keys.some(key => get(item, key) === term));
+ return list.filter((item) => keys.some((key) => get(item, key) === term));
}
}
@@ -129,7 +140,9 @@ function regexSearch(term, list, keys) {
const regex = new RegExp(term, 'i');
// Test the value of each key for each object against the regex
// All that match are returned.
- return list.filter(item => keys.some(key => regex.test(get(item, key))));
+ return list.filter((item) =>
+ keys.some((key) => regex.test(get(item, key)))
+ );
} catch (e) {
// Swallow the error; most likely due to an eager search of an incomplete regex
}
diff --git a/ui/app/mixins/sortable-factory.js b/ui/app/mixins/sortable-factory.js
index 814d42d6c..38510b9fb 100644
--- a/ui/app/mixins/sortable-factory.js
+++ b/ui/app/mixins/sortable-factory.js
@@ -19,14 +19,16 @@ import { warn } from '@ember/debug';
- listSorted: a copy of listToSort that has been sorted
*/
export default function sortableFactory(properties, fromSortableMixin) {
- const eachProperties = properties.map(property => `listToSort.@each.${property}`);
+ const eachProperties = properties.map(
+ (property) => `listToSort.@each.${property}`
+ );
// eslint-disable-next-line ember/no-new-mixins
return Mixin.create({
// Override in mixin consumer
sortProperty: null,
sortDescending: true,
- listToSort: computed(function() {
+ listToSort: computed(function () {
return [];
}),
@@ -38,16 +40,19 @@ export default function sortableFactory(properties, fromSortableMixin) {
'listToSort.[]',
'sortDescending',
'sortProperty',
- function() {
+ function () {
if (!this._sortableFactoryWarningPrinted && !Ember.testing) {
let message =
'Using SortableFactory without property keys means the list will only sort when the members change, not when any of their properties change.';
if (fromSortableMixin) {
- message += ' The Sortable mixin is deprecated in favor of SortableFactory.';
+ message +=
+ ' The Sortable mixin is deprecated in favor of SortableFactory.';
}
- warn(message, properties.length > 0, { id: 'nomad.no-sortable-properties' });
+ warn(message, properties.length > 0, {
+ id: 'nomad.no-sortable-properties',
+ });
// eslint-disable-next-line ember/no-side-effects
this.set('_sortableFactoryWarningPrinted', true);
}
diff --git a/ui/app/mixins/window-resizable.js b/ui/app/mixins/window-resizable.js
index d5d2eb159..164cb4c66 100644
--- a/ui/app/mixins/window-resizable.js
+++ b/ui/app/mixins/window-resizable.js
@@ -6,10 +6,13 @@ import { on } from '@ember/object/evented';
// eslint-disable-next-line ember/no-new-mixins
export default Mixin.create({
windowResizeHandler() {
- assert('windowResizeHandler needs to be overridden in the Component', false);
+ assert(
+ 'windowResizeHandler needs to be overridden in the Component',
+ false
+ );
},
- setupWindowResize: on('didInsertElement', function() {
+ setupWindowResize: on('didInsertElement', function () {
run.scheduleOnce('afterRender', this, this.addResizeListener);
}),
@@ -18,7 +21,7 @@ export default Mixin.create({
window.addEventListener('resize', this._windowResizeHandler);
},
- removeWindowResize: on('willDestroyElement', function() {
+ removeWindowResize: on('willDestroyElement', function () {
window.removeEventListener('resize', this._windowResizeHandler);
}),
});
diff --git a/ui/app/mixins/with-component-visibility-detection.js b/ui/app/mixins/with-component-visibility-detection.js
index 57c341930..96d76dffd 100644
--- a/ui/app/mixins/with-component-visibility-detection.js
+++ b/ui/app/mixins/with-component-visibility-detection.js
@@ -9,14 +9,14 @@ export default Mixin.create({
assert('visibilityHandler needs to be overridden in the Component', false);
},
- setupDocumentVisibility: on('init', function() {
+ setupDocumentVisibility: on('init', function () {
if (!Ember.testing) {
this.set('_visibilityHandler', this.visibilityHandler.bind(this));
document.addEventListener('visibilitychange', this._visibilityHandler);
}
}),
- removeDocumentVisibility: on('init', function() {
+ removeDocumentVisibility: on('init', function () {
if (!Ember.testing) {
document.removeEventListener('visibilitychange', this._visibilityHandler);
}
diff --git a/ui/app/mixins/with-route-visibility-detection.js b/ui/app/mixins/with-route-visibility-detection.js
index 707146df8..e54f4da5d 100644
--- a/ui/app/mixins/with-route-visibility-detection.js
+++ b/ui/app/mixins/with-route-visibility-detection.js
@@ -9,14 +9,14 @@ export default Mixin.create({
assert('visibilityHandler needs to be overridden in the Route', false);
},
- setupDocumentVisibility: on('activate', function() {
+ setupDocumentVisibility: on('activate', function () {
if (!Ember.testing) {
this.set('_visibilityHandler', this.visibilityHandler.bind(this));
document.addEventListener('visibilitychange', this._visibilityHandler);
}
}),
- removeDocumentVisibility: on('deactivate', function() {
+ removeDocumentVisibility: on('deactivate', function () {
if (!Ember.testing) {
document.removeEventListener('visibilitychange', this._visibilityHandler);
}
diff --git a/ui/app/mixins/with-watchers.js b/ui/app/mixins/with-watchers.js
index 811a2c792..b74a2b031 100644
--- a/ui/app/mixins/with-watchers.js
+++ b/ui/app/mixins/with-watchers.js
@@ -5,12 +5,12 @@ import WithVisibilityDetection from './with-route-visibility-detection';
// eslint-disable-next-line ember/no-new-mixins
export default Mixin.create(WithVisibilityDetection, {
- watchers: computed(function() {
+ watchers: computed(function () {
return [];
}),
cancelAllWatchers() {
- this.watchers.forEach(watcher => {
+ this.watchers.forEach((watcher) => {
assert('Watchers must be Ember Concurrency Tasks.', !!watcher.cancelAll);
watcher.cancelAll();
});
@@ -36,7 +36,10 @@ export default Mixin.create(WithVisibilityDetection, {
actions: {
willTransition(transition) {
// Don't cancel watchers if transitioning into a sub-route
- if (!transition.intent.name || !transition.intent.name.startsWith(this.routeName)) {
+ if (
+ !transition.intent.name ||
+ !transition.intent.name.startsWith(this.routeName)
+ ) {
this.cancelAllWatchers();
}
diff --git a/ui/app/models/allocation.js b/ui/app/models/allocation.js
index 79db30dd1..45d42727e 100644
--- a/ui/app/models/allocation.js
+++ b/ui/app/models/allocation.js
@@ -35,9 +35,7 @@ export default class Allocation extends Model {
@attr('string') nodeName;
@computed
get shortNodeId() {
- return this.belongsTo('node')
- .id()
- .split('-')[0];
+ return this.belongsTo('node').id().split('-')[0];
}
@attr('number') modifyIndex;
@@ -77,8 +75,10 @@ export default class Allocation extends Model {
@belongsTo('allocation', { inverse: 'nextAllocation' }) previousAllocation;
@belongsTo('allocation', { inverse: 'previousAllocation' }) nextAllocation;
- @hasMany('allocation', { inverse: 'preemptedByAllocation' }) preemptedAllocations;
- @belongsTo('allocation', { inverse: 'preemptedAllocations' }) preemptedByAllocation;
+ @hasMany('allocation', { inverse: 'preemptedByAllocation' })
+ preemptedAllocations;
+ @belongsTo('allocation', { inverse: 'preemptedAllocations' })
+ preemptedByAllocation;
@attr('boolean') wasPreempted;
@belongsTo('evaluation') followUpEvaluation;
@@ -135,7 +135,11 @@ export default class Allocation extends Model {
return this.get('rescheduleEvents.length') > 0 || this.nextAllocation;
}
- @computed('clientStatus', 'followUpEvaluation.content', 'nextAllocation.content')
+ @computed(
+ 'clientStatus',
+ 'followUpEvaluation.content',
+ 'nextAllocation.content'
+ )
get hasStoppedRescheduling() {
return (
!this.get('nextAllocation.content') &&
diff --git a/ui/app/models/deployment.js b/ui/app/models/deployment.js
index 97504e01d..0136f6380 100644
--- a/ui/app/models/deployment.js
+++ b/ui/app/models/deployment.js
@@ -24,7 +24,10 @@ export default class Deployment extends Model {
this.status === 'running' &&
this.taskGroupSummaries
.toArray()
- .some(summary => summary.get('requiresPromotion') && !summary.get('promoted'))
+ .some(
+ (summary) =>
+ summary.get('requiresPromotion') && !summary.get('promoted')
+ )
);
}
@@ -38,7 +41,10 @@ export default class Deployment extends Model {
@computed('versionNumber', 'job.versions.content.@each.number')
get version() {
- return (this.get('job.versions') || []).findBy('number', this.versionNumber);
+ return (this.get('job.versions') || []).findBy(
+ 'number',
+ this.versionNumber
+ );
}
// Dependent keys can only go one level past an @each so an alias is needed
@@ -65,7 +71,10 @@ export default class Deployment extends Model {
}
promote() {
- assert('A deployment needs to requirePromotion to be promoted', this.requiresPromotion);
+ assert(
+ 'A deployment needs to requirePromotion to be promoted',
+ this.requiresPromotion
+ );
return this.store.adapterFor('deployment').promote(this);
}
diff --git a/ui/app/models/evaluation.js b/ui/app/models/evaluation.js
index 8cd50ba2a..944d03e10 100644
--- a/ui/app/models/evaluation.js
+++ b/ui/app/models/evaluation.js
@@ -11,7 +11,8 @@ export default class Evaluation extends Model {
@attr('string') triggeredBy;
@attr('string') status;
@attr('string') statusDescription;
- @fragmentArray('placement-failure', { defaultValue: () => [] }) failedTGAllocs;
+ @fragmentArray('placement-failure', { defaultValue: () => [] })
+ failedTGAllocs;
@bool('failedTGAllocs.length') hasPlacementFailures;
@equal('status', 'blocked') isBlocked;
diff --git a/ui/app/models/job-plan.js b/ui/app/models/job-plan.js
index b7a06db06..7cebc1cc0 100644
--- a/ui/app/models/job-plan.js
+++ b/ui/app/models/job-plan.js
@@ -5,6 +5,7 @@ import { hasMany } from '@ember-data/model';
export default class JobPlan extends Model {
@attr() diff;
- @fragmentArray('placement-failure', { defaultValue: () => [] }) failedTGAllocs;
+ @fragmentArray('placement-failure', { defaultValue: () => [] })
+ failedTGAllocs;
@hasMany('allocation') preemptions;
}
diff --git a/ui/app/models/job.js b/ui/app/models/job.js
index 43c82e5d1..b157592ef 100644
--- a/ui/app/models/job.js
+++ b/ui/app/models/job.js
@@ -51,7 +51,9 @@ export default class Job extends Model {
// The parent job name is prepended to child launch job names
@computed('name', 'parent.content')
get trimmedName() {
- return this.get('parent.content') ? this.name.replace(/.+?\//, '') : this.name;
+ return this.get('parent.content')
+ ? this.name.replace(/.+?\//, '')
+ : this.name;
}
// A composite of type and other job attributes to determine
@@ -69,7 +71,12 @@ export default class Job extends Model {
// A composite of type and other job attributes to determine
// type for templating rather than scheduling
- @computed('type', 'periodic', 'parameterized', 'parent.{periodic,parameterized}')
+ @computed(
+ 'type',
+ 'periodic',
+ 'parameterized',
+ 'parent.{periodic,parameterized}'
+ )
get templateType() {
const type = this.type;
@@ -158,7 +165,9 @@ export default class Job extends Model {
@computed('evaluations.@each.isBlocked')
get hasBlockedEvaluation() {
- return this.evaluations.toArray().some(evaluation => evaluation.get('isBlocked'));
+ return this.evaluations
+ .toArray()
+ .some((evaluation) => evaluation.get('isBlocked'));
}
@and('latestFailureEvaluation', 'hasBlockedEvaluation') hasPlacementFailures;
@@ -246,7 +255,7 @@ export default class Job extends Model {
promise = this.store
.adapterFor('job')
.parse(this._newDefinition)
- .then(response => {
+ .then((response) => {
this.set('_newDefinitionJSON', response);
this.setIdByPayload(response);
});
@@ -256,7 +265,8 @@ export default class Job extends Model {
}
scale(group, count, message) {
- if (message == null) message = `Manually scaled to ${count} from the Nomad UI`;
+ if (message == null)
+ message = `Manually scaled to ${count} from the Nomad UI`;
return this.store.adapterFor('job').scale(this, group, count, message);
}
@@ -278,7 +288,10 @@ export default class Job extends Model {
}
resetId() {
- this.set('id', JSON.stringify([this.plainId, this.get('namespace.name') || 'default']));
+ this.set(
+ 'id',
+ JSON.stringify([this.plainId, this.get('namespace.name') || 'default'])
+ );
}
@computed('status')
diff --git a/ui/app/models/node.js b/ui/app/models/node.js
index abb0958a2..3e985bd4d 100644
--- a/ui/app/models/node.js
+++ b/ui/app/models/node.js
@@ -63,7 +63,9 @@ export default class Node extends Model {
@computed('allocations.@each.{isMigrating,isRunning}')
get migratingAllocations() {
- return this.allocations.filter(alloc => alloc.isRunning && alloc.isMigrating);
+ return this.allocations.filter(
+ (alloc) => alloc.isRunning && alloc.isMigrating
+ );
}
@computed('allocations.@each.{isMigrating,isRunning,modifyTime}')
diff --git a/ui/app/models/recommendation-summary.js b/ui/app/models/recommendation-summary.js
index 459b780e5..e3ca79226 100644
--- a/ui/app/models/recommendation-summary.js
+++ b/ui/app/models/recommendation-summary.js
@@ -5,7 +5,8 @@ import { action } from '@ember/object';
export default class RecommendationSummary extends Model {
@hasMany('recommendation') recommendations;
- @hasMany('recommendation', { defaultValue: () => [] }) excludedRecommendations;
+ @hasMany('recommendation', { defaultValue: () => [] })
+ excludedRecommendations;
@belongsTo('job') job;
@attr('string') jobId;
@@ -30,7 +31,8 @@ export default class RecommendationSummary extends Model {
@action
toggleRecommendation(recommendation) {
if (this.excludedRecommendations.includes(recommendation)) {
- this.excludedRecommendations = this.excludedRecommendations.removeObject(recommendation);
+ this.excludedRecommendations =
+ this.excludedRecommendations.removeObject(recommendation);
} else {
this.excludedRecommendations.pushObject(recommendation);
}
@@ -39,9 +41,14 @@ export default class RecommendationSummary extends Model {
@action
toggleAllRecommendationsForResource(resource, enabled) {
if (enabled) {
- this.excludedRecommendations = this.excludedRecommendations.rejectBy('resource', resource);
+ this.excludedRecommendations = this.excludedRecommendations.rejectBy(
+ 'resource',
+ resource
+ );
} else {
- this.excludedRecommendations.pushObjects(this.recommendations.filterBy('resource', resource));
+ this.excludedRecommendations.pushObjects(
+ this.recommendations.filterBy('resource', resource)
+ );
}
}
diff --git a/ui/app/models/recommendation.js b/ui/app/models/recommendation.js
index cb36e2504..36e2ed341 100644
--- a/ui/app/models/recommendation.js
+++ b/ui/app/models/recommendation.js
@@ -4,7 +4,8 @@ import { get } from '@ember/object';
export default class Recommendation extends Model {
@belongsTo('job') job;
- @belongsTo('recommendation-summary', { inverse: 'recommendations' }) recommendationSummary;
+ @belongsTo('recommendation-summary', { inverse: 'recommendations' })
+ recommendationSummary;
@attr('date') submitTime;
@@ -22,7 +23,8 @@ export default class Recommendation extends Model {
@attr('number') value;
get currentValue() {
- const resourceProperty = this.resource === 'CPU' ? 'reservedCPU' : 'reservedMemory';
+ const resourceProperty =
+ this.resource === 'CPU' ? 'reservedCPU' : 'reservedMemory';
return get(this, `task.${resourceProperty}`);
}
diff --git a/ui/app/models/scale-event.js b/ui/app/models/scale-event.js
index 1ff4063c7..083f35a51 100644
--- a/ui/app/models/scale-event.js
+++ b/ui/app/models/scale-event.js
@@ -11,12 +11,12 @@ export default class ScaleEvent extends Fragment {
@attr('boolean') error;
@attr('string') evalId;
- @computed('count', function() {
+ @computed('count', function () {
return this.count != null;
})
hasCount;
- @computed('count', 'previousCount', function() {
+ @computed('count', 'previousCount', function () {
return this.count > this.previousCount;
})
increased;
@@ -27,13 +27,13 @@ export default class ScaleEvent extends Fragment {
@attr('string') message;
@attr() meta;
- @computed('meta', function() {
+ @computed('meta', function () {
return Object.keys(this.meta).length > 0;
})
hasMeta;
// Since scale events don't have proper IDs, this UID is a compromise
- @computed('time', 'timeNanos', 'message', function() {
+ @computed('time', 'timeNanos', 'message', function () {
return `${+this.time}${this.timeNanos}_${this.message}`;
})
uid;
diff --git a/ui/app/models/task-group-scale.js b/ui/app/models/task-group-scale.js
index 5429a2837..9eb5238d4 100644
--- a/ui/app/models/task-group-scale.js
+++ b/ui/app/models/task-group-scale.js
@@ -1,7 +1,10 @@
import { computed } from '@ember/object';
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
-import { fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
+import {
+ fragmentOwner,
+ fragmentArray,
+} from 'ember-data-model-fragments/attributes';
export default class TaskGroupScale extends Fragment {
@fragmentOwner() jobScale;
diff --git a/ui/app/models/task-group.js b/ui/app/models/task-group.js
index 5ea8f2667..afeafe69c 100644
--- a/ui/app/models/task-group.js
+++ b/ui/app/models/task-group.js
@@ -1,11 +1,15 @@
import { computed } from '@ember/object';
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
-import { fragmentOwner, fragmentArray, fragment } from 'ember-data-model-fragments/attributes';
+import {
+ fragmentOwner,
+ fragmentArray,
+ fragment,
+} from 'ember-data-model-fragments/attributes';
import sumAggregation from '../utils/properties/sum-aggregation';
import classic from 'ember-classic-decorator';
-const maybe = arr => arr || [];
+const maybe = (arr) => arr || [];
@classic
export default class TaskGroup extends Fragment {
@@ -39,7 +43,10 @@ export default class TaskGroup extends Fragment {
@computed('job.allocations.@each.taskGroup', 'name')
get allocations() {
- return maybe(this.get('job.allocations')).filterBy('taskGroupName', this.name);
+ return maybe(this.get('job.allocations')).filterBy(
+ 'taskGroupName',
+ this.name
+ );
}
@sumAggregation('tasks', 'reservedCPU') reservedCPU;
@@ -49,7 +56,7 @@ export default class TaskGroup extends Fragment {
@computed('tasks.@each.{reservedMemory,reservedMemoryMax}')
get reservedMemoryMax() {
return this.get('tasks')
- .map(t => t.get('reservedMemoryMax') || t.get('reservedMemory'))
+ .map((t) => t.get('reservedMemoryMax') || t.get('reservedMemory'))
.reduce((sum, count) => sum + count, 0);
}
@@ -57,13 +64,17 @@ export default class TaskGroup extends Fragment {
@computed('job.latestFailureEvaluation.failedTGAllocs.[]', 'name')
get placementFailures() {
- const placementFailures = this.get('job.latestFailureEvaluation.failedTGAllocs');
+ const placementFailures = this.get(
+ 'job.latestFailureEvaluation.failedTGAllocs'
+ );
return placementFailures && placementFailures.findBy('name', this.name);
}
@computed('summary.{queuedAllocs,startingAllocs}')
get queuedOrStartingAllocs() {
- return this.get('summary.queuedAllocs') + this.get('summary.startingAllocs');
+ return (
+ this.get('summary.queuedAllocs') + this.get('summary.startingAllocs')
+ );
}
@computed('job.taskGroupSummaries.[]', 'name')
@@ -73,7 +84,10 @@ export default class TaskGroup extends Fragment {
@computed('job.scaleState.taskGroupScales.[]', 'name')
get scaleState() {
- return maybe(this.get('job.scaleState.taskGroupScales')).findBy('name', this.name);
+ return maybe(this.get('job.scaleState.taskGroupScales')).findBy(
+ 'name',
+ this.name
+ );
}
scale(count, message) {
diff --git a/ui/app/models/task-state.js b/ui/app/models/task-state.js
index 416a89c8e..0f80cdc30 100644
--- a/ui/app/models/task-state.js
+++ b/ui/app/models/task-state.js
@@ -2,7 +2,11 @@ import { computed } from '@ember/object';
import { alias, none, and } from '@ember/object/computed';
import Fragment from 'ember-data-model-fragments/fragment';
import { attr } from '@ember-data/model';
-import { fragment, fragmentOwner, fragmentArray } from 'ember-data-model-fragments/attributes';
+import {
+ fragment,
+ fragmentOwner,
+ fragmentArray,
+} from 'ember-data-model-fragments/attributes';
import classic from 'ember-classic-decorator';
@classic
diff --git a/ui/app/models/task.js b/ui/app/models/task.js
index bf9a0a3eb..83c22f64e 100644
--- a/ui/app/models/task.js
+++ b/ui/app/models/task.js
@@ -1,6 +1,10 @@
import { attr } from '@ember-data/model';
import Fragment from 'ember-data-model-fragments/fragment';
-import { fragment, fragmentArray, fragmentOwner } from 'ember-data-model-fragments/attributes';
+import {
+ fragment,
+ fragmentArray,
+ fragmentOwner,
+} from 'ember-data-model-fragments/attributes';
import { computed } from '@ember/object';
export default class Task extends Fragment {
diff --git a/ui/app/models/volume.js b/ui/app/models/volume.js
index 6e290af5f..f7de4b1f0 100644
--- a/ui/app/models/volume.js
+++ b/ui/app/models/volume.js
@@ -14,7 +14,10 @@ export default class Volume extends Model {
@computed('writeAllocations.[]', 'readAllocations.[]')
get allocations() {
- return [...this.writeAllocations.toArray(), ...this.readAllocations.toArray()];
+ return [
+ ...this.writeAllocations.toArray(),
+ ...this.readAllocations.toArray(),
+ ];
}
@attr('number') currentWriters;
diff --git a/ui/app/modifiers/window-resize.js b/ui/app/modifiers/window-resize.js
index f70b20976..d361a652f 100644
--- a/ui/app/modifiers/window-resize.js
+++ b/ui/app/modifiers/window-resize.js
@@ -1,7 +1,7 @@
import { modifier } from 'ember-modifier';
export default modifier(function windowResize(element, [handler]) {
- const boundHandler = ev => handler(element, ev);
+ const boundHandler = (ev) => handler(element, ev);
window.addEventListener('resize', boundHandler);
return () => {
diff --git a/ui/app/router.js b/ui/app/router.js
index 8e5c20708..d567714f1 100644
--- a/ui/app/router.js
+++ b/ui/app/router.js
@@ -6,16 +6,16 @@ export default class Router extends EmberRouter {
rootURL = config.rootURL;
}
-Router.map(function() {
- this.route('exec', { path: '/exec/:job_name' }, function() {
- this.route('task-group', { path: '/:task_group_name' }, function() {
+Router.map(function () {
+ this.route('exec', { path: '/exec/:job_name' }, function () {
+ this.route('task-group', { path: '/:task_group_name' }, function () {
this.route('task', { path: '/:task_name' });
});
});
- this.route('jobs', function() {
+ this.route('jobs', function () {
this.route('run');
- this.route('job', { path: '/:job_name' }, function() {
+ this.route('job', { path: '/:job_name' }, function () {
this.route('task-group', { path: '/:name' });
this.route('definition');
this.route('versions');
@@ -27,42 +27,42 @@ Router.map(function() {
});
});
- this.route('optimize', function() {
+ this.route('optimize', function () {
this.route('summary', { path: '*slug' });
});
- this.route('clients', function() {
- this.route('client', { path: '/:node_id' }, function() {
+ this.route('clients', function () {
+ this.route('client', { path: '/:node_id' }, function () {
this.route('monitor');
});
});
- this.route('servers', function() {
- this.route('server', { path: '/:agent_id' }, function() {
+ this.route('servers', function () {
+ this.route('server', { path: '/:agent_id' }, function () {
this.route('monitor');
});
});
this.route('topology');
- this.route('csi', function() {
- this.route('volumes', function() {
+ this.route('csi', function () {
+ this.route('volumes', function () {
this.route('volume', { path: '/:volume_name' });
});
- this.route('plugins', function() {
- this.route('plugin', { path: '/:plugin_name' }, function() {
+ this.route('plugins', function () {
+ this.route('plugin', { path: '/:plugin_name' }, function () {
this.route('allocations');
});
});
});
- this.route('allocations', function() {
- this.route('allocation', { path: '/:allocation_id' }, function() {
+ this.route('allocations', function () {
+ this.route('allocation', { path: '/:allocation_id' }, function () {
this.route('fs-root', { path: '/fs' });
this.route('fs', { path: '/fs/*path' });
- this.route('task', { path: '/:name' }, function() {
+ this.route('task', { path: '/:name' }, function () {
this.route('logs');
this.route('fs-root', { path: '/fs' });
this.route('fs', { path: '/fs/*path' });
@@ -70,7 +70,7 @@ Router.map(function() {
});
});
- this.route('settings', function() {
+ this.route('settings', function () {
this.route('tokens');
});
diff --git a/ui/app/routes/allocations/allocation.js b/ui/app/routes/allocations/allocation.js
index bb5ce7bfc..f95ebc31e 100644
--- a/ui/app/routes/allocations/allocation.js
+++ b/ui/app/routes/allocations/allocation.js
@@ -17,7 +17,7 @@ export default class AllocationRoute extends Route.extend(WithWatchers) {
// Preload the job for the allocation since it's required for the breadcrumb trail
return super
.model(...arguments)
- .then(allocation =>
+ .then((allocation) =>
allocation
.get('job')
.then(() => this.store.findAll('namespace')) // namespaces belong to a job and are an asynchronous relationship so we can peak them later on
diff --git a/ui/app/routes/allocations/allocation/fs.js b/ui/app/routes/allocations/allocation/fs.js
index c988b7e05..1f01725df 100644
--- a/ui/app/routes/allocations/allocation/fs.js
+++ b/ui/app/routes/allocations/allocation/fs.js
@@ -15,7 +15,9 @@ export default class FsRoute extends Route {
return RSVP.hash({
path: decodedPath,
allocation,
- directoryEntries: allocation.ls(decodedPath).catch(notifyError(this)),
+ directoryEntries: allocation
+ .ls(decodedPath)
+ .catch(notifyError(this)),
isFile: false,
});
} else {
@@ -30,8 +32,17 @@ export default class FsRoute extends Route {
.catch(notifyError(this));
}
- setupController(controller, { path, allocation, directoryEntries, isFile, stat } = {}) {
+ setupController(
+ controller,
+ { path, allocation, directoryEntries, isFile, stat } = {}
+ ) {
super.setupController(...arguments);
- controller.setProperties({ path, allocation, directoryEntries, isFile, stat });
+ controller.setProperties({
+ path,
+ allocation,
+ directoryEntries,
+ isFile,
+ stat,
+ });
}
}
diff --git a/ui/app/routes/allocations/allocation/index.js b/ui/app/routes/allocations/allocation/index.js
index e4de01cdb..672ce3330 100644
--- a/ui/app/routes/allocations/allocation/index.js
+++ b/ui/app/routes/allocations/allocation/index.js
@@ -4,7 +4,8 @@ export default class IndexRoute extends Route {
setupController(controller, model) {
// Suppress the preemptedByAllocation fetch error in the event it's a 404
if (model) {
- const setPreempter = () => controller.set('preempter', model.preemptedByAllocation);
+ const setPreempter = () =>
+ controller.set('preempter', model.preemptedByAllocation);
model.preemptedByAllocation.then(setPreempter, setPreempter);
}
diff --git a/ui/app/routes/allocations/allocation/task.js b/ui/app/routes/allocations/allocation/task.js
index 03be52f3c..8513aecbc 100644
--- a/ui/app/routes/allocations/allocation/task.js
+++ b/ui/app/routes/allocations/allocation/task.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-controller-access-in-routes */
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import EmberError from '@ember/error';
@@ -15,7 +16,9 @@ export default class TaskRoute extends Route {
const task = allocation.get('states').findBy('name', name);
if (!task) {
- const err = new EmberError(`Task ${name} not found for allocation ${allocation.get('id')}`);
+ const err = new EmberError(
+ `Task ${name} not found for allocation ${allocation.get('id')}`
+ );
err.code = '404';
this.controllerFor('application').set('error', err);
}
diff --git a/ui/app/routes/allocations/allocation/task/fs.js b/ui/app/routes/allocations/allocation/task/fs.js
index 8ba69555c..3143c9017 100644
--- a/ui/app/routes/allocations/allocation/task/fs.js
+++ b/ui/app/routes/allocations/allocation/task/fs.js
@@ -14,13 +14,18 @@ export default class FsRoute extends Route {
decodedPath.startsWith('/') ? '' : '/'
}${decodedPath}`;
- return RSVP.all([allocation.stat(pathWithTaskName), taskState.get('allocation.node')])
+ return RSVP.all([
+ allocation.stat(pathWithTaskName),
+ taskState.get('allocation.node'),
+ ])
.then(([statJson]) => {
if (statJson.IsDir) {
return RSVP.hash({
path: decodedPath,
taskState,
- directoryEntries: allocation.ls(pathWithTaskName).catch(notifyError(this)),
+ directoryEntries: allocation
+ .ls(pathWithTaskName)
+ .catch(notifyError(this)),
isFile: false,
});
} else {
@@ -35,8 +40,17 @@ export default class FsRoute extends Route {
.catch(notifyError(this));
}
- setupController(controller, { path, taskState, directoryEntries, isFile, stat } = {}) {
+ setupController(
+ controller,
+ { path, taskState, directoryEntries, isFile, stat } = {}
+ ) {
super.setupController(...arguments);
- controller.setProperties({ path, taskState, directoryEntries, isFile, stat });
+ controller.setProperties({
+ path,
+ taskState,
+ directoryEntries,
+ isFile,
+ stat,
+ });
}
}
diff --git a/ui/app/routes/application.js b/ui/app/routes/application.js
index f92fd5b3c..be815bd44 100644
--- a/ui/app/routes/application.js
+++ b/ui/app/routes/application.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-controller-access-in-routes */
import { inject as service } from '@ember/service';
import { later, next } from '@ember/runloop';
import Route from '@ember/routing/route';
@@ -33,11 +34,12 @@ export default class ApplicationRoute extends Route {
if (transition.queryParamsOnly) {
promises = Promise.resolve(true);
} else {
-
let exchangeOneTimeToken;
if (transition.to.queryParams.ott) {
- exchangeOneTimeToken = this.get('token').exchangeOneTimeToken(transition.to.queryParams.ott);
+ exchangeOneTimeToken = this.get('token').exchangeOneTimeToken(
+ transition.to.queryParams.ott
+ );
} else {
exchangeOneTimeToken = Promise.resolve(true);
}
@@ -48,15 +50,17 @@ export default class ApplicationRoute extends Route {
this.controllerFor('application').set('error', e);
}
- const fetchSelfTokenAndPolicies = this.get('token.fetchSelfTokenAndPolicies')
+ const fetchSelfTokenAndPolicies = this.get(
+ 'token.fetchSelfTokenAndPolicies'
+ )
.perform()
.catch();
- const fetchLicense = this.get('system.fetchLicense')
- .perform()
- .catch();
+ const fetchLicense = this.get('system.fetchLicense').perform().catch();
- const checkFuzzySearchPresence = this.get('system.checkFuzzySearchPresence')
+ const checkFuzzySearchPresence = this.get(
+ 'system.checkFuzzySearchPresence'
+ )
.perform()
.catch();
diff --git a/ui/app/routes/clients/client.js b/ui/app/routes/clients/client.js
index 7dc94a49d..3593cf107 100644
--- a/ui/app/routes/clients/client.js
+++ b/ui/app/routes/clients/client.js
@@ -11,7 +11,7 @@ export default class ClientRoute extends Route {
afterModel(model) {
if (model && model.get('isPartial')) {
- return model.reload().then(node => node.get('allocations'));
+ return model.reload().then((node) => node.get('allocations'));
}
return model && model.get('allocations');
}
diff --git a/ui/app/routes/clients/client/index.js b/ui/app/routes/clients/client/index.js
index 04f66faa6..b1383ca47 100644
--- a/ui/app/routes/clients/client/index.js
+++ b/ui/app/routes/clients/client/index.js
@@ -1,7 +1,10 @@
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
import { collect } from '@ember/object/computed';
-import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch';
+import {
+ watchRecord,
+ watchRelationship,
+} from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default class ClientRoute extends Route.extend(WithWatchers) {
diff --git a/ui/app/routes/csi/plugins.js b/ui/app/routes/csi/plugins.js
index 25728b2d2..9d24bc239 100644
--- a/ui/app/routes/csi/plugins.js
+++ b/ui/app/routes/csi/plugins.js
@@ -7,6 +7,8 @@ export default class PluginsRoute extends Route.extend(WithForbiddenState) {
@service store;
model() {
- return this.store.query('plugin', { type: 'csi' }).catch(notifyForbidden(this));
+ return this.store
+ .query('plugin', { type: 'csi' })
+ .catch(notifyForbidden(this));
}
}
diff --git a/ui/app/routes/csi/plugins/plugin.js b/ui/app/routes/csi/plugins/plugin.js
index 9728e5be1..41cbfb381 100644
--- a/ui/app/routes/csi/plugins/plugin.js
+++ b/ui/app/routes/csi/plugins/plugin.js
@@ -11,6 +11,8 @@ export default class PluginRoute extends Route {
}
model(params) {
- return this.store.findRecord('plugin', `csi/${params.plugin_name}`).catch(notifyError(this));
+ return this.store
+ .findRecord('plugin', `csi/${params.plugin_name}`)
+ .catch(notifyError(this));
}
}
diff --git a/ui/app/routes/csi/volumes/index.js b/ui/app/routes/csi/volumes/index.js
index f2db7cfa0..62d3db557 100644
--- a/ui/app/routes/csi/volumes/index.js
+++ b/ui/app/routes/csi/volumes/index.js
@@ -7,7 +7,10 @@ import WithWatchers from 'nomad-ui/mixins/with-watchers';
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
-export default class IndexRoute extends Route.extend(WithWatchers, WithForbiddenState) {
+export default class IndexRoute extends Route.extend(
+ WithWatchers,
+ WithForbiddenState
+) {
@service store;
queryParams = {
@@ -29,7 +32,10 @@ export default class IndexRoute extends Route.extend(WithWatchers, WithForbidden
controller.set('namespacesWatch', this.watchNamespaces.perform());
controller.set(
'modelWatch',
- this.watchVolumes.perform({ type: 'csi', namespace: controller.qpNamespace })
+ this.watchVolumes.perform({
+ type: 'csi',
+ namespace: controller.qpNamespace,
+ })
);
}
diff --git a/ui/app/routes/csi/volumes/volume.js b/ui/app/routes/csi/volumes/volume.js
index 01afa4b4c..e5722374a 100644
--- a/ui/app/routes/csi/volumes/volume.js
+++ b/ui/app/routes/csi/volumes/volume.js
@@ -32,7 +32,7 @@ export default class VolumeRoute extends Route.extend(WithWatchers) {
volume: this.store.findRecord('volume', fullId, { reload: true }),
namespaces: this.store.findAll('namespace'),
})
- .then(hash => hash.volume)
+ .then((hash) => hash.volume)
.catch(notifyError(this));
}
diff --git a/ui/app/routes/exec.js b/ui/app/routes/exec.js
index 4a9d009bd..33493e7a4 100644
--- a/ui/app/routes/exec.js
+++ b/ui/app/routes/exec.js
@@ -3,7 +3,10 @@ import Route from '@ember/routing/route';
import notifyError from 'nomad-ui/utils/notify-error';
import { collect } from '@ember/object/computed';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
-import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch';
+import {
+ watchRecord,
+ watchRelationship,
+} from 'nomad-ui/utils/properties/watch';
import classic from 'ember-classic-decorator';
@classic
@@ -22,12 +25,12 @@ export default class ExecRoute extends Route.extend(WithWatchers) {
const jobPromise = this.store
.findRecord('job', fullId)
- .then(job => {
+ .then((job) => {
return job.get('allocations').then(() => job);
})
.catch(notifyError(this));
- const xtermImport = import('xterm').then(module => module.Terminal);
+ const xtermImport = import('xterm').then((module) => module.Terminal);
return Promise.all([jobPromise, xtermImport]);
}
diff --git a/ui/app/routes/exec/task-group/task.js b/ui/app/routes/exec/task-group/task.js
index 39ce0a899..b20d209b5 100644
--- a/ui/app/routes/exec/task-group/task.js
+++ b/ui/app/routes/exec/task-group/task.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-controller-access-in-routes */
import { inject as service } from '@ember/service';
import Route from '@ember/routing/route';
diff --git a/ui/app/routes/jobs/index.js b/ui/app/routes/jobs/index.js
index a9d4edf39..93bc9d39e 100644
--- a/ui/app/routes/jobs/index.js
+++ b/ui/app/routes/jobs/index.js
@@ -7,7 +7,10 @@ import WithWatchers from 'nomad-ui/mixins/with-watchers';
import notifyForbidden from 'nomad-ui/utils/notify-forbidden';
import WithForbiddenState from 'nomad-ui/mixins/with-forbidden-state';
-export default class IndexRoute extends Route.extend(WithWatchers, WithForbiddenState) {
+export default class IndexRoute extends Route.extend(
+ WithWatchers,
+ WithForbiddenState
+) {
@service store;
queryParams = {
@@ -18,14 +21,19 @@ export default class IndexRoute extends Route.extend(WithWatchers, WithForbidden
model(params) {
return RSVP.hash({
- jobs: this.store.query('job', { namespace: params.qpNamespace }).catch(notifyForbidden(this)),
+ jobs: this.store
+ .query('job', { namespace: params.qpNamespace })
+ .catch(notifyForbidden(this)),
namespaces: this.store.findAll('namespace'),
});
}
startWatchers(controller) {
controller.set('namespacesWatch', this.watchNamespaces.perform());
- controller.set('modelWatch', this.watchJobs.perform({ namespace: controller.qpNamesapce }));
+ controller.set(
+ 'modelWatch',
+ this.watchJobs.perform({ namespace: controller.qpNamesapce })
+ );
}
@watchQuery('job') watchJobs;
diff --git a/ui/app/routes/jobs/job.js b/ui/app/routes/jobs/job.js
index 971d5be80..3a01c84ba 100644
--- a/ui/app/routes/jobs/job.js
+++ b/ui/app/routes/jobs/job.js
@@ -21,7 +21,7 @@ export default class JobRoute extends Route {
return this.store
.findRecord('job', fullId, { reload: true })
- .then(job => {
+ .then((job) => {
const relatedModelsQueries = [
job.get('allocations'),
job.get('evaluations'),
diff --git a/ui/app/routes/jobs/job/clients.js b/ui/app/routes/jobs/job/clients.js
index 71b9d23e8..bcd3a5af3 100644
--- a/ui/app/routes/jobs/job/clients.js
+++ b/ui/app/routes/jobs/job/clients.js
@@ -1,6 +1,10 @@
import Route from '@ember/routing/route';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
-import { watchRecord, watchRelationship, watchAll } from 'nomad-ui/utils/properties/watch';
+import {
+ watchRecord,
+ watchRelationship,
+ watchAll,
+} from 'nomad-ui/utils/properties/watch';
import { collect } from '@ember/object/computed';
export default class ClientsRoute extends Route.extend(WithWatchers) {
diff --git a/ui/app/routes/jobs/job/definition.js b/ui/app/routes/jobs/job/definition.js
index 4b089e871..b122e3d5f 100644
--- a/ui/app/routes/jobs/job/definition.js
+++ b/ui/app/routes/jobs/job/definition.js
@@ -5,7 +5,7 @@ export default class DefinitionRoute extends Route {
const job = this.modelFor('jobs.job');
if (!job) return;
- return job.fetchRawDefinition().then(definition => ({
+ return job.fetchRawDefinition().then((definition) => ({
job,
definition,
}));
diff --git a/ui/app/routes/jobs/job/deployments.js b/ui/app/routes/jobs/job/deployments.js
index e1e9d6b49..94aa0c1da 100644
--- a/ui/app/routes/jobs/job/deployments.js
+++ b/ui/app/routes/jobs/job/deployments.js
@@ -7,7 +7,10 @@ import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default class DeploymentsRoute extends Route.extend(WithWatchers) {
model() {
const job = this.modelFor('jobs.job');
- return job && RSVP.all([job.get('deployments'), job.get('versions')]).then(() => job);
+ return (
+ job &&
+ RSVP.all([job.get('deployments'), job.get('versions')]).then(() => job)
+ );
}
startWatchers(controller, model) {
diff --git a/ui/app/routes/jobs/job/index.js b/ui/app/routes/jobs/job/index.js
index b085ca744..8accf8734 100644
--- a/ui/app/routes/jobs/job/index.js
+++ b/ui/app/routes/jobs/job/index.js
@@ -38,10 +38,13 @@ export default class IndexRoute extends Route.extend(WithWatchers) {
allocations: this.watchAllocations.perform(model.job),
evaluations: this.watchEvaluations.perform(model.job),
latestDeployment:
- model.job.get('supportsDeployments') && this.watchLatestDeployment.perform(model.job),
+ model.job.get('supportsDeployments') &&
+ this.watchLatestDeployment.perform(model.job),
list:
model.job.get('hasChildren') &&
- this.watchAllJobs.perform({ namespace: model.job.namespace.get('name') }),
+ this.watchAllJobs.perform({
+ namespace: model.job.namespace.get('name'),
+ }),
nodes:
this.can.can('read client') &&
model.job.get('hasClientStatus') &&
@@ -52,7 +55,10 @@ export default class IndexRoute extends Route.extend(WithWatchers) {
setupController(controller, model) {
// Parameterized and periodic detail pages, which list children jobs,
// should sort by submit time.
- if (model.job && ['periodic', 'parameterized'].includes(model.job.templateType)) {
+ if (
+ model.job &&
+ ['periodic', 'parameterized'].includes(model.job.templateType)
+ ) {
controller.setProperties({
sortProperty: 'submitTime',
sortDescending: true,
diff --git a/ui/app/routes/jobs/job/task-group.js b/ui/app/routes/jobs/job/task-group.js
index 17ea124f4..88b654301 100644
--- a/ui/app/routes/jobs/job/task-group.js
+++ b/ui/app/routes/jobs/job/task-group.js
@@ -2,7 +2,10 @@ import Route from '@ember/routing/route';
import { collect } from '@ember/object/computed';
import EmberError from '@ember/error';
import { resolve, all } from 'rsvp';
-import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch';
+import {
+ watchRecord,
+ watchRelationship,
+} from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
import notifyError from 'nomad-ui/utils/notify-error';
@@ -21,15 +24,18 @@ export default class TaskGroupRoute extends Route.extend(WithWatchers) {
.then(() => {
const taskGroup = job.get('taskGroups').findBy('name', name);
if (!taskGroup) {
- const err = new EmberError(`Task group ${name} for job ${job.get('name')} not found`);
+ const err = new EmberError(
+ `Task group ${name} for job ${job.get('name')} not found`
+ );
err.code = '404';
throw err;
}
// Refresh job allocations before-hand (so page sort works on load)
- return all([job.hasMany('allocations').reload(), job.get('scaleState')]).then(
- () => taskGroup
- );
+ return all([
+ job.hasMany('allocations').reload(),
+ job.get('scaleState'),
+ ]).then(() => taskGroup);
})
.catch(notifyError(this));
}
@@ -42,7 +48,9 @@ export default class TaskGroupRoute extends Route.extend(WithWatchers) {
summary: this.watchSummary.perform(job.get('summary')),
scale: this.watchScale.perform(job.get('scaleState')),
allocations: this.watchAllocations.perform(job),
- latestDeployment: job.get('supportsDeployments') && this.watchLatestDeployment.perform(job),
+ latestDeployment:
+ job.get('supportsDeployments') &&
+ this.watchLatestDeployment.perform(job),
});
}
}
@@ -53,6 +61,12 @@ export default class TaskGroupRoute extends Route.extend(WithWatchers) {
@watchRelationship('allocations') watchAllocations;
@watchRelationship('latestDeployment') watchLatestDeployment;
- @collect('watchJob', 'watchSummary', 'watchScale', 'watchAllocations', 'watchLatestDeployment')
+ @collect(
+ 'watchJob',
+ 'watchSummary',
+ 'watchScale',
+ 'watchAllocations',
+ 'watchLatestDeployment'
+ )
watchers;
}
diff --git a/ui/app/routes/jobs/job/versions.js b/ui/app/routes/jobs/job/versions.js
index 2923c321c..dc924197f 100644
--- a/ui/app/routes/jobs/job/versions.js
+++ b/ui/app/routes/jobs/job/versions.js
@@ -1,6 +1,9 @@
import Route from '@ember/routing/route';
import { collect } from '@ember/object/computed';
-import { watchRecord, watchRelationship } from 'nomad-ui/utils/properties/watch';
+import {
+ watchRecord,
+ watchRelationship,
+} from 'nomad-ui/utils/properties/watch';
import WithWatchers from 'nomad-ui/mixins/with-watchers';
export default class VersionsRoute extends Route.extend(WithWatchers) {
diff --git a/ui/app/routes/jobs/run.js b/ui/app/routes/jobs/run.js
index 6d456ead9..915854ebf 100644
--- a/ui/app/routes/jobs/run.js
+++ b/ui/app/routes/jobs/run.js
@@ -9,7 +9,11 @@ export default class RunRoute extends Route {
@service system;
beforeModel(transition) {
- if (this.can.cannot('run job', null, { namespace: transition.to.queryParams.namespace })) {
+ if (
+ this.can.cannot('run job', null, {
+ namespace: transition.to.queryParams.namespace,
+ })
+ ) {
this.transitionTo('jobs');
}
}
diff --git a/ui/app/routes/not-found.js b/ui/app/routes/not-found.js
index 2c7ece2a2..4c1223592 100644
--- a/ui/app/routes/not-found.js
+++ b/ui/app/routes/not-found.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-controller-access-in-routes */
import Route from '@ember/routing/route';
import EmberError from '@ember/error';
diff --git a/ui/app/routes/optimize.js b/ui/app/routes/optimize.js
index 4ba930951..35f348a0c 100644
--- a/ui/app/routes/optimize.js
+++ b/ui/app/routes/optimize.js
@@ -21,9 +21,9 @@ export default class OptimizeRoute extends Route {
const [namespaces] = await RSVP.all([
this.store.findAll('namespace'),
...jobs
- .filter(job => job)
+ .filter((job) => job)
.filterBy('isPartial')
- .map(j => j.reload()),
+ .map((j) => j.reload()),
]);
return {
diff --git a/ui/app/routes/optimize/index.js b/ui/app/routes/optimize/index.js
index 605a6479e..63fd0de2a 100644
--- a/ui/app/routes/optimize/index.js
+++ b/ui/app/routes/optimize/index.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-controller-access-in-routes */
import Route from '@ember/routing/route';
export default class OptimizeIndexRoute extends Route {
diff --git a/ui/app/routes/optimize/summary.js b/ui/app/routes/optimize/summary.js
index 20822f4c2..13e6f30cd 100644
--- a/ui/app/routes/optimize/summary.js
+++ b/ui/app/routes/optimize/summary.js
@@ -4,11 +4,14 @@ import notifyError from 'nomad-ui/utils/notify-error';
export default class OptimizeSummaryRoute extends Route {
async model({ jobNamespace, slug }) {
const model = this.modelFor('optimize').summaries.find(
- summary => summary.slug === slug && summary.jobNamespace === jobNamespace
+ (summary) =>
+ summary.slug === slug && summary.jobNamespace === jobNamespace
);
if (!model) {
- const error = new Error(`Unable to find summary for ${slug} in namespace ${jobNamespace}`);
+ const error = new Error(
+ `Unable to find summary for ${slug} in namespace ${jobNamespace}`
+ );
error.code = 404;
notifyError(this)(error);
} else {
diff --git a/ui/app/serializers/agent.js b/ui/app/serializers/agent.js
index 75b4ce111..ec6b393c9 100644
--- a/ui/app/serializers/agent.js
+++ b/ui/app/serializers/agent.js
@@ -15,7 +15,8 @@ export default class AgentSerializer extends ApplicationSerializer {
// acts like the API in this case.
const error = new AdapterError([{ status: '404' }]);
- error.message = 'Requested Agent was not found in set of available Agents';
+ error.message =
+ 'Requested Agent was not found in set of available Agents';
throw error;
}
@@ -28,10 +29,21 @@ export default class AgentSerializer extends ApplicationSerializer {
}
normalizeResponse(store, typeClass, hash, ...args) {
- return super.normalizeResponse(store, typeClass, hash.Members || [], ...args);
+ return super.normalizeResponse(
+ store,
+ typeClass,
+ hash.Members || [],
+ ...args
+ );
}
normalizeSingleResponse(store, typeClass, hash, id, ...args) {
- return super.normalizeSingleResponse(store, typeClass, hash.findBy('Name', id), id, ...args);
+ return super.normalizeSingleResponse(
+ store,
+ typeClass,
+ hash.findBy('Name', id),
+ id,
+ ...args
+ );
}
}
diff --git a/ui/app/serializers/allocation.js b/ui/app/serializers/allocation.js
index 46922c357..6e471cb75 100644
--- a/ui/app/serializers/allocation.js
+++ b/ui/app/serializers/allocation.js
@@ -5,11 +5,12 @@ import classic from 'ember-classic-decorator';
const taskGroupFromJob = (job, taskGroupName) => {
const taskGroups = job && job.TaskGroups;
- const taskGroup = taskGroups && taskGroups.find(group => group.Name === taskGroupName);
+ const taskGroup =
+ taskGroups && taskGroups.find((group) => group.Name === taskGroupName);
return taskGroup ? taskGroup : null;
};
-const merge = tasks => {
+const merge = (tasks) => {
const mergedResources = {
Cpu: { CpuShares: 0 },
Memory: { MemoryMB: 0 },
@@ -41,15 +42,19 @@ export default class AllocationSerializer extends ApplicationSerializer {
const states = hash.TaskStates || {};
hash.TaskStates = Object.keys(states)
.sort()
- .map(key => {
+ .map((key) => {
const state = states[key] || {};
const summary = { Name: key };
- Object.keys(state).forEach(stateKey => (summary[stateKey] = state[stateKey]));
- summary.Resources = hash.AllocatedResources && hash.AllocatedResources.Tasks[key];
+ Object.keys(state).forEach(
+ (stateKey) => (summary[stateKey] = state[stateKey])
+ );
+ summary.Resources =
+ hash.AllocatedResources && hash.AllocatedResources.Tasks[key];
return summary;
});
- hash.JobVersion = hash.JobVersion != null ? hash.JobVersion : get(hash, 'Job.Version');
+ hash.JobVersion =
+ hash.JobVersion != null ? hash.JobVersion : get(hash, 'Job.Version');
hash.PlainJobId = hash.JobID;
hash.Namespace = hash.Namespace || get(hash, 'Job.Namespace') || 'default';
@@ -60,9 +65,13 @@ export default class AllocationSerializer extends ApplicationSerializer {
hash.IsMigrating = (hash.DesiredTransition || {}).Migrate;
// API returns empty strings instead of null
- hash.PreviousAllocationID = hash.PreviousAllocation ? hash.PreviousAllocation : null;
+ hash.PreviousAllocationID = hash.PreviousAllocation
+ ? hash.PreviousAllocation
+ : null;
hash.NextAllocationID = hash.NextAllocation ? hash.NextAllocation : null;
- hash.FollowUpEvaluationID = hash.FollowupEvalID ? hash.FollowupEvalID : null;
+ hash.FollowUpEvaluationID = hash.FollowupEvalID
+ ? hash.FollowupEvalID
+ : null;
hash.PreemptedAllocationIDs = hash.PreemptedAllocations || [];
hash.PreemptedByAllocationID = hash.PreemptedByAllocation || null;
@@ -70,14 +79,17 @@ export default class AllocationSerializer extends ApplicationSerializer {
const shared = hash.AllocatedResources && hash.AllocatedResources.Shared;
hash.AllocatedResources =
- hash.AllocatedResources && merge(Object.values(hash.AllocatedResources.Tasks));
+ hash.AllocatedResources &&
+ merge(Object.values(hash.AllocatedResources.Tasks));
if (shared) {
hash.AllocatedResources.Ports = shared.Ports;
hash.AllocatedResources.Networks = shared.Networks;
}
// The Job definition for an allocation is only included in findRecord responses.
- hash.AllocationTaskGroup = !hash.Job ? null : taskGroupFromJob(hash.Job, hash.TaskGroup);
+ hash.AllocationTaskGroup = !hash.Job
+ ? null
+ : taskGroupFromJob(hash.Job, hash.TaskGroup);
return super.normalize(typeHash, hash);
}
diff --git a/ui/app/serializers/application.js b/ui/app/serializers/application.js
index 7a6d41237..c37983af6 100644
--- a/ui/app/serializers/application.js
+++ b/ui/app/serializers/application.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-string-prototype-extensions */
import { copy } from 'ember-copy';
import { get } from '@ember/object';
import { makeArray } from '@ember/array';
@@ -62,9 +63,7 @@ export default class Application extends JSONSerializer {
}
keyForRelationship(attr, relationshipType) {
- const key = `${singularize(attr)
- .camelize()
- .capitalize()}ID`;
+ const key = `${singularize(attr).camelize().capitalize()}ID`;
return relationshipType === 'hasMany' ? pluralize(key) : key;
}
@@ -75,12 +74,12 @@ export default class Application extends JSONSerializer {
included: [],
};
- Object.keys(payload).forEach(key => {
+ Object.keys(payload).forEach((key) => {
const modelName = this.modelNameFromPayloadKey(key);
const serializer = store.serializerFor(modelName);
const type = store.modelFor(modelName);
- makeArray(payload[key]).forEach(hash => {
+ makeArray(payload[key]).forEach((hash) => {
const { data, included } = serializer.normalize(type, hash, key);
documentHash.data.push(data);
if (included) {
@@ -95,14 +94,14 @@ export default class Application extends JSONSerializer {
normalize(modelClass, hash) {
if (hash) {
if (this.arrayNullOverrides) {
- this.arrayNullOverrides.forEach(key => {
+ this.arrayNullOverrides.forEach((key) => {
if (!hash[key]) {
hash[key] = [];
}
});
}
if (this.objectNullOverrides) {
- this.objectNullOverrides.forEach(key => {
+ this.objectNullOverrides.forEach((key) => {
if (!hash[key]) {
hash[key] = {};
}
@@ -110,7 +109,7 @@ export default class Application extends JSONSerializer {
}
if (this.mapToArray) {
- this.mapToArray.forEach(conversion => {
+ this.mapToArray.forEach((conversion) => {
let apiKey, uiKey;
if (conversion.beforeName) {
@@ -125,7 +124,7 @@ export default class Application extends JSONSerializer {
hash[uiKey] = Object.keys(map)
.sort()
- .map(mapKey => {
+ .map((mapKey) => {
const propertiesForKey = map[mapKey] || {};
const convertedMap = { Name: mapKey };
@@ -137,7 +136,7 @@ export default class Application extends JSONSerializer {
}
if (this.separateNanos) {
- this.separateNanos.forEach(key => {
+ this.separateNanos.forEach((key) => {
const timeWithNanos = hash[key];
hash[`${key}Nanos`] = timeWithNanos % 1000000;
hash[key] = Math.floor(timeWithNanos / 1000000);
@@ -157,13 +156,15 @@ export default class Application extends JSONSerializer {
// When records are removed server-side, and therefore don't show up in requests,
// the local copies of those records need to be unloaded from the store.
cullStore(store, type, records, storeFilter = () => true) {
- const newRecords = copy(records).filter(record => get(record, 'id'));
+ const newRecords = copy(records).filter((record) => get(record, 'id'));
const oldRecords = store.peekAll(type);
oldRecords
- .filter(record => get(record, 'id'))
+ .filter((record) => get(record, 'id'))
.filter(storeFilter)
- .forEach(old => {
- const newRecord = newRecords.find(record => get(record, 'id') === get(old, 'id'));
+ .forEach((old) => {
+ const newRecord = newRecords.find(
+ (record) => get(record, 'id') === get(old, 'id')
+ );
if (!newRecord) {
removeRecord(store, old);
} else {
diff --git a/ui/app/serializers/deployment.js b/ui/app/serializers/deployment.js
index 49e8ddcdb..d947a4ad1 100644
--- a/ui/app/serializers/deployment.js
+++ b/ui/app/serializers/deployment.js
@@ -14,20 +14,26 @@ export default class DeploymentSerializer extends ApplicationSerializer {
normalize(typeHash, hash) {
if (hash) {
hash.PlainJobId = hash.JobID;
- hash.Namespace = hash.Namespace || get(hash, 'Job.Namespace') || 'default';
+ hash.Namespace =
+ hash.Namespace || get(hash, 'Job.Namespace') || 'default';
// Ember Data doesn't support multiple inverses. This means that since jobs have
// two relationships to a deployment (hasMany deployments, and belongsTo latestDeployment),
// the deployment must in turn have two relationships to the job, despite it being the
// same job.
- hash.JobID = hash.JobForLatestID = JSON.stringify([hash.JobID, hash.Namespace]);
+ hash.JobID = hash.JobForLatestID = JSON.stringify([
+ hash.JobID,
+ hash.Namespace,
+ ]);
}
return super.normalize(typeHash, hash);
}
extractRelationships(modelClass, hash) {
- const namespace = this.store.adapterFor(modelClass.modelName).get('namespace');
+ const namespace = this.store
+ .adapterFor(modelClass.modelName)
+ .get('namespace');
const id = this.extractId(modelClass, hash);
return assign(
diff --git a/ui/app/serializers/job-plan.js b/ui/app/serializers/job-plan.js
index 1893f8c9d..ea8971451 100644
--- a/ui/app/serializers/job-plan.js
+++ b/ui/app/serializers/job-plan.js
@@ -5,7 +5,9 @@ export default class JobPlan extends ApplicationSerializer {
mapToArray = ['FailedTGAllocs'];
normalize(typeHash, hash) {
- hash.PreemptionIDs = (get(hash, 'Annotations.PreemptedAllocs') || []).mapBy('ID');
+ hash.PreemptionIDs = (get(hash, 'Annotations.PreemptedAllocs') || []).mapBy(
+ 'ID'
+ );
return super.normalize(...arguments);
}
}
diff --git a/ui/app/serializers/job-summary.js b/ui/app/serializers/job-summary.js
index bf65f6c38..23af75c7c 100644
--- a/ui/app/serializers/job-summary.js
+++ b/ui/app/serializers/job-summary.js
@@ -13,12 +13,12 @@ export default class JobSummary extends ApplicationSerializer {
const fullSummary = hash.Summary || {};
hash.TaskGroupSummaries = Object.keys(fullSummary)
.sort()
- .map(key => {
+ .map((key) => {
const allocStats = fullSummary[key] || {};
const summary = { Name: key };
Object.keys(allocStats).forEach(
- allocKey => (summary[`${allocKey}Allocs`] = allocStats[allocKey])
+ (allocKey) => (summary[`${allocKey}Allocs`] = allocStats[allocKey])
);
return summary;
@@ -28,7 +28,8 @@ export default class JobSummary extends ApplicationSerializer {
const childrenStats = get(hash, 'Children');
if (childrenStats) {
Object.keys(childrenStats).forEach(
- childrenKey => (hash[`${childrenKey}Children`] = childrenStats[childrenKey])
+ (childrenKey) =>
+ (hash[`${childrenKey}Children`] = childrenStats[childrenKey])
);
}
diff --git a/ui/app/serializers/job.js b/ui/app/serializers/job.js
index 8c24bea0a..65a2001bb 100644
--- a/ui/app/serializers/job.js
+++ b/ui/app/serializers/job.js
@@ -20,7 +20,10 @@ export default class JobSerializer extends ApplicationSerializer {
if (!hash.ParentID) {
hash.ParentID = null;
} else {
- hash.ParentID = JSON.stringify([hash.ParentID, hash.NamespaceID || 'default']);
+ hash.ParentID = JSON.stringify([
+ hash.ParentID,
+ hash.NamespaceID || 'default',
+ ]);
}
// Job Summary is always at /:job-id/summary, but since it can also come from
@@ -52,10 +55,14 @@ export default class JobSerializer extends ApplicationSerializer {
extractRelationships(modelClass, hash) {
const namespace =
- !hash.NamespaceID || hash.NamespaceID === 'default' ? undefined : hash.NamespaceID;
+ !hash.NamespaceID || hash.NamespaceID === 'default'
+ ? undefined
+ : hash.NamespaceID;
const { modelName } = modelClass;
- const apiNamespace = this.store.adapterFor(modelClass.modelName).get('namespace');
+ const apiNamespace = this.store
+ .adapterFor(modelClass.modelName)
+ .get('namespace');
const [jobURL] = this.store
.adapterFor(modelName)
diff --git a/ui/app/serializers/network.js b/ui/app/serializers/network.js
index 3310db18c..605f4bc33 100644
--- a/ui/app/serializers/network.js
+++ b/ui/app/serializers/network.js
@@ -15,14 +15,14 @@ export default class NetworkSerializer extends ApplicationSerializer {
hash.IP = `[${ip}]`;
}
- const reservedPorts = (hash.ReservedPorts || []).map(port => ({
+ const reservedPorts = (hash.ReservedPorts || []).map((port) => ({
name: port.Label,
port: port.Value,
to: port.To,
isDynamic: false,
}));
- const dynamicPorts = (hash.DynamicPorts || []).map(port => ({
+ const dynamicPorts = (hash.DynamicPorts || []).map((port) => ({
name: port.Label,
port: port.Value,
to: port.To,
diff --git a/ui/app/serializers/node.js b/ui/app/serializers/node.js
index a689c40b2..69cce417a 100644
--- a/ui/app/serializers/node.js
+++ b/ui/app/serializers/node.js
@@ -17,7 +17,12 @@ export default class NodeSerializer extends ApplicationSerializer {
const { modelName } = modelClass;
const nodeURL = this.store
.adapterFor(modelName)
- .buildURL(modelName, this.extractId(modelClass, hash), hash, 'findRecord');
+ .buildURL(
+ modelName,
+ this.extractId(modelClass, hash),
+ hash,
+ 'findRecord'
+ );
return {
allocations: {
diff --git a/ui/app/serializers/plugin.js b/ui/app/serializers/plugin.js
index d113551e3..5f368a9fd 100644
--- a/ui/app/serializers/plugin.js
+++ b/ui/app/serializers/plugin.js
@@ -8,7 +8,7 @@ import ApplicationSerializer from './application';
const unmap = (hash, propKey) =>
Object.keys(hash)
.sort()
- .map(key => {
+ .map((key) => {
const record = hash[key];
record[propKey] = key;
return record;
diff --git a/ui/app/serializers/recommendation-summary.js b/ui/app/serializers/recommendation-summary.js
index a484d4d02..c04bb6458 100644
--- a/ui/app/serializers/recommendation-summary.js
+++ b/ui/app/serializers/recommendation-summary.js
@@ -16,10 +16,11 @@ export default class RecommendationSummarySerializer extends ApplicationSerializ
const slugToSummaryObject = {};
const allRecommendations = [];
- payload.forEach(recommendationHash => {
- const slug = `${JSON.stringify([recommendationHash.JobID, recommendationHash.Namespace])}/${
- recommendationHash.Group
- }`;
+ payload.forEach((recommendationHash) => {
+ const slug = `${JSON.stringify([
+ recommendationHash.JobID,
+ recommendationHash.Namespace,
+ ])}/${recommendationHash.Group}`;
if (!slugToSummaryObject[slug]) {
slugToSummaryObject[slug] = {
@@ -37,15 +38,14 @@ export default class RecommendationSummarySerializer extends ApplicationSerializ
});
return {
- data: Object.values(slugToSummaryObject).map(summaryObject => {
- const latest = Math.max(...summaryObject.recommendations.mapBy('SubmitTime'));
+ data: Object.values(slugToSummaryObject).map((summaryObject) => {
+ const latest = Math.max(
+ ...summaryObject.recommendations.mapBy('SubmitTime')
+ );
return {
type: 'recommendation-summary',
- id: summaryObject.recommendations
- .mapBy('ID')
- .sort()
- .join('-'),
+ id: summaryObject.recommendations.mapBy('ID').sort().join('-'),
attributes: {
...summaryObject.attributes,
submitTime: new Date(Math.floor(latest / 1000000)),
@@ -61,7 +61,7 @@ export default class RecommendationSummarySerializer extends ApplicationSerializ
},
},
recommendations: {
- data: summaryObject.recommendations.map(r => {
+ data: summaryObject.recommendations.map((r) => {
return {
type: 'recommendation',
id: r.ID,
@@ -72,8 +72,11 @@ export default class RecommendationSummarySerializer extends ApplicationSerializ
};
}),
included: allRecommendations.map(
- recommendationHash =>
- recommendationSerializer.normalize(RecommendationModel, recommendationHash).data
+ (recommendationHash) =>
+ recommendationSerializer.normalize(
+ RecommendationModel,
+ recommendationHash
+ ).data
),
};
}
diff --git a/ui/app/serializers/recommendation.js b/ui/app/serializers/recommendation.js
index bb9bd785a..32b062052 100644
--- a/ui/app/serializers/recommendation.js
+++ b/ui/app/serializers/recommendation.js
@@ -12,7 +12,10 @@ export default class RecommendationSerializer extends ApplicationSerializer {
separateNanos = ['SubmitTime'];
extractRelationships(modelClass, hash) {
- const namespace = !hash.Namespace || hash.Namespace === 'default' ? undefined : hash.Namespace;
+ const namespace =
+ !hash.Namespace || hash.Namespace === 'default'
+ ? undefined
+ : hash.Namespace;
const [jobURL] = this.store
.adapterFor('job')
diff --git a/ui/app/serializers/task-group.js b/ui/app/serializers/task-group.js
index 6c5034d28..28e86e003 100644
--- a/ui/app/serializers/task-group.js
+++ b/ui/app/serializers/task-group.js
@@ -7,7 +7,7 @@ export default class TaskGroup extends ApplicationSerializer {
normalize(typeHash, hash) {
// Provide EphemeralDisk to each task
- hash.Tasks.forEach(task => {
+ hash.Tasks.forEach((task) => {
task.EphemeralDisk = copy(hash.EphemeralDisk);
});
diff --git a/ui/app/serializers/volume.js b/ui/app/serializers/volume.js
index c3aa3a57d..faf2b398d 100644
--- a/ui/app/serializers/volume.js
+++ b/ui/app/serializers/volume.js
@@ -31,7 +31,7 @@ export default class VolumeSerializer extends ApplicationSerializer {
hash.WriteAllocations = [];
if (hash.Allocations) {
- hash.Allocations.forEach(function(alloc) {
+ hash.Allocations.forEach(function (alloc) {
const id = alloc.ID;
if (id in readAllocs) {
hash.ReadAllocations.push(alloc);
@@ -44,11 +44,17 @@ export default class VolumeSerializer extends ApplicationSerializer {
}
const normalizedHash = super.normalize(typeHash, hash);
- return this.extractEmbeddedRecords(this, this.store, typeHash, normalizedHash);
+ return this.extractEmbeddedRecords(
+ this,
+ this.store,
+ typeHash,
+ normalizedHash
+ );
}
keyForRelationship(attr, relationshipType) {
//Embedded relationship attributes don't end in IDs
+ /* eslint-disable-next-line ember/no-string-prototype-extensions */
if (this.embeddedRelationships.includes(attr)) return attr.capitalize();
return super.keyForRelationship(attr, relationshipType);
}
@@ -57,7 +63,7 @@ export default class VolumeSerializer extends ApplicationSerializer {
extractEmbeddedRecords(serializer, store, typeHash, partial) {
partial.included = partial.included || [];
- this.embeddedRelationships.forEach(embed => {
+ this.embeddedRelationships.forEach((embed) => {
const relationshipMeta = typeHash.relationshipsByName.get(embed);
const relationship = get(partial, `data.relationships.${embed}.data`);
diff --git a/ui/app/services/breadcrumbs.js b/ui/app/services/breadcrumbs.js
index eacf9f955..5d92984be 100644
--- a/ui/app/services/breadcrumbs.js
+++ b/ui/app/services/breadcrumbs.js
@@ -13,7 +13,7 @@ export default class BucketService extends Service {
}
@action deregisterBreadcrumb(crumb) {
- const newCrumbs = this.crumbs.filter(c => c !== crumb);
+ const newCrumbs = this.crumbs.filter((c) => c !== crumb);
this.crumbs = newCrumbs;
}
diff --git a/ui/app/services/sockets.js b/ui/app/services/sockets.js
index c6bebc6be..236d77630 100644
--- a/ui/app/services/sockets.js
+++ b/ui/app/services/sockets.js
@@ -19,7 +19,11 @@ export default class SocketsService extends Service {
send(e) {
if (!this.messageDisplayed) {
this.messageDisplayed = true;
- this.onmessage({ data: `{"stdout":{"data":"${btoa('unsupported in Mirage\n\r')}"}}` });
+ this.onmessage({
+ data: `{"stdout":{"data":"${btoa(
+ 'unsupported in Mirage\n\r'
+ )}"}}`,
+ });
} else {
this.onmessage({ data: e.replace('stdin', 'stdout') });
}
@@ -28,8 +32,9 @@ export default class SocketsService extends Service {
} else {
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const applicationAdapter = getOwner(this).lookup('adapter:application');
- const prefix = `${applicationAdapter.host ||
- window.location.host}/${applicationAdapter.urlPrefix()}`;
+ const prefix = `${
+ applicationAdapter.host || window.location.host
+ }/${applicationAdapter.urlPrefix()}`;
const region = this.system.activeRegion;
return new WebSocket(
diff --git a/ui/app/services/stats-trackers-registry.js b/ui/app/services/stats-trackers-registry.js
index 8c2fb2ab7..6d222dc08 100644
--- a/ui/app/services/stats-trackers-registry.js
+++ b/ui/app/services/stats-trackers-registry.js
@@ -12,7 +12,9 @@ const MAX_STAT_TRACKERS = 10;
let registry;
const exists = (tracker, prop) =>
- tracker.get(prop) && !tracker.get(prop).isDestroyed && !tracker.get(prop).isDestroying;
+ tracker.get(prop) &&
+ !tracker.get(prop).isDestroyed &&
+ !tracker.get(prop).isDestroying;
export default class StatsTrackersRegistryService extends Service {
@service token;
@@ -38,19 +40,21 @@ export default class StatsTrackersRegistryService extends Service {
const type = resource && resource.constructor.modelName;
const key = `${type}:${resource.get('id')}`;
- const Constructor = type === 'node' ? NodeStatsTracker : AllocationStatsTracker;
+ const Constructor =
+ type === 'node' ? NodeStatsTracker : AllocationStatsTracker;
const resourceProp = type === 'node' ? 'node' : 'allocation';
const cachedTracker = registry.get(key);
if (cachedTracker) {
// It's possible for the resource on a cachedTracker to have been
// deleted. Rebind it if that's the case.
- if (!exists(cachedTracker, resourceProp)) cachedTracker.set(resourceProp, resource);
+ if (!exists(cachedTracker, resourceProp))
+ cachedTracker.set(resourceProp, resource);
return cachedTracker;
}
const tracker = Constructor.create({
- fetch: url => this.token.authorizedRequest(url),
+ fetch: (url) => this.token.authorizedRequest(url),
[resourceProp]: resource,
});
diff --git a/ui/app/services/system.js b/ui/app/services/system.js
index cd296f338..1859c701e 100644
--- a/ui/app/services/system.js
+++ b/ui/app/services/system.js
@@ -21,9 +21,9 @@ export default class SystemService extends Service {
return PromiseObject.create({
promise: token
.authorizedRequest(`/${namespace}/status/leader`)
- .then(res => res.json())
- .then(rpcAddr => ({ rpcAddr }))
- .then(leader => {
+ .then((res) => res.json())
+ .then((rpcAddr) => ({ rpcAddr }))
+ .then((leader) => {
// Dirty self so leader can be used as a dependent key
this.notifyPropertyChange('leader.rpcAddr');
return leader;
@@ -38,12 +38,15 @@ export default class SystemService extends Service {
promise: token
.authorizedRawRequest(`/${namespace}/agent/self`)
.then(jsonWithDefault({}))
- .then(agent => {
+ .then((agent) => {
if (agent?.config?.Version) {
- const { Version, VersionPrerelease, VersionMetadata } = agent.config.Version;
+ const { Version, VersionPrerelease, VersionMetadata } =
+ agent.config.Version;
agent.version = Version;
- if (VersionPrerelease) agent.version = `${agent.version}-${VersionPrerelease}`;
- if (VersionMetadata) agent.version = `${agent.version}+${VersionMetadata}`;
+ if (VersionPrerelease)
+ agent.version = `${agent.version}-${VersionPrerelease}`;
+ if (VersionMetadata)
+ agent.version = `${agent.version}+${VersionMetadata}`;
}
return agent;
}),
@@ -57,7 +60,7 @@ export default class SystemService extends Service {
promise: token
.authorizedRawRequest(`/${namespace}/agent/members`)
.then(jsonWithDefault({}))
- .then(json => {
+ .then((json) => {
return { region: json.ServerRegion };
}),
});
@@ -68,7 +71,9 @@ export default class SystemService extends Service {
const token = this.token;
return PromiseArray.create({
- promise: token.authorizedRawRequest(`/${namespace}/regions`).then(jsonWithDefault([])),
+ promise: token
+ .authorizedRawRequest(`/${namespace}/regions`)
+ .then(jsonWithDefault([])),
});
}
@@ -103,20 +108,28 @@ export default class SystemService extends Service {
@computed('activeRegion', 'defaultRegion.region', 'shouldShowRegions')
get shouldIncludeRegion() {
- return this.shouldShowRegions && this.activeRegion !== this.get('defaultRegion.region');
+ return (
+ this.shouldShowRegions &&
+ this.activeRegion !== this.get('defaultRegion.region')
+ );
}
@computed('activeRegion')
get namespaces() {
return PromiseArray.create({
- promise: this.store.findAll('namespace').then(namespaces => namespaces.compact()),
+ promise: this.store
+ .findAll('namespace')
+ .then((namespaces) => namespaces.compact()),
});
}
@computed('namespaces.[]')
get shouldShowNamespaces() {
const namespaces = this.namespaces.toArray();
- return namespaces.length && namespaces.some(namespace => namespace.get('id') !== 'default');
+ return (
+ namespaces.length &&
+ namespaces.some((namespace) => namespace.get('id') !== 'default')
+ );
}
// The cachedNamespace is set on pages that have a namespaces filter.
@@ -125,7 +138,7 @@ export default class SystemService extends Service {
// to 'default' or '*'.
@tracked cachedNamespace = null;
- @task(function*() {
+ @task(function* () {
const emptyLicense = { License: { Features: [] } };
try {
@@ -138,7 +151,7 @@ export default class SystemService extends Service {
})
fetchLicense;
- @task(function*() {
+ @task(function* () {
try {
const request = yield this.token.authorizedRequest('/v1/search/fuzzy', {
method: 'POST',
diff --git a/ui/app/services/token.js b/ui/app/services/token.js
index c11453e23..13755155c 100644
--- a/ui/app/services/token.js
+++ b/ui/app/services/token.js
@@ -28,13 +28,13 @@ export default class TokenService extends Service {
}
}
- @task(function*() {
+ @task(function* () {
const TokenAdapter = getOwner(this).lookup('adapter:token');
try {
return yield TokenAdapter.findSelf();
} catch (e) {
const errors = e.errors ? e.errors.mapBy('detail') : [];
- if (errors.find(error => error === 'ACL support disabled')) {
+ if (errors.find((error) => error === 'ACL support disabled')) {
this.set('aclEnabled', false);
}
return null;
@@ -51,7 +51,7 @@ export default class TokenService extends Service {
this.secret = token.secret;
}
- @task(function*() {
+ @task(function* () {
try {
if (this.selfToken) {
return yield this.selfToken.get('policies');
@@ -67,7 +67,7 @@ export default class TokenService extends Service {
@alias('fetchSelfTokenPolicies.lastSuccessful.value') selfTokenPolicies;
- @task(function*() {
+ @task(function* () {
yield this.fetchSelfToken.perform();
if (this.aclEnabled) {
yield this.fetchSelfTokenPolicies.perform();
diff --git a/ui/app/services/user-settings.js b/ui/app/services/user-settings.js
index dbe650ed1..3c8362dfa 100644
--- a/ui/app/services/user-settings.js
+++ b/ui/app/services/user-settings.js
@@ -4,5 +4,6 @@ import localStorageProperty from 'nomad-ui/utils/properties/local-storage';
export default class UserSettingsService extends Service {
@localStorageProperty('nomadPageSize', 25) pageSize;
@localStorageProperty('nomadLogMode', 'stdout') logMode;
- @localStorageProperty('nomadTopoVizPollingNotice', true) showTopoVizPollingNotice;
+ @localStorageProperty('nomadTopoVizPollingNotice', true)
+ showTopoVizPollingNotice;
}
diff --git a/ui/app/utils/classes/abstract-logger.js b/ui/app/utils/classes/abstract-logger.js
index 8dc78ff1c..e8b404958 100644
--- a/ui/app/utils/classes/abstract-logger.js
+++ b/ui/app/utils/classes/abstract-logger.js
@@ -12,12 +12,14 @@ export default Mixin.create({
url: '',
params: overridable(() => ({})),
logFetch() {
- assert('Loggers need a logFetch method, which should have an interface like window.fetch');
+ assert(
+ 'Loggers need a logFetch method, which should have an interface like window.fetch'
+ );
},
endOffset: null,
- offsetParams: computed('endOffset', function() {
+ offsetParams: computed('endOffset', function () {
const endOffset = this.endOffset;
return endOffset
? { origin: 'start', offset: endOffset }
@@ -26,10 +28,16 @@ export default Mixin.create({
additionalParams: overridable(() => ({})),
- fullUrl: computed('url', 'params', 'offsetParams', 'additionalParams', function() {
- const queryParams = queryString.stringify(
- assign({}, this.params, this.offsetParams, this.additionalParams)
- );
- return `${this.url}?${queryParams}`;
- }),
+ fullUrl: computed(
+ 'url',
+ 'params',
+ 'offsetParams',
+ 'additionalParams',
+ function () {
+ const queryParams = queryString.stringify(
+ assign({}, this.params, this.offsetParams, this.additionalParams)
+ );
+ return `${this.url}?${queryParams}`;
+ }
+ ),
});
diff --git a/ui/app/utils/classes/abstract-stats-tracker.js b/ui/app/utils/classes/abstract-stats-tracker.js
index dd51c11f4..2c45f2f49 100644
--- a/ui/app/utils/classes/abstract-stats-tracker.js
+++ b/ui/app/utils/classes/abstract-stats-tracker.js
@@ -18,7 +18,9 @@ export default Mixin.create({
maxFrameMisses: 5,
fetch() {
- assert('StatsTrackers need a fetch method, which should have an interface like window.fetch');
+ assert(
+ 'StatsTrackers need a fetch method, which should have an interface like window.fetch'
+ );
},
append(/* frame */) {
@@ -56,7 +58,7 @@ export default Mixin.create({
// references to the same tracker from flooding the tracker,
// but also avoiding the issue where different places where the
// same tracker is used needs to coordinate.
- poll: task(function*() {
+ poll: task(function* () {
// Interrupt any pause attempt
this.signalPause.cancelAll();
@@ -66,7 +68,7 @@ export default Mixin.create({
yield this.fetch(url)
.then(jsonWithDefault({ error: true }))
- .then(frame => this.handleResponse(frame));
+ .then((frame) => this.handleResponse(frame));
} catch (error) {
throw new Error(error);
}
@@ -74,7 +76,7 @@ export default Mixin.create({
yield timeout(Ember.testing ? 0 : 2000);
}).drop(),
- signalPause: task(function*() {
+ signalPause: task(function* () {
// wait 2 seconds
yield timeout(Ember.testing ? 0 : 2000);
// if no poll called in 2 seconds, pause
diff --git a/ui/app/utils/classes/allocation-stats-tracker.js b/ui/app/utils/classes/allocation-stats-tracker.js
index 18782ba39..092357d18 100644
--- a/ui/app/utils/classes/allocation-stats-tracker.js
+++ b/ui/app/utils/classes/allocation-stats-tracker.js
@@ -11,7 +11,7 @@ const percent = (numerator, denominator) => {
return numerator / denominator;
};
-const empty = ts => ({ timestamp: ts, used: null, percent: null });
+const empty = (ts) => ({ timestamp: ts, used: null, percent: null });
// Tasks are sorted by their lifecycle phase in this order:
const sortMap = [
@@ -26,7 +26,8 @@ const sortMap = [
return map;
}, {});
-const taskPrioritySort = (a, b) => sortMap[a.lifecycleName] - sortMap[b.lifecycleName];
+const taskPrioritySort = (a, b) =>
+ sortMap[a.lifecycleName] - sortMap[b.lifecycleName];
@classic
class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
@@ -64,9 +65,12 @@ class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
// it has already stopped), just keep going.
if (!taskFrame) continue;
- const frameTimestamp = new Date(Math.floor(taskFrame.Timestamp / 1000000));
+ const frameTimestamp = new Date(
+ Math.floor(taskFrame.Timestamp / 1000000)
+ );
- const taskCpuUsed = Math.floor(taskFrame.ResourceUsage.CpuStats.TotalTicks) || 0;
+ const taskCpuUsed =
+ Math.floor(taskFrame.ResourceUsage.CpuStats.TotalTicks) || 0;
const percentCpuTotal = percent(taskCpuUsed, this.reservedCPU);
stats.cpu.pushObject({
timestamp: frameTimestamp,
@@ -77,7 +81,10 @@ class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
});
const taskMemoryUsed = taskFrame.ResourceUsage.MemoryStats.RSS;
- const percentMemoryTotal = percent(taskMemoryUsed / 1024 / 1024, this.reservedMemory);
+ const percentMemoryTotal = percent(
+ taskMemoryUsed / 1024 / 1024,
+ this.reservedMemory
+ );
stats.memory.pushObject({
timestamp: frameTimestamp,
used: taskMemoryUsed,
@@ -95,7 +102,7 @@ class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
const ts = new Date();
this.memory.pushObject(empty(ts));
this.cpu.pushObject(empty(ts));
- this.tasks.forEach(task => {
+ this.tasks.forEach((task) => {
task.memory.pushObject(empty(ts));
task.cpu.pushObject(empty(ts));
});
@@ -124,7 +131,7 @@ class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
return tasks
.slice()
.sort(taskPrioritySort)
- .map(task => ({
+ .map((task) => ({
task: get(task, 'name'),
// Static figures, denominators for stats
@@ -142,7 +149,7 @@ class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
export default AllocationStatsTracker;
export function stats(allocationProp, fetch) {
- return computed(allocationProp, function() {
+ return computed(allocationProp, function () {
return AllocationStatsTracker.create({
fetch: fetch.call(this),
allocation: this.get(allocationProp),
diff --git a/ui/app/utils/classes/exec-command-editor-xterm-adapter.js b/ui/app/utils/classes/exec-command-editor-xterm-adapter.js
index 45212f4f1..89fa68fcc 100644
--- a/ui/app/utils/classes/exec-command-editor-xterm-adapter.js
+++ b/ui/app/utils/classes/exec-command-editor-xterm-adapter.js
@@ -13,7 +13,7 @@ export default class ExecCommandEditorXtermAdapter {
this.command = command;
- this.dataListener = terminal.onData(data => {
+ this.dataListener = terminal.onData((data) => {
this.handleDataEvent(data);
});
diff --git a/ui/app/utils/classes/exec-socket-xterm-adapter.js b/ui/app/utils/classes/exec-socket-xterm-adapter.js
index c97e9cc0e..3eef4c726 100644
--- a/ui/app/utils/classes/exec-socket-xterm-adapter.js
+++ b/ui/app/utils/classes/exec-socket-xterm-adapter.js
@@ -15,12 +15,12 @@ export default class ExecSocketXtermAdapter {
this.sendTtySize();
this.startHeartbeat();
- terminal.onData(data => {
+ terminal.onData((data) => {
this.handleData(data);
});
};
- socket.onmessage = e => {
+ socket.onmessage = (e) => {
let json = JSON.parse(e.data);
// stderr messages will not be produced as the socket is opened with the tty flag
@@ -44,12 +44,16 @@ export default class ExecSocketXtermAdapter {
sendTtySize() {
this.socket.send(
- JSON.stringify({ tty_size: { width: this.terminal.cols, height: this.terminal.rows } })
+ JSON.stringify({
+ tty_size: { width: this.terminal.cols, height: this.terminal.rows },
+ })
);
}
sendWsHandshake() {
- this.socket.send(JSON.stringify({ version: 1, auth_token: this.token || '' }));
+ this.socket.send(
+ JSON.stringify({ version: 1, auth_token: this.token || '' })
+ );
}
startHeartbeat() {
@@ -63,6 +67,8 @@ export default class ExecSocketXtermAdapter {
}
handleData(data) {
- this.socket.send(JSON.stringify({ stdin: { data: base64EncodeString(data) } }));
+ this.socket.send(
+ JSON.stringify({ stdin: { data: base64EncodeString(data) } })
+ );
}
}
diff --git a/ui/app/utils/classes/log.js b/ui/app/utils/classes/log.js
index b23d14704..5ea91dc85 100644
--- a/ui/app/utils/classes/log.js
+++ b/ui/app/utils/classes/log.js
@@ -16,7 +16,8 @@ import classic from 'ember-classic-decorator';
const MAX_OUTPUT_LENGTH = 50000;
// eslint-disable-next-line
-export const fetchFailure = url => () => console.warn(`LOG FETCH: Couldn't connect to ${url}`);
+export const fetchFailure = (url) => () =>
+ console.warn(`LOG FETCH: Couldn't connect to ${url}`);
@classic
class Log extends EmberObject.extend(Evented) {
@@ -30,7 +31,9 @@ class Log extends EmberObject.extend(Evented) {
plainText = false;
logFetch() {
- assert('Log objects need a logFetch method, which should have an interface like window.fetch');
+ assert(
+ 'Log objects need a logFetch method, which should have an interface like window.fetch'
+ );
}
// Read-only state
@@ -61,7 +64,7 @@ class Log extends EmberObject.extend(Evented) {
super.init();
const args = this.getProperties('url', 'params', 'logFetch');
- args.write = chunk => {
+ args.write = (chunk) => {
let newTail = this.tail + chunk;
if (newTail.length > MAX_OUTPUT_LENGTH) {
newTail = newTail.substr(newTail.length - MAX_OUTPUT_LENGTH);
@@ -82,7 +85,7 @@ class Log extends EmberObject.extend(Evented) {
super.destroy();
}
- @task(function*() {
+ @task(function* () {
const logFetch = this.logFetch;
const queryParams = queryString.stringify(
assign(
@@ -96,19 +99,23 @@ class Log extends EmberObject.extend(Evented) {
const url = `${this.url}?${queryParams}`;
this.stop();
- const response = yield logFetch(url).then(res => res.text(), fetchFailure(url));
+ const response = yield logFetch(url).then(
+ (res) => res.text(),
+ fetchFailure(url)
+ );
let text = this.plainText ? response : decode(response).message;
if (text && text.length > MAX_OUTPUT_LENGTH) {
text = text.substr(0, MAX_OUTPUT_LENGTH);
- text += '\n\n---------- TRUNCATED: Click "tail" to view the bottom of the log ----------';
+ text +=
+ '\n\n---------- TRUNCATED: Click "tail" to view the bottom of the log ----------';
}
this.set('head', text);
this.set('logPointer', 'head');
})
gotoHead;
- @task(function*() {
+ @task(function* () {
const logFetch = this.logFetch;
const queryParams = queryString.stringify(
assign(
@@ -122,7 +129,10 @@ class Log extends EmberObject.extend(Evented) {
const url = `${this.url}?${queryParams}`;
this.stop();
- const response = yield logFetch(url).then(res => res.text(), fetchFailure(url));
+ const response = yield logFetch(url).then(
+ (res) => res.text(),
+ fetchFailure(url)
+ );
let text = this.plainText ? response : decode(response).message;
this.set('tail', text);
@@ -143,7 +153,7 @@ class Log extends EmberObject.extend(Evented) {
export default Log;
export function logger(urlProp, params, logFetch) {
- return computed(urlProp, params, function() {
+ return computed(urlProp, params, function () {
return Log.create({
logFetch: logFetch.call(this),
params: this.get(params),
diff --git a/ui/app/utils/classes/node-stats-tracker.js b/ui/app/utils/classes/node-stats-tracker.js
index 995f26500..7427a1e8d 100644
--- a/ui/app/utils/classes/node-stats-tracker.js
+++ b/ui/app/utils/classes/node-stats-tracker.js
@@ -11,7 +11,7 @@ const percent = (numerator, denominator) => {
return numerator / denominator;
};
-const empty = ts => ({ timestamp: ts, used: null, percent: null });
+const empty = (ts) => ({ timestamp: ts, used: null, percent: null });
@classic
class NodeStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
@@ -67,7 +67,7 @@ class NodeStatsTracker extends EmberObject.extend(AbstractStatsTracker) {
export default NodeStatsTracker;
export function stats(nodeProp, fetch) {
- return computed(nodeProp, function() {
+ return computed(nodeProp, function () {
return NodeStatsTracker.create({
fetch: fetch.call(this),
node: this.get(nodeProp),
diff --git a/ui/app/utils/classes/poll-logger.js b/ui/app/utils/classes/poll-logger.js
index 6fe015c2e..9f874cf38 100644
--- a/ui/app/utils/classes/poll-logger.js
+++ b/ui/app/utils/classes/poll-logger.js
@@ -17,11 +17,11 @@ export default class PollLogger extends EmberObject.extend(AbstractLogger) {
return this.poll.cancelAll();
}
- @task(function*() {
+ @task(function* () {
const { interval, logFetch } = this;
while (true) {
const url = this.fullUrl;
- let response = yield logFetch(url).then(res => res, fetchFailure(url));
+ let response = yield logFetch(url).then((res) => res, fetchFailure(url));
if (!response) {
return;
diff --git a/ui/app/utils/classes/promise-array.js b/ui/app/utils/classes/promise-array.js
index 1bf2efb1a..49615cfb2 100644
--- a/ui/app/utils/classes/promise-array.js
+++ b/ui/app/utils/classes/promise-array.js
@@ -3,4 +3,6 @@ import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
import classic from 'ember-classic-decorator';
@classic
-export default class PromiseArray extends ArrayProxy.extend(PromiseProxyMixin) {}
+export default class PromiseArray extends ArrayProxy.extend(
+ PromiseProxyMixin
+) {}
diff --git a/ui/app/utils/classes/promise-object.js b/ui/app/utils/classes/promise-object.js
index dbab8f7ec..bd8940b4a 100644
--- a/ui/app/utils/classes/promise-object.js
+++ b/ui/app/utils/classes/promise-object.js
@@ -3,4 +3,6 @@ import PromiseProxyMixin from '@ember/object/promise-proxy-mixin';
import classic from 'ember-classic-decorator';
@classic
-export default class PromiseObject extends ObjectProxy.extend(PromiseProxyMixin) {}
+export default class PromiseObject extends ObjectProxy.extend(
+ PromiseProxyMixin
+) {}
diff --git a/ui/app/utils/classes/query-params.js b/ui/app/utils/classes/query-params.js
index 9c61582d4..7450e2877 100644
--- a/ui/app/utils/classes/query-params.js
+++ b/ui/app/utils/classes/query-params.js
@@ -9,6 +9,6 @@ class QueryParams extends EmberObject {
values = null;
}
-export const qpBuilder = values => QueryParams.create({ values });
+export const qpBuilder = (values) => QueryParams.create({ values });
export default QueryParams;
diff --git a/ui/app/utils/classes/rolling-array.js b/ui/app/utils/classes/rolling-array.js
index 02790b88e..50269ce46 100644
--- a/ui/app/utils/classes/rolling-array.js
+++ b/ui/app/utils/classes/rolling-array.js
@@ -16,34 +16,34 @@ export default function RollingArray(maxLength, ...items) {
array.maxLength = maxLength;
// Bring the length back down to maxLength by removing from the front
- array._limit = function() {
+ array._limit = function () {
const surplus = this.length - this.maxLength;
if (surplus > 0) {
this.splice(0, surplus);
}
};
- array.push = function(...items) {
+ array.push = function (...items) {
push.apply(this, items);
this._limit();
return this.length;
};
- array.splice = function(...args) {
+ array.splice = function (...args) {
const returnValue = splice.apply(this, args);
this._limit();
return returnValue;
};
// All mutable array methods build on top of insertAt
- array.insertAt = function(...args) {
+ array.insertAt = function (...args) {
const returnValue = insertAt.apply(this, args);
this._limit();
this.arrayContentDidChange();
return returnValue;
};
- array.unshift = function() {
+ array.unshift = function () {
throw new Error('Cannot unshift onto a RollingArray');
};
diff --git a/ui/app/utils/classes/stream-logger.js b/ui/app/utils/classes/stream-logger.js
index aedd18f47..e935f199f 100644
--- a/ui/app/utils/classes/stream-logger.js
+++ b/ui/app/utils/classes/stream-logger.js
@@ -29,11 +29,11 @@ export default class StreamLogger extends EmberObject.extend(AbstractLogger) {
return this.poll.cancelAll();
}
- @task(function*() {
+ @task(function* () {
const url = this.fullUrl;
const logFetch = this.logFetch;
- const reader = yield logFetch(url).then(res => {
+ const reader = yield logFetch(url).then((res) => {
const reader = res.body.getReader();
// It's possible that the logger was stopped between the time
// polling was started and the log request responded.
diff --git a/ui/app/utils/classes/text-decoder.js b/ui/app/utils/classes/text-decoder.js
index f3bb66c81..552b152ed 100644
--- a/ui/app/utils/classes/text-decoder.js
+++ b/ui/app/utils/classes/text-decoder.js
@@ -5,8 +5,8 @@
// A complete polyfill exists if this becomes problematic:
// https://github.com/inexorabletash/text-encoding
export default window.TextDecoder ||
- function() {
- this.decode = function(value) {
+ function () {
+ this.decode = function (value) {
let text = '';
for (let i = 3; i < value.byteLength; i++) {
text += String.fromCharCode(value[i]);
diff --git a/ui/app/utils/codes-for-error.js b/ui/app/utils/codes-for-error.js
index 199290fa6..7669e96ed 100644
--- a/ui/app/utils/codes-for-error.js
+++ b/ui/app/utils/codes-for-error.js
@@ -3,7 +3,7 @@ export default function codesForError(error) {
const codes = [error.code];
if (error.errors) {
- error.errors.forEach(err => {
+ error.errors.forEach((err) => {
codes.push(err.status);
});
}
@@ -11,5 +11,5 @@ export default function codesForError(error) {
return codes
.compact()
.uniq()
- .map(code => '' + code);
+ .map((code) => '' + code);
}
diff --git a/ui/app/utils/format-duration.js b/ui/app/utils/format-duration.js
index feed6b262..768e0b43e 100644
--- a/ui/app/utils/format-duration.js
+++ b/ui/app/utils/format-duration.js
@@ -13,9 +13,27 @@ const allUnits = [
{ name: 'years', suffix: 'year', inMoment: true, pluralizable: true },
{ name: 'months', suffix: 'month', inMoment: true, pluralizable: true },
{ name: 'days', suffix: 'day', inMoment: true, pluralizable: true },
- { name: 'hours', suffix: 'h', longSuffix: 'hour', inMoment: true, pluralizable: false },
- { name: 'minutes', suffix: 'm', longSuffix: 'minute', inMoment: true, pluralizable: false },
- { name: 'seconds', suffix: 's', longSuffix: 'second', inMoment: true, pluralizable: false },
+ {
+ name: 'hours',
+ suffix: 'h',
+ longSuffix: 'hour',
+ inMoment: true,
+ pluralizable: false,
+ },
+ {
+ name: 'minutes',
+ suffix: 'm',
+ longSuffix: 'minute',
+ inMoment: true,
+ pluralizable: false,
+ },
+ {
+ name: 'seconds',
+ suffix: 's',
+ longSuffix: 'second',
+ inMoment: true,
+ pluralizable: false,
+ },
{ name: 'milliseconds', suffix: 'ms', inMoment: true, pluralizable: false },
{ name: 'microseconds', suffix: 'µs', inMoment: false, pluralizable: false },
{ name: 'nanoseconds', suffix: 'ns', inMoment: false, pluralizable: false },
@@ -30,7 +48,8 @@ const pluralizeUnits = (amount, unit, longForm) => {
suffix = amount === 1 ? unit.longSuffix : pluralize(unit.longSuffix);
} else {
// In the normal case, only pluralize based on the pluralizable flag
- suffix = amount === 1 || !unit.pluralizable ? unit.suffix : pluralize(unit.suffix);
+ suffix =
+ amount === 1 || !unit.pluralizable ? unit.suffix : pluralize(unit.suffix);
}
// A space should go between the value and the unit when the unit is a full word
@@ -47,7 +66,11 @@ const pluralizeUnits = (amount, unit, longForm) => {
* @param {Boolean} longForm Whether or not to expand single character suffixes,
* used to ensure screen readers correctly read units.
*/
-export default function formatDuration(duration = 0, units = 'ns', longForm = false) {
+export default function formatDuration(
+ duration = 0,
+ units = 'ns',
+ longForm = false
+) {
const durationParts = {};
// Moment only handles up to millisecond precision.
@@ -72,7 +95,7 @@ export default function formatDuration(duration = 0, units = 'ns', longForm = fa
allUnits
.filterBy('inMoment')
.mapBy('name')
- .forEach(unit => {
+ .forEach((unit) => {
durationParts[unit] = momentDuration[unit]();
});
diff --git a/ui/app/utils/generate-exec-url.js b/ui/app/utils/generate-exec-url.js
index a5b5d0fb7..ed619460f 100644
--- a/ui/app/utils/generate-exec-url.js
+++ b/ui/app/utils/generate-exec-url.js
@@ -1,6 +1,9 @@
import { get } from '@ember/object';
-export default function generateExecUrl(router, { job, taskGroup, task, allocation }) {
+export default function generateExecUrl(
+ router,
+ { job, taskGroup, task, allocation }
+) {
const queryParams = {};
const namespace = get(job, 'namespace.name');
@@ -33,9 +36,14 @@ export default function generateExecUrl(router, { job, taskGroup, task, allocati
}
);
} else if (taskGroup) {
- return router.urlFor('exec.task-group', get(job, 'plainId'), get(taskGroup, 'name'), {
- queryParams,
- });
+ return router.urlFor(
+ 'exec.task-group',
+ get(job, 'plainId'),
+ get(taskGroup, 'name'),
+ {
+ queryParams,
+ }
+ );
} else if (allocation) {
if (get(allocation, 'taskGroup.tasks.length') === 1) {
return router.urlFor(
@@ -43,14 +51,24 @@ export default function generateExecUrl(router, { job, taskGroup, task, allocati
get(job, 'plainId'),
get(allocation, 'taskGroup.name'),
get(allocation, 'taskGroup.tasks.firstObject.name'),
- { queryParams: { allocation: get(allocation, 'shortId'), ...queryParams } }
+ {
+ queryParams: {
+ allocation: get(allocation, 'shortId'),
+ ...queryParams,
+ },
+ }
);
} else {
return router.urlFor(
'exec.task-group',
get(job, 'plainId'),
get(allocation, 'taskGroup.name'),
- { queryParams: { allocation: get(allocation, 'shortId'), ...queryParams } }
+ {
+ queryParams: {
+ allocation: get(allocation, 'shortId'),
+ ...queryParams,
+ },
+ }
);
}
} else {
diff --git a/ui/app/utils/json-with-default.js b/ui/app/utils/json-with-default.js
index 840fefb14..4bd067e6a 100644
--- a/ui/app/utils/json-with-default.js
+++ b/ui/app/utils/json-with-default.js
@@ -4,7 +4,7 @@ import { copy } from 'ember-copy';
// Fetch only goes into the promise catch if there is a network error.
// This means that handling a 4xx or 5xx error is the responsibility
// of the developer.
-const jsonWithDefault = defaultResponse => res =>
+const jsonWithDefault = (defaultResponse) => (res) =>
res.ok ? res.json() : copy(defaultResponse, true);
export default jsonWithDefault;
diff --git a/ui/app/utils/notify-error.js b/ui/app/utils/notify-error.js
index 3ca5f5987..d907ef182 100644
--- a/ui/app/utils/notify-error.js
+++ b/ui/app/utils/notify-error.js
@@ -1,7 +1,9 @@
+/* eslint-disable ember/no-controller-access-in-routes */
+
// An error handler to provide to a promise catch to set an error
// on the application controller.
export default function notifyError(route) {
- return error => {
+ return (error) => {
route.controllerFor('application').set('error', error);
};
}
diff --git a/ui/app/utils/notify-forbidden.js b/ui/app/utils/notify-forbidden.js
index 433d1fc40..eaa4edc4a 100644
--- a/ui/app/utils/notify-forbidden.js
+++ b/ui/app/utils/notify-forbidden.js
@@ -2,7 +2,7 @@
// forbidden flag on the route
import codesForError from './codes-for-error';
export default function notifyForbidden(route) {
- return error => {
+ return (error) => {
if (codesForError(error).includes('403')) {
route.set('isForbidden', true);
} else {
diff --git a/ui/app/utils/properties/glimmer-style-string.js b/ui/app/utils/properties/glimmer-style-string.js
index cde60808f..d2d05d704 100644
--- a/ui/app/utils/properties/glimmer-style-string.js
+++ b/ui/app/utils/properties/glimmer-style-string.js
@@ -10,16 +10,18 @@ import { htmlSafe } from '@ember/template';
export default function styleString(target, name, descriptor) {
if (!descriptor.get) throw new Error('styleString only works on getters');
const orig = descriptor.get;
- descriptor.get = function() {
+ descriptor.get = function () {
const styles = orig.apply(this);
let str = '';
if (styles) {
str = Object.keys(styles)
- .reduce(function(arr, key) {
+ .reduce(function (arr, key) {
const val = styles[key];
- arr.push(key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val));
+ arr.push(
+ key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val)
+ );
return arr;
}, [])
.join(';');
diff --git a/ui/app/utils/properties/job-client-status.js b/ui/app/utils/properties/job-client-status.js
index d0e5e78fc..a71578681 100644
--- a/ui/app/utils/properties/job-client-status.js
+++ b/ui/app/utils/properties/job-client-status.js
@@ -19,12 +19,12 @@ export default function jobClientStatus(nodesKey, jobKey) {
return computed(
`${nodesKey}.[]`,
`${jobKey}.{datacenters,status,allocations.@each.clientStatus,taskGroups}`,
- function() {
+ function () {
const job = this.get(jobKey);
const nodes = this.get(nodesKey);
// Filter nodes by the datacenters defined in the job.
- const filteredNodes = nodes.filter(n => {
+ const filteredNodes = nodes.filter((n) => {
return job.datacenters.indexOf(n.datacenter) >= 0;
});
@@ -34,7 +34,7 @@ export default function jobClientStatus(nodesKey, jobKey) {
// Group the job allocations by the ID of the client that is running them.
const allocsByNodeID = {};
- job.allocations.forEach(a => {
+ job.allocations.forEach((a) => {
const nodeId = a.belongsTo('node').id();
if (!allocsByNodeID[nodeId]) {
allocsByNodeID[nodeId] = [];
@@ -47,7 +47,7 @@ export default function jobClientStatus(nodesKey, jobKey) {
byStatus: {},
totalNodes: filteredNodes.length,
};
- filteredNodes.forEach(n => {
+ filteredNodes.forEach((n) => {
const status = jobStatus(allocsByNodeID[n.id], job.taskGroups.length);
result.byNode[n.id] = status;
@@ -63,9 +63,9 @@ export default function jobClientStatus(nodesKey, jobKey) {
}
function allQueued(nodes) {
- const nodeIDs = nodes.map(n => n.id);
+ const nodeIDs = nodes.map((n) => n.id);
return {
- byNode: Object.fromEntries(nodeIDs.map(id => [id, 'queued'])),
+ byNode: Object.fromEntries(nodeIDs.map((id) => [id, 'queued'])),
byStatus: canonicalizeStatus({ queued: nodeIDs }),
totalNodes: nodes.length,
};
@@ -105,7 +105,7 @@ function jobStatus(allocs, expected) {
// Count how many allocations are in each `clientStatus` value.
const summary = allocs
- .filter(a => !a.isOld)
+ .filter((a) => !a.isOld)
.reduce((acc, a) => {
const status = a.clientStatus;
if (!acc[status]) {
diff --git a/ui/app/utils/properties/short-uuid.js b/ui/app/utils/properties/short-uuid.js
index 0a7af211c..4c7862f4c 100644
--- a/ui/app/utils/properties/short-uuid.js
+++ b/ui/app/utils/properties/short-uuid.js
@@ -6,7 +6,7 @@ import { computed } from '@ember/object';
// ex. id: 123456-7890-abcd-efghijk
// short: shortUUIDProperty('id') // 123456
export default function shortUUIDProperty(uuidKey) {
- return computed(uuidKey, function() {
+ return computed(uuidKey, function () {
return this.get(uuidKey).split('-')[0];
});
}
diff --git a/ui/app/utils/properties/style-string.js b/ui/app/utils/properties/style-string.js
index 3f3a225f2..804fd5218 100644
--- a/ui/app/utils/properties/style-string.js
+++ b/ui/app/utils/properties/style-string.js
@@ -7,15 +7,17 @@ import { htmlSafe } from '@ember/template';
// ex. styleProps: { color: '#FF0', border-width: '1px' }
// styleStr: styleStringProperty('styleProps') // color:#FF0;border-width:1px
export default function styleStringProperty(prop) {
- return computed(prop, function() {
+ return computed(prop, function () {
const styles = get(this, prop);
let str = '';
if (styles) {
str = Object.keys(styles)
- .reduce(function(arr, key) {
+ .reduce(function (arr, key) {
const val = styles[key];
- arr.push(key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val));
+ arr.push(
+ key + ':' + (typeof val === 'number' ? val.toFixed(2) + 'px' : val)
+ );
return arr;
}, [])
.join(';');
diff --git a/ui/app/utils/properties/sum-aggregation.js b/ui/app/utils/properties/sum-aggregation.js
index 41a486a0e..54e82ed5b 100644
--- a/ui/app/utils/properties/sum-aggregation.js
+++ b/ui/app/utils/properties/sum-aggregation.js
@@ -6,7 +6,7 @@ import { computed } from '@ember/object';
// ex. list: [ { foo: 1 }, { foo: 3 } ]
// sum: sumAggregationProperty('list', 'foo') // 4
export default function sumAggregationProperty(listKey, propKey) {
- return computed(`${listKey}.@each.${propKey}`, function() {
+ return computed(`${listKey}.@each.${propKey}`, function () {
return this.get(listKey)
.mapBy(propKey)
.reduce((sum, count) => sum + count, 0);
diff --git a/ui/app/utils/properties/uniquely.js b/ui/app/utils/properties/uniquely.js
index 96ce520e4..c8f32032a 100644
--- a/ui/app/utils/properties/uniquely.js
+++ b/ui/app/utils/properties/uniquely.js
@@ -6,7 +6,7 @@ import { guidFor } from '@ember/object/internals';
//
// ex. @uniquely('name') // 'name-ember129383'
export default function uniquely(prefix) {
- return computed(function() {
+ return computed(function () {
return `${prefix}-${guidFor(this)}`;
});
}
diff --git a/ui/app/utils/properties/watch.js b/ui/app/utils/properties/watch.js
index ee890ef2b..08dc18842 100644
--- a/ui/app/utils/properties/watch.js
+++ b/ui/app/utils/properties/watch.js
@@ -11,7 +11,7 @@ import config from 'nomad-ui/config/environment';
const isEnabled = config.APP.blockingQueries !== false;
export function watchRecord(modelName) {
- return task(function*(id, throttle = 2000) {
+ return task(function* (id, throttle = 2000) {
assert(
'To watch a record, the record adapter MUST extend Watchable',
this.store.adapterFor(modelName) instanceof Watchable
@@ -40,7 +40,7 @@ export function watchRecord(modelName) {
}
export function watchRelationship(relationshipName) {
- return task(function*(model, throttle = 2000) {
+ return task(function* (model, throttle = 2000) {
assert(
'To watch a relationship, the adapter of the model provided to the watchRelationship task MUST extend Watchable',
this.store.adapterFor(model.constructor.modelName) instanceof Watchable
@@ -68,7 +68,7 @@ export function watchRelationship(relationshipName) {
}
export function watchAll(modelName) {
- return task(function*(throttle = 2000) {
+ return task(function* (throttle = 2000) {
assert(
'To watch all, the respective adapter MUST extend Watchable',
this.store.adapterFor(modelName) instanceof Watchable
@@ -94,7 +94,7 @@ export function watchAll(modelName) {
}
export function watchQuery(modelName) {
- return task(function*(params, throttle = 10000) {
+ return task(function* (params, throttle = 10000) {
assert(
'To watch a query, the adapter for the type being queried MUST extend Watchable',
this.store.adapterFor(modelName) instanceof Watchable
diff --git a/ui/app/utils/qp-serialize.js b/ui/app/utils/qp-serialize.js
index 7717efc28..b3f146274 100644
--- a/ui/app/utils/qp-serialize.js
+++ b/ui/app/utils/qp-serialize.js
@@ -1,23 +1,21 @@
import { computed } from '@ember/object';
// An unattractive but robust way to encode query params
-export const serialize = val => {
+export const serialize = (val) => {
if (typeof val === 'string' || typeof val === 'number') return val;
return val.length ? JSON.stringify(val) : '';
};
-export const deserialize = str => {
+export const deserialize = (str) => {
try {
- return JSON.parse(str)
- .compact()
- .without('');
+ return JSON.parse(str).compact().without('');
} catch (e) {
return [];
}
};
// A computed property macro for deserializing a query param
-export const deserializedQueryParam = qpKey =>
- computed(qpKey, function() {
+export const deserializedQueryParam = (qpKey) =>
+ computed(qpKey, function () {
return deserialize(this.get(qpKey));
});
diff --git a/ui/app/utils/resources-diffs.js b/ui/app/utils/resources-diffs.js
index 068469f6a..7a301f11d 100644
--- a/ui/app/utils/resources-diffs.js
+++ b/ui/app/utils/resources-diffs.js
@@ -10,7 +10,9 @@ export default class ResourcesDiffs {
this.model = model;
this.multiplier = multiplier;
this.recommendations = recommendations;
- this.excludedRecommendations = excludedRecommendations.filter(r => recommendations.includes(r));
+ this.excludedRecommendations = excludedRecommendations.filter((r) =>
+ recommendations.includes(r)
+ );
}
get cpu() {
@@ -28,8 +30,14 @@ export default class ResourcesDiffs {
}
get memory() {
- const included = this.includedRecommendations.filterBy('resource', 'MemoryMB');
- const excluded = this.excludedRecommendations.filterBy('resource', 'MemoryMB');
+ const included = this.includedRecommendations.filterBy(
+ 'resource',
+ 'MemoryMB'
+ );
+ const excluded = this.excludedRecommendations.filterBy(
+ 'resource',
+ 'MemoryMB'
+ );
return new ResourceDiffs(
this.model.reservedMemory,
@@ -42,7 +50,9 @@ export default class ResourcesDiffs {
}
get includedRecommendations() {
- return this.recommendations.reject(r => this.excludedRecommendations.includes(r));
+ return this.recommendations.reject((r) =>
+ this.excludedRecommendations.includes(r)
+ );
}
}
@@ -67,7 +77,9 @@ class ResourceDiffs {
if (this.included.length) {
return (
this.included.mapBy('value').reduce(sumAggregate, 0) +
- this.excluded.mapBy(`task.${this.baseTaskPropertyName}`).reduce(sumAggregate, 0)
+ this.excluded
+ .mapBy(`task.${this.baseTaskPropertyName}`)
+ .reduce(sumAggregate, 0)
);
} else {
return this.base;
diff --git a/ui/app/utils/stream-frames.js b/ui/app/utils/stream-frames.js
index a4a4f54df..7a861fb8b 100644
--- a/ui/app/utils/stream-frames.js
+++ b/ui/app/utils/stream-frames.js
@@ -13,14 +13,13 @@ const decoder = new TextDecoderLite('utf-8');
* object represents.
*/
export function decode(chunk) {
- const lines = chunk
- .replace(/\}\{/g, '}\n{')
- .split('\n')
- .without('');
- const frames = lines.map(line => JSON.parse(line)).filter(frame => frame.Data);
+ const lines = chunk.replace(/\}\{/g, '}\n{').split('\n').without('');
+ const frames = lines
+ .map((line) => JSON.parse(line))
+ .filter((frame) => frame.Data);
if (frames.length) {
- frames.forEach(frame => (frame.Data = b64decode(frame.Data)));
+ frames.forEach((frame) => (frame.Data = b64decode(frame.Data)));
return {
offset: frames[frames.length - 1].Offset,
message: frames.mapBy('Data').join(''),
diff --git a/ui/app/utils/styleguide/product-metadata.js b/ui/app/utils/styleguide/product-metadata.js
index 37031d155..e515c3371 100644
--- a/ui/app/utils/styleguide/product-metadata.js
+++ b/ui/app/utils/styleguide/product-metadata.js
@@ -2,29 +2,25 @@ export default [
{
name: 'Nomad',
lang: 'golang',
- desc:
- 'Nomad is a flexible, enterprise-grade cluster scheduler designed to easily integrate into existing workflows. Nomad can run a diverse workload of micro-service, batch, containerized and non-containerized applications.',
+ desc: 'Nomad is a flexible, enterprise-grade cluster scheduler designed to easily integrate into existing workflows. Nomad can run a diverse workload of micro-service, batch, containerized and non-containerized applications.',
link: 'https://www.nomadproject.io/',
},
{
name: 'Terraform',
lang: 'golang',
- desc:
- 'Terraform is a tool for building, changing, and combining infrastructure safely and efficiently.',
+ desc: 'Terraform is a tool for building, changing, and combining infrastructure safely and efficiently.',
link: 'https://www.terraform.io/',
},
{
name: 'Vault',
lang: 'golang',
- desc:
- 'A tool for secrets management, encryption as a service, and privileged access management',
+ desc: 'A tool for secrets management, encryption as a service, and privileged access management',
link: 'https://www.vaultproject.io/',
},
{
name: 'Consul',
lang: 'golang',
- desc:
- 'Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.',
+ desc: 'Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure.',
link: 'https://www.consul.io/',
},
{
@@ -36,8 +32,7 @@ export default [
{
name: 'Packer',
lang: 'golang',
- desc:
- 'Packer is a tool for creating identical machine images for multiple platforms from a single source configuration.',
+ desc: 'Packer is a tool for creating identical machine images for multiple platforms from a single source configuration.',
link: 'https://www.packer.io/',
},
];
diff --git a/ui/app/utils/wait.js b/ui/app/utils/wait.js
index 3949cf23a..351b2a9a8 100644
--- a/ui/app/utils/wait.js
+++ b/ui/app/utils/wait.js
@@ -2,7 +2,7 @@ import RSVP from 'rsvp';
// An always passing promise used to throttle other promises
export default function wait(duration) {
- return new RSVP.Promise(resolve => {
+ return new RSVP.Promise((resolve) => {
setTimeout(() => {
resolve(`Waited ${duration}ms`);
}, duration);
diff --git a/ui/blueprints/story/index.js b/ui/blueprints/story/index.js
index 8cb37d653..56fd9194c 100644
--- a/ui/blueprints/story/index.js
+++ b/ui/blueprints/story/index.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-string-prototype-extensions */
const getPathOption = require('ember-cli-get-component-path-option');
const stringUtil = require('ember-cli-string-utils');
const path = require('path');
@@ -5,22 +6,22 @@ const path = require('path');
module.exports = {
description: 'generates a story for storybook',
- fileMapTokens: function() {
+ fileMapTokens: function () {
let { project } = this;
return {
- __path__: function() {
+ __path__: function () {
return path.relative(project.root, project.root);
},
- __markdownname__: function(options) {
+ __markdownname__: function (options) {
return options.dasherizedModuleName;
},
- __name__: function(options) {
+ __name__: function (options) {
return options.dasherizedModuleName;
},
};
},
- locals: function(options) {
+ locals: function (options) {
let contents = '';
return {
@@ -29,7 +30,7 @@ module.exports = {
header: stringUtil
.dasherize(options.entity.name)
.split('-')
- .map(word => stringUtil.capitalize(word))
+ .map((word) => stringUtil.capitalize(word))
.join(' '),
};
},
diff --git a/ui/config/deprecation-workflow.js b/ui/config/deprecation-workflow.js
index e7c8c41fe..abb58e926 100644
--- a/ui/config/deprecation-workflow.js
+++ b/ui/config/deprecation-workflow.js
@@ -5,7 +5,10 @@ self.deprecationWorkflow.config = {
{ handler: 'throw', matchId: 'ember-inflector.globals' },
{ handler: 'throw', matchId: 'ember-runtime.deprecate-copy-copyable' },
{ handler: 'throw', matchId: 'ember-console.deprecate-logger' },
- { handler: 'throw', matchId: 'ember-test-helpers.rendering-context.jquery-element' },
+ {
+ handler: 'throw',
+ matchId: 'ember-test-helpers.rendering-context.jquery-element',
+ },
{ handler: 'throw', matchId: 'ember-cli-page-object.is-property' },
{ handler: 'throw', matchId: 'ember-views.partial' },
],
diff --git a/ui/config/environment.js b/ui/config/environment.js
index 35f112b9b..d0bfae307 100644
--- a/ui/config/environment.js
+++ b/ui/config/environment.js
@@ -6,7 +6,7 @@ if (process.env.USE_MIRAGE) {
USE_MIRAGE = process.env.USE_MIRAGE == 'true';
}
-module.exports = function(environment) {
+module.exports = function (environment) {
var ENV = {
modulePrefix: 'nomad-ui',
environment: environment,
diff --git a/ui/config/targets.js b/ui/config/targets.js
index 9f6cc6396..1e48e0599 100644
--- a/ui/config/targets.js
+++ b/ui/config/targets.js
@@ -1,6 +1,10 @@
'use strict';
-const browsers = ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'];
+const browsers = [
+ 'last 1 Chrome versions',
+ 'last 1 Firefox versions',
+ 'last 1 Safari versions',
+];
module.exports = {
browsers,
diff --git a/ui/ember-cli-build.js b/ui/ember-cli-build.js
index 5b4d0eb85..bbeaf43f4 100644
--- a/ui/ember-cli-build.js
+++ b/ui/ember-cli-build.js
@@ -5,10 +5,13 @@ const environment = EmberApp.env();
const isProd = environment === 'production';
const isTest = environment === 'test';
-module.exports = function(defaults) {
+module.exports = function (defaults) {
var app = new EmberApp(defaults, {
svg: {
- paths: ['node_modules/@hashicorp/structure-icons/dist', 'public/images/icons'],
+ paths: [
+ 'node_modules/@hashicorp/structure-icons/dist',
+ 'public/images/icons',
+ ],
optimize: {
plugins: [{ removeViewBox: false }],
},
diff --git a/ui/jsconfig.json b/ui/jsconfig.json
new file mode 100644
index 000000000..8d067cec4
--- /dev/null
+++ b/ui/jsconfig.json
@@ -0,0 +1,5 @@
+{
+ "compilerOptions": {
+ "experimentalDecorators": true
+ }
+}
\ No newline at end of file
diff --git a/ui/lib/bulma/index.js b/ui/lib/bulma/index.js
index 0e773d0a7..3c7875e25 100644
--- a/ui/lib/bulma/index.js
+++ b/ui/lib/bulma/index.js
@@ -7,11 +7,11 @@ var Funnel = require('broccoli-funnel');
module.exports = {
name: 'bulma',
- isDevelopingAddon: function() {
+ isDevelopingAddon: function () {
return true;
},
- included: function(app) {
+ included: function (app) {
this._super.included.apply(this, arguments);
// see: https://github.com/ember-cli/ember-cli/issues/3718
@@ -23,7 +23,7 @@ module.exports = {
return app;
},
- treeForStyles: function() {
+ treeForStyles: function () {
return new Funnel(this.bulmaPath, {
srcDir: '/',
destDir: 'app/styles/bulma',
diff --git a/ui/package.json b/ui/package.json
index 1f7250733..8f5a619ba 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -10,9 +10,12 @@
"scripts": {
"build": "ember build --environment=production",
"precommit": "lint-staged",
- "lint": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*",
+ "lint": "npm-run-all --aggregate-output --continue-on-error --parallel 'lint:!(fix)'",
+ "lint:fix": "npm-run-all --aggregate-output --continue-on-error --parallel lint:*:fix",
"lint:hbs": "ember-template-lint .",
- "lint:js": "eslint .",
+ "lint:hbs:fix": "ember-template-lint . --fix",
+ "lint:js": "eslint . --cache",
+ "lint:js:fix": "eslint . --fix",
"start": "ember server",
"build-storybook": "STORYBOOK=true ember build && build-storybook -s dist",
"storybook": "STORYBOOK=true start-storybook -p 6006 -s dist",
@@ -102,10 +105,13 @@
"ember-template-lint": "^2.9.1",
"ember-test-selectors": "^5.0.0",
"ember-truth-helpers": "^2.0.0",
- "eslint": "^7.5.0",
- "eslint-plugin-ember": "^8.9.1",
+ "eslint": "^7.32.0",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-ember": "^10.5.8",
"eslint-plugin-ember-a11y-testing": "a11y-tool-sandbox/eslint-plugin-ember-a11y-testing#ca31c9698c7cb105f1c9761d98fcaca7d6874459",
"eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-prettier": "^3.4.1",
+ "eslint-plugin-qunit": "^6.2.0",
"faker": "^4.1.0",
"flat": "^5.0.2",
"fuse.js": "^3.4.4",
@@ -120,7 +126,7 @@
"morgan": "^1.3.2",
"npm-run-all": "^4.1.5",
"pretender": "^3.0.1",
- "prettier": "^1.4.4",
+ "prettier": "^2.5.1",
"query-string": "^7.0.1",
"qunit-dom": "^2.0.0",
"sass": "^1.17.3",
diff --git a/ui/server/.eslintrc.js b/ui/server/.eslintrc.js
index 1147d299f..1a4431d85 100644
--- a/ui/server/.eslintrc.js
+++ b/ui/server/.eslintrc.js
@@ -1,5 +1,5 @@
module.exports = {
env: {
- node: true
- }
+ node: true,
+ },
};
diff --git a/ui/server/index.js b/ui/server/index.js
index 701da9928..d0eb3d395 100644
--- a/ui/server/index.js
+++ b/ui/server/index.js
@@ -1,14 +1,16 @@
'use strict';
-module.exports = function(app, options) {
- const globSync = require('glob').sync;
- const mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
- const proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(require);
+module.exports = function (app, options) {
+ const globSync = require('glob').sync;
+ const mocks = globSync('./mocks/**/*.js', { cwd: __dirname }).map(require);
+ const proxies = globSync('./proxies/**/*.js', { cwd: __dirname }).map(
+ require
+ );
// Log proxy requests
const morgan = require('morgan');
app.use(morgan('dev'));
- mocks.forEach(route => route(app, options));
- proxies.forEach(route => route(app, options));
+ mocks.forEach((route) => route(app, options));
+ proxies.forEach((route) => route(app, options));
};
diff --git a/ui/server/proxies/api.js b/ui/server/proxies/api.js
index a8a0aeff7..3e6ab01e1 100644
--- a/ui/server/proxies/api.js
+++ b/ui/server/proxies/api.js
@@ -2,7 +2,7 @@
const proxyPath = '/v1';
-module.exports = function(app, options) {
+module.exports = function (app, options) {
// For options, see:
// https://github.com/nodejitsu/node-http-proxy
@@ -29,19 +29,22 @@ module.exports = function(app, options) {
changeOrigin: true,
});
- proxy.on('error', function(err, req) {
+ proxy.on('error', function (err, req) {
// eslint-disable-next-line
console.error(err, req.url);
});
- app.use(proxyPath, function(req, res) {
+ app.use(proxyPath, function (req, res) {
// include root path in proxied request
req.url = proxyPath + req.url;
proxy.web(req, res, { target: proxyAddress });
});
- server.on('upgrade', function(req, socket, head) {
- if (req.url.startsWith('/v1/client/allocation') && req.url.includes('exec?')) {
+ server.on('upgrade', function (req, socket, head) {
+ if (
+ req.url.startsWith('/v1/client/allocation') &&
+ req.url.includes('exec?')
+ ) {
req.headers.origin = proxyAddress;
proxy.ws(req, socket, head, { target: proxyAddress });
}
diff --git a/ui/stories/charts/distribution-bar.stories.js b/ui/stories/charts/distribution-bar.stories.js
index eb5596d8e..2826d29b9 100644
--- a/ui/stories/charts/distribution-bar.stories.js
+++ b/ui/stories/charts/distribution-bar.stories.js
@@ -98,7 +98,7 @@ export let LiveUpdating = () => {
controller: EmberObject.extend({
timerTicks: 0,
- startTimer: on('init', function() {
+ startTimer: on('init', function () {
this.set(
'timer',
setInterval(() => {
@@ -111,7 +111,7 @@ export let LiveUpdating = () => {
clearInterval(this.timer);
},
- distributionBarDataRotating: computed('timerTicks', function() {
+ distributionBarDataRotating: computed('timerTicks', function () {
return [
{ label: 'one', value: Math.round(Math.random() * 50) },
{ label: 'two', value: Math.round(Math.random() * 50) },
diff --git a/ui/stories/charts/line-chart.stories.js b/ui/stories/charts/line-chart.stories.js
index 08e4f00f2..f97fcb33e 100644
--- a/ui/stories/charts/line-chart.stories.js
+++ b/ui/stories/charts/line-chart.stories.js
@@ -148,7 +148,7 @@ export let LiveData = () => {
`,
context: {
controller: EmberObject.extend({
- startTimer: on('init', function() {
+ startTimer: on('init', function () {
this.lineChartLive = [];
this.set(
@@ -170,7 +170,7 @@ export let LiveData = () => {
},
get secondsFormat() {
- return date => moment(date).format('HH:mm:ss');
+ return (date) => moment(date).format('HH:mm:ss');
},
}).create(),
},
@@ -272,9 +272,7 @@ export let VerticalAnnotations = () => {
data: DelayedArray.create(
new Array(180).fill(null).map((_, idx) => ({
y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200,
- x: moment()
- .add(idx, 'd')
- .toDate(),
+ x: moment().add(idx, 'd').toDate(),
}))
),
annotations: [
@@ -291,16 +289,12 @@ export let VerticalAnnotations = () => {
info: 'This is the max of the sine curve',
},
{
- x: moment()
- .add(89, 'd')
- .toDate(),
+ x: moment().add(89, 'd').toDate(),
type: 'info',
info: 'This is the end of the first period',
},
{
- x: moment()
- .add(96, 'd')
- .toDate(),
+ x: moment().add(96, 'd').toDate(),
type: 'info',
info: 'A close annotation for staggering purposes',
},
@@ -312,9 +306,7 @@ export let VerticalAnnotations = () => {
info: 'This is the min of the sine curve',
},
{
- x: moment()
- .add(179, 'd')
- .toDate(),
+ x: moment().add(179, 'd').toDate(),
type: 'info',
info: 'Far right',
},
@@ -348,9 +340,7 @@ export let HorizontalAnnotations = () => {
data: DelayedArray.create(
new Array(180).fill(null).map((_, idx) => ({
y: Math.sin((idx * 4 * Math.PI) / 180) * 100 + 200,
- x: moment()
- .add(idx, 'd')
- .toDate(),
+ x: moment().add(idx, 'd').toDate(),
}))
),
annotations: [
diff --git a/ui/stories/charts/progress-bar.stories.js b/ui/stories/charts/progress-bar.stories.js
index cf42ed60b..617fbd20e 100644
--- a/ui/stories/charts/progress-bar.stories.js
+++ b/ui/stories/charts/progress-bar.stories.js
@@ -101,7 +101,7 @@ export let LiveUpdates = () => {
data: EmberObject.extend({
timerTicks: 0,
- startTimer: on('init', function() {
+ startTimer: on('init', function () {
this.set(
'timer',
setInterval(() => {
@@ -114,21 +114,26 @@ export let LiveUpdates = () => {
clearInterval(this.timer);
},
- denominator: computed('timerTicks', function() {
+ denominator: computed('timerTicks', function () {
return Math.round(Math.random() * 1000);
}),
- percentage: computed('timerTicks', function() {
+ percentage: computed('timerTicks', function () {
return Math.round(Math.random() * 100) / 100;
}),
- numerator: computed('denominator', 'percentage', function() {
+ numerator: computed('denominator', 'percentage', function () {
return Math.round(this.denominator * this.percentage * 100) / 100;
}),
- liveDetails: computed('denominator', 'numerator', 'percentage', function() {
- return this.getProperties('denominator', 'numerator', 'percentage');
- }),
+ liveDetails: computed(
+ 'denominator',
+ 'numerator',
+ 'percentage',
+ function () {
+ return this.getProperties('denominator', 'numerator', 'percentage');
+ }
+ ),
}).create(),
},
};
diff --git a/ui/stories/charts/stats-time-series.stories.js b/ui/stories/charts/stats-time-series.stories.js
index 83f3284af..959dda4b9 100644
--- a/ui/stories/charts/stats-time-series.stories.js
+++ b/ui/stories/charts/stats-time-series.stories.js
@@ -10,10 +10,7 @@ export default {
title: 'Charts/Stats Time Series',
};
-let ts = offset =>
- moment()
- .subtract(offset, 'm')
- .toDate();
+let ts = (offset) => moment().subtract(offset, 'm').toDate();
export let Standard = () => {
return {
@@ -66,19 +63,23 @@ export let HighLowComparison = () => {
data: EmberObject.extend({
timerTicks: 0,
- startTimer: on('init', function() {
+ startTimer: on('init', function () {
this.set(
'timer',
setInterval(() => {
let metricsHigh = this.metricsHigh;
- let prev = metricsHigh.length ? metricsHigh[metricsHigh.length - 1].percent : 0.9;
+ let prev = metricsHigh.length
+ ? metricsHigh[metricsHigh.length - 1].percent
+ : 0.9;
this.appendTSValue(
metricsHigh,
Math.min(Math.max(prev + Math.random() * 0.05 - 0.025, 0.5), 1)
);
let metricsLow = this.metricsLow;
- let prev2 = metricsLow.length ? metricsLow[metricsLow.length - 1].percent : 0.1;
+ let prev2 = metricsLow.length
+ ? metricsLow[metricsLow.length - 1].percent
+ : 0.1;
this.appendTSValue(
metricsLow,
Math.min(Math.max(prev2 + Math.random() * 0.05 - 0.025, 0), 0.5)
@@ -102,16 +103,16 @@ export let HighLowComparison = () => {
clearInterval(this.timer);
},
- metricsHigh: computed(function() {
+ metricsHigh: computed(function () {
return [];
}),
- metricsLow: computed(function() {
+ metricsLow: computed(function () {
return [];
}),
secondsFormat() {
- return date => moment(date).format('HH:mm:ss');
+ return (date) => moment(date).format('HH:mm:ss');
},
}).create(),
},
diff --git a/ui/stories/components/copy-button.stories.js b/ui/stories/components/copy-button.stories.js
index 3ebbd7082..f67b0369e 100644
--- a/ui/stories/components/copy-button.stories.js
+++ b/ui/stories/components/copy-button.stories.js
@@ -20,7 +20,10 @@ export let CopyButton = () => {
`,
context: {
- clipboardText: text('Clipboard Text', 'e8c898a0-794b-9063-7a7f-bf0c4a405f83'),
+ clipboardText: text(
+ 'Clipboard Text',
+ 'e8c898a0-794b-9063-7a7f-bf0c4a405f83'
+ ),
},
};
};
diff --git a/ui/stories/components/diff-viewer.stories.js b/ui/stories/components/diff-viewer.stories.js
index cbadcb0b7..4a13e5eeb 100644
--- a/ui/stories/components/diff-viewer.stories.js
+++ b/ui/stories/components/diff-viewer.stories.js
@@ -16,10 +16,34 @@ export let DiffViewerWithInsertions = () => {
`,
context: {
insertionsOnly: generateDiff([
- { Annotations: null, Name: 'Attempts', New: '15', Old: '15', Type: 'None' },
- { Annotations: null, Name: 'Delay', New: '25000000000', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Interval', New: '900000000000', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Mode', New: 'delay', Old: 'delay', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Attempts',
+ New: '15',
+ Old: '15',
+ Type: 'None',
+ },
+ {
+ Annotations: null,
+ Name: 'Delay',
+ New: '25000000000',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Interval',
+ New: '900000000000',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Mode',
+ New: 'delay',
+ Old: 'delay',
+ Type: 'None',
+ },
]),
},
};
@@ -37,7 +61,13 @@ export let DiffViewerWithDeletions = () => {
`,
context: {
deletionsOnly: generateDiff([
- { Annotations: null, Name: 'Attempts', New: '15', Old: '15', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Attempts',
+ New: '15',
+ Old: '15',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'Delay',
@@ -52,7 +82,13 @@ export let DiffViewerWithDeletions = () => {
Old: '900000000000',
Type: 'None',
},
- { Annotations: null, Name: 'Mode', New: '', Old: 'delay', Type: 'Deleted' },
+ {
+ Annotations: null,
+ Name: 'Mode',
+ New: '',
+ Old: 'delay',
+ Type: 'Deleted',
+ },
]),
},
};
@@ -71,7 +107,13 @@ export let DiffViewerWithEdits = () => {
`,
context: {
editsOnly: generateDiff([
- { Annotations: null, Name: 'Attempts', New: '15', Old: '15', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Attempts',
+ New: '15',
+ Old: '15',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'Delay',
@@ -86,7 +128,13 @@ export let DiffViewerWithEdits = () => {
Old: '250000000000',
Type: 'Edited',
},
- { Annotations: null, Name: 'Mode', New: 'delay', Old: 'delay', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Mode',
+ New: 'delay',
+ Old: 'delay',
+ Type: 'None',
+ },
]),
},
};
@@ -156,9 +204,27 @@ export let DiffViewerWithManyChanges = () => {
},
{
Fields: [
- { Annotations: null, Name: 'CPU', New: '1000', Old: '500', Type: 'Edited' },
- { Annotations: null, Name: 'DiskMB', New: '0', Old: '0', Type: 'None' },
- { Annotations: null, Name: 'IOPS', New: '0', Old: '0', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'CPU',
+ New: '1000',
+ Old: '500',
+ Type: 'Edited',
+ },
+ {
+ Annotations: null,
+ Name: 'DiskMB',
+ New: '0',
+ Old: '0',
+ Type: 'None',
+ },
+ {
+ Annotations: null,
+ Name: 'IOPS',
+ New: '0',
+ Old: '0',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'MemoryMB',
@@ -171,7 +237,13 @@ export let DiffViewerWithManyChanges = () => {
Objects: [
{
Fields: [
- { Annotations: null, Name: 'MBits', New: '100', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'MBits',
+ New: '100',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'Network',
Objects: [
@@ -194,7 +266,13 @@ export let DiffViewerWithManyChanges = () => {
},
{
Fields: [
- { Annotations: null, Name: 'MBits', New: '', Old: '10', Type: 'Deleted' },
+ {
+ Annotations: null,
+ Name: 'MBits',
+ New: '',
+ Old: '10',
+ Type: 'Deleted',
+ },
],
Name: 'Network',
Objects: [
@@ -234,13 +312,25 @@ export let DiffViewerWithManyChanges = () => {
Old: 'redis-cache',
Type: 'None',
},
- { Annotations: null, Name: 'PortLabel', New: 'db', Old: 'db', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'PortLabel',
+ New: 'db',
+ Old: 'db',
+ Type: 'None',
+ },
],
Name: 'Service',
Objects: [
{
Fields: [
- { Annotations: null, Name: 'Tags', New: 'redis', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Tags',
+ New: 'redis',
+ Old: '',
+ Type: 'Added',
+ },
{
Annotations: null,
Name: 'Tags',
@@ -269,7 +359,13 @@ export let DiffViewerWithManyChanges = () => {
Old: '',
Type: 'None',
},
- { Annotations: null, Name: 'Command', New: '', Old: '', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Command',
+ New: '',
+ Old: '',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'GRPCService',
@@ -298,7 +394,13 @@ export let DiffViewerWithManyChanges = () => {
Old: '10000000000',
Type: 'Edited',
},
- { Annotations: null, Name: 'Method', New: '', Old: '', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Method',
+ New: '',
+ Old: '',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'Name',
@@ -306,9 +408,27 @@ export let DiffViewerWithManyChanges = () => {
Old: 'alive',
Type: 'None',
},
- { Annotations: null, Name: 'Path', New: '', Old: '', Type: 'None' },
- { Annotations: null, Name: 'PortLabel', New: '', Old: '', Type: 'None' },
- { Annotations: null, Name: 'Protocol', New: '', Old: '', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Path',
+ New: '',
+ Old: '',
+ Type: 'None',
+ },
+ {
+ Annotations: null,
+ Name: 'PortLabel',
+ New: '',
+ Old: '',
+ Type: 'None',
+ },
+ {
+ Annotations: null,
+ Name: 'Protocol',
+ New: '',
+ Old: '',
+ Type: 'None',
+ },
{
Annotations: null,
Name: 'TLSSkipVerify',
@@ -323,7 +443,13 @@ export let DiffViewerWithManyChanges = () => {
Old: '2000000000',
Type: 'Edited',
},
- { Annotations: null, Name: 'Type', New: 'tcp', Old: 'tcp', Type: 'None' },
+ {
+ Annotations: null,
+ Name: 'Type',
+ New: 'tcp',
+ Old: 'tcp',
+ Type: 'None',
+ },
],
Name: 'Check',
Objects: null,
@@ -341,16 +467,46 @@ export let DiffViewerWithManyChanges = () => {
},
{
Fields: [
- { Annotations: null, Name: 'Count', New: '1', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Meta[key]', New: 'value', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Meta[red]', New: 'fish', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Count',
+ New: '1',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Meta[key]',
+ New: 'value',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Meta[red]',
+ New: 'fish',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'cache2',
Objects: [
{
Fields: [
- { Annotations: null, Name: 'Attempts', New: '2', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Delay', New: '15000000000', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Attempts',
+ New: '2',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Delay',
+ New: '15000000000',
+ Old: '',
+ Type: 'Added',
+ },
{
Annotations: null,
Name: 'Interval',
@@ -358,7 +514,13 @@ export let DiffViewerWithManyChanges = () => {
Old: '',
Type: 'Added',
},
- { Annotations: null, Name: 'Mode', New: 'fail', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Mode',
+ New: 'fail',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'RestartPolicy',
Objects: null,
@@ -366,9 +528,27 @@ export let DiffViewerWithManyChanges = () => {
},
{
Fields: [
- { Annotations: null, Name: 'Migrate', New: 'false', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'SizeMB', New: '300', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'Sticky', New: 'false', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Migrate',
+ New: 'false',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'SizeMB',
+ New: '300',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'Sticky',
+ New: 'false',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'EphemeralDisk',
Objects: null,
@@ -379,7 +559,13 @@ export let DiffViewerWithManyChanges = () => {
{
Annotations: null,
Fields: [
- { Annotations: null, Name: 'Driver', New: 'docker', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Driver',
+ New: 'docker',
+ Old: '',
+ Type: 'Added',
+ },
{
Annotations: null,
Name: 'KillTimeout',
@@ -387,8 +573,20 @@ export let DiffViewerWithManyChanges = () => {
Old: '',
Type: 'Added',
},
- { Annotations: null, Name: 'Leader', New: 'false', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'ShutdownDelay', New: '0', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'Leader',
+ New: 'false',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'ShutdownDelay',
+ New: '0',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'redis',
Objects: [
@@ -415,16 +613,46 @@ export let DiffViewerWithManyChanges = () => {
},
{
Fields: [
- { Annotations: null, Name: 'CPU', New: '500', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'DiskMB', New: '0', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'IOPS', New: '0', Old: '', Type: 'Added' },
- { Annotations: null, Name: 'MemoryMB', New: '256', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'CPU',
+ New: '500',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'DiskMB',
+ New: '0',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'IOPS',
+ New: '0',
+ Old: '',
+ Type: 'Added',
+ },
+ {
+ Annotations: null,
+ Name: 'MemoryMB',
+ New: '256',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'Resources',
Objects: [
{
Fields: [
- { Annotations: null, Name: 'MBits', New: '10', Old: '', Type: 'Added' },
+ {
+ Annotations: null,
+ Name: 'MBits',
+ New: '10',
+ Old: '',
+ Type: 'Added',
+ },
],
Name: 'Network',
Objects: [
@@ -469,7 +697,15 @@ function generateDiff(changeset) {
Objects: null,
TaskGroups: [
{
- Fields: [{ Annotations: null, Name: 'Count', New: '2', Old: '2', Type: 'None' }],
+ Fields: [
+ {
+ Annotations: null,
+ Name: 'Count',
+ New: '2',
+ Old: '2',
+ Type: 'None',
+ },
+ ],
Name: 'cache',
Objects: [
{
diff --git a/ui/stories/components/dropdown.stories.js b/ui/stories/components/dropdown.stories.js
index 528935cd0..57baf059a 100644
--- a/ui/stories/components/dropdown.stories.js
+++ b/ui/stories/components/dropdown.stories.js
@@ -77,7 +77,7 @@ export let Search = () => {
'Thirteen',
'Fourteen',
'Fifteen',
- ].map(name => ({ name })),
+ ].map((name) => ({ name })),
},
};
};
diff --git a/ui/stories/components/json-viewer.stories.js b/ui/stories/components/json-viewer.stories.js
index 236bd1da8..5c313a557 100644
--- a/ui/stories/components/json-viewer.stories.js
+++ b/ui/stories/components/json-viewer.stories.js
@@ -21,7 +21,14 @@ export let Standard = () => {
data: {
foo: 'bar',
number: 123456789,
- products: ['Consul', 'Nomad', 'Packer', 'Terraform', 'Vagrant', 'Vault'],
+ products: [
+ 'Consul',
+ 'Nomad',
+ 'Packer',
+ 'Terraform',
+ 'Vagrant',
+ 'Vault',
+ ],
currentTime: '2019-10-16T14:24:12.378Z',
nested: {
obj: 'ject',
diff --git a/ui/stories/components/table.stories.js b/ui/stories/components/table.stories.js
index 309beab3f..0cce0359c 100644
--- a/ui/stories/components/table.stories.js
+++ b/ui/stories/components/table.stories.js
@@ -20,15 +20,16 @@ export default {
* as the `controller` property so its query parameters are accessible from the template.
*/
function injectRoutedController(controllerClass) {
- return on('init', function() {
+ return on('init', function () {
let container = getOwner(this);
container.register('controller:storybook', controllerClass);
let routerFactory = container.factoryFor('router:main');
- routerFactory.class.map(function() {
+ routerFactory.class.map(function () {
this.route('storybook');
});
+ /* eslint-disable-next-line ember/no-private-routing-service */
let router = container.lookup('router:main');
router.initialURL = 'storybook';
router.startRouting(true);
@@ -38,10 +39,34 @@ function injectRoutedController(controllerClass) {
}
let longList = [
- { city: 'New York', growth: 0.048, population: '8405837', rank: '1', state: 'New York' },
- { city: 'Los Angeles', growth: 0.048, population: '3884307', rank: '2', state: 'California' },
- { city: 'Chicago', growth: -0.061, population: '2718782', rank: '3', state: 'Illinois' },
- { city: 'Houston', growth: 0.11, population: '2195914', rank: '4', state: 'Texas' },
+ {
+ city: 'New York',
+ growth: 0.048,
+ population: '8405837',
+ rank: '1',
+ state: 'New York',
+ },
+ {
+ city: 'Los Angeles',
+ growth: 0.048,
+ population: '3884307',
+ rank: '2',
+ state: 'California',
+ },
+ {
+ city: 'Chicago',
+ growth: -0.061,
+ population: '2718782',
+ rank: '3',
+ state: 'Illinois',
+ },
+ {
+ city: 'Houston',
+ growth: 0.11,
+ population: '2195914',
+ rank: '4',
+ state: 'Texas',
+ },
{
city: 'Philadelphia',
growth: 0.026,
@@ -49,14 +74,62 @@ let longList = [
rank: '5',
state: 'Pennsylvania',
},
- { city: 'Phoenix', growth: 0.14, population: '1513367', rank: '6', state: 'Arizona' },
- { city: 'San Antonio', growth: 0.21, population: '1409019', rank: '7', state: 'Texas' },
- { city: 'San Diego', growth: 0.105, population: '1355896', rank: '8', state: 'California' },
- { city: 'Dallas', growth: 0.056, population: '1257676', rank: '9', state: 'Texas' },
- { city: 'San Jose', growth: 0.105, population: '998537', rank: '10', state: 'California' },
- { city: 'Austin', growth: 0.317, population: '885400', rank: '11', state: 'Texas' },
- { city: 'Indianapolis', growth: 0.078, population: '843393', rank: '12', state: 'Indiana' },
- { city: 'Jacksonville', growth: 0.143, population: '842583', rank: '13', state: 'Florida' },
+ {
+ city: 'Phoenix',
+ growth: 0.14,
+ population: '1513367',
+ rank: '6',
+ state: 'Arizona',
+ },
+ {
+ city: 'San Antonio',
+ growth: 0.21,
+ population: '1409019',
+ rank: '7',
+ state: 'Texas',
+ },
+ {
+ city: 'San Diego',
+ growth: 0.105,
+ population: '1355896',
+ rank: '8',
+ state: 'California',
+ },
+ {
+ city: 'Dallas',
+ growth: 0.056,
+ population: '1257676',
+ rank: '9',
+ state: 'Texas',
+ },
+ {
+ city: 'San Jose',
+ growth: 0.105,
+ population: '998537',
+ rank: '10',
+ state: 'California',
+ },
+ {
+ city: 'Austin',
+ growth: 0.317,
+ population: '885400',
+ rank: '11',
+ state: 'Texas',
+ },
+ {
+ city: 'Indianapolis',
+ growth: 0.078,
+ population: '843393',
+ rank: '12',
+ state: 'Indiana',
+ },
+ {
+ city: 'Jacksonville',
+ growth: 0.143,
+ population: '842583',
+ rank: '13',
+ state: 'Florida',
+ },
{
city: 'San Francisco',
growth: 0.077,
@@ -64,7 +137,13 @@ let longList = [
rank: '14',
state: 'California',
},
- { city: 'Columbus', growth: 0.148, population: '822553', rank: '15', state: 'Ohio' },
+ {
+ city: 'Columbus',
+ growth: 0.148,
+ population: '822553',
+ rank: '15',
+ state: 'Ohio',
+ },
{
city: 'Charlotte',
growth: 0.391,
@@ -72,12 +151,48 @@ let longList = [
rank: '16',
state: 'North Carolina',
},
- { city: 'Fort Worth', growth: 0.451, population: '792727', rank: '17', state: 'Texas' },
- { city: 'Detroit', growth: -0.271, population: '688701', rank: '18', state: 'Michigan' },
- { city: 'El Paso', growth: 0.194, population: '674433', rank: '19', state: 'Texas' },
- { city: 'Memphis', growth: -0.053, population: '653450', rank: '20', state: 'Tennessee' },
- { city: 'Seattle', growth: 0.156, population: '652405', rank: '21', state: 'Washington' },
- { city: 'Denver', growth: 0.167, population: '649495', rank: '22', state: 'Colorado' },
+ {
+ city: 'Fort Worth',
+ growth: 0.451,
+ population: '792727',
+ rank: '17',
+ state: 'Texas',
+ },
+ {
+ city: 'Detroit',
+ growth: -0.271,
+ population: '688701',
+ rank: '18',
+ state: 'Michigan',
+ },
+ {
+ city: 'El Paso',
+ growth: 0.194,
+ population: '674433',
+ rank: '19',
+ state: 'Texas',
+ },
+ {
+ city: 'Memphis',
+ growth: -0.053,
+ population: '653450',
+ rank: '20',
+ state: 'Tennessee',
+ },
+ {
+ city: 'Seattle',
+ growth: 0.156,
+ population: '652405',
+ rank: '21',
+ state: 'Washington',
+ },
+ {
+ city: 'Denver',
+ growth: 0.167,
+ population: '649495',
+ rank: '22',
+ state: 'Colorado',
+ },
{
city: 'Washington',
growth: 0.13,
@@ -85,7 +200,13 @@ let longList = [
rank: '23',
state: 'District of Columbia',
},
- { city: 'Boston', growth: 0.094, population: '645966', rank: '24', state: 'Massachusetts' },
+ {
+ city: 'Boston',
+ growth: 0.094,
+ population: '645966',
+ rank: '24',
+ state: 'Massachusetts',
+ },
{
city: 'Nashville-Davidson',
growth: 0.162,
@@ -93,8 +214,20 @@ let longList = [
rank: '25',
state: 'Tennessee',
},
- { city: 'Baltimore', growth: -0.04, population: '622104', rank: '26', state: 'Maryland' },
- { city: 'Oklahoma City', growth: 0.202, population: '610613', rank: '27', state: 'Oklahoma' },
+ {
+ city: 'Baltimore',
+ growth: -0.04,
+ population: '622104',
+ rank: '26',
+ state: 'Maryland',
+ },
+ {
+ city: 'Oklahoma City',
+ growth: 0.202,
+ population: '610613',
+ rank: '27',
+ state: 'Oklahoma',
+ },
{
city: 'Louisville/Jefferson County',
growth: 0.1,
@@ -102,18 +235,90 @@ let longList = [
rank: '28',
state: 'Kentucky',
},
- { city: 'Portland', growth: 0.15, population: '609456', rank: '29', state: 'Oregon' },
- { city: 'Las Vegas', growth: 0.245, population: '603488', rank: '30', state: 'Nevada' },
- { city: 'Milwaukee', growth: 0.003, population: '599164', rank: '31', state: 'Wisconsin' },
- { city: 'Albuquerque', growth: 0.235, population: '556495', rank: '32', state: 'New Mexico' },
- { city: 'Tucson', growth: 0.075, population: '526116', rank: '33', state: 'Arizona' },
- { city: 'Fresno', growth: 0.183, population: '509924', rank: '34', state: 'California' },
- { city: 'Sacramento', growth: 0.172, population: '479686', rank: '35', state: 'California' },
- { city: 'Long Beach', growth: 0.015, population: '469428', rank: '36', state: 'California' },
- { city: 'Kansas City', growth: 0.055, population: '467007', rank: '37', state: 'Missouri' },
- { city: 'Mesa', growth: 0.135, population: '457587', rank: '38', state: 'Arizona' },
- { city: 'Virginia Beach', growth: 0.051, population: '448479', rank: '39', state: 'Virginia' },
- { city: 'Atlanta', growth: 0.062, population: '447841', rank: '40', state: 'Georgia' },
+ {
+ city: 'Portland',
+ growth: 0.15,
+ population: '609456',
+ rank: '29',
+ state: 'Oregon',
+ },
+ {
+ city: 'Las Vegas',
+ growth: 0.245,
+ population: '603488',
+ rank: '30',
+ state: 'Nevada',
+ },
+ {
+ city: 'Milwaukee',
+ growth: 0.003,
+ population: '599164',
+ rank: '31',
+ state: 'Wisconsin',
+ },
+ {
+ city: 'Albuquerque',
+ growth: 0.235,
+ population: '556495',
+ rank: '32',
+ state: 'New Mexico',
+ },
+ {
+ city: 'Tucson',
+ growth: 0.075,
+ population: '526116',
+ rank: '33',
+ state: 'Arizona',
+ },
+ {
+ city: 'Fresno',
+ growth: 0.183,
+ population: '509924',
+ rank: '34',
+ state: 'California',
+ },
+ {
+ city: 'Sacramento',
+ growth: 0.172,
+ population: '479686',
+ rank: '35',
+ state: 'California',
+ },
+ {
+ city: 'Long Beach',
+ growth: 0.015,
+ population: '469428',
+ rank: '36',
+ state: 'California',
+ },
+ {
+ city: 'Kansas City',
+ growth: 0.055,
+ population: '467007',
+ rank: '37',
+ state: 'Missouri',
+ },
+ {
+ city: 'Mesa',
+ growth: 0.135,
+ population: '457587',
+ rank: '38',
+ state: 'Arizona',
+ },
+ {
+ city: 'Virginia Beach',
+ growth: 0.051,
+ population: '448479',
+ rank: '39',
+ state: 'Virginia',
+ },
+ {
+ city: 'Atlanta',
+ growth: 0.062,
+ population: '447841',
+ rank: '40',
+ state: 'Georgia',
+ },
{
city: 'Colorado Springs',
growth: 0.214,
@@ -121,15 +326,69 @@ let longList = [
rank: '41',
state: 'Colorado',
},
- { city: 'Omaha', growth: 0.059, population: '434353', rank: '42', state: 'Nebraska' },
- { city: 'Raleigh', growth: 0.487, population: '431746', rank: '43', state: 'North Carolina' },
- { city: 'Miami', growth: 0.149, population: '417650', rank: '44', state: 'Florida' },
- { city: 'Oakland', growth: 0.013, population: '406253', rank: '45', state: 'California' },
- { city: 'Minneapolis', growth: 0.045, population: '400070', rank: '46', state: 'Minnesota' },
- { city: 'Tulsa', growth: 0.013, population: '398121', rank: '47', state: 'Oklahoma' },
- { city: 'Cleveland', growth: -0.181, population: '390113', rank: '48', state: 'Ohio' },
- { city: 'Wichita', growth: 0.097, population: '386552', rank: '49', state: 'Kansas' },
- { city: 'Arlington', growth: 0.133, population: '379577', rank: '50', state: 'Texas' },
+ {
+ city: 'Omaha',
+ growth: 0.059,
+ population: '434353',
+ rank: '42',
+ state: 'Nebraska',
+ },
+ {
+ city: 'Raleigh',
+ growth: 0.487,
+ population: '431746',
+ rank: '43',
+ state: 'North Carolina',
+ },
+ {
+ city: 'Miami',
+ growth: 0.149,
+ population: '417650',
+ rank: '44',
+ state: 'Florida',
+ },
+ {
+ city: 'Oakland',
+ growth: 0.013,
+ population: '406253',
+ rank: '45',
+ state: 'California',
+ },
+ {
+ city: 'Minneapolis',
+ growth: 0.045,
+ population: '400070',
+ rank: '46',
+ state: 'Minnesota',
+ },
+ {
+ city: 'Tulsa',
+ growth: 0.013,
+ population: '398121',
+ rank: '47',
+ state: 'Oklahoma',
+ },
+ {
+ city: 'Cleveland',
+ growth: -0.181,
+ population: '390113',
+ rank: '48',
+ state: 'Ohio',
+ },
+ {
+ city: 'Wichita',
+ growth: 0.097,
+ population: '386552',
+ rank: '49',
+ state: 'Kansas',
+ },
+ {
+ city: 'Arlington',
+ growth: 0.133,
+ population: '379577',
+ rank: '50',
+ state: 'Texas',
+ },
];
export let Standard = () => {
@@ -201,9 +460,11 @@ export let Search = () => {
controller: EmberObject.extend({
searchTerm: '',
- filteredShortList: computed('searchTerm', function() {
+ filteredShortList: computed('searchTerm', function () {
let term = this.searchTerm.toLowerCase();
- return productMetadata.filter(product => product.name.toLowerCase().includes(term));
+ return productMetadata.filter((product) =>
+ product.name.toLowerCase().includes(term)
+ );
}),
}).create(),
},
@@ -240,10 +501,17 @@ export let SortableColumns = () => {
})
),
- sortedShortList: computed('controller.{sortProperty,sortDescending}', function() {
- let sorted = productMetadata.sortBy(this.get('controller.sortProperty') || 'name');
- return this.get('controller.sortDescending') ? sorted.reverse() : sorted;
- }),
+ sortedShortList: computed(
+ 'controller.{sortProperty,sortDescending}',
+ function () {
+ let sorted = productMetadata.sortBy(
+ this.get('controller.sortProperty') || 'name'
+ );
+ return this.get('controller.sortDescending')
+ ? sorted.reverse()
+ : sorted;
+ }
+ ),
},
};
};
@@ -278,10 +546,17 @@ export let MultiRow = () => {
})
),
- sortedShortList: computed('controller.{sortProperty,sortDescending}', function() {
- let sorted = productMetadata.sortBy(this.get('controller.sortProperty') || 'name');
- return this.get('controller.sortDescending') ? sorted.reverse() : sorted;
- }),
+ sortedShortList: computed(
+ 'controller.{sortProperty,sortDescending}',
+ function () {
+ let sorted = productMetadata.sortBy(
+ this.get('controller.sortProperty') || 'name'
+ );
+ return this.get('controller.sortDescending')
+ ? sorted.reverse()
+ : sorted;
+ }
+ ),
},
};
};
diff --git a/ui/stories/theme/colors.stories.js b/ui/stories/theme/colors.stories.js
index b849613a1..da59a6c52 100644
--- a/ui/stories/theme/colors.stories.js
+++ b/ui/stories/theme/colors.stories.js
@@ -129,8 +129,8 @@ export let Colors = () => {
},
],
},
- ].map(palette => {
- palette.colors.forEach(color => {
+ ].map((palette) => {
+ palette.colors.forEach((color) => {
color.style = htmlSafe(`background-color: ${color.base}`);
});
return palette;
diff --git a/ui/stories/theme/font-stacks.stories.js b/ui/stories/theme/font-stacks.stories.js
index f91002571..35394d756 100644
--- a/ui/stories/theme/font-stacks.stories.js
+++ b/ui/stories/theme/font-stacks.stories.js
@@ -33,7 +33,7 @@ export let FontStacks = () => {
'Helvetica Neue',
'sans-serif',
'monospace',
- ].map(family => {
+ ].map((family) => {
return {
name: family,
style: htmlSafe(`font-family: ${family}`),
diff --git a/ui/testem.js b/ui/testem.js
index f15024e93..f0d81dfdf 100644
--- a/ui/testem.js
+++ b/ui/testem.js
@@ -25,20 +25,27 @@ const config = {
'--disable-software-rasterizer',
'--mute-audio',
'--remote-debugging-port=0',
- '--window-size=1440,900'
- ].filter(Boolean)
- }
- }
+ '--window-size=1440,900',
+ ].filter(Boolean),
+ },
+ },
};
if (process.env.CI) {
- const reporters = [{
- ReporterClass: TapReporter,
- args: [false, null, { get: () => false }]
- }, {
- ReporterClass: XunitReporter,
- args: [false, fs.createWriteStream('/tmp/test-reports/ui.xml'), { get: () => false }]
- }];
+ const reporters = [
+ {
+ ReporterClass: TapReporter,
+ args: [false, null, { get: () => false }],
+ },
+ {
+ ReporterClass: XunitReporter,
+ args: [
+ false,
+ fs.createWriteStream('/tmp/test-reports/ui.xml'),
+ { get: () => false },
+ ],
+ },
+ ];
const multiReporter = new MultiReporter({ reporters });
diff --git a/ui/tests/.eslintrc.js b/ui/tests/.eslintrc.js
index 66934a875..057b1bcb3 100644
--- a/ui/tests/.eslintrc.js
+++ b/ui/tests/.eslintrc.js
@@ -10,6 +10,7 @@ module.exports = {
env: {
embertest: true,
},
+ extends: ['plugin:qunit/recommended'],
overrides: [
{
files: ['acceptance/**/*-test.js'],
diff --git a/ui/tests/acceptance/allocation-detail-test.js b/ui/tests/acceptance/allocation-detail-test.js
index d1fd9defe..00861d08a 100644
--- a/ui/tests/acceptance/allocation-detail-test.js
+++ b/ui/tests/acceptance/allocation-detail-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* Mirage fixtures are random so we can't expect a set number of assertions */
import { run } from '@ember/runloop';
import { currentURL } from '@ember/test-helpers';
import { assign } from '@ember/polyfills';
@@ -14,11 +16,11 @@ let job;
let node;
let allocation;
-module('Acceptance | allocation detail', function(hooks) {
+module('Acceptance | allocation detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
node = server.create('node');
@@ -51,13 +53,20 @@ module('Acceptance | allocation detail', function(hooks) {
await Allocation.visit({ id: allocation.id });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await a11yAudit(assert);
});
- test('/allocation/:id should name the allocation and link to the corresponding job and node', async function(assert) {
- assert.ok(Allocation.title.includes(allocation.name), 'Allocation name is in the heading');
- assert.equal(Allocation.details.job, job.name, 'Job name is in the subheading');
+ test('/allocation/:id should name the allocation and link to the corresponding job and node', async function (assert) {
+ assert.ok(
+ Allocation.title.includes(allocation.name),
+ 'Allocation name is in the heading'
+ );
+ assert.equal(
+ Allocation.details.job,
+ job.name,
+ 'Job name is in the subheading'
+ );
assert.equal(
Allocation.details.client,
node.id.split('-')[0],
@@ -68,21 +77,41 @@ module('Acceptance | allocation detail', function(hooks) {
assert.equal(document.title, `Allocation ${allocation.name} - Nomad`);
await Allocation.details.visitJob();
- assert.equal(currentURL(), `/jobs/${job.id}`, 'Job link navigates to the job');
+ assert.equal(
+ currentURL(),
+ `/jobs/${job.id}`,
+ 'Job link navigates to the job'
+ );
await Allocation.visit({ id: allocation.id });
await Allocation.details.visitClient();
- assert.equal(currentURL(), `/clients/${node.id}`, 'Client link navigates to the client');
+ assert.equal(
+ currentURL(),
+ `/clients/${node.id}`,
+ 'Client link navigates to the client'
+ );
});
- test('/allocation/:id should include resource utilization graphs', async function(assert) {
- assert.equal(Allocation.resourceCharts.length, 2, 'Two resource utilization graphs');
- assert.equal(Allocation.resourceCharts.objectAt(0).name, 'CPU', 'First chart is CPU');
- assert.equal(Allocation.resourceCharts.objectAt(1).name, 'Memory', 'Second chart is Memory');
+ test('/allocation/:id should include resource utilization graphs', async function (assert) {
+ assert.equal(
+ Allocation.resourceCharts.length,
+ 2,
+ 'Two resource utilization graphs'
+ );
+ assert.equal(
+ Allocation.resourceCharts.objectAt(0).name,
+ 'CPU',
+ 'First chart is CPU'
+ );
+ assert.equal(
+ Allocation.resourceCharts.objectAt(1).name,
+ 'Memory',
+ 'Second chart is Memory'
+ );
});
- test('/allocation/:id should present task lifecycles', async function(assert) {
+ test('/allocation/:id should present task lifecycles', async function (assert) {
const job = server.create('job', {
groupsCount: 1,
groupTaskCount: 6,
@@ -107,15 +136,22 @@ module('Acceptance | allocation detail', function(hooks) {
const prestartEphemeralTask = server.db.taskStates
.where({ allocationId: allocation.id })
.sortBy('name')
- .find(taskState => {
+ .find((taskState) => {
const task = server.db.tasks.findBy({ name: taskState.name });
- return task.Lifecycle && task.Lifecycle.Hook === 'prestart' && !task.Lifecycle.Sidecar;
+ return (
+ task.Lifecycle &&
+ task.Lifecycle.Hook === 'prestart' &&
+ !task.Lifecycle.Sidecar
+ );
});
- assert.equal(currentURL(), `/allocations/${allocation.id}/${prestartEphemeralTask.name}`);
+ assert.equal(
+ currentURL(),
+ `/allocations/${allocation.id}/${prestartEphemeralTask.name}`
+ );
});
- test('/allocation/:id should list all tasks for the allocation', async function(assert) {
+ test('/allocation/:id should list all tasks for the allocation', async function (assert) {
assert.equal(
Allocation.tasks.length,
server.db.taskStates.where({ allocationId: allocation.id }).length,
@@ -124,8 +160,10 @@ module('Acceptance | allocation detail', function(hooks) {
assert.notOk(Allocation.isEmpty, 'Task table empty state is not shown');
});
- test('each task row should list high-level information for the task', async function(assert) {
- const task = server.db.taskStates.where({ allocationId: allocation.id }).sortBy('name')[0];
+ test('each task row should list high-level information for the task', async function (assert) {
+ const task = server.db.taskStates
+ .where({ allocationId: allocation.id })
+ .sortBy('name')[0];
const events = server.db.taskEvents.where({ taskStateId: task.id });
const event = events[events.length - 1];
@@ -134,13 +172,13 @@ module('Acceptance | allocation detail', function(hooks) {
name: allocation.taskGroup,
}).models[0];
- const jobTask = taskGroup.tasks.models.find(m => m.name === task.name);
- const volumes = jobTask.volumeMounts.map(volume => ({
+ const jobTask = taskGroup.tasks.models.find((m) => m.name === task.name);
+ const volumes = jobTask.volumeMounts.map((volume) => ({
name: volume.Volume,
source: taskGroup.volumes[volume.Volume].Source,
}));
- Allocation.tasks[0].as(taskRow => {
+ Allocation.tasks[0].as((taskRow) => {
assert.equal(taskRow.name, task.name, 'Name');
assert.equal(taskRow.state, task.state, 'State');
assert.equal(taskRow.message, event.displayMessage, 'Event Message');
@@ -151,18 +189,27 @@ module('Acceptance | allocation detail', function(hooks) {
);
const volumesText = taskRow.volumes;
- volumes.forEach(volume => {
- assert.ok(volumesText.includes(volume.name), `Found label ${volume.name}`);
- assert.ok(volumesText.includes(volume.source), `Found value ${volume.source}`);
+ volumes.forEach((volume) => {
+ assert.ok(
+ volumesText.includes(volume.name),
+ `Found label ${volume.name}`
+ );
+ assert.ok(
+ volumesText.includes(volume.source),
+ `Found value ${volume.source}`
+ );
});
});
});
- test('each task row should link to the task detail page', async function(assert) {
- const task = server.db.taskStates.where({ allocationId: allocation.id }).sortBy('name')[0];
+ test('each task row should link to the task detail page', async function (assert) {
+ const task = server.db.taskStates
+ .where({ allocationId: allocation.id })
+ .sortBy('name')[0];
await Allocation.tasks.objectAt(0).clickLink();
+ // Make sure the allocation is pending in order to ensure there are no tasks
assert.equal(
currentURL(),
`/allocations/${allocation.id}/${task.name}`,
@@ -179,7 +226,7 @@ module('Acceptance | allocation detail', function(hooks) {
);
});
- test('tasks with an unhealthy driver have a warning icon', async function(assert) {
+ test('tasks with an unhealthy driver have a warning icon', async function (assert) {
// Driver health status require node:read permission.
const policy = server.create('policy', {
id: 'node-read',
@@ -200,10 +247,13 @@ module('Acceptance | allocation detail', function(hooks) {
await Tokens.secret(clientToken.secretId).submit();
await Allocation.visit({ id: allocation.id });
- assert.ok(Allocation.firstUnhealthyTask().hasUnhealthyDriver, 'Warning is shown');
+ assert.ok(
+ Allocation.firstUnhealthyTask().hasUnhealthyDriver,
+ 'Warning is shown'
+ );
});
- test('proxy task has a proxy tag', async function(assert) {
+ test('proxy task has a proxy tag', async function (assert) {
// Must create a new job as existing one has loaded and it contains the tasks
job = server.create('job', {
groupsCount: 1,
@@ -226,19 +276,24 @@ module('Acceptance | allocation detail', function(hooks) {
assert.ok(Allocation.tasks[0].hasProxyTag);
});
- test('when there are no tasks, an empty state is shown', async function(assert) {
+ test('when there are no tasks, an empty state is shown', async function (assert) {
// Make sure the allocation is pending in order to ensure there are no tasks
- allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'pending' });
+ allocation = server.create('allocation', 'withTaskWithPorts', {
+ clientStatus: 'pending',
+ });
await Allocation.visit({ id: allocation.id });
assert.ok(Allocation.isEmpty, 'Task table empty state is shown');
});
- test('when the allocation has not been rescheduled, the reschedule events section is not rendered', async function(assert) {
- assert.notOk(Allocation.hasRescheduleEvents, 'Reschedule Events section exists');
+ test('when the allocation has not been rescheduled, the reschedule events section is not rendered', async function (assert) {
+ assert.notOk(
+ Allocation.hasRescheduleEvents,
+ 'Reschedule Events section exists'
+ );
});
- test('ports are listed', async function(assert) {
+ test('ports are listed', async function (assert) {
const allServerPorts = allocation.taskResources.models[0].resources.Ports;
allServerPorts.sortBy('Label').forEach((serverPort, index) => {
@@ -246,12 +301,17 @@ module('Acceptance | allocation detail', function(hooks) {
assert.equal(renderedPort.name, serverPort.Label);
assert.equal(renderedPort.to, serverPort.To);
- assert.equal(renderedPort.address, formatHost(serverPort.HostIP, serverPort.Value));
+ assert.equal(
+ renderedPort.address,
+ formatHost(serverPort.HostIP, serverPort.Value)
+ );
});
});
- test('services are listed', async function(assert) {
- const taskGroup = server.schema.taskGroups.findBy({ name: allocation.taskGroup });
+ test('services are listed', async function (assert) {
+ const taskGroup = server.schema.taskGroups.findBy({
+ name: allocation.taskGroup,
+ });
assert.equal(Allocation.services.length, taskGroup.services.length);
@@ -263,46 +323,59 @@ module('Acceptance | allocation detail', function(hooks) {
assert.equal(renderedService.onUpdate, serverService.onUpdate);
assert.equal(renderedService.tags, (serverService.tags || []).join(', '));
- assert.equal(renderedService.connect, serverService.Connect ? 'Yes' : 'No');
+ assert.equal(
+ renderedService.connect,
+ serverService.Connect ? 'Yes' : 'No'
+ );
const upstreams = serverService.Connect.SidecarService.Proxy.Upstreams;
const serverUpstreamsString = upstreams
- .map(upstream => `${upstream.DestinationName}:${upstream.LocalBindPort}`)
+ .map(
+ (upstream) => `${upstream.DestinationName}:${upstream.LocalBindPort}`
+ )
.join(' ');
assert.equal(renderedService.upstreams, serverUpstreamsString);
});
});
- test('when the allocation is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the allocation is not found, an error message is shown, but the URL persists', async function (assert) {
await Allocation.visit({ id: 'not-a-real-allocation' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/allocation/not-a-real-allocation',
'A request to the nonexistent allocation is made'
);
- assert.equal(currentURL(), '/allocations/not-a-real-allocation', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/allocations/not-a-real-allocation',
+ 'The URL persists'
+ );
assert.ok(Allocation.error.isShown, 'Error message is shown');
- assert.equal(Allocation.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ Allocation.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
- test('allocation can be stopped', async function(assert) {
+ test('allocation can be stopped', async function (assert) {
await Allocation.stop.idle();
await Allocation.stop.confirm();
assert.equal(
server.pretender.handledRequests
- .reject(request => request.url.includes('fuzzy'))
+ .reject((request) => request.url.includes('fuzzy'))
.findBy('method', 'POST').url,
`/v1/allocation/${allocation.id}/stop`,
'Stop request is made for the allocation'
);
});
- test('allocation can be restarted', async function(assert) {
+ test('allocation can be restarted', async function (assert) {
await Allocation.restart.idle();
await Allocation.restart.confirm();
@@ -313,7 +386,7 @@ module('Acceptance | allocation detail', function(hooks) {
);
});
- test('while an allocation is being restarted, the stop button is disabled', async function(assert) {
+ test('while an allocation is being restarted, the stop button is disabled', async function (assert) {
server.pretender.post('/v1/allocation/:id/stop', () => [204, {}, ''], true);
await Allocation.stop.idle();
@@ -327,7 +400,7 @@ module('Acceptance | allocation detail', function(hooks) {
await Allocation.stop.confirm();
});
- test('if stopping or restarting fails, an error message is shown', async function(assert) {
+ test('if stopping or restarting fails, an error message is shown', async function (assert) {
server.pretender.post('/v1/allocation/:id/stop', () => [403, {}, '']);
await Allocation.stop.idle();
@@ -345,15 +418,18 @@ module('Acceptance | allocation detail', function(hooks) {
await Allocation.inlineError.dismiss();
- assert.notOk(Allocation.inlineError.isShown, 'Inline error is no longer shown');
+ assert.notOk(
+ Allocation.inlineError.isShown,
+ 'Inline error is no longer shown'
+ );
});
});
-module('Acceptance | allocation detail (rescheduled)', function(hooks) {
+module('Acceptance | allocation detail (rescheduled)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
node = server.create('node');
@@ -363,16 +439,19 @@ module('Acceptance | allocation detail (rescheduled)', function(hooks) {
await Allocation.visit({ id: allocation.id });
});
- test('when the allocation has been rescheduled, the reschedule events section is rendered', async function(assert) {
- assert.ok(Allocation.hasRescheduleEvents, 'Reschedule Events section exists');
+ test('when the allocation has been rescheduled, the reschedule events section is rendered', async function (assert) {
+ assert.ok(
+ Allocation.hasRescheduleEvents,
+ 'Reschedule Events section exists'
+ );
});
});
-module('Acceptance | allocation detail (not running)', function(hooks) {
+module('Acceptance | allocation detail (not running)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
node = server.create('node');
@@ -382,7 +461,7 @@ module('Acceptance | allocation detail (not running)', function(hooks) {
await Allocation.visit({ id: allocation.id });
});
- test('when the allocation is not running, the utilization graphs are replaced by an empty message', async function(assert) {
+ test('when the allocation is not running, the utilization graphs are replaced by an empty message', async function (assert) {
assert.equal(Allocation.resourceCharts.length, 0, 'No resource charts');
assert.equal(
Allocation.resourceEmptyMessage,
@@ -391,34 +470,45 @@ module('Acceptance | allocation detail (not running)', function(hooks) {
);
});
- test('the exec and stop/restart buttons are absent', async function(assert) {
+ test('the exec and stop/restart buttons are absent', async function (assert) {
assert.notOk(Allocation.execButton.isPresent);
assert.notOk(Allocation.stop.isPresent);
assert.notOk(Allocation.restart.isPresent);
});
});
-module('Acceptance | allocation detail (preemptions)', function(hooks) {
+module('Acceptance | allocation detail (preemptions)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
node = server.create('node');
job = server.create('job', { createAllocations: false });
window.localStorage.clear();
});
- test('shows a dedicated section to the allocation that preempted this allocation', async function(assert) {
+ test('shows a dedicated section to the allocation that preempted this allocation', async function (assert) {
allocation = server.create('allocation', 'preempted');
- const preempter = server.schema.find('allocation', allocation.preemptedByAllocation);
+ const preempter = server.schema.find(
+ 'allocation',
+ allocation.preemptedByAllocation
+ );
const preempterJob = server.schema.find('job', preempter.jobId);
const preempterClient = server.schema.find('node', preempter.nodeId);
await Allocation.visit({ id: allocation.id });
assert.ok(Allocation.wasPreempted, 'Preempted allocation section is shown');
- assert.equal(Allocation.preempter.status, preempter.clientStatus, 'Preempter status matches');
- assert.equal(Allocation.preempter.name, preempter.name, 'Preempter name matches');
+ assert.equal(
+ Allocation.preempter.status,
+ preempter.clientStatus,
+ 'Preempter status matches'
+ );
+ assert.equal(
+ Allocation.preempter.name,
+ preempter.name,
+ 'Preempter name matches'
+ );
assert.equal(
Allocation.preempter.priority,
preempterJob.priority,
@@ -449,18 +539,21 @@ module('Acceptance | allocation detail (preemptions)', function(hooks) {
);
});
- test('shows a dedicated section to the allocations this allocation preempted', async function(assert) {
+ test('shows a dedicated section to the allocations this allocation preempted', async function (assert) {
allocation = server.create('allocation', 'preempter');
await Allocation.visit({ id: allocation.id });
- assert.ok(Allocation.preempted, 'The allocations this allocation preempted are shown');
+ assert.ok(
+ Allocation.preempted,
+ 'The allocations this allocation preempted are shown'
+ );
});
- test('each preempted allocation in the table lists basic allocation information', async function(assert) {
+ test('each preempted allocation in the table lists basic allocation information', async function (assert) {
allocation = server.create('allocation', 'preempter');
await Allocation.visit({ id: allocation.id });
const preemption = allocation.preemptedAllocations
- .map(id => server.schema.find('allocation', id))
+ .map((id) => server.schema.find('allocation', id))
.sortBy('modifyIndex')
.reverse()[0];
const preemptionRow = Allocation.preemptions.objectAt(0);
@@ -471,7 +564,11 @@ module('Acceptance | allocation detail (preemptions)', function(hooks) {
'The preemptions table has a row for each preempted allocation'
);
- assert.equal(preemptionRow.shortId, preemption.id.split('-')[0], 'Preemption short id');
+ assert.equal(
+ preemptionRow.shortId,
+ preemption.id.split('-')[0],
+ 'Preemption short id'
+ );
assert.equal(
preemptionRow.createTime,
moment(preemption.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
@@ -482,8 +579,16 @@ module('Acceptance | allocation detail (preemptions)', function(hooks) {
moment(preemption.modifyTime / 1000000).fromNow(),
'Preemption modify time'
);
- assert.equal(preemptionRow.status, preemption.clientStatus, 'Client status');
- assert.equal(preemptionRow.jobVersion, preemption.jobVersion, 'Job Version');
+ assert.equal(
+ preemptionRow.status,
+ preemption.clientStatus,
+ 'Client status'
+ );
+ assert.equal(
+ preemptionRow.jobVersion,
+ preemption.jobVersion,
+ 'Job Version'
+ );
assert.equal(
preemptionRow.client,
server.db.nodes.find(preemption.nodeId).id.split('-')[0],
@@ -491,7 +596,7 @@ module('Acceptance | allocation detail (preemptions)', function(hooks) {
);
});
- test('clicking the client ID in the preempted allocation row naviates to the client page', async function(assert) {
+ test('clicking the client ID in the preempted allocation row naviates to the client page', async function (assert) {
// Navigating to the client page requires node:read permission.
const policy = server.create('policy', {
id: 'node-read',
@@ -511,19 +616,26 @@ module('Acceptance | allocation detail (preemptions)', function(hooks) {
await Allocation.visit({ id: allocation.id });
const preemption = allocation.preemptedAllocations
- .map(id => server.schema.find('allocation', id))
+ .map((id) => server.schema.find('allocation', id))
.sortBy('modifyIndex')
.reverse()[0];
const preemptionRow = Allocation.preemptions.objectAt(0);
await preemptionRow.visitClient();
- assert.equal(currentURL(), `/clients/${preemption.nodeId}`, 'Node links to node page');
+ assert.equal(
+ currentURL(),
+ `/clients/${preemption.nodeId}`,
+ 'Node links to node page'
+ );
});
- test('when an allocation both preempted allocations and was preempted itself, both preemptions sections are shown', async function(assert) {
+ test('when an allocation both preempted allocations and was preempted itself, both preemptions sections are shown', async function (assert) {
allocation = server.create('allocation', 'preempter', 'preempted');
await Allocation.visit({ id: allocation.id });
- assert.ok(Allocation.preempted, 'The allocations this allocation preempted are shown');
+ assert.ok(
+ Allocation.preempted,
+ 'The allocations this allocation preempted are shown'
+ );
assert.ok(Allocation.wasPreempted, 'Preempted allocation section is shown');
});
});
diff --git a/ui/tests/acceptance/allocation-fs-test.js b/ui/tests/acceptance/allocation-fs-test.js
index 2712a325f..5f88d72ab 100644
--- a/ui/tests/acceptance/allocation-fs-test.js
+++ b/ui/tests/acceptance/allocation-fs-test.js
@@ -9,16 +9,19 @@ import browseFilesystem from './behaviors/fs';
let allocation;
let files;
-module('Acceptance | allocation fs', function(hooks) {
+module('Acceptance | allocation fs', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node', 'forceIPv4');
const job = server.create('job', { createAllocations: false });
- allocation = server.create('allocation', { jobId: job.id, clientStatus: 'running' });
+ allocation = server.create('allocation', {
+ jobId: job.id,
+ clientStatus: 'running',
+ });
this.allocation = allocation;
@@ -27,7 +30,13 @@ module('Acceptance | allocation fs', function(hooks) {
// Nested files
files.push(server.create('allocFile', { isDir: true, name: 'directory' }));
- files.push(server.create('allocFile', { isDir: true, name: 'another', parent: files[0] }));
+ files.push(
+ server.create('allocFile', {
+ isDir: true,
+ name: 'another',
+ parent: files[0],
+ })
+ );
files.push(
server.create('allocFile', 'file', {
name: 'something.txt',
@@ -36,7 +45,9 @@ module('Acceptance | allocation fs', function(hooks) {
})
);
- files.push(server.create('allocFile', { isDir: true, name: 'empty-directory' }));
+ files.push(
+ server.create('allocFile', { isDir: true, name: 'empty-directory' })
+ );
files.push(server.create('allocFile', 'file', { fileType: 'txt' }));
files.push(server.create('allocFile', 'file', { fileType: 'txt' }));
@@ -47,8 +58,10 @@ module('Acceptance | allocation fs', function(hooks) {
browseFilesystem({
visitSegments: ({ allocation }) => ({ id: allocation.id }),
- getExpectedPathBase: ({ allocation }) => `/allocations/${allocation.id}/fs/`,
- getTitleComponent: ({ allocation }) => `Allocation ${allocation.id.split('-')[0]} filesystem`,
+ getExpectedPathBase: ({ allocation }) =>
+ `/allocations/${allocation.id}/fs/`,
+ getTitleComponent: ({ allocation }) =>
+ `Allocation ${allocation.id.split('-')[0]} filesystem`,
getBreadcrumbComponent: ({ allocation }) => allocation.id.split('-')[0],
getFilesystemRoot: () => '',
pageObjectVisitFunctionName: 'visitAllocation',
diff --git a/ui/tests/acceptance/application-errors-test.js b/ui/tests/acceptance/application-errors-test.js
index ab609b615..ecd390be5 100644
--- a/ui/tests/acceptance/application-errors-test.js
+++ b/ui/tests/acceptance/application-errors-test.js
@@ -7,33 +7,38 @@ import ClientsList from 'nomad-ui/tests/pages/clients/list';
import JobsList from 'nomad-ui/tests/pages/jobs/list';
import Job from 'nomad-ui/tests/pages/jobs/detail';
-module('Acceptance | application errors ', function(hooks) {
+module('Acceptance | application errors ', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('agent');
server.create('node');
server.create('job');
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
server.pretender.get('/v1/nodes', () => [500, {}, null]);
await ClientsList.visit();
await a11yAudit(assert);
});
- test('transitioning away from an error page resets the global error', async function(assert) {
+ test('transitioning away from an error page resets the global error', async function (assert) {
server.pretender.get('/v1/nodes', () => [500, {}, null]);
await ClientsList.visit();
assert.ok(ClientsList.error.isPresent, 'Application has errored');
await JobsList.visit();
- assert.notOk(JobsList.error.isPresent, 'Application is no longer in an error state');
+ assert.notOk(
+ JobsList.error.isPresent,
+ 'Application is no longer in an error state'
+ );
});
- test('the 403 error page links to the ACL tokens page', async function(assert) {
+ test('the 403 error page links to the ACL tokens page', async function (assert) {
const job = server.db.jobs[0];
server.pretender.get(`/v1/job/${job.id}`, () => [403, {}, null]);
@@ -51,7 +56,7 @@ module('Acceptance | application errors ', function(hooks) {
);
});
- test('the no leader error state gets its own error message', async function(assert) {
+ test('the no leader error state gets its own error message', async function (assert) {
server.pretender.get('/v1/jobs', () => [500, {}, 'No cluster leader']);
await JobsList.visit();
@@ -64,7 +69,7 @@ module('Acceptance | application errors ', function(hooks) {
);
});
- test('error pages include links to the jobs and clients pages', async function(assert) {
+ test('error pages include links to the jobs and clients pages', async function (assert) {
await visit('/a/non-existent/page');
assert.ok(JobsList.error.isPresent, 'An error is shown');
diff --git a/ui/tests/acceptance/behaviors/fs.js b/ui/tests/acceptance/behaviors/fs.js
index 6a1665075..c6a1f4a57 100644
--- a/ui/tests/acceptance/behaviors/fs.js
+++ b/ui/tests/acceptance/behaviors/fs.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { test } from 'qunit';
import { currentURL, visit } from '@ember/test-helpers';
@@ -13,7 +14,7 @@ import FS from 'nomad-ui/tests/pages/allocations/fs';
const fileSort = (prop, files) => {
let dir = [];
let file = [];
- files.forEach(f => {
+ files.forEach((f) => {
if (f.isDir) {
dir.push(f);
} else {
@@ -33,14 +34,14 @@ export default function browseFilesystem({
getBreadcrumbComponent,
getFilesystemRoot,
}) {
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await FS[pageObjectVisitFunctionName](
visitSegments({ allocation: this.allocation, task: this.task })
);
await a11yAudit(assert);
});
- test('visiting filesystem root', async function(assert) {
+ test('visiting filesystem root', async function (assert) {
await FS[pageObjectVisitFunctionName](
visitSegments({ allocation: this.allocation, task: this.task })
);
@@ -54,10 +55,15 @@ export default function browseFilesystem({
assert.equal(currentURL(), pathBaseWithoutTrailingSlash, 'No redirect');
});
- test('visiting filesystem paths', async function(assert) {
- const paths = ['some-file.log', 'a/deep/path/to/a/file.log', '/', 'Unicode™®'];
+ test('visiting filesystem paths', async function (assert) {
+ const paths = [
+ 'some-file.log',
+ 'a/deep/path/to/a/file.log',
+ '/',
+ 'Unicode™®',
+ ];
- const testPath = async filePath => {
+ const testPath = async (filePath) => {
let pathWithLeadingSlash = filePath;
if (!pathWithLeadingSlash.startsWith('/')) {
@@ -98,13 +104,17 @@ export default function browseFilesystem({
}, Promise.resolve());
});
- test('navigating allocation filesystem', async function(assert) {
+ test('navigating allocation filesystem', async function (assert) {
const objects = { allocation: this.allocation, task: this.task };
- await FS[pageObjectVisitPathFunctionName]({ ...visitSegments(objects), path: '/' });
+ await FS[pageObjectVisitPathFunctionName]({
+ ...visitSegments(objects),
+ path: '/',
+ });
const sortedFiles = fileSort(
'name',
- filesForPath(this.server.schema.allocFiles, getFilesystemRoot(objects)).models
+ filesForPath(this.server.schema.allocFiles, getFilesystemRoot(objects))
+ .models
);
assert.ok(FS.fileViewer.isHidden);
@@ -117,16 +127,26 @@ export default function browseFilesystem({
assert.ok(FS.breadcrumbs[0].isActive);
assert.equal(FS.breadcrumbs[0].text, getBreadcrumbComponent(objects));
- FS.directoryEntries[0].as(directory => {
+ FS.directoryEntries[0].as((directory) => {
const fileRecord = sortedFiles[0];
- assert.equal(directory.name, fileRecord.name, 'directories should come first');
+ assert.equal(
+ directory.name,
+ fileRecord.name,
+ 'directories should come first'
+ );
assert.ok(directory.isDirectory);
assert.equal(directory.size, '', 'directory sizes are hidden');
- assert.equal(directory.lastModified, moment(fileRecord.modTime).fromNow());
- assert.notOk(directory.path.includes('//'), 'paths shouldn’t have redundant separators');
+ assert.equal(
+ directory.lastModified,
+ moment(fileRecord.modTime).fromNow()
+ );
+ assert.notOk(
+ directory.path.includes('//'),
+ 'paths shouldn’t have redundant separators'
+ );
});
- FS.directoryEntries[2].as(file => {
+ FS.directoryEntries[2].as((file) => {
const fileRecord = sortedFiles[2];
assert.equal(file.name, fileRecord.name);
assert.ok(file.isFile);
@@ -139,7 +159,10 @@ export default function browseFilesystem({
assert.equal(FS.directoryEntries.length, 1);
assert.equal(FS.breadcrumbs.length, 2);
- assert.equal(FS.breadcrumbsText, `${getBreadcrumbComponent(objects)} ${this.directory.name}`);
+ assert.equal(
+ FS.breadcrumbsText,
+ `${getBreadcrumbComponent(objects)} ${this.directory.name}`
+ );
assert.notOk(FS.breadcrumbs[0].isActive);
@@ -157,7 +180,9 @@ export default function browseFilesystem({
assert.equal(FS.breadcrumbs.length, 3);
assert.equal(
FS.breadcrumbsText,
- `${getBreadcrumbComponent(objects)} ${this.directory.name} ${this.nestedDirectory.name}`
+ `${getBreadcrumbComponent(objects)} ${this.directory.name} ${
+ this.nestedDirectory.name
+ }`
);
assert.equal(FS.breadcrumbs[2].text, this.nestedDirectory.name);
@@ -171,28 +196,27 @@ export default function browseFilesystem({
);
await FS.breadcrumbs[1].visit();
- assert.equal(FS.breadcrumbsText, `${getBreadcrumbComponent(objects)} ${this.directory.name}`);
+ assert.equal(
+ FS.breadcrumbsText,
+ `${getBreadcrumbComponent(objects)} ${this.directory.name}`
+ );
assert.equal(FS.breadcrumbs.length, 2);
});
- test('sorting allocation filesystem directory', async function(assert) {
+ test('sorting allocation filesystem directory', async function (assert) {
this.server.get('/client/fs/ls/:allocation_id', () => {
return [
{
Name: 'aaa-big-old-file',
IsDir: false,
Size: 19190000,
- ModTime: moment()
- .subtract(1, 'year')
- .format(),
+ ModTime: moment().subtract(1, 'year').format(),
},
{
Name: 'mmm-small-mid-file',
IsDir: false,
Size: 1919,
- ModTime: moment()
- .subtract(6, 'month')
- .format(),
+ ModTime: moment().subtract(6, 'month').format(),
},
{
Name: 'zzz-med-new-file',
@@ -204,17 +228,13 @@ export default function browseFilesystem({
Name: 'aaa-big-old-directory',
IsDir: true,
Size: 19190000,
- ModTime: moment()
- .subtract(1, 'year')
- .format(),
+ ModTime: moment().subtract(1, 'year').format(),
},
{
Name: 'mmm-small-mid-directory',
IsDir: true,
Size: 1919,
- ModTime: moment()
- .subtract(6, 'month')
- .format(),
+ ModTime: moment().subtract(6, 'month').format(),
},
{
Name: 'zzz-med-new-directory',
@@ -303,26 +323,36 @@ export default function browseFilesystem({
);
});
- test('viewing a file', async function(assert) {
+ test('viewing a file', async function (assert) {
const objects = { allocation: this.allocation, task: this.task };
const node = server.db.nodes.find(this.allocation.nodeId);
- server.get(`http://${node.httpAddr}/v1/client/fs/readat/:allocation_id`, function() {
- return new Response(500);
- });
+ server.get(
+ `http://${node.httpAddr}/v1/client/fs/readat/:allocation_id`,
+ function () {
+ return new Response(500);
+ }
+ );
- await FS[pageObjectVisitPathFunctionName]({ ...visitSegments(objects), path: '/' });
+ await FS[pageObjectVisitPathFunctionName]({
+ ...visitSegments(objects),
+ path: '/',
+ });
const sortedFiles = fileSort(
'name',
- filesForPath(this.server.schema.allocFiles, getFilesystemRoot(objects)).models
+ filesForPath(this.server.schema.allocFiles, getFilesystemRoot(objects))
+ .models
);
- const fileRecord = sortedFiles.find(f => !f.isDir);
+ const fileRecord = sortedFiles.find((f) => !f.isDir);
const fileIndex = sortedFiles.indexOf(fileRecord);
await FS.directoryEntries[fileIndex].visit();
- assert.equal(FS.breadcrumbsText, `${getBreadcrumbComponent(objects)} ${fileRecord.name}`);
+ assert.equal(
+ FS.breadcrumbsText,
+ `${getBreadcrumbComponent(objects)} ${fileRecord.name}`
+ );
assert.ok(FS.fileViewer.isPresent);
@@ -343,7 +373,7 @@ export default function browseFilesystem({
);
});
- test('viewing an empty directory', async function(assert) {
+ test('viewing an empty directory', async function (assert) {
await FS[pageObjectVisitPathFunctionName]({
...visitSegments({ allocation: this.allocation, task: this.task }),
path: 'empty-directory',
@@ -352,7 +382,7 @@ export default function browseFilesystem({
assert.ok(FS.isEmptyDirectory);
});
- test('viewing paths that produce stat API errors', async function(assert) {
+ test('viewing paths that produce stat API errors', async function (assert) {
this.server.get('/client/fs/stat/:allocation_id', () => {
return new Response(500, {}, 'no such file or directory');
});
@@ -361,8 +391,16 @@ export default function browseFilesystem({
...visitSegments({ allocation: this.allocation, task: this.task }),
path: '/what-is-this',
});
- assert.notEqual(FS.error.title, 'Not Found', '500 is not interpreted as 404');
- assert.equal(FS.error.title, 'Server Error', '500 is not interpreted as 500');
+ assert.notEqual(
+ FS.error.title,
+ 'Not Found',
+ '500 is not interpreted as 404'
+ );
+ assert.equal(
+ FS.error.title,
+ 'Server Error',
+ '500 is not interpreted as 500'
+ );
await visit('/');
@@ -377,7 +415,7 @@ export default function browseFilesystem({
assert.equal(FS.error.title, 'Error', 'other statuses are passed through');
});
- test('viewing paths that produce ls API errors', async function(assert) {
+ test('viewing paths that produce ls API errors', async function (assert) {
this.server.get('/client/fs/ls/:allocation_id', () => {
return new Response(500, {}, 'no such file or directory');
});
@@ -386,8 +424,16 @@ export default function browseFilesystem({
...visitSegments({ allocation: this.allocation, task: this.task }),
path: this.directory.name,
});
- assert.notEqual(FS.error.title, 'Not Found', '500 is not interpreted as 404');
- assert.equal(FS.error.title, 'Server Error', '500 is not interpreted as 404');
+ assert.notEqual(
+ FS.error.title,
+ 'Not Found',
+ '500 is not interpreted as 404'
+ );
+ assert.equal(
+ FS.error.title,
+ 'Server Error',
+ '500 is not interpreted as 404'
+ );
await visit('/');
diff --git a/ui/tests/acceptance/behaviors/page-size-select.js b/ui/tests/acceptance/behaviors/page-size-select.js
index 35d261449..f20204372 100644
--- a/ui/tests/acceptance/behaviors/page-size-select.js
+++ b/ui/tests/acceptance/behaviors/page-size-select.js
@@ -2,10 +2,15 @@ import { pluralize } from 'ember-inflector';
import { test } from 'qunit';
import { selectChoose } from 'ember-power-select/test-support';
-export default function pageSizeSelect({ resourceName, pageObject, pageObjectList, setup }) {
+export default function pageSizeSelect({
+ resourceName,
+ pageObject,
+ pageObjectList,
+ setup,
+}) {
test(`the number of ${pluralize(
resourceName
- )} is equal to the localStorage user setting for page size`, async function(assert) {
+ )} is equal to the localStorage user setting for page size`, async function (assert) {
const storedPageSize = 10;
window.localStorage.nomadPageSize = storedPageSize;
@@ -15,7 +20,7 @@ export default function pageSizeSelect({ resourceName, pageObject, pageObjectLis
assert.equal(pageObject.pageSizeSelect.selectedOption, storedPageSize);
});
- test('when the page size user setting is unset, the default page size is 25', async function(assert) {
+ test('when the page size user setting is unset, the default page size is 25', async function (assert) {
await setup.call(this);
assert.equal(pageObjectList.length, pageObject.pageSize);
@@ -24,7 +29,7 @@ export default function pageSizeSelect({ resourceName, pageObject, pageObjectLis
test(`changing the page size updates the ${pluralize(
resourceName
- )} list and also updates the user setting in localStorage`, async function(assert) {
+ )} list and also updates the user setting in localStorage`, async function (assert) {
const desiredPageSize = 10;
await setup.call(this);
diff --git a/ui/tests/acceptance/client-detail-test.js b/ui/tests/acceptance/client-detail-test.js
index 2b2049b54..ff7827cef 100644
--- a/ui/tests/acceptance/client-detail-test.js
+++ b/ui/tests/acceptance/client-detail-test.js
@@ -1,3 +1,6 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
+/* Mirage fixtures are random so we can't expect a set number of assertions */
import { currentURL, waitUntil, settled } from '@ember/test-helpers';
import { assign } from '@ember/polyfills';
import { module, test } from 'qunit';
@@ -15,19 +18,19 @@ let node;
let managementToken;
let clientToken;
-const wasPreemptedFilter = allocation => !!allocation.preemptedByAllocation;
+const wasPreemptedFilter = (allocation) => !!allocation.preemptedByAllocation;
function nonSearchPOSTS() {
return server.pretender.handledRequests
- .reject(request => request.url.includes('fuzzy'))
+ .reject((request) => request.url.includes('fuzzy'))
.filterBy('method', 'POST');
}
-module('Acceptance | client detail', function(hooks) {
+module('Acceptance | client detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
server.create('node', 'forceIPv4', { schedulingEligibility: 'eligible' });
@@ -46,17 +49,17 @@ module('Acceptance | client detail', function(hooks) {
// Force all allocations into the running state so now allocation rows are missing
// CPU/Mem runtime metrics
- server.schema.allocations.all().models.forEach(allocation => {
+ server.schema.allocations.all().models.forEach((allocation) => {
allocation.update({ clientStatus: 'running' });
});
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await ClientDetail.visit({ id: node.id });
await a11yAudit(assert);
});
- test('/clients/:id should have a breadcrumb trail linking back to clients', async function(assert) {
+ test('/clients/:id should have a breadcrumb trail linking back to clients', async function (assert) {
await ClientDetail.visit({ id: node.id });
assert.equal(document.title, `Client ${node.name} - Nomad`);
@@ -72,11 +75,18 @@ module('Acceptance | client detail', function(hooks) {
'Second breadcrumb is a titled breadcrumb saying the node short id'
);
await Layout.breadcrumbFor('clients.index').visit();
- assert.equal(currentURL(), '/clients', 'First breadcrumb links back to clients');
+ assert.equal(
+ currentURL(),
+ '/clients',
+ 'First breadcrumb links back to clients'
+ );
});
- test('/clients/:id should list immediate details for the node in the title', async function(assert) {
- node = server.create('node', 'forceIPv4', { schedulingEligibility: 'eligible', drain: false });
+ test('/clients/:id should list immediate details for the node in the title', async function (assert) {
+ node = server.create('node', 'forceIPv4', {
+ schedulingEligibility: 'eligible',
+ drain: false,
+ });
await ClientDetail.visit({ id: node.id });
@@ -89,7 +99,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('/clients/:id should list additional detail for the node below the title', async function(assert) {
+ test('/clients/:id should list additional detail for the node below the title', async function (assert) {
await ClientDetail.visit({ id: node.id });
assert.ok(
@@ -110,16 +120,30 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('/clients/:id should include resource utilization graphs', async function(assert) {
+ test('/clients/:id should include resource utilization graphs', async function (assert) {
await ClientDetail.visit({ id: node.id });
- assert.equal(ClientDetail.resourceCharts.length, 2, 'Two resource utilization graphs');
- assert.equal(ClientDetail.resourceCharts.objectAt(0).name, 'CPU', 'First chart is CPU');
- assert.equal(ClientDetail.resourceCharts.objectAt(1).name, 'Memory', 'Second chart is Memory');
+ assert.equal(
+ ClientDetail.resourceCharts.length,
+ 2,
+ 'Two resource utilization graphs'
+ );
+ assert.equal(
+ ClientDetail.resourceCharts.objectAt(0).name,
+ 'CPU',
+ 'First chart is CPU'
+ );
+ assert.equal(
+ ClientDetail.resourceCharts.objectAt(1).name,
+ 'Memory',
+ 'Second chart is Memory'
+ );
});
- test('/clients/:id should list all allocations on the node', async function(assert) {
- const allocationsCount = server.db.allocations.where({ nodeId: node.id }).length;
+ test('/clients/:id should list all allocations on the node', async function (assert) {
+ const allocationsCount = server.db.allocations.where({
+ nodeId: node.id,
+ }).length;
await ClientDetail.visit({ id: node.id });
@@ -130,16 +154,19 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('/clients/:id should show empty message if there are no allocations on the node', async function(assert) {
+ test('/clients/:id should show empty message if there are no allocations on the node', async function (assert) {
const emptyNode = server.create('node');
await ClientDetail.visit({ id: emptyNode.id });
- assert.true(ClientDetail.emptyAllocations.isVisible, 'Empty message is visible');
+ assert.true(
+ ClientDetail.emptyAllocations.isVisible,
+ 'Empty message is visible'
+ );
assert.equal(ClientDetail.emptyAllocations.headline, 'No Allocations');
});
- test('each allocation should have high-level details for the allocation', async function(assert) {
+ test('each allocation should have high-level details for the allocation', async function (assert) {
const allocation = server.db.allocations
.where({ nodeId: node.id })
.sortBy('modifyIndex')
@@ -151,15 +178,22 @@ module('Acceptance | client detail', function(hooks) {
jobId: allocation.jobId,
});
- const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ const tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
- const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
+ const memoryUsed = tasks.reduce(
+ (sum, task) => sum + task.resources.MemoryMB,
+ 0
+ );
await ClientDetail.visit({ id: node.id });
const allocationRow = ClientDetail.allocations.objectAt(0);
- assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID');
+ assert.equal(
+ allocationRow.shortId,
+ allocation.id.split('-')[0],
+ 'Allocation short ID'
+ );
assert.equal(
allocationRow.createTime,
moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
@@ -170,8 +204,16 @@ module('Acceptance | client detail', function(hooks) {
moment(allocation.modifyTime / 1000000).fromNow(),
'Allocation modify time'
);
- assert.equal(allocationRow.status, allocation.clientStatus, 'Client status');
- assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
+ assert.equal(
+ allocationRow.status,
+ allocation.clientStatus,
+ 'Client status'
+ );
+ assert.equal(
+ allocationRow.job,
+ server.db.jobs.find(allocation.jobId).name,
+ 'Job name'
+ );
assert.ok(allocationRow.taskGroup, 'Task group name');
assert.ok(allocationRow.jobVersion, 'Job Version');
assert.equal(allocationRow.volume, 'Yes', 'Volume');
@@ -180,7 +222,9 @@ module('Acceptance | client detail', function(hooks) {
Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
'CPU %'
);
- const roundedTicks = Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks);
+ const roundedTicks = Math.floor(
+ allocStats.resourceUsage.CpuStats.TotalTicks
+ );
assert.equal(
allocationRow.cpuTooltip,
`${formatHertz(roundedTicks, 'MHz')} / ${formatHertz(cpuUsed, 'MHz')}`,
@@ -201,7 +245,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('each allocation should show job information even if the job is incomplete and already in the store', async function(assert) {
+ test('each allocation should show job information even if the job is incomplete and already in the store', async function (assert) {
// First, visit clients to load the allocations for each visible node.
// Don't load the job belongsTo of the allocation! Leave it unfulfilled.
@@ -224,11 +268,18 @@ module('Acceptance | client detail', function(hooks) {
.sortBy('modifyIndex')
.reverse()[0];
- assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
- assert.ok(allocationRow.taskGroup.includes(allocation.taskGroup), 'Task group name');
+ assert.equal(
+ allocationRow.job,
+ server.db.jobs.find(allocation.jobId).name,
+ 'Job name'
+ );
+ assert.ok(
+ allocationRow.taskGroup.includes(allocation.taskGroup),
+ 'Task group name'
+ );
});
- test('each allocation should link to the allocation detail page', async function(assert) {
+ test('each allocation should link to the allocation detail page', async function (assert) {
const allocation = server.db.allocations
.where({ nodeId: node.id })
.sortBy('modifyIndex')
@@ -244,7 +295,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('each allocation should link to the job the allocation belongs to', async function(assert) {
+ test('each allocation should link to the job the allocation belongs to', async function (assert) {
await ClientDetail.visit({ id: node.id });
const allocation = server.db.allocations.where({ nodeId: node.id })[0];
@@ -259,7 +310,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('the allocation section should show the count of preempted allocations on the client', async function(assert) {
+ test('the allocation section should show the count of preempted allocations on the client', async function (assert) {
const allocations = server.db.allocations.where({ nodeId: node.id });
await ClientDetail.visit({ id: node.id });
@@ -277,7 +328,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('clicking the preemption badge filters the allocations table and sets a query param', async function(assert) {
+ test('clicking the preemption badge filters the allocations table and sets a query param', async function (assert) {
const allocations = server.db.allocations.where({ nodeId: node.id });
await ClientDetail.visit({ id: node.id });
@@ -295,18 +346,26 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('clicking the total allocations badge resets the filter and removes the query param', async function(assert) {
+ test('clicking the total allocations badge resets the filter and removes the query param', async function (assert) {
const allocations = server.db.allocations.where({ nodeId: node.id });
await ClientDetail.visit({ id: node.id });
await ClientDetail.allocationFilter.preemptions();
await ClientDetail.allocationFilter.all();
- assert.equal(ClientDetail.allocations.length, allocations.length, 'All allocations are shown');
- assert.equal(currentURL(), `/clients/${node.id}`, 'Filter is persisted in the URL');
+ assert.equal(
+ ClientDetail.allocations.length,
+ allocations.length,
+ 'All allocations are shown'
+ );
+ assert.equal(
+ currentURL(),
+ `/clients/${node.id}`,
+ 'Filter is persisted in the URL'
+ );
});
- test('navigating directly to the client detail page with the preemption query param set will filter the allocations table', async function(assert) {
+ test('navigating directly to the client detail page with the preemption query param set will filter the allocations table', async function (assert) {
const allocations = server.db.allocations.where({ nodeId: node.id });
await ClientDetail.visit({ id: node.id, preemptions: true });
@@ -318,13 +377,13 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('/clients/:id should list all attributes for the node', async function(assert) {
+ test('/clients/:id should list all attributes for the node', async function (assert) {
await ClientDetail.visit({ id: node.id });
assert.ok(ClientDetail.attributesTable, 'Attributes table is on the page');
});
- test('/clients/:id lists all meta attributes', async function(assert) {
+ test('/clients/:id lists all meta attributes', async function (assert) {
node = server.create('node', 'forceIPv4', 'withMeta');
await ClientDetail.visit({ id: node.id });
@@ -346,35 +405,42 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('/clients/:id shows an empty message when there is no meta data', async function(assert) {
+ test('/clients/:id shows an empty message when there is no meta data', async function (assert) {
await ClientDetail.visit({ id: node.id });
- assert.notOk(ClientDetail.metaTable, 'Meta attributes table is not on the page');
+ assert.notOk(
+ ClientDetail.metaTable,
+ 'Meta attributes table is not on the page'
+ );
assert.ok(ClientDetail.emptyMetaMessage, 'Meta attributes is empty');
});
- test('when the node is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the node is not found, an error message is shown, but the URL persists', async function (assert) {
await ClientDetail.visit({ id: 'not-a-real-node' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/node/not-a-real-node',
'A request to the nonexistent node is made'
);
assert.equal(currentURL(), '/clients/not-a-real-node', 'The URL persists');
assert.ok(ClientDetail.error.isShown, 'Error message is shown');
- assert.equal(ClientDetail.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ ClientDetail.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
- test('/clients/:id shows the recent events list', async function(assert) {
+ test('/clients/:id shows the recent events list', async function (assert) {
await ClientDetail.visit({ id: node.id });
assert.ok(ClientDetail.hasEvents, 'Client events section exists');
});
- test('each node event shows basic node event information', async function(assert) {
+ test('each node event shows basic node event information', async function (assert) {
const event = server.db.nodeEvents
.where({ nodeId: node.id })
.sortBy('time')
@@ -392,12 +458,12 @@ module('Acceptance | client detail', function(hooks) {
assert.equal(eventRow.message, event.message, 'Event message');
});
- test('/clients/:id shows the driver status of every driver for the node', async function(assert) {
+ test('/clients/:id shows the driver status of every driver for the node', async function (assert) {
// Set the drivers up so health and detection is well tested
const nodeDrivers = node.drivers;
const undetectedDriver = 'raw_exec';
- Object.values(nodeDrivers).forEach(driver => {
+ Object.values(nodeDrivers).forEach((driver) => {
driver.Detected = true;
});
@@ -405,7 +471,9 @@ module('Acceptance | client detail', function(hooks) {
node.drivers = nodeDrivers;
const drivers = Object.keys(node.drivers)
- .map(driverName => assign({ Name: driverName }, node.drivers[driverName]))
+ .map((driverName) =>
+ assign({ Name: driverName }, node.drivers[driverName])
+ )
.sortBy('Name');
assert.ok(drivers.length > 0, 'Node has drivers');
@@ -415,7 +483,11 @@ module('Acceptance | client detail', function(hooks) {
drivers.forEach((driver, index) => {
const driverHead = ClientDetail.driverHeads.objectAt(index);
- assert.equal(driverHead.name, driver.Name, `${driver.Name}: Name is correct`);
+ assert.equal(
+ driverHead.name,
+ driver.Name,
+ `${driver.Name}: Name is correct`
+ );
assert.equal(
driverHead.detected,
driver.Detected ? 'Yes' : 'No',
@@ -439,31 +511,41 @@ module('Acceptance | client detail', function(hooks) {
`${driver.Name}: Health is correct`
);
assert.ok(
- driverHead.healthClass.includes(driver.Healthy ? 'running' : 'failed'),
+ driverHead.healthClass.includes(
+ driver.Healthy ? 'running' : 'failed'
+ ),
`${driver.Name}: Swatch with correct class is shown`
);
}
});
});
- test('each driver can be opened to see a message and attributes', async function(assert) {
+ test('each driver can be opened to see a message and attributes', async function (assert) {
// Only detected drivers can be expanded
const nodeDrivers = node.drivers;
- Object.values(nodeDrivers).forEach(driver => {
+ Object.values(nodeDrivers).forEach((driver) => {
driver.Detected = true;
});
node.drivers = nodeDrivers;
const driver = Object.keys(node.drivers)
- .map(driverName => assign({ Name: driverName }, node.drivers[driverName]))
+ .map((driverName) =>
+ assign({ Name: driverName }, node.drivers[driverName])
+ )
.sortBy('Name')[0];
await ClientDetail.visit({ id: node.id });
const driverHead = ClientDetail.driverHeads.objectAt(0);
const driverBody = ClientDetail.driverBodies.objectAt(0);
- assert.notOk(driverBody.descriptionIsShown, 'Driver health description is not shown');
- assert.notOk(driverBody.attributesAreShown, 'Driver attributes section is not shown');
+ assert.notOk(
+ driverBody.descriptionIsShown,
+ 'Driver health description is not shown'
+ );
+ assert.notOk(
+ driverBody.attributesAreShown,
+ 'Driver attributes section is not shown'
+ );
await driverHead.toggle();
assert.equal(
@@ -471,10 +553,13 @@ module('Acceptance | client detail', function(hooks) {
driver.HealthDescription,
'Driver health description is now shown'
);
- assert.ok(driverBody.attributesAreShown, 'Driver attributes section is now shown');
+ assert.ok(
+ driverBody.attributesAreShown,
+ 'Driver attributes section is now shown'
+ );
});
- test('the status light indicates when the node is ineligible for scheduling', async function(assert) {
+ test('the status light indicates when the node is ineligible for scheduling', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'ineligible',
@@ -490,7 +575,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('when the node has a drain strategy with a positive deadline, the drain stategy section prints the duration', async function(assert) {
+ test('when the node has a drain strategy with a positive deadline, the drain stategy section prints the duration', async function (assert) {
const deadline = 5400000000000; // 1.5 hours in nanoseconds
const forceDeadline = moment().add(1, 'd');
@@ -523,7 +608,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('when the node has a drain stategy with no deadline, the drain stategy section mentions that and omits the force deadline', async function(assert) {
+ test('when the node has a drain stategy with no deadline, the drain stategy section mentions that and omits the force deadline', async function (assert) {
const deadline = 0;
node = server.create('node', {
@@ -538,7 +623,10 @@ module('Acceptance | client detail', function(hooks) {
await ClientDetail.visit({ id: node.id });
- assert.notOk(ClientDetail.drainDetails.durationIsShown, 'Duration is omitted');
+ assert.notOk(
+ ClientDetail.drainDetails.durationIsShown,
+ 'Duration is omitted'
+ );
assert.ok(
ClientDetail.drainDetails.deadline.includes('No deadline'),
@@ -551,7 +639,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('when the node has a drain stategy with a negative deadline, the drain strategy section shows the force badge', async function(assert) {
+ test('when the node has a drain stategy with a negative deadline, the drain strategy section shows the force badge', async function (assert) {
const deadline = -1;
node = server.create('node', {
@@ -571,9 +659,15 @@ module('Acceptance | client detail', function(hooks) {
'Forced Drain is described'
);
- assert.ok(ClientDetail.drainDetails.duration.includes('--'), 'Duration is shown but unset');
+ assert.ok(
+ ClientDetail.drainDetails.duration.includes('--'),
+ 'Duration is shown but unset'
+ );
- assert.ok(ClientDetail.drainDetails.deadline.includes('--'), 'Deadline is shown but unset');
+ assert.ok(
+ ClientDetail.drainDetails.deadline.includes('--'),
+ 'Deadline is shown but unset'
+ );
assert.ok(
ClientDetail.drainDetails.drainSystemJobsText.endsWith('Yes'),
@@ -581,13 +675,17 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('toggling node eligibility disables the toggle and sends the correct POST request', async function(assert) {
+ test('toggling node eligibility disables the toggle and sends the correct POST request', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'eligible',
});
- server.pretender.post('/v1/node/:id/eligibility', () => [200, {}, ''], true);
+ server.pretender.post(
+ '/v1/node/:id/eligibility',
+ () => [200, {}, ''],
+ true
+ );
await ClientDetail.visit({ id: node.id });
assert.ok(ClientDetail.eligibilityToggle.isActive);
@@ -624,7 +722,7 @@ module('Acceptance | client detail', function(hooks) {
});
});
- test('starting a drain sends the correct POST request', async function(assert) {
+ test('starting a drain sends the correct POST request', async function (assert) {
let request;
node = server.create('node', {
@@ -690,8 +788,11 @@ module('Acceptance | client detail', function(hooks) {
await ClientDetail.drainPopover.toggle();
await ClientDetail.drainPopover.deadlineOptions.open();
- const optionsCount = ClientDetail.drainPopover.deadlineOptions.options.length;
- await ClientDetail.drainPopover.deadlineOptions.options.objectAt(optionsCount - 1).choose();
+ const optionsCount =
+ ClientDetail.drainPopover.deadlineOptions.options.length;
+ await ClientDetail.drainPopover.deadlineOptions.options
+ .objectAt(optionsCount - 1)
+ .choose();
await ClientDetail.drainPopover.setCustomDeadline('1h40m20s');
await ClientDetail.drainPopover.submit();
@@ -747,7 +848,7 @@ module('Acceptance | client detail', function(hooks) {
);
});
- test('starting a drain persists options to localstorage', async function(assert) {
+ test('starting a drain persists options to localstorage', async function (assert) {
const nodes = server.createList('node', 2, {
drain: false,
schedulingEligibility: 'eligible',
@@ -759,8 +860,11 @@ module('Acceptance | client detail', function(hooks) {
// Change all options to non-default values.
await ClientDetail.drainPopover.deadlineToggle.toggle();
await ClientDetail.drainPopover.deadlineOptions.open();
- const optionsCount = ClientDetail.drainPopover.deadlineOptions.options.length;
- await ClientDetail.drainPopover.deadlineOptions.options.objectAt(optionsCount - 1).choose();
+ const optionsCount =
+ ClientDetail.drainPopover.deadlineOptions.options.length;
+ await ClientDetail.drainPopover.deadlineOptions.options
+ .objectAt(optionsCount - 1)
+ .choose();
await ClientDetail.drainPopover.setCustomDeadline('1h40m20s');
await ClientDetail.drainPopover.forceDrainToggle.toggle();
await ClientDetail.drainPopover.systemJobsToggle.toggle();
@@ -786,7 +890,7 @@ module('Acceptance | client detail', function(hooks) {
assert.false(ClientDetail.drainPopover.systemJobsToggle.isActive);
});
- test('the drain popover cancel button closes the popover', async function(assert) {
+ test('the drain popover cancel button closes the popover', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'eligible',
@@ -803,7 +907,7 @@ module('Acceptance | client detail', function(hooks) {
assert.equal(nonSearchPOSTS(), 0);
});
- test('toggling eligibility is disabled while a drain is active', async function(assert) {
+ test('toggling eligibility is disabled while a drain is active', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -813,7 +917,7 @@ module('Acceptance | client detail', function(hooks) {
assert.ok(ClientDetail.eligibilityToggle.isDisabled);
});
- test('stopping a drain sends the correct POST request', async function(assert) {
+ test('stopping a drain sends the correct POST request', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -833,7 +937,7 @@ module('Acceptance | client detail', function(hooks) {
});
});
- test('when a drain is active, the "drain" popover is labeled as the "update" popover', async function(assert) {
+ test('when a drain is active, the "drain" popover is labeled as the "update" popover', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -843,7 +947,7 @@ module('Acceptance | client detail', function(hooks) {
assert.equal(ClientDetail.drainPopover.label, 'Update Drain');
});
- test('forcing a drain sends the correct POST request', async function(assert) {
+ test('forcing a drain sends the correct POST request', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -868,7 +972,7 @@ module('Acceptance | client detail', function(hooks) {
});
});
- test('when stopping a drain fails, an error is shown', async function(assert) {
+ test('when stopping a drain fails, an error is shown', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -887,7 +991,7 @@ module('Acceptance | client detail', function(hooks) {
assert.notOk(ClientDetail.stopDrainError.isPresent);
});
- test('when starting a drain fails, an error message is shown', async function(assert) {
+ test('when starting a drain fails, an error message is shown', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'eligible',
@@ -906,7 +1010,7 @@ module('Acceptance | client detail', function(hooks) {
assert.notOk(ClientDetail.drainError.isPresent);
});
- test('when updating a drain fails, an error message is shown', async function(assert) {
+ test('when updating a drain fails, an error message is shown', async function (assert) {
node = server.create('node', {
drain: true,
schedulingEligibility: 'ineligible',
@@ -925,7 +1029,7 @@ module('Acceptance | client detail', function(hooks) {
assert.notOk(ClientDetail.drainError.isPresent);
});
- test('when toggling eligibility fails, an error message is shown', async function(assert) {
+ test('when toggling eligibility fails, an error message is shown', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'eligible',
@@ -937,13 +1041,15 @@ module('Acceptance | client detail', function(hooks) {
await ClientDetail.eligibilityToggle.toggle();
assert.ok(ClientDetail.eligibilityError.isPresent);
- assert.ok(ClientDetail.eligibilityError.title.includes('Eligibility Error'));
+ assert.ok(
+ ClientDetail.eligibilityError.title.includes('Eligibility Error')
+ );
await ClientDetail.eligibilityError.dismiss();
assert.notOk(ClientDetail.eligibilityError.isPresent);
});
- test('when navigating away from a client that has an error message to another client, the error is not shown', async function(assert) {
+ test('when navigating away from a client that has an error message to another client, the error is not shown', async function (assert) {
node = server.create('node', {
drain: false,
schedulingEligibility: 'eligible',
@@ -957,14 +1063,16 @@ module('Acceptance | client detail', function(hooks) {
await ClientDetail.eligibilityToggle.toggle();
assert.ok(ClientDetail.eligibilityError.isPresent);
- assert.ok(ClientDetail.eligibilityError.title.includes('Eligibility Error'));
+ assert.ok(
+ ClientDetail.eligibilityError.title.includes('Eligibility Error')
+ );
await ClientDetail.visit({ id: node2.id });
assert.notOk(ClientDetail.eligibilityError.isPresent);
});
- test('toggling eligibility and node drain are disabled when the active ACL token does not permit node write', async function(assert) {
+ test('toggling eligibility and node drain are disabled when the active ACL token does not permit node write', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await ClientDetail.visit({ id: node.id });
@@ -972,37 +1080,43 @@ module('Acceptance | client detail', function(hooks) {
assert.ok(ClientDetail.drainPopover.isDisabled);
});
- test('the host volumes table lists all host volumes in alphabetical order by name', async function(assert) {
+ test('the host volumes table lists all host volumes in alphabetical order by name', async function (assert) {
await ClientDetail.visit({ id: node.id });
const sortedHostVolumes = Object.keys(node.hostVolumes)
- .map(key => node.hostVolumes[key])
+ .map((key) => node.hostVolumes[key])
.sortBy('Name');
assert.ok(ClientDetail.hasHostVolumes);
- assert.equal(ClientDetail.hostVolumes.length, Object.keys(node.hostVolumes).length);
+ assert.equal(
+ ClientDetail.hostVolumes.length,
+ Object.keys(node.hostVolumes).length
+ );
ClientDetail.hostVolumes.forEach((volume, index) => {
assert.equal(volume.name, sortedHostVolumes[index].Name);
});
});
- test('each host volume row contains information about the host volume', async function(assert) {
+ test('each host volume row contains information about the host volume', async function (assert) {
await ClientDetail.visit({ id: node.id });
const sortedHostVolumes = Object.keys(node.hostVolumes)
- .map(key => node.hostVolumes[key])
+ .map((key) => node.hostVolumes[key])
.sortBy('Name');
- ClientDetail.hostVolumes[0].as(volume => {
+ ClientDetail.hostVolumes[0].as((volume) => {
const volumeRow = sortedHostVolumes[0];
assert.equal(volume.name, volumeRow.Name);
assert.equal(volume.path, volumeRow.Path);
- assert.equal(volume.permissions, volumeRow.ReadOnly ? 'Read' : 'Read/Write');
+ assert.equal(
+ volume.permissions,
+ volumeRow.ReadOnly ? 'Read' : 'Read/Write'
+ );
});
});
- test('the host volumes table is not shown if the client has no host volumes', async function(assert) {
+ test('the host volumes table is not shown if the client has no host volumes', async function (assert) {
node = server.create('node', 'noHostVolumes');
await ClientDetail.visit({ id: node.id });
@@ -1029,7 +1143,7 @@ module('Acceptance | client detail', function(hooks) {
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
async beforeEach() {
server.createList('job', 5, { createAllocations: false });
- ['pending', 'running', 'complete', 'failed', 'lost'].forEach(s => {
+ ['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
server.createList('allocation', 5, { clientStatus: s });
});
@@ -1038,7 +1152,7 @@ module('Acceptance | client detail', function(hooks) {
filter: (alloc, selection) => selection.includes(alloc.clientStatus),
});
- test('fiter results with no matches display empty message', async function(assert) {
+ test('fiter results with no matches display empty message', async function (assert) {
const job = server.create('job', { createAllocations: false });
server.create('allocation', { jobId: job.id, clientStatus: 'running' });
@@ -1052,11 +1166,11 @@ module('Acceptance | client detail', function(hooks) {
});
});
-module('Acceptance | client detail (multi-namespace)', function(hooks) {
+module('Acceptance | client detail (multi-namespace)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node', 'forceIPv4', { schedulingEligibility: 'eligible' });
node = server.db.nodes[0];
@@ -1067,14 +1181,22 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
server.create('agent');
// Make a job for each namespace, but have both scheduled on the same node
- server.create('job', { id: 'job-1', namespaceId: 'default', createAllocations: false });
+ server.create('job', {
+ id: 'job-1',
+ namespaceId: 'default',
+ createAllocations: false,
+ });
server.createList('allocation', 3, {
nodeId: node.id,
jobId: 'job-1',
clientStatus: 'running',
});
- server.create('job', { id: 'job-2', namespaceId: 'other-namespace', createAllocations: false });
+ server.create('job', {
+ id: 'job-2',
+ namespaceId: 'other-namespace',
+ createAllocations: false,
+ });
server.createList('allocation', 3, {
nodeId: node.id,
jobId: 'job-2',
@@ -1082,7 +1204,7 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
});
});
- test('when the node has allocations on different namespaces, the associated jobs are fetched correctly', async function(assert) {
+ test('when the node has allocations on different namespaces, the associated jobs are fetched correctly', async function (assert) {
window.localStorage.nomadActiveNamespace = 'other-namespace';
await ClientDetail.visit({ id: node.id });
@@ -1097,7 +1219,10 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
'Job One fetched correctly'
);
assert.ok(
- server.pretender.handledRequests.findBy('url', '/v1/job/job-2?namespace=other-namespace'),
+ server.pretender.handledRequests.findBy(
+ 'url',
+ '/v1/job/job-2?namespace=other-namespace'
+ ),
'Job Two fetched correctly'
);
});
@@ -1114,7 +1239,7 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
filter: (alloc, selection) => selection.includes(alloc.namespace),
});
- test('facet Namespace | selecting namespace filters job options', async function(assert) {
+ test('facet Namespace | selecting namespace filters job options', async function (assert) {
await ClientDetail.visit({ id: node.id });
const nsFacet = ClientDetail.facets.namespace;
@@ -1127,7 +1252,7 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
await jobFacet.toggle();
assert.deepEqual(
- jobFacet.options.map(option => option.label.trim()),
+ jobFacet.options.map((option) => option.label.trim()),
['job-1', 'job-2']
);
@@ -1137,14 +1262,17 @@ module('Acceptance | client detail (multi-namespace)', function(hooks) {
await jobFacet.toggle();
assert.deepEqual(
- jobFacet.options.map(option => option.label.trim()),
+ jobFacet.options.map((option) => option.label.trim()),
['job-1']
);
});
});
-function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`facet ${label} | the ${label} facet has the correct options`, async function(assert) {
+function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+) {
+ test(`facet ${label} | the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -1156,13 +1284,13 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
});
- test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function(assert) {
+ test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -1173,7 +1301,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
const selection = [option.key];
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -1186,7 +1314,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -1200,7 +1328,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
selection.push(option2.key);
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -1213,7 +1341,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -1228,7 +1356,9 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
assert.equal(
currentURL(),
- `/clients/${node.id}?${paramName}=${encodeURIComponent(JSON.stringify(selection))}`,
+ `/clients/${node.id}?${paramName}=${encodeURIComponent(
+ JSON.stringify(selection)
+ )}`,
'URL has the correct query param key and value'
);
});
diff --git a/ui/tests/acceptance/client-monitor-test.js b/ui/tests/acceptance/client-monitor-test.js
index c795345e6..9b7db370a 100644
--- a/ui/tests/acceptance/client-monitor-test.js
+++ b/ui/tests/acceptance/client-monitor-test.js
@@ -11,11 +11,11 @@ let node;
let managementToken;
let clientToken;
-module('Acceptance | client monitor', function(hooks) {
+module('Acceptance | client monitor', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
node = server.create('node');
managementToken = server.create('token');
@@ -27,25 +27,30 @@ module('Acceptance | client monitor', function(hooks) {
run.later(run, run.cancelTimers, 500);
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await ClientMonitor.visit({ id: node.id });
await a11yAudit(assert);
});
- test('/clients/:id/monitor should have a breadcrumb trail linking back to clients', async function(assert) {
+ test('/clients/:id/monitor should have a breadcrumb trail linking back to clients', async function (assert) {
await ClientMonitor.visit({ id: node.id });
assert.equal(Layout.breadcrumbFor('clients.index').text, 'Clients');
- assert.equal(Layout.breadcrumbFor('clients.client').text, `Client ${node.id.split('-')[0]}`);
+ assert.equal(
+ Layout.breadcrumbFor('clients.client').text,
+ `Client ${node.id.split('-')[0]}`
+ );
await Layout.breadcrumbFor('clients.index').visit();
assert.equal(currentURL(), '/clients');
});
- test('the monitor page immediately streams agent monitor output at the info level', async function(assert) {
+ test('the monitor page immediately streams agent monitor output at the info level', async function (assert) {
await ClientMonitor.visit({ id: node.id });
- const logRequest = server.pretender.handledRequests.find(req =>
+ const logRequest = server.pretender.handledRequests.find((req) =>
req.url.startsWith('/v1/agent/monitor')
);
assert.ok(ClientMonitor.logsArePresent);
@@ -53,13 +58,13 @@ module('Acceptance | client monitor', function(hooks) {
assert.ok(logRequest.url.includes('log_level=info'));
});
- test('switching the log level persists the new log level as a query param', async function(assert) {
+ test('switching the log level persists the new log level as a query param', async function (assert) {
await ClientMonitor.visit({ id: node.id });
await ClientMonitor.selectLogLevel('Debug');
assert.equal(currentURL(), `/clients/${node.id}/monitor?level=debug`);
});
- test('when the current access token does not include the agent:read rule, a descriptive error message is shown', async function(assert) {
+ test('when the current access token does not include the agent:read rule, a descriptive error message is shown', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await ClientMonitor.visit({ id: node.id });
diff --git a/ui/tests/acceptance/clients-list-test.js b/ui/tests/acceptance/clients-list-test.js
index dd76d5a8c..37b3bf97b 100644
--- a/ui/tests/acceptance/clients-list-test.js
+++ b/ui/tests/acceptance/clients-list-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -6,15 +7,15 @@ import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import pageSizeSelect from './behaviors/page-size-select';
import ClientsList from 'nomad-ui/tests/pages/clients/list';
-module('Acceptance | clients list', function(hooks) {
+module('Acceptance | clients list', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
const nodesCount = ClientsList.pageSize + 1;
server.createList('node', nodesCount);
@@ -24,7 +25,7 @@ module('Acceptance | clients list', function(hooks) {
await a11yAudit(assert);
});
- test('/clients should list one page of clients', async function(assert) {
+ test('/clients should list one page of clients', async function (assert) {
// Make sure to make more nodes than 1 page to assert that pagination is working
const nodesCount = ClientsList.pageSize + 1;
@@ -39,13 +40,17 @@ module('Acceptance | clients list', function(hooks) {
const sortedNodes = server.db.nodes.sortBy('modifyIndex').reverse();
ClientsList.nodes.forEach((node, index) => {
- assert.equal(node.id, sortedNodes[index].id.split('-')[0], 'Clients are ordered');
+ assert.equal(
+ node.id,
+ sortedNodes[index].id.split('-')[0],
+ 'Clients are ordered'
+ );
});
assert.equal(document.title, 'Clients - Nomad');
});
- test('each client record should show high-level info of the client', async function(assert) {
+ test('each client record should show high-level info of the client', async function (assert) {
const node = server.create('node', 'draining', {
status: 'ready',
});
@@ -70,7 +75,7 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(nodeRow.allocations, allocations.length, '# Allocations');
});
- test('each client record should show running allocations', async function(assert) {
+ test('each client record should show running allocations', async function (assert) {
server.createList('agent', 1);
const node = server.create('node', {
@@ -82,7 +87,9 @@ module('Acceptance | clients list', function(hooks) {
server.create('job', { createAllocations: false });
- const running = server.createList('allocation', 2, { clientStatus: 'running' });
+ const running = server.createList('allocation', 2, {
+ clientStatus: 'running',
+ });
server.createList('allocation', 3, { clientStatus: 'pending' });
server.createList('allocation', 10, { clientStatus: 'complete' });
@@ -99,7 +106,7 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(nodeRow.allocations, running.length, '# Allocations');
});
- test('client status, draining, and eligibility are collapsed into one column that stays sorted', async function(assert) {
+ test('client status, draining, and eligibility are collapsed into one column that stays sorted', async function (assert) {
server.createList('agent', 1);
server.create('node', {
@@ -139,7 +146,7 @@ module('Acceptance | clients list', function(hooks) {
await ClientsList.visit();
- ClientsList.nodes[0].compositeStatus.as(readyClient => {
+ ClientsList.nodes[0].compositeStatus.as((readyClient) => {
assert.equal(readyClient.text, 'ready');
assert.ok(readyClient.isUnformatted, 'expected no status class');
assert.equal(readyClient.tooltip, 'ready / not draining / eligible');
@@ -154,10 +161,16 @@ module('Acceptance | clients list', function(hooks) {
);
assert.equal(ClientsList.nodes[4].compositeStatus.text, 'ineligible');
- assert.ok(ClientsList.nodes[4].compositeStatus.isWarning, 'expected warning class');
+ assert.ok(
+ ClientsList.nodes[4].compositeStatus.isWarning,
+ 'expected warning class'
+ );
assert.equal(ClientsList.nodes[5].compositeStatus.text, 'draining');
- assert.ok(ClientsList.nodes[5].compositeStatus.isInfo, 'expected info class');
+ assert.ok(
+ ClientsList.nodes[5].compositeStatus.isInfo,
+ 'expected info class'
+ );
await ClientsList.sortBy('compositeStatus');
@@ -189,7 +202,7 @@ module('Acceptance | clients list', function(hooks) {
]);
});
- test('each client should link to the client detail page', async function(assert) {
+ test('each client should link to the client detail page', async function (assert) {
server.createList('node', 1);
server.createList('agent', 1);
@@ -201,7 +214,7 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(currentURL(), `/clients/${node.id}`);
});
- test('when there are no clients, there is an empty message', async function(assert) {
+ test('when there are no clients, there is an empty message', async function (assert) {
server.createList('agent', 1);
await ClientsList.visit();
@@ -210,7 +223,7 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(ClientsList.empty.headline, 'No Clients');
});
- test('when there are clients, but no matches for a search term, there is an empty message', async function(assert) {
+ test('when there are clients, but no matches for a search term, there is an empty message', async function (assert) {
server.createList('agent', 1);
server.create('node', { name: 'node' });
@@ -221,7 +234,7 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(ClientsList.empty.headline, 'No Matches');
});
- test('when accessing clients is forbidden, show a message with a link to the tokens page', async function(assert) {
+ test('when accessing clients is forbidden, show a message with a link to the tokens page', async function (assert) {
server.create('agent');
server.create('node', { name: 'node' });
server.pretender.get('/v1/nodes', () => [403, {}, null]);
@@ -265,7 +278,13 @@ module('Acceptance | clients list', function(hooks) {
testFacet('State', {
facet: ClientsList.facets.state,
paramName: 'state',
- expectedOptions: ['Initializing', 'Ready', 'Down', 'Ineligible', 'Draining'],
+ expectedOptions: [
+ 'Initializing',
+ 'Ready',
+ 'Down',
+ 'Ineligible',
+ 'Draining',
+ ],
async beforeEach() {
server.create('agent');
@@ -273,15 +292,27 @@ module('Acceptance | clients list', function(hooks) {
server.createList('node', 2, { status: 'ready' });
server.createList('node', 2, { status: 'down' });
- server.createList('node', 2, { schedulingEligibility: 'eligible', drain: false });
- server.createList('node', 2, { schedulingEligibility: 'ineligible', drain: false });
- server.createList('node', 2, { schedulingEligibility: 'ineligible', drain: true });
+ server.createList('node', 2, {
+ schedulingEligibility: 'eligible',
+ drain: false,
+ });
+ server.createList('node', 2, {
+ schedulingEligibility: 'ineligible',
+ drain: false,
+ });
+ server.createList('node', 2, {
+ schedulingEligibility: 'ineligible',
+ drain: true,
+ });
await ClientsList.visit();
},
filter: (node, selection) => {
if (selection.includes('draining') && !node.drain) return false;
- if (selection.includes('ineligible') && node.schedulingEligibility === 'eligible')
+ if (
+ selection.includes('ineligible') &&
+ node.schedulingEligibility === 'eligible'
+ )
return false;
return selection.includes(node.status);
@@ -325,20 +356,26 @@ module('Acceptance | clients list', function(hooks) {
paramName: 'volume',
expectedOptions(nodes) {
const flatten = (acc, val) => acc.concat(Object.keys(val));
- return Array.from(new Set(nodes.mapBy('hostVolumes').reduce(flatten, [])));
+ return Array.from(
+ new Set(nodes.mapBy('hostVolumes').reduce(flatten, []))
+ );
},
async beforeEach() {
server.create('agent');
server.createList('node', 2, { hostVolumes: { One: { Name: 'One' } } });
- server.createList('node', 2, { hostVolumes: { One: { Name: 'One' }, Two: { Name: 'Two' } } });
+ server.createList('node', 2, {
+ hostVolumes: { One: { Name: 'One' }, Two: { Name: 'Two' } },
+ });
server.createList('node', 2, { hostVolumes: { Two: { Name: 'Two' } } });
await ClientsList.visit();
},
filter: (node, selection) =>
- Object.keys(node.hostVolumes).find(volume => selection.includes(volume)),
+ Object.keys(node.hostVolumes).find((volume) =>
+ selection.includes(volume)
+ ),
});
- test('when the facet selections result in no matches, the empty state states why', async function(assert) {
+ test('when the facet selections result in no matches, the empty state states why', async function (assert) {
server.create('agent');
server.createList('node', 2, { status: 'ready' });
@@ -347,21 +384,32 @@ module('Acceptance | clients list', function(hooks) {
await ClientsList.facets.state.toggle();
await ClientsList.facets.state.options.objectAt(0).toggle();
assert.ok(ClientsList.isEmpty, 'There is an empty message');
- assert.equal(ClientsList.empty.headline, 'No Matches', 'The message is appropriate');
+ assert.equal(
+ ClientsList.empty.headline,
+ 'No Matches',
+ 'The message is appropriate'
+ );
});
- test('the clients list is immediately filtered based on query params', async function(assert) {
+ test('the clients list is immediately filtered based on query params', async function (assert) {
server.create('agent');
server.create('node', { nodeClass: 'omg-large' });
server.create('node', { nodeClass: 'wtf-tiny' });
await ClientsList.visit({ class: JSON.stringify(['wtf-tiny']) });
- assert.equal(ClientsList.nodes.length, 1, 'Only one client shown due to query param');
+ assert.equal(
+ ClientsList.nodes.length,
+ 1,
+ 'Only one client shown due to query param'
+ );
});
- function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+ ) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -373,13 +421,13 @@ module('Acceptance | clients list', function(hooks) {
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
});
- test(`the ${label} facet filters the nodes list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the nodes list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -390,7 +438,7 @@ module('Acceptance | clients list', function(hooks) {
const selection = [option.key];
const expectedNodes = server.db.nodes
- .filter(node => filter(node, selection))
+ .filter((node) => filter(node, selection))
.sortBy('modifyIndex')
.reverse();
@@ -403,7 +451,7 @@ module('Acceptance | clients list', function(hooks) {
});
});
- test(`selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -417,7 +465,7 @@ module('Acceptance | clients list', function(hooks) {
selection.push(option2.key);
const expectedNodes = server.db.nodes
- .filter(node => filter(node, selection))
+ .filter((node) => filter(node, selection))
.sortBy('modifyIndex')
.reverse();
@@ -430,7 +478,7 @@ module('Acceptance | clients list', function(hooks) {
});
});
- test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -445,7 +493,9 @@ module('Acceptance | clients list', function(hooks) {
assert.equal(
currentURL(),
- `/clients?${paramName}=${encodeURIComponent(JSON.stringify(selection))}`,
+ `/clients?${paramName}=${encodeURIComponent(
+ JSON.stringify(selection)
+ )}`,
'URL has the correct query param key and value'
);
});
diff --git a/ui/tests/acceptance/exec-test.js b/ui/tests/acceptance/exec-test.js
index 2ce12ff0d..b37f164fa 100644
--- a/ui/tests/acceptance/exec-test.js
+++ b/ui/tests/acceptance/exec-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { module, skip, test } from 'qunit';
import { currentURL, settled } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
@@ -7,11 +8,11 @@ import Service from '@ember/service';
import Exec from 'nomad-ui/tests/pages/exec';
import KEYS from 'nomad-ui/utils/keys';
-module('Acceptance | exec', function(hooks) {
+module('Acceptance | exec', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
window.localStorage.clear();
window.sessionStorage.clear();
@@ -25,7 +26,7 @@ module('Acceptance | exec', function(hooks) {
status: 'running',
});
- this.job.taskGroups.models.forEach(taskGroup => {
+ this.job.taskGroups.models.forEach((taskGroup) => {
server.create('allocation', {
jobId: this.job.id,
taskGroup: taskGroup.name,
@@ -34,12 +35,12 @@ module('Acceptance | exec', function(hooks) {
});
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await Exec.visitJob({ job: this.job.id });
await a11yAudit(assert);
});
- test('/exec/:job should show the region, namespace, and job name', async function(assert) {
+ test('/exec/:job should show the region, namespace, and job name', async function (assert) {
server.create('namespace');
let namespace = server.create('namespace');
@@ -52,7 +53,11 @@ module('Acceptance | exec', function(hooks) {
status: 'running',
});
- await Exec.visitJob({ job: this.job.id, namespace: namespace.id, region: 'region-2' });
+ await Exec.visitJob({
+ job: this.job.id,
+ namespace: namespace.id,
+ region: 'region-2',
+ });
assert.equal(document.title, 'Exec - region-2 - Nomad');
@@ -63,14 +68,14 @@ module('Acceptance | exec', function(hooks) {
assert.notOk(Exec.jobDead.isPresent);
});
- test('/exec/:job should not show region and namespace when there are none', async function(assert) {
+ test('/exec/:job should not show region and namespace when there are none', async function (assert) {
await Exec.visitJob({ job: this.job.id });
assert.ok(Exec.header.region.isHidden);
assert.ok(Exec.header.namespace.isHidden);
});
- test('/exec/:job should show the task groups collapsed by default and allow the tasks to be shown', async function(assert) {
+ test('/exec/:job should show the task groups collapsed by default and allow the tasks to be shown', async function (assert) {
const firstTaskGroup = this.job.taskGroups.models.sortBy('name')[0];
await Exec.visitJob({ job: this.job.id });
@@ -90,35 +95,38 @@ module('Acceptance | exec', function(hooks) {
assert.equal(Exec.taskGroups[0].tasks.length, 0);
});
- test('/exec/:job should require selecting a task', async function(assert) {
+ test('/exec/:job should require selecting a task', async function (assert) {
await Exec.visitJob({ job: this.job.id });
assert.equal(
- window.execTerminal.buffer.active
- .getLine(0)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(0).translateToString().trim(),
'Select a task to start your session.'
);
});
- test('a task group with a pending allocation shows a loading spinner', async function(assert) {
+ test('a task group with a pending allocation shows a loading spinner', async function (assert) {
let taskGroup = this.job.taskGroups.models.sortBy('name')[0];
- this.server.db.allocations.update({ taskGroup: taskGroup.name }, { clientStatus: 'pending' });
+ this.server.db.allocations.update(
+ { taskGroup: taskGroup.name },
+ { clientStatus: 'pending' }
+ );
await Exec.visitJob({ job: this.job.id });
assert.ok(Exec.taskGroups[0].isLoading);
});
- test('a task group with no running task states or pending allocations should not be shown', async function(assert) {
+ test('a task group with no running task states or pending allocations should not be shown', async function (assert) {
let taskGroup = this.job.taskGroups.models.sortBy('name')[0];
- this.server.db.allocations.update({ taskGroup: taskGroup.name }, { clientStatus: 'failed' });
+ this.server.db.allocations.update(
+ { taskGroup: taskGroup.name },
+ { clientStatus: 'failed' }
+ );
await Exec.visitJob({ job: this.job.id });
assert.notEqual(Exec.taskGroups[0].name, taskGroup.name);
});
- test('an inactive task should not be shown', async function(assert) {
+ test('an inactive task should not be shown', async function (assert) {
let notRunningTaskGroup = this.job.taskGroups.models.sortBy('name')[0];
this.server.db.allocations.update(
{ taskGroup: notRunningTaskGroup.name },
@@ -128,7 +136,10 @@ module('Acceptance | exec', function(hooks) {
let runningTaskGroup = this.job.taskGroups.models.sortBy('name')[1];
runningTaskGroup.tasks.models.forEach((task, index) => {
if (index > 0) {
- this.server.db.taskStates.update({ name: task.name }, { finishedAt: new Date() });
+ this.server.db.taskStates.update(
+ { name: task.name },
+ { finishedAt: new Date() }
+ );
}
});
@@ -138,7 +149,7 @@ module('Acceptance | exec', function(hooks) {
assert.equal(Exec.taskGroups[0].tasks.length, 1);
});
- test('a task that becomes active should appear', async function(assert) {
+ test('a task that becomes active should appear', async function (assert) {
let notRunningTaskGroup = this.job.taskGroups.models.sortBy('name')[0];
this.server.db.allocations.update(
{ taskGroup: notRunningTaskGroup.name },
@@ -149,7 +160,10 @@ module('Acceptance | exec', function(hooks) {
let changingTaskStateName;
runningTaskGroup.tasks.models.sortBy('name').forEach((task, index) => {
if (index > 0) {
- this.server.db.taskStates.update({ name: task.name }, { finishedAt: new Date() });
+ this.server.db.taskStates.update(
+ { name: task.name },
+ { finishedAt: new Date() }
+ );
}
if (index === 1) {
@@ -166,8 +180,11 @@ module('Acceptance | exec', function(hooks) {
this.owner
.lookup('service:store')
.peekAll('allocation')
- .forEach(allocation => {
- const changingTaskState = allocation.states.findBy('name', changingTaskStateName);
+ .forEach((allocation) => {
+ const changingTaskState = allocation.states.findBy(
+ 'name',
+ changingTaskStateName
+ );
if (changingTaskState) {
changingTaskState.set('finishedAt', undefined);
@@ -180,7 +197,7 @@ module('Acceptance | exec', function(hooks) {
assert.equal(Exec.taskGroups[0].tasks[1].name, changingTaskStateName);
});
- test('a dead job has an inert window', async function(assert) {
+ test('a dead job has an inert window', async function (assert) {
this.job.status = 'dead';
this.job.save();
@@ -202,21 +219,21 @@ module('Acceptance | exec', function(hooks) {
);
});
- test('when a job dies the exec window becomes inert', async function(assert) {
+ test('when a job dies the exec window becomes inert', async function (assert) {
await Exec.visitJob({ job: this.job.id });
// Approximate live-polling job death
this.owner
.lookup('service:store')
.peekAll('job')
- .forEach(job => job.set('status', 'dead'));
+ .forEach((job) => job.set('status', 'dead'));
await settled();
assert.ok(Exec.jobDead.isPresent);
});
- test('visiting a path with a task group should open the group by default', async function(assert) {
+ test('visiting a path with a task group should open the group by default', async function (assert) {
let taskGroup = this.job.taskGroups.models.sortBy('name')[0];
await Exec.visitTaskGroup({ job: this.job.id, task_group: taskGroup.name });
@@ -224,13 +241,17 @@ module('Acceptance | exec', function(hooks) {
assert.ok(Exec.taskGroups[0].chevron.isDown);
let task = taskGroup.tasks.models.sortBy('name')[0];
- await Exec.visitTask({ job: this.job.id, task_group: taskGroup.name, task_name: task.name });
+ await Exec.visitTask({
+ job: this.job.id,
+ task_group: taskGroup.name,
+ task_name: task.name,
+ });
assert.equal(Exec.taskGroups[0].tasks.length, taskGroup.tasks.length);
assert.ok(Exec.taskGroups[0].chevron.isDown);
});
- test('navigating to a task adds its name to the route, chooses an allocation, and assigns a default command', async function(assert) {
+ test('navigating to a task adds its name to the route, chooses an allocation, and assigns a default command', async function (assert) {
await Exec.visitJob({ job: this.job.id });
await Exec.taskGroups[0].click();
await Exec.taskGroups[0].tasks[0].click();
@@ -241,39 +262,35 @@ module('Acceptance | exec', function(hooks) {
let taskStates = this.server.db.taskStates.where({
name: task.name,
});
- let allocationId = taskStates.find(ts => ts.allocationId).allocationId;
+ let allocationId = taskStates.find((ts) => ts.allocationId).allocationId;
await settled();
- assert.equal(currentURL(), `/exec/${this.job.id}/${taskGroup.name}/${task.name}`);
+ assert.equal(
+ currentURL(),
+ `/exec/${this.job.id}/${taskGroup.name}/${task.name}`
+ );
assert.ok(Exec.taskGroups[0].tasks[0].isActive);
assert.equal(
- window.execTerminal.buffer.active
- .getLine(2)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(2).translateToString().trim(),
'Multiple instances of this task are running. The allocation below was selected by random draw.'
);
assert.equal(
- window.execTerminal.buffer.active
- .getLine(4)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(4).translateToString().trim(),
'Customize your command, then hit ‘return’ to run.'
);
assert.equal(
- window.execTerminal.buffer.active
- .getLine(6)
- .translateToString()
- .trim(),
- `$ nomad alloc exec -i -t -task ${task.name} ${allocationId.split('-')[0]} /bin/bash`
+ window.execTerminal.buffer.active.getLine(6).translateToString().trim(),
+ `$ nomad alloc exec -i -t -task ${task.name} ${
+ allocationId.split('-')[0]
+ } /bin/bash`
);
});
- test('an allocation can be specified', async function(assert) {
+ test('an allocation can be specified', async function (assert) {
let taskGroup = this.job.taskGroups.models.sortBy('name')[0];
let task = taskGroup.tasks.models.sortBy('name')[0];
let allocations = this.server.db.allocations.where({
@@ -282,7 +299,10 @@ module('Acceptance | exec', function(hooks) {
});
let allocation = allocations[allocations.length - 1];
- this.server.db.taskStates.update({ name: task.name }, { name: 'spaced name!' });
+ this.server.db.taskStates.update(
+ { name: task.name },
+ { name: 'spaced name!' }
+ );
task.name = 'spaced name!';
task.save();
@@ -297,15 +317,14 @@ module('Acceptance | exec', function(hooks) {
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(4)
- .translateToString()
- .trim(),
- `$ nomad alloc exec -i -t -task spaced\\ name\\! ${allocation.id.split('-')[0]} /bin/bash`
+ window.execTerminal.buffer.active.getLine(4).translateToString().trim(),
+ `$ nomad alloc exec -i -t -task spaced\\ name\\! ${
+ allocation.id.split('-')[0]
+ } /bin/bash`
);
});
- test('running the command opens the socket for reading/writing and detects it closing', async function(assert) {
+ test('running the command opens the socket for reading/writing and detects it closing', async function (assert) {
let mockSocket = new MockSocket();
let mockSockets = Service.extend({
getTaskStateSocket(taskState, command) {
@@ -352,10 +371,7 @@ module('Acceptance | exec', function(hooks) {
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(5)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(5).translateToString().trim(),
'sh-3.2 🥳$'
);
@@ -372,15 +388,12 @@ module('Acceptance | exec', function(hooks) {
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(6)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(6).translateToString().trim(),
'The connection has closed.'
);
});
- test('the opening message includes the token if it exists', async function(assert) {
+ test('the opening message includes the token if it exists', async function (assert) {
const { secretId } = server.create('token');
window.localStorage.nomadTokenSecret = secretId;
@@ -415,10 +428,13 @@ module('Acceptance | exec', function(hooks) {
await Exec.terminal.pressEnter();
await settled();
- assert.equal(mockSocket.sent[0], `{"version":1,"auth_token":"${secretId}"}`);
+ assert.equal(
+ mockSocket.sent[0],
+ `{"version":1,"auth_token":"${secretId}"}`
+ );
});
- test('only one socket is opened after switching between tasks', async function(assert) {
+ test('only one socket is opened after switching between tasks', async function (assert) {
let mockSockets = Service.extend({
getTaskStateSocket() {
assert.step('Socket built');
@@ -445,7 +461,7 @@ module('Acceptance | exec', function(hooks) {
assert.verifySteps(['Socket built']);
});
- test('the command can be customised', async function(assert) {
+ test('the command can be customised', async function (assert) {
let mockSockets = Service.extend({
getTaskStateSocket(taskState, command) {
assert.equal(command, '/sh');
@@ -491,11 +507,10 @@ module('Acceptance | exec', function(hooks) {
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(6)
- .translateToString()
- .trim(),
- `$ nomad alloc exec -i -t -task ${task.name} ${allocation.id.split('-')[0]}`
+ window.execTerminal.buffer.active.getLine(6).translateToString().trim(),
+ `$ nomad alloc exec -i -t -task ${task.name} ${
+ allocation.id.split('-')[0]
+ }`
);
await window.execTerminal.simulateCommandDataEvent('/sh');
@@ -506,7 +521,7 @@ module('Acceptance | exec', function(hooks) {
assert.verifySteps(['Socket built']);
});
- test('a persisted customised command is recalled', async function(assert) {
+ test('a persisted customised command is recalled', async function (assert) {
window.localStorage.setItem('nomadExecCommand', JSON.stringify('/bin/sh'));
let taskGroup = this.job.taskGroups.models[0];
@@ -527,15 +542,14 @@ module('Acceptance | exec', function(hooks) {
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(4)
- .translateToString()
- .trim(),
- `$ nomad alloc exec -i -t -task ${task.name} ${allocation.id.split('-')[0]} /bin/sh`
+ window.execTerminal.buffer.active.getLine(4).translateToString().trim(),
+ `$ nomad alloc exec -i -t -task ${task.name} ${
+ allocation.id.split('-')[0]
+ } /bin/sh`
);
});
- skip('when a task state finishes submitting a command displays an error', async function(assert) {
+ skip('when a task state finishes submitting a command displays an error', async function (assert) {
let taskGroup = this.job.taskGroups.models.sortBy('name')[0];
let task = taskGroup.tasks.models.sortBy('name')[0];
@@ -549,16 +563,13 @@ module('Acceptance | exec', function(hooks) {
this.owner
.lookup('service:store')
.peekAll('allocation')
- .forEach(allocation => allocation.set('clientStatus', 'failed'));
+ .forEach((allocation) => allocation.set('clientStatus', 'failed'));
await Exec.terminal.pressEnter();
await settled();
assert.equal(
- window.execTerminal.buffer.active
- .getLine(7)
- .translateToString()
- .trim(),
+ window.execTerminal.buffer.active.getLine(7).translateToString().trim(),
`Failed to open a socket because task ${task.name} is not active.`
);
});
diff --git a/ui/tests/acceptance/global-header-test.js b/ui/tests/acceptance/global-header-test.js
index 5b4442aee..9234324e4 100644
--- a/ui/tests/acceptance/global-header-test.js
+++ b/ui/tests/acceptance/global-header-test.js
@@ -5,11 +5,11 @@ import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import Layout from 'nomad-ui/tests/pages/layout';
-module('Acceptance | global header', function(hooks) {
+module('Acceptance | global header', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- test('it diplays no links', async function(assert) {
+ test('it diplays no links', async function (assert) {
server.create('agent');
await visit('/');
@@ -18,7 +18,7 @@ module('Acceptance | global header', function(hooks) {
assert.false(Layout.navbar.end.vaultLink.isVisible);
});
- test('it diplays both links', async function(assert) {
+ test('it diplays both links', async function (assert) {
server.create('agent', 'withConsulLink', 'withVaultLink');
await visit('/');
@@ -27,7 +27,7 @@ module('Acceptance | global header', function(hooks) {
assert.true(Layout.navbar.end.vaultLink.isVisible);
});
- test('it diplays Consul link', async function(assert) {
+ test('it diplays Consul link', async function (assert) {
server.create('agent', 'withConsulLink');
await visit('/');
@@ -37,7 +37,7 @@ module('Acceptance | global header', function(hooks) {
assert.equal(Layout.navbar.end.consulLink.link, 'http://localhost:8500/ui');
});
- test('it diplays Vault link', async function(assert) {
+ test('it diplays Vault link', async function (assert) {
server.create('agent', 'withVaultLink');
await visit('/');
diff --git a/ui/tests/acceptance/job-allocations-test.js b/ui/tests/acceptance/job-allocations-test.js
index 73fcc7207..4f276316d 100644
--- a/ui/tests/acceptance/job-allocations-test.js
+++ b/ui/tests/acceptance/job-allocations-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -8,7 +9,7 @@ import Allocations from 'nomad-ui/tests/pages/jobs/job/allocations';
let job;
let allocations;
-const makeSearchAllocations = server => {
+const makeSearchAllocations = (server) => {
Array(10)
.fill(null)
.map((_, index) => {
@@ -19,26 +20,33 @@ const makeSearchAllocations = server => {
});
};
-module('Acceptance | job allocations', function(hooks) {
+module('Acceptance | job allocations', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
- job = server.create('job', { noFailedPlacements: true, createAllocations: false });
+ job = server.create('job', {
+ noFailedPlacements: true,
+ createAllocations: false,
+ });
});
- test('it passes an accessibility audit', async function(assert) {
- server.createList('allocation', Allocations.pageSize - 1, { shallow: true });
+ test('it passes an accessibility audit', async function (assert) {
+ server.createList('allocation', Allocations.pageSize - 1, {
+ shallow: true,
+ });
allocations = server.schema.allocations.where({ jobId: job.id }).models;
await Allocations.visit({ id: job.id });
await a11yAudit(assert);
});
- test('lists all allocations for the job', async function(assert) {
- server.createList('allocation', Allocations.pageSize - 1, { shallow: true });
+ test('lists all allocations for the job', async function (assert) {
+ server.createList('allocation', Allocations.pageSize - 1, {
+ shallow: true,
+ });
allocations = server.schema.allocations.where({ jobId: job.id }).models;
await Allocations.visit({ id: job.id });
@@ -53,13 +61,17 @@ module('Acceptance | job allocations', function(hooks) {
Allocations.allocations.forEach((allocation, index) => {
const shortId = sortedAllocations[index].id.split('-')[0];
- assert.equal(allocation.shortId, shortId, `Allocation ${index} is ${shortId}`);
+ assert.equal(
+ allocation.shortId,
+ shortId,
+ `Allocation ${index} is ${shortId}`
+ );
});
assert.equal(document.title, `Job ${job.name} allocations - Nomad`);
});
- test('allocations table is sortable', async function(assert) {
+ test('allocations table is sortable', async function (assert) {
server.createList('allocation', Allocations.pageSize - 1);
allocations = server.schema.allocations.where({ jobId: job.id }).models;
@@ -82,7 +94,7 @@ module('Acceptance | job allocations', function(hooks) {
});
});
- test('allocations table is searchable', async function(assert) {
+ test('allocations table is searchable', async function (assert) {
makeSearchAllocations(server);
allocations = server.schema.allocations.where({ jobId: job.id }).models;
@@ -90,10 +102,14 @@ module('Acceptance | job allocations', function(hooks) {
await Allocations.visit({ id: job.id });
await Allocations.search('ffffff');
- assert.equal(Allocations.allocations.length, 5, 'List is filtered by search term');
+ assert.equal(
+ Allocations.allocations.length,
+ 5,
+ 'List is filtered by search term'
+ );
});
- test('when a search yields no results, the search box remains', async function(assert) {
+ test('when a search yields no results, the search box remains', async function (assert) {
makeSearchAllocations(server);
allocations = server.schema.allocations.where({ jobId: job.id }).models;
@@ -110,19 +126,27 @@ module('Acceptance | job allocations', function(hooks) {
assert.ok(Allocations.hasSearchBox, 'Search box is still shown');
});
- test('when the job for the allocations is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the allocations is not found, an error message is shown, but the URL persists', async function (assert) {
await Allocations.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/allocations', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/allocations',
+ 'The URL persists'
+ );
assert.ok(Allocations.error.isPresent, 'Error message is shown');
- assert.equal(Allocations.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ Allocations.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
testFacet('Status', {
@@ -130,12 +154,13 @@ module('Acceptance | job allocations', function(hooks) {
paramName: 'status',
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
async beforeEach() {
- ['pending', 'running', 'complete', 'failed', 'lost'].forEach(s => {
+ ['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
server.createList('allocation', 5, { clientStatus: s });
});
await Allocations.visit({ id: job.id });
},
- filter: (alloc, selection) => alloc.jobId == job.id && selection.includes(alloc.clientStatus),
+ filter: (alloc, selection) =>
+ alloc.jobId == job.id && selection.includes(alloc.clientStatus),
});
testFacet('Client', {
@@ -145,9 +170,9 @@ module('Acceptance | job allocations', function(hooks) {
return Array.from(
new Set(
allocs
- .filter(alloc => alloc.jobId == job.id)
+ .filter((alloc) => alloc.jobId == job.id)
.mapBy('nodeId')
- .map(id => id.split('-')[0])
+ .map((id) => id.split('-')[0])
)
).sort();
},
@@ -166,7 +191,9 @@ module('Acceptance | job allocations', function(hooks) {
paramName: 'taskGroup',
expectedOptions(allocs) {
return Array.from(
- new Set(allocs.filter(alloc => alloc.jobId == job.id).mapBy('taskGroup'))
+ new Set(
+ allocs.filter((alloc) => alloc.jobId == job.id).mapBy('taskGroup')
+ )
).sort();
},
async beforeEach() {
@@ -178,12 +205,16 @@ module('Acceptance | job allocations', function(hooks) {
await Allocations.visit({ id: job.id });
},
- filter: (alloc, selection) => alloc.jobId == job.id && selection.includes(alloc.taskGroup),
+ filter: (alloc, selection) =>
+ alloc.jobId == job.id && selection.includes(alloc.taskGroup),
});
});
-function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`facet ${label} | the ${label} facet has the correct options`, async function(assert) {
+function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+) {
+ test(`facet ${label} | the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -195,13 +226,13 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
});
- test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function(assert) {
+ test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -212,7 +243,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
const selection = [option.key];
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -225,7 +256,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -239,7 +270,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
selection.push(option2.key);
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -252,7 +283,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -267,7 +298,9 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
assert.equal(
currentURL(),
- `/jobs/${job.id}/allocations?${paramName}=${encodeURIComponent(JSON.stringify(selection))}`,
+ `/jobs/${job.id}/allocations?${paramName}=${encodeURIComponent(
+ JSON.stringify(selection)
+ )}`,
'URL has the correct query param key and value'
);
});
diff --git a/ui/tests/acceptance/job-clients-test.js b/ui/tests/acceptance/job-clients-test.js
index 34583f1d9..4af17e15d 100644
--- a/ui/tests/acceptance/job-clients-test.js
+++ b/ui/tests/acceptance/job-clients-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -21,11 +22,11 @@ const makeSearchableClients = (server, job) => {
});
};
-module('Acceptance | job clients', function(hooks) {
+module('Acceptance | job clients', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
clients = server.createList('node', 12, {
datacenter: 'dc1',
status: 'ready',
@@ -38,7 +39,7 @@ module('Acceptance | job clients', function(hooks) {
resourceSpec: ['M: 256, C: 500'],
createAllocations: false,
});
- clients.forEach(c => {
+ clients.forEach((c) => {
server.create('allocation', { jobId: job.id, nodeId: c.id });
});
@@ -51,43 +52,52 @@ module('Acceptance | job clients', function(hooks) {
);
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await Clients.visit({ id: job.id });
await a11yAudit(assert);
});
- test('lists all clients for the job', async function(assert) {
+ test('lists all clients for the job', async function (assert) {
await Clients.visit({ id: job.id });
assert.equal(Clients.clients.length, 15, 'Clients are shown in a table');
- const clientIDs = clients.sortBy('id').map(c => c.id);
- const clientsInTable = Clients.clients.map(c => c.id).sort();
+ const clientIDs = clients.sortBy('id').map((c) => c.id);
+ const clientsInTable = Clients.clients.map((c) => c.id).sort();
assert.deepEqual(clientsInTable, clientIDs);
assert.equal(document.title, `Job ${job.name} clients - Nomad`);
});
- test('dates have tooltip', async function(assert) {
+ test('dates have tooltip', async function (assert) {
await Clients.visit({ id: job.id });
Clients.clients.forEach((clientRow, index) => {
const jobStatus = Clients.clientFor(clientRow.id).status;
- ['createTime', 'modifyTime'].forEach(col => {
+ ['createTime', 'modifyTime'].forEach((col) => {
if (jobStatus === 'not scheduled') {
- assert.equal(clientRow[col].text, '-', `row ${index} doesn't have ${col} tooltip`);
+ /* eslint-disable-next-line qunit/no-conditional-assertions */
+ assert.equal(
+ clientRow[col].text,
+ '-',
+ `row ${index} doesn't have ${col} tooltip`
+ );
+ /* eslint-disable-next-line qunit/no-early-return */
return;
}
const hasTooltip = clientRow[col].tooltip.isPresent;
const tooltipText = clientRow[col].tooltip.text;
assert.true(hasTooltip, `row ${index} has ${col} tooltip`);
- assert.ok(tooltipText, `row ${index} has ${col} tooltip content ${tooltipText}`);
+ assert.ok(
+ tooltipText,
+ `row ${index} has ${col} tooltip content ${tooltipText}`
+ );
});
});
});
- test('clients table is sortable', async function(assert) {
+ test('clients table is sortable', async function (assert) {
await Clients.visit({ id: job.id });
await Clients.sortBy('node.name');
@@ -108,7 +118,7 @@ module('Acceptance | job clients', function(hooks) {
});
});
- test('clients table is searchable', async function(assert) {
+ test('clients table is searchable', async function (assert) {
makeSearchableClients(server, job);
await Clients.visit({ id: job.id });
@@ -117,7 +127,7 @@ module('Acceptance | job clients', function(hooks) {
assert.equal(Clients.clients.length, 5, 'List is filtered by search term');
});
- test('when a search yields no results, the search box remains', async function(assert) {
+ test('when a search yields no results, the search box remains', async function (assert) {
makeSearchableClients(server, job);
await Clients.visit({ id: job.id });
@@ -132,22 +142,26 @@ module('Acceptance | job clients', function(hooks) {
assert.ok(Clients.hasSearchBox, 'Search box is still shown');
});
- test('when the job for the clients is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the clients is not found, an error message is shown, but the URL persists', async function (assert) {
await Clients.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/clients', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/clients',
+ 'The URL persists'
+ );
assert.ok(Clients.error.isPresent, 'Error message is shown');
assert.equal(Clients.error.title, 'Not Found', 'Error message is for 404');
});
- test('clicking row goes to client details', async function(assert) {
+ test('clicking row goes to client details', async function (assert) {
const client = clients[0];
await Clients.visit({ id: job.id });
@@ -182,7 +196,7 @@ module('Acceptance | job clients', function(hooks) {
});
function testFacet(label, { facet, paramName, beforeEach, expectedOptions }) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -194,7 +208,7 @@ module('Acceptance | job clients', function(hooks) {
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
`Options for facet ${paramName} are as expected`
);
diff --git a/ui/tests/acceptance/job-definition-test.js b/ui/tests/acceptance/job-definition-test.js
index 779d0f813..c8948645f 100644
--- a/ui/tests/acceptance/job-definition-test.js
+++ b/ui/tests/acceptance/job-definition-test.js
@@ -8,49 +8,58 @@ import Definition from 'nomad-ui/tests/pages/jobs/job/definition';
let job;
-module('Acceptance | job definition', function(hooks) {
+module('Acceptance | job definition', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
setupCodeMirror(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('node');
server.create('job');
job = server.db.jobs[0];
await Definition.visit({ id: job.id });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await a11yAudit(assert, 'scrollable-region-focusable');
});
- test('visiting /jobs/:job_id/definition', async function(assert) {
+ test('visiting /jobs/:job_id/definition', async function (assert) {
assert.equal(currentURL(), `/jobs/${job.id}/definition`);
assert.equal(document.title, `Job ${job.name} definition - Nomad`);
});
- test('the job definition page contains a json viewer component', async function(assert) {
+ test('the job definition page contains a json viewer component', async function (assert) {
assert.ok(Definition.jsonViewer, 'JSON viewer found');
});
- test('the job definition page requests the job to display in an unmutated form', async function(assert) {
+ test('the job definition page requests the job to display in an unmutated form', async function (assert) {
const jobURL = `/v1/job/${job.id}`;
const jobRequests = server.pretender.handledRequests
- .map(req => req.url.split('?')[0])
- .filter(url => url === jobURL);
- assert.ok(jobRequests.length === 2, 'Two requests for the job were made');
+ .map((req) => req.url.split('?')[0])
+ .filter((url) => url === jobURL);
+ assert.strictEqual(
+ jobRequests.length,
+ 2,
+ 'Two requests for the job were made'
+ );
});
- test('the job definition can be edited', async function(assert) {
+ test('the job definition can be edited', async function (assert) {
assert.notOk(Definition.editor.isPresent, 'Editor is not shown on load');
await Definition.edit();
- assert.ok(Definition.editor.isPresent, 'Editor is shown after clicking edit');
+ assert.ok(
+ Definition.editor.isPresent,
+ 'Editor is shown after clicking edit'
+ );
assert.notOk(Definition.jsonViewer, 'Editor replaces the JSON viewer');
});
- test('when in editing mode, the action can be canceled, showing the read-only definition again', async function(assert) {
+ test('when in editing mode, the action can be canceled, showing the read-only definition again', async function (assert) {
await Definition.edit();
await Definition.editor.cancelEditing();
@@ -58,10 +67,17 @@ module('Acceptance | job definition', function(hooks) {
assert.notOk(Definition.editor.isPresent, 'The editor is gone');
});
- test('when in editing mode, the editor is prepopulated with the job definition', async function(assert) {
+ test('when in editing mode, the editor is prepopulated with the job definition', async function (assert) {
const requests = server.pretender.handledRequests;
- const jobDefinition = requests.findBy('url', `/v1/job/${job.id}`).responseText;
- const formattedJobDefinition = JSON.stringify(JSON.parse(jobDefinition), null, 2);
+ const jobDefinition = requests.findBy(
+ 'url',
+ `/v1/job/${job.id}`
+ ).responseText;
+ const formattedJobDefinition = JSON.stringify(
+ JSON.parse(jobDefinition),
+ null,
+ 2
+ );
await Definition.edit();
@@ -72,26 +88,38 @@ module('Acceptance | job definition', function(hooks) {
);
});
- test('when changes are submitted, the site redirects to the job overview page', async function(assert) {
+ test('when changes are submitted, the site redirects to the job overview page', async function (assert) {
await Definition.edit();
await Definition.editor.plan();
await Definition.editor.run();
- assert.equal(currentURL(), `/jobs/${job.id}`, 'Now on the job overview page');
+ assert.equal(
+ currentURL(),
+ `/jobs/${job.id}`,
+ 'Now on the job overview page'
+ );
});
- test('when the job for the definition is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the definition is not found, an error message is shown, but the URL persists', async function (assert) {
await Definition.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/definition', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/definition',
+ 'The URL persists'
+ );
assert.ok(Definition.error.isPresent, 'Error message is shown');
- assert.equal(Definition.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ Definition.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
});
diff --git a/ui/tests/acceptance/job-deployments-test.js b/ui/tests/acceptance/job-deployments-test.js
index c4fb897ed..fd1680755 100644
--- a/ui/tests/acceptance/job-deployments-test.js
+++ b/ui/tests/acceptance/job-deployments-test.js
@@ -7,24 +7,30 @@ import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import moment from 'moment';
import Deployments from 'nomad-ui/tests/pages/jobs/job/deployments';
-const sum = (list, key, getter = a => a) =>
+const sum = (list, key, getter = (a) => a) =>
list.reduce((sum, item) => sum + getter(get(item, key)), 0);
let job;
let deployments;
let sortedDeployments;
-module('Acceptance | job deployments', function(hooks) {
+module('Acceptance | job deployments', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
job = server.create('job');
deployments = server.schema.deployments.where({ jobId: job.id });
sortedDeployments = deployments.sort((a, b) => {
- const aVersion = server.db.jobVersions.findBy({ jobId: a.jobId, version: a.versionNumber });
- const bVersion = server.db.jobVersions.findBy({ jobId: b.jobId, version: b.versionNumber });
+ const aVersion = server.db.jobVersions.findBy({
+ jobId: a.jobId,
+ version: a.versionNumber,
+ });
+ const bVersion = server.db.jobVersions.findBy({
+ jobId: b.jobId,
+ version: b.versionNumber,
+ });
if (aVersion.submitTime < bVersion.submitTime) {
return 1;
} else if (aVersion.submitTime > bVersion.submitTime) {
@@ -34,15 +40,17 @@ module('Acceptance | job deployments', function(hooks) {
});
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await Deployments.visit({ id: job.id });
await a11yAudit(assert);
});
- test('/jobs/:id/deployments should list all job deployments', async function(assert) {
+ test('/jobs/:id/deployments should list all job deployments', async function (assert) {
await Deployments.visit({ id: job.id });
- assert.ok(
+ assert.equal(
Deployments.deployments.length,
deployments.length,
'Each deployment gets a row in the timeline'
@@ -50,7 +58,7 @@ module('Acceptance | job deployments', function(hooks) {
assert.equal(document.title, `Job ${job.name} deployments - Nomad`);
});
- test('each deployment mentions the deployment shortId, status, version, and time since it was submitted', async function(assert) {
+ test('each deployment mentions the deployment shortId, status, version, and time since it was submitted', async function (assert) {
await Deployments.visit({ id: job.id });
const deployment = sortedDeployments.models[0];
@@ -60,24 +68,32 @@ module('Acceptance | job deployments', function(hooks) {
});
const deploymentRow = Deployments.deployments.objectAt(0);
- assert.ok(deploymentRow.text.includes(deployment.id.split('-')[0]), 'Short ID');
+ assert.ok(
+ deploymentRow.text.includes(deployment.id.split('-')[0]),
+ 'Short ID'
+ );
assert.equal(deploymentRow.status, deployment.status, 'Status');
assert.ok(
deploymentRow.statusClass.includes(classForStatus(deployment.status)),
'Status Class'
);
- assert.ok(deploymentRow.version.includes(deployment.versionNumber), 'Version #');
assert.ok(
- deploymentRow.submitTime.includes(moment(version.submitTime / 1000000).fromNow()),
+ deploymentRow.version.includes(deployment.versionNumber),
+ 'Version #'
+ );
+ assert.ok(
+ deploymentRow.submitTime.includes(
+ moment(version.submitTime / 1000000).fromNow()
+ ),
'Submit time ago'
);
});
- test('when the deployment is running and needs promotion, the deployment item says so', async function(assert) {
+ test('when the deployment is running and needs promotion, the deployment item says so', async function (assert) {
// Ensure the deployment needs deployment
const deployment = sortedDeployments.models[0];
- const taskGroupSummary = deployment.deploymentTaskGroupSummaryIds.map(id =>
- server.schema.deploymentTaskGroupSummaries.find(id)
+ const taskGroupSummary = deployment.deploymentTaskGroupSummaryIds.map(
+ (id) => server.schema.deploymentTaskGroupSummaries.find(id)
)[0];
deployment.update('status', 'running');
@@ -94,10 +110,13 @@ module('Acceptance | job deployments', function(hooks) {
await Deployments.visit({ id: job.id });
const deploymentRow = Deployments.deployments.objectAt(0);
- assert.ok(deploymentRow.promotionIsRequired, 'Requires Promotion badge found');
+ assert.ok(
+ deploymentRow.promotionIsRequired,
+ 'Requires Promotion badge found'
+ );
});
- test('each deployment item can be opened to show details', async function(assert) {
+ test('each deployment item can be opened to show details', async function (assert) {
await Deployments.visit({ id: job.id });
const deploymentRow = Deployments.deployments.objectAt(0);
@@ -107,20 +126,20 @@ module('Acceptance | job deployments', function(hooks) {
assert.ok(deploymentRow.hasDetails, 'Deployment body found');
});
- test('when open, a deployment shows the deployment metrics', async function(assert) {
+ test('when open, a deployment shows the deployment metrics', async function (assert) {
await Deployments.visit({ id: job.id });
const deployment = sortedDeployments.models[0];
const deploymentRow = Deployments.deployments.objectAt(0);
- const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(id =>
- server.db.deploymentTaskGroupSummaries.find(id)
+ const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(
+ (id) => server.db.deploymentTaskGroupSummaries.find(id)
);
await deploymentRow.toggle();
assert.equal(
deploymentRow.metricFor('canaries').text,
- `${sum(taskGroupSummaries, 'placedCanaries', a => a.length)} / ${sum(
+ `${sum(taskGroupSummaries, 'placedCanaries', (a) => a.length)} / ${sum(
taskGroupSummaries,
'desiredCanaries'
)}`,
@@ -158,13 +177,13 @@ module('Acceptance | job deployments', function(hooks) {
);
});
- test('when open, a deployment shows a list of all task groups and their respective stats', async function(assert) {
+ test('when open, a deployment shows a list of all task groups and their respective stats', async function (assert) {
await Deployments.visit({ id: job.id });
const deployment = sortedDeployments.models[0];
const deploymentRow = Deployments.deployments.objectAt(0);
- const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(id =>
- server.db.deploymentTaskGroupSummaries.find(id)
+ const taskGroupSummaries = deployment.deploymentTaskGroupSummaryIds.map(
+ (id) => server.db.deploymentTaskGroupSummaries.find(id)
);
await deploymentRow.toggle();
@@ -178,11 +197,22 @@ module('Acceptance | job deployments', function(hooks) {
);
const taskGroup = taskGroupSummaries[0];
- const taskGroupRow = deploymentRow.taskGroups.findOneBy('name', taskGroup.name);
+ const taskGroupRow = deploymentRow.taskGroups.findOneBy(
+ 'name',
+ taskGroup.name
+ );
assert.equal(taskGroupRow.name, taskGroup.name, 'Name');
- assert.equal(taskGroupRow.promotion, promotionTestForTaskGroup(taskGroup), 'Needs Promotion');
- assert.equal(taskGroupRow.autoRevert, taskGroup.autoRevert ? 'Yes' : 'No', 'Auto Revert');
+ assert.equal(
+ taskGroupRow.promotion,
+ promotionTestForTaskGroup(taskGroup),
+ 'Needs Promotion'
+ );
+ assert.equal(
+ taskGroupRow.autoRevert,
+ taskGroup.autoRevert ? 'Yes' : 'No',
+ 'Auto Revert'
+ );
assert.equal(
taskGroupRow.canaries,
`${taskGroup.placedCanaries.length} / ${taskGroup.desiredCanaries}`,
@@ -193,8 +223,16 @@ module('Acceptance | job deployments', function(hooks) {
`${taskGroup.placedAllocs} / ${taskGroup.desiredTotal}`,
'Allocs'
);
- assert.equal(taskGroupRow.healthy, taskGroup.healthyAllocs, 'Healthy Allocs');
- assert.equal(taskGroupRow.unhealthy, taskGroup.unhealthyAllocs, 'Unhealthy Allocs');
+ assert.equal(
+ taskGroupRow.healthy,
+ taskGroup.healthyAllocs,
+ 'Healthy Allocs'
+ );
+ assert.equal(
+ taskGroupRow.unhealthy,
+ taskGroup.unhealthyAllocs,
+ 'Unhealthy Allocs'
+ );
assert.equal(
taskGroupRow.progress,
moment(taskGroup.requireProgressBy).format("MMM DD, 'YY HH:mm:ss ZZ"),
@@ -202,7 +240,7 @@ module('Acceptance | job deployments', function(hooks) {
);
});
- test('when open, a deployment shows a list of all allocations for the deployment', async function(assert) {
+ test('when open, a deployment shows a list of all allocations for the deployment', async function (assert) {
await Deployments.visit({ id: job.id });
const deployment = sortedDeployments.models[0];
@@ -210,31 +248,49 @@ module('Acceptance | job deployments', function(hooks) {
// TODO: Make this less brittle. This logic is copied from the mirage config,
// since there is no reference to allocations on the deployment model.
- const allocations = server.db.allocations.where({ jobId: deployment.jobId }).slice(0, 3);
+ const allocations = server.db.allocations
+ .where({ jobId: deployment.jobId })
+ .slice(0, 3);
await deploymentRow.toggle();
assert.ok(deploymentRow.hasAllocations, 'Allocations found');
- assert.equal(deploymentRow.allocations.length, allocations.length, 'One row per allocation');
+ assert.equal(
+ deploymentRow.allocations.length,
+ allocations.length,
+ 'One row per allocation'
+ );
const allocation = allocations[0];
const allocationRow = deploymentRow.allocations.objectAt(0);
- assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation is as expected');
+ assert.equal(
+ allocationRow.shortId,
+ allocation.id.split('-')[0],
+ 'Allocation is as expected'
+ );
});
- test('when the job for the deployments is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the deployments is not found, an error message is shown, but the URL persists', async function (assert) {
await Deployments.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/deployments', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/deployments',
+ 'The URL persists'
+ );
assert.ok(Deployments.error.isPresent, 'Error message is shown');
- assert.equal(Deployments.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ Deployments.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
function classForStatus(status) {
diff --git a/ui/tests/acceptance/job-detail-test.js b/ui/tests/acceptance/job-detail-test.js
index a0cf8409c..e6027ef3c 100644
--- a/ui/tests/acceptance/job-detail-test.js
+++ b/ui/tests/acceptance/job-detail-test.js
@@ -1,11 +1,14 @@
/* eslint-disable ember/no-test-module-for */
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import moment from 'moment';
import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
-import moduleForJob, { moduleForJobWithClientStatus } from 'nomad-ui/tests/helpers/module-for-job';
+import moduleForJob, {
+ moduleForJobWithClientStatus,
+} from 'nomad-ui/tests/helpers/module-for-job';
import JobDetail from 'nomad-ui/tests/pages/jobs/detail';
moduleForJob('Acceptance | job detail (batch)', 'allocations', () =>
@@ -16,26 +19,30 @@ moduleForJob('Acceptance | job detail (system)', 'allocations', () =>
server.create('job', { type: 'system', shallow: true })
);
-moduleForJobWithClientStatus('Acceptance | job detail with client status (system)', () =>
- server.create('job', {
- status: 'running',
- datacenters: ['dc1'],
- type: 'system',
- createAllocations: false,
- })
+moduleForJobWithClientStatus(
+ 'Acceptance | job detail with client status (system)',
+ () =>
+ server.create('job', {
+ status: 'running',
+ datacenters: ['dc1'],
+ type: 'system',
+ createAllocations: false,
+ })
);
moduleForJob('Acceptance | job detail (sysbatch)', 'allocations', () =>
server.create('job', { type: 'sysbatch', shallow: true })
);
-moduleForJobWithClientStatus('Acceptance | job detail with client status (sysbatch)', () =>
- server.create('job', {
- status: 'running',
- datacenters: ['dc1'],
- type: 'sysbatch',
- createAllocations: false,
- })
+moduleForJobWithClientStatus(
+ 'Acceptance | job detail with client status (sysbatch)',
+ () =>
+ server.create('job', {
+ status: 'running',
+ datacenters: ['dc1'],
+ type: 'sysbatch',
+ createAllocations: false,
+ })
);
moduleForJobWithClientStatus(
@@ -61,14 +68,17 @@ moduleForJob('Acceptance | job detail (sysbatch child)', 'allocations', () => {
return server.db.jobs.where({ parentId: parent.id })[0];
});
-moduleForJobWithClientStatus('Acceptance | job detail with client status (sysbatch child)', () => {
- const parent = server.create('job', 'periodicSysbatch', {
- childrenCount: 1,
- shallow: true,
- datacenters: ['dc1'],
- });
- return server.db.jobs.where({ parentId: parent.id })[0];
-});
+moduleForJobWithClientStatus(
+ 'Acceptance | job detail with client status (sysbatch child)',
+ () => {
+ const parent = server.create('job', 'periodicSysbatch', {
+ childrenCount: 1,
+ shallow: true,
+ datacenters: ['dc1'],
+ });
+ return server.db.jobs.where({ parentId: parent.id })[0];
+ }
+);
moduleForJobWithClientStatus(
'Acceptance | job detail with client status (sysbatch child with namespace)',
@@ -89,7 +99,7 @@ moduleForJob(
'children',
() => server.create('job', 'periodic', { shallow: true }),
{
- 'the default sort is submitTime descending': async function(job, assert) {
+ 'the default sort is submitTime descending': async function (job, assert) {
const mostRecentLaunch = server.db.jobs
.where({ parentId: job.id })
.sortBy('submitTime')
@@ -98,7 +108,9 @@ moduleForJob(
assert.ok(JobDetail.jobsHeader.hasSubmitTime);
assert.equal(
JobDetail.jobs[0].submitTime,
- moment(mostRecentLaunch.submitTime / 1000000).format('MMM DD HH:mm:ss ZZ')
+ moment(mostRecentLaunch.submitTime / 1000000).format(
+ 'MMM DD HH:mm:ss ZZ'
+ )
);
},
}
@@ -116,7 +128,7 @@ moduleForJob(
return parent;
},
{
- 'display namespace in children table': async function(job, assert) {
+ 'display namespace in children table': async function (job, assert) {
assert.ok(JobDetail.jobsHeader.hasNamespace);
assert.equal(JobDetail.jobs[0].namespace, job.namespace);
},
@@ -137,7 +149,9 @@ moduleForJob(
assert.ok(JobDetail.jobsHeader.hasSubmitTime);
assert.equal(
JobDetail.jobs[0].submitTime,
- moment(mostRecentLaunch.submitTime / 1000000).format('MMM DD HH:mm:ss ZZ')
+ moment(mostRecentLaunch.submitTime / 1000000).format(
+ 'MMM DD HH:mm:ss ZZ'
+ )
);
},
}
@@ -155,7 +169,7 @@ moduleForJob(
return parent;
},
{
- 'display namespace in children table': async function(job, assert) {
+ 'display namespace in children table': async function (job, assert) {
assert.ok(JobDetail.jobsHeader.hasNamespace);
assert.equal(JobDetail.jobs[0].namespace, job.namespace);
},
@@ -163,14 +177,24 @@ moduleForJob(
);
moduleForJob('Acceptance | job detail (periodic child)', 'allocations', () => {
- const parent = server.create('job', 'periodic', { childrenCount: 1, shallow: true });
+ const parent = server.create('job', 'periodic', {
+ childrenCount: 1,
+ shallow: true,
+ });
return server.db.jobs.where({ parentId: parent.id })[0];
});
-moduleForJob('Acceptance | job detail (parameterized child)', 'allocations', () => {
- const parent = server.create('job', 'parameterized', { childrenCount: 1, shallow: true });
- return server.db.jobs.where({ parentId: parent.id })[0];
-});
+moduleForJob(
+ 'Acceptance | job detail (parameterized child)',
+ 'allocations',
+ () => {
+ const parent = server.create('job', 'parameterized', {
+ childrenCount: 1,
+ shallow: true,
+ });
+ return server.db.jobs.where({ parentId: parent.id })[0];
+ }
+);
moduleForJob(
'Acceptance | job detail (service)',
@@ -181,33 +205,35 @@ moduleForJob(
await JobDetail.tabFor('deployments').visit();
assert.equal(currentURL(), `/jobs/${job.id}/deployments`);
},
- 'when the job is not found, an error message is shown, but the URL persists': async (
- job,
- assert
- ) => {
- await JobDetail.visit({ id: 'not-a-real-job' });
+ 'when the job is not found, an error message is shown, but the URL persists':
+ async (job, assert) => {
+ await JobDetail.visit({ id: 'not-a-real-job' });
- assert.equal(
- server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
- .findBy('status', 404).url,
- '/v1/job/not-a-real-job',
- 'A request to the nonexistent job is made'
- );
- assert.equal(currentURL(), '/jobs/not-a-real-job', 'The URL persists');
- assert.ok(JobDetail.error.isPresent, 'Error message is shown');
- assert.equal(JobDetail.error.title, 'Not Found', 'Error message is for 404');
- },
+ assert.equal(
+ server.pretender.handledRequests
+ .filter((request) => !request.url.includes('policy'))
+ .findBy('status', 404).url,
+ '/v1/job/not-a-real-job',
+ 'A request to the nonexistent job is made'
+ );
+ assert.equal(currentURL(), '/jobs/not-a-real-job', 'The URL persists');
+ assert.ok(JobDetail.error.isPresent, 'Error message is shown');
+ assert.equal(
+ JobDetail.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
+ },
}
);
-module('Acceptance | job detail (with namespaces)', function(hooks) {
+module('Acceptance | job detail (with namespaces)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let job, managementToken, clientToken;
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.createList('namespace', 2);
server.create('node');
job = server.create('job', {
@@ -223,20 +249,23 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
clientToken = server.create('token');
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
const namespace = server.db.namespaces.find(job.namespaceId);
await JobDetail.visit({ id: job.id, namespace: namespace.name });
await a11yAudit(assert);
});
- test('when there are namespaces, the job detail page states the namespace for the job', async function(assert) {
+ test('when there are namespaces, the job detail page states the namespace for the job', async function (assert) {
const namespace = server.db.namespaces.find(job.namespaceId);
await JobDetail.visit({ id: job.id, namespace: namespace.name });
- assert.ok(JobDetail.statFor('namespace').text, 'Namespace included in stats');
+ assert.ok(
+ JobDetail.statFor('namespace').text,
+ 'Namespace included in stats'
+ );
});
- test('the exec button state can change between namespaces', async function(assert) {
+ test('the exec button state can change between namespaces', async function (assert) {
const job1 = server.create('job', {
status: 'running',
namespaceId: server.db.namespaces[0].id,
@@ -276,7 +305,7 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
assert.ok(JobDetail.execButton.isDisabled);
});
- test('the anonymous policy is fetched to check whether to show the exec button', async function(assert) {
+ test('the anonymous policy is fetched to check whether to show the exec button', async function (assert) {
window.localStorage.removeItem('nomadTokenSecret');
server.create('policy', {
@@ -292,11 +321,14 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
},
});
- await JobDetail.visit({ id: job.id, namespace: server.db.namespaces[1].name });
+ await JobDetail.visit({
+ id: job.id,
+ namespace: server.db.namespaces[1].name,
+ });
assert.notOk(JobDetail.execButton.isDisabled);
});
- test('meta table is displayed if job has meta attributes', async function(assert) {
+ test('meta table is displayed if job has meta attributes', async function (assert) {
const jobWithMeta = server.create('job', {
status: 'running',
namespaceId: server.db.namespaces[1].id,
@@ -305,14 +337,20 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
},
});
- await JobDetail.visit({ id: job.id, namespace: server.db.namespaces[1].name });
+ await JobDetail.visit({
+ id: job.id,
+ namespace: server.db.namespaces[1].name,
+ });
assert.notOk(JobDetail.metaTable, 'Meta table not present');
- await JobDetail.visit({ id: jobWithMeta.id, namespace: server.db.namespaces[1].name });
+ await JobDetail.visit({
+ id: jobWithMeta.id,
+ namespace: server.db.namespaces[1].name,
+ });
assert.ok(JobDetail.metaTable, 'Meta table is present');
});
- test('pack details are displayed', async function(assert) {
+ test('pack details are displayed', async function (assert) {
const namespace = server.db.namespaces[1].id;
const jobFromPack = server.create('job', {
status: 'running',
@@ -337,7 +375,7 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
);
});
- test('resource recommendations show when they exist and can be expanded, collapsed, and processed', async function(assert) {
+ test('resource recommendations show when they exist and can be expanded, collapsed, and processed', async function (assert) {
server.create('feature', { name: 'Dynamic Application Sizing' });
job = server.create('job', {
@@ -349,10 +387,13 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
});
window.localStorage.nomadTokenSecret = managementToken.secretId;
- await JobDetail.visit({ id: job.id, namespace: server.db.namespaces[1].name });
+ await JobDetail.visit({
+ id: job.id,
+ namespace: server.db.namespaces[1].name,
+ });
- const groupsWithRecommendations = job.taskGroups.filter(group =>
- group.tasks.models.any(task => task.recommendations.models.length)
+ const groupsWithRecommendations = job.taskGroups.filter((group) =>
+ group.tasks.models.any((task) => task.recommendations.models.length)
);
const jobRecommendationCount = groupsWithRecommendations.length;
@@ -380,7 +421,10 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
await toggle.click();
- assert.equal(recommendation.card.slug.groupName, firstRecommendationGroup.name);
+ assert.equal(
+ recommendation.card.slug.groupName,
+ firstRecommendationGroup.name
+ );
await recommendation.card.acceptButton.click();
@@ -392,26 +436,34 @@ module('Acceptance | job detail (with namespaces)', function(hooks) {
assert.equal(JobDetail.recommendations.length, jobRecommendationCount - 1);
});
- test('resource recommendations are not fetched when the feature doesn’t exist', async function(assert) {
+ test('resource recommendations are not fetched when the feature doesn’t exist', async function (assert) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
- await JobDetail.visit({ id: job.id, namespace: server.db.namespaces[1].name });
+ await JobDetail.visit({
+ id: job.id,
+ namespace: server.db.namespaces[1].name,
+ });
assert.equal(JobDetail.recommendations.length, 0);
assert.equal(
- server.pretender.handledRequests.filter(request => request.url.includes('recommendations'))
- .length,
+ server.pretender.handledRequests.filter((request) =>
+ request.url.includes('recommendations')
+ ).length,
0
);
});
- test('when the dynamic autoscaler is applied, you can scale a task within the job detail page', async function(assert) {
+ test('when the dynamic autoscaler is applied, you can scale a task within the job detail page', async function (assert) {
const SCALE_AND_WRITE_NAMESPACE = 'scale-and-write-namespace';
const READ_ONLY_NAMESPACE = 'read-only-namespace';
const clientToken = server.create('token');
- const namespace = server.create('namespace', { id: SCALE_AND_WRITE_NAMESPACE });
- const secondNamespace = server.create('namespace', { id: READ_ONLY_NAMESPACE });
+ const namespace = server.create('namespace', {
+ id: SCALE_AND_WRITE_NAMESPACE,
+ });
+ const secondNamespace = server.create('namespace', {
+ id: READ_ONLY_NAMESPACE,
+ });
job = server.create('job', {
groupCount: 0,
diff --git a/ui/tests/acceptance/job-dispatch-test.js b/ui/tests/acceptance/job-dispatch-test.js
index 00d4aa888..ef4764310 100644
--- a/ui/tests/acceptance/job-dispatch-test.js
+++ b/ui/tests/acceptance/job-dispatch-test.js
@@ -1,4 +1,6 @@
/* eslint-disable ember/no-test-module-for */
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
@@ -33,12 +35,12 @@ moduleForJobDispatch('Acceptance | job dispatch (with namespace)', () => {
function moduleForJobDispatch(title, jobFactory) {
let job, namespace, managementToken, clientToken;
- module(title, function(hooks) {
+ module(title, function (hooks) {
setupApplicationTest(hooks);
setupCodeMirror(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
// Required for placing allocations (a result of dispatching jobs)
server.create('node');
@@ -51,17 +53,17 @@ function moduleForJobDispatch(title, jobFactory) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await JobDispatch.visit({ id: job.id, namespace: namespace.name });
await a11yAudit(assert);
});
- test('the dispatch button is displayed with management token', async function(assert) {
+ test('the dispatch button is displayed with management token', async function (assert) {
await JobDetail.visit({ id: job.id, namespace: namespace.name });
assert.notOk(JobDetail.dispatchButton.isDisabled);
});
- test('the dispatch button is displayed when allowed', async function(assert) {
+ test('the dispatch button is displayed when allowed', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
const policy = server.create('policy', {
@@ -88,37 +90,43 @@ function moduleForJobDispatch(title, jobFactory) {
clientToken.save();
});
- test('the dispatch button is disabled when not allowed', async function(assert) {
+ test('the dispatch button is disabled when not allowed', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await JobDetail.visit({ id: job.id, namespace: namespace.name });
assert.ok(JobDetail.dispatchButton.isDisabled);
});
- test('all meta fields are displayed', async function(assert) {
+ test('all meta fields are displayed', async function (assert) {
await JobDispatch.visit({ id: job.id, namespace: namespace.name });
assert.equal(
JobDispatch.metaFields.length,
- job.parameterizedJob.MetaOptional.length + job.parameterizedJob.MetaRequired.length
+ job.parameterizedJob.MetaOptional.length +
+ job.parameterizedJob.MetaRequired.length
);
});
- test('required meta fields are properly indicated', async function(assert) {
+ test('required meta fields are properly indicated', async function (assert) {
await JobDispatch.visit({ id: job.id, namespace: namespace.name });
- JobDispatch.metaFields.forEach(f => {
+ JobDispatch.metaFields.forEach((f) => {
const hasIndicator = f.label.includes(REQUIRED_INDICATOR);
- const isRequired = job.parameterizedJob.MetaRequired.includes(f.field.id);
+ const isRequired = job.parameterizedJob.MetaRequired.includes(
+ f.field.id
+ );
if (isRequired) {
assert.ok(hasIndicator, `${f.label} contains required indicator.`);
} else {
- assert.notOk(hasIndicator, `${f.label} doesn't contain required indicator.`);
+ assert.notOk(
+ hasIndicator,
+ `${f.label} doesn't contain required indicator.`
+ );
}
});
});
- test('job without meta fields', async function(assert) {
+ test('job without meta fields', async function (assert) {
const jobWithoutMeta = server.create('job', 'parameterized', {
status: 'running',
namespaceId: namespace.name,
@@ -128,11 +136,14 @@ function moduleForJobDispatch(title, jobFactory) {
},
});
- await JobDispatch.visit({ id: jobWithoutMeta.id, namespace: namespace.name });
+ await JobDispatch.visit({
+ id: jobWithoutMeta.id,
+ namespace: namespace.name,
+ });
assert.ok(JobDispatch.dispatchButton.isPresent);
});
- test('payload text area is hidden when forbidden', async function(assert) {
+ test('payload text area is hidden when forbidden', async function (assert) {
job.parameterizedJob.Payload = 'forbidden';
job.save();
@@ -142,7 +153,7 @@ function moduleForJobDispatch(title, jobFactory) {
assert.notOk(JobDispatch.payload.editor.isPresent);
});
- test('payload is indicated as required', async function(assert) {
+ test('payload is indicated as required', async function (assert) {
const jobPayloadRequired = server.create('job', 'parameterized', {
status: 'running',
namespaceId: namespace.name,
@@ -158,7 +169,10 @@ function moduleForJobDispatch(title, jobFactory) {
},
});
- await JobDispatch.visit({ id: jobPayloadRequired.id, namespace: namespace.name });
+ await JobDispatch.visit({
+ id: jobPayloadRequired.id,
+ namespace: namespace.name,
+ });
let payloadTitle = JobDispatch.payload.title;
assert.ok(
@@ -166,7 +180,10 @@ function moduleForJobDispatch(title, jobFactory) {
`${payloadTitle} contains required indicator.`
);
- await JobDispatch.visit({ id: jobPayloadOptional.id, namespace: namespace.name });
+ await JobDispatch.visit({
+ id: jobPayloadOptional.id,
+ namespace: namespace.name,
+ });
payloadTitle = JobDispatch.payload.title;
assert.notOk(
@@ -175,15 +192,17 @@ function moduleForJobDispatch(title, jobFactory) {
);
});
- test('dispatch a job', async function(assert) {
+ test('dispatch a job', async function (assert) {
function countDispatchChildren() {
- return server.db.jobs.where(j => j.id.startsWith(`${job.id}/`)).length;
+ return server.db.jobs.where((j) =>
+ j.id.startsWith(`${job.id}/`)
+ ).length;
}
await JobDispatch.visit({ id: job.id, namespace: namespace.name });
// Fill form.
- JobDispatch.metaFields.map(f => f.field.input('meta value'));
+ JobDispatch.metaFields.map((f) => f.field.input('meta value'));
JobDispatch.payload.editor.fillIn('payload');
const childrenCountBefore = countDispatchChildren();
@@ -191,11 +210,13 @@ function moduleForJobDispatch(title, jobFactory) {
const childrenCountAfter = countDispatchChildren();
assert.equal(childrenCountAfter, childrenCountBefore + 1);
- assert.ok(currentURL().startsWith(`/jobs/${encodeURIComponent(`${job.id}/`)}`));
+ assert.ok(
+ currentURL().startsWith(`/jobs/${encodeURIComponent(`${job.id}/`)}`)
+ );
assert.ok(JobDetail.jobName);
});
- test('fail when required meta field is empty', async function(assert) {
+ test('fail when required meta field is empty', async function (assert) {
// Make sure we have a required meta param.
job.parameterizedJob.MetaRequired = ['required'];
job.parameterizedJob.Payload = 'forbidden';
@@ -204,14 +225,14 @@ function moduleForJobDispatch(title, jobFactory) {
await JobDispatch.visit({ id: job.id, namespace: namespace.name });
// Fill only optional meta params.
- JobDispatch.optionalMetaFields.map(f => f.field.input('meta value'));
+ JobDispatch.optionalMetaFields.map((f) => f.field.input('meta value'));
await JobDispatch.dispatchButton.click();
assert.ok(JobDispatch.hasError, 'Dispatch error message is shown');
});
- test('fail when required payload is empty', async function(assert) {
+ test('fail when required payload is empty', async function (assert) {
job.parameterizedJob.MetaRequired = [];
job.parameterizedJob.Payload = 'required';
job.save();
diff --git a/ui/tests/acceptance/job-evaluations-test.js b/ui/tests/acceptance/job-evaluations-test.js
index 54e2c3dc8..d77eab4f8 100644
--- a/ui/tests/acceptance/job-evaluations-test.js
+++ b/ui/tests/acceptance/job-evaluations-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -8,23 +9,30 @@ import Evaluations from 'nomad-ui/tests/pages/jobs/job/evaluations';
let job;
let evaluations;
-module('Acceptance | job evaluations', function(hooks) {
+module('Acceptance | job evaluations', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
- job = server.create('job', { noFailedPlacements: true, createAllocations: false });
+ hooks.beforeEach(async function () {
+ job = server.create('job', {
+ noFailedPlacements: true,
+ createAllocations: false,
+ });
evaluations = server.db.evaluations.where({ jobId: job.id });
await Evaluations.visit({ id: job.id });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await a11yAudit(assert);
});
- test('lists all evaluations for the job', async function(assert) {
- assert.equal(Evaluations.evaluations.length, evaluations.length, 'All evaluations are listed');
+ test('lists all evaluations for the job', async function (assert) {
+ assert.equal(
+ Evaluations.evaluations.length,
+ evaluations.length,
+ 'All evaluations are listed'
+ );
const sortedEvaluations = evaluations.sortBy('modifyIndex').reverse();
@@ -36,7 +44,7 @@ module('Acceptance | job evaluations', function(hooks) {
assert.equal(document.title, `Job ${job.name} evaluations - Nomad`);
});
- test('evaluations table is sortable', async function(assert) {
+ test('evaluations table is sortable', async function (assert) {
await Evaluations.sortBy('priority');
assert.equal(
@@ -55,18 +63,26 @@ module('Acceptance | job evaluations', function(hooks) {
});
});
- test('when the job for the evaluations is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the evaluations is not found, an error message is shown, but the URL persists', async function (assert) {
await Evaluations.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/evaluations', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/evaluations',
+ 'The URL persists'
+ );
assert.ok(Evaluations.error.isPresent, 'Error message is shown');
- assert.equal(Evaluations.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ Evaluations.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
});
diff --git a/ui/tests/acceptance/job-run-test.js b/ui/tests/acceptance/job-run-test.js
index b8d723eda..619ae0da7 100644
--- a/ui/tests/acceptance/job-run-test.js
+++ b/ui/tests/acceptance/job-run-test.js
@@ -12,7 +12,7 @@ const newJobTaskGroupName = 'redis';
let managementToken, clientToken;
-const jsonJob = overrides => {
+const jsonJob = (overrides) => {
return JSON.stringify(
assign(
{},
@@ -40,12 +40,12 @@ const jsonJob = overrides => {
);
};
-module('Acceptance | job run', function(hooks) {
+module('Acceptance | job run', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
setupCodeMirror(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
// Required for placing allocations (a result of creating jobs)
server.create('node');
@@ -55,19 +55,21 @@ module('Acceptance | job run', function(hooks) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await JobRun.visit();
await a11yAudit(assert);
});
- test('visiting /jobs/run', async function(assert) {
+ test('visiting /jobs/run', async function (assert) {
await JobRun.visit();
assert.equal(currentURL(), '/jobs/run');
assert.equal(document.title, 'Run a job - Nomad');
});
- test('when submitting a job, the site redirects to the new job overview page', async function(assert) {
+ test('when submitting a job, the site redirects to the new job overview page', async function (assert) {
const spec = jsonJob();
await JobRun.visit();
@@ -82,7 +84,7 @@ module('Acceptance | job run', function(hooks) {
);
});
- test('when submitting a job to a different namespace, the redirect to the job overview page takes namespace into account', async function(assert) {
+ test('when submitting a job to a different namespace, the redirect to the job overview page takes namespace into account', async function (assert) {
const newNamespace = 'second-namespace';
server.create('namespace', { id: newNamespace });
@@ -100,14 +102,14 @@ module('Acceptance | job run', function(hooks) {
);
});
- test('when the user doesn’t have permission to run a job, redirects to the job overview page', async function(assert) {
+ test('when the user doesn’t have permission to run a job, redirects to the job overview page', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await JobRun.visit();
assert.equal(currentURL(), '/jobs');
});
- test('when using client token user can still go to job page if they have correct permissions', async function(assert) {
+ test('when using client token user can still go to job page if they have correct permissions', async function (assert) {
const clientTokenWithPolicy = server.create('token');
const newNamespace = 'second-namespace';
diff --git a/ui/tests/acceptance/job-versions-test.js b/ui/tests/acceptance/job-versions-test.js
index 902bd2a47..af43ded0a 100644
--- a/ui/tests/acceptance/job-versions-test.js
+++ b/ui/tests/acceptance/job-versions-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -11,15 +13,18 @@ let job;
let namespace;
let versions;
-module('Acceptance | job versions', function(hooks) {
+module('Acceptance | job versions', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('namespace');
namespace = server.create('namespace');
- job = server.create('job', { namespaceId: namespace.id, createAllocations: false });
+ job = server.create('job', {
+ namespaceId: namespace.id,
+ createAllocations: false,
+ });
versions = server.db.jobVersions.where({ jobId: job.id });
const managementToken = server.create('token');
@@ -28,31 +33,38 @@ module('Acceptance | job versions', function(hooks) {
await Versions.visit({ id: job.id, namespace: namespace.id });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await a11yAudit(assert);
});
- test('/jobs/:id/versions should list all job versions', async function(assert) {
- assert.ok(Versions.versions.length, versions.length, 'Each version gets a row in the timeline');
+ test('/jobs/:id/versions should list all job versions', async function (assert) {
+ assert.equal(
+ Versions.versions.length,
+ versions.length,
+ 'Each version gets a row in the timeline'
+ );
assert.equal(document.title, `Job ${job.name} versions - Nomad`);
});
- test('each version mentions the version number, the stability, and the submitted time', async function(assert) {
+ test('each version mentions the version number, the stability, and the submitted time', async function (assert) {
const version = versions.sortBy('submitTime').reverse()[0];
const formattedSubmitTime = moment(version.submitTime / 1000000).format(
"MMM DD, 'YY HH:mm:ss ZZ"
);
const versionRow = Versions.versions.objectAt(0);
- assert.ok(versionRow.text.includes(`Version #${version.version}`), 'Version #');
+ assert.ok(
+ versionRow.text.includes(`Version #${version.version}`),
+ 'Version #'
+ );
assert.equal(versionRow.stability, version.stable.toString(), 'Stability');
assert.equal(versionRow.submitTime, formattedSubmitTime, 'Submit time');
});
- test('all versions but the current one have a button to revert to that version', async function(assert) {
+ test('all versions but the current one have a button to revert to that version', async function (assert) {
let versionRowToRevertTo;
- Versions.versions.forEach(versionRow => {
+ Versions.versions.forEach((versionRow) => {
if (versionRow.number === job.version) {
assert.ok(versionRow.revertToButton.isHidden);
} else {
@@ -67,11 +79,14 @@ module('Acceptance | job versions', function(hooks) {
await versionRowToRevertTo.revertToButton.idle();
await versionRowToRevertTo.revertToButton.confirm();
- const revertRequest = this.server.pretender.handledRequests.find(request =>
- request.url.includes('revert')
+ const revertRequest = this.server.pretender.handledRequests.find(
+ (request) => request.url.includes('revert')
);
- assert.equal(revertRequest.url, `/v1/job/${job.id}/revert?namespace=${namespace.id}`);
+ assert.equal(
+ revertRequest.url,
+ `/v1/job/${job.id}/revert?namespace=${namespace.id}`
+ );
assert.deepEqual(JSON.parse(revertRequest.requestBody), {
JobID: job.id,
@@ -82,9 +97,9 @@ module('Acceptance | job versions', function(hooks) {
}
});
- test('when reversion fails, the error message from the API is piped through to the alert', async function(assert) {
+ test('when reversion fails, the error message from the API is piped through to the alert', async function (assert) {
const versionRowToRevertTo = Versions.versions.filter(
- versionRow => versionRow.revertToButton.isPresent
+ (versionRow) => versionRow.revertToButton.isPresent
)[0];
if (versionRowToRevertTo) {
@@ -107,9 +122,9 @@ module('Acceptance | job versions', function(hooks) {
}
});
- test('when reversion has no effect, the error message explains', async function(assert) {
+ test('when reversion has no effect, the error message explains', async function (assert) {
const versionRowToRevertTo = Versions.versions.filter(
- versionRow => versionRow.revertToButton.isPresent
+ (versionRow) => versionRow.revertToButton.isPresent
)[0];
if (versionRowToRevertTo) {
@@ -131,27 +146,31 @@ module('Acceptance | job versions', function(hooks) {
}
});
- test('when the job for the versions is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the job for the versions is not found, an error message is shown, but the URL persists', async function (assert) {
await Versions.visit({ id: 'not-a-real-job' });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/versions', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/versions',
+ 'The URL persists'
+ );
assert.ok(Versions.error.isPresent, 'Error message is shown');
assert.equal(Versions.error.title, 'Not Found', 'Error message is for 404');
});
});
-module('Acceptance | job versions (with client token)', function(hooks) {
+module('Acceptance | job versions (with client token)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
job = server.create('job', { createAllocations: false });
versions = server.db.jobVersions.where({ jobId: job.id });
@@ -162,9 +181,9 @@ module('Acceptance | job versions (with client token)', function(hooks) {
await Versions.visit({ id: job.id });
});
- test('reversion buttons are disabled when the token lacks permissions', async function(assert) {
+ test('reversion buttons are disabled when the token lacks permissions', async function (assert) {
const versionRowWithReversion = Versions.versions.filter(
- versionRow => versionRow.revertToButton.isPresent
+ (versionRow) => versionRow.revertToButton.isPresent
)[0];
if (versionRowWithReversion) {
@@ -176,7 +195,7 @@ module('Acceptance | job versions (with client token)', function(hooks) {
window.localStorage.clear();
});
- test('reversion buttons are available when the client token has permissions', async function(assert) {
+ test('reversion buttons are available when the client token has permissions', async function (assert) {
const REVERT_NAMESPACE = 'revert-namespace';
window.localStorage.clear();
const clientToken = server.create('token');
@@ -212,7 +231,7 @@ module('Acceptance | job versions (with client token)', function(hooks) {
versions = server.db.jobVersions.where({ jobId: job.id });
await Versions.visit({ id: job.id, namespace: REVERT_NAMESPACE });
const versionRowWithReversion = Versions.versions.filter(
- versionRow => versionRow.revertToButton.isPresent
+ (versionRow) => versionRow.revertToButton.isPresent
)[0];
if (versionRowWithReversion) {
diff --git a/ui/tests/acceptance/jobs-list-test.js b/ui/tests/acceptance/jobs-list-test.js
index 6a0038303..2a46b0649 100644
--- a/ui/tests/acceptance/jobs-list-test.js
+++ b/ui/tests/acceptance/jobs-list-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -9,11 +10,11 @@ import Layout from 'nomad-ui/tests/pages/layout';
let managementToken, clientToken;
-module('Acceptance | jobs list', function(hooks) {
+module('Acceptance | jobs list', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
// Required for placing allocations (a result of creating jobs)
server.create('node');
@@ -24,19 +25,19 @@ module('Acceptance | jobs list', function(hooks) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await JobsList.visit();
await a11yAudit(assert);
});
- test('visiting /jobs', async function(assert) {
+ test('visiting /jobs', async function (assert) {
await JobsList.visit();
assert.equal(currentURL(), '/jobs');
assert.equal(document.title, 'Jobs - Nomad');
});
- test('/jobs should list the first page of jobs sorted by modify index', async function(assert) {
+ test('/jobs should list the first page of jobs sorted by modify index', async function (assert) {
const jobsCount = JobsList.pageSize + 1;
server.createList('job', jobsCount, { createAllocations: false });
@@ -49,7 +50,7 @@ module('Acceptance | jobs list', function(hooks) {
});
});
- test('each job row should contain information about the job', async function(assert) {
+ test('each job row should contain information about the job', async function (assert) {
server.createList('job', 2);
const job = server.db.jobs.sortBy('modifyIndex').reverse()[0];
const taskGroups = server.db.taskGroups.where({ jobId: job.id });
@@ -67,7 +68,7 @@ module('Acceptance | jobs list', function(hooks) {
assert.equal(jobRow.taskGroups, taskGroups.length, '# Groups');
});
- test('each job row should link to the corresponding job', async function(assert) {
+ test('each job row should link to the corresponding job', async function (assert) {
server.create('job');
const job = server.db.jobs[0];
@@ -77,14 +78,14 @@ module('Acceptance | jobs list', function(hooks) {
assert.equal(currentURL(), `/jobs/${job.id}`);
});
- test('the new job button transitions to the new job page', async function(assert) {
+ test('the new job button transitions to the new job page', async function (assert) {
await JobsList.visit();
await JobsList.runJobButton.click();
assert.equal(currentURL(), '/jobs/run');
});
- test('the job run button is disabled when the token lacks permission', async function(assert) {
+ test('the job run button is disabled when the token lacks permission', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await JobsList.visit();
@@ -94,7 +95,7 @@ module('Acceptance | jobs list', function(hooks) {
assert.equal(currentURL(), '/jobs');
});
- test('the anonymous policy is fetched to check whether to show the job run button', async function(assert) {
+ test('the anonymous policy is fetched to check whether to show the job run button', async function (assert) {
window.localStorage.removeItem('nomadTokenSecret');
server.create('policy', {
@@ -114,14 +115,18 @@ module('Acceptance | jobs list', function(hooks) {
assert.notOk(JobsList.runJobButton.isDisabled);
});
- test('when there are no jobs, there is an empty message', async function(assert) {
+ test('when there are no jobs, there is an empty message', async function (assert) {
await JobsList.visit();
assert.ok(JobsList.isEmpty, 'There is an empty message');
- assert.equal(JobsList.emptyState.headline, 'No Jobs', 'The message is appropriate');
+ assert.equal(
+ JobsList.emptyState.headline,
+ 'No Jobs',
+ 'The message is appropriate'
+ );
});
- test('when there are jobs, but no matches for a search result, there is an empty message', async function(assert) {
+ test('when there are jobs, but no matches for a search result, there is an empty message', async function (assert) {
server.create('job', { name: 'cat 1' });
server.create('job', { name: 'cat 2' });
@@ -129,23 +134,33 @@ module('Acceptance | jobs list', function(hooks) {
await JobsList.search.fillIn('dog');
assert.ok(JobsList.isEmpty, 'The empty message is shown');
- assert.equal(JobsList.emptyState.headline, 'No Matches', 'The message is appropriate');
+ assert.equal(
+ JobsList.emptyState.headline,
+ 'No Matches',
+ 'The message is appropriate'
+ );
});
- test('searching resets the current page', async function(assert) {
- server.createList('job', JobsList.pageSize + 1, { createAllocations: false });
+ test('searching resets the current page', async function (assert) {
+ server.createList('job', JobsList.pageSize + 1, {
+ createAllocations: false,
+ });
await JobsList.visit();
await JobsList.nextPage();
- assert.equal(currentURL(), '/jobs?page=2', 'Page query param captures page=2');
+ assert.equal(
+ currentURL(),
+ '/jobs?page=2',
+ 'Page query param captures page=2'
+ );
await JobsList.search.fillIn('foobar');
assert.equal(currentURL(), '/jobs?search=foobar', 'No page query param');
});
- test('when a cluster has namespaces, each job row includes the job namespace', async function(assert) {
+ test('when a cluster has namespaces, each job row includes the job namespace', async function (assert) {
server.createList('namespace', 2);
server.createList('job', 2);
const job = server.db.jobs.sortBy('modifyIndex').reverse()[0];
@@ -156,10 +171,14 @@ module('Acceptance | jobs list', function(hooks) {
assert.equal(jobRow.namespace, job.namespaceId);
});
- test('when the namespace query param is set, only matching jobs are shown', async function(assert) {
+ test('when the namespace query param is set, only matching jobs are shown', async function (assert) {
server.createList('namespace', 2);
- const job1 = server.create('job', { namespaceId: server.db.namespaces[0].id });
- const job2 = server.create('job', { namespaceId: server.db.namespaces[1].id });
+ const job1 = server.create('job', {
+ namespaceId: server.db.namespaces[0].id,
+ });
+ const job2 = server.create('job', {
+ namespaceId: server.db.namespaces[1].id,
+ });
await JobsList.visit();
assert.equal(JobsList.jobs.length, 2, 'All jobs by default');
@@ -167,16 +186,28 @@ module('Acceptance | jobs list', function(hooks) {
const firstNamespace = server.db.namespaces[0];
await JobsList.visit({ namespace: firstNamespace.id });
assert.equal(JobsList.jobs.length, 1, 'One job in the default namespace');
- assert.equal(JobsList.jobs.objectAt(0).name, job1.name, 'The correct job is shown');
+ assert.equal(
+ JobsList.jobs.objectAt(0).name,
+ job1.name,
+ 'The correct job is shown'
+ );
const secondNamespace = server.db.namespaces[1];
await JobsList.visit({ namespace: secondNamespace.id });
- assert.equal(JobsList.jobs.length, 1, `One job in the ${secondNamespace.name} namespace`);
- assert.equal(JobsList.jobs.objectAt(0).name, job2.name, 'The correct job is shown');
+ assert.equal(
+ JobsList.jobs.length,
+ 1,
+ `One job in the ${secondNamespace.name} namespace`
+ );
+ assert.equal(
+ JobsList.jobs.objectAt(0).name,
+ job2.name,
+ 'The correct job is shown'
+ );
});
- test('when accessing jobs is forbidden, show a message with a link to the tokens page', async function(assert) {
+ test('when accessing jobs is forbidden, show a message with a link to the tokens page', async function (assert) {
server.pretender.get('/v1/jobs', () => [403, {}, null]);
await JobsList.visit();
@@ -187,13 +218,20 @@ module('Acceptance | jobs list', function(hooks) {
});
function typeForJob(job) {
- return job.periodic ? 'periodic' : job.parameterized ? 'parameterized' : job.type;
+ return job.periodic
+ ? 'periodic'
+ : job.parameterized
+ ? 'parameterized'
+ : job.type;
}
- test('the jobs list page has appropriate faceted search options', async function(assert) {
+ test('the jobs list page has appropriate faceted search options', async function (assert) {
await JobsList.visit();
- assert.ok(JobsList.facets.namespace.isHidden, 'Namespace facet not found (no namespaces)');
+ assert.ok(
+ JobsList.facets.namespace.isHidden,
+ 'Namespace facet not found (no namespaces)'
+ );
assert.ok(JobsList.facets.type.isPresent, 'Type facet found');
assert.ok(JobsList.facets.status.isPresent, 'Status facet found');
assert.ok(JobsList.facets.datacenter.isPresent, 'Datacenter facet found');
@@ -220,7 +258,14 @@ module('Acceptance | jobs list', function(hooks) {
testFacet('Type', {
facet: JobsList.facets.type,
paramName: 'type',
- expectedOptions: ['Batch', 'Parameterized', 'Periodic', 'Service', 'System', 'System Batch'],
+ expectedOptions: [
+ 'Batch',
+ 'Parameterized',
+ 'Periodic',
+ 'Service',
+ 'System',
+ 'System Batch',
+ ],
async beforeEach() {
server.createList('job', 2, { createAllocations: false, type: 'batch' });
server.createList('job', 2, {
@@ -235,7 +280,10 @@ module('Acceptance | jobs list', function(hooks) {
parameterized: true,
childrenCount: 0,
});
- server.createList('job', 2, { createAllocations: false, type: 'service' });
+ server.createList('job', 2, {
+ createAllocations: false,
+ type: 'service',
+ });
await JobsList.visit();
},
filter(job, selection) {
@@ -261,7 +309,11 @@ module('Acceptance | jobs list', function(hooks) {
createAllocations: false,
childrenCount: 0,
});
- server.createList('job', 2, { status: 'dead', createAllocations: false, childrenCount: 0 });
+ server.createList('job', 2, {
+ status: 'dead',
+ createAllocations: false,
+ childrenCount: 0,
+ });
await JobsList.visit();
},
filter: (job, selection) => selection.includes(job.status),
@@ -297,10 +349,15 @@ module('Acceptance | jobs list', function(hooks) {
createAllocations: false,
childrenCount: 0,
});
- server.create('job', { datacenters: ['pdx'], createAllocations: false, childrenCount: 0 });
+ server.create('job', {
+ datacenters: ['pdx'],
+ createAllocations: false,
+ childrenCount: 0,
+ });
await JobsList.visit();
},
- filter: (job, selection) => job.datacenters.find(dc => selection.includes(dc)),
+ filter: (job, selection) =>
+ job.datacenters.find((dc) => selection.includes(dc)),
});
testFacet('Prefix', {
@@ -318,35 +375,52 @@ module('Acceptance | jobs list', function(hooks) {
'hashi-three',
'nmd_two',
'noprefix',
- ].forEach(name => {
- server.create('job', { name, createAllocations: false, childrenCount: 0 });
+ ].forEach((name) => {
+ server.create('job', {
+ name,
+ createAllocations: false,
+ childrenCount: 0,
+ });
});
await JobsList.visit();
},
- filter: (job, selection) => selection.find(prefix => job.name.startsWith(prefix)),
+ filter: (job, selection) =>
+ selection.find((prefix) => job.name.startsWith(prefix)),
});
- test('when the facet selections result in no matches, the empty state states why', async function(assert) {
- server.createList('job', 2, { status: 'pending', createAllocations: false, childrenCount: 0 });
+ test('when the facet selections result in no matches, the empty state states why', async function (assert) {
+ server.createList('job', 2, {
+ status: 'pending',
+ createAllocations: false,
+ childrenCount: 0,
+ });
await JobsList.visit();
await JobsList.facets.status.toggle();
await JobsList.facets.status.options.objectAt(1).toggle();
assert.ok(JobsList.isEmpty, 'There is an empty message');
- assert.equal(JobsList.emptyState.headline, 'No Matches', 'The message is appropriate');
+ assert.equal(
+ JobsList.emptyState.headline,
+ 'No Matches',
+ 'The message is appropriate'
+ );
});
- test('the jobs list is immediately filtered based on query params', async function(assert) {
+ test('the jobs list is immediately filtered based on query params', async function (assert) {
server.create('job', { type: 'batch', createAllocations: false });
server.create('job', { type: 'service', createAllocations: false });
await JobsList.visit({ type: JSON.stringify(['batch']) });
- assert.equal(JobsList.jobs.length, 1, 'Only one job shown due to query param');
+ assert.equal(
+ JobsList.jobs.length,
+ 1,
+ 'Only one job shown due to query param'
+ );
});
- test('the active namespace is carried over to the storage pages', async function(assert) {
+ test('the active namespace is carried over to the storage pages', async function (assert) {
server.createList('namespace', 2);
const namespace = server.db.namespaces[1];
@@ -359,7 +433,7 @@ module('Acceptance | jobs list', function(hooks) {
assert.equal(currentURL(), `/csi/volumes?namespace=${namespace.id}`);
});
- test('when the user has a client token that has a namespace with a policy to run a job', async function(assert) {
+ test('when the user has a client token that has a namespace with a policy to run a job', async function (assert) {
const READ_AND_WRITE_NAMESPACE = 'read-and-write-namespace';
const READ_ONLY_NAMESPACE = 'read-only-namespace';
@@ -400,7 +474,10 @@ module('Acceptance | jobs list', function(hooks) {
pageObject: JobsList,
pageObjectList: JobsList.jobs,
async setup() {
- server.createList('job', JobsList.pageSize, { shallow: true, createAllocations: false });
+ server.createList('job', JobsList.pageSize, {
+ shallow: true,
+ createAllocations: false,
+ });
await JobsList.visit();
},
});
@@ -417,7 +494,7 @@ module('Acceptance | jobs list', function(hooks) {
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
@@ -427,11 +504,11 @@ module('Acceptance | jobs list', function(hooks) {
label,
{ facet, paramName, beforeEach, filter, expectedOptions, optionToSelect }
) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await facetOptions(assert, beforeEach, facet, expectedOptions);
});
- test(`the ${label} facet filters the jobs list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the jobs list by ${label}`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -440,7 +517,7 @@ module('Acceptance | jobs list', function(hooks) {
await option.select();
const expectedJobs = server.db.jobs
- .filter(job => filter(job, selection))
+ .filter((job) => filter(job, selection))
.sortBy('modifyIndex')
.reverse();
@@ -453,7 +530,7 @@ module('Acceptance | jobs list', function(hooks) {
});
});
- test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -468,12 +545,15 @@ module('Acceptance | jobs list', function(hooks) {
});
}
- function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+ ) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await facetOptions(assert, beforeEach, facet, expectedOptions);
});
- test(`the ${label} facet filters the jobs list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the jobs list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -484,7 +564,7 @@ module('Acceptance | jobs list', function(hooks) {
const selection = [option.key];
const expectedJobs = server.db.jobs
- .filter(job => filter(job, selection))
+ .filter((job) => filter(job, selection))
.sortBy('modifyIndex')
.reverse();
@@ -497,7 +577,7 @@ module('Acceptance | jobs list', function(hooks) {
});
});
- test(`selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -511,7 +591,7 @@ module('Acceptance | jobs list', function(hooks) {
selection.push(option2.key);
const expectedJobs = server.db.jobs
- .filter(job => filter(job, selection))
+ .filter((job) => filter(job, selection))
.sortBy('modifyIndex')
.reverse();
@@ -524,7 +604,7 @@ module('Acceptance | jobs list', function(hooks) {
});
});
- test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -543,9 +623,13 @@ module('Acceptance | jobs list', function(hooks) {
);
});
- test('the run job button works when filters are set', async function(assert) {
- ['pre-one', 'pre-two', 'pre-three'].forEach(name => {
- server.create('job', { name, createAllocations: false, childrenCount: 0 });
+ test('the run job button works when filters are set', async function (assert) {
+ ['pre-one', 'pre-two', 'pre-three'].forEach((name) => {
+ server.create('job', {
+ name,
+ createAllocations: false,
+ childrenCount: 0,
+ });
});
await JobsList.visit();
diff --git a/ui/tests/acceptance/optimize-test.js b/ui/tests/acceptance/optimize-test.js
index 0f459b8a7..ec1e291fd 100644
--- a/ui/tests/acceptance/optimize-test.js
+++ b/ui/tests/acceptance/optimize-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { currentURL, visit } from '@ember/test-helpers';
@@ -18,17 +20,18 @@ function getLatestRecommendationSubmitTimeForJob(job) {
.mapBy('tasks.models')
.reduce((tasks, taskModels) => tasks.concat(taskModels), []);
const recommendations = tasks.reduce(
- (recommendations, task) => recommendations.concat(task.recommendations.models),
+ (recommendations, task) =>
+ recommendations.concat(task.recommendations.models),
[]
);
return Math.max(...recommendations.mapBy('submitTime'));
}
-module('Acceptance | optimize', function(hooks) {
+module('Acceptance | optimize', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('feature', { name: 'Dynamic Application Sizing' });
server.create('node');
@@ -58,19 +61,19 @@ module('Acceptance | optimize', function(hooks) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await Optimize.visit();
await a11yAudit(assert);
});
- test('lets recommendations be toggled, reports the choices to the recommendations API, and displays task group recommendations serially', async function(assert) {
+ test('lets recommendations be toggled, reports the choices to the recommendations API, and displays task group recommendations serially', async function (assert) {
const currentTaskGroup = this.job1.taskGroups.models[0];
const nextTaskGroup = this.job2.taskGroups.models[0];
const currentTaskGroupHasCPURecommendation = currentTaskGroup.tasks.models
.mapBy('recommendations.models')
.flat()
- .find(r => r.resource === 'CPU');
+ .find((r) => r.resource === 'CPU');
// If no CPU recommendation, will not be able to accept recommendation with all memory recommendations turned off
@@ -96,7 +99,10 @@ module('Acceptance | optimize', function(hooks) {
`${this.job1.name} / ${currentTaskGroup.name}`
);
- assert.equal(Optimize.recommendationSummaries[0].namespace, this.job1.namespace);
+ assert.equal(
+ Optimize.recommendationSummaries[0].namespace,
+ this.job1.namespace
+ );
assert.equal(
Optimize.recommendationSummaries[1].slug,
@@ -104,15 +110,20 @@ module('Acceptance | optimize', function(hooks) {
);
const currentRecommendations = currentTaskGroup.tasks.models.reduce(
- (recommendations, task) => recommendations.concat(task.recommendations.models),
+ (recommendations, task) =>
+ recommendations.concat(task.recommendations.models),
[]
);
- const latestSubmitTime = Math.max(...currentRecommendations.mapBy('submitTime'));
+ const latestSubmitTime = Math.max(
+ ...currentRecommendations.mapBy('submitTime')
+ );
- Optimize.recommendationSummaries[0].as(summary => {
+ Optimize.recommendationSummaries[0].as((summary) => {
assert.equal(
summary.date,
- moment(new Date(latestSubmitTime / 1000000)).format('MMM DD HH:mm:ss ZZ')
+ moment(new Date(latestSubmitTime / 1000000)).format(
+ 'MMM DD HH:mm:ss ZZ'
+ )
);
const currentTaskGroupAllocations = server.schema.allocations.where({
@@ -154,23 +165,39 @@ module('Acceptance | optimize', function(hooks) {
assert.equal(
replaceMinus(summary.cpu),
- cpuDiff ? `${cpuSign}${formatHertz(cpuDiff, 'MHz')} ${cpuSign}${cpuDiffPercent}%` : ''
+ cpuDiff
+ ? `${cpuSign}${formatHertz(
+ cpuDiff,
+ 'MHz'
+ )} ${cpuSign}${cpuDiffPercent}%`
+ : ''
);
assert.equal(
replaceMinus(summary.memory),
- memDiff ? `${memSign}${formattedMemDiff(memDiff)} ${memSign}${memDiffPercent}%` : ''
+ memDiff
+ ? `${memSign}${formattedMemDiff(
+ memDiff
+ )} ${memSign}${memDiffPercent}%`
+ : ''
);
assert.equal(
replaceMinus(summary.aggregateCpu),
cpuDiff
- ? `${cpuSign}${formatHertz(cpuDiff * currentTaskGroupAllocations.length, 'MHz')}`
+ ? `${cpuSign}${formatHertz(
+ cpuDiff * currentTaskGroupAllocations.length,
+ 'MHz'
+ )}`
: ''
);
assert.equal(
replaceMinus(summary.aggregateMemory),
- memDiff ? `${memSign}${formattedMemDiff(memDiff * currentTaskGroupAllocations.length)}` : ''
+ memDiff
+ ? `${memSign}${formattedMemDiff(
+ memDiff * currentTaskGroupAllocations.length
+ )}`
+ : ''
);
});
@@ -203,7 +230,7 @@ module('Acceptance | optimize', function(hooks) {
);
const currentTaskIds = currentTaskGroup.tasks.models.mapBy('id');
- const taskIdFilter = task => currentTaskIds.includes(task.taskId);
+ const taskIdFilter = (task) => currentTaskIds.includes(task.taskId);
const cpuRecommendationIds = server.schema.recommendations
.where({ resource: 'CPU' })
@@ -215,12 +242,16 @@ module('Acceptance | optimize', function(hooks) {
.models.filter(taskIdFilter)
.mapBy('id');
- const appliedIds = toggledAnything ? cpuRecommendationIds : memoryRecommendationIds;
+ const appliedIds = toggledAnything
+ ? cpuRecommendationIds
+ : memoryRecommendationIds;
const dismissedIds = toggledAnything ? memoryRecommendationIds : [];
await Optimize.card.acceptButton.click();
- const request = server.pretender.handledRequests.filterBy('method', 'POST').pop();
+ const request = server.pretender.handledRequests
+ .filterBy('method', 'POST')
+ .pop();
const { Apply, Dismiss } = JSON.parse(request.requestBody);
assert.equal(request.url, '/v1/recommendations/apply');
@@ -234,7 +265,7 @@ module('Acceptance | optimize', function(hooks) {
assert.ok(Optimize.recommendationSummaries[1].isActive);
});
- test('can navigate between summaries via the table', async function(assert) {
+ test('can navigate between summaries via the table', async function (assert) {
server.createList('job', 10, {
createRecommendations: true,
groupsCount: 1,
@@ -252,7 +283,7 @@ module('Acceptance | optimize', function(hooks) {
assert.ok(Optimize.recommendationSummaries[1].isActive);
});
- test('can visit a summary directly via URL', async function(assert) {
+ test('can visit a summary directly via URL', async function (assert) {
server.createList('job', 10, {
createRecommendations: true,
groupsCount: 1,
@@ -263,29 +294,39 @@ module('Acceptance | optimize', function(hooks) {
await Optimize.visit();
const lastSummary =
- Optimize.recommendationSummaries[Optimize.recommendationSummaries.length - 1];
+ Optimize.recommendationSummaries[
+ Optimize.recommendationSummaries.length - 1
+ ];
const collapsedSlug = lastSummary.slug.replace(' / ', '/');
// preferable to use page object’s visitable but it encodes the slash
- await visit(`/optimize/${collapsedSlug}?namespace=${lastSummary.namespace}`);
+ await visit(
+ `/optimize/${collapsedSlug}?namespace=${lastSummary.namespace}`
+ );
assert.equal(
`${Optimize.card.slug.jobName} / ${Optimize.card.slug.groupName}`,
lastSummary.slug
);
assert.ok(lastSummary.isActive);
- assert.equal(currentURL(), `/optimize/${collapsedSlug}?namespace=${lastSummary.namespace}`);
+ assert.equal(
+ currentURL(),
+ `/optimize/${collapsedSlug}?namespace=${lastSummary.namespace}`
+ );
});
- test('when a summary is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when a summary is not found, an error message is shown, but the URL persists', async function (assert) {
await visit('/optimize/nonexistent/summary?namespace=anamespace');
- assert.equal(currentURL(), '/optimize/nonexistent/summary?namespace=anamespace');
+ assert.equal(
+ currentURL(),
+ '/optimize/nonexistent/summary?namespace=anamespace'
+ );
assert.ok(Optimize.applicationError.isPresent);
assert.equal(Optimize.applicationError.title, 'Not Found');
});
- test('cannot return to already-processed summaries', async function(assert) {
+ test('cannot return to already-processed summaries', async function (assert) {
await Optimize.visit();
await Optimize.card.acceptButton.click();
@@ -296,12 +337,12 @@ module('Acceptance | optimize', function(hooks) {
assert.ok(Optimize.recommendationSummaries[1].isActive);
});
- test('can dismiss a set of recommendations', async function(assert) {
+ test('can dismiss a set of recommendations', async function (assert) {
await Optimize.visit();
const currentTaskGroup = this.job1.taskGroups.models[0];
const currentTaskIds = currentTaskGroup.tasks.models.mapBy('id');
- const taskIdFilter = task => currentTaskIds.includes(task.taskId);
+ const taskIdFilter = (task) => currentTaskIds.includes(task.taskId);
const idsBeforeDismissal = server.schema.recommendations
.all()
@@ -310,7 +351,9 @@ module('Acceptance | optimize', function(hooks) {
await Optimize.card.dismissButton.click();
- const request = server.pretender.handledRequests.filterBy('method', 'POST').pop();
+ const request = server.pretender.handledRequests
+ .filterBy('method', 'POST')
+ .pop();
const { Apply, Dismiss } = JSON.parse(request.requestBody);
assert.equal(request.url, '/v1/recommendations/apply');
@@ -319,8 +362,8 @@ module('Acceptance | optimize', function(hooks) {
assert.deepEqual(Dismiss, idsBeforeDismissal);
});
- test('it displays an error encountered trying to save and proceeds to the next summary when the error is dismissed', async function(assert) {
- server.post('/recommendations/apply', function() {
+ test('it displays an error encountered trying to save and proceeds to the next summary when the error is dismissed', async function (assert) {
+ server.post('/recommendations/apply', function () {
return new Response(500, {}, null);
});
@@ -338,7 +381,7 @@ module('Acceptance | optimize', function(hooks) {
assert.equal(Optimize.card.slug.jobName, this.job2.name);
});
- test('it displays an empty message when there are no recommendations', async function(assert) {
+ test('it displays an empty message when there are no recommendations', async function (assert) {
server.db.recommendations.remove();
await Optimize.visit();
@@ -346,7 +389,7 @@ module('Acceptance | optimize', function(hooks) {
assert.equal(Optimize.empty.headline, 'No Recommendations');
});
- test('it displays an empty message after all recommendations have been processed', async function(assert) {
+ test('it displays an empty message after all recommendations have been processed', async function (assert) {
await Optimize.visit();
await Optimize.card.acceptButton.click();
@@ -355,7 +398,7 @@ module('Acceptance | optimize', function(hooks) {
assert.ok(Optimize.empty.isPresent);
});
- test('it redirects to jobs and hides the gutter link when the token lacks permissions', async function(assert) {
+ test('it redirects to jobs and hides the gutter link when the token lacks permissions', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await Optimize.visit();
@@ -363,7 +406,7 @@ module('Acceptance | optimize', function(hooks) {
assert.ok(Layout.gutter.optimize.isHidden);
});
- test('it reloads partially-loaded jobs', async function(assert) {
+ test('it reloads partially-loaded jobs', async function (assert) {
await JobsList.visit();
await Optimize.visit();
@@ -371,11 +414,11 @@ module('Acceptance | optimize', function(hooks) {
});
});
-module('Acceptance | optimize search and facets', function(hooks) {
+module('Acceptance | optimize search and facets', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('feature', { name: 'Dynamic Application Sizing' });
server.create('node');
@@ -388,7 +431,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- test('search field narrows summary table results, changes the active summary if it no longer matches, and displays a no matches message when there are none', async function(assert) {
+ test('search field narrows summary table results, changes the active summary if it no longer matches, and displays a no matches message when there are none', async function (assert) {
server.create('job', {
name: 'zzzzzz',
createRecommendations: true,
@@ -444,7 +487,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
assert.ok(Optimize.recommendationSummaries[0].isActive);
});
- test('the namespaces toggle doesn’t show when there aren’t namespaces', async function(assert) {
+ test('the namespaces toggle doesn’t show when there aren’t namespaces', async function (assert) {
server.db.namespaces.remove();
server.create('job', {
@@ -458,7 +501,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
assert.ok(Optimize.facets.namespace.isHidden);
});
- test('processing a summary moves to the next one in the sorted list', async function(assert) {
+ test('processing a summary moves to the next one in the sorted list', async function (assert) {
server.create('job', {
name: 'ooo111',
createRecommendations: true,
@@ -491,9 +534,10 @@ module('Acceptance | optimize search and facets', function(hooks) {
ooo222: pastSubmitTime,
};
- server.schema.recommendations.all().models.forEach(recommendation => {
+ server.schema.recommendations.all().models.forEach((recommendation) => {
const parentJob = recommendation.task.taskGroup.job;
- const submitTimeForJob = jobNameToRecommendationSubmitTime[parentJob.name];
+ const submitTimeForJob =
+ jobNameToRecommendationSubmitTime[parentJob.name];
recommendation.submitTime = submitTimeForJob;
recommendation.save();
});
@@ -505,7 +549,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
assert.equal(Optimize.card.slug.jobName, 'ooo222');
});
- test('the optimize page has appropriate faceted search options', async function(assert) {
+ test('the optimize page has appropriate faceted search options', async function (assert) {
server.createList('job', 4, {
status: 'running',
createRecommendations: true,
@@ -527,8 +571,14 @@ module('Acceptance | optimize search and facets', function(hooks) {
expectedOptions: ['All (*)', 'default', 'namespace-1'],
optionToSelect: 'namespace-1',
async beforeEach() {
- server.createList('job', 2, { namespaceId: 'default', createRecommendations: true });
- server.createList('job', 2, { namespaceId: 'namespace-1', createRecommendations: true });
+ server.createList('job', 2, {
+ namespaceId: 'default',
+ createRecommendations: true,
+ });
+ server.createList('job', 2, {
+ namespaceId: 'namespace-1',
+ createRecommendations: true,
+ });
await Optimize.visit();
},
filter(taskGroup, selection) {
@@ -629,10 +679,15 @@ module('Acceptance | optimize search and facets', function(hooks) {
groupTaskCount: 2,
childrenCount: 0,
});
- server.create('job', { datacenters: ['pdx'], createRecommendations: true, childrenCount: 0 });
+ server.create('job', {
+ datacenters: ['pdx'],
+ createRecommendations: true,
+ childrenCount: 0,
+ });
await Optimize.visit();
},
- filter: (taskGroup, selection) => taskGroup.job.datacenters.find(dc => selection.includes(dc)),
+ filter: (taskGroup, selection) =>
+ taskGroup.job.datacenters.find((dc) => selection.includes(dc)),
});
testFacet('Prefix', {
@@ -650,7 +705,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
'hashi-three',
'nmd_two',
'noprefix',
- ].forEach(name => {
+ ].forEach((name) => {
server.create('job', {
name,
createRecommendations: true,
@@ -663,7 +718,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
await Optimize.visit();
},
filter: (taskGroup, selection) =>
- selection.find(prefix => taskGroup.job.name.startsWith(prefix)),
+ selection.find((prefix) => taskGroup.job.name.startsWith(prefix)),
});
async function facetOptions(assert, beforeEach, facet, expectedOptions) {
@@ -678,7 +733,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
@@ -688,11 +743,11 @@ module('Acceptance | optimize search and facets', function(hooks) {
label,
{ facet, paramName, beforeEach, filter, expectedOptions, optionToSelect }
) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await facetOptions.call(this, assert, beforeEach, facet, expectedOptions);
});
- test(`the ${label} facet filters the jobs list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the jobs list by ${label}`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -700,13 +755,15 @@ module('Acceptance | optimize search and facets', function(hooks) {
const selection = option.key;
await option.select();
- const sortedRecommendations = server.db.recommendations.sortBy('submitTime').reverse();
+ const sortedRecommendations = server.db.recommendations
+ .sortBy('submitTime')
+ .reverse();
const recommendationTaskGroups = server.schema.tasks
.find(sortedRecommendations.mapBy('taskId').uniq())
.models.mapBy('taskGroup')
.uniqBy('id')
- .filter(group => filter(group, selection));
+ .filter((group) => filter(group, selection));
Optimize.recommendationSummaries.forEach((summary, index) => {
const group = recommendationTaskGroups[index];
@@ -714,7 +771,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
});
});
- test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -729,12 +786,15 @@ module('Acceptance | optimize search and facets', function(hooks) {
});
}
- function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+ ) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await facetOptions.call(this, assert, beforeEach, facet, expectedOptions);
});
- test(`the ${label} facet filters the recommendation summaries by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the recommendation summaries by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -745,13 +805,15 @@ module('Acceptance | optimize search and facets', function(hooks) {
const selection = [option.key];
- const sortedRecommendations = server.db.recommendations.sortBy('submitTime').reverse();
+ const sortedRecommendations = server.db.recommendations
+ .sortBy('submitTime')
+ .reverse();
const recommendationTaskGroups = server.schema.tasks
.find(sortedRecommendations.mapBy('taskId').uniq())
.models.mapBy('taskGroup')
.uniqBy('id')
- .filter(group => filter(group, selection));
+ .filter((group) => filter(group, selection));
Optimize.recommendationSummaries.forEach((summary, index) => {
const group = recommendationTaskGroups[index];
@@ -759,7 +821,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
});
});
- test(`selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -772,13 +834,15 @@ module('Acceptance | optimize search and facets', function(hooks) {
await option2.toggle();
selection.push(option2.key);
- const sortedRecommendations = server.db.recommendations.sortBy('submitTime').reverse();
+ const sortedRecommendations = server.db.recommendations
+ .sortBy('submitTime')
+ .reverse();
const recommendationTaskGroups = server.schema.tasks
.find(sortedRecommendations.mapBy('taskId').uniq())
.models.mapBy('taskGroup')
.uniqBy('id')
- .filter(group => filter(group, selection));
+ .filter((group) => filter(group, selection));
Optimize.recommendationSummaries.forEach((summary, index) => {
const group = recommendationTaskGroups[index];
@@ -786,7 +850,7 @@ module('Acceptance | optimize search and facets', function(hooks) {
});
});
- test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -799,7 +863,9 @@ module('Acceptance | optimize search and facets', function(hooks) {
await option2.toggle();
selection.push(option2.key);
- assert.ok(currentURL().includes(encodeURIComponent(JSON.stringify(selection))));
+ assert.ok(
+ currentURL().includes(encodeURIComponent(JSON.stringify(selection)))
+ );
});
}
});
diff --git a/ui/tests/acceptance/plugin-allocations-test.js b/ui/tests/acceptance/plugin-allocations-test.js
index 34a78f261..5f85c6203 100644
--- a/ui/tests/acceptance/plugin-allocations-test.js
+++ b/ui/tests/acceptance/plugin-allocations-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { module, test } from 'qunit';
import { currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
@@ -6,18 +7,18 @@ import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import pageSizeSelect from './behaviors/page-size-select';
import PluginAllocations from 'nomad-ui/tests/pages/storage/plugins/plugin/allocations';
-module('Acceptance | plugin allocations', function(hooks) {
+module('Acceptance | plugin allocations', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let plugin;
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
window.localStorage.clear();
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
@@ -29,7 +30,7 @@ module('Acceptance | plugin allocations', function(hooks) {
await a11yAudit(assert);
});
- test('/csi/plugins/:id/allocations shows all allocations in a single table', async function(assert) {
+ test('/csi/plugins/:id/allocations shows all allocations in a single table', async function (assert) {
plugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: true,
@@ -71,7 +72,8 @@ module('Acceptance | plugin allocations', function(hooks) {
await PluginAllocations.visit({ id: plugin.id });
},
- filter: (allocation, selection) => selection.includes(allocation.healthy.toString()),
+ filter: (allocation, selection) =>
+ selection.includes(allocation.healthy.toString()),
});
testFacet('Type', {
@@ -89,13 +91,14 @@ module('Acceptance | plugin allocations', function(hooks) {
},
filter: (allocation, selection) => {
if (selection.length === 0 || selection.length === 2) return true;
- if (selection[0] === 'controller') return plugin.controllers.models.includes(allocation);
+ if (selection[0] === 'controller')
+ return plugin.controllers.models.includes(allocation);
return plugin.nodes.models.includes(allocation);
},
});
function testFacet(label, { facet, paramName, beforeEach, filter }) {
- test(`the ${label} facet filters the allocations list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the allocations list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -105,9 +108,12 @@ module('Acceptance | plugin allocations', function(hooks) {
await option.toggle();
const selection = [option.key];
- const allAllocations = [...plugin.controllers.models, ...plugin.nodes.models];
+ const allAllocations = [
+ ...plugin.controllers.models,
+ ...plugin.nodes.models,
+ ];
const expectedAllocations = allAllocations
- .filter(allocation => filter(allocation, selection))
+ .filter((allocation) => filter(allocation, selection))
.sortBy('updateTime');
PluginAllocations.allocations.forEach((allocation, index) => {
@@ -115,7 +121,7 @@ module('Acceptance | plugin allocations', function(hooks) {
});
});
- test(`selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -128,9 +134,12 @@ module('Acceptance | plugin allocations', function(hooks) {
await option2.toggle();
selection.push(option2.key);
- const allAllocations = [...plugin.controllers.models, ...plugin.nodes.models];
+ const allAllocations = [
+ ...plugin.controllers.models,
+ ...plugin.nodes.models,
+ ];
const expectedAllocations = allAllocations
- .filter(allocation => filter(allocation, selection))
+ .filter((allocation) => filter(allocation, selection))
.sortBy('updateTime');
PluginAllocations.allocations.forEach((allocation, index) => {
@@ -138,7 +147,7 @@ module('Acceptance | plugin allocations', function(hooks) {
});
});
- test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
@@ -151,9 +160,14 @@ module('Acceptance | plugin allocations', function(hooks) {
await option2.toggle();
selection.push(option2.key);
- const queryString = `${paramName}=${window.encodeURIComponent(JSON.stringify(selection))}`;
+ const queryString = `${paramName}=${window.encodeURIComponent(
+ JSON.stringify(selection)
+ )}`;
- assert.equal(currentURL(), `/csi/plugins/${plugin.id}/allocations?${queryString}`);
+ assert.equal(
+ currentURL(),
+ `/csi/plugins/${plugin.id}/allocations?${queryString}`
+ );
});
}
});
diff --git a/ui/tests/acceptance/plugin-detail-test.js b/ui/tests/acceptance/plugin-detail-test.js
index 4f7a82200..fe00f8419 100644
--- a/ui/tests/acceptance/plugin-detail-test.js
+++ b/ui/tests/acceptance/plugin-detail-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { module, test } from 'qunit';
import { currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
@@ -8,23 +9,23 @@ import { formatBytes, formatHertz } from 'nomad-ui/utils/units';
import PluginDetail from 'nomad-ui/tests/pages/storage/plugins/detail';
import Layout from 'nomad-ui/tests/pages/layout';
-module('Acceptance | plugin detail', function(hooks) {
+module('Acceptance | plugin detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let plugin;
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
plugin = server.create('csi-plugin', { controllerRequired: true });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
await a11yAudit(assert);
});
- test('/csi/plugins/:id should have a breadcrumb trail linking back to Plugins and Storage', async function(assert) {
+ test('/csi/plugins/:id should have a breadcrumb trail linking back to Plugins and Storage', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
assert.equal(Layout.breadcrumbFor('csi.index').text, 'Storage');
@@ -32,19 +33,21 @@ module('Acceptance | plugin detail', function(hooks) {
assert.equal(Layout.breadcrumbFor('csi.plugins.plugin').text, plugin.id);
});
- test('/csi/plugins/:id should show the plugin name in the title', async function(assert) {
+ test('/csi/plugins/:id should show the plugin name in the title', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
assert.equal(document.title, `CSI Plugin ${plugin.id} - Nomad`);
assert.equal(PluginDetail.title, plugin.id);
});
- test('/csi/plugins/:id should list additional details for the plugin below the title', async function(assert) {
+ test('/csi/plugins/:id should list additional details for the plugin below the title', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
assert.ok(
PluginDetail.controllerHealth.includes(
- `${Math.round((plugin.controllersHealthy / plugin.controllersExpected) * 100)}%`
+ `${Math.round(
+ (plugin.controllersHealthy / plugin.controllersExpected) * 100
+ )}%`
)
);
assert.ok(
@@ -57,23 +60,33 @@ module('Acceptance | plugin detail', function(hooks) {
`${Math.round((plugin.nodesHealthy / plugin.nodesExpected) * 100)}%`
)
);
- assert.ok(PluginDetail.nodeHealth.includes(`${plugin.nodesHealthy}/${plugin.nodesExpected}`));
+ assert.ok(
+ PluginDetail.nodeHealth.includes(
+ `${plugin.nodesHealthy}/${plugin.nodesExpected}`
+ )
+ );
assert.ok(PluginDetail.provider.includes(plugin.provider));
});
- test('/csi/plugins/:id should list all the controller plugin allocations for the plugin', async function(assert) {
+ test('/csi/plugins/:id should list all the controller plugin allocations for the plugin', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
- assert.equal(PluginDetail.controllerAllocations.length, plugin.controllers.length);
+ assert.equal(
+ PluginDetail.controllerAllocations.length,
+ plugin.controllers.length
+ );
plugin.controllers.models
.sortBy('updateTime')
.reverse()
.forEach((allocation, idx) => {
- assert.equal(PluginDetail.controllerAllocations.objectAt(idx).id, allocation.allocID);
+ assert.equal(
+ PluginDetail.controllerAllocations.objectAt(idx).id,
+ allocation.allocID
+ );
});
});
- test('/csi/plugins/:id should list all the node plugin allocations for the plugin', async function(assert) {
+ test('/csi/plugins/:id should list all the node plugin allocations for the plugin', async function (assert) {
await PluginDetail.visit({ id: plugin.id });
assert.equal(PluginDetail.nodeAllocations.length, plugin.nodes.length);
@@ -81,12 +94,17 @@ module('Acceptance | plugin detail', function(hooks) {
.sortBy('updateTime')
.reverse()
.forEach((allocation, idx) => {
- assert.equal(PluginDetail.nodeAllocations.objectAt(idx).id, allocation.allocID);
+ assert.equal(
+ PluginDetail.nodeAllocations.objectAt(idx).id,
+ allocation.allocID
+ );
});
});
- test('each allocation should have high-level details for the allocation', async function(assert) {
- const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0];
+ test('each allocation should have high-level details for the allocation', async function (assert) {
+ const controller = plugin.controllers.models
+ .sortBy('updateTime')
+ .reverse()[0];
const allocation = server.db.allocations.find(controller.allocID);
const allocStats = server.db.clientAllocationStats.find(allocation.id);
const taskGroup = server.db.taskGroups.findBy({
@@ -94,14 +112,21 @@ module('Acceptance | plugin detail', function(hooks) {
jobId: allocation.jobId,
});
- const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ const tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
- const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
+ const memoryUsed = tasks.reduce(
+ (sum, task) => sum + task.resources.MemoryMB,
+ 0
+ );
await PluginDetail.visit({ id: plugin.id });
- PluginDetail.controllerAllocations.objectAt(0).as(allocationRow => {
- assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID');
+ PluginDetail.controllerAllocations.objectAt(0).as((allocationRow) => {
+ assert.equal(
+ allocationRow.shortId,
+ allocation.id.split('-')[0],
+ 'Allocation short ID'
+ );
assert.equal(
allocationRow.createTime,
moment(allocation.createTime / 1000000).format('MMM D')
@@ -110,8 +135,14 @@ module('Acceptance | plugin detail', function(hooks) {
allocationRow.createTooltip,
moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ')
);
- assert.equal(allocationRow.modifyTime, moment(allocation.modifyTime / 1000000).fromNow());
- assert.equal(allocationRow.health, controller.healthy ? 'Healthy' : 'Unhealthy');
+ assert.equal(
+ allocationRow.modifyTime,
+ moment(allocation.modifyTime / 1000000).fromNow()
+ );
+ assert.equal(
+ allocationRow.health,
+ controller.healthy ? 'Healthy' : 'Unhealthy'
+ );
assert.equal(
allocationRow.client,
server.db.nodes.find(allocation.nodeId).id.split('-')[0],
@@ -122,7 +153,11 @@ module('Acceptance | plugin detail', function(hooks) {
server.db.nodes.find(allocation.nodeId).name.substr(0, 15),
'Node Name'
);
- assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
+ assert.equal(
+ allocationRow.job,
+ server.db.jobs.find(allocation.jobId).name,
+ 'Job name'
+ );
assert.ok(allocationRow.taskGroup, 'Task group name');
assert.ok(allocationRow.jobVersion, 'Job Version');
assert.equal(
@@ -130,7 +165,9 @@ module('Acceptance | plugin detail', function(hooks) {
Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
'CPU %'
);
- const roundedTicks = Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks);
+ const roundedTicks = Math.floor(
+ allocStats.resourceUsage.CpuStats.TotalTicks
+ );
assert.equal(
allocationRow.cpuTooltip,
`${formatHertz(roundedTicks, 'MHz')} / ${formatHertz(cpuUsed, 'MHz')}`,
@@ -143,17 +180,18 @@ module('Acceptance | plugin detail', function(hooks) {
);
assert.equal(
allocationRow.memTooltip,
- `${formatBytes(allocStats.resourceUsage.MemoryStats.RSS)} / ${formatBytes(
- memoryUsed,
- 'MiB'
- )}`,
+ `${formatBytes(
+ allocStats.resourceUsage.MemoryStats.RSS
+ )} / ${formatBytes(memoryUsed, 'MiB')}`,
'Detailed memory information is in a tooltip'
);
});
});
- test('each allocation should link to the allocation detail page', async function(assert) {
- const controller = plugin.controllers.models.sortBy('updateTime').reverse()[0];
+ test('each allocation should link to the allocation detail page', async function (assert) {
+ const controller = plugin.controllers.models
+ .sortBy('updateTime')
+ .reverse()[0];
await PluginDetail.visit({ id: plugin.id });
await PluginDetail.controllerAllocations.objectAt(0).visit();
@@ -161,7 +199,7 @@ module('Acceptance | plugin detail', function(hooks) {
assert.equal(currentURL(), `/allocations/${controller.allocID}`);
});
- test('when there are no plugin allocations, the tables present empty states', async function(assert) {
+ test('when there are no plugin allocations, the tables present empty states', async function (assert) {
const emptyPlugin = server.create('csi-plugin', {
controllerRequired: true,
controllersHealthy: 0,
@@ -173,14 +211,22 @@ module('Acceptance | plugin detail', function(hooks) {
await PluginDetail.visit({ id: emptyPlugin.id });
assert.ok(PluginDetail.controllerTableIsEmpty);
- assert.equal(PluginDetail.controllerEmptyState.headline, 'No Controller Plugin Allocations');
+ assert.equal(
+ PluginDetail.controllerEmptyState.headline,
+ 'No Controller Plugin Allocations'
+ );
assert.ok(PluginDetail.nodeTableIsEmpty);
- assert.equal(PluginDetail.nodeEmptyState.headline, 'No Node Plugin Allocations');
+ assert.equal(
+ PluginDetail.nodeEmptyState.headline,
+ 'No Node Plugin Allocations'
+ );
});
- test('when the plugin is node-only, the controller information is omitted', async function(assert) {
- const nodeOnlyPlugin = server.create('csi-plugin', { controllerRequired: false });
+ test('when the plugin is node-only, the controller information is omitted', async function (assert) {
+ const nodeOnlyPlugin = server.create('csi-plugin', {
+ controllerRequired: false,
+ });
await PluginDetail.visit({ id: nodeOnlyPlugin.id });
@@ -191,7 +237,7 @@ module('Acceptance | plugin detail', function(hooks) {
assert.notOk(PluginDetail.controllerTableIsPresent);
});
- test('when there are more than 10 controller or node allocations, only 10 are shown', async function(assert) {
+ test('when there are more than 10 controller or node allocations, only 10 are shown', async function (assert) {
const manyAllocationsPlugin = server.create('csi-plugin', {
shallow: true,
controllerRequired: false,
@@ -203,12 +249,14 @@ module('Acceptance | plugin detail', function(hooks) {
assert.equal(PluginDetail.nodeAllocations.length, 10);
});
- test('the View All links under each allocation table link to a filtered view of the plugins allocation list', async function(assert) {
- const serialize = arr => window.encodeURIComponent(JSON.stringify(arr));
+ test('the View All links under each allocation table link to a filtered view of the plugins allocation list', async function (assert) {
+ const serialize = (arr) => window.encodeURIComponent(JSON.stringify(arr));
await PluginDetail.visit({ id: plugin.id });
assert.ok(
- PluginDetail.goToControllerAllocationsText.includes(plugin.controllers.models.length)
+ PluginDetail.goToControllerAllocationsText.includes(
+ plugin.controllers.models.length
+ )
);
await PluginDetail.goToControllerAllocations();
assert.equal(
@@ -217,8 +265,13 @@ module('Acceptance | plugin detail', function(hooks) {
);
await PluginDetail.visit({ id: plugin.id });
- assert.ok(PluginDetail.goToNodeAllocationsText.includes(plugin.nodes.models.length));
+ assert.ok(
+ PluginDetail.goToNodeAllocationsText.includes(plugin.nodes.models.length)
+ );
await PluginDetail.goToNodeAllocations();
- assert.equal(currentURL(), `/csi/plugins/${plugin.id}/allocations?type=${serialize(['node'])}`);
+ assert.equal(
+ currentURL(),
+ `/csi/plugins/${plugin.id}/allocations?type=${serialize(['node'])}`
+ );
});
});
diff --git a/ui/tests/acceptance/plugins-list-test.js b/ui/tests/acceptance/plugins-list-test.js
index b378f0f2e..3660ec9db 100644
--- a/ui/tests/acceptance/plugins-list-test.js
+++ b/ui/tests/acceptance/plugins-list-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -6,28 +7,28 @@ import a11yAudit from 'nomad-ui/tests/helpers/a11y-audit';
import pageSizeSelect from './behaviors/page-size-select';
import PluginsList from 'nomad-ui/tests/pages/storage/plugins/list';
-module('Acceptance | plugins list', function(hooks) {
+module('Acceptance | plugins list', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
window.localStorage.clear();
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await PluginsList.visit();
await a11yAudit(assert);
});
- test('visiting /csi/plugins', async function(assert) {
+ test('visiting /csi/plugins', async function (assert) {
await PluginsList.visit();
assert.equal(currentURL(), '/csi/plugins');
assert.equal(document.title, 'CSI Plugins - Nomad');
});
- test('/csi/plugins should list the first page of plugins sorted by id', async function(assert) {
+ test('/csi/plugins should list the first page of plugins sorted by id', async function (assert) {
const pluginCount = PluginsList.pageSize + 1;
server.createList('csi-plugin', pluginCount, { shallow: true });
@@ -40,13 +41,17 @@ module('Acceptance | plugins list', function(hooks) {
});
});
- test('each plugin row should contain information about the plugin', async function(assert) {
- const plugin = server.create('csi-plugin', { shallow: true, controllerRequired: true });
+ test('each plugin row should contain information about the plugin', async function (assert) {
+ const plugin = server.create('csi-plugin', {
+ shallow: true,
+ controllerRequired: true,
+ });
await PluginsList.visit();
const pluginRow = PluginsList.plugins.objectAt(0);
- const controllerHealthStr = plugin.controllersHealthy > 0 ? 'Healthy' : 'Unhealthy';
+ const controllerHealthStr =
+ plugin.controllersHealthy > 0 ? 'Healthy' : 'Unhealthy';
const nodeHealthStr = plugin.nodesHealthy > 0 ? 'Healthy' : 'Unhealthy';
assert.equal(pluginRow.id, plugin.id);
@@ -61,8 +66,11 @@ module('Acceptance | plugins list', function(hooks) {
assert.equal(pluginRow.provider, plugin.provider);
});
- test('node only plugins explain that there is no controller health for this plugin type', async function(assert) {
- const plugin = server.create('csi-plugin', { shallow: true, controllerRequired: false });
+ test('node only plugins explain that there is no controller health for this plugin type', async function (assert) {
+ const plugin = server.create('csi-plugin', {
+ shallow: true,
+ controllerRequired: false,
+ });
await PluginsList.visit();
@@ -78,7 +86,7 @@ module('Acceptance | plugins list', function(hooks) {
assert.equal(pluginRow.provider, plugin.provider);
});
- test('each plugin row should link to the corresponding plugin', async function(assert) {
+ test('each plugin row should link to the corresponding plugin', async function (assert) {
const plugin = server.create('csi-plugin', { shallow: true });
await PluginsList.visit();
@@ -93,14 +101,14 @@ module('Acceptance | plugins list', function(hooks) {
assert.equal(currentURL(), `/csi/plugins/${plugin.id}`);
});
- test('when there are no plugins, there is an empty message', async function(assert) {
+ test('when there are no plugins, there is an empty message', async function (assert) {
await PluginsList.visit();
assert.ok(PluginsList.isEmpty);
assert.equal(PluginsList.emptyState.headline, 'No Plugins');
});
- test('when there are plugins, but no matches for a search, there is an empty message', async function(assert) {
+ test('when there are plugins, but no matches for a search, there is an empty message', async function (assert) {
server.create('csi-plugin', { id: 'cat 1', shallow: true });
server.create('csi-plugin', { id: 'cat 2', shallow: true });
@@ -111,8 +119,10 @@ module('Acceptance | plugins list', function(hooks) {
assert.equal(PluginsList.emptyState.headline, 'No Matches');
});
- test('search resets the current page', async function(assert) {
- server.createList('csi-plugin', PluginsList.pageSize + 1, { shallow: true });
+ test('search resets the current page', async function (assert) {
+ server.createList('csi-plugin', PluginsList.pageSize + 1, {
+ shallow: true,
+ });
await PluginsList.visit();
await PluginsList.nextPage();
@@ -124,7 +134,7 @@ module('Acceptance | plugins list', function(hooks) {
assert.equal(currentURL(), '/csi/plugins?search=foobar');
});
- test('when accessing plugins is forbidden, a message is shown with a link to the tokens page', async function(assert) {
+ test('when accessing plugins is forbidden, a message is shown with a link to the tokens page', async function (assert) {
server.pretender.get('/v1/plugins', () => [403, {}, null]);
await PluginsList.visit();
diff --git a/ui/tests/acceptance/proxy-test.js b/ui/tests/acceptance/proxy-test.js
index 582a57e76..7d7a4643e 100644
--- a/ui/tests/acceptance/proxy-test.js
+++ b/ui/tests/acceptance/proxy-test.js
@@ -6,11 +6,11 @@ import Jobs from 'nomad-ui/tests/pages/jobs/list';
let managementToken;
-module('Acceptance | reverse proxy', function(hooks) {
+module('Acceptance | reverse proxy', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
window.sessionStorage.clear();
@@ -19,30 +19,34 @@ module('Acceptance | reverse proxy', function(hooks) {
// Simulate a reverse proxy injecting X-Nomad-Token header for all requests
this._originalXMLHttpRequestSend = XMLHttpRequest.prototype.send;
- (function(send) {
- XMLHttpRequest.prototype.send = function(data) {
+ (function (send) {
+ XMLHttpRequest.prototype.send = function (data) {
this.setRequestHeader('X-Nomad-Token', managementToken.secretId);
send.call(this, data);
};
})(this._originalXMLHttpRequestSend);
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
XMLHttpRequest.prototype.send = this._originalXMLHttpRequestSend;
});
- test('when token is inserted by a reverse proxy, the UI is adjusted', async function(assert) {
+ test('when token is inserted by a reverse proxy, the UI is adjusted', async function (assert) {
// when token is inserted by reserve proxy, the token is reverse proxy
const { secretId } = managementToken;
await Jobs.visit();
- assert.ok(window.localStorage.nomadTokenSecret == null, 'No token secret set');
+ assert.equal(
+ window.localStorage.nomadTokenSecret,
+ null,
+ 'No token secret set'
+ );
// Make sure that server received the header
assert.ok(
server.pretender.handledRequests
.mapBy('requestHeaders')
- .every(headers => headers['X-Nomad-Token'] === secretId),
+ .every((headers) => headers['X-Nomad-Token'] === secretId),
'The token header is always present'
);
diff --git a/ui/tests/acceptance/regions-test.js b/ui/tests/acceptance/regions-test.js
index 0e48903ff..fc3ba7026 100644
--- a/ui/tests/acceptance/regions-test.js
+++ b/ui/tests/acceptance/regions-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -9,22 +11,25 @@ import ClientsList from 'nomad-ui/tests/pages/clients/list';
import Layout from 'nomad-ui/tests/pages/layout';
import Allocation from 'nomad-ui/tests/pages/allocations/detail';
-module('Acceptance | regions (only one)', function(hooks) {
+module('Acceptance | regions (only one)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('agent');
server.create('node');
- server.createList('job', 2, { createAllocations: false, noDeployments: true });
+ server.createList('job', 2, {
+ createAllocations: false,
+ noDeployments: true,
+ });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await JobsList.visit();
await a11yAudit(assert);
});
- test('when there is only one region, the region switcher is not shown in the nav bar and the region is not in the page title', async function(assert) {
+ test('when there is only one region, the region switcher is not shown in the nav bar and the region is not in the page title', async function (assert) {
server.create('region', { id: 'global' });
await JobsList.visit();
@@ -33,7 +38,7 @@ module('Acceptance | regions (only one)', function(hooks) {
assert.equal(document.title, 'Jobs - Nomad');
});
- test('when the only region is not named "global", the region switcher still is not shown', async function(assert) {
+ test('when the only region is not named "global", the region switcher still is not shown', async function (assert) {
server.create('region', { id: 'some-region' });
await JobsList.visit();
@@ -41,7 +46,7 @@ module('Acceptance | regions (only one)', function(hooks) {
assert.notOk(Layout.navbar.regionSwitcher.isPresent, 'No region switcher');
});
- test('pages do not include the region query param', async function(assert) {
+ test('pages do not include the region query param', async function (assert) {
server.create('region', { id: 'global' });
await JobsList.visit();
@@ -55,47 +60,57 @@ module('Acceptance | regions (only one)', function(hooks) {
assert.equal(currentURL(), '/clients', 'No region query param');
});
- test('api requests do not include the region query param', async function(assert) {
+ test('api requests do not include the region query param', async function (assert) {
server.create('region', { id: 'global' });
await JobsList.visit();
await JobsList.jobs.objectAt(0).clickRow();
await Layout.gutter.visitClients();
await Layout.gutter.visitServers();
- server.pretender.handledRequests.forEach(req => {
+ server.pretender.handledRequests.forEach((req) => {
assert.notOk(req.url.includes('region='), req.url);
});
});
});
-module('Acceptance | regions (many)', function(hooks) {
+module('Acceptance | regions (many)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('agent');
server.create('node');
- server.createList('job', 2, { createAllocations: false, noDeployments: true });
+ server.createList('job', 2, {
+ createAllocations: false,
+ noDeployments: true,
+ });
server.create('allocation');
server.create('region', { id: 'global' });
server.create('region', { id: 'region-2' });
});
- test('the region switcher is rendered in the nav bar and the region is in the page title', async function(assert) {
+ test('the region switcher is rendered in the nav bar and the region is in the page title', async function (assert) {
await JobsList.visit();
- assert.ok(Layout.navbar.regionSwitcher.isPresent, 'Region switcher is shown');
+ assert.ok(
+ Layout.navbar.regionSwitcher.isPresent,
+ 'Region switcher is shown'
+ );
assert.equal(document.title, 'Jobs - global - Nomad');
});
- test('when on the default region, pages do not include the region query param', async function(assert) {
+ test('when on the default region, pages do not include the region query param', async function (assert) {
await JobsList.visit();
assert.equal(currentURL(), '/jobs', 'No region query param');
- assert.equal(window.localStorage.nomadActiveRegion, 'global', 'Region in localStorage');
+ assert.equal(
+ window.localStorage.nomadActiveRegion,
+ 'global',
+ 'Region in localStorage'
+ );
});
- test('switching regions sets localStorage and the region query param', async function(assert) {
+ test('switching regions sets localStorage and the region query param', async function (assert) {
const newRegion = server.db.regions[1].id;
await JobsList.visit();
@@ -106,10 +121,14 @@ module('Acceptance | regions (many)', function(hooks) {
currentURL().includes(`region=${newRegion}`),
'New region is the region query param value'
);
- assert.equal(window.localStorage.nomadActiveRegion, newRegion, 'New region in localStorage');
+ assert.equal(
+ window.localStorage.nomadActiveRegion,
+ newRegion,
+ 'New region in localStorage'
+ );
});
- test('switching regions to the default region, unsets the region query param', async function(assert) {
+ test('switching regions to the default region, unsets the region query param', async function (assert) {
const startingRegion = server.db.regions[1].id;
const defaultRegion = server.db.regions[0].id;
@@ -117,7 +136,10 @@ module('Acceptance | regions (many)', function(hooks) {
await selectChoose('[data-test-region-switcher-parent]', defaultRegion);
- assert.notOk(currentURL().includes('region='), 'No region query param for the default region');
+ assert.notOk(
+ currentURL().includes('region='),
+ 'No region query param for the default region'
+ );
assert.equal(
window.localStorage.nomadActiveRegion,
defaultRegion,
@@ -125,7 +147,7 @@ module('Acceptance | regions (many)', function(hooks) {
);
});
- test('switching regions on deep pages redirects to the application root', async function(assert) {
+ test('switching regions on deep pages redirects to the application root', async function (assert) {
const newRegion = server.db.regions[1].id;
await Allocation.visit({ id: server.db.allocations[0].id });
@@ -135,7 +157,7 @@ module('Acceptance | regions (many)', function(hooks) {
assert.ok(currentURL().includes('/jobs?'), 'Back at the jobs page');
});
- test('navigating directly to a page with the region query param sets the application to that region', async function(assert) {
+ test('navigating directly to a page with the region query param sets the application to that region', async function (assert) {
const allocation = server.db.allocations[0];
const region = server.db.regions[1].id;
await Allocation.visit({ id: allocation.id, region });
@@ -152,7 +174,7 @@ module('Acceptance | regions (many)', function(hooks) {
);
});
- test('when the region is not the default region, all api requests other than the agent/self request include the region query param', async function(assert) {
+ test('when the region is not the default region, all api requests other than the agent/self request include the region query param', async function (assert) {
window.localStorage.removeItem('nomadTokenSecret');
const region = server.db.regions[1].id;
@@ -182,7 +204,7 @@ module('Acceptance | regions (many)', function(hooks) {
'The default region request is made without a region qp'
);
- appRequests.forEach(req => {
+ appRequests.forEach((req) => {
if (req.url === '/v1/agent/self') {
assert.notOk(req.url.includes('region='), `(no region) ${req.url}`);
} else {
diff --git a/ui/tests/acceptance/search-test.js b/ui/tests/acceptance/search-test.js
index 635aa0ee9..78a0fbd2b 100644
--- a/ui/tests/acceptance/search-test.js
+++ b/ui/tests/acceptance/search-test.js
@@ -1,4 +1,5 @@
-/* eslint-disable ember-a11y-testing/a11y-audit-called */ // TODO
+/* eslint-disable ember-a11y-testing/a11y-audit-called */
+/* eslint-disable qunit/require-expect */
import { module, test } from 'qunit';
import { currentURL, triggerEvent, visit } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
@@ -8,11 +9,11 @@ import JobsList from 'nomad-ui/tests/pages/jobs/list';
import { selectSearch } from 'ember-power-select/test-support';
import Response from 'ember-cli-mirage/response';
-module('Acceptance | search', function(hooks) {
+module('Acceptance | search', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- test('search exposes and navigates to results from the fuzzy search endpoint', async function(assert) {
+ test('search exposes and navigates to results from the fuzzy search endpoint', async function (assert) {
server.create('node', { name: 'xyz' });
const otherNode = server.create('node', { name: 'ghi' });
@@ -29,7 +30,12 @@ module('Acceptance | search', function(hooks) {
groupsCount: 1,
groupTaskCount: 1,
});
- server.create('job', { id: 'abc', namespaceId: 'default', groupsCount: 1, groupTaskCount: 1 });
+ server.create('job', {
+ id: 'abc',
+ namespaceId: 'default',
+ groupsCount: 1,
+ groupTaskCount: 1,
+ });
const firstAllocation = server.schema.allocations.all().models[0];
const firstTaskGroup = server.schema.taskGroups.all().models[0];
@@ -40,33 +46,33 @@ module('Acceptance | search', function(hooks) {
await selectSearch(Layout.navbar.search.scope, 'xy');
- Layout.navbar.search.as(search => {
+ Layout.navbar.search.as((search) => {
assert.equal(search.groups.length, 5);
- search.groups[0].as(jobs => {
+ search.groups[0].as((jobs) => {
assert.equal(jobs.name, 'Jobs (2)');
assert.equal(jobs.options.length, 2);
assert.equal(jobs.options[0].text, 'default > vwxyz');
assert.equal(jobs.options[1].text, 'default > xyz job');
});
- search.groups[1].as(clients => {
+ search.groups[1].as((clients) => {
assert.equal(clients.name, 'Clients (1)');
assert.equal(clients.options.length, 1);
assert.equal(clients.options[0].text, 'xyz');
});
- search.groups[2].as(allocs => {
+ search.groups[2].as((allocs) => {
assert.equal(allocs.name, 'Allocations (0)');
assert.equal(allocs.options.length, 0);
});
- search.groups[3].as(groups => {
+ search.groups[3].as((groups) => {
assert.equal(groups.name, 'Task Groups (0)');
assert.equal(groups.options.length, 0);
});
- search.groups[4].as(plugins => {
+ search.groups[4].as((plugins) => {
assert.equal(plugins.name, 'CSI Plugins (1)');
assert.equal(plugins.options.length, 1);
assert.equal(plugins.options[0].text, 'xyz-plugin');
@@ -100,13 +106,16 @@ module('Acceptance | search', function(hooks) {
await Layout.navbar.search.groups[4].options[0].click();
assert.equal(currentURL(), '/csi/plugins/xyz-plugin');
- const fuzzySearchQueries = server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy');
+ const fuzzySearchQueries = server.pretender.handledRequests.filterBy(
+ 'url',
+ '/v1/search/fuzzy'
+ );
- const featureDetectionQueries = fuzzySearchQueries.filter(request =>
+ const featureDetectionQueries = fuzzySearchQueries.filter((request) =>
request.requestBody.includes('feature-detection-query')
);
- assert.ok(
+ assert.equal(
featureDetectionQueries.length,
1,
'expect the feature detection query to only run once'
@@ -121,21 +130,22 @@ module('Acceptance | search', function(hooks) {
});
});
- test('search does not perform a request when only one character has been entered', async function(assert) {
+ test('search does not perform a request when only one character has been entered', async function (assert) {
await visit('/');
await selectSearch(Layout.navbar.search.scope, 'q');
assert.ok(Layout.navbar.search.noOptionsShown);
assert.equal(
- server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy').length,
+ server.pretender.handledRequests.filterBy('url', '/v1/search/fuzzy')
+ .length,
1,
'expect the feature detection query'
);
});
- test('when fuzzy search is disabled on the server, the search control is hidden', async function(assert) {
- server.post('/search/fuzzy', function() {
+ test('when fuzzy search is disabled on the server, the search control is hidden', async function (assert) {
+ server.post('/search/fuzzy', function () {
return new Response(500, {}, '');
});
@@ -144,7 +154,7 @@ module('Acceptance | search', function(hooks) {
assert.ok(Layout.navbar.search.isHidden);
});
- test('results are truncated at 10 per group', async function(assert) {
+ test('results are truncated at 10 per group', async function (assert) {
server.create('node', { name: 'xyz' });
for (let i = 0; i < 11; i++) {
@@ -155,15 +165,15 @@ module('Acceptance | search', function(hooks) {
await selectSearch(Layout.navbar.search.scope, 'job');
- Layout.navbar.search.as(search => {
- search.groups[0].as(jobs => {
+ Layout.navbar.search.as((search) => {
+ search.groups[0].as((jobs) => {
assert.equal(jobs.name, 'Jobs (showing 10 of 11)');
assert.equal(jobs.options.length, 10);
});
});
});
- test('server-side truncation is indicated in the group label', async function(assert) {
+ test('server-side truncation is indicated in the group label', async function (assert) {
server.create('node', { name: 'xyz' });
for (let i = 0; i < 21; i++) {
@@ -174,14 +184,14 @@ module('Acceptance | search', function(hooks) {
await selectSearch(Layout.navbar.search.scope, 'job');
- Layout.navbar.search.as(search => {
- search.groups[0].as(jobs => {
+ Layout.navbar.search.as((search) => {
+ search.groups[0].as((jobs) => {
assert.equal(jobs.name, 'Jobs (showing 10 of 20+)');
});
});
});
- test('clicking the search field starts search immediately', async function(assert) {
+ test('clicking the search field starts search immediately', async function (assert) {
await visit('/');
assert.notOk(Layout.navbar.search.field.isPresent);
@@ -191,7 +201,7 @@ module('Acceptance | search', function(hooks) {
assert.ok(Layout.navbar.search.field.isPresent);
});
- test('pressing slash starts a search', async function(assert) {
+ test('pressing slash starts a search', async function (assert) {
await visit('/');
assert.notOk(Layout.navbar.search.field.isPresent);
@@ -201,7 +211,7 @@ module('Acceptance | search', function(hooks) {
assert.ok(Layout.navbar.search.field.isPresent);
});
- test('pressing slash when an input element is focused does not start a search', async function(assert) {
+ test('pressing slash when an input element is focused does not start a search', async function (assert) {
server.create('node');
server.create('job');
diff --git a/ui/tests/acceptance/server-detail-test.js b/ui/tests/acceptance/server-detail-test.js
index 507d83fb8..ef8b761f5 100644
--- a/ui/tests/acceptance/server-detail-test.js
+++ b/ui/tests/acceptance/server-detail-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -8,41 +9,43 @@ import formatHost from 'nomad-ui/utils/format-host';
let agent;
-module('Acceptance | server detail', function(hooks) {
+module('Acceptance | server detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.createList('agent', 3);
agent = server.db.agents[0];
await ServerDetail.visit({ name: agent.name });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await a11yAudit(assert);
});
- test('visiting /servers/:server_name', async function(assert) {
+ test('visiting /servers/:server_name', async function (assert) {
assert.equal(currentURL(), `/servers/${encodeURIComponent(agent.name)}`);
assert.equal(document.title, `Server ${agent.name} - Nomad`);
});
- test('when the server is the leader, the title shows a leader badge', async function(assert) {
+ test('when the server is the leader, the title shows a leader badge', async function (assert) {
assert.ok(ServerDetail.title.includes(agent.name));
assert.ok(ServerDetail.hasLeaderBadge);
});
- test('the details ribbon displays basic information about the server', async function(assert) {
+ test('the details ribbon displays basic information about the server', async function (assert) {
assert.ok(ServerDetail.serverStatus.includes(agent.member.Status));
assert.ok(
- ServerDetail.address.includes(formatHost(agent.member.Address, agent.member.Tags.port))
+ ServerDetail.address.includes(
+ formatHost(agent.member.Address, agent.member.Tags.port)
+ )
);
assert.ok(ServerDetail.datacenter.includes(agent.member.Tags.dc));
});
- test('the server detail page should list all tags for the server', async function(assert) {
+ test('the server detail page should list all tags for the server', async function (assert) {
const tags = Object.keys(agent.member.Tags)
- .map(name => ({ name, value: agent.member.Tags[name] }))
+ .map((name) => ({ name, value: agent.member.Tags[name] }))
.sortBy('name');
assert.equal(ServerDetail.tags.length, tags.length, '# of tags');
@@ -53,15 +56,23 @@ module('Acceptance | server detail', function(hooks) {
});
});
- test('when the server is not the leader, there is no leader badge', async function(assert) {
+ test('when the server is not the leader, there is no leader badge', async function (assert) {
await ServerDetail.visit({ name: server.db.agents[1].name });
assert.notOk(ServerDetail.hasLeaderBadge);
});
- test('when the server is not found, an error message is shown, but the URL persists', async function(assert) {
+ test('when the server is not found, an error message is shown, but the URL persists', async function (assert) {
await ServerDetail.visit({ name: 'not-a-real-server' });
- assert.equal(currentURL(), '/servers/not-a-real-server', 'The URL persists');
- assert.equal(ServerDetail.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ currentURL(),
+ '/servers/not-a-real-server',
+ 'The URL persists'
+ );
+ assert.equal(
+ ServerDetail.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
});
diff --git a/ui/tests/acceptance/server-monitor-test.js b/ui/tests/acceptance/server-monitor-test.js
index 0f6aeed3e..dc3b755e7 100644
--- a/ui/tests/acceptance/server-monitor-test.js
+++ b/ui/tests/acceptance/server-monitor-test.js
@@ -11,11 +11,11 @@ let agent;
let managementToken;
let clientToken;
-module('Acceptance | server monitor', function(hooks) {
+module('Acceptance | server monitor', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
agent = server.create('agent');
managementToken = server.create('token');
@@ -26,28 +26,33 @@ module('Acceptance | server monitor', function(hooks) {
run.later(run, run.cancelTimers, 500);
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await ServerMonitor.visit({ name: agent.name });
await a11yAudit(assert);
});
- test('/servers/:id/monitor should have a breadcrumb trail linking back to servers', async function(assert) {
+ test('/servers/:id/monitor should have a breadcrumb trail linking back to servers', async function (assert) {
await ServerMonitor.visit({ name: agent.name });
assert.equal(
Layout.breadcrumbFor('servers.index').text,
'Servers',
'The page should read the breadcrumb Servers'
);
- assert.equal(Layout.breadcrumbFor('servers.server').text, `Server ${agent.name}`);
+ assert.equal(
+ Layout.breadcrumbFor('servers.server').text,
+ `Server ${agent.name}`
+ );
await Layout.breadcrumbFor('servers.index').visit();
assert.equal(currentURL(), '/servers');
});
- test('the monitor page immediately streams agent monitor output at the info level', async function(assert) {
+ test('the monitor page immediately streams agent monitor output at the info level', async function (assert) {
await ServerMonitor.visit({ name: agent.name });
- const logRequest = server.pretender.handledRequests.find(req =>
+ const logRequest = server.pretender.handledRequests.find((req) =>
req.url.startsWith('/v1/agent/monitor')
);
assert.ok(ServerMonitor.logsArePresent);
@@ -55,13 +60,13 @@ module('Acceptance | server monitor', function(hooks) {
assert.ok(logRequest.url.includes('log_level=info'));
});
- test('switching the log level persists the new log level as a query param', async function(assert) {
+ test('switching the log level persists the new log level as a query param', async function (assert) {
await ServerMonitor.visit({ name: agent.name });
await ServerMonitor.selectLogLevel('Debug');
assert.equal(currentURL(), `/servers/${agent.name}/monitor?level=debug`);
});
- test('when the current access token does not include the agent:read rule, a descriptive error message is shown', async function(assert) {
+ test('when the current access token does not include the agent:read rule, a descriptive error message is shown', async function (assert) {
window.localStorage.nomadTokenSecret = clientToken.secretId;
await ServerMonitor.visit({ name: agent.name });
diff --git a/ui/tests/acceptance/servers-list-test.js b/ui/tests/acceptance/servers-list-test.js
index 05ac3f327..6c6a12abb 100644
--- a/ui/tests/acceptance/servers-list-test.js
+++ b/ui/tests/acceptance/servers-list-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -12,7 +13,7 @@ const minimumSetup = () => {
server.createList('agent', 1);
};
-const agentSort = leader => (a, b) => {
+const agentSort = (leader) => (a, b) => {
if (formatHost(a.member.Address, a.member.Tags.port) === leader) {
return 1;
} else if (formatHost(b.member.Address, b.member.Tags.port) === leader) {
@@ -21,17 +22,17 @@ const agentSort = leader => (a, b) => {
return 0;
};
-module('Acceptance | servers list', function(hooks) {
+module('Acceptance | servers list', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
minimumSetup();
await ServersList.visit();
await a11yAudit(assert);
});
- test('/servers should list all servers', async function(assert) {
+ test('/servers should list all servers', async function (assert) {
server.createList('node', 1);
server.createList('agent', 10);
@@ -40,16 +41,24 @@ module('Acceptance | servers list', function(hooks) {
await ServersList.visit();
- assert.equal(ServersList.servers.length, ServersList.pageSize, 'List is stopped at pageSize');
+ assert.equal(
+ ServersList.servers.length,
+ ServersList.pageSize,
+ 'List is stopped at pageSize'
+ );
ServersList.servers.forEach((server, index) => {
- assert.equal(server.name, sortedAgents[index].name, 'Servers are ordered');
+ assert.equal(
+ server.name,
+ sortedAgents[index].name,
+ 'Servers are ordered'
+ );
});
assert.equal(document.title, 'Servers - Nomad');
});
- test('each server should show high-level info of the server', async function(assert) {
+ test('each server should show high-level info of the server', async function (assert) {
minimumSetup();
const agent = server.db.agents[0];
@@ -66,17 +75,21 @@ module('Acceptance | servers list', function(hooks) {
assert.equal(agentRow.version, agent.version, 'Version');
});
- test('each server should link to the server detail page', async function(assert) {
+ test('each server should link to the server detail page', async function (assert) {
minimumSetup();
const agent = server.db.agents[0];
await ServersList.visit();
await ServersList.servers.objectAt(0).clickRow();
- assert.equal(currentURL(), `/servers/${agent.name}`, 'Now at the server detail page');
+ assert.equal(
+ currentURL(),
+ `/servers/${agent.name}`,
+ 'Now at the server detail page'
+ );
});
- test('when accessing servers is forbidden, show a message with a link to the tokens page', async function(assert) {
+ test('when accessing servers is forbidden, show a message with a link to the tokens page', async function (assert) {
server.create('agent');
server.pretender.get('/v1/agent/members', () => [403, {}, null]);
diff --git a/ui/tests/acceptance/task-detail-test.js b/ui/tests/acceptance/task-detail-test.js
index becc9c212..b9adbb3d0 100644
--- a/ui/tests/acceptance/task-detail-test.js
+++ b/ui/tests/acceptance/task-detail-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL, waitFor } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -10,38 +11,49 @@ import moment from 'moment';
let allocation;
let task;
-module('Acceptance | task detail', function(hooks) {
+module('Acceptance | task detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node');
server.create('job', { createAllocations: false });
- allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'running' });
+ allocation = server.create('allocation', 'withTaskWithPorts', {
+ clientStatus: 'running',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
await Task.visit({ id: allocation.id, name: task.name });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await a11yAudit(assert);
});
- test('/allocation/:id/:task_name should name the task and list high-level task information', async function(assert) {
+ test('/allocation/:id/:task_name should name the task and list high-level task information', async function (assert) {
assert.ok(Task.title.text.includes(task.name), 'Task name');
assert.ok(Task.state.includes(task.state), 'Task state');
assert.ok(
- Task.startedAt.includes(moment(task.startedAt).format("MMM DD, 'YY HH:mm:ss ZZ")),
+ Task.startedAt.includes(
+ moment(task.startedAt).format("MMM DD, 'YY HH:mm:ss ZZ")
+ ),
'Task started at'
);
const lifecycle = server.db.tasks.where({ name: task.name })[0].Lifecycle;
let lifecycleName = 'main';
- if (lifecycle && (lifecycle.Hook === 'prestart' || lifecycle.Hook === 'poststart')) {
- lifecycleName = `${lifecycle.Hook}-${lifecycle.Sidecar ? 'sidecar' : 'ephemeral'}`;
+ if (
+ lifecycle &&
+ (lifecycle.Hook === 'prestart' || lifecycle.Hook === 'poststart')
+ ) {
+ lifecycleName = `${lifecycle.Hook}-${
+ lifecycle.Sidecar ? 'sidecar' : 'ephemeral'
+ }`;
}
if (lifecycle && lifecycle.Hook === 'poststop') {
lifecycleName = 'poststop';
@@ -52,12 +64,16 @@ module('Acceptance | task detail', function(hooks) {
assert.equal(document.title, `Task ${task.name} - Nomad`);
});
- test('breadcrumbs match jobs / job / task group / allocation / task', async function(assert) {
+ test('breadcrumbs match jobs / job / task group / allocation / task', async function (assert) {
const { jobId, taskGroup } = allocation;
const job = server.db.jobs.find(jobId);
const shortId = allocation.id.split('-')[0];
- assert.equal(Layout.breadcrumbFor('jobs.index').text, 'Jobs', 'Jobs is the first breadcrumb');
+ assert.equal(
+ Layout.breadcrumbFor('jobs.index').text,
+ 'Jobs',
+ 'Jobs is the first breadcrumb'
+ );
await waitFor('[data-test-job-breadcrumb]');
assert.equal(
@@ -86,7 +102,11 @@ module('Acceptance | task detail', function(hooks) {
await Task.visit({ id: allocation.id, name: task.name });
await Layout.breadcrumbFor('jobs.job.index').visit();
- assert.equal(currentURL(), `/jobs/${job.id}`, 'Job breadcrumb links correctly');
+ assert.equal(
+ currentURL(),
+ `/jobs/${job.id}`,
+ 'Job breadcrumb links correctly'
+ );
await Task.visit({ id: allocation.id, name: task.name });
await Layout.breadcrumbFor('jobs.job.task-group').visit();
@@ -105,57 +125,85 @@ module('Acceptance | task detail', function(hooks) {
);
});
- test('/allocation/:id/:task_name should include resource utilization graphs', async function(assert) {
- assert.equal(Task.resourceCharts.length, 2, 'Two resource utilization graphs');
- assert.equal(Task.resourceCharts.objectAt(0).name, 'CPU', 'First chart is CPU');
- assert.equal(Task.resourceCharts.objectAt(1).name, 'Memory', 'Second chart is Memory');
+ test('/allocation/:id/:task_name should include resource utilization graphs', async function (assert) {
+ assert.equal(
+ Task.resourceCharts.length,
+ 2,
+ 'Two resource utilization graphs'
+ );
+ assert.equal(
+ Task.resourceCharts.objectAt(0).name,
+ 'CPU',
+ 'First chart is CPU'
+ );
+ assert.equal(
+ Task.resourceCharts.objectAt(1).name,
+ 'Memory',
+ 'Second chart is Memory'
+ );
});
- test('the events table lists all recent events', async function(assert) {
+ test('the events table lists all recent events', async function (assert) {
const events = server.db.taskEvents.where({ taskStateId: task.id });
- assert.equal(Task.events.length, events.length, `Lists ${events.length} events`);
+ assert.equal(
+ Task.events.length,
+ events.length,
+ `Lists ${events.length} events`
+ );
});
- test('when a task has volumes, the volumes table is shown', async function(assert) {
+ test('when a task has volumes, the volumes table is shown', async function (assert) {
const taskGroup = server.schema.taskGroups.where({
jobId: allocation.jobId,
name: allocation.taskGroup,
}).models[0];
- const jobTask = taskGroup.tasks.models.find(m => m.name === task.name);
+ const jobTask = taskGroup.tasks.models.find((m) => m.name === task.name);
assert.ok(Task.hasVolumes);
assert.equal(Task.volumes.length, jobTask.volumeMounts.length);
});
- test('when a task does not have volumes, the volumes table is not shown', async function(assert) {
- const job = server.create('job', { createAllocations: false, noHostVolumes: true });
- allocation = server.create('allocation', { jobId: job.id, clientStatus: 'running' });
+ test('when a task does not have volumes, the volumes table is not shown', async function (assert) {
+ const job = server.create('job', {
+ createAllocations: false,
+ noHostVolumes: true,
+ });
+ allocation = server.create('allocation', {
+ jobId: job.id,
+ clientStatus: 'running',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
await Task.visit({ id: allocation.id, name: task.name });
assert.notOk(Task.hasVolumes);
});
- test('each volume in the volumes table shows information about the volume', async function(assert) {
+ test('each volume in the volumes table shows information about the volume', async function (assert) {
const taskGroup = server.schema.taskGroups.where({
jobId: allocation.jobId,
name: allocation.taskGroup,
}).models[0];
- const jobTask = taskGroup.tasks.models.find(m => m.name === task.name);
+ const jobTask = taskGroup.tasks.models.find((m) => m.name === task.name);
const volume = jobTask.volumeMounts[0];
- Task.volumes[0].as(volumeRow => {
+ Task.volumes[0].as((volumeRow) => {
assert.equal(volumeRow.name, volume.Volume);
assert.equal(volumeRow.destination, volume.Destination);
- assert.equal(volumeRow.permissions, volume.ReadOnly ? 'Read' : 'Read/Write');
- assert.equal(volumeRow.clientSource, taskGroup.volumes[volume.Volume].Source);
+ assert.equal(
+ volumeRow.permissions,
+ volume.ReadOnly ? 'Read' : 'Read/Write'
+ );
+ assert.equal(
+ volumeRow.clientSource,
+ taskGroup.volumes[volume.Volume].Source
+ );
});
});
- test('each recent event should list the time, type, and description of the event', async function(assert) {
+ test('each recent event should list the time, type, and description of the event', async function (assert) {
const event = server.db.taskEvents.where({ taskStateId: task.id })[0];
const recentEvent = Task.events.objectAt(Task.events.length - 1);
@@ -168,12 +216,12 @@ module('Acceptance | task detail', function(hooks) {
assert.equal(recentEvent.message, event.displayMessage, 'Event message');
});
- test('when the allocation is not found, the application errors', async function(assert) {
+ test('when the allocation is not found, the application errors', async function (assert) {
await Task.visit({ id: 'not-a-real-allocation', name: task.name });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/allocation/not-a-real-allocation',
'A request to the nonexistent allocation is made'
@@ -187,7 +235,7 @@ module('Acceptance | task detail', function(hooks) {
assert.equal(Task.error.title, 'Not Found', 'Error message is for 404');
});
- test('when the allocation is found but the task is not, the application errors', async function(assert) {
+ test('when the allocation is found but the task is not, the application errors', async function (assert) {
await Task.visit({ id: allocation.id, name: 'not-a-real-task-name' });
assert.ok(
@@ -206,7 +254,7 @@ module('Acceptance | task detail', function(hooks) {
assert.equal(Task.error.title, 'Not Found', 'Error message is for 404');
});
- test('task can be restarted', async function(assert) {
+ test('task can be restarted', async function (assert) {
await Task.restart.idle();
await Task.restart.confirm();
@@ -224,14 +272,21 @@ module('Acceptance | task detail', function(hooks) {
);
});
- test('when task restart fails (403), an ACL permissions error message is shown', async function(assert) {
- server.pretender.put('/v1/client/allocation/:id/restart', () => [403, {}, '']);
+ test('when task restart fails (403), an ACL permissions error message is shown', async function (assert) {
+ server.pretender.put('/v1/client/allocation/:id/restart', () => [
+ 403,
+ {},
+ '',
+ ]);
await Task.restart.idle();
await Task.restart.confirm();
assert.ok(Task.inlineError.isShown, 'Inline error is shown');
- assert.ok(Task.inlineError.title.includes('Could Not Restart Task'), 'Title is descriptive');
+ assert.ok(
+ Task.inlineError.title.includes('Could Not Restart Task'),
+ 'Title is descriptive'
+ );
assert.ok(
/ACL token.+?allocation lifecycle/.test(Task.inlineError.message),
'Message mentions ACLs and the appropriate permission'
@@ -242,9 +297,13 @@ module('Acceptance | task detail', function(hooks) {
assert.notOk(Task.inlineError.isShown, 'Inline error is no longer shown');
});
- test('when task restart fails (500), the error message from the API is piped through to the alert', async function(assert) {
+ test('when task restart fails (500), the error message from the API is piped through to the alert', async function (assert) {
const message = 'A plaintext error message';
- server.pretender.put('/v1/client/allocation/:id/restart', () => [500, {}, message]);
+ server.pretender.put('/v1/client/allocation/:id/restart', () => [
+ 500,
+ {},
+ message,
+ ]);
await Task.restart.idle();
await Task.restart.confirm();
@@ -258,48 +317,59 @@ module('Acceptance | task detail', function(hooks) {
assert.notOk(Task.inlineError.isShown);
});
- test('exec button is present', async function(assert) {
+ test('exec button is present', async function (assert) {
assert.ok(Task.execButton.isPresent);
});
});
-module('Acceptance | task detail (no addresses)', function(hooks) {
+module('Acceptance | task detail (no addresses)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node');
server.create('job');
- allocation = server.create('allocation', 'withoutTaskWithPorts', { clientStatus: 'running' });
+ allocation = server.create('allocation', 'withoutTaskWithPorts', {
+ clientStatus: 'running',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
await Task.visit({ id: allocation.id, name: task.name });
});
});
-module('Acceptance | task detail (different namespace)', function(hooks) {
+module('Acceptance | task detail (different namespace)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node');
server.create('namespace');
server.create('namespace', { id: 'other-namespace' });
- server.create('job', { createAllocations: false, namespaceId: 'other-namespace' });
- allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'running' });
+ server.create('job', {
+ createAllocations: false,
+ namespaceId: 'other-namespace',
+ });
+ allocation = server.create('allocation', 'withTaskWithPorts', {
+ clientStatus: 'running',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
await Task.visit({ id: allocation.id, name: task.name });
});
- test('breadcrumbs match jobs / job / task group / allocation / task', async function(assert) {
+ test('breadcrumbs match jobs / job / task group / allocation / task', async function (assert) {
const { jobId, taskGroup } = allocation;
const job = server.db.jobs.find(jobId);
await Layout.breadcrumbFor('jobs.index').visit();
- assert.equal(currentURL(), '/jobs?namespace=*', 'Jobs breadcrumb links correctly');
+ assert.equal(
+ currentURL(),
+ '/jobs?namespace=*',
+ 'Jobs breadcrumb links correctly'
+ );
await Task.visit({ id: allocation.id, name: task.name });
await Layout.breadcrumbFor('jobs.job.index').visit();
@@ -327,41 +397,52 @@ module('Acceptance | task detail (different namespace)', function(hooks) {
});
});
-module('Acceptance | task detail (not running)', function(hooks) {
+module('Acceptance | task detail (not running)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node');
server.create('namespace');
server.create('namespace', { id: 'other-namespace' });
- server.create('job', { createAllocations: false, namespaceId: 'other-namespace' });
- allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'complete' });
+ server.create('job', {
+ createAllocations: false,
+ namespaceId: 'other-namespace',
+ });
+ allocation = server.create('allocation', 'withTaskWithPorts', {
+ clientStatus: 'complete',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
await Task.visit({ id: allocation.id, name: task.name });
});
- test('when the allocation for a task is not running, the resource utilization graphs are replaced by an empty message', async function(assert) {
+ test('when the allocation for a task is not running, the resource utilization graphs are replaced by an empty message', async function (assert) {
assert.equal(Task.resourceCharts.length, 0, 'No resource charts');
- assert.equal(Task.resourceEmptyMessage, "Task isn't running", 'Empty message is appropriate');
+ assert.equal(
+ Task.resourceEmptyMessage,
+ "Task isn't running",
+ 'Empty message is appropriate'
+ );
});
- test('exec button is absent', async function(assert) {
+ test('exec button is absent', async function (assert) {
assert.notOk(Task.execButton.isPresent);
});
});
-module('Acceptance | proxy task detail', function(hooks) {
+module('Acceptance | proxy task detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node');
server.create('job', { createAllocations: false });
- allocation = server.create('allocation', 'withTaskWithPorts', { clientStatus: 'running' });
+ allocation = server.create('allocation', 'withTaskWithPorts', {
+ clientStatus: 'running',
+ });
const taskState = allocation.taskStates.models[0];
const task = server.schema.tasks.findBy({ name: taskState.name });
@@ -371,7 +452,7 @@ module('Acceptance | proxy task detail', function(hooks) {
await Task.visit({ id: allocation.id, name: taskState.name });
});
- test('a proxy tag is shown', async function(assert) {
+ test('a proxy tag is shown', async function (assert) {
assert.ok(Task.title.proxyTag.isPresent);
});
});
diff --git a/ui/tests/acceptance/task-fs-test.js b/ui/tests/acceptance/task-fs-test.js
index 9737e8060..4af319090 100644
--- a/ui/tests/acceptance/task-fs-test.js
+++ b/ui/tests/acceptance/task-fs-test.js
@@ -10,17 +10,21 @@ let allocation;
let task;
let files, taskDirectory, directory, nestedDirectory;
-module('Acceptance | task fs', function(hooks) {
+module('Acceptance | task fs', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node', 'forceIPv4');
const job = server.create('job', { createAllocations: false });
- allocation = server.create('allocation', { jobId: job.id, clientStatus: 'running' });
- task = server.schema.taskStates.where({ allocationId: allocation.id }).models[0];
+ allocation = server.create('allocation', {
+ jobId: job.id,
+ clientStatus: 'running',
+ });
+ task = server.schema.taskStates.where({ allocationId: allocation.id })
+ .models[0];
task.name = 'task-name';
task.save();
@@ -30,7 +34,10 @@ module('Acceptance | task fs', function(hooks) {
// Reset files
files = [];
- taskDirectory = server.create('allocFile', { isDir: true, name: task.name });
+ taskDirectory = server.create('allocFile', {
+ isDir: true,
+ name: task.name,
+ });
files.push(taskDirectory);
// Nested files
@@ -57,10 +64,24 @@ module('Acceptance | task fs', function(hooks) {
);
files.push(
- server.create('allocFile', { isDir: true, name: 'empty-directory', parent: taskDirectory })
+ server.create('allocFile', {
+ isDir: true,
+ name: 'empty-directory',
+ parent: taskDirectory,
+ })
+ );
+ files.push(
+ server.create('allocFile', 'file', {
+ fileType: 'txt',
+ parent: taskDirectory,
+ })
+ );
+ files.push(
+ server.create('allocFile', 'file', {
+ fileType: 'txt',
+ parent: taskDirectory,
+ })
);
- files.push(server.create('allocFile', 'file', { fileType: 'txt', parent: taskDirectory }));
- files.push(server.create('allocFile', 'file', { fileType: 'txt', parent: taskDirectory }));
this.files = files;
this.directory = directory;
@@ -68,8 +89,12 @@ module('Acceptance | task fs', function(hooks) {
});
browseFilesystem({
- visitSegments: ({ allocation, task }) => ({ id: allocation.id, name: task.name }),
- getExpectedPathBase: ({ allocation, task }) => `/allocations/${allocation.id}/${task.name}/fs/`,
+ visitSegments: ({ allocation, task }) => ({
+ id: allocation.id,
+ name: task.name,
+ }),
+ getExpectedPathBase: ({ allocation, task }) =>
+ `/allocations/${allocation.id}/${task.name}/fs/`,
getTitleComponent: ({ task }) => `Task ${task.name} filesystem`,
getBreadcrumbComponent: ({ task }) => task.name,
getFilesystemRoot: ({ task }) => task.name,
diff --git a/ui/tests/acceptance/task-group-detail-test.js b/ui/tests/acceptance/task-group-detail-test.js
index 1b76705fe..c07e0c477 100644
--- a/ui/tests/acceptance/task-group-detail-test.js
+++ b/ui/tests/acceptance/task-group-detail-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { currentURL, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -22,11 +24,11 @@ let managementToken;
const sum = (total, n) => total + n;
-module('Acceptance | task group detail', function(hooks) {
+module('Acceptance | task group detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node', 'forceIPv4');
@@ -38,7 +40,7 @@ module('Acceptance | task group detail', function(hooks) {
const taskGroups = server.db.taskGroups.where({ jobId: job.id });
taskGroup = taskGroups[0];
- tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
server.create('node', 'forceIPv4');
@@ -57,7 +59,7 @@ module('Acceptance | task group detail', function(hooks) {
});
// Set a static name to make the search test deterministic
- server.db.allocations.forEach(alloc => {
+ server.db.allocations.forEach((alloc) => {
alloc.name = 'aaaaa';
});
@@ -74,16 +76,16 @@ module('Acceptance | task group detail', function(hooks) {
window.localStorage.clear();
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
await a11yAudit(assert);
});
- test('/jobs/:id/:task-group should list high-level metrics for the allocation', async function(assert) {
+ test('/jobs/:id/:task-group should list high-level metrics for the allocation', async function (assert) {
const totalCPU = tasks.mapBy('resources.CPU').reduce(sum, 0);
const totalMemory = tasks.mapBy('resources.MemoryMB').reduce(sum, 0);
const totalMemoryMax = tasks
- .map(t => t.resources.MemoryMaxMB || t.resources.MemoryMB)
+ .map((t) => t.resources.MemoryMaxMB || t.resources.MemoryMB)
.reduce(sum, 0);
const totalDisk = taskGroup.ephemeralDisk.SizeMB;
@@ -99,12 +101,18 @@ module('Acceptance | task group detail', function(hooks) {
let totalMemoryMaxAddendum = '';
if (totalMemoryMax > totalMemory) {
- totalMemoryMaxAddendum = ` (${formatScheduledBytes(totalMemoryMax, 'MiB')} Max)`;
+ totalMemoryMaxAddendum = ` (${formatScheduledBytes(
+ totalMemoryMax,
+ 'MiB'
+ )} Max)`;
}
assert.equal(
TaskGroup.mem,
- `Reserved Memory ${formatScheduledBytes(totalMemory, 'MiB')}${totalMemoryMaxAddendum}`,
+ `Reserved Memory ${formatScheduledBytes(
+ totalMemory,
+ 'MiB'
+ )}${totalMemoryMaxAddendum}`,
'Aggregated Memory reservation for all tasks'
);
assert.equal(
@@ -113,13 +121,20 @@ module('Acceptance | task group detail', function(hooks) {
'Aggregated Disk reservation for all tasks'
);
- assert.equal(document.title, `Task group ${taskGroup.name} - Job ${job.name} - Nomad`);
+ assert.equal(
+ document.title,
+ `Task group ${taskGroup.name} - Job ${job.name} - Nomad`
+ );
});
- test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', async function(assert) {
+ test('/jobs/:id/:task-group should have breadcrumbs for job and jobs', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
- assert.equal(Layout.breadcrumbFor('jobs.index').text, 'Jobs', 'First breadcrumb says jobs');
+ assert.equal(
+ Layout.breadcrumbFor('jobs.index').text,
+ 'Jobs',
+ 'First breadcrumb says jobs'
+ );
assert.equal(
Layout.breadcrumbFor('jobs.job.index').text,
`Job ${job.name}`,
@@ -132,14 +147,14 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('/jobs/:id/:task-group first breadcrumb should link to jobs', async function(assert) {
+ test('/jobs/:id/:task-group first breadcrumb should link to jobs', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
await Layout.breadcrumbFor('jobs.index').visit();
assert.equal(currentURL(), '/jobs', 'First breadcrumb links back to jobs');
});
- test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', async function(assert) {
+ test('/jobs/:id/:task-group second breadcrumb should link to the job for the task group', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
await Layout.breadcrumbFor('jobs.job.index').visit();
@@ -150,7 +165,7 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('when the user has a client token that has a namespace with a policy to run and scale a job the autoscaler options should be available', async function(assert) {
+ test('when the user has a client token that has a namespace with a policy to run and scale a job the autoscaler options should be available', async function (assert) {
window.localStorage.clear();
const SCALE_AND_WRITE_NAMESPACE = 'scale-and-write-namespace';
@@ -158,7 +173,9 @@ module('Acceptance | task group detail', function(hooks) {
const clientToken = server.create('token');
server.create('namespace', { id: SCALE_AND_WRITE_NAMESPACE });
- const secondNamespace = server.create('namespace', { id: READ_ONLY_NAMESPACE });
+ const secondNamespace = server.create('namespace', {
+ id: READ_ONLY_NAMESPACE,
+ });
job = server.create('job', {
groupCount: 0,
@@ -220,7 +237,10 @@ module('Acceptance | task group detail', function(hooks) {
namespace: SCALE_AND_WRITE_NAMESPACE,
});
- assert.equal(currentURL(), `/jobs/${job.id}/scaling?namespace=${SCALE_AND_WRITE_NAMESPACE}`);
+ assert.equal(
+ currentURL(),
+ `/jobs/${job.id}/scaling?namespace=${SCALE_AND_WRITE_NAMESPACE}`
+ );
assert.notOk(TaskGroup.countStepper.increment.isDisabled);
await TaskGroup.visit({
@@ -228,11 +248,14 @@ module('Acceptance | task group detail', function(hooks) {
name: scalingGroup2.name,
namespace: secondNamespace.name,
});
- assert.equal(currentURL(), `/jobs/${job2.id}/scaling?namespace=${READ_ONLY_NAMESPACE}`);
+ assert.equal(
+ currentURL(),
+ `/jobs/${job2.id}/scaling?namespace=${READ_ONLY_NAMESPACE}`
+ );
assert.ok(TaskGroup.countStepper.increment.isDisabled);
});
- test('/jobs/:id/:task-group should list one page of allocations for the task group', async function(assert) {
+ test('/jobs/:id/:task-group should list one page of allocations for the task group', async function (assert) {
server.createList('allocation', TaskGroup.pageSize, {
jobId: job.id,
taskGroup: taskGroup.name,
@@ -242,7 +265,8 @@ module('Acceptance | task group detail', function(hooks) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
assert.ok(
- server.db.allocations.where({ jobId: job.id }).length > TaskGroup.pageSize,
+ server.db.allocations.where({ jobId: job.id }).length >
+ TaskGroup.pageSize,
'There are enough allocations to invoke pagination'
);
@@ -253,13 +277,17 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('each allocation should show basic information about the allocation', async function(assert) {
+ test('each allocation should show basic information about the allocation', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
const allocation = allocations.sortBy('modifyIndex').reverse()[0];
const allocationRow = TaskGroup.allocations.objectAt(0);
- assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short id');
+ assert.equal(
+ allocationRow.shortId,
+ allocation.id.split('-')[0],
+ 'Allocation short id'
+ );
assert.equal(
allocationRow.createTime,
moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
@@ -270,8 +298,16 @@ module('Acceptance | task group detail', function(hooks) {
moment(allocation.modifyTime / 1000000).fromNow(),
'Allocation modify time'
);
- assert.equal(allocationRow.status, allocation.clientStatus, 'Client status');
- assert.equal(allocationRow.jobVersion, allocation.jobVersion, 'Job Version');
+ assert.equal(
+ allocationRow.status,
+ allocation.clientStatus,
+ 'Client status'
+ );
+ assert.equal(
+ allocationRow.jobVersion,
+ allocation.jobVersion,
+ 'Job Version'
+ );
assert.equal(
allocationRow.client,
server.db.nodes.find(allocation.nodeId).id.split('-')[0],
@@ -284,7 +320,7 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('clicking the client ID in the allocation row naviates to the client page', async function(assert) {
+ test('clicking the client ID in the allocation row naviates to the client page', async function (assert) {
// Navigating to the client page requires node:read permission.
const policy = server.create('policy', {
id: 'node-read',
@@ -306,20 +342,27 @@ module('Acceptance | task group detail', function(hooks) {
const allocationRow = TaskGroup.allocations.objectAt(0);
await allocationRow.visitClient();
- assert.equal(currentURL(), `/clients/${allocation.nodeId}`, 'Node links to node page');
+ assert.equal(
+ currentURL(),
+ `/clients/${allocation.nodeId}`,
+ 'Node links to node page'
+ );
});
- test('each allocation should show stats about the allocation', async function(assert) {
+ test('each allocation should show stats about the allocation', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
const allocation = allocations.sortBy('name')[0];
const allocationRow = TaskGroup.allocations.objectAt(0);
const allocStats = server.db.clientAllocationStats.find(allocation.id);
- const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ const tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
- const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
+ const memoryUsed = tasks.reduce(
+ (sum, task) => sum + task.resources.MemoryMB,
+ 0
+ );
assert.equal(
allocationRow.cpu,
@@ -327,7 +370,9 @@ module('Acceptance | task group detail', function(hooks) {
'CPU %'
);
- const roundedTicks = Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks);
+ const roundedTicks = Math.floor(
+ allocStats.resourceUsage.CpuStats.TotalTicks
+ );
assert.equal(
allocationRow.cpuTooltip,
`${formatHertz(roundedTicks, 'MHz')} / ${formatHertz(cpuUsed, 'MHz')}`,
@@ -350,7 +395,7 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('when the allocation search has no matches, there is an empty message', async function(assert) {
+ test('when the allocation search has no matches, there is an empty message', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
await TaskGroup.search('zzzzzz');
@@ -363,17 +408,20 @@ module('Acceptance | task group detail', function(hooks) {
);
});
- test('when the allocation has reschedule events, the allocation row is denoted with an icon', async function(assert) {
+ test('when the allocation has reschedule events, the allocation row is denoted with an icon', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
const rescheduleRow = TaskGroup.allocationFor(allocations[0].id);
const normalRow = TaskGroup.allocationFor(allocations[1].id);
- assert.ok(rescheduleRow.rescheduled, 'Reschedule row has a reschedule icon');
+ assert.ok(
+ rescheduleRow.rescheduled,
+ 'Reschedule row has a reschedule icon'
+ );
assert.notOk(normalRow.rescheduled, 'Normal row has no reschedule icon');
});
- test('/jobs/:id/:task-group should present task lifecycles', async function(assert) {
+ test('/jobs/:id/:task-group should present task lifecycles', async function (assert) {
job = server.create('job', {
groupsCount: 2,
groupTaskCount: 3,
@@ -385,30 +433,36 @@ module('Acceptance | task group detail', function(hooks) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
assert.ok(TaskGroup.lifecycleChart.isPresent);
- assert.equal(TaskGroup.lifecycleChart.title, 'Task Lifecycle Configuration');
+ assert.equal(
+ TaskGroup.lifecycleChart.title,
+ 'Task Lifecycle Configuration'
+ );
- tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
const taskNames = tasks.mapBy('name');
// This is thoroughly tested in allocation detail tests, so this mostly checks what’s different
assert.equal(TaskGroup.lifecycleChart.tasks.length, 3);
- TaskGroup.lifecycleChart.tasks.forEach(Task => {
+ TaskGroup.lifecycleChart.tasks.forEach((Task) => {
assert.ok(taskNames.includes(Task.name));
assert.notOk(Task.isActive);
assert.notOk(Task.isFinished);
});
});
- test('when the task group depends on volumes, the volumes table is shown', async function(assert) {
+ test('when the task group depends on volumes, the volumes table is shown', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
assert.ok(TaskGroup.hasVolumes);
- assert.equal(TaskGroup.volumes.length, Object.keys(taskGroup.volumes).length);
+ assert.equal(
+ TaskGroup.volumes.length,
+ Object.keys(taskGroup.volumes).length
+ );
});
- test('when the task group does not depend on volumes, the volumes table is not shown', async function(assert) {
+ test('when the task group does not depend on volumes, the volumes table is not shown', async function (assert) {
job = server.create('job', { noHostVolumes: true, shallow: true });
taskGroup = server.db.taskGroups.where({ jobId: job.id })[0];
@@ -417,19 +471,22 @@ module('Acceptance | task group detail', function(hooks) {
assert.notOk(TaskGroup.hasVolumes);
});
- test('each row in the volumes table lists information about the volume', async function(assert) {
+ test('each row in the volumes table lists information about the volume', async function (assert) {
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
- TaskGroup.volumes[0].as(volumeRow => {
+ TaskGroup.volumes[0].as((volumeRow) => {
const volume = taskGroup.volumes[volumeRow.name];
assert.equal(volumeRow.name, volume.Name);
assert.equal(volumeRow.type, volume.Type);
assert.equal(volumeRow.source, volume.Source);
- assert.equal(volumeRow.permissions, volume.ReadOnly ? 'Read' : 'Read/Write');
+ assert.equal(
+ volumeRow.permissions,
+ volume.ReadOnly ? 'Read' : 'Read/Write'
+ );
});
});
- test('the count stepper sends the appropriate POST request', async function(assert) {
+ test('the count stepper sends the appropriate POST request', async function (assert) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
job = server.create('job', {
@@ -452,14 +509,14 @@ module('Acceptance | task group detail', function(hooks) {
await settled();
const scaleRequest = server.pretender.handledRequests.find(
- req => req.method === 'POST' && req.url.endsWith('/scale')
+ (req) => req.method === 'POST' && req.url.endsWith('/scale')
);
const requestBody = JSON.parse(scaleRequest.requestBody);
assert.equal(requestBody.Target.Group, scalingGroup.name);
assert.equal(requestBody.Count, scalingGroup.count + 1);
});
- test('the count stepper is disabled when a deployment is running', async function(assert) {
+ test('the count stepper is disabled when a deployment is running', async function (assert) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
job = server.create('job', {
@@ -484,22 +541,33 @@ module('Acceptance | task group detail', function(hooks) {
assert.ok(TaskGroup.countStepper.decrement.isDisabled);
});
- test('when the job for the task group is not found, an error message is shown, but the URL persists', async function(assert) {
- await TaskGroup.visit({ id: 'not-a-real-job', name: 'not-a-real-task-group' });
+ test('when the job for the task group is not found, an error message is shown, but the URL persists', async function (assert) {
+ await TaskGroup.visit({
+ id: 'not-a-real-job',
+ name: 'not-a-real-task-group',
+ });
assert.equal(
server.pretender.handledRequests
- .filter(request => !request.url.includes('policy'))
+ .filter((request) => !request.url.includes('policy'))
.findBy('status', 404).url,
'/v1/job/not-a-real-job',
'A request to the nonexistent job is made'
);
- assert.equal(currentURL(), '/jobs/not-a-real-job/not-a-real-task-group', 'The URL persists');
+ assert.equal(
+ currentURL(),
+ '/jobs/not-a-real-job/not-a-real-task-group',
+ 'The URL persists'
+ );
assert.ok(TaskGroup.error.isPresent, 'Error message is shown');
- assert.equal(TaskGroup.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ TaskGroup.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
- test('when the task group is not found on the job, an error message is shown, but the URL persists', async function(assert) {
+ test('when the task group is not found on the job, an error message is shown, but the URL persists', async function (assert) {
await TaskGroup.visit({ id: job.id, name: 'not-a-real-task-group' });
assert.ok(
@@ -509,9 +577,17 @@ module('Acceptance | task group detail', function(hooks) {
.includes(`/v1/job/${job.id}`),
'A request to the job is made and succeeds'
);
- assert.equal(currentURL(), `/jobs/${job.id}/not-a-real-task-group`, 'The URL persists');
+ assert.equal(
+ currentURL(),
+ `/jobs/${job.id}/not-a-real-task-group`,
+ 'The URL persists'
+ );
assert.ok(TaskGroup.error.isPresent, 'Error message is shown');
- assert.equal(TaskGroup.error.title, 'Not Found', 'Error message is for 404');
+ assert.equal(
+ TaskGroup.error.title,
+ 'Not Found',
+ 'Error message is for 404'
+ );
});
pageSizeSelect({
@@ -529,8 +605,10 @@ module('Acceptance | task group detail', function(hooks) {
},
});
- test('when a task group has no scaling events, there is no recent scaling events section', async function(assert) {
- const taskGroupScale = job.jobScale.taskGroupScales.models.find(m => m.name === taskGroup.name);
+ test('when a task group has no scaling events, there is no recent scaling events section', async function (assert) {
+ const taskGroupScale = job.jobScale.taskGroupScales.models.find(
+ (m) => m.name === taskGroup.name
+ );
taskGroupScale.update({ events: [] });
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
@@ -538,8 +616,10 @@ module('Acceptance | task group detail', function(hooks) {
assert.notOk(TaskGroup.hasScaleEvents);
});
- test('the recent scaling events section shows all recent scaling events in reverse chronological order', async function(assert) {
- const taskGroupScale = job.jobScale.taskGroupScales.models.find(m => m.name === taskGroup.name);
+ test('the recent scaling events section shows all recent scaling events in reverse chronological order', async function (assert) {
+ const taskGroupScale = job.jobScale.taskGroupScales.models.find(
+ (m) => m.name === taskGroup.name
+ );
taskGroupScale.update({
events: [
server.create('scale-event', { error: true }),
@@ -558,7 +638,10 @@ module('Acceptance | task group detail', function(hooks) {
scaleEvents.forEach((scaleEvent, idx) => {
const ScaleEvent = TaskGroup.scaleEvents[idx];
- assert.equal(ScaleEvent.time, moment(scaleEvent.time / 1000000).format('MMM DD HH:mm:ss ZZ'));
+ assert.equal(
+ ScaleEvent.time,
+ moment(scaleEvent.time / 1000000).format('MMM DD HH:mm:ss ZZ')
+ );
assert.equal(ScaleEvent.message, scaleEvent.message);
if (scaleEvent.count != null) {
@@ -577,8 +660,10 @@ module('Acceptance | task group detail', function(hooks) {
});
});
- test('when a task group has at least two count scaling events and the count scaling events outnumber the non-count scaling events, a timeline is shown in addition to the accordion', async function(assert) {
- const taskGroupScale = job.jobScale.taskGroupScales.models.find(m => m.name === taskGroup.name);
+ test('when a task group has at least two count scaling events and the count scaling events outnumber the non-count scaling events, a timeline is shown in addition to the accordion', async function (assert) {
+ const taskGroupScale = job.jobScale.taskGroupScales.models.find(
+ (m) => m.name === taskGroup.name
+ );
taskGroupScale.update({
events: [
server.create('scale-event', { error: true }),
@@ -600,7 +685,7 @@ module('Acceptance | task group detail', function(hooks) {
assert.equal(
TaskGroup.scalingAnnotations.length,
- scaleEvents.filter(ev => ev.count == null).length
+ scaleEvents.filter((ev) => ev.count == null).length
);
});
@@ -609,7 +694,7 @@ module('Acceptance | task group detail', function(hooks) {
paramName: 'status',
expectedOptions: ['Pending', 'Running', 'Complete', 'Failed', 'Lost'],
async beforeEach() {
- ['pending', 'running', 'complete', 'failed', 'lost'].forEach(s => {
+ ['pending', 'running', 'complete', 'failed', 'lost'].forEach((s) => {
server.createList('allocation', 5, { clientStatus: s });
});
await TaskGroup.visit({ id: job.id, name: taskGroup.name });
@@ -627,15 +712,18 @@ module('Acceptance | task group detail', function(hooks) {
return Array.from(
new Set(
allocs
- .filter(alloc => alloc.jobId == job.id && alloc.taskGroup == taskGroup.name)
+ .filter(
+ (alloc) =>
+ alloc.jobId == job.id && alloc.taskGroup == taskGroup.name
+ )
.mapBy('nodeId')
- .map(id => id.split('-')[0])
+ .map((id) => id.split('-')[0])
)
).sort();
},
async beforeEach() {
const nodes = server.createList('node', 3, 'forceIPv4');
- nodes.forEach(node =>
+ nodes.forEach((node) =>
server.createList('allocation', 5, {
nodeId: node.id,
jobId: job.id,
@@ -651,8 +739,11 @@ module('Acceptance | task group detail', function(hooks) {
});
});
-function testFacet(label, { facet, paramName, beforeEach, filter, expectedOptions }) {
- test(`facet ${label} | the ${label} facet has the correct options`, async function(assert) {
+function testFacet(
+ label,
+ { facet, paramName, beforeEach, filter, expectedOptions }
+) {
+ test(`facet ${label} | the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -664,13 +755,13 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
});
- test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function(assert) {
+ test(`facet ${label} | the ${label} facet filters the allocations list by ${label}`, async function (assert) {
let option;
await beforeEach();
@@ -681,7 +772,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
const selection = [option.key];
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -694,7 +785,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function(assert) {
+ test(`facet ${label} | selecting multiple options in the ${label} facet results in a broader search`, async function (assert) {
const selection = [];
await beforeEach();
@@ -708,7 +799,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
selection.push(option2.key);
const expectedAllocs = server.db.allocations
- .filter(alloc => filter(alloc, selection))
+ .filter((alloc) => filter(alloc, selection))
.sortBy('modifyIndex')
.reverse();
@@ -721,7 +812,7 @@ function testFacet(label, { facet, paramName, beforeEach, filter, expectedOption
});
});
- test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`facet ${label} | selecting options in the ${label} facet updates the ${paramName} query param`, async function (assert) {
const selection = [];
await beforeEach();
diff --git a/ui/tests/acceptance/task-logs-test.js b/ui/tests/acceptance/task-logs-test.js
index 9887e9892..90ca1e9b3 100644
--- a/ui/tests/acceptance/task-logs-test.js
+++ b/ui/tests/acceptance/task-logs-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL } from '@ember/test-helpers';
import { run } from '@ember/runloop';
import { module, test } from 'qunit';
@@ -9,37 +10,48 @@ import TaskLogs from 'nomad-ui/tests/pages/allocations/task/logs';
let allocation;
let task;
-module('Acceptance | task logs', function(hooks) {
+module('Acceptance | task logs', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('agent');
server.create('node', 'forceIPv4');
const job = server.create('job', { createAllocations: false });
- allocation = server.create('allocation', { jobId: job.id, clientStatus: 'running' });
+ allocation = server.create('allocation', {
+ jobId: job.id,
+ clientStatus: 'running',
+ });
task = server.db.taskStates.where({ allocationId: allocation.id })[0];
run.later(run, run.cancelTimers, 1000);
await TaskLogs.visit({ id: allocation.id, name: task.name });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await a11yAudit(assert);
});
- test('/allocation/:id/:task_name/logs should have a log component', async function(assert) {
- assert.equal(currentURL(), `/allocations/${allocation.id}/${task.name}/logs`, 'No redirect');
+ test('/allocation/:id/:task_name/logs should have a log component', async function (assert) {
+ assert.equal(
+ currentURL(),
+ `/allocations/${allocation.id}/${task.name}/logs`,
+ 'No redirect'
+ );
assert.ok(TaskLogs.hasTaskLog, 'Task log component found');
assert.equal(document.title, `Task ${task.name} logs - Nomad`);
});
- test('the stdout log immediately starts streaming', async function(assert) {
+ test('the stdout log immediately starts streaming', async function (assert) {
const node = server.db.nodes.find(allocation.nodeId);
- const logUrlRegex = new RegExp(`${node.httpAddr}/v1/client/fs/logs/${allocation.id}`);
+ const logUrlRegex = new RegExp(
+ `${node.httpAddr}/v1/client/fs/logs/${allocation.id}`
+ );
assert.ok(
- server.pretender.handledRequests.filter(req => logUrlRegex.test(req.url)).length,
+ server.pretender.handledRequests.filter((req) =>
+ logUrlRegex.test(req.url)
+ ).length,
'Log requests were made'
);
});
diff --git a/ui/tests/acceptance/token-test.js b/ui/tests/acceptance/token-test.js
index 9a1f3545c..96a1275e1 100644
--- a/ui/tests/acceptance/token-test.js
+++ b/ui/tests/acceptance/token-test.js
@@ -14,11 +14,11 @@ let node;
let managementToken;
let clientToken;
-module('Acceptance | tokens', function(hooks) {
+module('Acceptance | tokens', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
window.sessionStorage.clear();
@@ -29,32 +29,45 @@ module('Acceptance | tokens', function(hooks) {
clientToken = server.create('token');
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
await Tokens.visit();
await a11yAudit(assert);
});
- test('the token form sets the token in local storage', async function(assert) {
+ test('the token form sets the token in local storage', async function (assert) {
const { secretId } = managementToken;
await Tokens.visit();
- assert.ok(window.localStorage.nomadTokenSecret == null, 'No token secret set');
+ assert.equal(
+ window.localStorage.nomadTokenSecret,
+ null,
+ 'No token secret set'
+ );
assert.equal(document.title, 'Tokens - Nomad');
await Tokens.secret(secretId).submit();
- assert.equal(window.localStorage.nomadTokenSecret, secretId, 'Token secret was set');
+ assert.equal(
+ window.localStorage.nomadTokenSecret,
+ secretId,
+ 'Token secret was set'
+ );
});
// TODO: unskip once store.unloadAll reliably waits for in-flight requests to settle
- skip('the x-nomad-token header gets sent with requests once it is set', async function(assert) {
+ skip('the x-nomad-token header gets sent with requests once it is set', async function (assert) {
const { secretId } = managementToken;
await JobDetail.visit({ id: job.id });
await ClientDetail.visit({ id: node.id });
- assert.ok(server.pretender.handledRequests.length > 1, 'Requests have been made');
+ assert.ok(
+ server.pretender.handledRequests.length > 1,
+ 'Requests have been made'
+ );
- server.pretender.handledRequests.forEach(req => {
+ server.pretender.handledRequests.forEach((req) => {
assert.notOk(getHeader(req, 'x-nomad-token'), `No token for ${req.url}`);
});
@@ -70,12 +83,16 @@ module('Acceptance | tokens', function(hooks) {
assert.ok(newRequests.length > 1, 'New requests have been made');
// Cross-origin requests can't have a token
- newRequests.forEach(req => {
- assert.equal(getHeader(req, 'x-nomad-token'), secretId, `Token set for ${req.url}`);
+ newRequests.forEach((req) => {
+ assert.equal(
+ getHeader(req, 'x-nomad-token'),
+ secretId,
+ `Token set for ${req.url}`
+ );
});
});
- test('an error message is shown when authenticating a token fails', async function(assert) {
+ test('an error message is shown when authenticating a token fails', async function (assert) {
const { secretId } = managementToken;
const bogusSecret = 'this-is-not-the-secret';
assert.notEqual(
@@ -87,13 +104,17 @@ module('Acceptance | tokens', function(hooks) {
await Tokens.visit();
await Tokens.secret(bogusSecret).submit();
- assert.ok(window.localStorage.nomadTokenSecret == null, 'Token secret is discarded on failure');
+ assert.equal(
+ window.localStorage.nomadTokenSecret,
+ null,
+ 'Token secret is discarded on failure'
+ );
assert.ok(Tokens.errorMessage, 'Token error message is shown');
assert.notOk(Tokens.successMessage, 'Token success message is not shown');
assert.equal(Tokens.policies.length, 0, 'No token policies are shown');
});
- test('a success message and a special management token message are shown when authenticating succeeds', async function(assert) {
+ test('a success message and a special management token message are shown when authenticating succeeds', async function (assert) {
const { secretId } = managementToken;
await Tokens.visit();
@@ -105,7 +126,7 @@ module('Acceptance | tokens', function(hooks) {
assert.equal(Tokens.policies.length, 0, 'No token policies are shown');
});
- test('a success message and associated policies are shown when authenticating succeeds', async function(assert) {
+ test('a success message and associated policies are shown when authenticating succeeds', async function (assert) {
const { secretId } = clientToken;
const policy = clientToken.policies.models[0];
policy.update('description', 'Make sure there is a description');
@@ -115,7 +136,10 @@ module('Acceptance | tokens', function(hooks) {
assert.ok(Tokens.successMessage, 'Token success message is shown');
assert.notOk(Tokens.errorMessage, 'Token error message is not shown');
- assert.notOk(Tokens.managementMessage, 'Token management message is not shown');
+ assert.notOk(
+ Tokens.managementMessage,
+ 'Token management message is not shown'
+ );
assert.equal(
Tokens.policies.length,
clientToken.policies.length,
@@ -125,11 +149,15 @@ module('Acceptance | tokens', function(hooks) {
const policyElement = Tokens.policies.objectAt(0);
assert.equal(policyElement.name, policy.name, 'Policy Name');
- assert.equal(policyElement.description, policy.description, 'Policy Description');
+ assert.equal(
+ policyElement.description,
+ policy.description,
+ 'Policy Description'
+ );
assert.equal(policyElement.rules, policy.rules, 'Policy Rules');
});
- test('setting a token clears the store', async function(assert) {
+ test('setting a token clears the store', async function (assert) {
const { secretId } = clientToken;
await Jobs.visit();
@@ -138,7 +166,7 @@ module('Acceptance | tokens', function(hooks) {
await Tokens.visit();
await Tokens.secret(secretId).submit();
- server.pretender.get('/v1/jobs', function() {
+ server.pretender.get('/v1/jobs', function () {
return [200, {}, '[]'];
});
@@ -148,24 +176,34 @@ module('Acceptance | tokens', function(hooks) {
assert.notOk(find('[data-test-job-row]'), 'No jobs found');
});
- test('when the ott query parameter is present upon application load it’s exchanged for a token', async function(assert) {
+ test('when the ott query parameter is present upon application load it’s exchanged for a token', async function (assert) {
const { oneTimeSecret, secretId } = managementToken;
await JobDetail.visit({ id: job.id, ott: oneTimeSecret });
- assert.notOk(currentURL().includes(oneTimeSecret), 'OTT is cleared from the URL after loading');
+ assert.notOk(
+ currentURL().includes(oneTimeSecret),
+ 'OTT is cleared from the URL after loading'
+ );
await Tokens.visit();
- assert.equal(window.localStorage.nomadTokenSecret, secretId, 'Token secret was set');
+ assert.equal(
+ window.localStorage.nomadTokenSecret,
+ secretId,
+ 'Token secret was set'
+ );
});
- test('when the ott exchange fails an error is shown', async function(assert) {
+ test('when the ott exchange fails an error is shown', async function (assert) {
await visit('/?ott=fake');
assert.ok(Layout.error.isPresent);
assert.equal(Layout.error.title, 'Token Exchange Error');
- assert.equal(Layout.error.message, 'Failed to exchange the one-time token.');
+ assert.equal(
+ Layout.error.message,
+ 'Failed to exchange the one-time token.'
+ );
});
function getHeader({ requestHeaders }, name) {
diff --git a/ui/tests/acceptance/topology-test.js b/ui/tests/acceptance/topology-test.js
index 3685fc2cf..a12cb8880 100644
--- a/ui/tests/acceptance/topology-test.js
+++ b/ui/tests/acceptance/topology-test.js
@@ -16,15 +16,17 @@ import queryString from 'query-string';
const sumResources = (list, dimension) =>
list.reduce((agg, val) => agg + (get(val, dimension) || 0), 0);
-module('Acceptance | topology', function(hooks) {
+module('Acceptance | topology', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('job', { createAllocations: false });
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
+ assert.expect(1);
+
server.createList('node', 3);
server.createList('allocation', 5);
@@ -32,7 +34,7 @@ module('Acceptance | topology', function(hooks) {
await a11yAudit(assert);
});
- test('by default the info panel shows cluster aggregate stats', async function(assert) {
+ test('by default the info panel shows cluster aggregate stats', async function (assert) {
server.createList('node', 3);
server.createList('allocation', 5);
@@ -46,12 +48,17 @@ module('Acceptance | topology', function(hooks) {
);
const allocs = server.schema.allocations.all().models;
- const scheduledAllocs = allocs.filter(alloc =>
+ const scheduledAllocs = allocs.filter((alloc) =>
['pending', 'running'].includes(alloc.clientStatus)
);
- assert.equal(Topology.clusterInfoPanel.allocCount, `${scheduledAllocs.length} Allocations`);
+ assert.equal(
+ Topology.clusterInfoPanel.allocCount,
+ `${scheduledAllocs.length} Allocations`
+ );
- const nodeResources = server.schema.nodes.all().models.mapBy('nodeResources');
+ const nodeResources = server.schema.nodes
+ .all()
+ .models.mapBy('nodeResources');
const taskResources = scheduledAllocs
.mapBy('taskResources.models')
.flat()
@@ -62,21 +69,32 @@ module('Acceptance | topology', function(hooks) {
const reservedMem = sumResources(taskResources, 'Memory.MemoryMB');
const reservedCPU = sumResources(taskResources, 'Cpu.CpuShares');
- assert.equal(Topology.clusterInfoPanel.memoryProgressValue, reservedMem / totalMem);
- assert.equal(Topology.clusterInfoPanel.cpuProgressValue, reservedCPU / totalCPU);
+ assert.equal(
+ Topology.clusterInfoPanel.memoryProgressValue,
+ reservedMem / totalMem
+ );
+ assert.equal(
+ Topology.clusterInfoPanel.cpuProgressValue,
+ reservedCPU / totalCPU
+ );
assert.equal(
Topology.clusterInfoPanel.memoryAbsoluteValue,
- `${formatBytes(reservedMem * 1024 * 1024)} / ${formatBytes(totalMem * 1024 * 1024)} reserved`
+ `${formatBytes(reservedMem * 1024 * 1024)} / ${formatBytes(
+ totalMem * 1024 * 1024
+ )} reserved`
);
assert.equal(
Topology.clusterInfoPanel.cpuAbsoluteValue,
- `${formatHertz(reservedCPU, 'MHz')} / ${formatHertz(totalCPU, 'MHz')} reserved`
+ `${formatHertz(reservedCPU, 'MHz')} / ${formatHertz(
+ totalCPU,
+ 'MHz'
+ )} reserved`
);
});
- test('all allocations for all namespaces and all clients are queried on load', async function(assert) {
+ test('all allocations for all namespaces and all clients are queried on load', async function (assert) {
server.createList('node', 3);
server.createList('allocation', 5);
@@ -84,10 +102,14 @@ module('Acceptance | topology', function(hooks) {
const requests = this.server.pretender.handledRequests;
assert.ok(requests.findBy('url', '/v1/nodes?resources=true'));
- const allocationsRequest = requests.find(req => req.url.startsWith('/v1/allocations'));
+ const allocationsRequest = requests.find((req) =>
+ req.url.startsWith('/v1/allocations')
+ );
assert.ok(allocationsRequest);
- const allocationRequestParams = queryString.parse(allocationsRequest.url.split('?')[1]);
+ const allocationRequestParams = queryString.parse(
+ allocationsRequest.url.split('?')[1]
+ );
assert.deepEqual(allocationRequestParams, {
namespace: '*',
task_states: 'false',
@@ -95,7 +117,7 @@ module('Acceptance | topology', function(hooks) {
});
});
- test('when an allocation is selected, the info panel shows information on the allocation', async function(assert) {
+ test('when an allocation is selected, the info panel shows information on the allocation', async function (assert) {
const nodes = server.createList('node', 5);
const job = server.create('job', { createAllocations: false });
const taskGroup = server.schema.find('taskGroup', job.taskGroupIds[0]).name;
@@ -109,7 +131,7 @@ module('Acceptance | topology', function(hooks) {
const sortedNodes = nodes.sortBy('datacenter');
let node, alloc;
for (let n of sortedNodes) {
- alloc = allocs.find(a => a.nodeId === n.id);
+ alloc = allocs.find((a) => a.nodeId === n.id);
if (alloc) {
node = n;
break;
@@ -121,11 +143,15 @@ module('Acceptance | topology', function(hooks) {
.uniq()
.sort()
.indexOf(node.datacenter);
- const nodeIndex = nodes.filterBy('datacenter', node.datacenter).indexOf(node);
+ const nodeIndex = nodes
+ .filterBy('datacenter', node.datacenter)
+ .indexOf(node);
const reset = async () => {
await Topology.visit();
- await Topology.viz.datacenters[dcIndex].nodes[nodeIndex].memoryRects[0].select();
+ await Topology.viz.datacenters[dcIndex].nodes[
+ nodeIndex
+ ].memoryRects[0].select();
};
await reset();
@@ -134,7 +160,10 @@ module('Acceptance | topology', function(hooks) {
assert.equal(Topology.allocInfoPanel.id, alloc.id.split('-')[0]);
const uniqueClients = allocs.mapBy('nodeId').uniq();
- assert.equal(Topology.allocInfoPanel.siblingAllocs, `Sibling Allocations: ${allocs.length}`);
+ assert.equal(
+ Topology.allocInfoPanel.siblingAllocs,
+ `Sibling Allocations: ${allocs.length}`
+ );
assert.equal(
Topology.allocInfoPanel.uniquePlacements,
`Unique Client Placements: ${uniqueClients.length}`
@@ -158,10 +187,13 @@ module('Acceptance | topology', function(hooks) {
assert.equal(currentURL(), `/clients/${node.id}`);
});
- test('changing which allocation is selected changes the metric charts', async function(assert) {
+ test('changing which allocation is selected changes the metric charts', async function (assert) {
server.create('node');
const job1 = server.create('job', { createAllocations: false });
- const taskGroup1 = server.schema.find('taskGroup', job1.taskGroupIds[0]).name;
+ const taskGroup1 = server.schema.find(
+ 'taskGroup',
+ job1.taskGroupIds[0]
+ ).name;
server.create('allocation', {
forceRunningClientStatus: true,
jobId: job1.id,
@@ -169,7 +201,10 @@ module('Acceptance | topology', function(hooks) {
});
const job2 = server.create('job', { createAllocations: false });
- const taskGroup2 = server.schema.find('taskGroup', job2.taskGroupIds[0]).name;
+ const taskGroup2 = server.schema.find(
+ 'taskGroup',
+ job2.taskGroupIds[0]
+ ).name;
server.create('allocation', {
forceRunningClientStatus: true,
jobId: job2.id,
@@ -178,15 +213,17 @@ module('Acceptance | topology', function(hooks) {
await Topology.visit();
await Topology.viz.datacenters[0].nodes[0].memoryRects[0].select();
- const firstAllocationTaskNames = Topology.allocInfoPanel.charts[0].areas.mapBy('taskName');
+ const firstAllocationTaskNames =
+ Topology.allocInfoPanel.charts[0].areas.mapBy('taskName');
await Topology.viz.datacenters[0].nodes[0].memoryRects[1].select();
- const secondAllocationTaskNames = Topology.allocInfoPanel.charts[0].areas.mapBy('taskName');
+ const secondAllocationTaskNames =
+ Topology.allocInfoPanel.charts[0].areas.mapBy('taskName');
assert.notDeepEqual(firstAllocationTaskNames, secondAllocationTaskNames);
});
- test('when a node is selected, the info panel shows information on the node', async function(assert) {
+ test('when a node is selected, the info panel shows information on the node', async function (assert) {
// A high node count is required for node selection
const nodes = server.createList('node', 51);
const node = nodes.sortBy('datacenter')[0];
@@ -204,7 +241,10 @@ module('Acceptance | topology', function(hooks) {
assert.equal(Topology.nodeInfoPanel.address, `Address: ${node.httpAddr}`);
assert.equal(Topology.nodeInfoPanel.status, `Status: ${node.status}`);
- assert.equal(Topology.nodeInfoPanel.drainingLabel, node.drain ? 'Yes' : 'No');
+ assert.equal(
+ Topology.nodeInfoPanel.drainingLabel,
+ node.drain ? 'Yes' : 'No'
+ );
assert.equal(
Topology.nodeInfoPanel.eligibleLabel,
node.schedulingEligibility === 'eligible' ? 'Yes' : 'No'
@@ -226,15 +266,20 @@ module('Acceptance | topology', function(hooks) {
const totalMem = node.nodeResources.Memory.MemoryMB;
const totalCPU = node.nodeResources.Cpu.CpuShares;
- assert.equal(Topology.nodeInfoPanel.memoryProgressValue, reservedMem / totalMem);
- assert.equal(Topology.nodeInfoPanel.cpuProgressValue, reservedCPU / totalCPU);
+ assert.equal(
+ Topology.nodeInfoPanel.memoryProgressValue,
+ reservedMem / totalMem
+ );
+ assert.equal(
+ Topology.nodeInfoPanel.cpuProgressValue,
+ reservedCPU / totalCPU
+ );
assert.equal(
Topology.nodeInfoPanel.memoryAbsoluteValue,
- `${formatScheduledBytes(reservedMem * 1024 * 1024)} / ${formatScheduledBytes(
- totalMem,
- 'MiB'
- )} reserved`
+ `${formatScheduledBytes(
+ reservedMem * 1024 * 1024
+ )} / ${formatScheduledBytes(totalMem, 'MiB')} reserved`
);
assert.equal(
@@ -249,7 +294,7 @@ module('Acceptance | topology', function(hooks) {
assert.equal(currentURL(), `/clients/${node.id}`);
});
- test('when one or more nodes lack the NodeResources property, a warning message is shown', async function(assert) {
+ test('when one or more nodes lack the NodeResources property, a warning message is shown', async function (assert) {
server.createList('node', 3);
server.createList('allocation', 5);
diff --git a/ui/tests/acceptance/volume-detail-test.js b/ui/tests/acceptance/volume-detail-test.js
index d43d2bb31..fb264110a 100644
--- a/ui/tests/acceptance/volume-detail-test.js
+++ b/ui/tests/acceptance/volume-detail-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { module, test } from 'qunit';
import { currentURL } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
@@ -20,24 +21,24 @@ const assignReadAlloc = (volume, alloc) => {
volume.save();
};
-module('Acceptance | volume detail', function(hooks) {
+module('Acceptance | volume detail', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let volume;
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
server.create('csi-plugin', { createVolumes: false });
volume = server.create('csi-volume');
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
await a11yAudit(assert);
});
- test('/csi/volumes/:id should have a breadcrumb trail linking back to Volumes and Storage', async function(assert) {
+ test('/csi/volumes/:id should have a breadcrumb trail linking back to Volumes and Storage', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
assert.equal(Layout.breadcrumbFor('csi.index').text, 'Storage');
@@ -45,17 +46,21 @@ module('Acceptance | volume detail', function(hooks) {
assert.equal(Layout.breadcrumbFor('csi.volumes.volume').text, volume.name);
});
- test('/csi/volumes/:id should show the volume name in the title', async function(assert) {
+ test('/csi/volumes/:id should show the volume name in the title', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
assert.equal(document.title, `CSI Volume ${volume.name} - Nomad`);
assert.equal(VolumeDetail.title, volume.name);
});
- test('/csi/volumes/:id should list additional details for the volume below the title', async function(assert) {
+ test('/csi/volumes/:id should list additional details for the volume below the title', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
- assert.ok(VolumeDetail.health.includes(volume.schedulable ? 'Schedulable' : 'Unschedulable'));
+ assert.ok(
+ VolumeDetail.health.includes(
+ volume.schedulable ? 'Schedulable' : 'Unschedulable'
+ )
+ );
assert.ok(VolumeDetail.provider.includes(volume.provider));
assert.ok(VolumeDetail.externalId.includes(volume.externalId));
assert.notOk(
@@ -64,11 +69,11 @@ module('Acceptance | volume detail', function(hooks) {
);
});
- test('/csi/volumes/:id should list all write allocations the volume is attached to', async function(assert) {
+ test('/csi/volumes/:id should list all write allocations the volume is attached to', async function (assert) {
const writeAllocations = server.createList('allocation', 2);
const readAllocations = server.createList('allocation', 3);
- writeAllocations.forEach(alloc => assignWriteAlloc(volume, alloc));
- readAllocations.forEach(alloc => assignReadAlloc(volume, alloc));
+ writeAllocations.forEach((alloc) => assignWriteAlloc(volume, alloc));
+ readAllocations.forEach((alloc) => assignReadAlloc(volume, alloc));
await VolumeDetail.visit({ id: volume.id });
@@ -77,15 +82,18 @@ module('Acceptance | volume detail', function(hooks) {
.sortBy('modifyIndex')
.reverse()
.forEach((allocation, idx) => {
- assert.equal(allocation.id, VolumeDetail.writeAllocations.objectAt(idx).id);
+ assert.equal(
+ allocation.id,
+ VolumeDetail.writeAllocations.objectAt(idx).id
+ );
});
});
- test('/csi/volumes/:id should list all read allocations the volume is attached to', async function(assert) {
+ test('/csi/volumes/:id should list all read allocations the volume is attached to', async function (assert) {
const writeAllocations = server.createList('allocation', 2);
const readAllocations = server.createList('allocation', 3);
- writeAllocations.forEach(alloc => assignWriteAlloc(volume, alloc));
- readAllocations.forEach(alloc => assignReadAlloc(volume, alloc));
+ writeAllocations.forEach((alloc) => assignWriteAlloc(volume, alloc));
+ readAllocations.forEach((alloc) => assignReadAlloc(volume, alloc));
await VolumeDetail.visit({ id: volume.id });
@@ -94,11 +102,14 @@ module('Acceptance | volume detail', function(hooks) {
.sortBy('modifyIndex')
.reverse()
.forEach((allocation, idx) => {
- assert.equal(allocation.id, VolumeDetail.readAllocations.objectAt(idx).id);
+ assert.equal(
+ allocation.id,
+ VolumeDetail.readAllocations.objectAt(idx).id
+ );
});
});
- test('each allocation should have high-level details for the allocation', async function(assert) {
+ test('each allocation should have high-level details for the allocation', async function (assert) {
const allocation = server.create('allocation', { clientStatus: 'running' });
assignWriteAlloc(volume, allocation);
@@ -108,14 +119,21 @@ module('Acceptance | volume detail', function(hooks) {
jobId: allocation.jobId,
});
- const tasks = taskGroup.taskIds.map(id => server.db.tasks.find(id));
+ const tasks = taskGroup.taskIds.map((id) => server.db.tasks.find(id));
const cpuUsed = tasks.reduce((sum, task) => sum + task.resources.CPU, 0);
- const memoryUsed = tasks.reduce((sum, task) => sum + task.resources.MemoryMB, 0);
+ const memoryUsed = tasks.reduce(
+ (sum, task) => sum + task.resources.MemoryMB,
+ 0
+ );
await VolumeDetail.visit({ id: volume.id });
- VolumeDetail.writeAllocations.objectAt(0).as(allocationRow => {
- assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'Allocation short ID');
+ VolumeDetail.writeAllocations.objectAt(0).as((allocationRow) => {
+ assert.equal(
+ allocationRow.shortId,
+ allocation.id.split('-')[0],
+ 'Allocation short ID'
+ );
assert.equal(
allocationRow.createTime,
moment(allocation.createTime / 1000000).format('MMM DD HH:mm:ss ZZ'),
@@ -126,8 +144,16 @@ module('Acceptance | volume detail', function(hooks) {
moment(allocation.modifyTime / 1000000).fromNow(),
'Allocation modify time'
);
- assert.equal(allocationRow.status, allocation.clientStatus, 'Client status');
- assert.equal(allocationRow.job, server.db.jobs.find(allocation.jobId).name, 'Job name');
+ assert.equal(
+ allocationRow.status,
+ allocation.clientStatus,
+ 'Client status'
+ );
+ assert.equal(
+ allocationRow.job,
+ server.db.jobs.find(allocation.jobId).name,
+ 'Job name'
+ );
assert.ok(allocationRow.taskGroup, 'Task group name');
assert.ok(allocationRow.jobVersion, 'Job Version');
assert.equal(
@@ -145,7 +171,9 @@ module('Acceptance | volume detail', function(hooks) {
Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks) / cpuUsed,
'CPU %'
);
- const roundedTicks = Math.floor(allocStats.resourceUsage.CpuStats.TotalTicks);
+ const roundedTicks = Math.floor(
+ allocStats.resourceUsage.CpuStats.TotalTicks
+ );
assert.equal(
allocationRow.cpuTooltip,
`${formatHertz(roundedTicks, 'MHz')} / ${formatHertz(cpuUsed, 'MHz')}`,
@@ -158,16 +186,15 @@ module('Acceptance | volume detail', function(hooks) {
);
assert.equal(
allocationRow.memTooltip,
- `${formatBytes(allocStats.resourceUsage.MemoryStats.RSS)} / ${formatBytes(
- memoryUsed,
- 'MiB'
- )}`,
+ `${formatBytes(
+ allocStats.resourceUsage.MemoryStats.RSS
+ )} / ${formatBytes(memoryUsed, 'MiB')}`,
'Detailed memory information is in a tooltip'
);
});
});
- test('each allocation should link to the allocation detail page', async function(assert) {
+ test('each allocation should link to the allocation detail page', async function (assert) {
const allocation = server.create('allocation');
assignWriteAlloc(volume, allocation);
@@ -177,43 +204,46 @@ module('Acceptance | volume detail', function(hooks) {
assert.equal(currentURL(), `/allocations/${allocation.id}`);
});
- test('when there are no write allocations, the table presents an empty state', async function(assert) {
+ test('when there are no write allocations, the table presents an empty state', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
assert.ok(VolumeDetail.writeTableIsEmpty);
assert.equal(VolumeDetail.writeEmptyState.headline, 'No Write Allocations');
});
- test('when there are no read allocations, the table presents an empty state', async function(assert) {
+ test('when there are no read allocations, the table presents an empty state', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
assert.ok(VolumeDetail.readTableIsEmpty);
assert.equal(VolumeDetail.readEmptyState.headline, 'No Read Allocations');
});
- test('the constraints table shows access mode and attachment mode', async function(assert) {
+ test('the constraints table shows access mode and attachment mode', async function (assert) {
await VolumeDetail.visit({ id: volume.id });
assert.equal(VolumeDetail.constraints.accessMode, volume.accessMode);
- assert.equal(VolumeDetail.constraints.attachmentMode, volume.attachmentMode);
+ assert.equal(
+ VolumeDetail.constraints.attachmentMode,
+ volume.attachmentMode
+ );
});
});
// Namespace test: details shows the namespace
-module('Acceptance | volume detail (with namespaces)', function(hooks) {
+module('Acceptance | volume detail (with namespaces)', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
let volume;
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.createList('namespace', 2);
server.create('node');
server.create('csi-plugin', { createVolumes: false });
volume = server.create('csi-volume');
});
- test('/csi/volumes/:id detail ribbon includes the namespace of the volume', async function(assert) {
+ test('/csi/volumes/:id detail ribbon includes the namespace of the volume', async function (assert) {
await VolumeDetail.visit({ id: volume.id, namespace: volume.namespaceId });
assert.ok(VolumeDetail.hasNamespace);
diff --git a/ui/tests/acceptance/volumes-list-test.js b/ui/tests/acceptance/volumes-list-test.js
index bec92893f..0876aa36a 100644
--- a/ui/tests/acceptance/volumes-list-test.js
+++ b/ui/tests/acceptance/volumes-list-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/require-expect */
import { currentURL, visit } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -19,35 +20,35 @@ const assignReadAlloc = (volume, alloc) => {
volume.save();
};
-module('Acceptance | volumes list', function(hooks) {
+module('Acceptance | volumes list', function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
server.create('node');
server.create('csi-plugin', { createVolumes: false });
window.localStorage.clear();
});
- test('it passes an accessibility audit', async function(assert) {
+ test('it passes an accessibility audit', async function (assert) {
await VolumesList.visit();
await a11yAudit(assert);
});
- test('visiting /csi redirects to /csi/volumes', async function(assert) {
+ test('visiting /csi redirects to /csi/volumes', async function (assert) {
await visit('/csi');
assert.equal(currentURL(), '/csi/volumes');
});
- test('visiting /csi/volumes', async function(assert) {
+ test('visiting /csi/volumes', async function (assert) {
await VolumesList.visit();
assert.equal(currentURL(), '/csi/volumes');
assert.equal(document.title, 'CSI Volumes - Nomad');
});
- test('/csi/volumes should list the first page of volumes sorted by name', async function(assert) {
+ test('/csi/volumes should list the first page of volumes sorted by name', async function (assert) {
const volumeCount = VolumesList.pageSize + 1;
server.createList('csi-volume', volumeCount);
@@ -60,12 +61,12 @@ module('Acceptance | volumes list', function(hooks) {
});
});
- test('each volume row should contain information about the volume', async function(assert) {
+ test('each volume row should contain information about the volume', async function (assert) {
const volume = server.create('csi-volume');
const readAllocs = server.createList('allocation', 2, { shallow: true });
const writeAllocs = server.createList('allocation', 3, { shallow: true });
- readAllocs.forEach(alloc => assignReadAlloc(volume, alloc));
- writeAllocs.forEach(alloc => assignWriteAlloc(volume, alloc));
+ readAllocs.forEach((alloc) => assignReadAlloc(volume, alloc));
+ writeAllocs.forEach((alloc) => assignWriteAlloc(volume, alloc));
await VolumesList.visit();
@@ -76,14 +77,19 @@ module('Acceptance | volumes list', function(hooks) {
const healthy = volume.controllersHealthy;
const expected = volume.controllersExpected;
const isHealthy = healthy > 0;
- controllerHealthStr = `${isHealthy ? 'Healthy' : 'Unhealthy'} (${healthy}/${expected})`;
+ controllerHealthStr = `${
+ isHealthy ? 'Healthy' : 'Unhealthy'
+ } (${healthy}/${expected})`;
}
const nodeHealthStr = volume.nodesHealthy > 0 ? 'Healthy' : 'Unhealthy';
assert.equal(volumeRow.name, volume.id);
assert.notOk(volumeRow.hasNamespace);
- assert.equal(volumeRow.schedulable, volume.schedulable ? 'Schedulable' : 'Unschedulable');
+ assert.equal(
+ volumeRow.schedulable,
+ volume.schedulable ? 'Schedulable' : 'Unschedulable'
+ );
assert.equal(volumeRow.controllerHealth, controllerHealthStr);
assert.equal(
volumeRow.nodeHealth,
@@ -93,30 +99,38 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(volumeRow.allocations, readAllocs.length + writeAllocs.length);
});
- test('each volume row should link to the corresponding volume', async function(assert) {
+ test('each volume row should link to the corresponding volume', async function (assert) {
const [, secondNamespace] = server.createList('namespace', 2);
- const volume = server.create('csi-volume', { namespaceId: secondNamespace.id });
+ const volume = server.create('csi-volume', {
+ namespaceId: secondNamespace.id,
+ });
await VolumesList.visit({ namespace: '*' });
await VolumesList.volumes.objectAt(0).clickName();
- assert.equal(currentURL(), `/csi/volumes/${volume.id}?namespace=${secondNamespace.id}`);
+ assert.equal(
+ currentURL(),
+ `/csi/volumes/${volume.id}?namespace=${secondNamespace.id}`
+ );
await VolumesList.visit({ namespace: '*' });
assert.equal(currentURL(), '/csi/volumes?namespace=*');
await VolumesList.volumes.objectAt(0).clickRow();
- assert.equal(currentURL(), `/csi/volumes/${volume.id}?namespace=${secondNamespace.id}`);
+ assert.equal(
+ currentURL(),
+ `/csi/volumes/${volume.id}?namespace=${secondNamespace.id}`
+ );
});
- test('when there are no volumes, there is an empty message', async function(assert) {
+ test('when there are no volumes, there is an empty message', async function (assert) {
await VolumesList.visit();
assert.ok(VolumesList.isEmpty);
assert.equal(VolumesList.emptyState.headline, 'No Volumes');
});
- test('when there are volumes, but no matches for a search, there is an empty message', async function(assert) {
+ test('when there are volumes, but no matches for a search, there is an empty message', async function (assert) {
server.create('csi-volume', { id: 'cat 1' });
server.create('csi-volume', { id: 'cat 2' });
@@ -127,7 +141,7 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(VolumesList.emptyState.headline, 'No Matches');
});
- test('searching resets the current page', async function(assert) {
+ test('searching resets the current page', async function (assert) {
server.createList('csi-volume', VolumesList.pageSize + 1);
await VolumesList.visit();
@@ -140,7 +154,7 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(currentURL(), '/csi/volumes?search=foobar');
});
- test('when the cluster has namespaces, each volume row includes the volume namespace', async function(assert) {
+ test('when the cluster has namespaces, each volume row includes the volume namespace', async function (assert) {
server.createList('namespace', 2);
const volume = server.create('csi-volume');
@@ -150,10 +164,14 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(volumeRow.namespace, volume.namespaceId);
});
- test('when the namespace query param is set, only matching volumes are shown and the namespace value is forwarded to app state', async function(assert) {
+ test('when the namespace query param is set, only matching volumes are shown and the namespace value is forwarded to app state', async function (assert) {
server.createList('namespace', 2);
- const volume1 = server.create('csi-volume', { namespaceId: server.db.namespaces[0].id });
- const volume2 = server.create('csi-volume', { namespaceId: server.db.namespaces[1].id });
+ const volume1 = server.create('csi-volume', {
+ namespaceId: server.db.namespaces[0].id,
+ });
+ const volume2 = server.create('csi-volume', {
+ namespaceId: server.db.namespaces[1].id,
+ });
await VolumesList.visit();
assert.equal(VolumesList.volumes.length, 2);
@@ -170,7 +188,7 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(VolumesList.volumes.objectAt(0).name, volume2.id);
});
- test('the active namespace is carried over to the jobs pages', async function(assert) {
+ test('the active namespace is carried over to the jobs pages', async function (assert) {
server.createList('namespace', 2);
const namespace = server.db.namespaces[1];
@@ -183,7 +201,7 @@ module('Acceptance | volumes list', function(hooks) {
assert.equal(currentURL(), `/jobs?namespace=${namespace.id}`);
});
- test('when accessing volumes is forbidden, a message is shown with a link to the tokens page', async function(assert) {
+ test('when accessing volumes is forbidden, a message is shown with a link to the tokens page', async function (assert) {
server.pretender.get('/v1/volumes', () => [403, {}, null]);
await VolumesList.visit();
@@ -224,7 +242,7 @@ module('Acceptance | volumes list', function(hooks) {
label,
{ facet, paramName, beforeEach, filter, expectedOptions, optionToSelect }
) {
- test(`the ${label} facet has the correct options`, async function(assert) {
+ test(`the ${label} facet has the correct options`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -236,13 +254,13 @@ module('Acceptance | volumes list', function(hooks) {
}
assert.deepEqual(
- facet.options.map(option => option.label.trim()),
+ facet.options.map((option) => option.label.trim()),
expectation,
'Options for facet are as expected'
);
});
- test(`the ${label} facet filters the volumes list by ${label}`, async function(assert) {
+ test(`the ${label} facet filters the volumes list by ${label}`, async function (assert) {
await beforeEach();
await facet.toggle();
@@ -251,7 +269,7 @@ module('Acceptance | volumes list', function(hooks) {
await option.select();
const expectedVolumes = server.db.csiVolumes
- .filter(volume => filter(volume, selection))
+ .filter((volume) => filter(volume, selection))
.sortBy('id');
VolumesList.volumes.forEach((volume, index) => {
@@ -263,7 +281,7 @@ module('Acceptance | volumes list', function(hooks) {
});
});
- test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function(assert) {
+ test(`selecting an option in the ${label} facet updates the ${paramName} query param`, async function (assert) {
await beforeEach();
await facet.toggle();
diff --git a/ui/tests/helpers/a11y-audit.js b/ui/tests/helpers/a11y-audit.js
index 6ab951a66..a866784f2 100644
--- a/ui/tests/helpers/a11y-audit.js
+++ b/ui/tests/helpers/a11y-audit.js
@@ -10,7 +10,7 @@ function appendRuleOverrides(overriddenRules) {
},
};
- overriddenRules.forEach(rule => (rules[rule] = { enabled: false }));
+ overriddenRules.forEach((rule) => (rules[rule] = { enabled: false }));
return rules;
}
diff --git a/ui/tests/helpers/codemirror.js b/ui/tests/helpers/codemirror.js
index 0cc9674fe..923db4563 100644
--- a/ui/tests/helpers/codemirror.js
+++ b/ui/tests/helpers/codemirror.js
@@ -3,7 +3,7 @@ const invariant = (truthy, error) => {
};
export function getCodeMirrorInstance(container) {
- return function(selector) {
+ return function (selector) {
const cmService = container.lookup('service:code-mirror');
const element = document.querySelector(selector);
@@ -17,14 +17,14 @@ export function getCodeMirrorInstance(container) {
}
export default function setupCodeMirror(hooks) {
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.getCodeMirrorInstance = getCodeMirrorInstance(this.owner);
// Expose to window for access from page objects
window.getCodeMirrorInstance = this.getCodeMirrorInstance;
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
delete window.getCodeMirrorInstance;
delete this.getCodeMirrorInstance;
});
diff --git a/ui/tests/helpers/glimmer-factory.js b/ui/tests/helpers/glimmer-factory.js
index 5525eee7b..3326155dc 100644
--- a/ui/tests/helpers/glimmer-factory.js
+++ b/ui/tests/helpers/glimmer-factory.js
@@ -1,22 +1,31 @@
-// Used in glimmer component unit tests. Glimmer components should typically
-// be tested with integration tests, but occasionally individual methods or
-// properties have logic that isn't coupled to rendering or the DOM and can
-// be better tested in a unit fashion.
-//
-// Use like
-//
-// setupGlimmerComponentFactory(hooks, 'my-component')
-//
-// test('testing my component', function(assert) {
-// const component = this.createComponent({ hello: 'world' });
-// assert.equal(component.args.hello, 'world');
-// });
+/* eslint-disable qunit/no-commented-tests */
+// We comment test to show an example of how to use the factory function
+
+/*
+ Used in glimmer component unit tests. Glimmer components should typically
+ be tested with integration tests, but occasionally individual methods or
+ properties have logic that isn't coupled to rendering or the DOM and can
+ be better tested in a unit fashion.
+
+ Use like
+
+ setupGlimmerComponentFactory(hooks, 'my-component')
+
+ test('testing my component', function(assert) {
+ const component = this.createComponent({ hello: 'world' });
+ assert.equal(component.args.hello, 'world');
+ });
+*/
+
export default function setupGlimmerComponentFactory(hooks, componentKey) {
- hooks.beforeEach(function() {
- this.createComponent = glimmerComponentInstantiator(this.owner, componentKey);
+ hooks.beforeEach(function () {
+ this.createComponent = glimmerComponentInstantiator(
+ this.owner,
+ componentKey
+ );
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
delete this.createComponent;
});
}
diff --git a/ui/tests/helpers/module-for-job.js b/ui/tests/helpers/module-for-job.js
index 87462b063..5fb740a01 100644
--- a/ui/tests/helpers/module-for-job.js
+++ b/ui/tests/helpers/module-for-job.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* eslint-disable qunit/no-conditional-assertions */
import { currentURL } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
@@ -6,13 +8,18 @@ import JobDetail from 'nomad-ui/tests/pages/jobs/detail';
import Tokens from 'nomad-ui/tests/pages/settings/tokens';
// eslint-disable-next-line ember/no-test-module-for
-export default function moduleForJob(title, context, jobFactory, additionalTests) {
+export default function moduleForJob(
+ title,
+ context,
+ jobFactory,
+ additionalTests
+) {
let job;
- module(title, function(hooks) {
+ module(title, function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.before(function() {
+ hooks.before(function () {
if (context !== 'allocations' && context !== 'children') {
throw new Error(
`Invalid context provided to moduleForJob, expected either "allocations" or "children", got ${context}`
@@ -20,7 +27,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
}
});
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
server.create('node');
job = jobFactory();
if (!job.namespace || job.namespace === 'default') {
@@ -30,7 +37,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
}
});
- test('visiting /jobs/:job_id', async function(assert) {
+ test('visiting /jobs/:job_id', async function (assert) {
const expectedURL = new URL(
urlWithNamespace(`/jobs/${encodeURIComponent(job.id)}`, job.namespace),
window.location
@@ -42,7 +49,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
assert.equal(document.title, `Job ${job.name} - Nomad`);
});
- test('the subnav links to overview', async function(assert) {
+ test('the subnav links to overview', async function (assert) {
await JobDetail.tabFor('overview').visit();
const expectedURL = new URL(
@@ -55,31 +62,40 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
assert.deepEqual(gotURL.searchParams, expectedURL.searchParams);
});
- test('the subnav links to definition', async function(assert) {
+ test('the subnav links to definition', async function (assert) {
await JobDetail.tabFor('definition').visit();
assert.equal(
currentURL(),
- urlWithNamespace(`/jobs/${encodeURIComponent(job.id)}/definition`, job.namespace)
+ urlWithNamespace(
+ `/jobs/${encodeURIComponent(job.id)}/definition`,
+ job.namespace
+ )
);
});
- test('the subnav links to versions', async function(assert) {
+ test('the subnav links to versions', async function (assert) {
await JobDetail.tabFor('versions').visit();
assert.equal(
currentURL(),
- urlWithNamespace(`/jobs/${encodeURIComponent(job.id)}/versions`, job.namespace)
+ urlWithNamespace(
+ `/jobs/${encodeURIComponent(job.id)}/versions`,
+ job.namespace
+ )
);
});
- test('the subnav links to evaluations', async function(assert) {
+ test('the subnav links to evaluations', async function (assert) {
await JobDetail.tabFor('evaluations').visit();
assert.equal(
currentURL(),
- urlWithNamespace(`/jobs/${encodeURIComponent(job.id)}/evaluations`, job.namespace)
+ urlWithNamespace(
+ `/jobs/${encodeURIComponent(job.id)}/evaluations`,
+ job.namespace
+ )
);
});
- test('the title buttons are dependent on job status', async function(assert) {
+ test('the title buttons are dependent on job status', async function (assert) {
if (job.status === 'dead') {
assert.ok(JobDetail.start.isPresent);
assert.notOk(JobDetail.stop.isPresent);
@@ -92,7 +108,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
});
if (context === 'allocations') {
- test('allocations for the job are shown in the overview', async function(assert) {
+ test('allocations for the job are shown in the overview', async function (assert) {
assert.ok(
JobDetail.allocationsSummary.isPresent,
'Allocations are shown in the summary section'
@@ -103,7 +119,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
);
});
- test('clicking in an allocation row navigates to that allocation', async function(assert) {
+ test('clicking in an allocation row navigates to that allocation', async function (assert) {
const allocationRow = JobDetail.allocations[0];
const allocationId = allocationRow.id;
@@ -116,14 +132,18 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
);
});
- test('clicking legend item navigates to a pre-filtered allocations table', async function(assert) {
- const legendItem = JobDetail.allocationsSummary.legend.clickableItems[1];
+ test('clicking legend item navigates to a pre-filtered allocations table', async function (assert) {
+ const legendItem =
+ JobDetail.allocationsSummary.legend.clickableItems[1];
const status = legendItem.label;
await legendItem.click();
const encodedStatus = encodeURIComponent(JSON.stringify([status]));
const expectedURL = new URL(
- urlWithNamespace(`/jobs/${job.name}/clients?status=${encodedStatus}`, job.namespace),
+ urlWithNamespace(
+ `/jobs/${job.name}/clients?status=${encodedStatus}`,
+ job.namespace
+ ),
window.location
);
const gotURL = new URL(currentURL(), window.location);
@@ -131,7 +151,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
assert.deepEqual(gotURL.searchParams, expectedURL.searchParams);
});
- test('clicking in a slice takes you to a pre-filtered allocations table', async function(assert) {
+ test('clicking in a slice takes you to a pre-filtered allocations table', async function (assert) {
const slice = JobDetail.allocationsSummary.slices[1];
const status = slice.label;
await slice.click();
@@ -139,7 +159,9 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
const encodedStatus = encodeURIComponent(JSON.stringify([status]));
const expectedURL = new URL(
urlWithNamespace(
- `/jobs/${encodeURIComponent(job.name)}/allocations?status=${encodedStatus}`,
+ `/jobs/${encodeURIComponent(
+ job.name
+ )}/allocations?status=${encodedStatus}`,
job.namespace
),
window.location
@@ -150,13 +172,19 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
// Sort and compare URL query params.
gotURL.searchParams.sort();
expectedURL.searchParams.sort();
- assert.equal(gotURL.searchParams.toString(), expectedURL.searchParams.toString());
+ assert.equal(
+ gotURL.searchParams.toString(),
+ expectedURL.searchParams.toString()
+ );
});
}
if (context === 'children') {
- test('children for the job are shown in the overview', async function(assert) {
- assert.ok(JobDetail.childrenSummary.isPresent, 'Children are shown in the summary section');
+ test('children for the job are shown in the overview', async function (assert) {
+ assert.ok(
+ JobDetail.childrenSummary.isPresent,
+ 'Children are shown in the summary section'
+ );
assert.ok(
JobDetail.allocationsSummary.isHidden,
'Allocations are not shown in the summary section'
@@ -165,7 +193,7 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
}
for (var testName in additionalTests) {
- test(testName, async function(assert) {
+ test(testName, async function (assert) {
await additionalTests[testName].call(this, job, assert);
});
}
@@ -173,14 +201,18 @@ export default function moduleForJob(title, context, jobFactory, additionalTests
}
// eslint-disable-next-line ember/no-test-module-for
-export function moduleForJobWithClientStatus(title, jobFactory, additionalTests) {
+export function moduleForJobWithClientStatus(
+ title,
+ jobFactory,
+ additionalTests
+) {
let job;
- module(title, function(hooks) {
+ module(title, function (hooks) {
setupApplicationTest(hooks);
setupMirage(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
// Displaying the job status in client requires node:read permission.
const policy = server.create('policy', {
id: 'node-read',
@@ -203,7 +235,7 @@ export function moduleForJobWithClientStatus(title, jobFactory, additionalTests)
status: 'ready',
});
job = jobFactory();
- clients.forEach(c => {
+ clients.forEach((c) => {
server.create('allocation', { jobId: job.id, nodeId: c.id });
});
if (!job.namespace || job.namespace === 'default') {
@@ -213,7 +245,7 @@ export function moduleForJobWithClientStatus(title, jobFactory, additionalTests)
}
});
- test('job status summary is collapsed when not authorized', async function(assert) {
+ test('job status summary is collapsed when not authorized', async function (assert) {
const clientToken = server.create('token', { type: 'client' });
await Tokens.visit();
await Tokens.secret(clientToken.secretId).submit();
@@ -230,29 +262,36 @@ export function moduleForJobWithClientStatus(title, jobFactory, additionalTests)
);
});
- test('the subnav links to clients', async function(assert) {
+ test('the subnav links to clients', async function (assert) {
await JobDetail.tabFor('clients').visit();
assert.equal(
currentURL(),
- urlWithNamespace(`/jobs/${encodeURIComponent(job.id)}/clients`, job.namespace)
+ urlWithNamespace(
+ `/jobs/${encodeURIComponent(job.id)}/clients`,
+ job.namespace
+ )
);
});
- test('job status summary is shown in the overview', async function(assert) {
+ test('job status summary is shown in the overview', async function (assert) {
assert.ok(
JobDetail.jobClientStatusSummary.statusBar.isPresent,
'Summary bar is displayed in the Job Status in Client summary section'
);
});
- test('clicking legend item navigates to a pre-filtered clients table', async function(assert) {
- const legendItem = JobDetail.jobClientStatusSummary.statusBar.legend.clickableItems[0];
+ test('clicking legend item navigates to a pre-filtered clients table', async function (assert) {
+ const legendItem =
+ JobDetail.jobClientStatusSummary.statusBar.legend.clickableItems[0];
const status = legendItem.label;
await legendItem.click();
const encodedStatus = encodeURIComponent(JSON.stringify([status]));
const expectedURL = new URL(
- urlWithNamespace(`/jobs/${job.name}/clients?status=${encodedStatus}`, job.namespace),
+ urlWithNamespace(
+ `/jobs/${job.name}/clients?status=${encodedStatus}`,
+ job.namespace
+ ),
window.location
);
const gotURL = new URL(currentURL(), window.location);
@@ -260,14 +299,17 @@ export function moduleForJobWithClientStatus(title, jobFactory, additionalTests)
assert.deepEqual(gotURL.searchParams, expectedURL.searchParams);
});
- test('clicking in a slice takes you to a pre-filtered clients table', async function(assert) {
+ test('clicking in a slice takes you to a pre-filtered clients table', async function (assert) {
const slice = JobDetail.jobClientStatusSummary.statusBar.slices[0];
const status = slice.label;
await slice.click();
const encodedStatus = encodeURIComponent(JSON.stringify([status]));
const expectedURL = new URL(
- urlWithNamespace(`/jobs/${job.name}/clients?status=${encodedStatus}`, job.namespace),
+ urlWithNamespace(
+ `/jobs/${job.name}/clients?status=${encodedStatus}`,
+ job.namespace
+ ),
window.location
);
const gotURL = new URL(currentURL(), window.location);
@@ -276,11 +318,14 @@ export function moduleForJobWithClientStatus(title, jobFactory, additionalTests)
// Sort and compare URL query params.
gotURL.searchParams.sort();
expectedURL.searchParams.sort();
- assert.equal(gotURL.searchParams.toString(), expectedURL.searchParams.toString());
+ assert.equal(
+ gotURL.searchParams.toString(),
+ expectedURL.searchParams.toString()
+ );
});
for (var testName in additionalTests) {
- test(testName, async function(assert) {
+ test(testName, async function (assert) {
await additionalTests[testName].call(this, job, assert);
});
}
diff --git a/ui/tests/helpers/setup-ability.js b/ui/tests/helpers/setup-ability.js
index c2edd14b7..1d8f49982 100644
--- a/ui/tests/helpers/setup-ability.js
+++ b/ui/tests/helpers/setup-ability.js
@@ -1,10 +1,10 @@
-export default ability => hooks => {
- hooks.beforeEach(function() {
+export default (ability) => (hooks) => {
+ hooks.beforeEach(function () {
this.ability = this.owner.lookup(`ability:${ability}`);
this.can = this.owner.lookup('service:can');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
delete this.ability;
delete this.can;
});
diff --git a/ui/tests/integration/components/agent-monitor-test.js b/ui/tests/integration/components/agent-monitor-test.js
index 2dc4570ee..13947a385 100644
--- a/ui/tests/integration/components/agent-monitor-test.js
+++ b/ui/tests/integration/components/agent-monitor-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable ember/no-string-prototype-extensions */
import { run } from '@ember/runloop';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
@@ -6,27 +7,37 @@ import hbs from 'htmlbars-inline-precompile';
import Pretender from 'pretender';
import sinon from 'sinon';
import { logEncode } from '../../../mirage/data/logs';
-import { selectOpen, selectOpenChoose } from '../../utils/ember-power-select-extensions';
+import {
+ selectOpen,
+ selectOpenChoose,
+} from '../../utils/ember-power-select-extensions';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | agent-monitor', function(hooks) {
+module('Integration | Component | agent-monitor', function (hooks) {
setupRenderingTest(hooks);
const LOG_MESSAGE = 'log message goes here';
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
// Normally this would be called server, but server is a prop of this component.
- this.pretender = new Pretender(function() {
+ this.pretender = new Pretender(function () {
this.get('/v1/regions', () => [200, {}, '[]']);
this.get('/v1/agent/monitor', ({ queryParams }) => [
200,
{},
- logEncode([`[${(queryParams.log_level || 'info').toUpperCase()}] ${LOG_MESSAGE}\n`], 0),
+ logEncode(
+ [
+ `[${(
+ queryParams.log_level || 'info'
+ ).toUpperCase()}] ${LOG_MESSAGE}\n`,
+ ],
+ 0
+ ),
]);
});
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.pretender.shutdown();
});
@@ -40,7 +51,9 @@ module('Integration | Component | agent-monitor', function(hooks) {
@onLevelChange={{this.onLevelChange}} />
`;
- test('basic appearance', async function(assert) {
+ test('basic appearance', async function (assert) {
+ assert.expect(5);
+
this.setProperties({
level: 'info',
client: { id: 'client1' },
@@ -58,7 +71,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when provided with a client, AgentMonitor streams logs for the client', async function(assert) {
+ test('when provided with a client, AgentMonitor streams logs for the client', async function (assert) {
this.setProperties({
level: 'info',
client: { id: 'client1', region: 'us-west-1' },
@@ -76,7 +89,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
assert.notOk(logRequest.url.includes('region='));
});
- test('when provided with a server, AgentMonitor streams logs for the server', async function(assert) {
+ test('when provided with a server, AgentMonitor streams logs for the server', async function (assert) {
this.setProperties({
level: 'warn',
server: { id: 'server1', region: 'us-west-1' },
@@ -94,7 +107,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
assert.notOk(logRequest.url.includes('client_id'));
});
- test('switching levels calls onLevelChange and restarts the logger', async function(assert) {
+ test('switching levels calls onLevelChange and restarts the logger', async function (assert) {
const onLevelChange = sinon.spy();
const newLevel = 'trace';
@@ -107,7 +120,6 @@ module('Integration | Component | agent-monitor', function(hooks) {
run.later(run, run.cancelTimers, INTERVAL);
await render(commonTemplate);
- await settled();
const contentId = await selectOpen('[data-test-level-switcher-parent]');
run.later(run, run.cancelTimers, INTERVAL);
@@ -121,7 +133,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
assert.ok(secondLogRequest.url.includes(`log_level=${newLevel}`));
});
- test('when switching levels, the scrollback is preserved and annotated with a switch message', async function(assert) {
+ test('when switching levels, the scrollback is preserved and annotated with a switch message', async function (assert) {
const newLevel = 'trace';
const onLevelChange = sinon.spy();
@@ -134,8 +146,11 @@ module('Integration | Component | agent-monitor', function(hooks) {
run.later(run, run.cancelTimers, INTERVAL);
await render(commonTemplate);
- await settled();
- assert.equal(find('[data-test-log-cli]').textContent, `[INFO] ${LOG_MESSAGE}\n`);
+
+ assert.equal(
+ find('[data-test-log-cli]').textContent,
+ `[INFO] ${LOG_MESSAGE}\n`
+ );
const contentId = await selectOpen('[data-test-level-switcher-parent]');
run.later(run, run.cancelTimers, INTERVAL);
@@ -148,7 +163,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
);
});
- test('when switching levels and there is no scrollback, there is no appended switch message', async function(assert) {
+ test('when switching levels and there is no scrollback, there is no appended switch message', async function (assert) {
const newLevel = 'trace';
const onLevelChange = sinon.spy();
@@ -158,7 +173,14 @@ module('Integration | Component | agent-monitor', function(hooks) {
{},
queryParams.log_level === 'info'
? logEncode([''], 0)
- : logEncode([`[${(queryParams.log_level || 'info').toUpperCase()}] ${LOG_MESSAGE}\n`], 0),
+ : logEncode(
+ [
+ `[${(
+ queryParams.log_level || 'info'
+ ).toUpperCase()}] ${LOG_MESSAGE}\n`,
+ ],
+ 0
+ ),
]);
this.setProperties({
@@ -170,7 +192,7 @@ module('Integration | Component | agent-monitor', function(hooks) {
run.later(run, run.cancelTimers, INTERVAL);
await render(commonTemplate);
- await settled();
+
assert.equal(find('[data-test-log-cli]').textContent, '');
const contentId = await selectOpen('[data-test-level-switcher-parent]');
@@ -178,6 +200,9 @@ module('Integration | Component | agent-monitor', function(hooks) {
await selectOpenChoose(contentId, newLevel.capitalize());
await settled();
- assert.equal(find('[data-test-log-cli]').textContent, `[TRACE] ${LOG_MESSAGE}\n`);
+ assert.equal(
+ find('[data-test-log-cli]').textContent,
+ `[TRACE] ${LOG_MESSAGE}\n`
+ );
});
});
diff --git a/ui/tests/integration/components/allocation-row-test.js b/ui/tests/integration/components/allocation-row-test.js
index e363f7454..864629e79 100644
--- a/ui/tests/integration/components/allocation-row-test.js
+++ b/ui/tests/integration/components/allocation-row-test.js
@@ -8,10 +8,10 @@ import Response from 'ember-cli-mirage/response';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | allocation row', function(hooks) {
+module('Integration | Component | allocation row', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.token = this.owner.lookup('service:token');
@@ -22,11 +22,11 @@ module('Integration | Component | allocation row', function(hooks) {
window.localStorage.clear();
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('Allocation row polls for stats, even when it errors or has an invalid response', async function(assert) {
+ test('Allocation row polls for stats, even when it errors or has an invalid response', async function (assert) {
const component = this;
let currentFrame = 0;
@@ -38,7 +38,7 @@ module('Integration | Component | allocation row', function(hooks) {
JSON.stringify({ ResourceUsage: generateResources() }),
];
- this.server.get('/client/allocation/:id/stats', function() {
+ this.server.get('/client/allocation/:id/stats', function () {
const response = frames[++currentFrame];
// Disable polling to stop the EC task in the component
@@ -80,7 +80,9 @@ module('Integration | Component | allocation row', function(hooks) {
);
});
- test('Allocation row shows warning when it requires drivers that are unhealthy on the node it is running on', async function(assert) {
+ test('Allocation row shows warning when it requires drivers that are unhealthy on the node it is running on', async function (assert) {
+ assert.expect(2);
+
// Driver health status require node:read permission.
const policy = server.create('policy', {
id: 'node-read',
@@ -101,7 +103,7 @@ module('Integration | Component | allocation row', function(hooks) {
const node = this.server.schema.nodes.first();
const drivers = node.drivers;
- Object.values(drivers).forEach(driver => {
+ Object.values(drivers).forEach((driver) => {
driver.Healthy = false;
driver.Detected = true;
});
@@ -125,11 +127,16 @@ module('Integration | Component | allocation row', function(hooks) {
@context={{context}} />
`);
- assert.ok(find('[data-test-icon="unhealthy-driver"]'), 'Unhealthy driver icon is shown');
+ assert.ok(
+ find('[data-test-icon="unhealthy-driver"]'),
+ 'Unhealthy driver icon is shown'
+ );
await componentA11yAudit(this.element, assert);
});
- test('Allocation row shows an icon indicator when it was preempted', async function(assert) {
+ test('Allocation row shows an icon indicator when it was preempted', async function (assert) {
+ assert.expect(2);
+
const allocId = this.server.create('allocation', 'preempted').id;
const allocation = await this.store.findRecord('allocation', allocId);
@@ -144,14 +151,16 @@ module('Integration | Component | allocation row', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when an allocation is not running, the utilization graphs are omitted', async function(assert) {
+ test('when an allocation is not running, the utilization graphs are omitted', async function (assert) {
+ assert.expect(8);
+
this.setProperties({
context: 'job',
enablePolling: false,
});
// All non-running statuses need to be tested
- ['pending', 'complete', 'failed', 'lost'].forEach(clientStatus =>
+ ['pending', 'complete', 'failed', 'lost'].forEach((clientStatus) =>
this.server.create('allocation', { clientStatus })
);
@@ -161,7 +170,7 @@ module('Integration | Component | allocation row', function(hooks) {
for (const allocation of allocations.toArray()) {
this.set('allocation', allocation);
- await this.render(hbs`
+ await render(hbs`
@@ -25,7 +26,9 @@ module('Integration | Component | app breadcrumbs', function(hooks) {
assert
.dom('[data-test-breadcrumb-default]')
- .exists('We register the default breadcrumb component if no type is specified on the crumb');
+ .exists(
+ 'We register the default breadcrumb component if no type is specified on the crumb'
+ );
const renderedCrumbs = findAll('[data-test-breadcrumb]');
@@ -38,21 +41,20 @@ module('Integration | Component | app breadcrumbs', function(hooks) {
});
});
- test('when we register a crumb with a type property, a dedicated breadcrumb/ component renders', async function(assert) {
+ test('when we register a crumb with a type property, a dedicated breadcrumb/ component renders', async function (assert) {
const crumbs = [
{ label: 'Jobs', args: ['jobs.index'] },
{ type: 'special', label: 'Job', args: ['jobs.job.index'] },
];
this.set('crumbs', crumbs);
- class MockComponent extends Component {}
this.owner.register(
'component:breadcrumbs/special',
setComponentTemplate(
hbs`
Test
`,
- MockComponent
+ templateOnlyComponent()
)
);
diff --git a/ui/tests/integration/components/attributes-table-test.js b/ui/tests/integration/components/attributes-table-test.js
index 8ea493a9f..ac7873838 100644
--- a/ui/tests/integration/components/attributes-table-test.js
+++ b/ui/tests/integration/components/attributes-table-test.js
@@ -7,7 +7,7 @@ import flat from 'flat';
const { flatten } = flat;
-module('Integration | Component | attributes table', function(hooks) {
+module('Integration | Component | attributes table', function (hooks) {
setupRenderingTest(hooks);
const commonAttributes = {
@@ -27,13 +27,17 @@ module('Integration | Component | attributes table', function(hooks) {
},
};
- test('should render a row for each key/value pair in a deep object', async function(assert) {
+ test('should render a row for each key/value pair in a deep object', async function (assert) {
+ assert.expect(2);
+
this.set('attributes', commonAttributes);
await render(hbs``);
const rowsCount = Object.keys(flatten(commonAttributes)).length;
assert.equal(
- this.element.querySelectorAll('[data-test-attributes-section] [data-test-value]').length,
+ this.element.querySelectorAll(
+ '[data-test-attributes-section] [data-test-value]'
+ ).length,
rowsCount,
`Table has ${rowsCount} rows with values`
);
@@ -41,12 +45,20 @@ module('Integration | Component | attributes table', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('should render the full path of key/value pair from the root of the object', async function(assert) {
+ test('should render the full path of key/value pair from the root of the object', async function (assert) {
this.set('attributes', commonAttributes);
await render(hbs``);
- assert.equal(find('[data-test-key]').textContent.trim(), 'key', 'Row renders the key');
- assert.equal(find('[data-test-value]').textContent.trim(), 'value', 'Row renders the value');
+ assert.equal(
+ find('[data-test-key]').textContent.trim(),
+ 'key',
+ 'Row renders the key'
+ );
+ assert.equal(
+ find('[data-test-value]').textContent.trim(),
+ 'value',
+ 'Row renders the value'
+ );
const deepRow = findAll('[data-test-attributes-section]')[8];
assert.equal(
@@ -59,10 +71,13 @@ module('Integration | Component | attributes table', function(hooks) {
'so.are.deeply.',
'The prefix is faded to put emphasis on the attribute'
);
- assert.equal(deepRow.querySelector('[data-test-value]').textContent.trim(), 'properties');
+ assert.equal(
+ deepRow.querySelector('[data-test-value]').textContent.trim(),
+ 'properties'
+ );
});
- test('should render a row for key/value pairs even when the value is another object', async function(assert) {
+ test('should render a row for key/value pairs even when the value is another object', async function (assert) {
this.set('attributes', commonAttributes);
await render(hbs``);
diff --git a/ui/tests/integration/components/breadcrumbs-test.js b/ui/tests/integration/components/breadcrumbs-test.js
index 5d24329ff..b8fe92503 100644
--- a/ui/tests/integration/components/breadcrumbs-test.js
+++ b/ui/tests/integration/components/breadcrumbs-test.js
@@ -4,10 +4,10 @@ import { setupRenderingTest } from 'ember-qunit';
import { click, findAll, render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
-module('Integration | Component | breadcrumbs', function(hooks) {
+module('Integration | Component | breadcrumbs', function (hooks) {
setupRenderingTest(hooks);
- test('it declaratively renders a list of registered crumbs', async function(assert) {
+ test('it declaratively renders a list of registered crumbs', async function (assert) {
this.set('isRegistered', false);
this.set('toggleCrumb', () => this.set('isRegistered', !this.isRegistered));
await render(hbs`
@@ -25,8 +25,12 @@ module('Integration | Component | breadcrumbs', function(hooks) {
{{/if}}
`);
- assert.dom('[data-test-crumb]').exists({ count: 1 }, 'We register one crumb');
- assert.dom('[data-test-crumb]').hasText('Zoey', 'The first registered crumb is Zoey');
+ assert
+ .dom('[data-test-crumb]')
+ .exists({ count: 1 }, 'We register one crumb');
+ assert
+ .dom('[data-test-crumb]')
+ .hasText('Zoey', 'The first registered crumb is Zoey');
await click('[data-test-button]');
const crumbs = await findAll('[data-test-crumb]');
@@ -36,19 +40,30 @@ module('Integration | Component | breadcrumbs', function(hooks) {
.exists({ count: 2 }, 'The second crumb registered successfully');
assert
.dom(crumbs[0])
- .hasText('Zoey', 'Breadcrumbs maintain the order in which they are declared');
+ .hasText(
+ 'Zoey',
+ 'Breadcrumbs maintain the order in which they are declared'
+ );
assert
.dom(crumbs[1])
- .hasText('Tomster', 'Breadcrumbs maintain the order in which they are declared');
+ .hasText(
+ 'Tomster',
+ 'Breadcrumbs maintain the order in which they are declared'
+ );
await click('[data-test-button]');
- assert.dom('[data-test-crumb]').exists({ count: 1 }, 'We deregister one crumb');
assert
.dom('[data-test-crumb]')
- .hasText('Zoey', 'Zoey remains in the template after Tomster deregisters');
+ .exists({ count: 1 }, 'We deregister one crumb');
+ assert
+ .dom('[data-test-crumb]')
+ .hasText(
+ 'Zoey',
+ 'Zoey remains in the template after Tomster deregisters'
+ );
});
- test('it can register complex crumb objects', async function(assert) {
+ test('it can register complex crumb objects', async function (assert) {
await render(hbs`
@@ -62,6 +77,9 @@ module('Integration | Component | breadcrumbs', function(hooks) {
assert
.dom('[data-test-crumb]')
- .hasText('Tomster', 'We can access the registered breadcrumbs in the template');
+ .hasText(
+ 'Tomster',
+ 'We can access the registered breadcrumbs in the template'
+ );
});
});
diff --git a/ui/tests/integration/components/copy-button-test.js b/ui/tests/integration/components/copy-button-test.js
index 734294f37..acc4579cf 100644
--- a/ui/tests/integration/components/copy-button-test.js
+++ b/ui/tests/integration/components/copy-button-test.js
@@ -6,19 +6,26 @@ import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import sinon from 'sinon';
-import { triggerCopyError, triggerCopySuccess } from 'ember-cli-clipboard/test-support';
+import {
+ triggerCopyError,
+ triggerCopySuccess,
+} from 'ember-cli-clipboard/test-support';
-module('Integration | Component | copy-button', function(hooks) {
+module('Integration | Component | copy-button', function (hooks) {
setupRenderingTest(hooks);
- test('it shows the copy icon by default', async function(assert) {
+ test('it shows the copy icon by default', async function (assert) {
+ assert.expect(2);
+
await render(hbs``);
assert.dom('.copy-button .icon-is-copy-action').exists();
await componentA11yAudit(this.element, assert);
});
- test('it shows the success icon on success and resets afterward', async function(assert) {
+ test('it shows the success icon on success and resets afterward', async function (assert) {
+ assert.expect(4);
+
const clock = sinon.useFakeTimers({ shouldAdvanceTime: true });
await render(hbs``);
@@ -37,7 +44,9 @@ module('Integration | Component | copy-button', function(hooks) {
clock.restore();
});
- test('it shows the error icon on error', async function(assert) {
+ test('it shows the error icon on error', async function (assert) {
+ assert.expect(2);
+
await render(hbs``);
await click('.copy-button button');
diff --git a/ui/tests/integration/components/das/dismissed-test.js b/ui/tests/integration/components/das/dismissed-test.js
index c990e964f..c3b4ed741 100644
--- a/ui/tests/integration/components/das/dismissed-test.js
+++ b/ui/tests/integration/components/das/dismissed-test.js
@@ -5,14 +5,16 @@ import { hbs } from 'ember-cli-htmlbars';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import sinon from 'sinon';
-module('Integration | Component | das/dismissed', function(hooks) {
+module('Integration | Component | das/dismissed', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
});
- test('it renders the dismissal interstitial with a button to proceed and an option to never show again and proceeds manually', async function(assert) {
+ test('it renders the dismissal interstitial with a button to proceed and an option to never show again and proceeds manually', async function (assert) {
+ assert.expect(3);
+
const proceedSpy = sinon.spy();
this.set('proceedSpy', proceedSpy);
@@ -24,10 +26,15 @@ module('Integration | Component | das/dismissed', function(hooks) {
await click('[data-test-understood]');
assert.ok(proceedSpy.calledWith({ manuallyDismissed: true }));
- assert.equal(window.localStorage.getItem('nomadRecommendationDismssalUnderstood'), 'true');
+ assert.equal(
+ window.localStorage.getItem('nomadRecommendationDismssalUnderstood'),
+ 'true'
+ );
});
- test('it renders the dismissal interstitial with no button when the option to never show again has been chosen and proceeds automatically', async function(assert) {
+ test('it renders the dismissal interstitial with no button when the option to never show again has been chosen and proceeds automatically', async function (assert) {
+ assert.expect(3);
+
window.localStorage.setItem('nomadRecommendationDismssalUnderstood', true);
const proceedSpy = sinon.spy();
diff --git a/ui/tests/integration/components/das/recommendation-card-test.js b/ui/tests/integration/components/das/recommendation-card-test.js
index c0d0f956f..73f229bbe 100644
--- a/ui/tests/integration/components/das/recommendation-card-test.js
+++ b/ui/tests/integration/components/das/recommendation-card-test.js
@@ -13,10 +13,10 @@ import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { set } from '@ember/object';
-module('Integration | Component | das/recommendation-card', function(hooks) {
+module('Integration | Component | das/recommendation-card', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
const mockRouter = Service.extend({
init() {
this._super(...arguments);
@@ -30,7 +30,9 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
this.owner.register('service:router', mockRouter);
});
- test('it renders a recommendation card', async function(assert) {
+ test('it renders a recommendation card', async function (assert) {
+ assert.expect(49);
+
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -103,15 +105,17 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.equal(RecommendationCard.totalsTable.current.cpu.text, '275 MHz');
assert.equal(RecommendationCard.totalsTable.current.memory.text, '384 MiB');
- RecommendationCard.totalsTable.recommended.cpu.as(RecommendedCpu => {
+ RecommendationCard.totalsTable.recommended.cpu.as((RecommendedCpu) => {
assert.equal(RecommendedCpu.text, '200 MHz');
assert.ok(RecommendedCpu.isDecrease);
});
- RecommendationCard.totalsTable.recommended.memory.as(RecommendedMemory => {
- assert.equal(RecommendedMemory.text, '512 MiB');
- assert.ok(RecommendedMemory.isIncrease);
- });
+ RecommendationCard.totalsTable.recommended.memory.as(
+ (RecommendedMemory) => {
+ assert.equal(RecommendedMemory.text, '512 MiB');
+ assert.ok(RecommendedMemory.isIncrease);
+ }
+ );
assert.equal(RecommendationCard.totalsTable.unitDiff.cpu, '-75 MHz');
assert.equal(RecommendationCard.totalsTable.unitDiff.memory, '+128 MiB');
@@ -127,18 +131,28 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
)
);
- assert.equal(RecommendationCard.activeTask.totalsTable.current.cpu.text, '150 MHz');
- assert.equal(RecommendationCard.activeTask.totalsTable.current.memory.text, '128 MiB');
+ assert.equal(
+ RecommendationCard.activeTask.totalsTable.current.cpu.text,
+ '150 MHz'
+ );
+ assert.equal(
+ RecommendationCard.activeTask.totalsTable.current.memory.text,
+ '128 MiB'
+ );
- RecommendationCard.activeTask.totalsTable.recommended.cpu.as(RecommendedCpu => {
- assert.equal(RecommendedCpu.text, '50 MHz');
- assert.ok(RecommendedCpu.isDecrease);
- });
+ RecommendationCard.activeTask.totalsTable.recommended.cpu.as(
+ (RecommendedCpu) => {
+ assert.equal(RecommendedCpu.text, '50 MHz');
+ assert.ok(RecommendedCpu.isDecrease);
+ }
+ );
- RecommendationCard.activeTask.totalsTable.recommended.memory.as(RecommendedMemory => {
- assert.equal(RecommendedMemory.text, '192 MiB');
- assert.ok(RecommendedMemory.isIncrease);
- });
+ RecommendationCard.activeTask.totalsTable.recommended.memory.as(
+ (RecommendedMemory) => {
+ assert.equal(RecommendedMemory.text, '192 MiB');
+ assert.ok(RecommendedMemory.isIncrease);
+ }
+ );
assert.equal(RecommendationCard.activeTask.charts.length, 2);
assert.equal(
@@ -152,7 +166,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.equal(RecommendationCard.togglesTable.tasks.length, 2);
- await RecommendationCard.togglesTable.tasks[0].as(async FirstTask => {
+ await RecommendationCard.togglesTable.tasks[0].as(async (FirstTask) => {
assert.equal(FirstTask.name, 'jortle');
assert.ok(FirstTask.isActive);
@@ -172,25 +186,29 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.equal(RecommendationCard.activeTask.name, 'jortle task');
- RecommendationCard.totalsTable.recommended.cpu.as(RecommendedCpu => {
+ RecommendationCard.totalsTable.recommended.cpu.as((RecommendedCpu) => {
assert.equal(RecommendedCpu.text, '300 MHz');
assert.ok(RecommendedCpu.isIncrease);
});
- RecommendationCard.activeTask.totalsTable.recommended.cpu.as(RecommendedCpu => {
- assert.equal(RecommendedCpu.text, '150 MHz');
- assert.ok(RecommendedCpu.isNeutral);
- });
+ RecommendationCard.activeTask.totalsTable.recommended.cpu.as(
+ (RecommendedCpu) => {
+ assert.equal(RecommendedCpu.text, '150 MHz');
+ assert.ok(RecommendedCpu.isNeutral);
+ }
+ );
await RecommendationCard.togglesTable.toggleAllMemory.toggle();
assert.notOk(RecommendationCard.togglesTable.tasks[0].memory.isActive);
assert.notOk(RecommendationCard.togglesTable.tasks[1].memory.isActive);
- RecommendationCard.totalsTable.recommended.memory.as(RecommendedMemory => {
- assert.equal(RecommendedMemory.text, '384 MiB');
- assert.ok(RecommendedMemory.isNeutral);
- });
+ RecommendationCard.totalsTable.recommended.memory.as(
+ (RecommendedMemory) => {
+ assert.equal(RecommendedMemory.text, '384 MiB');
+ assert.ok(RecommendedMemory.isNeutral);
+ }
+ );
await RecommendationCard.togglesTable.tasks[1].click();
@@ -198,12 +216,15 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.ok(RecommendationCard.togglesTable.tasks[1].isActive);
assert.equal(RecommendationCard.activeTask.name, 'tortle task');
- assert.equal(RecommendationCard.activeTask.totalsTable.current.cpu.text, '125 MHz');
+ assert.equal(
+ RecommendationCard.activeTask.totalsTable.current.cpu.text,
+ '125 MHz'
+ );
await componentA11yAudit(this.element, assert);
});
- test('it doesn’t have header toggles when there’s only one task', async function(assert) {
+ test('it doesn’t have header toggles when there’s only one task', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -243,7 +264,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.notOk(RecommendationCard.togglesTable.toggleAllMemory.isPresent);
});
- test('it disables the accept button when all recommendations are disabled', async function(assert) {
+ test('it disables the accept button when all recommendations are disabled', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -284,7 +305,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.ok(RecommendationCard.acceptButton.isDisabled);
});
- test('it doesn’t show a toggle or chart when there’s no recommendation for that resource', async function(assert) {
+ test('it doesn’t show a toggle or chart when there’s no recommendation for that resource', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -317,7 +338,10 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
await render(hbs``);
- assert.equal(RecommendationCard.totalsTable.recommended.memory.text, '128 MiB');
+ assert.equal(
+ RecommendationCard.totalsTable.recommended.memory.text,
+ '128 MiB'
+ );
assert.equal(RecommendationCard.totalsTable.unitDiff.memory, '0 MiB');
assert.equal(RecommendationCard.totalsTable.percentDiff.memory, '+0%');
@@ -330,7 +354,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.notOk(RecommendationCard.activeTask.memoryChart.isPresent);
});
- test('it disables a resource’s toggle all toggle when there are no recommendations for it', async function(assert) {
+ test('it disables a resource’s toggle all toggle when there are no recommendations for it', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -380,7 +404,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
assert.notOk(RecommendationCard.activeTask.memoryChart.isPresent);
});
- test('it renders diff calculations in a sentence', async function(assert) {
+ test('it renders diff calculations in a sentence', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -507,7 +531,7 @@ module('Integration | Component | das/recommendation-card', function(hooks) {
);
});
- test('it renders diff calculations in a sentence with no aggregation for one allocatio', async function(assert) {
+ test('it renders diff calculations in a sentence with no aggregation for one allocatio', async function (assert) {
const task1 = {
name: 'jortle',
reservedCPU: 150,
@@ -601,9 +625,14 @@ class MockRecommendationSummary {
@action
toggleAllRecommendationsForResource(resource, enabled) {
if (enabled) {
- this.excludedRecommendations = this.excludedRecommendations.rejectBy('resource', resource);
+ this.excludedRecommendations = this.excludedRecommendations.rejectBy(
+ 'resource',
+ resource
+ );
} else {
- this.excludedRecommendations.pushObjects(this.recommendations.filterBy('resource', resource));
+ this.excludedRecommendations.pushObjects(
+ this.recommendations.filterBy('resource', resource)
+ );
}
}
}
diff --git a/ui/tests/integration/components/das/recommendation-chart-test.js b/ui/tests/integration/components/das/recommendation-chart-test.js
index 3df2cb6fc..53b7d6c9e 100644
--- a/ui/tests/integration/components/das/recommendation-chart-test.js
+++ b/ui/tests/integration/components/das/recommendation-chart-test.js
@@ -4,10 +4,12 @@ import { render, triggerEvent } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | das/recommendation-chart', function(hooks) {
+module('Integration | Component | das/recommendation-chart', function (hooks) {
setupRenderingTest(hooks);
- test('it renders a chart for a recommended CPU increase', async function(assert) {
+ test('it renders a chart for a recommended CPU increase', async function (assert) {
+ assert.expect(5);
+
this.set('resource', 'CPU');
this.set('current', 1312);
this.set('recommended', 1919);
@@ -29,7 +31,9 @@ module('Integration | Component | das/recommendation-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('it renders a chart for a recommended memory decrease', async function(assert) {
+ test('it renders a chart for a recommended memory decrease', async function (assert) {
+ assert.expect(5);
+
this.set('resource', 'MemoryMB');
this.set('current', 1919);
this.set('recommended', 1312);
@@ -51,7 +55,7 @@ module('Integration | Component | das/recommendation-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('it handles the maximum being far beyond the recommended', async function(assert) {
+ test('it handles the maximum being far beyond the recommended', async function (assert) {
this.set('resource', 'CPU');
this.set('current', 1312);
this.set('recommended', 1919);
@@ -74,7 +78,9 @@ module('Integration | Component | das/recommendation-chart', function(hooks) {
assert.ok(maxLine.getAttribute('x1') < chartSvg.clientWidth);
});
- test('it can be disabled and will show no delta', async function(assert) {
+ test('it can be disabled and will show no delta', async function (assert) {
+ assert.expect(6);
+
this.set('resource', 'CPU');
this.set('current', 1312);
this.set('recommended', 1919);
@@ -99,7 +105,7 @@ module('Integration | Component | das/recommendation-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the stats labels shift aligment and disappear to account for space', async function(assert) {
+ test('the stats labels shift aligment and disappear to account for space', async function (assert) {
this.set('resource', 'CPU');
this.set('current', 50);
this.set('recommended', 100);
@@ -140,7 +146,7 @@ module('Integration | Component | das/recommendation-chart', function(hooks) {
assert.dom('[data-test-label=p99]').hasClass('hidden');
});
- test('a legend tooltip shows the sorted stats values on hover', async function(assert) {
+ test('a legend tooltip shows the sorted stats values on hover', async function (assert) {
this.set('resource', 'CPU');
this.set('current', 50);
this.set('recommended', 101);
diff --git a/ui/tests/integration/components/flex-masonry-test.js b/ui/tests/integration/components/flex-masonry-test.js
index 7134f9397..a27b64d1e 100644
--- a/ui/tests/integration/components/flex-masonry-test.js
+++ b/ui/tests/integration/components/flex-masonry-test.js
@@ -1,22 +1,24 @@
import { htmlSafe } from '@ember/template';
-import { click, find, findAll, settled } from '@ember/test-helpers';
+import { click, find, findAll, render, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
// Used to prevent XSS warnings in console
-const h = height => htmlSafe(`height:${height}px`);
+const h = (height) => htmlSafe(`height:${height}px`);
-module('Integration | Component | FlexMasonry', function(hooks) {
+module('Integration | Component | FlexMasonry', function (hooks) {
setupRenderingTest(hooks);
- test('presents as a single div when @items is empty', async function(assert) {
+ test('presents as a single div when @items is empty', async function (assert) {
+ assert.expect(4);
+
this.setProperties({
items: [],
});
- await this.render(hbs`
+ await render(hbs`
@@ -31,13 +33,13 @@ module('Integration | Component | FlexMasonry', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('each item in @items gets wrapped in a flex-masonry-item wrapper', async function(assert) {
+ test('each item in @items gets wrapped in a flex-masonry-item wrapper', async function (assert) {
this.setProperties({
items: ['one', 'two', 'three'],
columns: 2,
});
- await this.render(hbs`
+ await render(hbs`
@@ -45,11 +47,14 @@ module('Integration | Component | FlexMasonry', function(hooks) {
`);
- assert.equal(findAll('[data-test-flex-masonry-item]').length, this.items.length);
+ assert.equal(
+ findAll('[data-test-flex-masonry-item]').length,
+ this.items.length
+ );
});
- test('the @withSpacing arg adds the with-spacing class', async function(assert) {
- await this.render(hbs`
+ test('the @withSpacing arg adds the with-spacing class', async function (assert) {
+ await render(hbs`
`);
- assert.ok(find('[data-test-flex-masonry]').classList.contains('with-spacing'));
+ assert.ok(
+ find('[data-test-flex-masonry]').classList.contains('with-spacing')
+ );
});
- test('individual items along with the reflow action are yielded', async function(assert) {
+ test('individual items along with the reflow action are yielded', async function (assert) {
this.setProperties({
items: ['one', 'two'],
columns: 2,
height: h(50),
});
- await this.render(hbs`
+ await render(hbs`
@@ -86,11 +93,13 @@ module('Integration | Component | FlexMasonry', function(hooks) {
// The height of the div changes when reflow is called
await click('[data-test-flex-masonry-item]:first-child div');
- await settled();
+
assert.equal(div.style.maxHeight, '501px');
});
- test('items are rendered to the DOM in the order they were passed into the component', async function(assert) {
+ test('items are rendered to the DOM in the order they were passed into the component', async function (assert) {
+ assert.expect(4);
+
this.setProperties({
items: [
{ text: 'One', height: h(20) },
@@ -101,7 +110,7 @@ module('Integration | Component | FlexMasonry', function(hooks) {
columns: 2,
});
- await this.render(hbs`
+ await render(hbs`
@@ -114,7 +123,9 @@ module('Integration | Component | FlexMasonry', function(hooks) {
});
});
- test('each item gets an order property', async function(assert) {
+ test('each item gets an order property', async function (assert) {
+ assert.expect(4);
+
this.setProperties({
items: [
{ text: 'One', height: h(20), expectedOrder: 0 },
@@ -125,7 +136,7 @@ module('Integration | Component | FlexMasonry', function(hooks) {
columns: 2,
});
- await this.render(hbs`
+ await render(hbs`
@@ -138,7 +149,9 @@ module('Integration | Component | FlexMasonry', function(hooks) {
});
});
- test('the last item in each column gets a specific flex-basis value', async function(assert) {
+ test('the last item in each column gets a specific flex-basis value', async function (assert) {
+ assert.expect(4);
+
this.setProperties({
items: [
{ text: 'One', height: h(20) },
@@ -151,7 +164,7 @@ module('Integration | Component | FlexMasonry', function(hooks) {
columns: 4,
});
- await this.render(hbs`
+ await render(hbs`
@@ -161,12 +174,15 @@ module('Integration | Component | FlexMasonry', function(hooks) {
findAll('[data-test-flex-masonry-item]').forEach((el, index) => {
if (el.style.flexBasis) {
+ /* eslint-disable-next-line qunit/no-conditional-assertions */
assert.equal(el.style.flexBasis, this.items[index].flexBasis);
}
});
});
- test('when a multi-column layout becomes a single column layout, all inline-styles are reset', async function(assert) {
+ test('when a multi-column layout becomes a single column layout, all inline-styles are reset', async function (assert) {
+ assert.expect(14);
+
this.setProperties({
items: [
{ text: 'One', height: h(20) },
@@ -179,7 +195,7 @@ module('Integration | Component | FlexMasonry', function(hooks) {
columns: 4,
});
- await this.render(hbs`
+ await render(hbs`
@@ -192,7 +208,7 @@ module('Integration | Component | FlexMasonry', function(hooks) {
this.set('columns', 1);
await settled();
- findAll('[data-test-flex-masonry-item]').forEach(el => {
+ findAll('[data-test-flex-masonry-item]').forEach((el) => {
assert.equal(el.style.flexBasis, '');
assert.equal(el.style.order, '');
});
diff --git a/ui/tests/integration/components/fs/file-test.js b/ui/tests/integration/components/fs/file-test.js
index 79d844637..29ad9c703 100644
--- a/ui/tests/integration/components/fs/file-test.js
+++ b/ui/tests/integration/components/fs/file-test.js
@@ -9,25 +9,37 @@ import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
const { assign } = Object;
const HOST = '1.1.1.1:1111';
-module('Integration | Component | fs/file', function(hooks) {
+module('Integration | Component | fs/file', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
- this.server = new Pretender(function() {
+ hooks.beforeEach(function () {
+ this.server = new Pretender(function () {
this.get('/v1/agent/members', () => [
200,
{},
JSON.stringify({ ServerRegion: 'default', Members: [] }),
]);
- this.get('/v1/regions', () => [200, {}, JSON.stringify(['default', 'region-2'])]);
- this.get('/v1/client/fs/stream/:alloc_id', () => [200, {}, logEncode(['Hello World'], 0)]);
+ this.get('/v1/regions', () => [
+ 200,
+ {},
+ JSON.stringify(['default', 'region-2']),
+ ]);
+ this.get('/v1/client/fs/stream/:alloc_id', () => [
+ 200,
+ {},
+ logEncode(['Hello World'], 0),
+ ]);
this.get('/v1/client/fs/cat/:alloc_id', () => [200, {}, 'Hello World']);
- this.get('/v1/client/fs/readat/:alloc_id', () => [200, {}, 'Hello World']);
+ this.get('/v1/client/fs/readat/:alloc_id', () => [
+ 200,
+ {},
+ 'Hello World',
+ ]);
});
this.system = this.owner.lookup('service:system');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
@@ -64,7 +76,9 @@ module('Integration | Component | fs/file', function(hooks) {
props
);
- test('When a file is text-based, the file mode is streaming', async function(assert) {
+ test('When a file is text-based, the file mode is streaming', async function (assert) {
+ assert.expect(3);
+
const props = makeProps(fileStat('text/plain', 500));
this.setProperties(props);
@@ -82,7 +96,9 @@ module('Integration | Component | fs/file', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When a file is an image, the file mode is image', async function(assert) {
+ test('When a file is an image, the file mode is image', async function (assert) {
+ assert.expect(3);
+
const props = makeProps(fileStat('image/png', 1234));
this.setProperties(props);
@@ -100,7 +116,9 @@ module('Integration | Component | fs/file', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When the file is neither text-based or an image, the unsupported file type empty state is shown', async function(assert) {
+ test('When the file is neither text-based or an image, the unsupported file type empty state is shown', async function (assert) {
+ assert.expect(4);
+
const props = makeProps(fileStat('wat/ohno', 1234));
this.setProperties(props);
@@ -114,11 +132,14 @@ module('Integration | Component | fs/file', function(hooks) {
find('[data-test-file-box] [data-test-log-cli]'),
'The streaming file component was not rendered'
);
- assert.ok(find('[data-test-unsupported-type]'), 'Unsupported file type message is shown');
+ assert.ok(
+ find('[data-test-unsupported-type]'),
+ 'Unsupported file type message is shown'
+ );
await componentA11yAudit(this.element, assert);
});
- test('The unsupported file type empty state includes a link to the raw file', async function(assert) {
+ test('The unsupported file type empty state includes a link to the raw file', async function (assert) {
const props = makeProps(fileStat('wat/ohno', 1234));
this.setProperties(props);
@@ -135,7 +156,7 @@ module('Integration | Component | fs/file', function(hooks) {
);
});
- test('The view raw button goes to the correct API url', async function(assert) {
+ test('The view raw button goes to the correct API url', async function (assert) {
const props = makeProps(fileStat('image/png', 1234));
this.setProperties(props);
@@ -154,7 +175,7 @@ module('Integration | Component | fs/file', function(hooks) {
);
});
- test('The view raw button respects the active region', async function(assert) {
+ test('The view raw button respects the active region', async function (assert) {
const region = 'region-2';
window.localStorage.nomadActiveRegion = region;
@@ -178,7 +199,7 @@ module('Integration | Component | fs/file', function(hooks) {
);
});
- test('The head and tail buttons are not shown when the file is small', async function(assert) {
+ test('The head and tail buttons are not shown when the file is small', async function (assert) {
const props = makeProps(fileStat('application/json', 5000));
this.setProperties(props);
@@ -195,7 +216,7 @@ module('Integration | Component | fs/file', function(hooks) {
assert.ok(find('[data-test-log-action="tail"]'), 'Tail button is shown');
});
- test('The head and tail buttons are not shown for an image file', async function(assert) {
+ test('The head and tail buttons are not shown for an image file', async function (assert) {
const props = makeProps(fileStat('image/svg', 5000));
this.setProperties(props);
@@ -212,7 +233,9 @@ module('Integration | Component | fs/file', function(hooks) {
assert.notOk(find('[data-test-log-action="tail"]'), 'Still no tail button');
});
- test('Yielded content goes in the top-left header area', async function(assert) {
+ test('Yielded content goes in the top-left header area', async function (assert) {
+ assert.expect(2);
+
const props = makeProps(fileStat('image/svg', 5000));
this.setProperties(props);
@@ -230,7 +253,7 @@ module('Integration | Component | fs/file', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('The body is full-bleed and dark when the file is streaming', async function(assert) {
+ test('The body is full-bleed and dark when the file is streaming', async function (assert) {
const props = makeProps(fileStat('application/json', 5000));
this.setProperties(props);
@@ -241,7 +264,7 @@ module('Integration | Component | fs/file', function(hooks) {
assert.ok(classes.includes('is-full-bleed'), 'Body is full-bleed');
});
- test('The body has padding and a light background when the file is not streaming', async function(assert) {
+ test('The body has padding and a light background when the file is not streaming', async function (assert) {
const props = makeProps(fileStat('image/jpeg', 5000));
this.setProperties(props);
@@ -257,6 +280,9 @@ module('Integration | Component | fs/file', function(hooks) {
classes = Array.from(find('[data-test-file-box]').classList);
assert.notOk(classes.includes('is-dark'), 'Body is still not dark');
- assert.notOk(classes.includes('is-full-bleed'), 'Body is still not full-bleed');
+ assert.notOk(
+ classes.includes('is-full-bleed'),
+ 'Body is still not full-bleed'
+ );
});
});
diff --git a/ui/tests/integration/components/gauge-chart-test.js b/ui/tests/integration/components/gauge-chart-test.js
index 910c31922..fb10f5f7a 100644
--- a/ui/tests/integration/components/gauge-chart-test.js
+++ b/ui/tests/integration/components/gauge-chart-test.js
@@ -8,7 +8,7 @@ import gaugeChart from 'nomad-ui/tests/pages/components/gauge-chart';
const GaugeChart = create(gaugeChart());
-module('Integration | Component | gauge chart', function(hooks) {
+module('Integration | Component | gauge chart', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -17,7 +17,9 @@ module('Integration | Component | gauge chart', function(hooks) {
label: 'Gauge',
});
- test('presents as an svg, a formatted percentage, and a label', async function(assert) {
+ test('presents as an svg, a formatted percentage, and a label', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
this.setProperties(props);
@@ -35,7 +37,7 @@ module('Integration | Component | gauge chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the width of the chart is determined based on the container and the height is a function of the width', async function(assert) {
+ test('the width of the chart is determined based on the container and the height is a function of the width', async function (assert) {
const props = commonProperties();
this.setProperties(props);
diff --git a/ui/tests/integration/components/image-file-test.js b/ui/tests/integration/components/image-file-test.js
index 80299e815..60f0e6813 100644
--- a/ui/tests/integration/components/image-file-test.js
+++ b/ui/tests/integration/components/image-file-test.js
@@ -1,4 +1,4 @@
-import { find, settled } from '@ember/test-helpers';
+import { find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -7,7 +7,7 @@ import sinon from 'sinon';
import RSVP from 'rsvp';
import { formatBytes } from 'nomad-ui/utils/units';
-module('Integration | Component | image file', function(hooks) {
+module('Integration | Component | image file', function (hooks) {
setupRenderingTest(hooks);
const commonTemplate = hbs`
@@ -20,10 +20,12 @@ module('Integration | Component | image file', function(hooks) {
size: 123456,
};
- test('component displays the image', async function(assert) {
+ test('component displays the image', async function (assert) {
+ assert.expect(3);
+
this.setProperties(commonProperties);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(find('img'), 'Image is in the DOM');
assert.equal(
@@ -35,10 +37,10 @@ module('Integration | Component | image file', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the image is wrapped in an anchor that links directly to the image', async function(assert) {
+ test('the image is wrapped in an anchor that links directly to the image', async function (assert) {
this.setProperties(commonProperties);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(find('a'), 'Anchor');
assert.ok(find('a > img'), 'Image in anchor');
@@ -47,7 +49,11 @@ module('Integration | Component | image file', function(hooks) {
commonProperties.src,
`href is ${commonProperties.src}`
);
- assert.equal(find('a').getAttribute('target'), '_blank', 'Anchor opens to a new tab');
+ assert.equal(
+ find('a').getAttribute('target'),
+ '_blank',
+ 'Anchor opens to a new tab'
+ );
assert.equal(
find('a').getAttribute('rel'),
'noopener noreferrer',
@@ -55,13 +61,13 @@ module('Integration | Component | image file', function(hooks) {
);
});
- test('component updates image meta when the image loads', async function(assert) {
+ test('component updates image meta when the image loads', async function (assert) {
const { spy, wrapper, notifier } = notifyingSpy();
this.setProperties(commonProperties);
this.set('spy', wrapper);
- this.render(hbs`
+ render(hbs`
`);
@@ -69,11 +75,10 @@ module('Integration | Component | image file', function(hooks) {
assert.ok(spy.calledOnce);
});
- test('component shows the width, height, and size of the image', async function(assert) {
+ test('component shows the width, height, and size of the image', async function (assert) {
this.setProperties(commonProperties);
- await this.render(commonTemplate);
- await settled();
+ await render(commonTemplate);
const statsEl = find('[data-test-file-stats]');
assert.ok(
@@ -81,7 +86,9 @@ module('Integration | Component | image file', function(hooks) {
'Width and height are formatted correctly'
);
assert.ok(
- statsEl.textContent.trim().endsWith(formatBytes(commonProperties.size) + ')'),
+ statsEl.textContent
+ .trim()
+ .endsWith(formatBytes(commonProperties.size) + ')'),
'Human-formatted size is included'
);
});
@@ -90,7 +97,7 @@ module('Integration | Component | image file', function(hooks) {
function notifyingSpy() {
// The notifier must resolve when the spy wrapper is called
let dispatch;
- const notifier = new RSVP.Promise(resolve => {
+ const notifier = new RSVP.Promise((resolve) => {
dispatch = resolve;
});
diff --git a/ui/tests/integration/components/job-client-status-bar-test.js b/ui/tests/integration/components/job-client-status-bar-test.js
index 827c033c7..b4adac86d 100644
--- a/ui/tests/integration/components/job-client-status-bar-test.js
+++ b/ui/tests/integration/components/job-client-status-bar-test.js
@@ -9,7 +9,7 @@ import jobClientStatusBar from 'nomad-ui/tests/pages/components/job-client-statu
const JobClientStatusBar = create(jobClientStatusBar());
-module('Integration | Component | job-client-status-bar', function(hooks) {
+module('Integration | Component | job-client-status-bar', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -42,7 +42,9 @@ module('Integration | Component | job-client-status-bar', function(hooks) {
@isNarrow={{isNarrow}}
/>`;
- test('it renders', async function(assert) {
+ test('it renders', async function (assert) {
+ assert.expect(2);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -51,7 +53,7 @@ module('Integration | Component | job-client-status-bar', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('it fires the onBarClick handler method when clicking a bar in the chart', async function(assert) {
+ test('it fires the onBarClick handler method when clicking a bar in the chart', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -59,7 +61,7 @@ module('Integration | Component | job-client-status-bar', function(hooks) {
assert.ok(props.onSliceClick.calledOnce);
});
- test('it handles an update to client status property', async function(assert) {
+ test('it handles an update to client status property', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -67,7 +69,11 @@ module('Integration | Component | job-client-status-bar', function(hooks) {
...props,
jobClientStatus: {
...props.jobClientStatus,
- byStatus: { ...props.jobClientStatus.byStatus, starting: [], running: ['someNodeId'] },
+ byStatus: {
+ ...props.jobClientStatus.byStatus,
+ starting: [],
+ running: ['someNodeId'],
+ },
},
};
this.setProperties(newProps);
diff --git a/ui/tests/integration/components/job-diff-test.js b/ui/tests/integration/components/job-diff-test.js
index 4661e6a64..dfc1fa403 100644
--- a/ui/tests/integration/components/job-diff-test.js
+++ b/ui/tests/integration/components/job-diff-test.js
@@ -5,7 +5,7 @@ import hbs from 'htmlbars-inline-precompile';
import cleanWhitespace from '../../utils/clean-whitespace';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job diff', function(hooks) {
+module('Integration | Component | job diff', function (hooks) {
setupRenderingTest(hooks);
const commonTemplate = hbs`
@@ -16,7 +16,9 @@ module('Integration | Component | job diff', function(hooks) {
`;
- test('job field diffs', async function(assert) {
+ test('job field diffs', async function (assert) {
+ assert.expect(5);
+
this.set('diff', {
ID: 'test-case-1',
Type: 'Edited',
@@ -37,21 +39,27 @@ module('Integration | Component | job diff', function(hooks) {
);
assert.equal(
cleanWhitespace(
- find('[data-test-diff-section-label="field"][data-test-diff-field="added"]').textContent
+ find(
+ '[data-test-diff-section-label="field"][data-test-diff-field="added"]'
+ ).textContent
),
'+ Added Field: "Foobar"',
'Added field is rendered correctly'
);
assert.equal(
cleanWhitespace(
- find('[data-test-diff-section-label="field"][data-test-diff-field="edited"]').textContent
+ find(
+ '[data-test-diff-section-label="field"][data-test-diff-field="edited"]'
+ ).textContent
),
'+/- Edited Field: "256" => "512"',
'Edited field is rendered correctly'
);
assert.equal(
cleanWhitespace(
- find('[data-test-diff-section-label="field"][data-test-diff-field="deleted"]').textContent
+ find(
+ '[data-test-diff-section-label="field"][data-test-diff-field="deleted"]'
+ ).textContent
),
'- Removed Field: "12"',
'Removed field is rendered correctly'
@@ -60,7 +68,9 @@ module('Integration | Component | job diff', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('job object diffs', async function(assert) {
+ test('job object diffs', async function (assert) {
+ assert.expect(9);
+
this.set('diff', {
ID: 'test-case-2',
Type: 'Edited',
@@ -108,38 +118,50 @@ module('Integration | Component | job diff', function(hooks) {
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="added"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="added"]'
+ ).textContent
).startsWith('+ DeepConfiguration {'),
'Added object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="edited"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="edited"]'
+ ).textContent
).startsWith('+/- ComplexProperty {'),
'Edited object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="deleted"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="deleted"]'
+ ).textContent
).startsWith('- DatedStuff {'),
'Removed object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="added"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="added"]'
+ ).textContent
).endsWith('}'),
'Added object ends the JSON block'
);
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="edited"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="edited"]'
+ ).textContent
).endsWith('}'),
'Edited object starts with a JSON block'
);
assert.ok(
cleanWhitespace(
- find('[data-test-diff-section-label="object"][data-test-diff-field="deleted"]').textContent
+ find(
+ '[data-test-diff-section-label="object"][data-test-diff-field="deleted"]'
+ ).textContent
).endsWith('}'),
'Removed object ends the JSON block'
);
diff --git a/ui/tests/integration/components/job-editor-test.js b/ui/tests/integration/components/job-editor-test.js
index d3818ca4b..aab1e7973 100644
--- a/ui/tests/integration/components/job-editor-test.js
+++ b/ui/tests/integration/components/job-editor-test.js
@@ -12,11 +12,11 @@ import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
const Editor = create(jobEditor());
-module('Integration | Component | job-editor', function(hooks) {
+module('Integration | Component | job-editor', function (hooks) {
setupRenderingTest(hooks);
setupCodeMirror(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
window.localStorage.clear();
fragmentSerializerInitializer(this.owner);
@@ -28,13 +28,13 @@ module('Integration | Component | job-editor', function(hooks) {
this.server.create('node');
});
- hooks.afterEach(async function() {
+ hooks.afterEach(async function () {
this.server.shutdown();
});
const newJobName = 'new-job';
const newJobTaskGroupName = 'redis';
- const jsonJob = overrides => {
+ const jsonJob = (overrides) => {
return JSON.stringify(
assign(
{},
@@ -95,31 +95,44 @@ module('Integration | Component | job-editor', function(hooks) {
};
const renderEditJob = async (component, job) => {
- component.setProperties({ job, onSubmit: sinon.spy(), onCancel: sinon.spy(), context: 'edit' });
+ component.setProperties({
+ job,
+ onSubmit: sinon.spy(),
+ onCancel: sinon.spy(),
+ context: 'edit',
+ });
await component.render(cancelableTemplate);
};
- const planJob = async spec => {
+ const planJob = async (spec) => {
await Editor.editor.fillIn(spec);
await Editor.plan();
};
- test('the default state is an editor with an explanation popup', async function(assert) {
+ test('the default state is an editor with an explanation popup', async function (assert) {
+ assert.expect(3);
+
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
- assert.ok(Editor.editorHelp.isPresent, 'Editor explanation popup is present');
+ assert.ok(
+ Editor.editorHelp.isPresent,
+ 'Editor explanation popup is present'
+ );
assert.ok(Editor.editor.isPresent, 'Editor is present');
await componentA11yAudit(this.element, assert);
});
- test('the explanation popup can be dismissed', async function(assert) {
+ test('the explanation popup can be dismissed', async function (assert) {
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
await Editor.editorHelp.dismiss();
- assert.notOk(Editor.editorHelp.isPresent, 'Editor explanation popup is gone');
+ assert.notOk(
+ Editor.editorHelp.isPresent,
+ 'Editor explanation popup is gone'
+ );
assert.equal(
window.localStorage.nomadMessageJobEditor,
'false',
@@ -127,55 +140,76 @@ module('Integration | Component | job-editor', function(hooks) {
);
});
- test('the explanation popup is not shown once the dismissal state is set in localStorage', async function(assert) {
+ test('the explanation popup is not shown once the dismissal state is set in localStorage', async function (assert) {
window.localStorage.nomadMessageJobEditor = 'false';
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
- assert.notOk(Editor.editorHelp.isPresent, 'Editor explanation popup is gone');
+ assert.notOk(
+ Editor.editorHelp.isPresent,
+ 'Editor explanation popup is gone'
+ );
});
- test('submitting a json job skips the parse endpoint', async function(assert) {
+ test('submitting a json job skips the parse endpoint', async function (assert) {
const spec = jsonJob();
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
await planJob(spec);
const requests = this.server.pretender.handledRequests.mapBy('url');
- assert.notOk(requests.includes('/v1/jobs/parse'), 'JSON job spec is not parsed');
- assert.ok(requests.includes(`/v1/job/${newJobName}/plan`), 'JSON job spec is still planned');
+ assert.notOk(
+ requests.includes('/v1/jobs/parse'),
+ 'JSON job spec is not parsed'
+ );
+ assert.ok(
+ requests.includes(`/v1/job/${newJobName}/plan`),
+ 'JSON job spec is still planned'
+ );
});
- test('submitting an hcl job requires the parse endpoint', async function(assert) {
+ test('submitting an hcl job requires the parse endpoint', async function (assert) {
const spec = hclJob();
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
await planJob(spec);
const requests = this.server.pretender.handledRequests.mapBy('url');
- assert.ok(requests.includes('/v1/jobs/parse'), 'HCL job spec is parsed first');
- assert.ok(requests.includes(`/v1/job/${newJobName}/plan`), 'HCL job spec is planned');
assert.ok(
- requests.indexOf('/v1/jobs/parse') < requests.indexOf(`/v1/job/${newJobName}/plan`),
+ requests.includes('/v1/jobs/parse'),
+ 'HCL job spec is parsed first'
+ );
+ assert.ok(
+ requests.includes(`/v1/job/${newJobName}/plan`),
+ 'HCL job spec is planned'
+ );
+ assert.ok(
+ requests.indexOf('/v1/jobs/parse') <
+ requests.indexOf(`/v1/job/${newJobName}/plan`),
'Parse comes before Plan'
);
});
- test('when a job is successfully parsed and planned, the plan is shown to the user', async function(assert) {
+ test('when a job is successfully parsed and planned, the plan is shown to the user', async function (assert) {
+ assert.expect(4);
+
const spec = hclJob();
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
await planJob(spec);
assert.ok(Editor.planOutput, 'The plan is outputted');
- assert.notOk(Editor.editor.isPresent, 'The editor is replaced with the plan output');
+ assert.notOk(
+ Editor.editor.isPresent,
+ 'The editor is replaced with the plan output'
+ );
assert.ok(Editor.planHelp.isPresent, 'The plan explanation popup is shown');
await componentA11yAudit(this.element, assert);
});
- test('from the plan screen, the cancel button goes back to the editor with the job still in tact', async function(assert) {
+ test('from the plan screen, the cancel button goes back to the editor with the job still in tact', async function (assert) {
const spec = hclJob();
const job = await this.store.createRecord('job');
@@ -183,10 +217,16 @@ module('Integration | Component | job-editor', function(hooks) {
await planJob(spec);
await Editor.cancel();
assert.ok(Editor.editor.isPresent, 'The editor is shown again');
- assert.equal(Editor.editor.contents, spec, 'The spec that was planned is still in the editor');
+ assert.equal(
+ Editor.editor.contents,
+ spec,
+ 'The spec that was planned is still in the editor'
+ );
});
- test('when parse fails, the parse error message is shown', async function(assert) {
+ test('when parse fails, the parse error message is shown', async function (assert) {
+ assert.expect(5);
+
const spec = hclJob();
const errorMessage = 'Parse Failed!! :o';
const job = await this.store.createRecord('job');
@@ -208,12 +248,18 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when plan fails, the plan error message is shown', async function(assert) {
+ test('when plan fails, the plan error message is shown', async function (assert) {
+ assert.expect(5);
+
const spec = hclJob();
const errorMessage = 'Plan Failed!! :o';
const job = await this.store.createRecord('job');
- this.server.pretender.post(`/v1/job/${newJobName}/plan`, () => [400, {}, errorMessage]);
+ this.server.pretender.post(`/v1/job/${newJobName}/plan`, () => [
+ 400,
+ {},
+ errorMessage,
+ ]);
await renderNewJob(this, job);
await planJob(spec);
@@ -230,7 +276,9 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when run fails, the run error message is shown', async function(assert) {
+ test('when run fails, the run error message is shown', async function (assert) {
+ assert.expect(5);
+
const spec = hclJob();
const errorMessage = 'Run Failed!! :o';
const job = await this.store.createRecord('job');
@@ -253,7 +301,9 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when the scheduler dry-run has warnings, the warnings are shown to the user', async function(assert) {
+ test('when the scheduler dry-run has warnings, the warnings are shown to the user', async function (assert) {
+ assert.expect(4);
+
const spec = jsonJob({ Unschedulable: true });
const job = await this.store.createRecord('job');
@@ -275,7 +325,9 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when the scheduler dry-run has no warnings, a success message is shown to the user', async function(assert) {
+ test('when the scheduler dry-run has no warnings, a success message is shown to the user', async function (assert) {
+ assert.expect(3);
+
const spec = hclJob();
const job = await this.store.createRecord('job');
@@ -293,34 +345,47 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when a job is submitted in the edit context, a POST request is made to the update job endpoint', async function(assert) {
+ test('when a job is submitted in the edit context, a POST request is made to the update job endpoint', async function (assert) {
const spec = hclJob();
const job = await this.store.createRecord('job');
await renderEditJob(this, job);
await planJob(spec);
await Editor.run();
- const requests = this.server.pretender.handledRequests.filterBy('method', 'POST').mapBy('url');
- assert.ok(requests.includes(`/v1/job/${newJobName}`), 'A request was made to job update');
- assert.notOk(requests.includes('/v1/jobs'), 'A request was not made to job create');
+ const requests = this.server.pretender.handledRequests
+ .filterBy('method', 'POST')
+ .mapBy('url');
+ assert.ok(
+ requests.includes(`/v1/job/${newJobName}`),
+ 'A request was made to job update'
+ );
+ assert.notOk(
+ requests.includes('/v1/jobs'),
+ 'A request was not made to job create'
+ );
});
- test('when a job is submitted in the new context, a POST request is made to the create job endpoint', async function(assert) {
+ test('when a job is submitted in the new context, a POST request is made to the create job endpoint', async function (assert) {
const spec = hclJob();
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
await planJob(spec);
await Editor.run();
- const requests = this.server.pretender.handledRequests.filterBy('method', 'POST').mapBy('url');
- assert.ok(requests.includes('/v1/jobs'), 'A request was made to job create');
+ const requests = this.server.pretender.handledRequests
+ .filterBy('method', 'POST')
+ .mapBy('url');
+ assert.ok(
+ requests.includes('/v1/jobs'),
+ 'A request was made to job create'
+ );
assert.notOk(
requests.includes(`/v1/job/${newJobName}`),
'A request was not made to job update'
);
});
- test('when a job is successfully submitted, the onSubmit hook is called', async function(assert) {
+ test('when a job is successfully submitted, the onSubmit hook is called', async function (assert) {
const spec = hclJob();
const job = await this.store.createRecord('job');
@@ -333,14 +398,16 @@ module('Integration | Component | job-editor', function(hooks) {
);
});
- test('when the job-editor cancelable flag is false, there is no cancel button in the header', async function(assert) {
+ test('when the job-editor cancelable flag is false, there is no cancel button in the header', async function (assert) {
const job = await this.store.createRecord('job');
await renderNewJob(this, job);
assert.notOk(Editor.cancelEditingIsAvailable, 'No way to cancel editing');
});
- test('when the job-editor cancelable flag is true, there is a cancel button in the header', async function(assert) {
+ test('when the job-editor cancelable flag is true, there is a cancel button in the header', async function (assert) {
+ assert.expect(2);
+
const job = await this.store.createRecord('job');
await renderEditJob(this, job);
@@ -349,7 +416,7 @@ module('Integration | Component | job-editor', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when the job-editor cancel button is clicked, the onCancel hook is called', async function(assert) {
+ test('when the job-editor cancel button is clicked, the onCancel hook is called', async function (assert) {
const job = await this.store.createRecord('job');
await renderEditJob(this, job);
diff --git a/ui/tests/integration/components/job-page/helpers.js b/ui/tests/integration/components/job-page/helpers.js
index ddefc9c28..7b986816d 100644
--- a/ui/tests/integration/components/job-page/helpers.js
+++ b/ui/tests/integration/components/job-page/helpers.js
@@ -24,12 +24,15 @@ export function expectStartRequest(assert, server, job) {
const expectedURL = jobURL(job);
const request = server.pretender.handledRequests
.filterBy('method', 'POST')
- .find(req => req.url === expectedURL);
+ .find((req) => req.url === expectedURL);
const requestPayload = JSON.parse(request.requestBody).Job;
assert.ok(request, 'POST URL was made correctly');
- assert.ok(requestPayload.Stop == null, 'The Stop signal is not sent in the POST request');
+ assert.ok(
+ requestPayload.Stop == null,
+ 'The Stop signal is not sent in the POST request'
+ );
}
export async function expectError(assert, title) {
@@ -44,7 +47,10 @@ export async function expectError(assert, title) {
);
await click('[data-test-job-error-close]');
- assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ assert.notOk(
+ find('[data-test-job-error-title]'),
+ 'Error message is dismissable'
+ );
}
export function expectDeleteRequest(assert, server, job) {
@@ -53,7 +59,7 @@ export function expectDeleteRequest(assert, server, job) {
assert.ok(
server.pretender.handledRequests
.filterBy('method', 'DELETE')
- .find(req => req.url === expectedURL),
+ .find((req) => req.url === expectedURL),
'DELETE URL was made correctly'
);
}
diff --git a/ui/tests/integration/components/job-page/parts/body-test.js b/ui/tests/integration/components/job-page/parts/body-test.js
index 7a5aab931..f61abc69c 100644
--- a/ui/tests/integration/components/job-page/parts/body-test.js
+++ b/ui/tests/integration/components/job-page/parts/body-test.js
@@ -5,21 +5,21 @@ import hbs from 'htmlbars-inline-precompile';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/parts/body', function(hooks) {
+module('Integration | Component | job-page/parts/body', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
this.server = startMirage();
this.server.createList('namespace', 3);
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
- test('includes a subnav for the job', async function(assert) {
+ test('includes a subnav for the job', async function (assert) {
this.set('job', {});
await render(hbs`
@@ -31,7 +31,9 @@ module('Integration | Component | job-page/parts/body', function(hooks) {
assert.ok(find('[data-test-subnav="job"]'), 'Job subnav is rendered');
});
- test('the subnav includes the deployments link when the job is a service', async function(assert) {
+ test('the subnav includes the deployments link when the job is a service', async function (assert) {
+ assert.expect(4);
+
const store = this.owner.lookup('service:store');
const job = await store.createRecord('job', {
id: 'service-job',
@@ -46,15 +48,26 @@ module('Integration | Component | job-page/parts/body', function(hooks) {
`);
- const subnavLabels = findAll('[data-test-tab]').map(anchor => anchor.textContent);
- assert.ok(subnavLabels.some(label => label === 'Definition'), 'Definition link');
- assert.ok(subnavLabels.some(label => label === 'Versions'), 'Versions link');
- assert.ok(subnavLabels.some(label => label === 'Deployments'), 'Deployments link');
+ const subnavLabels = findAll('[data-test-tab]').map(
+ (anchor) => anchor.textContent
+ );
+ assert.ok(
+ subnavLabels.some((label) => label === 'Definition'),
+ 'Definition link'
+ );
+ assert.ok(
+ subnavLabels.some((label) => label === 'Versions'),
+ 'Versions link'
+ );
+ assert.ok(
+ subnavLabels.some((label) => label === 'Deployments'),
+ 'Deployments link'
+ );
await componentA11yAudit(this.element, assert);
});
- test('the subnav does not include the deployments link when the job is not a service', async function(assert) {
+ test('the subnav does not include the deployments link when the job is not a service', async function (assert) {
const store = this.owner.lookup('service:store');
const job = await store.createRecord('job', {
id: 'batch-job',
@@ -69,13 +82,24 @@ module('Integration | Component | job-page/parts/body', function(hooks) {
`);
- const subnavLabels = findAll('[data-test-tab]').map(anchor => anchor.textContent);
- assert.ok(subnavLabels.some(label => label === 'Definition'), 'Definition link');
- assert.ok(subnavLabels.some(label => label === 'Versions'), 'Versions link');
- assert.notOk(subnavLabels.some(label => label === 'Deployments'), 'Deployments link');
+ const subnavLabels = findAll('[data-test-tab]').map(
+ (anchor) => anchor.textContent
+ );
+ assert.ok(
+ subnavLabels.some((label) => label === 'Definition'),
+ 'Definition link'
+ );
+ assert.ok(
+ subnavLabels.some((label) => label === 'Versions'),
+ 'Versions link'
+ );
+ assert.notOk(
+ subnavLabels.some((label) => label === 'Deployments'),
+ 'Deployments link'
+ );
});
- test('body yields content to a section after the subnav', async function(assert) {
+ test('body yields content to a section after the subnav', async function (assert) {
this.set('job', {});
await render(hbs`
diff --git a/ui/tests/integration/components/job-page/parts/children-test.js b/ui/tests/integration/components/job-page/parts/children-test.js
index 29b42eac3..3c7bb98c9 100644
--- a/ui/tests/integration/components/job-page/parts/children-test.js
+++ b/ui/tests/integration/components/job-page/parts/children-test.js
@@ -7,17 +7,17 @@ import { setupRenderingTest } from 'ember-qunit';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/parts/children', function(hooks) {
+module('Integration | Component | job-page/parts/children', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('namespace');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
@@ -34,7 +34,7 @@ module('Integration | Component | job-page/parts/children', function(hooks) {
options
);
- test('lists each child', async function(assert) {
+ test('lists each child', async function (assert) {
this.server.create('job', 'periodic', {
id: 'parent',
childrenCount: 3,
@@ -63,7 +63,9 @@ module('Integration | Component | job-page/parts/children', function(hooks) {
);
});
- test('eventually paginates', async function(assert) {
+ test('eventually paginates', async function (assert) {
+ assert.expect(5);
+
const pageSize = 10;
window.localStorage.nomadPageSize = pageSize;
@@ -89,18 +91,29 @@ module('Integration | Component | job-page/parts/children', function(hooks) {
`);
const childrenCount = parent.get('children.length');
- assert.ok(childrenCount > pageSize, 'Parent has more children than one page size');
- assert.equal(findAll('[data-test-job-name]').length, pageSize, 'Table length maxes out at 10');
+ assert.ok(
+ childrenCount > pageSize,
+ 'Parent has more children than one page size'
+ );
+ assert.equal(
+ findAll('[data-test-job-name]').length,
+ pageSize,
+ 'Table length maxes out at 10'
+ );
assert.ok(find('.pagination-next'), 'Next button is rendered');
assert.ok(
- new RegExp(`1.10.+?${childrenCount}`).test(find('.pagination-numbers').textContent.trim())
+ new RegExp(`1.10.+?${childrenCount}`).test(
+ find('.pagination-numbers').textContent.trim()
+ )
);
await componentA11yAudit(this.element, assert);
});
- test('is sorted based on the sortProperty and sortDescending properties', async function(assert) {
+ test('is sorted based on the sortProperty and sortDescending properties', async function (assert) {
+ assert.expect(6);
+
this.server.create('job', 'periodic', {
id: 'parent',
childrenCount: 3,
@@ -144,7 +157,7 @@ module('Integration | Component | job-page/parts/children', function(hooks) {
});
});
- test('gotoJob is called when a job row is clicked', async function(assert) {
+ test('gotoJob is called when a job row is clicked', async function (assert) {
const gotoJobSpy = sinon.spy();
this.server.create('job', 'periodic', {
diff --git a/ui/tests/integration/components/job-page/parts/latest-deployment-test.js b/ui/tests/integration/components/job-page/parts/latest-deployment-test.js
index d51c430cb..873ed200e 100644
--- a/ui/tests/integration/components/job-page/parts/latest-deployment-test.js
+++ b/ui/tests/integration/components/job-page/parts/latest-deployment-test.js
@@ -7,176 +7,206 @@ import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/parts/latest-deployment', function(hooks) {
- setupRenderingTest(hooks);
+module(
+ 'Integration | Component | job-page/parts/latest-deployment',
+ function (hooks) {
+ setupRenderingTest(hooks);
- hooks.beforeEach(function() {
- fragmentSerializerInitializer(this.owner);
- window.localStorage.clear();
- this.store = this.owner.lookup('service:store');
- this.server = startMirage();
- this.server.create('namespace');
- });
-
- hooks.afterEach(function() {
- this.server.shutdown();
- window.localStorage.clear();
- });
-
- test('there is no latest deployment section when the job has no deployments', async function(assert) {
- this.server.create('job', {
- type: 'service',
- noDeployments: true,
- createAllocations: false,
+ hooks.beforeEach(function () {
+ fragmentSerializerInitializer(this.owner);
+ window.localStorage.clear();
+ this.store = this.owner.lookup('service:store');
+ this.server = startMirage();
+ this.server.create('namespace');
});
- await this.store.findAll('job');
+ hooks.afterEach(function () {
+ this.server.shutdown();
+ window.localStorage.clear();
+ });
- this.set('job', this.store.peekAll('job').get('firstObject'));
- await render(hbs`
+ test('there is no latest deployment section when the job has no deployments', async function (assert) {
+ this.server.create('job', {
+ type: 'service',
+ noDeployments: true,
+ createAllocations: false,
+ });
+
+ await this.store.findAll('job');
+
+ this.set('job', this.store.peekAll('job').get('firstObject'));
+ await render(hbs`
)
`);
- assert.notOk(find('[data-test-active-deployment]'), 'No active deployment');
- });
-
- test('the latest deployment section shows up for the currently running deployment', async function(assert) {
- this.server.create('job', {
- type: 'service',
- createAllocations: false,
- activeDeployment: true,
+ assert.notOk(
+ find('[data-test-active-deployment]'),
+ 'No active deployment'
+ );
});
- await this.store.findAll('job');
+ test('the latest deployment section shows up for the currently running deployment', async function (assert) {
+ assert.expect(11);
- this.set('job', this.store.peekAll('job').get('firstObject'));
- await render(hbs`
+ this.server.create('job', {
+ type: 'service',
+ createAllocations: false,
+ activeDeployment: true,
+ });
+
+ await this.store.findAll('job');
+
+ this.set('job', this.store.peekAll('job').get('firstObject'));
+ await render(hbs`
`);
- const deployment = await this.get('job.latestDeployment');
- const version = await deployment.get('version');
+ const deployment = await this.get('job.latestDeployment');
+ const version = await deployment.get('version');
- assert.ok(find('[data-test-active-deployment]'), 'Active deployment');
- assert.ok(
- find('[data-test-active-deployment]').classList.contains('is-info'),
- 'Running deployment gets the is-info class'
- );
- assert.equal(
- find('[data-test-active-deployment-stat="id"]').textContent.trim(),
- deployment.get('shortId'),
- 'The active deployment is the most recent running deployment'
- );
+ assert.ok(find('[data-test-active-deployment]'), 'Active deployment');
+ assert.ok(
+ find('[data-test-active-deployment]').classList.contains('is-info'),
+ 'Running deployment gets the is-info class'
+ );
+ assert.equal(
+ find('[data-test-active-deployment-stat="id"]').textContent.trim(),
+ deployment.get('shortId'),
+ 'The active deployment is the most recent running deployment'
+ );
- assert.equal(
- find('[data-test-active-deployment-stat="submit-time"]').textContent.trim(),
- moment(version.get('submitTime')).fromNow(),
- 'Time since the job was submitted is in the active deployment header'
- );
+ assert.equal(
+ find(
+ '[data-test-active-deployment-stat="submit-time"]'
+ ).textContent.trim(),
+ moment(version.get('submitTime')).fromNow(),
+ 'Time since the job was submitted is in the active deployment header'
+ );
- assert.equal(
- find('[data-test-deployment-metric="canaries"]').textContent.trim(),
- `${deployment.get('placedCanaries')} / ${deployment.get('desiredCanaries')}`,
- 'Canaries, both places and desired, are in the metrics'
- );
+ assert.equal(
+ find('[data-test-deployment-metric="canaries"]').textContent.trim(),
+ `${deployment.get('placedCanaries')} / ${deployment.get(
+ 'desiredCanaries'
+ )}`,
+ 'Canaries, both places and desired, are in the metrics'
+ );
- assert.equal(
- find('[data-test-deployment-metric="placed"]').textContent.trim(),
- deployment.get('placedAllocs'),
- 'Placed allocs aggregates across task groups'
- );
+ assert.equal(
+ find('[data-test-deployment-metric="placed"]').textContent.trim(),
+ deployment.get('placedAllocs'),
+ 'Placed allocs aggregates across task groups'
+ );
- assert.equal(
- find('[data-test-deployment-metric="desired"]').textContent.trim(),
- deployment.get('desiredTotal'),
- 'Desired allocs aggregates across task groups'
- );
+ assert.equal(
+ find('[data-test-deployment-metric="desired"]').textContent.trim(),
+ deployment.get('desiredTotal'),
+ 'Desired allocs aggregates across task groups'
+ );
- assert.equal(
- find('[data-test-deployment-metric="healthy"]').textContent.trim(),
- deployment.get('healthyAllocs'),
- 'Healthy allocs aggregates across task groups'
- );
+ assert.equal(
+ find('[data-test-deployment-metric="healthy"]').textContent.trim(),
+ deployment.get('healthyAllocs'),
+ 'Healthy allocs aggregates across task groups'
+ );
- assert.equal(
- find('[data-test-deployment-metric="unhealthy"]').textContent.trim(),
- deployment.get('unhealthyAllocs'),
- 'Unhealthy allocs aggregates across task groups'
- );
+ assert.equal(
+ find('[data-test-deployment-metric="unhealthy"]').textContent.trim(),
+ deployment.get('unhealthyAllocs'),
+ 'Unhealthy allocs aggregates across task groups'
+ );
- assert.equal(
- find('[data-test-deployment-notification]').textContent.trim(),
- deployment.get('statusDescription'),
- 'Status description is in the metrics block'
- );
+ assert.equal(
+ find('[data-test-deployment-notification]').textContent.trim(),
+ deployment.get('statusDescription'),
+ 'Status description is in the metrics block'
+ );
- await componentA11yAudit(this.element, assert);
- });
-
- test('when there is no running deployment, the latest deployment section shows up for the last deployment', async function(assert) {
- this.server.create('job', {
- type: 'service',
- createAllocations: false,
- noActiveDeployment: true,
+ await componentA11yAudit(this.element, assert);
});
- await this.store.findAll('job');
+ test('when there is no running deployment, the latest deployment section shows up for the last deployment', async function (assert) {
+ this.server.create('job', {
+ type: 'service',
+ createAllocations: false,
+ noActiveDeployment: true,
+ });
- this.set('job', this.store.peekAll('job').get('firstObject'));
- await render(hbs`
+ await this.store.findAll('job');
+
+ this.set('job', this.store.peekAll('job').get('firstObject'));
+ await render(hbs`
`);
- assert.ok(find('[data-test-active-deployment]'), 'Active deployment');
- assert.notOk(
- find('[data-test-active-deployment]').classList.contains('is-info'),
- 'Non-running deployment does not get the is-info class'
- );
- });
+ assert.ok(find('[data-test-active-deployment]'), 'Active deployment');
+ assert.notOk(
+ find('[data-test-active-deployment]').classList.contains('is-info'),
+ 'Non-running deployment does not get the is-info class'
+ );
+ });
- test('the latest deployment section can be expanded to show task groups and allocations', async function(assert) {
- this.server.create('node');
- this.server.create('job', { type: 'service', activeDeployment: true });
+ test('the latest deployment section can be expanded to show task groups and allocations', async function (assert) {
+ assert.expect(5);
- await this.store.findAll('job');
+ this.server.create('node');
+ this.server.create('job', { type: 'service', activeDeployment: true });
- this.set('job', this.store.peekAll('job').get('firstObject'));
- await render(hbs`
+ await this.store.findAll('job');
+
+ this.set('job', this.store.peekAll('job').get('firstObject'));
+ await render(hbs`
`);
- assert.notOk(find('[data-test-deployment-task-groups]'), 'Task groups not found');
- assert.notOk(find('[data-test-deployment-allocations]'), 'Allocations not found');
+ assert.notOk(
+ find('[data-test-deployment-task-groups]'),
+ 'Task groups not found'
+ );
+ assert.notOk(
+ find('[data-test-deployment-allocations]'),
+ 'Allocations not found'
+ );
- await click('[data-test-deployment-toggle-details]');
+ await click('[data-test-deployment-toggle-details]');
- assert.ok(find('[data-test-deployment-task-groups]'), 'Task groups found');
- assert.ok(find('[data-test-deployment-allocations]'), 'Allocations found');
+ assert.ok(
+ find('[data-test-deployment-task-groups]'),
+ 'Task groups found'
+ );
+ assert.ok(
+ find('[data-test-deployment-allocations]'),
+ 'Allocations found'
+ );
- await componentA11yAudit(this.element, assert);
- });
+ await componentA11yAudit(this.element, assert);
+ });
- test('each task group in the expanded task group section shows task group details', async function(assert) {
- this.server.create('node');
- this.server.create('job', { type: 'service', activeDeployment: true });
+ test('each task group in the expanded task group section shows task group details', async function (assert) {
+ this.server.create('node');
+ this.server.create('job', { type: 'service', activeDeployment: true });
- await this.store.findAll('job');
+ await this.store.findAll('job');
- const job = this.store.peekAll('job').get('firstObject');
+ const job = this.store.peekAll('job').get('firstObject');
- this.set('job', job);
- await render(hbs`
+ this.set('job', job);
+ await render(hbs`
`);
- await click('[data-test-deployment-toggle-details]');
+ await click('[data-test-deployment-toggle-details]');
- const task = job.get('runningDeployment.taskGroupSummaries.firstObject');
- const findForTaskGroup = selector => find(`[data-test-deployment-task-group-${selector}]`);
- assert.equal(findForTaskGroup('name').textContent.trim(), task.get('name'));
- assert.equal(
- findForTaskGroup('progress-deadline').textContent.trim(),
- moment(task.get('requireProgressBy')).format("MMM DD, 'YY HH:mm:ss ZZ")
- );
- });
-});
+ const task = job.get('runningDeployment.taskGroupSummaries.firstObject');
+ const findForTaskGroup = (selector) =>
+ find(`[data-test-deployment-task-group-${selector}]`);
+ assert.equal(
+ findForTaskGroup('name').textContent.trim(),
+ task.get('name')
+ );
+ assert.equal(
+ findForTaskGroup('progress-deadline').textContent.trim(),
+ moment(task.get('requireProgressBy')).format("MMM DD, 'YY HH:mm:ss ZZ")
+ );
+ });
+ }
+);
diff --git a/ui/tests/integration/components/job-page/parts/placement-failures-test.js b/ui/tests/integration/components/job-page/parts/placement-failures-test.js
index 80b409dad..7e27425f2 100644
--- a/ui/tests/integration/components/job-page/parts/placement-failures-test.js
+++ b/ui/tests/integration/components/job-page/parts/placement-failures-test.js
@@ -1,3 +1,5 @@
+/* eslint-disable qunit/require-expect */
+/* Mirage fixtures are random so we can't expect a set number of assertions */
import hbs from 'htmlbars-inline-precompile';
import { findAll, find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
@@ -6,76 +8,93 @@ import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/parts/placement-failures', function(hooks) {
- setupRenderingTest(hooks);
+module(
+ 'Integration | Component | job-page/parts/placement-failures',
+ function (hooks) {
+ setupRenderingTest(hooks);
- hooks.beforeEach(function() {
- fragmentSerializerInitializer(this.owner);
- window.localStorage.clear();
- this.store = this.owner.lookup('service:store');
- this.server = startMirage();
- this.server.create('namespace');
- });
-
- hooks.afterEach(function() {
- this.server.shutdown();
- window.localStorage.clear();
- });
-
- test('when the job has placement failures, they are called out', async function(assert) {
- this.server.create('job', { failedPlacements: true, createAllocations: false });
- await this.store.findAll('job');
-
- const job = this.store.peekAll('job').get('firstObject');
- await job.reload();
-
- this.set('job', job);
-
- await render(hbs`
- )
- `);
-
- const failedEvaluation = this.get('job.evaluations')
- .filterBy('hasPlacementFailures')
- .sortBy('modifyIndex')
- .reverse()
- .get('firstObject');
- const failedTGAllocs = failedEvaluation.get('failedTGAllocs');
-
- assert.ok(find('[data-test-placement-failures]'), 'Placement failures section found');
-
- const taskGroupLabels = findAll('[data-test-placement-failure-task-group]').map(title =>
- title.textContent.trim()
- );
-
- failedTGAllocs.forEach(alloc => {
- const name = alloc.get('name');
- assert.ok(
- taskGroupLabels.find(label => label.includes(name)),
- `${name} included in placement failures list`
- );
- assert.ok(
- taskGroupLabels.find(label => label.includes(alloc.get('coalescedFailures') + 1)),
- 'The number of unplaced allocs = CoalescedFailures + 1'
- );
+ hooks.beforeEach(function () {
+ fragmentSerializerInitializer(this.owner);
+ window.localStorage.clear();
+ this.store = this.owner.lookup('service:store');
+ this.server = startMirage();
+ this.server.create('namespace');
});
- await componentA11yAudit(this.element, assert);
- });
+ hooks.afterEach(function () {
+ this.server.shutdown();
+ window.localStorage.clear();
+ });
- test('when the job has no placement failures, the placement failures section is gone', async function(assert) {
- this.server.create('job', { noFailedPlacements: true, createAllocations: false });
- await this.store.findAll('job');
+ test('when the job has placement failures, they are called out', async function (assert) {
+ this.server.create('job', {
+ failedPlacements: true,
+ createAllocations: false,
+ });
+ await this.store.findAll('job');
- const job = this.store.peekAll('job').get('firstObject');
- await job.reload();
+ const job = this.store.peekAll('job').get('firstObject');
+ await job.reload();
- this.set('job', job);
+ this.set('job', job);
- await render(hbs`
+ await render(hbs`
)
`);
- assert.notOk(find('[data-test-placement-failures]'), 'Placement failures section not found');
- });
-});
+ const failedEvaluation = this.get('job.evaluations')
+ .filterBy('hasPlacementFailures')
+ .sortBy('modifyIndex')
+ .reverse()
+ .get('firstObject');
+ const failedTGAllocs = failedEvaluation.get('failedTGAllocs');
+
+ assert.ok(
+ find('[data-test-placement-failures]'),
+ 'Placement failures section found'
+ );
+
+ const taskGroupLabels = findAll(
+ '[data-test-placement-failure-task-group]'
+ ).map((title) => title.textContent.trim());
+
+ failedTGAllocs.forEach((alloc) => {
+ const name = alloc.get('name');
+ assert.ok(
+ taskGroupLabels.find((label) => label.includes(name)),
+ `${name} included in placement failures list`
+ );
+ assert.ok(
+ taskGroupLabels.find((label) =>
+ label.includes(alloc.get('coalescedFailures') + 1)
+ ),
+ 'The number of unplaced allocs = CoalescedFailures + 1'
+ );
+ });
+
+ await componentA11yAudit(this.element, assert);
+ });
+
+ test('when the job has no placement failures, the placement failures section is gone', async function (assert) {
+ this.server.create('job', {
+ noFailedPlacements: true,
+ createAllocations: false,
+ });
+ await this.store.findAll('job');
+
+ const job = this.store.peekAll('job').get('firstObject');
+ await job.reload();
+
+ this.set('job', job);
+
+ await render(hbs`
+ )
+ `);
+
+ assert.notOk(
+ find('[data-test-placement-failures]'),
+ 'Placement failures section not found'
+ );
+ });
+ }
+);
diff --git a/ui/tests/integration/components/job-page/parts/summary-test.js b/ui/tests/integration/components/job-page/parts/summary-test.js
index 975a1b892..dc18a8c33 100644
--- a/ui/tests/integration/components/job-page/parts/summary-test.js
+++ b/ui/tests/integration/components/job-page/parts/summary-test.js
@@ -6,10 +6,10 @@ import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/parts/summary', function(hooks) {
+module('Integration | Component | job-page/parts/summary', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
window.localStorage.clear();
this.store = this.owner.lookup('service:store');
@@ -17,12 +17,14 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
this.server.create('namespace');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
- test('jobs with children use the children diagram', async function(assert) {
+ test('jobs with children use the children diagram', async function (assert) {
+ assert.expect(3);
+
this.server.create('job', 'periodic', {
createAllocations: false,
});
@@ -35,13 +37,21 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
`);
- assert.ok(find('[data-test-children-status-bar]'), 'Children status bar found');
- assert.notOk(find('[data-test-allocation-status-bar]'), 'Allocation status bar not found');
+ assert.ok(
+ find('[data-test-children-status-bar]'),
+ 'Children status bar found'
+ );
+ assert.notOk(
+ find('[data-test-allocation-status-bar]'),
+ 'Allocation status bar not found'
+ );
await componentA11yAudit(this.element, assert);
});
- test('jobs without children use the allocations diagram', async function(assert) {
+ test('jobs without children use the allocations diagram', async function (assert) {
+ assert.expect(3);
+
this.server.create('job', {
createAllocations: false,
});
@@ -54,13 +64,19 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
`);
- assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation status bar found');
- assert.notOk(find('[data-test-children-status-bar]'), 'Children status bar not found');
+ assert.ok(
+ find('[data-test-allocation-status-bar]'),
+ 'Allocation status bar found'
+ );
+ assert.notOk(
+ find('[data-test-children-status-bar]'),
+ 'Children status bar not found'
+ );
await componentA11yAudit(this.element, assert);
});
- test('the allocations diagram lists all allocation status figures', async function(assert) {
+ test('the allocations diagram lists all allocation status figures', async function (assert) {
this.server.create('job', {
createAllocations: false,
});
@@ -110,7 +126,7 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
);
});
- test('the children diagram lists all children status figures', async function(assert) {
+ test('the children diagram lists all children status figures', async function (assert) {
this.server.create('job', 'periodic', {
createAllocations: false,
});
@@ -142,7 +158,7 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
);
});
- test('the summary block can be collapsed', async function(assert) {
+ test('the summary block can be collapsed', async function (assert) {
this.server.create('job', {
createAllocations: false,
});
@@ -161,7 +177,9 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
assert.notOk(find('[data-test-legend]'), 'No legend');
});
- test('when collapsed, the summary block includes an inline version of the chart', async function(assert) {
+ test('when collapsed, the summary block includes an inline version of the chart', async function (assert) {
+ assert.expect(3);
+
this.server.create('job', {
createAllocations: false,
});
@@ -176,7 +194,10 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
await click('[data-test-accordion-toggle]');
- assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed');
+ assert.ok(
+ find('[data-test-allocation-status-bar]'),
+ 'Allocation bar still existed'
+ );
assert.ok(
find('.inline-chart [data-test-allocation-status-bar]'),
'Allocation bar is rendered in an inline-chart container'
@@ -185,7 +206,7 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the collapsed/expanded state is persisted to localStorage', async function(assert) {
+ test('the collapsed/expanded state is persisted to localStorage', async function (assert) {
this.server.create('job', {
createAllocations: false,
});
@@ -198,7 +219,10 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
`);
- assert.notOk(window.localStorage.nomadExpandJobSummary, 'No value in localStorage yet');
+ assert.notOk(
+ window.localStorage.nomadExpandJobSummary,
+ 'No value in localStorage yet'
+ );
await click('[data-test-accordion-toggle]');
assert.equal(
@@ -208,7 +232,7 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
);
});
- test('the collapsed/expanded state from localStorage is used for the initial state when available', async function(assert) {
+ test('the collapsed/expanded state from localStorage is used for the initial state when available', async function (assert) {
this.server.create('job', {
createAllocations: false,
});
@@ -223,7 +247,10 @@ module('Integration | Component | job-page/parts/summary', function(hooks) {
`);
- assert.ok(find('[data-test-allocation-status-bar]'), 'Allocation bar still existed');
+ assert.ok(
+ find('[data-test-allocation-status-bar]'),
+ 'Allocation bar still existed'
+ );
assert.ok(
find('.inline-chart [data-test-allocation-status-bar]'),
'Allocation bar is rendered in an inline-chart container'
diff --git a/ui/tests/integration/components/job-page/parts/task-groups-test.js b/ui/tests/integration/components/job-page/parts/task-groups-test.js
index 86722b026..0fa42ec1f 100644
--- a/ui/tests/integration/components/job-page/parts/task-groups-test.js
+++ b/ui/tests/integration/components/job-page/parts/task-groups-test.js
@@ -1,51 +1,58 @@
import { assign } from '@ember/polyfills';
import hbs from 'htmlbars-inline-precompile';
-import { click, findAll, find } from '@ember/test-helpers';
+import { click, findAll, find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import sinon from 'sinon';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { setupRenderingTest } from 'ember-qunit';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-import { formatScheduledHertz, formatScheduledBytes } from 'nomad-ui/utils/units';
+import {
+ formatScheduledHertz,
+ formatScheduledBytes,
+} from 'nomad-ui/utils/units';
-module('Integration | Component | job-page/parts/task-groups', function(hooks) {
- setupRenderingTest(hooks);
+module(
+ 'Integration | Component | job-page/parts/task-groups',
+ function (hooks) {
+ setupRenderingTest(hooks);
- hooks.beforeEach(function() {
- window.localStorage.clear();
- this.store = this.owner.lookup('service:store');
- this.server = startMirage();
- this.server.create('namespace');
- });
-
- hooks.afterEach(function() {
- this.server.shutdown();
- });
-
- const props = (job, options = {}) =>
- assign(
- {
- job,
- sortProperty: 'name',
- sortDescending: true,
- gotoTaskGroup: () => {},
- },
- options
- );
-
- test('the job detail page should list all task groups', async function(assert) {
- this.server.create('job', {
- createAllocations: false,
+ hooks.beforeEach(function () {
+ window.localStorage.clear();
+ this.store = this.owner.lookup('service:store');
+ this.server = startMirage();
+ this.server.create('namespace');
});
- await this.store.findAll('job').then(jobs => {
- jobs.forEach(job => job.reload());
+ hooks.afterEach(function () {
+ this.server.shutdown();
});
- const job = this.store.peekAll('job').get('firstObject');
- this.setProperties(props(job));
+ const props = (job, options = {}) =>
+ assign(
+ {
+ job,
+ sortProperty: 'name',
+ sortDescending: true,
+ gotoTaskGroup: () => {},
+ },
+ options
+ );
- await this.render(hbs`
+ test('the job detail page should list all task groups', async function (assert) {
+ assert.expect(2);
+
+ this.server.create('job', {
+ createAllocations: false,
+ });
+
+ await this.store.findAll('job').then((jobs) => {
+ jobs.forEach((job) => job.reload());
+ });
+
+ const job = this.store.peekAll('job').get('firstObject');
+ this.setProperties(props(job));
+
+ await render(hbs`
`);
- assert.equal(
- findAll('[data-test-task-group]').length,
- job.get('taskGroups.length'),
- 'One row per task group'
- );
+ assert.equal(
+ findAll('[data-test-task-group]').length,
+ job.get('taskGroups.length'),
+ 'One row per task group'
+ );
- await componentA11yAudit(this.element, assert);
- });
-
- test('each row in the task group table should show basic information about the task group', async function(assert) {
- this.server.create('job', {
- createAllocations: false,
+ await componentA11yAudit(this.element, assert);
});
- const job = await this.store.findAll('job').then(async jobs => {
- return await jobs.get('firstObject').reload();
- });
+ test('each row in the task group table should show basic information about the task group', async function (assert) {
+ this.server.create('job', {
+ createAllocations: false,
+ });
- const taskGroups = await job.get('taskGroups');
- const taskGroup = taskGroups
- .sortBy('name')
- .reverse()
- .get('firstObject');
+ const job = await this.store.findAll('job').then(async (jobs) => {
+ return await jobs.get('firstObject').reload();
+ });
- this.setProperties(props(job));
+ const taskGroups = await job.get('taskGroups');
+ const taskGroup = taskGroups.sortBy('name').reverse().get('firstObject');
- await this.render(hbs`
+ this.setProperties(props(job));
+
+ await render(hbs`
`);
- const taskGroupRow = find('[data-test-task-group]');
+ const taskGroupRow = find('[data-test-task-group]');
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-name]').textContent.trim(),
- taskGroup.get('name'),
- 'Name'
- );
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-count]').textContent.trim(),
- taskGroup.get('count'),
- 'Count'
- );
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-volume]').textContent.trim(),
- taskGroup.get('volumes.length') ? 'Yes' : '',
- 'Volumes'
- );
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-cpu]').textContent.trim(),
- `${formatScheduledHertz(taskGroup.get('reservedCPU'), 'MHz')}`,
- 'Reserved CPU'
- );
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-mem]').textContent.trim(),
- `${formatScheduledBytes(taskGroup.get('reservedMemory'), 'MiB')}`,
- 'Reserved Memory'
- );
- assert.equal(
- taskGroupRow.querySelector('[data-test-task-group-disk]').textContent.trim(),
- `${formatScheduledBytes(taskGroup.get('reservedEphemeralDisk'), 'MiB')}`,
- 'Reserved Disk'
- );
- });
-
- test('gotoTaskGroup is called when task group rows are clicked', async function(assert) {
- this.server.create('job', {
- createAllocations: false,
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-name]')
+ .textContent.trim(),
+ taskGroup.get('name'),
+ 'Name'
+ );
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-count]')
+ .textContent.trim(),
+ taskGroup.get('count'),
+ 'Count'
+ );
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-volume]')
+ .textContent.trim(),
+ taskGroup.get('volumes.length') ? 'Yes' : '',
+ 'Volumes'
+ );
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-cpu]')
+ .textContent.trim(),
+ `${formatScheduledHertz(taskGroup.get('reservedCPU'), 'MHz')}`,
+ 'Reserved CPU'
+ );
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-mem]')
+ .textContent.trim(),
+ `${formatScheduledBytes(taskGroup.get('reservedMemory'), 'MiB')}`,
+ 'Reserved Memory'
+ );
+ assert.equal(
+ taskGroupRow
+ .querySelector('[data-test-task-group-disk]')
+ .textContent.trim(),
+ `${formatScheduledBytes(
+ taskGroup.get('reservedEphemeralDisk'),
+ 'MiB'
+ )}`,
+ 'Reserved Disk'
+ );
});
- const job = await this.store.findAll('job').then(async jobs => {
- return await jobs.get('firstObject').reload();
- });
+ test('gotoTaskGroup is called when task group rows are clicked', async function (assert) {
+ this.server.create('job', {
+ createAllocations: false,
+ });
- const taskGroupSpy = sinon.spy();
+ const job = await this.store.findAll('job').then(async (jobs) => {
+ return await jobs.get('firstObject').reload();
+ });
- const taskGroups = await job.get('taskGroups');
- const taskGroup = taskGroups
- .sortBy('name')
- .reverse()
- .get('firstObject');
+ const taskGroupSpy = sinon.spy();
- this.setProperties(
- props(job, {
- gotoTaskGroup: taskGroupSpy,
- })
- );
+ const taskGroups = await job.get('taskGroups');
+ const taskGroup = taskGroups.sortBy('name').reverse().get('firstObject');
- await this.render(hbs`
+ this.setProperties(
+ props(job, {
+ gotoTaskGroup: taskGroupSpy,
+ })
+ );
+
+ await render(hbs`
`);
- await click('[data-test-task-group]');
+ await click('[data-test-task-group]');
- assert.ok(
- taskGroupSpy.withArgs(taskGroup).calledOnce,
- 'Clicking the task group row calls the gotoTaskGroup action'
- );
- });
-});
+ assert.ok(
+ taskGroupSpy.withArgs(taskGroup).calledOnce,
+ 'Clicking the task group row calls the gotoTaskGroup action'
+ );
+ });
+ }
+);
diff --git a/ui/tests/integration/components/job-page/periodic-test.js b/ui/tests/integration/components/job-page/periodic-test.js
index edcec6b54..54df6cd05 100644
--- a/ui/tests/integration/components/job-page/periodic-test.js
+++ b/ui/tests/integration/components/job-page/periodic-test.js
@@ -24,17 +24,17 @@ const PeriodicJobPage = create({
pageSizeSelect: pageSizeSelectPageObject(),
});
-module('Integration | Component | job-page/periodic', function(hooks) {
+module('Integration | Component | job-page/periodic', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
window.localStorage.clear();
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('namespace');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
@@ -48,7 +48,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
@gotoJob={{gotoJob}} />
`;
- const commonProperties = job => ({
+ const commonProperties = (job) => ({
job,
sortProperty: 'name',
sortDescending: true,
@@ -56,7 +56,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
gotoJob: () => {},
});
- test('Clicking Force Launch launches a new periodic child job', async function(assert) {
+ test('Clicking Force Launch launches a new periodic child job', async function (assert) {
const childrenCount = 3;
this.server.create('job', 'periodic', {
@@ -70,7 +70,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
const job = this.store.peekAll('job').findBy('plainId', 'parent');
this.setProperties(commonProperties(job));
- await this.render(commonTemplate);
+ await render(commonTemplate);
const currentJobCount = server.db.jobs.length;
@@ -87,15 +87,23 @@ module('Integration | Component | job-page/periodic', function(hooks) {
assert.ok(
this.server.pretender.handledRequests
.filterBy('method', 'POST')
- .find(req => req.url === expectedURL),
+ .find((req) => req.url === expectedURL),
'POST URL was correct'
);
- assert.equal(server.db.jobs.length, currentJobCount + 1, 'POST request was made');
+ assert.equal(
+ server.db.jobs.length,
+ currentJobCount + 1,
+ 'POST request was made'
+ );
});
- test('Clicking force launch without proper permissions shows an error message', async function(assert) {
- this.server.pretender.post('/v1/job/:id/periodic/force', () => [403, {}, '']);
+ test('Clicking force launch without proper permissions shows an error message', async function (assert) {
+ this.server.pretender.post('/v1/job/:id/periodic/force', () => [
+ 403,
+ {},
+ '',
+ ]);
this.server.create('job', 'periodic', {
id: 'parent',
@@ -109,7 +117,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
const job = this.store.peekAll('job').findBy('plainId', 'parent');
this.setProperties(commonProperties(job));
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(find('[data-test-job-error-title]'), 'No error message yet');
@@ -127,10 +135,15 @@ module('Integration | Component | job-page/periodic', function(hooks) {
await click('[data-test-job-error-close]');
- assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ assert.notOk(
+ find('[data-test-job-error-title]'),
+ 'Error message is dismissable'
+ );
});
- test('Stopping a job sends a delete request for the job', async function(assert) {
+ test('Stopping a job sends a delete request for the job', async function (assert) {
+ assert.expect(1);
+
const mirageJob = this.server.create('job', 'periodic', {
childrenCount: 0,
createAllocations: false,
@@ -149,7 +162,9 @@ module('Integration | Component | job-page/periodic', function(hooks) {
expectDeleteRequest(assert, this.server, job);
});
- test('Stopping a job without proper permissions shows an error message', async function(assert) {
+ test('Stopping a job without proper permissions shows an error message', async function (assert) {
+ assert.expect(4);
+
this.server.pretender.delete('/v1/job/:id', () => [403, {}, '']);
const mirageJob = this.server.create('job', 'periodic', {
@@ -171,7 +186,9 @@ module('Integration | Component | job-page/periodic', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Starting a job sends a post request for the job using the current definition', async function(assert) {
+ test('Starting a job sends a post request for the job using the current definition', async function (assert) {
+ assert.expect(2);
+
const mirageJob = this.server.create('job', 'periodic', {
childrenCount: 0,
createAllocations: false,
@@ -188,7 +205,9 @@ module('Integration | Component | job-page/periodic', function(hooks) {
expectStartRequest(assert, this.server, job);
});
- test('Starting a job without proper permissions shows an error message', async function(assert) {
+ test('Starting a job without proper permissions shows an error message', async function (assert) {
+ assert.expect(3);
+
this.server.pretender.post('/v1/job/:id', () => [403, {}, '']);
const mirageJob = this.server.create('job', 'periodic', {
@@ -207,7 +226,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
expectError(assert, 'Could Not Start Job');
});
- test('Each job row includes the submitted time', async function(assert) {
+ test('Each job row includes the submitted time', async function (assert) {
this.server.create('job', 'periodic', {
id: 'parent',
childrenCount: 1,
@@ -219,11 +238,13 @@ module('Integration | Component | job-page/periodic', function(hooks) {
const job = this.store.peekAll('job').findBy('plainId', 'parent');
this.setProperties(commonProperties(job));
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.equal(
find('[data-test-job-submit-time]').textContent,
- moment(job.get('children.firstObject.submitTime')).format('MMM DD HH:mm:ss ZZ'),
+ moment(job.get('children.firstObject.submitTime')).format(
+ 'MMM DD HH:mm:ss ZZ'
+ ),
'The new periodic job launch is in the children list'
);
});
@@ -244,7 +265,7 @@ module('Integration | Component | job-page/periodic', function(hooks) {
const job = this.store.peekAll('job').findBy('plainId', 'parent');
this.setProperties(commonProperties(job));
- await this.render(commonTemplate);
+ await render(commonTemplate);
},
});
});
diff --git a/ui/tests/integration/components/job-page/service-test.js b/ui/tests/integration/components/job-page/service-test.js
index 075e001f1..79160c790 100644
--- a/ui/tests/integration/components/job-page/service-test.js
+++ b/ui/tests/integration/components/job-page/service-test.js
@@ -4,15 +4,21 @@ import { setupRenderingTest } from 'ember-qunit';
import { click, find, render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
-import { startJob, stopJob, expectError, expectDeleteRequest, expectStartRequest } from './helpers';
+import {
+ startJob,
+ stopJob,
+ expectError,
+ expectDeleteRequest,
+ expectStartRequest,
+} from './helpers';
import Job from 'nomad-ui/tests/pages/jobs/detail';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | job-page/service', function(hooks) {
+module('Integration | Component | job-page/service', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
window.localStorage.clear();
this.store = this.owner.lookup('service:store');
@@ -20,7 +26,7 @@ module('Integration | Component | job-page/service', function(hooks) {
this.server.create('namespace');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
Job.removeContext();
this.server.shutdown();
window.localStorage.clear();
@@ -35,7 +41,7 @@ module('Integration | Component | job-page/service', function(hooks) {
@gotoJob={{gotoJob}} />
`;
- const commonProperties = job => ({
+ const commonProperties = (job) => ({
job,
sortProperty: 'name',
sortDescending: true,
@@ -56,7 +62,9 @@ module('Integration | Component | job-page/service', function(hooks) {
)
);
- test('Stopping a job sends a delete request for the job', async function(assert) {
+ test('Stopping a job sends a delete request for the job', async function (assert) {
+ assert.expect(1);
+
const mirageJob = makeMirageJob(this.server);
await this.store.findAll('job');
@@ -69,7 +77,9 @@ module('Integration | Component | job-page/service', function(hooks) {
expectDeleteRequest(assert, this.server, job);
});
- test('Stopping a job without proper permissions shows an error message', async function(assert) {
+ test('Stopping a job without proper permissions shows an error message', async function (assert) {
+ assert.expect(4);
+
this.server.pretender.delete('/v1/job/:id', () => [403, {}, '']);
const mirageJob = makeMirageJob(this.server);
@@ -86,7 +96,9 @@ module('Integration | Component | job-page/service', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Starting a job sends a post request for the job using the current definition', async function(assert) {
+ test('Starting a job sends a post request for the job using the current definition', async function (assert) {
+ assert.expect(2);
+
const mirageJob = makeMirageJob(this.server, { status: 'dead' });
await this.store.findAll('job');
@@ -99,7 +111,9 @@ module('Integration | Component | job-page/service', function(hooks) {
expectStartRequest(assert, this.server, job);
});
- test('Starting a job without proper permissions shows an error message', async function(assert) {
+ test('Starting a job without proper permissions shows an error message', async function (assert) {
+ assert.expect(3);
+
this.server.pretender.post('/v1/job/:id', () => [403, {}, '']);
const mirageJob = makeMirageJob(this.server, { status: 'dead' });
@@ -114,7 +128,9 @@ module('Integration | Component | job-page/service', function(hooks) {
expectError(assert, 'Could Not Start Job');
});
- test('Recent allocations shows allocations in the job context', async function(assert) {
+ test('Recent allocations shows allocations in the job context', async function (assert) {
+ assert.expect(3);
+
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { createAllocations: true });
await this.store.findAll('job');
@@ -124,16 +140,22 @@ module('Integration | Component | job-page/service', function(hooks) {
this.setProperties(commonProperties(job));
await render(commonTemplate);
- const allocation = this.server.db.allocations.sortBy('modifyIndex').reverse()[0];
+ const allocation = this.server.db.allocations
+ .sortBy('modifyIndex')
+ .reverse()[0];
const allocationRow = Job.allocations.objectAt(0);
assert.equal(allocationRow.shortId, allocation.id.split('-')[0], 'ID');
- assert.equal(allocationRow.taskGroup, allocation.taskGroup, 'Task Group name');
+ assert.equal(
+ allocationRow.taskGroup,
+ allocation.taskGroup,
+ 'Task Group name'
+ );
await componentA11yAudit(this.element, assert);
});
- test('Recent allocations caps out at five', async function(assert) {
+ test('Recent allocations caps out at five', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server);
this.server.createList('allocation', 10);
@@ -152,7 +174,9 @@ module('Integration | Component | job-page/service', function(hooks) {
);
});
- test('Recent allocations shows an empty message when the job has no allocations', async function(assert) {
+ test('Recent allocations shows an empty message when the job has no allocations', async function (assert) {
+ assert.expect(2);
+
this.server.create('node');
const mirageJob = makeMirageJob(this.server);
@@ -171,7 +195,7 @@ module('Integration | Component | job-page/service', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Active deployment can be promoted', async function(assert) {
+ test('Active deployment can be promoted', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
@@ -195,8 +219,14 @@ module('Integration | Component | job-page/service', function(hooks) {
);
});
- test('When promoting the active deployment fails, an error is shown', async function(assert) {
- this.server.pretender.post('/v1/deployment/promote/:id', () => [403, {}, '']);
+ test('When promoting the active deployment fails, an error is shown', async function (assert) {
+ assert.expect(4);
+
+ this.server.pretender.post('/v1/deployment/promote/:id', () => [
+ 403,
+ {},
+ '',
+ ]);
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
@@ -224,10 +254,13 @@ module('Integration | Component | job-page/service', function(hooks) {
await click('[data-test-job-error-close]');
- assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ assert.notOk(
+ find('[data-test-job-error-title]'),
+ 'Error message is dismissable'
+ );
});
- test('Active deployment can be failed', async function(assert) {
+ test('Active deployment can be failed', async function (assert) {
this.server.create('node');
const mirageJob = makeMirageJob(this.server, { activeDeployment: true });
@@ -252,7 +285,9 @@ module('Integration | Component | job-page/service', function(hooks) {
);
});
- test('When failing the active deployment fails, an error is shown', async function(assert) {
+ test('When failing the active deployment fails, an error is shown', async function (assert) {
+ assert.expect(4);
+
this.server.pretender.post('/v1/deployment/fail/:id', () => [403, {}, '']);
this.server.create('node');
@@ -282,6 +317,9 @@ module('Integration | Component | job-page/service', function(hooks) {
await click('[data-test-job-error-close]');
- assert.notOk(find('[data-test-job-error-title]'), 'Error message is dismissable');
+ assert.notOk(
+ find('[data-test-job-error-title]'),
+ 'Error message is dismissable'
+ );
});
});
diff --git a/ui/tests/integration/components/lifecycle-chart-test.js b/ui/tests/integration/components/lifecycle-chart-test.js
index 9dd541946..d9ab57a27 100644
--- a/ui/tests/integration/components/lifecycle-chart-test.js
+++ b/ui/tests/integration/components/lifecycle-chart-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/no-conditional-assertions */
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render, settled } from '@ember/test-helpers';
@@ -40,10 +41,12 @@ const tasks = [
},
];
-module('Integration | Component | lifecycle-chart', function(hooks) {
+module('Integration | Component | lifecycle-chart', function (hooks) {
setupRenderingTest(hooks);
- test('it renders stateless phases and lifecycle- and name-sorted tasks', async function(assert) {
+ test('it renders stateless phases and lifecycle- and name-sorted tasks', async function (assert) {
+ assert.expect(32);
+
this.set('tasks', tasks);
await render(hbs``);
@@ -54,7 +57,7 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
assert.equal(Chart.phases[2].name, 'Poststart');
assert.equal(Chart.phases[3].name, 'Poststop');
- Chart.phases.forEach(phase => assert.notOk(phase.isActive));
+ Chart.phases.forEach((phase) => assert.notOk(phase.isActive));
assert.deepEqual(Chart.tasks.mapBy('name'), [
'prestart ephemeral: 0',
@@ -82,7 +85,7 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
assert.ok(Chart.tasks[5].isPoststartEphemeral);
assert.ok(Chart.tasks[6].isPoststop);
- Chart.tasks.forEach(task => {
+ Chart.tasks.forEach((task) => {
assert.notOk(task.isActive);
assert.notOk(task.isFinished);
});
@@ -90,7 +93,7 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('it doesn’t render when there’s only one phase', async function(assert) {
+ test('it doesn’t render when there’s only one phase', async function (assert) {
this.set('tasks', [
{
lifecycleName: 'main',
@@ -101,17 +104,19 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
assert.notOk(Chart.isPresent);
});
- test('it renders all phases when there are any non-main tasks', async function(assert) {
+ test('it renders all phases when there are any non-main tasks', async function (assert) {
this.set('tasks', [tasks[0], tasks[6]]);
await render(hbs``);
assert.equal(Chart.phases.length, 4);
});
- test('it reflects phase and task states when states are passed in', async function(assert) {
+ test('it reflects phase and task states when states are passed in', async function (assert) {
+ assert.expect(24);
+
this.set(
'taskStates',
- tasks.map(task => {
+ tasks.map((task) => {
return { task };
})
);
@@ -119,9 +124,9 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
await render(hbs``);
assert.ok(Chart.isPresent);
- Chart.phases.forEach(phase => assert.notOk(phase.isActive));
+ Chart.phases.forEach((phase) => assert.notOk(phase.isActive));
- Chart.tasks.forEach(task => {
+ Chart.tasks.forEach((task) => {
assert.notOk(task.isActive);
assert.notOk(task.isFinished);
});
@@ -158,18 +163,24 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
activePhaseNames: [],
},
{
- testName: 'poststart ephemeral task states affect main phase active state',
+ testName:
+ 'poststart ephemeral task states affect main phase active state',
runningTaskNames: ['poststart ephemeral'],
activePhaseNames: ['Main'],
},
].forEach(async ({ testName, runningTaskNames, activePhaseNames }) => {
- test(testName, async function(assert) {
- this.set('taskStates', tasks.map(task => ({ task })));
+ test(testName, async function (assert) {
+ assert.expect(4);
+
+ this.set(
+ 'taskStates',
+ tasks.map((task) => ({ task }))
+ );
await render(hbs``);
- runningTaskNames.forEach(taskName => {
- const taskState = this.taskStates.find(taskState =>
+ runningTaskNames.forEach((taskName) => {
+ const taskState = this.taskStates.find((taskState) =>
taskState.task.name.includes(taskName)
);
set(taskState, 'state', 'running');
@@ -177,11 +188,14 @@ module('Integration | Component | lifecycle-chart', function(hooks) {
await settled();
- Chart.phases.forEach(Phase => {
+ Chart.phases.forEach((Phase) => {
if (activePhaseNames.includes(Phase.name)) {
assert.ok(Phase.isActive, `expected ${Phase.name} not to be active`);
} else {
- assert.notOk(Phase.isActive, `expected ${Phase.name} phase not to be active`);
+ assert.notOk(
+ Phase.isActive,
+ `expected ${Phase.name} phase not to be active`
+ );
}
});
});
diff --git a/ui/tests/integration/components/line-chart-test.js b/ui/tests/integration/components/line-chart-test.js
index 16d9fa77e..3e53c0362 100644
--- a/ui/tests/integration/components/line-chart-test.js
+++ b/ui/tests/integration/components/line-chart-test.js
@@ -1,4 +1,10 @@
-import { find, findAll, click, render, triggerEvent } from '@ember/test-helpers';
+import {
+ find,
+ findAll,
+ click,
+ render,
+ triggerEvent,
+} from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -8,10 +14,12 @@ import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
const REF_DATE = new Date();
-module('Integration | Component | line-chart', function(hooks) {
+module('Integration | Component | line-chart', function (hooks) {
setupRenderingTest(hooks);
- test('when a chart has annotations, they are rendered in order', async function(assert) {
+ test('when a chart has annotations, they are rendered in order', async function (assert) {
+ assert.expect(4);
+
const annotations = [
{ x: 2, type: 'info' },
{ x: 1, type: 'error' },
@@ -48,24 +56,20 @@ module('Integration | Component | line-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when a chart has annotations and is timeseries, annotations are sorted reverse-chronologically', async function(assert) {
+ test('when a chart has annotations and is timeseries, annotations are sorted reverse-chronologically', async function (assert) {
+ assert.expect(3);
+
const annotations = [
{
- x: moment(REF_DATE)
- .add(2, 'd')
- .toDate(),
+ x: moment(REF_DATE).add(2, 'd').toDate(),
type: 'info',
},
{
- x: moment(REF_DATE)
- .add(1, 'd')
- .toDate(),
+ x: moment(REF_DATE).add(1, 'd').toDate(),
type: 'error',
},
{
- x: moment(REF_DATE)
- .add(3, 'd')
- .toDate(),
+ x: moment(REF_DATE).add(3, 'd').toDate(),
type: 'info',
},
];
@@ -99,7 +103,7 @@ module('Integration | Component | line-chart', function(hooks) {
});
});
- test('clicking annotations calls the onAnnotationClick action with the annotation as an argument', async function(assert) {
+ test('clicking annotations calls the onAnnotationClick action with the annotation as an argument', async function (assert) {
const annotations = [{ x: 2, type: 'info', meta: { data: 'here' } }];
this.setProperties({
annotations,
@@ -125,7 +129,9 @@ module('Integration | Component | line-chart', function(hooks) {
assert.ok(this.click.calledWith(annotations[0]));
});
- test('annotations will have staggered heights when too close to be positioned side-by-side', async function(assert) {
+ test('annotations will have staggered heights when too close to be positioned side-by-side', async function (assert) {
+ assert.expect(4);
+
const annotations = [
{ x: 2, type: 'info' },
{ x: 2.4, type: 'error' },
@@ -161,7 +167,9 @@ module('Integration | Component | line-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('horizontal annotations render in order', async function(assert) {
+ test('horizontal annotations render in order', async function (assert) {
+ assert.expect(3);
+
const annotations = [
{ y: 2, label: 'label one' },
{ y: 9, label: 'label three' },
@@ -195,7 +203,9 @@ module('Integration | Component | line-chart', function(hooks) {
});
});
- test('the tooltip includes information on the data closest to the mouse', async function(assert) {
+ test('the tooltip includes information on the data closest to the mouse', async function (assert) {
+ assert.expect(8);
+
const series1 = [
{ x: 1, y: 2 },
{ x: 3, y: 3 },
@@ -251,12 +261,17 @@ module('Integration | Component | line-chart', function(hooks) {
// MouseEnter triggers the tooltip visibility
await triggerEvent(hoverTarget, 'mouseenter');
// MouseMove positions the tooltip and updates the active datum
- await triggerEvent(hoverTarget, 'mousemove', { clientX: xOffset + interval * 1 + 5 });
+ await triggerEvent(hoverTarget, 'mousemove', {
+ clientX: xOffset + interval * 1 + 5,
+ });
assert.equal(findAll('[data-test-chart-tooltip] li').length, 1);
- assert.equal(find('[data-test-chart-tooltip] .label').textContent.trim(), this.data[1].series);
+ assert.equal(
+ find('[data-test-chart-tooltip] .label').textContent.trim(),
+ this.data[1].series
+ );
assert.equal(
find('[data-test-chart-tooltip] .value').textContent.trim(),
- series2.find(d => d.x === 2).y
+ series2.find((d) => d.x === 2).y
);
// When the mouse falls between points and each series has points with different x values,
@@ -264,14 +279,22 @@ module('Integration | Component | line-chart', function(hooks) {
// to the cursor.
// This event is intentionally between points such that both points are within proximity.
const expected = [
- { label: this.data[0].series, value: series1.find(d => d.x === 3).y },
- { label: this.data[1].series, value: series2.find(d => d.x === 2).y },
+ { label: this.data[0].series, value: series1.find((d) => d.x === 3).y },
+ { label: this.data[1].series, value: series2.find((d) => d.x === 2).y },
];
- await triggerEvent(hoverTarget, 'mousemove', { clientX: xOffset + interval * 1.5 + 5 });
+ await triggerEvent(hoverTarget, 'mousemove', {
+ clientX: xOffset + interval * 1.5 + 5,
+ });
assert.equal(findAll('[data-test-chart-tooltip] li').length, 2);
findAll('[data-test-chart-tooltip] li').forEach((tooltipEntry, index) => {
- assert.equal(tooltipEntry.querySelector('.label').textContent.trim(), expected[index].label);
- assert.equal(tooltipEntry.querySelector('.value').textContent.trim(), expected[index].value);
+ assert.equal(
+ tooltipEntry.querySelector('.label').textContent.trim(),
+ expected[index].label
+ );
+ assert.equal(
+ tooltipEntry.querySelector('.value').textContent.trim(),
+ expected[index].value
+ );
});
});
});
diff --git a/ui/tests/integration/components/list-pagination-test.js b/ui/tests/integration/components/list-pagination-test.js
index 9731f4902..23d47f8c9 100644
--- a/ui/tests/integration/components/list-pagination-test.js
+++ b/ui/tests/integration/components/list-pagination-test.js
@@ -4,7 +4,7 @@ import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | list pagination', function(hooks) {
+module('Integration | Component | list pagination', function (hooks) {
setupRenderingTest(hooks);
const defaults = {
@@ -18,7 +18,9 @@ module('Integration | Component | list pagination', function(hooks) {
.fill(null)
.map((_, i) => i);
- test('the source property', async function(assert) {
+ test('the source property', async function (assert) {
+ assert.expect(36);
+
this.set('source', list100);
await render(hbs`
@@ -37,8 +39,14 @@ module('Integration | Component | list pagination', function(hooks) {
`);
- assert.ok(!findAll('.first').length, 'On the first page, there is no first link');
- assert.ok(!findAll('.prev').length, 'On the first page, there is no prev link');
+ assert.notOk(
+ findAll('.first').length,
+ 'On the first page, there is no first link'
+ );
+ assert.notOk(
+ findAll('.prev').length,
+ 'On the first page, there is no prev link'
+ );
await componentA11yAudit(this.element, assert);
assert.equal(
@@ -48,14 +56,23 @@ module('Integration | Component | list pagination', function(hooks) {
);
for (var pageNumber = 1; pageNumber <= defaults.spread + 1; pageNumber++) {
- assert.ok(findAll(`.link.page-${pageNumber}`).length, `Page link includes ${pageNumber}`);
+ assert.ok(
+ findAll(`.link.page-${pageNumber}`).length,
+ `Page link includes ${pageNumber}`
+ );
}
- assert.ok(findAll('.next').length, 'While not on the last page, there is a next link');
- assert.ok(findAll('.last').length, 'While not on the last page, there is a last link');
+ assert.ok(
+ findAll('.next').length,
+ 'While not on the last page, there is a next link'
+ );
+ assert.ok(
+ findAll('.last').length,
+ 'While not on the last page, there is a last link'
+ );
await componentA11yAudit(this.element, assert);
- assert.ok(
+ assert.equal(
findAll('.item').length,
defaults.size,
`Only ${defaults.size} (the default) number of items are rendered`
@@ -70,7 +87,7 @@ module('Integration | Component | list pagination', function(hooks) {
}
});
- test('the size property', async function(assert) {
+ test('the size property', async function (assert) {
this.setProperties({
size: 5,
source: list100,
@@ -82,10 +99,16 @@ module('Integration | Component | list pagination', function(hooks) {
`);
const totalPages = Math.ceil(this.source.length / this.size);
- assert.equal(find('.page-info').textContent, `1 of ${totalPages}`, `${totalPages} total pages`);
+ assert.equal(
+ find('.page-info').textContent,
+ `1 of ${totalPages}`,
+ `${totalPages} total pages`
+ );
});
- test('the spread property', async function(assert) {
+ test('the spread property', async function (assert) {
+ assert.expect(12);
+
this.setProperties({
source: list100,
spread: 1,
@@ -106,7 +129,9 @@ module('Integration | Component | list pagination', function(hooks) {
testSpread.call(this, assert);
});
- test('page property', async function(assert) {
+ test('page property', async function (assert) {
+ assert.expect(10);
+
this.setProperties({
source: list100,
size: 5,
@@ -129,9 +154,9 @@ module('Integration | Component | list pagination', function(hooks) {
// Ember doesn't support query params (or controllers or routes) in integration tests,
// so links can only be tested in acceptance tests.
// Leaving this test here for posterity.
- skip('pagination links link with query params', function() {});
+ skip('pagination links link with query params', function () {});
- test('there are no pagination links when source is less than page size', async function(assert) {
+ test('there are no pagination links when source is less than page size', async function (assert) {
this.set('source', list100.slice(0, 10));
await render(hbs`
@@ -150,10 +175,10 @@ module('Integration | Component | list pagination', function(hooks) {
`);
- assert.ok(!findAll('.first').length, 'No first link');
- assert.ok(!findAll('.prev').length, 'No prev link');
- assert.ok(!findAll('.next').length, 'No next link');
- assert.ok(!findAll('.last').length, 'No last link');
+ assert.notOk(findAll('.first').length, 'No first link');
+ assert.notOk(findAll('.prev').length, 'No prev link');
+ assert.notOk(findAll('.next').length, 'No next link');
+ assert.notOk(findAll('.last').length, 'No last link');
assert.equal(find('.page-info').textContent, '1 of 1', 'Only one page');
assert.equal(
@@ -164,7 +189,9 @@ module('Integration | Component | list pagination', function(hooks) {
});
// when there is less pages than the total spread amount
- test('when there is less pages than the total spread amount', async function(assert) {
+ test('when there is less pages than the total spread amount', async function (assert) {
+ assert.expect(9);
+
this.setProperties({
source: list100,
spread: 4,
@@ -191,15 +218,26 @@ module('Integration | Component | list pagination', function(hooks) {
assert.ok(findAll('.prev').length, 'Prev page still exists');
assert.ok(findAll('.next').length, 'Next page still exists');
assert.ok(findAll('.last').length, 'Last page still exists');
- assert.equal(findAll('.link').length, totalPages, 'Every page gets a page link');
+ assert.equal(
+ findAll('.link').length,
+ totalPages,
+ 'Every page gets a page link'
+ );
for (var pageNumber = 1; pageNumber < totalPages; pageNumber++) {
- assert.ok(findAll(`.link.page-${pageNumber}`).length, `Page link for ${pageNumber} exists`);
+ assert.ok(
+ findAll(`.link.page-${pageNumber}`).length,
+ `Page link for ${pageNumber} exists`
+ );
}
});
function testSpread(assert) {
const { spread, currentPage } = this.getProperties('spread', 'currentPage');
- for (var pageNumber = currentPage - spread; pageNumber <= currentPage + spread; pageNumber++) {
+ for (
+ var pageNumber = currentPage - spread;
+ pageNumber <= currentPage + spread;
+ pageNumber++
+ ) {
assert.ok(
findAll(`.link.page-${pageNumber}`).length,
`Page links for currentPage (${currentPage}) +/- spread of ${spread} (${pageNumber})`
@@ -213,8 +251,9 @@ module('Integration | Component | list pagination', function(hooks) {
assert.equal(
findAll('.item')[item].textContent,
item + (currentPage - 1) * size,
- `Rendered items are in the current page, ${currentPage} (${item +
- (currentPage - 1) * size})`
+ `Rendered items are in the current page, ${currentPage} (${
+ item + (currentPage - 1) * size
+ })`
);
}
}
diff --git a/ui/tests/integration/components/list-table-test.js b/ui/tests/integration/components/list-table-test.js
index 385fadac6..134f4f7d5 100644
--- a/ui/tests/integration/components/list-table-test.js
+++ b/ui/tests/integration/components/list-table-test.js
@@ -5,7 +5,7 @@ import faker from 'nomad-ui/mirage/faker';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | list table', function(hooks) {
+module('Integration | Component | list table', function (hooks) {
setupRenderingTest(hooks);
const commonTable = Array(10)
@@ -17,7 +17,7 @@ module('Integration | Component | list table', function(hooks) {
}));
// thead
- test('component exposes a thead contextual component', async function(assert) {
+ test('component exposes a thead contextual component', async function (assert) {
this.set('source', commonTable);
await render(hbs`
@@ -30,11 +30,17 @@ module('Integration | Component | list table', function(hooks) {
`);
assert.ok(findAll('.head').length, 'Table head is rendered');
- assert.equal(find('.head').tagName.toLowerCase(), 'thead', 'Table head is a thead element');
+ assert.equal(
+ find('.head').tagName.toLowerCase(),
+ 'thead',
+ 'Table head is a thead element'
+ );
});
// tbody
- test('component exposes a tbody contextual component', async function(assert) {
+ test('component exposes a tbody contextual component', async function (assert) {
+ assert.expect(44);
+
this.setProperties({
source: commonTable,
sortProperty: 'firstName',
@@ -54,18 +60,42 @@ module('Integration | Component | list table', function(hooks) {
`);
assert.ok(findAll('.body').length, 'Table body is rendered');
- assert.equal(find('.body').tagName.toLowerCase(), 'tbody', 'Table body is a tbody element');
+ assert.equal(
+ find('.body').tagName.toLowerCase(),
+ 'tbody',
+ 'Table body is a tbody element'
+ );
- assert.equal(findAll('.item').length, this.get('source.length'), 'Each item gets its own row');
+ assert.equal(
+ findAll('.item').length,
+ this.get('source.length'),
+ 'Each item gets its own row'
+ );
// list-table is not responsible for sorting, only dispatching sort events. The table is still
// rendered in index-order.
this.source.forEach((item, index) => {
const $item = this.element.querySelectorAll('.item')[index];
- assert.equal($item.querySelectorAll('td')[0].innerHTML.trim(), item.firstName, 'First name');
- assert.equal($item.querySelectorAll('td')[1].innerHTML.trim(), item.lastName, 'Last name');
- assert.equal($item.querySelectorAll('td')[2].innerHTML.trim(), item.age, 'Age');
- assert.equal($item.querySelectorAll('td')[3].innerHTML.trim(), index, 'Index');
+ assert.equal(
+ $item.querySelectorAll('td')[0].innerHTML.trim(),
+ item.firstName,
+ 'First name'
+ );
+ assert.equal(
+ $item.querySelectorAll('td')[1].innerHTML.trim(),
+ item.lastName,
+ 'Last name'
+ );
+ assert.equal(
+ $item.querySelectorAll('td')[2].innerHTML.trim(),
+ item.age,
+ 'Age'
+ );
+ assert.equal(
+ $item.querySelectorAll('td')[3].innerHTML.trim(),
+ index,
+ 'Index'
+ );
});
await componentA11yAudit(this.element, assert);
@@ -74,5 +104,5 @@ module('Integration | Component | list table', function(hooks) {
// Ember doesn't support query params (or controllers or routes) in integration tests,
// so sorting links can only be tested in acceptance tests.
// Leaving this test here for posterity.
- skip('sort-by creates links using the appropriate links given sort property and sort descending', function() {});
+ skip('sort-by creates links using the appropriate links given sort property and sort descending', function () {});
});
diff --git a/ui/tests/integration/components/multi-select-dropdown-test.js b/ui/tests/integration/components/multi-select-dropdown-test.js
index 1592395f0..1d2f931be 100644
--- a/ui/tests/integration/components/multi-select-dropdown-test.js
+++ b/ui/tests/integration/components/multi-select-dropdown-test.js
@@ -1,4 +1,11 @@
-import { findAll, find, click, focus, render, triggerKeyEvent } from '@ember/test-helpers';
+import {
+ findAll,
+ find,
+ click,
+ focus,
+ render,
+ triggerKeyEvent,
+} from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import sinon from 'sinon';
@@ -11,7 +18,7 @@ const SPACE = 32;
const ARROW_UP = 38;
const ARROW_DOWN = 40;
-module('Integration | Component | multi-select dropdown', function(hooks) {
+module('Integration | Component | multi-select dropdown', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -36,7 +43,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
@onSelect={{this.onSelect}} />
`;
- test('component is initially closed', async function(assert) {
+ test('component is initially closed', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -47,27 +56,40 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
props.label,
'Trigger is appropriately labeled'
);
- assert.notOk(find('[data-test-dropdown-options]'), 'Options are not rendered');
+ assert.notOk(
+ find('[data-test-dropdown-options]'),
+ 'Options are not rendered'
+ );
await componentA11yAudit(this.element, assert);
});
- test('component opens the options dropdown when clicked', async function(assert) {
+ test('component opens the options dropdown when clicked', async function (assert) {
+ assert.expect(3);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await click('[data-test-dropdown-trigger]');
- await assert.ok(find('[data-test-dropdown-options]'), 'Options are shown now');
+ await assert.ok(
+ find('[data-test-dropdown-options]'),
+ 'Options are shown now'
+ );
await componentA11yAudit(this.element, assert);
await click('[data-test-dropdown-trigger]');
- assert.notOk(find('[data-test-dropdown-options]'), 'Options are hidden after clicking again');
+ assert.notOk(
+ find('[data-test-dropdown-options]'),
+ 'Options are hidden after clicking again'
+ );
});
- test('all options are shown in the options dropdown, each with a checkbox input', async function(assert) {
+ test('all options are shown in the options dropdown, each with a checkbox input', async function (assert) {
+ assert.expect(13);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -81,12 +103,19 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
findAll('[data-test-dropdown-option]').forEach((optionEl, index) => {
const label = props.options[index].label;
- assert.equal(optionEl.textContent.trim(), label, `Correct label for ${label}`);
- assert.ok(optionEl.querySelector('input[type="checkbox"]'), 'Option contains a checkbox');
+ assert.equal(
+ optionEl.textContent.trim(),
+ label,
+ `Correct label for ${label}`
+ );
+ assert.ok(
+ optionEl.querySelector('input[type="checkbox"]'),
+ 'Option contains a checkbox'
+ );
});
});
- test('onSelect gets called when an option is clicked', async function(assert) {
+ test('onSelect gets called when an option is clicked', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -103,7 +132,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('the component trigger shows the selection count when there is a selection', async function(assert) {
+ test('the component trigger shows the selection count when there is a selection', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
props.selection = [props.options[0].key, props.options[1].key];
this.setProperties(props);
@@ -114,7 +145,8 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
'The count is shown'
);
assert.equal(
- find('[data-test-dropdown-trigger] [data-test-dropdown-count]').textContent,
+ find('[data-test-dropdown-trigger] [data-test-dropdown-count]')
+ .textContent,
props.selection.length,
'The count is accurate'
);
@@ -129,14 +161,21 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing DOWN when the trigger has focus opens the options list', async function(assert) {
+ test('pressing DOWN when the trigger has focus opens the options list', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await focus('[data-test-dropdown-trigger]');
- assert.notOk(find('[data-test-dropdown-options]'), 'Options are not shown on focus');
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
+ assert.notOk(
+ find('[data-test-dropdown-options]'),
+ 'Options are not shown on focus'
+ );
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
assert.ok(find('[data-test-dropdown-options]'), 'Options are now shown');
assert.equal(
document.activeElement,
@@ -145,14 +184,22 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing DOWN when the trigger has focus and the options list is open focuses the first option', async function(assert) {
+ test('pressing DOWN when the trigger has focus and the options list is open focuses the first option', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await focus('[data-test-dropdown-trigger]');
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
assert.equal(
document.activeElement,
find('[data-test-dropdown-option]'),
@@ -160,13 +207,17 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing TAB when the trigger has focus and the options list is open focuses the first option', async function(assert) {
+ test('pressing TAB when the trigger has focus and the options list is open focuses the first option', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await focus('[data-test-dropdown-trigger]');
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', TAB);
assert.equal(
document.activeElement,
@@ -175,7 +226,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing UP when the first list option is focused does nothing', async function(assert) {
+ test('pressing UP when the first list option is focused does nothing', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -191,7 +242,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing DOWN when the a list option is focused moves focus to the next list option', async function(assert) {
+ test('pressing DOWN when the a list option is focused moves focus to the next list option', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -207,7 +258,9 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('pressing DOWN when the last list option has focus does nothing', async function(assert) {
+ test('pressing DOWN when the last list option has focus does nothing', async function (assert) {
+ assert.expect(6);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -222,7 +275,12 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
await triggerKeyEvent(option, 'keydown', ARROW_DOWN);
if (index < lastIndex) {
- assert.equal(document.activeElement, optionEls[index + 1], `Option ${index + 1} has focus`);
+ /* eslint-disable-next-line qunit/no-conditional-assertions */
+ assert.equal(
+ document.activeElement,
+ optionEls[index + 1],
+ `Option ${index + 1} has focus`
+ );
}
}
@@ -234,7 +292,7 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('onSelect gets called when pressing SPACE when a list option is focused', async function(assert) {
+ test('onSelect gets called when pressing SPACE when a list option is focused', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -253,44 +311,68 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('list options have a zero tabindex and are therefore sequentially navigable', async function(assert) {
+ test('list options have a zero tabindex and are therefore sequentially navigable', async function (assert) {
+ assert.expect(6);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await click('[data-test-dropdown-trigger]');
- findAll('[data-test-dropdown-option]').forEach(option => {
- assert.equal(parseInt(option.getAttribute('tabindex'), 10), 0, 'tabindex is zero');
+ findAll('[data-test-dropdown-option]').forEach((option) => {
+ assert.equal(
+ parseInt(option.getAttribute('tabindex'), 10),
+ 0,
+ 'tabindex is zero'
+ );
});
});
- test('the checkboxes inside list options have a negative tabindex and are therefore not sequentially navigable', async function(assert) {
+ test('the checkboxes inside list options have a negative tabindex and are therefore not sequentially navigable', async function (assert) {
+ assert.expect(6);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await click('[data-test-dropdown-trigger]');
- findAll('[data-test-dropdown-option]').forEach(option => {
+ findAll('[data-test-dropdown-option]').forEach((option) => {
assert.ok(
- parseInt(option.querySelector('input[type="checkbox"]').getAttribute('tabindex'), 10) < 0,
+ parseInt(
+ option
+ .querySelector('input[type="checkbox"]')
+ .getAttribute('tabindex'),
+ 10
+ ) < 0,
'tabindex is a negative value'
);
});
});
- test('pressing ESC when the options list is open closes the list and returns focus to the dropdown trigger', async function(assert) {
+ test('pressing ESC when the options list is open closes the list and returns focus to the dropdown trigger', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
await focus('[data-test-dropdown-trigger]');
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
- await triggerKeyEvent('[data-test-dropdown-trigger]', 'keydown', ARROW_DOWN);
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
+ await triggerKeyEvent(
+ '[data-test-dropdown-trigger]',
+ 'keydown',
+ ARROW_DOWN
+ );
await triggerKeyEvent('[data-test-dropdown-option]', 'keydown', ESC);
- assert.notOk(find('[data-test-dropdown-options]'), 'The options list is hidden once more');
+ assert.notOk(
+ find('[data-test-dropdown-options]'),
+ 'The options list is hidden once more'
+ );
assert.equal(
document.activeElement,
find('[data-test-dropdown-trigger]'),
@@ -298,14 +380,19 @@ module('Integration | Component | multi-select dropdown', function(hooks) {
);
});
- test('when there are no list options, an empty message is shown', async function(assert) {
+ test('when there are no list options, an empty message is shown', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
props.options = [];
this.setProperties(props);
await render(commonTemplate);
await click('[data-test-dropdown-trigger]');
- assert.ok(find('[data-test-dropdown-options]'), 'The dropdown is still shown');
+ assert.ok(
+ find('[data-test-dropdown-options]'),
+ 'The dropdown is still shown'
+ );
assert.ok(find('[data-test-dropdown-empty]'), 'The empty state is shown');
assert.notOk(find('[data-test-dropdown-option]'), 'No options are shown');
await componentA11yAudit(this.element, assert);
diff --git a/ui/tests/integration/components/page-layout-test.js b/ui/tests/integration/components/page-layout-test.js
index f2437dae7..59611fd63 100644
--- a/ui/tests/integration/components/page-layout-test.js
+++ b/ui/tests/integration/components/page-layout-test.js
@@ -5,18 +5,20 @@ import hbs from 'htmlbars-inline-precompile';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | page layout', function(hooks) {
+module('Integration | Component | page layout', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.server = startMirage();
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('the global-header hamburger menu opens the gutter menu', async function(assert) {
+ test('the global-header hamburger menu opens the gutter menu', async function (assert) {
+ assert.expect(3);
+
await render(hbs``);
assert.notOk(
@@ -25,16 +27,22 @@ module('Integration | Component | page layout', function(hooks) {
);
await click('[data-test-header-gutter-toggle]');
- assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open');
+ assert.ok(
+ find('[data-test-gutter-menu]').classList.contains('is-open'),
+ 'Gutter menu is open'
+ );
await componentA11yAudit(this.element, assert);
});
- test('the gutter-menu hamburger menu closes the gutter menu', async function(assert) {
+ test('the gutter-menu hamburger menu closes the gutter menu', async function (assert) {
await render(hbs``);
await click('[data-test-header-gutter-toggle]');
- assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open');
+ assert.ok(
+ find('[data-test-gutter-menu]').classList.contains('is-open'),
+ 'Gutter menu is open'
+ );
await click('[data-test-gutter-gutter-toggle]');
assert.notOk(
@@ -43,12 +51,15 @@ module('Integration | Component | page layout', function(hooks) {
);
});
- test('the gutter-menu backdrop closes the gutter menu', async function(assert) {
+ test('the gutter-menu backdrop closes the gutter menu', async function (assert) {
await render(hbs``);
await click('[data-test-header-gutter-toggle]');
- assert.ok(find('[data-test-gutter-menu]').classList.contains('is-open'), 'Gutter menu is open');
+ assert.ok(
+ find('[data-test-gutter-menu]').classList.contains('is-open'),
+ 'Gutter menu is open'
+ );
await click('[data-test-gutter-backdrop]');
assert.notOk(
diff --git a/ui/tests/integration/components/placement-failure-test.js b/ui/tests/integration/components/placement-failure-test.js
index 78653426a..0801956f8 100644
--- a/ui/tests/integration/components/placement-failure-test.js
+++ b/ui/tests/integration/components/placement-failure-test.js
@@ -6,14 +6,16 @@ import hbs from 'htmlbars-inline-precompile';
import cleanWhitespace from '../../utils/clean-whitespace';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | placement failures', function(hooks) {
+module('Integration | Component | placement failures', function (hooks) {
setupRenderingTest(hooks);
const commonTemplate = hbs`
`;
- test('should render the placement failure (basic render)', async function(assert) {
+ test('should render the placement failure (basic render)', async function (assert) {
+ assert.expect(12);
+
const name = 'Placement Failure';
const failures = 11;
this.set(
@@ -29,12 +31,16 @@ module('Integration | Component | placement failures', function(hooks) {
await render(commonTemplate);
assert.equal(
- cleanWhitespace(find('[data-test-placement-failure-task-group]').firstChild.wholeText),
+ cleanWhitespace(
+ find('[data-test-placement-failure-task-group]').firstChild.wholeText
+ ),
name,
'Title is rendered with the name of the placement failure'
);
assert.equal(
- parseInt(find('[data-test-placement-failure-coalesced-failures]').textContent),
+ parseInt(
+ find('[data-test-placement-failure-coalesced-failures]').textContent
+ ),
failures,
'Title is rendered correctly with a count of unplaced'
);
@@ -78,12 +84,18 @@ module('Integration | Component | placement failures', function(hooks) {
1,
'Quota exhausted message shown'
);
- assert.equal(findAll('[data-test-placement-failure-scores]').length, 1, 'Scores message shown');
+ assert.equal(
+ findAll('[data-test-placement-failure-scores]').length,
+ 1,
+ 'Scores message shown'
+ );
await componentA11yAudit(this.element, assert);
});
- test('should render correctly when a node is not evaluated', async function(assert) {
+ test('should render correctly when a node is not evaluated', async function (assert) {
+ assert.expect(3);
+
this.set(
'taskGroup',
createFixture({
diff --git a/ui/tests/integration/components/plugin-allocation-row-test.js b/ui/tests/integration/components/plugin-allocation-row-test.js
index 243679a6b..073dff281 100644
--- a/ui/tests/integration/components/plugin-allocation-row-test.js
+++ b/ui/tests/integration/components/plugin-allocation-row-test.js
@@ -6,22 +6,27 @@ import { render, settled } from '@ember/test-helpers';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | plugin allocation row', function(hooks) {
+module('Integration | Component | plugin allocation row', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('node');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('Plugin allocation row immediately fetches the plugin allocation', async function(assert) {
- const plugin = this.server.create('csi-plugin', { id: 'plugin', controllerRequired: true });
+ test('Plugin allocation row immediately fetches the plugin allocation', async function (assert) {
+ assert.expect(2);
+
+ const plugin = this.server.create('csi-plugin', {
+ id: 'plugin',
+ controllerRequired: true,
+ });
const storageController = plugin.controllers.models[0];
const pluginRecord = await this.store.find('plugin', 'csi/plugin');
@@ -34,17 +39,21 @@ module('Integration | Component | plugin allocation row', function(hooks) {
`);
- await settled();
-
- const allocationRequest = this.server.pretender.handledRequests.find(req =>
- req.url.startsWith('/v1/allocation')
+ const allocationRequest = this.server.pretender.handledRequests.find(
+ (req) => req.url.startsWith('/v1/allocation')
+ );
+ assert.equal(
+ allocationRequest.url,
+ `/v1/allocation/${storageController.allocID}`
);
- assert.equal(allocationRequest.url, `/v1/allocation/${storageController.allocID}`);
await componentA11yAudit(this.element, assert);
});
- test('After the plugin allocation row fetches the plugin allocation, allocation stats are fetched', async function(assert) {
- const plugin = this.server.create('csi-plugin', { id: 'plugin', controllerRequired: true });
+ test('After the plugin allocation row fetches the plugin allocation, allocation stats are fetched', async function (assert) {
+ const plugin = this.server.create('csi-plugin', {
+ id: 'plugin',
+ controllerRequired: true,
+ });
const storageController = plugin.controllers.models[0];
const pluginRecord = await this.store.find('plugin', 'csi/plugin');
@@ -57,14 +66,15 @@ module('Integration | Component | plugin allocation row', function(hooks) {
`);
- await settled();
-
const [statsRequest] = this.server.pretender.handledRequests.slice(-1);
- assert.equal(statsRequest.url, `/v1/client/allocation/${storageController.allocID}/stats`);
+ assert.equal(
+ statsRequest.url,
+ `/v1/client/allocation/${storageController.allocID}/stats`
+ );
});
- test('Setting a new plugin fetches the new plugin allocation', async function(assert) {
+ test('Setting a new plugin fetches the new plugin allocation', async function (assert) {
const plugin = this.server.create('csi-plugin', {
id: 'plugin',
isMonolith: false,
@@ -84,21 +94,25 @@ module('Integration | Component | plugin allocation row', function(hooks) {
`);
- await settled();
-
- const allocationRequest = this.server.pretender.handledRequests.find(req =>
- req.url.startsWith('/v1/allocation')
+ const allocationRequest = this.server.pretender.handledRequests.find(
+ (req) => req.url.startsWith('/v1/allocation')
);
- assert.equal(allocationRequest.url, `/v1/allocation/${storageController.allocID}`);
+ assert.equal(
+ allocationRequest.url,
+ `/v1/allocation/${storageController.allocID}`
+ );
this.set('plugin', pluginRecord.get('controllers').toArray()[1]);
await settled();
const latestAllocationRequest = this.server.pretender.handledRequests
- .filter(req => req.url.startsWith('/v1/allocation'))
+ .filter((req) => req.url.startsWith('/v1/allocation'))
.reverse()[0];
- assert.equal(latestAllocationRequest.url, `/v1/allocation/${storageController2.allocID}`);
+ assert.equal(
+ latestAllocationRequest.url,
+ `/v1/allocation/${storageController2.allocID}`
+ );
});
});
diff --git a/ui/tests/integration/components/popover-menu-test.js b/ui/tests/integration/components/popover-menu-test.js
index 4f0184b37..511765cd7 100644
--- a/ui/tests/integration/components/popover-menu-test.js
+++ b/ui/tests/integration/components/popover-menu-test.js
@@ -1,4 +1,4 @@
-import { click } from '@ember/test-helpers';
+import { click, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -8,10 +8,10 @@ import popoverMenuPageObject from 'nomad-ui/tests/pages/components/popover-menu'
const PopoverMenu = create(popoverMenuPageObject());
-module('Integration | Component | popover-menu', function(hooks) {
+module('Integration | Component | popover-menu', function (hooks) {
setupRenderingTest(hooks);
- const commonProperties = overrides =>
+ const commonProperties = (overrides) =>
Object.assign(
{
triggerClass: '',
@@ -31,10 +31,12 @@ module('Integration | Component | popover-menu', function(hooks) {
`;
- test('presents as a button with a chevron-down icon', async function(assert) {
+ test('presents as a button with a chevron-down icon', async function (assert) {
+ assert.expect(5);
+
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(PopoverMenu.isPresent);
assert.ok(PopoverMenu.labelHasIcon);
@@ -43,10 +45,12 @@ module('Integration | Component | popover-menu', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('clicking the trigger button toggles the popover menu', async function(assert) {
+ test('clicking the trigger button toggles the popover menu', async function (assert) {
+ assert.expect(3);
+
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(PopoverMenu.menu.isOpen);
await PopoverMenu.toggle();
@@ -55,19 +59,19 @@ module('Integration | Component | popover-menu', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the trigger gets the triggerClass prop assigned as a class', async function(assert) {
+ test('the trigger gets the triggerClass prop assigned as a class', async function (assert) {
const specialClass = 'is-special';
const props = commonProperties({ triggerClass: specialClass });
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.dom('[data-test-popover-trigger]').hasClass('is-special');
});
- test('pressing DOWN ARROW when the trigger is focused opens the popover menu', async function(assert) {
+ test('pressing DOWN ARROW when the trigger is focused opens the popover menu', async function (assert) {
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(PopoverMenu.menu.isOpen);
await PopoverMenu.focus();
@@ -76,10 +80,10 @@ module('Integration | Component | popover-menu', function(hooks) {
assert.ok(PopoverMenu.menu.isOpen);
});
- test('pressing TAB when the trigger button is focused and the menu is open focuses the first focusable element in the popover menu', async function(assert) {
+ test('pressing TAB when the trigger button is focused and the menu is open focuses the first focusable element in the popover menu', async function (assert) {
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await PopoverMenu.focus();
await PopoverMenu.downArrow();
@@ -91,10 +95,10 @@ module('Integration | Component | popover-menu', function(hooks) {
assert.dom('#mock-input-for-test').isFocused();
});
- test('pressing ESC when the popover menu is open closes the menu and returns focus to the trigger button', async function(assert) {
+ test('pressing ESC when the popover menu is open closes the menu and returns focus to the trigger button', async function (assert) {
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await PopoverMenu.toggle();
assert.ok(PopoverMenu.menu.isOpen);
@@ -104,10 +108,10 @@ module('Integration | Component | popover-menu', function(hooks) {
assert.notOk(PopoverMenu.menu.isOpen);
});
- test('the ember-basic-dropdown object is yielded as context, including the close action', async function(assert) {
+ test('the ember-basic-dropdown object is yielded as context, including the close action', async function (assert) {
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await PopoverMenu.toggle();
assert.ok(PopoverMenu.menu.isOpen);
diff --git a/ui/tests/integration/components/primary-metric/allocation-test.js b/ui/tests/integration/components/primary-metric/allocation-test.js
index edc52a457..1a50f6f41 100644
--- a/ui/tests/integration/components/primary-metric/allocation-test.js
+++ b/ui/tests/integration/components/primary-metric/allocation-test.js
@@ -13,21 +13,25 @@ const mockTasks = [
{ task: 'Three', reservedCPU: 300, reservedMemory: 100, cpu: [], memory: [] },
];
-module('Integration | Component | PrimaryMetric::Allocation', function(hooks) {
+module('Integration | Component | PrimaryMetric::Allocation', function (hooks) {
setupRenderingTest(hooks);
setupPrimaryMetricMocks(hooks, [...mockTasks]);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('namespace');
this.server.create('node');
- this.server.create('job', { groupsCount: 1, groupTaskCount: 3, createAllocations: false });
+ this.server.create('job', {
+ groupsCount: 1,
+ groupTaskCount: 3,
+ createAllocations: false,
+ });
this.server.create('allocation');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -37,13 +41,16 @@ module('Integration | Component | PrimaryMetric::Allocation', function(hooks) {
@metric={{this.metric}} />
`;
- const preload = async store => {
+ const preload = async (store) => {
await store.findAll('allocation');
};
- const findResource = store => store.peekAll('allocation').get('firstObject');
+ const findResource = (store) =>
+ store.peekAll('allocation').get('firstObject');
+
+ test('Must pass an accessibility audit', async function (assert) {
+ assert.expect(1);
- test('Must pass an accessibility audit', async function(assert) {
await preload(this.store);
const resource = findResource(this.store);
@@ -53,7 +60,7 @@ module('Integration | Component | PrimaryMetric::Allocation', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Each task for the allocation gets its own line', async function(assert) {
+ test('Each task for the allocation gets its own line', async function (assert) {
await preload(this.store);
const resource = findResource(this.store);
diff --git a/ui/tests/integration/components/primary-metric/node-test.js b/ui/tests/integration/components/primary-metric/node-test.js
index e444c79ac..a6d944c3b 100644
--- a/ui/tests/integration/components/primary-metric/node-test.js
+++ b/ui/tests/integration/components/primary-metric/node-test.js
@@ -8,11 +8,11 @@ import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { formatScheduledHertz } from 'nomad-ui/utils/units';
-module('Integration | Component | PrimaryMetric::Node', function(hooks) {
+module('Integration | Component | PrimaryMetric::Node', function (hooks) {
setupRenderingTest(hooks);
setupPrimaryMetricMocks(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.server = startMirage();
@@ -20,7 +20,7 @@ module('Integration | Component | PrimaryMetric::Node', function(hooks) {
this.server.create('node');
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -30,13 +30,15 @@ module('Integration | Component | PrimaryMetric::Node', function(hooks) {
@metric={{this.metric}} />
`;
- const preload = async store => {
+ const preload = async (store) => {
await store.findAll('node');
};
- const findResource = store => store.peekAll('node').get('firstObject');
+ const findResource = (store) => store.peekAll('node').get('firstObject');
+
+ test('Must pass an accessibility audit', async function (assert) {
+ assert.expect(1);
- test('Must pass an accessibility audit', async function(assert) {
await preload(this.store);
const resource = findResource(this.store);
@@ -46,7 +48,7 @@ module('Integration | Component | PrimaryMetric::Node', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When the node has a reserved amount for the metric, a horizontal annotation is shown', async function(assert) {
+ test('When the node has a reserved amount for the metric, a horizontal annotation is shown', async function (assert) {
this.server.create('node', 'reserved', { id: 'withAnnotation' });
await preload(this.store);
diff --git a/ui/tests/integration/components/primary-metric/primary-metric.js b/ui/tests/integration/components/primary-metric/primary-metric.js
index a4e8f7f70..fb91cb20b 100644
--- a/ui/tests/integration/components/primary-metric/primary-metric.js
+++ b/ui/tests/integration/components/primary-metric/primary-metric.js
@@ -6,23 +6,23 @@ import { task } from 'ember-concurrency';
import sinon from 'sinon';
export function setupPrimaryMetricMocks(hooks, tasks = []) {
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
const getTrackerSpy = (this.getTrackerSpy = sinon.spy());
const trackerPollSpy = (this.trackerPollSpy = sinon.spy());
const trackerSignalPauseSpy = (this.trackerSignalPauseSpy = sinon.spy());
const MockTracker = EmberObject.extend({
- poll: task(function*() {
+ poll: task(function* () {
yield trackerPollSpy();
}),
- signalPause: task(function*() {
+ signalPause: task(function* () {
yield trackerSignalPauseSpy();
}),
- cpu: computed(function() {
+ cpu: computed(function () {
return [];
}),
- memory: computed(function() {
+ memory: computed(function () {
return [];
}),
tasks,
@@ -35,13 +35,18 @@ export function setupPrimaryMetricMocks(hooks, tasks = []) {
},
});
- this.owner.register('service:stats-trackers-registry', mockStatsTrackersRegistry);
- this.statsTrackersRegistry = this.owner.lookup('service:stats-trackers-registry');
+ this.owner.register(
+ 'service:stats-trackers-registry',
+ mockStatsTrackersRegistry
+ );
+ this.statsTrackersRegistry = this.owner.lookup(
+ 'service:stats-trackers-registry'
+ );
});
}
export function primaryMetric({ template, findResource, preload }) {
- test('Contains a line chart, a percentage bar, a percentage figure, and an absolute usage figure', async function(assert) {
+ test('Contains a line chart, a percentage bar, a percentage figure, and an absolute usage figure', async function (assert) {
const metric = 'cpu';
await preload(this.store);
@@ -57,7 +62,7 @@ export function primaryMetric({ template, findResource, preload }) {
assert.ok(find('[data-test-absolute-value]'), 'Absolute usage figure');
});
- test('The CPU metric maps to is-info', async function(assert) {
+ test('The CPU metric maps to is-info', async function (assert) {
const metric = 'cpu';
await preload(this.store);
@@ -73,7 +78,7 @@ export function primaryMetric({ template, findResource, preload }) {
);
});
- test('The Memory metric maps to is-danger', async function(assert) {
+ test('The Memory metric maps to is-danger', async function (assert) {
const metric = 'memory';
await preload(this.store);
@@ -89,7 +94,27 @@ export function primaryMetric({ template, findResource, preload }) {
);
});
- test('Gets the tracker from the tracker registry', async function(assert) {
+ test('Gets the tracker from the tracker registry', async function (assert) {
+ const metric = 'cpu';
+
+ await preload(this.store);
+
+ const resource = findResource(this.store);
+ this.setProperties({ resource, metric });
+
+ await render(template);
+
+ const spy =
+ this.getTrackerSpy.calledWith(resource) ||
+ this.getTrackerSpy.calledWith(resource.allocation);
+
+ assert.ok(
+ spy,
+ 'Uses the tracker registry to get the tracker for the provided resource'
+ );
+ });
+
+ test('Immediately polls the tracker', async function (assert) {
const metric = 'cpu';
await preload(this.store);
@@ -100,25 +125,12 @@ export function primaryMetric({ template, findResource, preload }) {
await render(template);
assert.ok(
- this.getTrackerSpy.calledWith(resource) || this.getTrackerSpy.calledWith(resource.allocation),
- 'Uses the tracker registry to get the tracker for the provided resource'
+ this.trackerPollSpy.calledOnce,
+ 'The tracker is polled immediately'
);
});
- test('Immediately polls the tracker', async function(assert) {
- const metric = 'cpu';
-
- await preload(this.store);
-
- const resource = findResource(this.store);
- this.setProperties({ resource, metric });
-
- await render(template);
-
- assert.ok(this.trackerPollSpy.calledOnce, 'The tracker is polled immediately');
- });
-
- test('A pause signal is sent to the tracker when the component is destroyed', async function(assert) {
+ test('A pause signal is sent to the tracker when the component is destroyed', async function (assert) {
const metric = 'cpu';
// Capture a reference to the spy before the component is destroyed
@@ -130,9 +142,15 @@ export function primaryMetric({ template, findResource, preload }) {
this.setProperties({ resource, metric });
await render(template);
- assert.notOk(trackerSignalPauseSpy.called, 'No pause signal has been sent yet');
+ assert.notOk(
+ trackerSignalPauseSpy.called,
+ 'No pause signal has been sent yet'
+ );
await clearRender();
- assert.ok(trackerSignalPauseSpy.calledOnce, 'A pause signal is sent to the tracker');
+ assert.ok(
+ trackerSignalPauseSpy.calledOnce,
+ 'A pause signal is sent to the tracker'
+ );
});
}
diff --git a/ui/tests/integration/components/primary-metric/task-test.js b/ui/tests/integration/components/primary-metric/task-test.js
index 71ac4ed25..d77638fac 100644
--- a/ui/tests/integration/components/primary-metric/task-test.js
+++ b/ui/tests/integration/components/primary-metric/task-test.js
@@ -13,11 +13,11 @@ const mockTasks = [
{ task: 'Three', reservedCPU: 300, reservedMemory: 100, cpu: [], memory: [] },
];
-module('Integration | Component | PrimaryMetric::Task', function(hooks) {
+module('Integration | Component | PrimaryMetric::Task', function (hooks) {
setupRenderingTest(hooks);
setupPrimaryMetricMocks(hooks, [...mockTasks]);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.server = startMirage();
@@ -37,7 +37,7 @@ module('Integration | Component | PrimaryMetric::Task', function(hooks) {
this.server.create('allocation', { forceRunningClientStatus: true });
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -47,13 +47,16 @@ module('Integration | Component | PrimaryMetric::Task', function(hooks) {
@metric={{this.metric}} />
`;
- const preload = async store => {
+ const preload = async (store) => {
await store.findAll('allocation');
};
- const findResource = store => store.peekAll('allocation').get('firstObject.states.firstObject');
+ const findResource = (store) =>
+ store.peekAll('allocation').get('firstObject.states.firstObject');
+
+ test('Must pass an accessibility audit', async function (assert) {
+ assert.expect(1);
- test('Must pass an accessibility audit', async function(assert) {
await preload(this.store);
const resource = findResource(this.store);
diff --git a/ui/tests/integration/components/reschedule-event-timeline-test.js b/ui/tests/integration/components/reschedule-event-timeline-test.js
index 80ca60bf3..34b8d6b08 100644
--- a/ui/tests/integration/components/reschedule-event-timeline-test.js
+++ b/ui/tests/integration/components/reschedule-event-timeline-test.js
@@ -6,10 +6,10 @@ import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import moment from 'moment';
-module('Integration | Component | reschedule event timeline', function(hooks) {
+module('Integration | Component | reschedule event timeline', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('namespace');
@@ -17,7 +17,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
this.server.create('job', { createAllocations: false });
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -25,7 +25,9 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
`;
- test('when the allocation is running, the timeline shows past allocations', async function(assert) {
+ test('when the allocation is running, the timeline shows past allocations', async function (assert) {
+ assert.expect(7);
+
const attempts = 2;
this.server.create('allocation', 'rescheduled', {
@@ -37,7 +39,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
const allocation = this.store
.peekAll('allocation')
- .find(alloc => !alloc.get('nextAllocation.content'));
+ .find((alloc) => !alloc.get('nextAllocation.content'));
this.set('allocation', allocation);
await render(commonTemplate);
@@ -74,7 +76,9 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when the allocation has failed and there is a follow up evaluation, a note with a time is shown', async function(assert) {
+ test('when the allocation has failed and there is a follow up evaluation, a note with a time is shown', async function (assert) {
+ assert.expect(3);
+
const attempts = 2;
this.server.create('allocation', 'rescheduled', {
@@ -86,7 +90,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
const allocation = this.store
.peekAll('allocation')
- .find(alloc => !alloc.get('nextAllocation.content'));
+ .find((alloc) => !alloc.get('nextAllocation.content'));
this.set('allocation', allocation);
await render(commonTemplate);
@@ -95,12 +99,17 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
find('[data-test-stop-warning]'),
'Stop warning is shown since the last allocation failed'
);
- assert.notOk(find('[data-test-attempt-notice]'), 'Reschdule attempt notice is not shown');
+ assert.notOk(
+ find('[data-test-attempt-notice]'),
+ 'Reschdule attempt notice is not shown'
+ );
await componentA11yAudit(this.element, assert);
});
- test('when the allocation has failed and there is no follow up evaluation, a warning is shown', async function(assert) {
+ test('when the allocation has failed and there is no follow up evaluation, a warning is shown', async function (assert) {
+ assert.expect(3);
+
const attempts = 2;
this.server.create('allocation', 'rescheduled', {
@@ -108,12 +117,12 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
rescheduleSuccess: false,
});
- const lastAllocation = server.schema.allocations.findBy({ nextAllocation: undefined });
+ const lastAllocation = server.schema.allocations.findBy({
+ nextAllocation: undefined,
+ });
lastAllocation.update({
followupEvalId: server.create('evaluation', {
- waitUntil: moment()
- .add(2, 'hours')
- .toDate(),
+ waitUntil: moment().add(2, 'hours').toDate(),
}).id,
});
@@ -121,7 +130,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
let allocation = this.store
.peekAll('allocation')
- .find(alloc => !alloc.get('nextAllocation.content'));
+ .find((alloc) => !alloc.get('nextAllocation.content'));
this.set('allocation', allocation);
await render(commonTemplate);
@@ -135,7 +144,7 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when the allocation has a next allocation already, it is shown in the timeline', async function(assert) {
+ test('when the allocation has a next allocation already, it is shown in the timeline', async function (assert) {
const attempts = 2;
const originalAllocation = this.server.create('allocation', 'rescheduled', {
@@ -145,19 +154,23 @@ module('Integration | Component | reschedule event timeline', function(hooks) {
await this.store.findAll('allocation');
- const allocation = this.store.peekAll('allocation').findBy('id', originalAllocation.id);
+ const allocation = this.store
+ .peekAll('allocation')
+ .findBy('id', originalAllocation.id);
this.set('allocation', allocation);
await render(commonTemplate);
- assert.ok(
+ assert.equal(
find('[data-test-reschedule-label]').textContent.trim(),
'Next Allocation',
'The first allocation is the next allocation and labeled as such'
);
assert.equal(
- find('[data-test-allocation] [data-test-allocation-link]').textContent.trim(),
+ find(
+ '[data-test-allocation] [data-test-allocation-link]'
+ ).textContent.trim(),
allocation.get('nextAllocation.shortId'),
'The next allocation item is for the correct allocation'
);
diff --git a/ui/tests/integration/components/scale-events-accordion-test.js b/ui/tests/integration/components/scale-events-accordion-test.js
index 5b4af356b..0f3623dd0 100644
--- a/ui/tests/integration/components/scale-events-accordion-test.js
+++ b/ui/tests/integration/components/scale-events-accordion-test.js
@@ -7,44 +7,58 @@ import setupCodeMirror from 'nomad-ui/tests/helpers/codemirror';
import { initialize as fragmentSerializerInitializer } from 'nomad-ui/initializers/fragment-serializer';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | scale-events-accordion', function(hooks) {
+module('Integration | Component | scale-events-accordion', function (hooks) {
setupRenderingTest(hooks);
setupCodeMirror(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.server = startMirage();
this.server.create('node');
- this.taskGroupWithEvents = async function(events) {
+ this.taskGroupWithEvents = async function (events) {
const job = this.server.create('job', { createAllocations: false });
const group = job.taskGroups.models[0];
- job.jobScale.taskGroupScales.models.findBy('name', group.name).update({ events });
+ job.jobScale.taskGroupScales.models
+ .findBy('name', group.name)
+ .update({ events });
- const jobModel = await this.store.find('job', JSON.stringify([job.id, 'default']));
+ const jobModel = await this.store.find(
+ 'job',
+ JSON.stringify([job.id, 'default'])
+ );
await jobModel.get('scaleState');
return jobModel.taskGroups.findBy('name', group.name);
};
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
const commonTemplate = hbs``;
- test('it shows an accordion with an entry for each event', async function(assert) {
+ test('it shows an accordion with an entry for each event', async function (assert) {
+ assert.expect(2);
+
const eventCount = 5;
- const taskGroup = await this.taskGroupWithEvents(server.createList('scale-event', eventCount));
+ const taskGroup = await this.taskGroupWithEvents(
+ server.createList('scale-event', eventCount)
+ );
this.set('events', taskGroup.scaleState.events);
await render(commonTemplate);
- assert.equal(findAll('[data-test-scale-events] [data-test-accordion-head]').length, eventCount);
+ assert.equal(
+ findAll('[data-test-scale-events] [data-test-accordion-head]').length,
+ eventCount
+ );
await componentA11yAudit(this.element, assert);
});
- test('when an event is an error, an error icon is shown', async function(assert) {
+ test('when an event is an error, an error icon is shown', async function (assert) {
+ assert.expect(2);
+
const taskGroup = await this.taskGroupWithEvents(
server.createList('scale-event', 1, { error: true })
);
@@ -56,10 +70,16 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when an event has a count higher than previous count, a danger up arrow is shown', async function(assert) {
+ test('when an event has a count higher than previous count, a danger up arrow is shown', async function (assert) {
+ assert.expect(4);
+
const count = 5;
const taskGroup = await this.taskGroupWithEvents(
- server.createList('scale-event', 1, { count, previousCount: count - 1, error: false })
+ server.createList('scale-event', 1, {
+ count,
+ previousCount: count - 1,
+ error: false,
+ })
);
this.set('events', taskGroup.scaleState.events);
@@ -75,10 +95,14 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when an event has a count lower than previous count, a primary down arrow is shown', async function(assert) {
+ test('when an event has a count lower than previous count, a primary down arrow is shown', async function (assert) {
const count = 5;
const taskGroup = await this.taskGroupWithEvents(
- server.createList('scale-event', 1, { count, previousCount: count + 1, error: false })
+ server.createList('scale-event', 1, {
+ count,
+ previousCount: count + 1,
+ error: false,
+ })
);
this.set('events', taskGroup.scaleState.events);
@@ -93,7 +117,7 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
);
});
- test('when an event has no count, the count is omitted', async function(assert) {
+ test('when an event has no count, the count is omitted', async function (assert) {
const taskGroup = await this.taskGroupWithEvents(
server.createList('scale-event', 1, { count: null })
);
@@ -105,7 +129,9 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
assert.notOk(find('[data-test-count-icon]'));
});
- test('when an event has no meta properties, the accordion entry is not expandable', async function(assert) {
+ test('when an event has no meta properties, the accordion entry is not expandable', async function (assert) {
+ assert.expect(2);
+
const taskGroup = await this.taskGroupWithEvents(
server.createList('scale-event', 1, { meta: {} })
);
@@ -113,11 +139,15 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
await render(commonTemplate);
- assert.ok(find('[data-test-accordion-toggle]').classList.contains('is-invisible'));
+ assert.ok(
+ find('[data-test-accordion-toggle]').classList.contains('is-invisible')
+ );
await componentA11yAudit(this.element, assert);
});
- test('when an event has meta properties, the accordion entry is expanding, presenting the meta properties in a json viewer', async function(assert) {
+ test('when an event has meta properties, the accordion entry is expanding, presenting the meta properties in a json viewer', async function (assert) {
+ assert.expect(4);
+
const meta = {
prop: 'one',
prop2: 'two',
@@ -126,7 +156,9 @@ module('Integration | Component | scale-events-accordion', function(hooks) {
'dot.separate.prop': 12,
},
};
- const taskGroup = await this.taskGroupWithEvents(server.createList('scale-event', 1, { meta }));
+ const taskGroup = await this.taskGroupWithEvents(
+ server.createList('scale-event', 1, { meta })
+ );
this.set('events', taskGroup.scaleState.events);
await render(commonTemplate);
diff --git a/ui/tests/integration/components/scale-events-chart-test.js b/ui/tests/integration/components/scale-events-chart-test.js
index 87994e806..f0c048eca 100644
--- a/ui/tests/integration/components/scale-events-chart-test.js
+++ b/ui/tests/integration/components/scale-events-chart-test.js
@@ -6,7 +6,7 @@ import moment from 'moment';
import setupCodeMirror from 'nomad-ui/tests/helpers/codemirror';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | scale-events-chart', function(hooks) {
+module('Integration | Component | scale-events-chart', function (hooks) {
setupRenderingTest(hooks);
setupCodeMirror(hooks);
@@ -51,22 +51,23 @@ module('Integration | Component | scale-events-chart', function(hooks) {
},
];
- test('each event is rendered as an annotation', async function(assert) {
+ test('each event is rendered as an annotation', async function (assert) {
+ assert.expect(2);
+
this.set('events', events);
await render(hbs``);
assert.equal(
findAll('[data-test-annotation]').length,
- events.filter(ev => ev.count == null).length
+ events.filter((ev) => ev.count == null).length
);
await componentA11yAudit(this.element, assert);
});
- test('clicking an annotation presents details for the event', async function(assert) {
- const annotation = events
- .rejectBy('hasCount')
- .sortBy('time')
- .reverse()[0];
+ test('clicking an annotation presents details for the event', async function (assert) {
+ assert.expect(6);
+
+ const annotation = events.rejectBy('hasCount').sortBy('time').reverse()[0];
this.set('events', events);
await render(hbs``);
@@ -88,7 +89,7 @@ module('Integration | Component | scale-events-chart', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('clicking an active annotation closes event details', async function(assert) {
+ test('clicking an active annotation closes event details', async function (assert) {
this.set('events', events);
await render(hbs``);
diff --git a/ui/tests/integration/components/single-select-dropdown-test.js b/ui/tests/integration/components/single-select-dropdown-test.js
index 3d509de75..cc6d0b37b 100644
--- a/ui/tests/integration/components/single-select-dropdown-test.js
+++ b/ui/tests/integration/components/single-select-dropdown-test.js
@@ -1,12 +1,15 @@
import { findAll, find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
-import { selectChoose, clickTrigger } from 'ember-power-select/test-support/helpers';
+import {
+ selectChoose,
+ clickTrigger,
+} from 'ember-power-select/test-support/helpers';
import sinon from 'sinon';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
-module('Integration | Component | single-select dropdown', function(hooks) {
+module('Integration | Component | single-select dropdown', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -31,12 +34,16 @@ module('Integration | Component | single-select dropdown', function(hooks) {
@onSelect={{this.onSelect}} />
`;
- test('component shows label and selection in the trigger', async function(assert) {
+ test('component shows label and selection in the trigger', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
- assert.ok(find('.ember-power-select-trigger').textContent.includes(props.label));
+ assert.ok(
+ find('.ember-power-select-trigger').textContent.includes(props.label)
+ );
assert.ok(
find('.ember-power-select-trigger').textContent.includes(
props.options.findBy('key', props.selection).label
@@ -47,7 +54,9 @@ module('Integration | Component | single-select dropdown', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('all options are shown in the dropdown', async function(assert) {
+ test('all options are shown in the dropdown', async function (assert) {
+ assert.expect(7);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -67,7 +76,7 @@ module('Integration | Component | single-select dropdown', function(hooks) {
});
});
- test('selecting an option calls `onSelect` with the key for the selected option', async function(assert) {
+ test('selecting an option calls `onSelect` with the key for the selected option', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
diff --git a/ui/tests/integration/components/stepper-input-test.js b/ui/tests/integration/components/stepper-input-test.js
index 9e22ad9b3..fa5c3e144 100644
--- a/ui/tests/integration/components/stepper-input-test.js
+++ b/ui/tests/integration/components/stepper-input-test.js
@@ -1,4 +1,10 @@
-import { find, render, settled, triggerEvent, waitUntil } from '@ember/test-helpers';
+import {
+ find,
+ render,
+ settled,
+ triggerEvent,
+ waitUntil,
+} from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -13,7 +19,7 @@ const valueChange = () => {
return () => StepperInput.input.value !== initial;
};
-module('Integration | Component | stepper input', function(hooks) {
+module('Integration | Component | stepper input', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -39,7 +45,9 @@ module('Integration | Component | stepper input', function(hooks) {
`;
- test('basic appearance includes a label, an input, and two buttons', async function(assert) {
+ test('basic appearance includes a label, an input, and two buttons', async function (assert) {
+ assert.expect(7);
+
this.setProperties(commonProperties());
await render(commonTemplate);
@@ -48,13 +56,17 @@ module('Integration | Component | stepper input', function(hooks) {
assert.equal(StepperInput.input.value, this.value);
assert.ok(StepperInput.decrement.isPresent);
assert.ok(StepperInput.increment.isPresent);
- assert.ok(StepperInput.decrement.classNames.split(' ').includes(this.classVariant));
- assert.ok(StepperInput.increment.classNames.split(' ').includes(this.classVariant));
+ assert.ok(
+ StepperInput.decrement.classNames.split(' ').includes(this.classVariant)
+ );
+ assert.ok(
+ StepperInput.increment.classNames.split(' ').includes(this.classVariant)
+ );
await componentA11yAudit(this.element, assert);
});
- test('clicking the increment and decrement buttons immediately changes the shown value in the input but debounces the onUpdate call', async function(assert) {
+ test('clicking the increment and decrement buttons immediately changes the shown value in the input but debounces the onUpdate call', async function (assert) {
this.setProperties(commonProperties());
const baseValue = this.value;
@@ -80,7 +92,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(this.onChange.calledWith(baseValue - 1));
});
- test('the increment button is disabled when the internal value is the max value', async function(assert) {
+ test('the increment button is disabled when the internal value is the max value', async function (assert) {
this.setProperties(commonProperties());
this.set('value', this.max);
@@ -89,7 +101,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(StepperInput.increment.isDisabled);
});
- test('the decrement button is disabled when the internal value is the min value', async function(assert) {
+ test('the decrement button is disabled when the internal value is the min value', async function (assert) {
this.setProperties(commonProperties());
this.set('value', this.min);
@@ -98,7 +110,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(StepperInput.decrement.isDisabled);
});
- test('the text input does not call the onUpdate function on oninput', async function(assert) {
+ test('the text input does not call the onUpdate function on oninput', async function (assert) {
this.setProperties(commonProperties());
const newValue = 8;
@@ -119,7 +131,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(this.onChange.calledWith(newValue));
});
- test('the text input does call the onUpdate function on onchange', async function(assert) {
+ test('the text input does call the onUpdate function on onchange', async function (assert) {
this.setProperties(commonProperties());
const newValue = 8;
@@ -132,7 +144,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(this.onChange.calledWith(newValue));
});
- test('text input limits input to the bounds of the min/max range', async function(assert) {
+ test('text input limits input to the bounds of the min/max range', async function (assert) {
this.setProperties(commonProperties());
let newValue = this.max + 1;
@@ -153,7 +165,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(this.onChange.calledWith(this.min));
});
- test('pressing ESC in the text input reverts the text value back to the current value', async function(assert) {
+ test('pressing ESC in the text input reverts the text value back to the current value', async function (assert) {
this.setProperties(commonProperties());
const newValue = 8;
@@ -168,7 +180,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.equal(StepperInput.input.value, this.value);
});
- test('clicking the label focuses in the input', async function(assert) {
+ test('clicking the label focuses in the input', async function (assert) {
this.setProperties(commonProperties());
await render(commonTemplate);
@@ -178,22 +190,19 @@ module('Integration | Component | stepper input', function(hooks) {
assert.equal(document.activeElement, input);
});
- test('focusing the input selects the input value', async function(assert) {
+ test('focusing the input selects the input value', async function (assert) {
this.setProperties(commonProperties());
await render(commonTemplate);
await StepperInput.input.focus();
assert.equal(
- window
- .getSelection()
- .toString()
- .trim(),
+ window.getSelection().toString().trim(),
this.value.toString()
);
});
- test('entering a fractional value floors the value', async function(assert) {
+ test('entering a fractional value floors the value', async function (assert) {
this.setProperties(commonProperties());
const newValue = 3.14159;
@@ -206,7 +215,7 @@ module('Integration | Component | stepper input', function(hooks) {
assert.ok(this.onChange.calledWith(Math.floor(newValue)));
});
- test('entering an invalid value reverts the value', async function(assert) {
+ test('entering an invalid value reverts the value', async function (assert) {
this.setProperties(commonProperties());
const newValue = 'NaN';
diff --git a/ui/tests/integration/components/streaming-file-test.js b/ui/tests/integration/components/streaming-file-test.js
index 94bb56ec3..31e7b9580 100644
--- a/ui/tests/integration/components/streaming-file-test.js
+++ b/ui/tests/integration/components/streaming-file-test.js
@@ -1,5 +1,5 @@
import { run } from '@ember/runloop';
-import { find, settled, triggerKeyEvent } from '@ember/test-helpers';
+import { find, render, triggerKeyEvent } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -12,7 +12,7 @@ import Log from 'nomad-ui/utils/classes/log';
const { assign } = Object;
const A_KEY = 65;
-const stringifyValues = obj =>
+const stringifyValues = (obj) =>
Object.keys(obj).reduce((newObj, key) => {
newObj[key] = obj[key].toString();
return newObj;
@@ -23,20 +23,20 @@ const makeLogger = (url, params) =>
url,
params,
plainText: true,
- logFetch: url => fetch(url).then(res => res),
+ logFetch: (url) => fetch(url).then((res) => res),
});
-module('Integration | Component | streaming file', function(hooks) {
+module('Integration | Component | streaming file', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
- this.server = new Pretender(function() {
+ hooks.beforeEach(function () {
+ this.server = new Pretender(function () {
this.get('/file/endpoint', () => [200, {}, 'Hello World']);
this.get('/file/stream', () => [200, {}, logEncode(['Hello World'], 0)]);
});
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -44,7 +44,9 @@ module('Integration | Component | streaming file', function(hooks) {
`;
- test('when mode is `head`, the logger signals head', async function(assert) {
+ test('when mode is `head`, the logger signals head', async function (assert) {
+ assert.expect(5);
+
const url = '/file/endpoint';
const params = { path: 'hello/world.txt', offset: 0, limit: 50000 };
this.setProperties({
@@ -53,8 +55,7 @@ module('Integration | Component | streaming file', function(hooks) {
isStreaming: false,
});
- await this.render(commonTemplate);
- await settled();
+ await render(commonTemplate);
const request = this.server.handledRequests[0];
assert.equal(this.server.handledRequests.length, 1, 'One request made');
@@ -68,7 +69,7 @@ module('Integration | Component | streaming file', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('when mode is `tail`, the logger signals tail', async function(assert) {
+ test('when mode is `tail`, the logger signals tail', async function (assert) {
const url = '/file/endpoint';
const params = { path: 'hello/world.txt', limit: 50000 };
this.setProperties({
@@ -77,8 +78,7 @@ module('Integration | Component | streaming file', function(hooks) {
isStreaming: false,
});
- await this.render(commonTemplate);
- await settled();
+ await render(commonTemplate);
const request = this.server.handledRequests[0];
assert.equal(this.server.handledRequests.length, 1, 'One request made');
@@ -91,7 +91,7 @@ module('Integration | Component | streaming file', function(hooks) {
assert.equal(find('[data-test-output]').textContent, 'Hello World');
});
- test('when mode is `streaming` and `isStreaming` is true, streaming starts', async function(assert) {
+ test('when mode is `streaming` and `isStreaming` is true, streaming starts', async function (assert) {
const url = '/file/stream';
const params = { path: 'hello/world.txt', limit: 50000 };
this.setProperties({
@@ -104,15 +104,14 @@ module('Integration | Component | streaming file', function(hooks) {
run.later(run, run.cancelTimers, 500);
- await this.render(commonTemplate);
- await settled();
+ await render(commonTemplate);
const request = this.server.handledRequests[0];
assert.equal(request.url.split('?')[0], url, `URL is ${url}`);
assert.equal(find('[data-test-output]').textContent, 'Hello World');
});
- test('the ctrl+a/cmd+a shortcut selects only the text in the output window', async function(assert) {
+ test('the ctrl+a/cmd+a shortcut selects only the text in the output window', async function (assert) {
const url = '/file/endpoint';
const params = { path: 'hello/world.txt', offset: 0, limit: 50000 };
this.setProperties({
@@ -121,32 +120,29 @@ module('Integration | Component | streaming file', function(hooks) {
isStreaming: false,
});
- await this.render(hbs`
+ await render(hbs`
Extra text
On either side
`);
- await settled();
// Windows and Linux shortcut
- await triggerKeyEvent('[data-test-output]', 'keydown', A_KEY, { ctrlKey: true });
+ await triggerKeyEvent('[data-test-output]', 'keydown', A_KEY, {
+ ctrlKey: true,
+ });
assert.equal(
- window
- .getSelection()
- .toString()
- .trim(),
+ window.getSelection().toString().trim(),
find('[data-test-output]').textContent.trim()
);
window.getSelection().removeAllRanges();
// MacOS shortcut
- await triggerKeyEvent('[data-test-output]', 'keydown', A_KEY, { metaKey: true });
+ await triggerKeyEvent('[data-test-output]', 'keydown', A_KEY, {
+ metaKey: true,
+ });
assert.equal(
- window
- .getSelection()
- .toString()
- .trim(),
+ window.getSelection().toString().trim(),
find('[data-test-output]').textContent.trim()
);
});
diff --git a/ui/tests/integration/components/task-group-row-test.js b/ui/tests/integration/components/task-group-row-test.js
index 1f7ac954d..48f0cd77b 100644
--- a/ui/tests/integration/components/task-group-row-test.js
+++ b/ui/tests/integration/components/task-group-row-test.js
@@ -45,10 +45,10 @@ const makeJob = (server, props = {}) => {
});
};
-module('Integration | Component | task group row', function(hooks) {
+module('Integration | Component | task group row', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
fragmentSerializerInitializer(this.owner);
this.store = this.owner.lookup('service:store');
this.token = this.owner.lookup('service:token');
@@ -60,7 +60,7 @@ module('Integration | Component | task group row', function(hooks) {
window.localStorage.nomadTokenSecret = managementToken.secretId;
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
window.localStorage.clear();
});
@@ -69,7 +69,9 @@ module('Integration | Component | task group row', function(hooks) {
`;
- test('Task group row conditionally shows scaling buttons based on the presence of the scaling attr on the task group', async function(assert) {
+ test('Task group row conditionally shows scaling buttons based on the presence of the scaling attr on the task group', async function (assert) {
+ assert.expect(3);
+
makeJob(this.server, { noActiveDeployment: true });
this.token.fetchSelfTokenAndPolicies.perform();
await settled();
@@ -88,7 +90,7 @@ module('Integration | Component | task group row', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Clicking scaling buttons immediately updates the rendered count but debounces the scaling API request', async function(assert) {
+ test('Clicking scaling buttons immediately updates the rendered count but debounces the scaling API request', async function (assert) {
makeJob(this.server, { noActiveDeployment: true });
this.token.fetchSelfTokenAndPolicies.perform();
await settled();
@@ -109,19 +111,21 @@ module('Integration | Component | task group row', function(hooks) {
assert.notOk(
server.pretender.handledRequests.find(
- req => req.method === 'POST' && req.url.endsWith('/scale')
+ (req) => req.method === 'POST' && req.url.endsWith('/scale')
)
);
await settled();
const scaleRequests = server.pretender.handledRequests.filter(
- req => req.method === 'POST' && req.url.endsWith('/scale')
+ (req) => req.method === 'POST' && req.url.endsWith('/scale')
);
assert.equal(scaleRequests.length, 1);
assert.equal(JSON.parse(scaleRequests[0].requestBody).Count, 4);
});
- test('When the current count is equal to the max count, the increment count button is disabled', async function(assert) {
+ test('When the current count is equal to the max count, the increment count button is disabled', async function (assert) {
+ assert.expect(2);
+
makeJob(this.server, { noActiveDeployment: true });
this.token.fetchSelfTokenAndPolicies.perform();
await settled();
@@ -137,7 +141,9 @@ module('Integration | Component | task group row', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When the current count is equal to the min count, the decrement count button is disabled', async function(assert) {
+ test('When the current count is equal to the min count, the decrement count button is disabled', async function (assert) {
+ assert.expect(2);
+
makeJob(this.server, { noActiveDeployment: true });
this.token.fetchSelfTokenAndPolicies.perform();
await settled();
@@ -153,7 +159,9 @@ module('Integration | Component | task group row', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When there is an active deployment, both scale buttons are disabled', async function(assert) {
+ test('When there is an active deployment, both scale buttons are disabled', async function (assert) {
+ assert.expect(3);
+
makeJob(this.server, { activeDeployment: true });
this.token.fetchSelfTokenAndPolicies.perform();
await settled();
@@ -168,7 +176,7 @@ module('Integration | Component | task group row', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('When the current ACL token does not have the namespace:scale-job or namespace:submit-job policy rule', async function(assert) {
+ test('When the current ACL token does not have the namespace:scale-job or namespace:submit-job policy rule', async function (assert) {
makeJob(this.server, { noActiveDeployment: true });
window.localStorage.nomadTokenSecret = clientToken.secretId;
this.token.fetchSelfTokenAndPolicies.perform();
diff --git a/ui/tests/integration/components/task-log-test.js b/ui/tests/integration/components/task-log-test.js
index ef3943e0a..90c3d41cb 100644
--- a/ui/tests/integration/components/task-log-test.js
+++ b/ui/tests/integration/components/task-log-test.js
@@ -28,10 +28,10 @@ const streamFrames = ['one\n', 'two\n', 'three\n', 'four\n', 'five\n'];
let streamPointer = 0;
let logMode = null;
-module('Integration | Component | task log', function(hooks) {
+module('Integration | Component | task log', function (hooks) {
setupRenderingTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
const handler = ({ queryParams }) => {
let frames;
let data;
@@ -45,42 +45,56 @@ module('Integration | Component | task log', function(hooks) {
}
if (frames === streamFrames) {
- data = queryParams.plain ? frames[streamPointer] : logEncode(frames, streamPointer);
+ data = queryParams.plain
+ ? frames[streamPointer]
+ : logEncode(frames, streamPointer);
streamPointer++;
} else {
- data = queryParams.plain ? frames.join('') : logEncode(frames, frames.length - 1);
+ data = queryParams.plain
+ ? frames.join('')
+ : logEncode(frames, frames.length - 1);
}
return [200, {}, data];
};
- this.server = new Pretender(function() {
+ this.server = new Pretender(function () {
this.get(`http://${HOST}/v1/client/fs/logs/:allocation_id`, handler);
this.get('/v1/client/fs/logs/:allocation_id', handler);
this.get('/v1/regions', () => [200, {}, '[]']);
});
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
window.localStorage.clear();
this.server.shutdown();
streamPointer = 0;
logMode = null;
});
- test('Basic appearance', async function(assert) {
+ test('Basic appearance', async function (assert) {
+ assert.expect(8);
+
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
assert.ok(find('[data-test-log-action="stdout"]'), 'Stdout button');
assert.ok(find('[data-test-log-action="stderr"]'), 'Stderr button');
assert.ok(find('[data-test-log-action="head"]'), 'Head button');
assert.ok(find('[data-test-log-action="tail"]'), 'Tail button');
- assert.ok(find('[data-test-log-action="toggle-stream"]'), 'Stream toggle button');
+ assert.ok(
+ find('[data-test-log-action="toggle-stream"]'),
+ 'Stream toggle button'
+ );
- assert.ok(find('[data-test-log-box].is-full-bleed.is-dark'), 'Body is full-bleed and dark');
+ assert.ok(
+ find('[data-test-log-box].is-full-bleed.is-dark'),
+ 'Body is full-bleed and dark'
+ );
assert.ok(
find('pre.cli-window'),
@@ -90,15 +104,22 @@ module('Integration | Component | task log', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Streaming starts on creation', async function(assert) {
+ test('Streaming starts on creation', async function (assert) {
+ assert.expect(3);
+
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
- const logUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
+ const logUrlRegex = new RegExp(
+ `${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`
+ );
assert.ok(
- this.server.handledRequests.filter(req => logUrlRegex.test(req.url)).length,
+ this.server.handledRequests.filter((req) => logUrlRegex.test(req.url))
+ .length,
'Log requests were made'
);
@@ -112,12 +133,14 @@ module('Integration | Component | task log', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('Clicking Head loads the log head', async function(assert) {
+ test('Clicking Head loads the log head', async function (assert) {
logMode = 'head';
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
click('[data-test-log-action="head"]');
@@ -128,27 +151,41 @@ module('Integration | Component | task log', function(hooks) {
),
'Log head request was made'
);
- assert.equal(find('[data-test-log-cli]').textContent, logHead[0], 'Head of the log is shown');
+ assert.equal(
+ find('[data-test-log-cli]').textContent,
+ logHead[0],
+ 'Head of the log is shown'
+ );
});
- test('Clicking Tail loads the log tail', async function(assert) {
+ test('Clicking Tail loads the log tail', async function (assert) {
logMode = 'tail';
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
click('[data-test-log-action="tail"]');
await settled();
assert.ok(
- this.server.handledRequests.find(({ queryParams: qp }) => qp.origin === 'end'),
+ this.server.handledRequests.find(
+ ({ queryParams: qp }) => qp.origin === 'end'
+ ),
'Log tail request was made'
);
- assert.equal(find('[data-test-log-cli]').textContent, logTail[0], 'Tail of the log is shown');
+ assert.equal(
+ find('[data-test-log-cli]').textContent,
+ logTail[0],
+ 'Tail of the log is shown'
+ );
});
- test('Clicking toggleStream starts and stops the log stream', async function(assert) {
+ test('Clicking toggleStream starts and stops the log stream', async function (assert) {
+ assert.expect(3);
+
run.later(run, run.cancelTimers, commonProps.interval);
const { interval } = commonProps;
@@ -162,7 +199,11 @@ module('Integration | Component | task log', function(hooks) {
}, interval);
await settled();
- assert.equal(find('[data-test-log-cli]').textContent, streamFrames[0], 'First frame loaded');
+ assert.equal(
+ find('[data-test-log-cli]').textContent,
+ streamFrames[0],
+ 'First frame loaded'
+ );
run.later(() => {
assert.equal(
@@ -182,23 +223,27 @@ module('Integration | Component | task log', function(hooks) {
);
});
- test('Clicking stderr switches the log to standard error', async function(assert) {
+ test('Clicking stderr switches the log to standard error', async function (assert) {
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
click('[data-test-log-action="stderr"]');
run.later(run, run.cancelTimers, commonProps.interval);
await settled();
assert.ok(
- this.server.handledRequests.filter(req => req.queryParams.type === 'stderr').length,
+ this.server.handledRequests.filter(
+ (req) => req.queryParams.type === 'stderr'
+ ).length,
'stderr log requests were made'
);
});
- test('Clicking stderr/stdout mode buttons does nothing when the mode remains the same', async function(assert) {
+ test('Clicking stderr/stdout mode buttons does nothing when the mode remains the same', async function (assert) {
const { interval } = commonProps;
run.later(() => {
@@ -207,9 +252,10 @@ module('Integration | Component | task log', function(hooks) {
}, interval * 2);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
- await settled();
assert.equal(
find('[data-test-log-cli]').textContent,
streamFrames[0] + streamFrames[0] + streamFrames[1],
@@ -217,7 +263,7 @@ module('Integration | Component | task log', function(hooks) {
);
});
- test('When the client is inaccessible, task-log falls back to requesting logs through the server', async function(assert) {
+ test('When the client is inaccessible, task-log falls back to requesting logs through the server', async function (assert) {
run.later(run, run.cancelTimers, allowedConnectionTime * 2);
// override client response to timeout
@@ -234,26 +280,34 @@ module('Integration | Component | task log', function(hooks) {
@clientTimeout={{clientTimeout}}
@serverTimeout={{serverTimeout}} />`);
- const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
+ const clientUrlRegex = new RegExp(
+ `${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`
+ );
assert.ok(
- this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
+ this.server.handledRequests.filter((req) => clientUrlRegex.test(req.url))
+ .length,
'Log request was initially made directly to the client'
);
await settled();
const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
assert.ok(
- this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
+ this.server.handledRequests.filter((req) => req.url.startsWith(serverUrl))
+ .length,
'Log request was later made to the server'
);
assert.ok(
- this.server.handledRequests.filter(req => clientUrlRegex.test(req.url))[0].aborted,
+ this.server.handledRequests.filter((req) =>
+ clientUrlRegex.test(req.url)
+ )[0].aborted,
'Client log request was aborted'
);
});
- test('When both the client and the server are inaccessible, an error message is shown', async function(assert) {
+ test('When both the client and the server are inaccessible, an error message is shown', async function (assert) {
+ assert.expect(5);
+
run.later(run, run.cancelTimers, allowedConnectionTime * 5);
// override client and server responses to timeout
@@ -275,26 +329,35 @@ module('Integration | Component | task log', function(hooks) {
@clientTimeout={{clientTimeout}}
@serverTimeout={{serverTimeout}} />`);
- await settled();
- const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
+ const clientUrlRegex = new RegExp(
+ `${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`
+ );
assert.ok(
- this.server.handledRequests.filter(req => clientUrlRegex.test(req.url)).length,
+ this.server.handledRequests.filter((req) => clientUrlRegex.test(req.url))
+ .length,
'Log request was initially made directly to the client'
);
const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
assert.ok(
- this.server.handledRequests.filter(req => req.url.startsWith(serverUrl)).length,
+ this.server.handledRequests.filter((req) => req.url.startsWith(serverUrl))
+ .length,
'Log request was later made to the server'
);
- assert.ok(find('[data-test-connection-error]'), 'An error message is shown');
+ assert.ok(
+ find('[data-test-connection-error]'),
+ 'An error message is shown'
+ );
await click('[data-test-connection-error-dismiss]');
- assert.notOk(find('[data-test-connection-error]'), 'The error message is dismissable');
+ assert.notOk(
+ find('[data-test-connection-error]'),
+ 'The error message is dismissable'
+ );
await componentA11yAudit(this.element, assert);
});
- test('When the client is inaccessible, the server is accessible, and stderr is pressed before the client timeout occurs, the no connection error is not shown', async function(assert) {
+ test('When the client is inaccessible, the server is accessible, and stderr is pressed before the client timeout occurs, the no connection error is not shown', async function (assert) {
// override client response to timeout
this.server.get(
`http://${HOST}/v1/client/fs/logs/:allocation_id`,
@@ -315,49 +378,65 @@ module('Integration | Component | task log', function(hooks) {
@clientTimeout={{clientTimeout}}
@serverTimeout={{serverTimeout}} />`);
- await settled();
-
- const clientUrlRegex = new RegExp(`${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`);
- const clientRequests = this.server.handledRequests.filter(req => clientUrlRegex.test(req.url));
+ const clientUrlRegex = new RegExp(
+ `${HOST}/v1/client/fs/logs/${commonProps.allocation.id}`
+ );
+ const clientRequests = this.server.handledRequests.filter((req) =>
+ clientUrlRegex.test(req.url)
+ );
assert.ok(
- clientRequests.find(req => req.queryParams.type === 'stdout'),
+ clientRequests.find((req) => req.queryParams.type === 'stdout'),
'Client request for stdout'
);
assert.ok(
- clientRequests.find(req => req.queryParams.type === 'stderr'),
+ clientRequests.find((req) => req.queryParams.type === 'stderr'),
'Client request for stderr'
);
const serverUrl = `/v1/client/fs/logs/${commonProps.allocation.id}`;
assert.ok(
this.server.handledRequests
- .filter(req => req.url.startsWith(serverUrl))
- .find(req => req.queryParams.type === 'stderr'),
+ .filter((req) => req.url.startsWith(serverUrl))
+ .find((req) => req.queryParams.type === 'stderr'),
'Server request for stderr'
);
- assert.notOk(find('[data-test-connection-error]'), 'An error message is not shown');
+ assert.notOk(
+ find('[data-test-connection-error]'),
+ 'An error message is not shown'
+ );
});
- test('The log streaming mode is persisted in localStorage', async function(assert) {
+ test('The log streaming mode is persisted in localStorage', async function (assert) {
window.localStorage.nomadLogMode = JSON.stringify('stderr');
run.later(run, run.cancelTimers, commonProps.interval);
this.setProperties(commonProps);
- await render(hbs``);
+ await render(
+ hbs``
+ );
- await settled();
- assert.ok(this.server.handledRequests.filter(req => req.queryParams.type === 'stderr').length);
+ assert.ok(
+ this.server.handledRequests.filter(
+ (req) => req.queryParams.type === 'stderr'
+ ).length
+ );
assert.notOk(
- this.server.handledRequests.filter(req => req.queryParams.type === 'stdout').length
+ this.server.handledRequests.filter(
+ (req) => req.queryParams.type === 'stdout'
+ ).length
);
click('[data-test-log-action="stdout"]');
run.later(run, run.cancelTimers, commonProps.interval);
await settled();
- assert.ok(this.server.handledRequests.filter(req => req.queryParams.type === 'stdout').length);
+ assert.ok(
+ this.server.handledRequests.filter(
+ (req) => req.queryParams.type === 'stdout'
+ ).length
+ );
assert.equal(window.localStorage.nomadLogMode, JSON.stringify('stdout'));
});
});
diff --git a/ui/tests/integration/components/toggle-test.js b/ui/tests/integration/components/toggle-test.js
index 862b69e5e..e49238f16 100644
--- a/ui/tests/integration/components/toggle-test.js
+++ b/ui/tests/integration/components/toggle-test.js
@@ -1,4 +1,4 @@
-import { find, settled } from '@ember/test-helpers';
+import { find, render, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -9,7 +9,7 @@ import togglePageObject from 'nomad-ui/tests/pages/components/toggle';
const Toggle = create(togglePageObject());
-module('Integration | Component | toggle', function(hooks) {
+module('Integration | Component | toggle', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -28,10 +28,12 @@ module('Integration | Component | toggle', function(hooks) {
`;
- test('presents as a label with an inner checkbox and display span, and text', async function(assert) {
+ test('presents as a label with an inner checkbox and display span, and text', async function (assert) {
+ assert.expect(7);
+
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.equal(Toggle.label, props.label, `Label should be ${props.label}`);
assert.ok(Toggle.isPresent);
@@ -51,10 +53,12 @@ module('Integration | Component | toggle', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the isActive property dictates the active state and class', async function(assert) {
+ test('the isActive property dictates the active state and class', async function (assert) {
+ assert.expect(5);
+
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(Toggle.isActive);
assert.notOk(Toggle.hasActiveClass);
@@ -68,10 +72,12 @@ module('Integration | Component | toggle', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the isDisabled property dictates the disabled state and class', async function(assert) {
+ test('the isDisabled property dictates the disabled state and class', async function (assert) {
+ assert.expect(5);
+
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(Toggle.isDisabled);
assert.notOk(Toggle.hasDisabledClass);
@@ -85,10 +91,10 @@ module('Integration | Component | toggle', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('toggling the input calls the onToggle action', async function(assert) {
+ test('toggling the input calls the onToggle action', async function (assert) {
const props = commonProperties();
this.setProperties(props);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await Toggle.toggle();
assert.equal(props.onToggle.callCount, 1);
diff --git a/ui/tests/integration/components/topo-viz-test.js b/ui/tests/integration/components/topo-viz-test.js
index abc0b7a52..6b25e6752 100644
--- a/ui/tests/integration/components/topo-viz-test.js
+++ b/ui/tests/integration/components/topo-viz-test.js
@@ -1,5 +1,5 @@
import { module, test } from 'qunit';
-import { triggerEvent } from '@ember/test-helpers';
+import { render, triggerEvent } from '@ember/test-helpers';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
@@ -19,7 +19,7 @@ const alloc = (nodeId, jobId, taskGroupName, memory, cpu, props = {}) => ({
cpu,
memory,
},
- belongsTo: type => ({
+ belongsTo: (type) => ({
id: () => (type === 'job' ? jobId : nodeId),
}),
...props,
@@ -31,7 +31,7 @@ const node = (datacenter, id, memory, cpu) => ({
resources: { memory, cpu },
});
-module('Integration | Component | TopoViz', function(hooks) {
+module('Integration | Component | TopoViz', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
@@ -44,7 +44,9 @@ module('Integration | Component | TopoViz', function(hooks) {
@onDataError={{this.onDataError}} />
`;
- test('presents as a FlexMasonry of datacenters', async function(assert) {
+ test('presents as a FlexMasonry of datacenters', async function (assert) {
+ assert.expect(6);
+
this.setProperties({
nodes: [node('dc1', 'node0', 1000, 500), node('dc2', 'node1', 1000, 500)],
@@ -55,7 +57,7 @@ module('Integration | Component | TopoViz', function(hooks) {
],
});
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.equal(TopoViz.datacenters.length, 2);
assert.equal(TopoViz.datacenters[0].nodes.length, 1);
@@ -66,7 +68,7 @@ module('Integration | Component | TopoViz', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('clicking on a node in a deeply nested TopoViz::Node will toggle node selection and call @onNodeSelect', async function(assert) {
+ test('clicking on a node in a deeply nested TopoViz::Node will toggle node selection and call @onNodeSelect', async function (assert) {
this.setProperties({
// TopoViz must be dense for node selection to be a feature
nodes: Array(55)
@@ -76,7 +78,7 @@ module('Integration | Component | TopoViz', function(hooks) {
onNodeSelect: sinon.spy(),
});
- await this.render(commonTemplate);
+ await render(commonTemplate);
await TopoViz.datacenters[0].nodes[0].selectNode();
assert.ok(this.onNodeSelect.calledOnce);
@@ -87,7 +89,7 @@ module('Integration | Component | TopoViz', function(hooks) {
assert.equal(this.onNodeSelect.getCall(1).args[0], null);
});
- test('clicking on an allocation in a deeply nested TopoViz::Node will update the topology object with selections and call @onAllocationSelect and @onNodeSelect', async function(assert) {
+ test('clicking on an allocation in a deeply nested TopoViz::Node will update the topology object with selections and call @onAllocationSelect and @onNodeSelect', async function (assert) {
this.setProperties({
nodes: [node('dc1', 'node0', 1000, 500)],
allocations: [alloc('node0', 'job1', 'group', 100, 100)],
@@ -95,11 +97,14 @@ module('Integration | Component | TopoViz', function(hooks) {
onAllocationSelect: sinon.spy(),
});
- await this.render(commonTemplate);
+ await render(commonTemplate);
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
assert.ok(this.onAllocationSelect.calledOnce);
- assert.equal(this.onAllocationSelect.getCall(0).args[0], this.allocations[0]);
+ assert.equal(
+ this.onAllocationSelect.getCall(0).args[0],
+ this.allocations[0]
+ );
assert.ok(this.onNodeSelect.calledOnce);
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
@@ -109,7 +114,7 @@ module('Integration | Component | TopoViz', function(hooks) {
assert.ok(this.onNodeSelect.alwaysCalledWith(null));
});
- test('clicking on an allocation in a deeply nested TopoViz::Node will associate sibling allocations with curves', async function(assert) {
+ test('clicking on an allocation in a deeply nested TopoViz::Node will associate sibling allocations with curves', async function (assert) {
this.setProperties({
nodes: [
node('dc1', 'node0', 1000, 500),
@@ -133,27 +138,35 @@ module('Integration | Component | TopoViz', function(hooks) {
});
const selectedAllocations = this.allocations.filter(
- alloc => alloc.belongsTo('job').id() === 'job1' && alloc.taskGroupName === 'group'
+ (alloc) =>
+ alloc.belongsTo('job').id() === 'job1' &&
+ alloc.taskGroupName === 'group'
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(TopoViz.allocationAssociationsArePresent);
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
assert.ok(TopoViz.allocationAssociationsArePresent);
- assert.equal(TopoViz.allocationAssociations.length, selectedAllocations.length * 2);
+ assert.equal(
+ TopoViz.allocationAssociations.length,
+ selectedAllocations.length * 2
+ );
// Lines get redrawn when the window resizes; make sure the lines persist.
await triggerEvent(window, 'resize');
- assert.equal(TopoViz.allocationAssociations.length, selectedAllocations.length * 2);
+ assert.equal(
+ TopoViz.allocationAssociations.length,
+ selectedAllocations.length * 2
+ );
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
assert.notOk(TopoViz.allocationAssociationsArePresent);
});
- test('when the count of sibling allocations is high enough relative to the node count, curves are not rendered', async function(assert) {
+ test('when the count of sibling allocations is high enough relative to the node count, curves are not rendered', async function (assert) {
this.setProperties({
nodes: [node('dc1', 'node0', 1000, 500), node('dc1', 'node1', 1000, 500)],
allocations: [
@@ -176,7 +189,7 @@ module('Integration | Component | TopoViz', function(hooks) {
onAllocationSelect: sinon.spy(),
});
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.notOk(TopoViz.allocationAssociationsArePresent);
await TopoViz.datacenters[0].nodes[0].memoryRects[0].select();
@@ -187,7 +200,7 @@ module('Integration | Component | TopoViz', function(hooks) {
assert.equal(TopoViz.allocationAssociations.length, 0);
});
- test('when one or more nodes are missing the resources property, those nodes are filtered out of the topology view and onDataError is called', async function(assert) {
+ test('when one or more nodes are missing the resources property, those nodes are filtered out of the topology view and onDataError is called', async function (assert) {
const badNode = node('dc1', 'node0', 1000, 500);
delete badNode.resources;
@@ -205,7 +218,7 @@ module('Integration | Component | TopoViz', function(hooks) {
onDataError: sinon.spy(),
});
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(this.onDataError.calledOnce);
assert.deepEqual(this.onDataError.getCall(0).args[0], [
diff --git a/ui/tests/integration/components/topo-viz/datacenter-test.js b/ui/tests/integration/components/topo-viz/datacenter-test.js
index 25e7c3b8f..1d6d81119 100644
--- a/ui/tests/integration/components/topo-viz/datacenter-test.js
+++ b/ui/tests/integration/components/topo-viz/datacenter-test.js
@@ -1,4 +1,4 @@
-import { find } from '@ember/test-helpers';
+import { find, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -17,7 +17,7 @@ const nodeGen = (name, datacenter, memory, cpu, allocations = []) => ({
memory,
cpu,
node: { name },
- allocations: allocations.map(alloc => ({
+ allocations: allocations.map((alloc) => ({
memory: alloc.memory,
cpu: alloc.cpu,
memoryPercent: alloc.memory / memory,
@@ -30,13 +30,13 @@ const nodeGen = (name, datacenter, memory, cpu, allocations = []) => ({
});
// Used in Array#reduce to sum by a property common to an array of objects
-const sumBy = prop => (sum, obj) => (sum += obj[prop]);
+const sumBy = (prop) => (sum, obj) => (sum += obj[prop]);
-module('Integration | Component | TopoViz::Datacenter', function(hooks) {
+module('Integration | Component | TopoViz::Datacenter', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
- const commonProps = props => ({
+ const commonProps = (props) => ({
isSingleColumn: true,
isDense: false,
heightScale: () => 50,
@@ -55,7 +55,9 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
@onNodeSelect={{this.onNodeSelect}} />
`;
- test('presents as a div with a label and a FlexMasonry with a collection of nodes', async function(assert) {
+ test('presents as a div with a label and a FlexMasonry with a collection of nodes', async function (assert) {
+ assert.expect(3);
+
this.setProperties(
commonProps({
datacenter: {
@@ -65,7 +67,7 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizDatacenter.isPresent);
assert.equal(TopoVizDatacenter.nodes.length, this.datacenter.nodes.length);
@@ -73,7 +75,7 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('datacenter stats are an aggregate of node stats', async function(assert) {
+ test('datacenter stats are an aggregate of node stats', async function (assert) {
this.setProperties(
commonProps({
datacenter: {
@@ -94,7 +96,7 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
const allocs = this.datacenter.nodes.reduce(
(allocs, node) => allocs.concat(node.allocations),
@@ -106,11 +108,16 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
const cpuTotal = this.datacenter.nodes.reduce(sumBy('cpu'), 0);
assert.ok(TopoVizDatacenter.label.includes(this.datacenter.name));
- assert.ok(TopoVizDatacenter.label.includes(`${this.datacenter.nodes.length} Nodes`));
+ assert.ok(
+ TopoVizDatacenter.label.includes(`${this.datacenter.nodes.length} Nodes`)
+ );
assert.ok(TopoVizDatacenter.label.includes(`${allocs.length} Allocs`));
assert.ok(
TopoVizDatacenter.label.includes(
- `${formatBytes(memoryReserved, 'MiB')}/${formatBytes(memoryTotal, 'MiB')}`
+ `${formatBytes(memoryReserved, 'MiB')}/${formatBytes(
+ memoryTotal,
+ 'MiB'
+ )}`
)
);
assert.ok(
@@ -120,18 +127,21 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
);
});
- test('when @isSingleColumn is true, the FlexMasonry layout gets one column, otherwise it gets two', async function(assert) {
+ test('when @isSingleColumn is true, the FlexMasonry layout gets one column, otherwise it gets two', async function (assert) {
this.setProperties(
commonProps({
isSingleColumn: true,
datacenter: {
name: 'dc1',
- nodes: [nodeGen('node-1', 'dc1', 1000, 500), nodeGen('node-2', 'dc1', 1000, 500)],
+ nodes: [
+ nodeGen('node-1', 'dc1', 1000, 500),
+ nodeGen('node-2', 'dc1', 1000, 500),
+ ],
},
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-1'));
@@ -139,7 +149,9 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
assert.ok(find('[data-test-flex-masonry].flex-masonry-columns-2'));
});
- test('args get passed down to the TopViz::Node children', async function(assert) {
+ test('args get passed down to the TopViz::Node children', async function (assert) {
+ assert.expect(4);
+
const heightSpy = sinon.spy();
this.setProperties(
commonProps({
@@ -150,14 +162,16 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
},
datacenter: {
name: 'dc1',
- nodes: [nodeGen('node-1', 'dc1', 1000, 500, [{ memory: 100, cpu: 300 }])],
+ nodes: [
+ nodeGen('node-1', 'dc1', 1000, 500, [{ memory: 100, cpu: 300 }]),
+ ],
},
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
- TopoVizDatacenter.nodes[0].as(async TopoVizNode => {
+ TopoVizDatacenter.nodes[0].as(async (TopoVizNode) => {
assert.notOk(TopoVizNode.labelIsPresent);
assert.ok(heightSpy.calledWith(this.datacenter.nodes[0].memory));
@@ -165,7 +179,11 @@ module('Integration | Component | TopoViz::Datacenter', function(hooks) {
assert.ok(this.onNodeSelect.calledWith(this.datacenter.nodes[0]));
await TopoVizNode.memoryRects[0].select();
- assert.ok(this.onAllocationSelect.calledWith(this.datacenter.nodes[0].allocations[0]));
+ assert.ok(
+ this.onAllocationSelect.calledWith(
+ this.datacenter.nodes[0].allocations[0]
+ )
+ );
});
});
});
diff --git a/ui/tests/integration/components/topo-viz/node-test.js b/ui/tests/integration/components/topo-viz/node-test.js
index a85df060d..54588002d 100644
--- a/ui/tests/integration/components/topo-viz/node-test.js
+++ b/ui/tests/integration/components/topo-viz/node-test.js
@@ -1,4 +1,4 @@
-import { findAll } from '@ember/test-helpers';
+import { findAll, render } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
@@ -8,7 +8,10 @@ import faker from 'nomad-ui/mirage/faker';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import { setupMirage } from 'ember-cli-mirage/test-support';
import topoVisNodePageObject from 'nomad-ui/tests/pages/components/topo-viz/node';
-import { formatScheduledBytes, formatScheduledHertz } from 'nomad-ui/utils/units';
+import {
+ formatScheduledBytes,
+ formatScheduledHertz,
+} from 'nomad-ui/utils/units';
const TopoVizNode = create(topoVisNodePageObject());
@@ -36,7 +39,7 @@ const allocGen = (node, memory, cpu, isScheduled = true) => ({
},
});
-const props = overrides => ({
+const props = (overrides) => ({
isDense: false,
heightScale: () => 50,
onAllocationSelect: sinon.spy(),
@@ -46,7 +49,7 @@ const props = overrides => ({
...overrides,
});
-module('Integration | Component | TopoViz::Node', function(hooks) {
+module('Integration | Component | TopoViz::Node', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
@@ -61,7 +64,9 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
@onNodeSelect={{this.onNodeSelect}} />
`;
- test('presents as a div with a label and an svg with CPU and memory rows', async function(assert) {
+ test('presents as a div with a label and an svg with CPU and memory rows', async function (assert) {
+ assert.expect(4);
+
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -76,7 +81,7 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizNode.isPresent);
assert.equal(
@@ -88,7 +93,7 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('the label contains aggregate information about the node', async function(assert) {
+ test('the label contains aggregate information about the node', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -103,19 +108,29 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizNode.label.includes(node.node.name));
assert.ok(
TopoVizNode.label.includes(
- `${this.node.allocations.filterBy('allocation.isScheduled').length} Allocs`
+ `${
+ this.node.allocations.filterBy('allocation.isScheduled').length
+ } Allocs`
+ )
+ );
+ assert.ok(
+ TopoVizNode.label.includes(
+ `${formatScheduledBytes(this.node.memory, 'MiB')}`
+ )
+ );
+ assert.ok(
+ TopoVizNode.label.includes(
+ `${formatScheduledHertz(this.node.cpu, 'MHz')}`
)
);
- assert.ok(TopoVizNode.label.includes(`${formatScheduledBytes(this.node.memory, 'MiB')}`));
- assert.ok(TopoVizNode.label.includes(`${formatScheduledHertz(this.node.cpu, 'MHz')}`));
});
- test('the status icon indicates when the node is draining', async function(assert) {
+ test('the status icon indicates when the node is draining', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000, { isDraining: true });
this.setProperties(
props({
@@ -126,13 +141,13 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizNode.statusIcon.includes('icon-is-clock-outline'));
assert.equal(TopoVizNode.statusIconLabel, 'Client is draining');
});
- test('the status icon indicates when the node is ineligible for scheduling', async function(assert) {
+ test('the status icon indicates when the node is ineligible for scheduling', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000, { isEligible: false });
this.setProperties(
props({
@@ -143,13 +158,13 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizNode.statusIcon.includes('icon-is-lock-closed'));
assert.equal(TopoVizNode.statusIconLabel, 'Client is ineligible');
});
- test('when isDense is false, clicking the node does nothing', async function(assert) {
+ test('when isDense is false, clicking the node does nothing', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -161,14 +176,14 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await TopoVizNode.selectNode();
assert.notOk(TopoVizNode.nodeIsInteractive);
assert.notOk(this.onNodeSelect.called);
});
- test('when isDense is true, clicking the node calls onNodeSelect', async function(assert) {
+ test('when isDense is true, clicking the node calls onNodeSelect', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -180,7 +195,7 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
await TopoVizNode.selectNode();
assert.ok(TopoVizNode.nodeIsInteractive);
@@ -188,7 +203,7 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
assert.ok(this.onNodeSelect.calledWith(this.node));
});
- test('the node gets the is-selected class when the node is selected', async function(assert) {
+ test('the node gets the is-selected class when the node is selected', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000, { isSelected: true });
this.setProperties(
props({
@@ -200,12 +215,12 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(TopoVizNode.nodeIsSelected);
});
- test('the node gets its height form the @heightScale arg', async function(assert) {
+ test('the node gets its height form the @heightScale arg', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000);
const height = 50;
const heightSpy = sinon.spy();
@@ -222,14 +237,14 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.ok(heightSpy.called);
assert.ok(heightSpy.calledWith(this.node.memory));
assert.equal(TopoVizNode.memoryRects[0].height, `${height}px`);
});
- test('each allocation gets a memory rect and a cpu rect', async function(assert) {
+ test('each allocation gets a memory rect and a cpu rect', async function (assert) {
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -240,13 +255,15 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(commonTemplate);
+ await render(commonTemplate);
assert.equal(TopoVizNode.memoryRects.length, this.node.allocations.length);
assert.equal(TopoVizNode.cpuRects.length, this.node.allocations.length);
});
- test('each allocation is sized according to its percentage of utilization', async function(assert) {
+ test('each allocation is sized according to its percentage of utilization', async function (assert) {
+ assert.expect(4);
+
const node = nodeGen('Node One', 'dc1', 1000, 1000);
this.setProperties(
props({
@@ -257,7 +274,7 @@ module('Integration | Component | TopoViz::Node', function(hooks) {
})
);
- await this.render(hbs`
+ await render(hbs`
this.set('name', 'Zoey'));
await render(hbs`
@@ -17,16 +17,21 @@ module('Integration | Component | trigger', function(hooks) {
`);
- assert.dom('[data-test-name]').hasText('Tomster', 'Initial state renders correctly.');
+ assert
+ .dom('[data-test-name]')
+ .hasText('Tomster', 'Initial state renders correctly.');
await click('[data-test-button]');
assert
.dom('[data-test-name]')
- .hasText('Zoey', 'The name property changes when the button is clicked');
+ .hasText(
+ 'Zoey',
+ 'The name property changes when the button is clicked'
+ );
});
- test('it sets the result of the action', async function(assert) {
+ test('it sets the result of the action', async function (assert) {
this.set('tomster', () => 'Tomster');
await render(hbs`
@@ -38,22 +43,27 @@ module('Integration | Component | trigger', function(hooks) {
`);
assert
.dom('[data-test-name]')
- .doesNotExist('Initial state does not render because there is no result yet.');
+ .doesNotExist(
+ 'Initial state does not render because there is no result yet.'
+ );
await click('[data-test-button]');
assert
.dom('[data-test-name]')
- .hasText('Tomster', 'The result state updates after the triggered action');
+ .hasText(
+ 'Tomster',
+ 'The result state updates after the triggered action'
+ );
});
});
- module('Asynchronous Interactions', function() {
- test('it can trigger an asynchronous action', async function(assert) {
+ module('Asynchronous Interactions', function () {
+ test('it can trigger an asynchronous action', async function (assert) {
this.set(
'onTrigger',
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
this.set('resolve', resolve);
})
);
@@ -72,15 +82,21 @@ module('Integration | Component | trigger', function(hooks) {
assert
.dom('[data-test-div]')
- .doesNotExist('The div does not render until after the action dispatches successfully');
+ .doesNotExist(
+ 'The div does not render until after the action dispatches successfully'
+ );
await click('[data-test-button]');
assert
.dom('[data-test-div-loading]')
- .exists('Loading state is displayed when the action hasnt resolved yet');
+ .exists(
+ 'Loading state is displayed when the action hasnt resolved yet'
+ );
assert
.dom('[data-test-div]')
- .doesNotExist('Success message does not display until after promise resolves');
+ .doesNotExist(
+ 'Success message does not display until after promise resolves'
+ );
this.resolve();
await waitFor('[data-test-div]');
@@ -91,15 +107,21 @@ module('Integration | Component | trigger', function(hooks) {
);
assert
.dom('[data-test-div]')
- .exists('Action has dispatched successfully after the promise resolves');
+ .exists(
+ 'Action has dispatched successfully after the promise resolves'
+ );
await click('[data-test-button]');
assert
.dom('[data-test-div]')
- .doesNotExist('Aftering clicking the button, again, the state is reset');
+ .doesNotExist(
+ 'Aftering clicking the button, again, the state is reset'
+ );
assert
.dom('[data-test-div-loading]')
- .exists('After clicking the button, again, we are back in the loading state');
+ .exists(
+ 'After clicking the button, again, we are back in the loading state'
+ );
this.resolve();
await waitFor('[data-test-div]');
@@ -111,11 +133,11 @@ module('Integration | Component | trigger', function(hooks) {
);
});
- test('it handles the success state', async function(assert) {
+ test('it handles the success state', async function (assert) {
this.set(
'onTrigger',
() =>
- new Promise(resolve => {
+ new Promise((resolve) => {
this.set('resolve', resolve);
})
);
@@ -132,14 +154,16 @@ module('Integration | Component | trigger', function(hooks) {
assert
.dom('[data-test-div]')
- .doesNotExist('No text should appear until after the onSuccess callback is fired');
+ .doesNotExist(
+ 'No text should appear until after the onSuccess callback is fired'
+ );
await click('[data-test-button]');
this.resolve();
await waitFor('[data-test-div]');
assert.verifySteps(['On success happened']);
});
- test('it handles the error state', async function(assert) {
+ test('it handles the error state', async function (assert) {
this.set(
'onTrigger',
() =>
@@ -166,11 +190,15 @@ module('Integration | Component | trigger', function(hooks) {
await click('[data-test-button]');
assert
.dom('[data-test-div-loading]')
- .exists('Loading state is displayed when the action hasnt resolved yet');
+ .exists(
+ 'Loading state is displayed when the action hasnt resolved yet'
+ );
assert
.dom('[data-test-div]')
- .doesNotExist('No text should appear until after the onError callback is fired');
+ .doesNotExist(
+ 'No text should appear until after the onError callback is fired'
+ );
this.reject();
await waitFor('[data-test-span]');
@@ -180,7 +208,9 @@ module('Integration | Component | trigger', function(hooks) {
assert
.dom('[data-test-div-loading]')
- .exists('The previous error state was cleared and we show loading, again.');
+ .exists(
+ 'The previous error state was cleared and we show loading, again.'
+ );
assert.dom('[data-test-div]').doesNotExist('The error state is cleared');
diff --git a/ui/tests/integration/components/two-step-button-test.js b/ui/tests/integration/components/two-step-button-test.js
index 4dd9be00f..3ef1be602 100644
--- a/ui/tests/integration/components/two-step-button-test.js
+++ b/ui/tests/integration/components/two-step-button-test.js
@@ -9,7 +9,7 @@ import twoStepButton from 'nomad-ui/tests/pages/components/two-step-button';
const TwoStepButton = create(twoStepButton());
-module('Integration | Component | two step button', function(hooks) {
+module('Integration | Component | two step button', function (hooks) {
setupRenderingTest(hooks);
const commonProperties = () => ({
@@ -35,22 +35,33 @@ module('Integration | Component | two step button', function(hooks) {
@onCancel={{onCancel}} />
`;
- test('presents as a button in the idle state', async function(assert) {
+ test('presents as a button in the idle state', async function (assert) {
+ assert.expect(6);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
assert.ok(find('[data-test-idle-button]'), 'Idle button is rendered');
- assert.equal(TwoStepButton.idleText, props.idleText, 'Button is labeled correctly');
+ assert.equal(
+ TwoStepButton.idleText,
+ props.idleText,
+ 'Button is labeled correctly'
+ );
assert.notOk(find('[data-test-cancel-button]'), 'No cancel button yet');
assert.notOk(find('[data-test-confirm-button]'), 'No confirm button yet');
- assert.notOk(find('[data-test-confirmation-message]'), 'No confirmation message yet');
+ assert.notOk(
+ find('[data-test-confirmation-message]'),
+ 'No confirmation message yet'
+ );
await componentA11yAudit(this.element, assert);
});
- test('clicking the idle state button transitions into the promptForConfirmation state', async function(assert) {
+ test('clicking the idle state button transitions into the promptForConfirmation state', async function (assert) {
+ assert.expect(7);
+
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -58,10 +69,18 @@ module('Integration | Component | two step button', function(hooks) {
await TwoStepButton.idle();
assert.ok(find('[data-test-cancel-button]'), 'Cancel button is rendered');
- assert.equal(TwoStepButton.cancelText, props.cancelText, 'Button is labeled correctly');
+ assert.equal(
+ TwoStepButton.cancelText,
+ props.cancelText,
+ 'Button is labeled correctly'
+ );
assert.ok(find('[data-test-confirm-button]'), 'Confirm button is rendered');
- assert.equal(TwoStepButton.confirmText, props.confirmText, 'Button is labeled correctly');
+ assert.equal(
+ TwoStepButton.confirmText,
+ props.confirmText,
+ 'Button is labeled correctly'
+ );
assert.equal(
TwoStepButton.confirmationMessage,
@@ -73,7 +92,7 @@ module('Integration | Component | two step button', function(hooks) {
await componentA11yAudit(this.element, assert);
});
- test('canceling in the promptForConfirmation state calls the onCancel hook and resets to the idle state', async function(assert) {
+ test('canceling in the promptForConfirmation state calls the onCancel hook and resets to the idle state', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -86,7 +105,7 @@ module('Integration | Component | two step button', function(hooks) {
assert.ok(find('[data-test-idle-button]'), 'Idle button is back');
});
- test('confirming the promptForConfirmation state calls the onConfirm hook and resets to the idle state', async function(assert) {
+ test('confirming the promptForConfirmation state calls the onConfirm hook and resets to the idle state', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -99,7 +118,9 @@ module('Integration | Component | two step button', function(hooks) {
assert.ok(find('[data-test-idle-button]'), 'Idle button is back');
});
- test('when awaitingConfirmation is true, the cancel and submit buttons are disabled and the submit button is loading', async function(assert) {
+ test('when awaitingConfirmation is true, the cancel and submit buttons are disabled and the submit button is loading', async function (assert) {
+ assert.expect(4);
+
const props = commonProperties();
props.awaitingConfirmation = true;
this.setProperties(props);
@@ -108,13 +129,19 @@ module('Integration | Component | two step button', function(hooks) {
await TwoStepButton.idle();
assert.ok(TwoStepButton.cancelIsDisabled, 'The cancel button is disabled');
- assert.ok(TwoStepButton.confirmIsDisabled, 'The confirm button is disabled');
- assert.ok(TwoStepButton.isRunning, 'The confirm button is in a loading state');
+ assert.ok(
+ TwoStepButton.confirmIsDisabled,
+ 'The confirm button is disabled'
+ );
+ assert.ok(
+ TwoStepButton.isRunning,
+ 'The confirm button is in a loading state'
+ );
await componentA11yAudit(this.element, assert);
});
- test('when in the prompt state, clicking outside will reset state back to idle', async function(assert) {
+ test('when in the prompt state, clicking outside will reset state back to idle', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -128,7 +155,7 @@ module('Integration | Component | two step button', function(hooks) {
assert.ok(find('[data-test-idle-button]'), 'Back in the idle state');
});
- test('when in the prompt state, clicking inside will not reset state back to idle', async function(assert) {
+ test('when in the prompt state, clicking inside will not reset state back to idle', async function (assert) {
const props = commonProperties();
this.setProperties(props);
await render(commonTemplate);
@@ -142,7 +169,7 @@ module('Integration | Component | two step button', function(hooks) {
assert.notOk(find('[data-test-idle-button]'), 'Still in the prompt state');
});
- test('when awaitingConfirmation is true, clicking outside does nothing', async function(assert) {
+ test('when awaitingConfirmation is true, clicking outside does nothing', async function (assert) {
const props = commonProperties();
props.awaitingConfirmation = true;
this.setProperties(props);
@@ -157,7 +184,9 @@ module('Integration | Component | two step button', function(hooks) {
assert.notOk(find('[data-test-idle-button]'), 'Still in the prompt state');
});
- test('when disabled is true, the idle button is disabled', async function(assert) {
+ test('when disabled is true, the idle button is disabled', async function (assert) {
+ assert.expect(3);
+
const props = commonProperties();
props.disabled = true;
this.setProperties(props);
@@ -166,7 +195,10 @@ module('Integration | Component | two step button', function(hooks) {
assert.ok(TwoStepButton.isDisabled, 'The idle button is disabled');
await TwoStepButton.idle();
- assert.ok(find('[data-test-idle-button]'), 'Still in the idle state after clicking');
+ assert.ok(
+ find('[data-test-idle-button]'),
+ 'Still in the idle state after clicking'
+ );
await componentA11yAudit(this.element, assert);
});
diff --git a/ui/tests/integration/util/exec-command-editor-xterm-adapter-test.js b/ui/tests/integration/util/exec-command-editor-xterm-adapter-test.js
index d895cc41a..1c1328298 100644
--- a/ui/tests/integration/util/exec-command-editor-xterm-adapter-test.js
+++ b/ui/tests/integration/util/exec-command-editor-xterm-adapter-test.js
@@ -6,132 +6,132 @@ import hbs from 'htmlbars-inline-precompile';
import { Terminal } from 'xterm';
import KEYS from 'nomad-ui/utils/keys';
-module('Integration | Utility | exec-command-editor-xterm-adapter', function(hooks) {
- setupRenderingTest(hooks);
+module(
+ 'Integration | Utility | exec-command-editor-xterm-adapter',
+ function (hooks) {
+ setupRenderingTest(hooks);
- test('it can wrap to a previous line while backspacing', async function(assert) {
- let done = assert.async();
+ test('it can wrap to a previous line while backspacing', async function (assert) {
+ assert.expect(2);
- await render(hbs`
+ let done = assert.async();
+
+ await render(hbs`
`);
- let terminal = new Terminal({ cols: 10 });
- terminal.open(document.getElementById('terminal'));
+ let terminal = new Terminal({ cols: 10 });
+ terminal.open(document.getElementById('terminal'));
- terminal.write('/bin/long-command');
+ terminal.write('/bin/long-command');
- new ExecCommandEditorXtermAdapter(
- terminal,
- command => {
- assert.equal(command, '/bin/long');
- done();
- },
- '/bin/long-command'
- );
+ new ExecCommandEditorXtermAdapter(
+ terminal,
+ (command) => {
+ assert.equal(command, '/bin/long');
+ done();
+ },
+ '/bin/long-command'
+ );
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
+ await terminal.simulateCommandDataEvent(KEYS.DELETE);
- await settled();
+ await settled();
- assert.equal(
- terminal.buffer.active
- .getLine(0)
- .translateToString()
- .trim(),
- '/bin/long'
- );
+ assert.equal(
+ terminal.buffer.active.getLine(0).translateToString().trim(),
+ '/bin/long'
+ );
- await terminal.simulateCommandDataEvent(KEYS.ENTER);
- });
+ await terminal.simulateCommandDataEvent(KEYS.ENTER);
+ });
- test('it ignores arrow keys and unprintable characters other than ^U', async function(assert) {
- let done = assert.async();
+ test('it ignores arrow keys and unprintable characters other than ^U', async function (assert) {
+ assert.expect(4);
- await render(hbs`
+ let done = assert.async();
+
+ await render(hbs`
`);
- let terminal = new Terminal({ cols: 72 });
- terminal.open(document.getElementById('terminal'));
+ let terminal = new Terminal({ cols: 72 });
+ terminal.open(document.getElementById('terminal'));
- terminal.write('/bin/bash');
+ terminal.write('/bin/bash');
- new ExecCommandEditorXtermAdapter(
- terminal,
- command => {
- assert.equal(command, '/bin/bash!');
- done();
- },
- '/bin/bash'
- );
+ new ExecCommandEditorXtermAdapter(
+ terminal,
+ (command) => {
+ assert.equal(command, '/bin/bash!');
+ done();
+ },
+ '/bin/bash'
+ );
- await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.LEFT_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.DOWN_ARROW);
- await terminal.simulateCommandDataEvent(KEYS.CONTROL_A);
- await terminal.simulateCommandDataEvent('!');
+ await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.LEFT_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.DOWN_ARROW);
+ await terminal.simulateCommandDataEvent(KEYS.CONTROL_A);
+ await terminal.simulateCommandDataEvent('!');
- await settled();
+ await settled();
- assert.equal(terminal.buffer.active.cursorY, 0);
- assert.equal(terminal.buffer.active.cursorX, 10);
+ assert.equal(terminal.buffer.active.cursorY, 0);
+ assert.equal(terminal.buffer.active.cursorX, 10);
- assert.equal(
- terminal.buffer.active
- .getLine(0)
- .translateToString()
- .trim(),
- '/bin/bash!'
- );
+ assert.equal(
+ terminal.buffer.active.getLine(0).translateToString().trim(),
+ '/bin/bash!'
+ );
- await terminal.simulateCommandDataEvent(KEYS.ENTER);
- });
+ await terminal.simulateCommandDataEvent(KEYS.ENTER);
+ });
- test('it supports typing ^U to delete the entire command', async function(assert) {
- let done = assert.async();
+ test('it supports typing ^U to delete the entire command', async function (assert) {
+ assert.expect(2);
- await render(hbs`
+ let done = assert.async();
+
+ await render(hbs`
`);
- let terminal = new Terminal({ cols: 10 });
- terminal.open(document.getElementById('terminal'));
+ let terminal = new Terminal({ cols: 10 });
+ terminal.open(document.getElementById('terminal'));
- terminal.write('to-delete');
+ terminal.write('to-delete');
- new ExecCommandEditorXtermAdapter(
- terminal,
- command => {
- assert.equal(command, '!');
- done();
- },
- 'to-delete'
- );
+ new ExecCommandEditorXtermAdapter(
+ terminal,
+ (command) => {
+ assert.equal(command, '!');
+ done();
+ },
+ 'to-delete'
+ );
- await terminal.simulateCommandDataEvent(KEYS.CONTROL_U);
+ await terminal.simulateCommandDataEvent(KEYS.CONTROL_U);
- await settled();
+ await settled();
- assert.equal(
- terminal.buffer.active
- .getLine(0)
- .translateToString()
- .trim(),
- ''
- );
+ assert.equal(
+ terminal.buffer.active.getLine(0).translateToString().trim(),
+ ''
+ );
- await terminal.simulateCommandDataEvent('!');
- await terminal.simulateCommandDataEvent(KEYS.ENTER);
- });
-});
+ await terminal.simulateCommandDataEvent('!');
+ await terminal.simulateCommandDataEvent(KEYS.ENTER);
+ });
+ }
+);
diff --git a/ui/tests/integration/util/exec-socket-xterm-adapter-test.js b/ui/tests/integration/util/exec-socket-xterm-adapter-test.js
index d6b78b109..49cdd9b00 100644
--- a/ui/tests/integration/util/exec-socket-xterm-adapter-test.js
+++ b/ui/tests/integration/util/exec-socket-xterm-adapter-test.js
@@ -1,3 +1,4 @@
+/* eslint-disable qunit/no-conditional-assertions */
import ExecSocketXtermAdapter from 'nomad-ui/utils/classes/exec-socket-xterm-adapter';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';
@@ -7,10 +8,12 @@ import { Terminal } from 'xterm';
import { HEARTBEAT_INTERVAL } from 'nomad-ui/utils/classes/exec-socket-xterm-adapter';
import sinon from 'sinon';
-module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
+module('Integration | Utility | exec-socket-xterm-adapter', function (hooks) {
setupRenderingTest(hooks);
- test('initiating socket sends authentication handshake', async function(assert) {
+ test('initiating socket sends authentication handshake', async function (assert) {
+ assert.expect(1);
+
let done = assert.async();
let terminal = new Terminal();
@@ -20,14 +23,15 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let firstMessage = true;
let mockSocket = new Object({
send(message) {
if (firstMessage) {
firstMessage = false;
- assert.deepEqual(message, JSON.stringify({ version: 1, auth_token: 'mysecrettoken' }));
+ assert.deepEqual(
+ message,
+ JSON.stringify({ version: 1, auth_token: 'mysecrettoken' })
+ );
mockSocket.onclose();
done();
}
@@ -41,7 +45,9 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
await settled();
});
- test('initiating socket sends authentication handshake even if unauthenticated', async function(assert) {
+ test('initiating socket sends authentication handshake even if unauthenticated', async function (assert) {
+ assert.expect(1);
+
let done = assert.async();
let terminal = new Terminal();
@@ -51,14 +57,15 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let firstMessage = true;
let mockSocket = new Object({
send(message) {
if (firstMessage) {
firstMessage = false;
- assert.deepEqual(message, JSON.stringify({ version: 1, auth_token: '' }));
+ assert.deepEqual(
+ message,
+ JSON.stringify({ version: 1, auth_token: '' })
+ );
mockSocket.onclose();
done();
}
@@ -72,7 +79,9 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
await settled();
});
- test('a heartbeat is sent periodically', async function(assert) {
+ test('a heartbeat is sent periodically', async function (assert) {
+ assert.expect(1);
+
let done = assert.async();
const clock = sinon.useFakeTimers({
@@ -87,8 +96,6 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let mockSocket = new Object({
send(message) {
if (!message.includes('version') && !message.includes('tty_size')) {
@@ -106,7 +113,9 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
clock.tick(HEARTBEAT_INTERVAL);
});
- test('resizing the window passes a resize message through the socket', async function(assert) {
+ test('resizing the window passes a resize message through the socket', async function (assert) {
+ assert.expect(1);
+
let done = assert.async();
let terminal = new Terminal();
@@ -116,13 +125,13 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let mockSocket = new Object({
send(message) {
assert.deepEqual(
message,
- JSON.stringify({ tty_size: { width: terminal.cols, height: terminal.rows } })
+ JSON.stringify({
+ tty_size: { width: terminal.cols, height: terminal.rows },
+ })
);
mockSocket.onclose();
done();
@@ -136,7 +145,7 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
await settled();
});
- test('stdout frames without data are ignored', async function(assert) {
+ test('stdout frames without data are ignored', async function (assert) {
assert.expect(0);
let terminal = new Terminal();
@@ -146,8 +155,6 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let mockSocket = new Object({
send() {},
});
@@ -162,7 +169,7 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
mockSocket.onclose();
});
- test('stderr frames are ignored', async function(assert) {
+ test('stderr frames are ignored', async function (assert) {
let terminal = new Terminal();
this.set('terminal', terminal);
@@ -170,8 +177,6 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
`);
- await settled();
-
let mockSocket = new Object({
send() {},
});
@@ -189,10 +194,7 @@ module('Integration | Utility | exec-socket-xterm-adapter', function(hooks) {
await settled();
assert.equal(
- terminal.buffer.active
- .getLine(0)
- .translateToString()
- .trim(),
+ terminal.buffer.active.getLine(0).translateToString().trim(),
'sh-3.2 🥳$'
);
diff --git a/ui/tests/pages/allocations/detail.js b/ui/tests/pages/allocations/detail.js
index b08b90eb8..cabc44672 100644
--- a/ui/tests/pages/allocations/detail.js
+++ b/ui/tests/pages/allocations/detail.js
@@ -81,7 +81,10 @@ export default create({
},
preempted: isPresent('[data-test-preemptions]'),
- ...allocations('[data-test-preemptions] [data-test-allocation]', 'preemptions'),
+ ...allocations(
+ '[data-test-preemptions] [data-test-allocation]',
+ 'preemptions'
+ ),
ports: collection('[data-test-allocation-port]', {
name: text('[data-test-allocation-port-name]'),
diff --git a/ui/tests/pages/allocations/fs.js b/ui/tests/pages/allocations/fs.js
index fbfc8f9a7..c5cf4d549 100644
--- a/ui/tests/pages/allocations/fs.js
+++ b/ui/tests/pages/allocations/fs.js
@@ -34,10 +34,7 @@ export default create({
}),
sortBy(id) {
- return this.sortOptions
- .toArray()
- .findBy('id', id)
- .sort();
+ return this.sortOptions.toArray().findBy('id', id).sort();
},
directoryEntries: collection('[data-test-entry]', {
diff --git a/ui/tests/pages/clients/detail.js b/ui/tests/pages/clients/detail.js
index bcfe0d2de..366e1242d 100644
--- a/ui/tests/pages/clients/detail.js
+++ b/ui/tests/pages/clients/detail.js
@@ -28,7 +28,10 @@ export default create({
}),
statusDefinition: text('[data-test-status-definition]'),
- statusDecorationClass: attribute('class', '[data-test-status-definition] .status-text'),
+ statusDecorationClass: attribute(
+ 'class',
+ '[data-test-status-definition] .status-text'
+ ),
addressDefinition: text('[data-test-address-definition]'),
datacenterDefinition: text('[data-test-datacenter-definition]'),
@@ -62,10 +65,13 @@ export default create({
metaTable: isPresent('[data-test-meta]'),
emptyMetaMessage: isPresent('[data-test-empty-meta-message]'),
- metaAttributes: collection('[data-test-meta] [data-test-attributes-section]', {
- key: text('[data-test-key]'),
- value: text('[data-test-value]'),
- }),
+ metaAttributes: collection(
+ '[data-test-meta] [data-test-attributes-section]',
+ {
+ key: text('[data-test-key]'),
+ value: text('[data-test-value]'),
+ }
+ ),
error: {
isShown: isPresent('[data-test-error]'),
@@ -88,22 +94,28 @@ export default create({
permissions: text('[data-test-permissions]'),
}),
- driverHeads: collection('[data-test-driver-status] [data-test-accordion-head]', {
- name: text('[data-test-name]'),
- detected: text('[data-test-detected]'),
- lastUpdated: text('[data-test-last-updated]'),
- healthIsShown: isPresent('[data-test-health]'),
- health: text('[data-test-health]'),
- healthClass: attribute('class', '[data-test-health] .color-swatch'),
+ driverHeads: collection(
+ '[data-test-driver-status] [data-test-accordion-head]',
+ {
+ name: text('[data-test-name]'),
+ detected: text('[data-test-detected]'),
+ lastUpdated: text('[data-test-last-updated]'),
+ healthIsShown: isPresent('[data-test-health]'),
+ health: text('[data-test-health]'),
+ healthClass: attribute('class', '[data-test-health] .color-swatch'),
- toggle: clickable('[data-test-accordion-toggle]'),
- }),
+ toggle: clickable('[data-test-accordion-toggle]'),
+ }
+ ),
- driverBodies: collection('[data-test-driver-status] [data-test-accordion-body]', {
- description: text('[data-test-health-description]'),
- descriptionIsShown: isPresent('[data-test-health-description]'),
- attributesAreShown: isPresent('[data-test-driver-attributes]'),
- }),
+ driverBodies: collection(
+ '[data-test-driver-status] [data-test-accordion-body]',
+ {
+ description: text('[data-test-health-description]'),
+ descriptionIsShown: isPresent('[data-test-health-description]'),
+ attributesAreShown: isPresent('[data-test-driver-attributes]'),
+ }
+ ),
drainDetails: {
scope: '[data-test-drain-details]',
@@ -151,10 +163,7 @@ export default create({
setDeadline(label) {
this.deadlineOptions.open();
- this.deadlineOptions.options
- .toArray()
- .findBy('label', label)
- .choose();
+ this.deadlineOptions.options.toArray().findBy('label', label).choose();
},
},
@@ -166,7 +175,13 @@ export default create({
eligibilityError: notification('[data-test-eligibility-error]'),
stopDrainError: notification('[data-test-stop-drain-error]'),
drainError: notification('[data-test-drain-error]'),
- drainStoppedNotification: notification('[data-test-drain-stopped-notification]'),
- drainUpdatedNotification: notification('[data-test-drain-updated-notification]'),
- drainCompleteNotification: notification('[data-test-drain-complete-notification]'),
+ drainStoppedNotification: notification(
+ '[data-test-drain-stopped-notification]'
+ ),
+ drainUpdatedNotification: notification(
+ '[data-test-drain-updated-notification]'
+ ),
+ drainCompleteNotification: notification(
+ '[data-test-drain-complete-notification]'
+ ),
});
diff --git a/ui/tests/pages/clients/list.js b/ui/tests/pages/clients/list.js
index f00c36a28..57af923d6 100644
--- a/ui/tests/pages/clients/list.js
+++ b/ui/tests/pages/clients/list.js
@@ -27,10 +27,7 @@ export default create({
}),
sortBy(id) {
- return this.sortOptions
- .toArray()
- .findBy('id', id)
- .sort();
+ return this.sortOptions.toArray().findBy('id', id).sort();
},
nodes: collection('[data-test-client-node-row]', {
diff --git a/ui/tests/pages/clients/monitor.js b/ui/tests/pages/clients/monitor.js
index 4ec32bef8..828fd84e3 100644
--- a/ui/tests/pages/clients/monitor.js
+++ b/ui/tests/pages/clients/monitor.js
@@ -1,6 +1,15 @@
-import { create, clickable, isPresent, text, visitable } from 'ember-cli-page-object';
+import {
+ create,
+ clickable,
+ isPresent,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import { run } from '@ember/runloop';
-import { selectOpen, selectOpenChoose } from '../../utils/ember-power-select-extensions';
+import {
+ selectOpen,
+ selectOpenChoose,
+} from '../../utils/ember-power-select-extensions';
export default create({
visit: visitable('/clients/:id/monitor'),
diff --git a/ui/tests/pages/components/allocations.js b/ui/tests/pages/components/allocations.js
index 748a0ab16..6f152a4ee 100644
--- a/ui/tests/pages/components/allocations.js
+++ b/ui/tests/pages/components/allocations.js
@@ -1,7 +1,16 @@
-import { attribute, collection, clickable, isPresent, text } from 'ember-cli-page-object';
+import {
+ attribute,
+ collection,
+ clickable,
+ isPresent,
+ text,
+} from 'ember-cli-page-object';
import { singularize } from 'ember-inflector';
-export default function(selector = '[data-test-allocation]', propKey = 'allocations') {
+export default function (
+ selector = '[data-test-allocation]',
+ propKey = 'allocations'
+) {
const lookupKey = `${singularize(propKey)}For`;
// Remove the bracket notation
const attr = selector.substring(1, selector.length - 1);
@@ -11,7 +20,10 @@ export default function(selector = '[data-test-allocation]', propKey = 'allocati
id: attribute(attr),
shortId: text('[data-test-short-id]'),
createTime: text('[data-test-create-time]'),
- createTooltip: attribute('aria-label', '[data-test-create-time] .tooltip'),
+ createTooltip: attribute(
+ 'aria-label',
+ '[data-test-create-time] .tooltip'
+ ),
modifyTime: text('[data-test-modify-time]'),
health: text('[data-test-health]'),
status: text('[data-test-client-status]'),
@@ -25,7 +37,9 @@ export default function(selector = '[data-test-allocation]', propKey = 'allocati
cpuTooltip: attribute('aria-label', '[data-test-cpu] .tooltip'),
mem: text('[data-test-mem]'),
memTooltip: attribute('aria-label', '[data-test-mem] .tooltip'),
- rescheduled: isPresent('[data-test-indicators] [data-test-icon="reschedule"]'),
+ rescheduled: isPresent(
+ '[data-test-indicators] [data-test-icon="reschedule"]'
+ ),
visit: clickable('[data-test-short-id] a'),
visitRow: clickable(),
@@ -33,8 +47,8 @@ export default function(selector = '[data-test-allocation]', propKey = 'allocati
visitClient: clickable('[data-test-client] a'),
}),
- [lookupKey]: function(id) {
- return this[propKey].toArray().find(allocation => allocation.id === id);
+ [lookupKey]: function (id) {
+ return this[propKey].toArray().find((allocation) => allocation.id === id);
},
};
}
diff --git a/ui/tests/pages/components/clients.js b/ui/tests/pages/components/clients.js
index 4be7fbee3..6cf592d3b 100644
--- a/ui/tests/pages/components/clients.js
+++ b/ui/tests/pages/components/clients.js
@@ -1,7 +1,7 @@
import { attribute, collection, clickable, text } from 'ember-cli-page-object';
import { singularize } from 'ember-inflector';
-export default function(selector = '[data-test-client]', propKey = 'clients') {
+export default function (selector = '[data-test-client]', propKey = 'clients') {
const lookupKey = `${singularize(propKey)}For`;
// Remove the bracket notation
const attr = selector.substring(1, selector.length - 1);
@@ -33,8 +33,8 @@ export default function(selector = '[data-test-client]', propKey = 'clients') {
visitRow: clickable(),
}),
- [lookupKey]: function(id) {
- return this[propKey].toArray().find(client => client.id === id);
+ [lookupKey]: function (id) {
+ return this[propKey].toArray().find((client) => client.id === id);
},
};
}
diff --git a/ui/tests/pages/components/error.js b/ui/tests/pages/components/error.js
index 066ef08fc..634cb6ab1 100644
--- a/ui/tests/pages/components/error.js
+++ b/ui/tests/pages/components/error.js
@@ -1,6 +1,6 @@
import { clickable, isPresent, text } from 'ember-cli-page-object';
-export default function(selectorBase = 'data-test-error') {
+export default function (selectorBase = 'data-test-error') {
return {
scope: `[${selectorBase}]`,
isPresent: isPresent(),
diff --git a/ui/tests/pages/components/facet.js b/ui/tests/pages/components/facet.js
index a4d737184..a5ce8a77b 100644
--- a/ui/tests/pages/components/facet.js
+++ b/ui/tests/pages/components/facet.js
@@ -1,7 +1,10 @@
import { clickable, collection, text, attribute } from 'ember-cli-page-object';
-import { selectChoose, clickTrigger } from 'ember-power-select/test-support/helpers';
+import {
+ selectChoose,
+ clickTrigger,
+} from 'ember-power-select/test-support/helpers';
-export const multiFacet = scope => ({
+export const multiFacet = (scope) => ({
scope,
toggle: clickable('[data-test-dropdown-trigger]'),
@@ -15,7 +18,7 @@ export const multiFacet = scope => ({
}),
});
-export const singleFacet = scope => ({
+export const singleFacet = (scope) => ({
scope,
async toggle() {
diff --git a/ui/tests/pages/components/gauge-chart.js b/ui/tests/pages/components/gauge-chart.js
index 04b59287c..57f8da766 100644
--- a/ui/tests/pages/components/gauge-chart.js
+++ b/ui/tests/pages/components/gauge-chart.js
@@ -1,6 +1,6 @@
import { isPresent, text } from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
svgIsPresent: isPresent('[data-test-gauge-svg]'),
diff --git a/ui/tests/pages/components/job-client-status-bar.js b/ui/tests/pages/components/job-client-status-bar.js
index e29d84185..6172259cc 100644
--- a/ui/tests/pages/components/job-client-status-bar.js
+++ b/ui/tests/pages/components/job-client-status-bar.js
@@ -1,6 +1,6 @@
import { attribute, clickable, collection } from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
slices: collection('svg .bars g', {
@@ -21,17 +21,11 @@ export default scope => ({
}),
},
- visitSlice: async function(label) {
- await this.slices
- .toArray()
- .findBy('label', label)
- .click();
+ visitSlice: async function (label) {
+ await this.slices.toArray().findBy('label', label).click();
},
- visitLegend: async function(label) {
- await this.legend.clickableItems
- .toArray()
- .findBy('label', label)
- .click();
+ visitLegend: async function (label) {
+ await this.legend.clickableItems.toArray().findBy('label', label).click();
},
});
diff --git a/ui/tests/pages/components/notification.js b/ui/tests/pages/components/notification.js
index 95e4a20a8..9c07c54ac 100644
--- a/ui/tests/pages/components/notification.js
+++ b/ui/tests/pages/components/notification.js
@@ -1,6 +1,6 @@
import { isPresent, clickable, text } from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
isPresent: isPresent(),
diff --git a/ui/tests/pages/components/page-size-select.js b/ui/tests/pages/components/page-size-select.js
index 51d09cbfc..3ea9f3747 100644
--- a/ui/tests/pages/components/page-size-select.js
+++ b/ui/tests/pages/components/page-size-select.js
@@ -1,9 +1,15 @@
import { clickable, collection, isPresent, text } from 'ember-cli-page-object';
export default () => ({
- isPresent: isPresent('[data-test-page-size-select-parent] .ember-power-select-trigger'),
- open: clickable('[data-test-page-size-select-parent] .ember-power-select-trigger'),
- selectedOption: text('[data-test-page-size-select-parent] .ember-power-select-selected-item'),
+ isPresent: isPresent(
+ '[data-test-page-size-select-parent] .ember-power-select-trigger'
+ ),
+ open: clickable(
+ '[data-test-page-size-select-parent] .ember-power-select-trigger'
+ ),
+ selectedOption: text(
+ '[data-test-page-size-select-parent] .ember-power-select-selected-item'
+ ),
options: collection('.ember-power-select-option', {
testContainer: '#ember-testing',
resetScope: true,
diff --git a/ui/tests/pages/components/popover-menu.js b/ui/tests/pages/components/popover-menu.js
index e156198aa..8b38d2fb7 100644
--- a/ui/tests/pages/components/popover-menu.js
+++ b/ui/tests/pages/components/popover-menu.js
@@ -1,10 +1,16 @@
-import { clickable, focusable, isPresent, text, triggerable } from 'ember-cli-page-object';
+import {
+ clickable,
+ focusable,
+ isPresent,
+ text,
+ triggerable,
+} from 'ember-cli-page-object';
const ARROW_DOWN = 40;
const ESC = 27;
const TAB = 9;
-export default scope => ({
+export default (scope) => ({
scope,
isPresent: isPresent(),
diff --git a/ui/tests/pages/components/recommendation-card.js b/ui/tests/pages/components/recommendation-card.js
index 823a4a4ca..5be7a7855 100644
--- a/ui/tests/pages/components/recommendation-card.js
+++ b/ui/tests/pages/components/recommendation-card.js
@@ -1,4 +1,10 @@
-import { attribute, collection, hasClass, isPresent, text } from 'ember-cli-page-object';
+import {
+ attribute,
+ collection,
+ hasClass,
+ isPresent,
+ text,
+} from 'ember-cli-page-object';
import { getter } from 'ember-cli-page-object/macros';
import toggle from 'nomad-ui/tests/pages/components/toggle';
@@ -67,7 +73,7 @@ function totalsTableCell(scope) {
scope,
isIncrease: hasClass('increase'),
isDecrease: hasClass('decrease'),
- isNeutral: getter(function() {
+ isNeutral: getter(function () {
return !this.isIncrease && !this.isDecrease;
}),
};
diff --git a/ui/tests/pages/components/stepper-input.js b/ui/tests/pages/components/stepper-input.js
index b9eac7233..17b4af348 100644
--- a/ui/tests/pages/components/stepper-input.js
+++ b/ui/tests/pages/components/stepper-input.js
@@ -10,7 +10,7 @@ import {
value,
} from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
label: text('[data-test-stepper-label]'),
diff --git a/ui/tests/pages/components/toggle.js b/ui/tests/pages/components/toggle.js
index cdd1342cf..3db03a46f 100644
--- a/ui/tests/pages/components/toggle.js
+++ b/ui/tests/pages/components/toggle.js
@@ -1,6 +1,13 @@
-import { attribute, property, clickable, hasClass, isPresent, text } from 'ember-cli-page-object';
+import {
+ attribute,
+ property,
+ clickable,
+ hasClass,
+ isPresent,
+ text,
+} from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
isPresent: isPresent(),
diff --git a/ui/tests/pages/components/topo-viz.js b/ui/tests/pages/components/topo-viz.js
index 657e5a165..455a084c4 100644
--- a/ui/tests/pages/components/topo-viz.js
+++ b/ui/tests/pages/components/topo-viz.js
@@ -1,11 +1,16 @@
import { collection, isPresent } from 'ember-cli-page-object';
import TopoVizDatacenter from './topo-viz/datacenter';
-export default scope => ({
+export default (scope) => ({
scope,
- datacenters: collection('[data-test-topo-viz-datacenter]', TopoVizDatacenter()),
+ datacenters: collection(
+ '[data-test-topo-viz-datacenter]',
+ TopoVizDatacenter()
+ ),
- allocationAssociationsArePresent: isPresent('[data-test-allocation-associations]'),
+ allocationAssociationsArePresent: isPresent(
+ '[data-test-allocation-associations]'
+ ),
allocationAssociations: collection('[data-test-allocation-association]'),
});
diff --git a/ui/tests/pages/components/topo-viz/datacenter.js b/ui/tests/pages/components/topo-viz/datacenter.js
index 1388eeead..6f371ccfb 100644
--- a/ui/tests/pages/components/topo-viz/datacenter.js
+++ b/ui/tests/pages/components/topo-viz/datacenter.js
@@ -1,7 +1,7 @@
import { collection, text } from 'ember-cli-page-object';
import TopoVizNode from './node';
-export default scope => ({
+export default (scope) => ({
scope,
label: text('[data-test-topo-viz-datacenter-label]'),
diff --git a/ui/tests/pages/components/topo-viz/node.js b/ui/tests/pages/components/topo-viz/node.js
index a31bab0f1..4874d63dc 100644
--- a/ui/tests/pages/components/topo-viz/node.js
+++ b/ui/tests/pages/components/topo-viz/node.js
@@ -21,7 +21,7 @@ const allocationRect = {
pending: hasClass('pending'),
};
-export default scope => ({
+export default (scope) => ({
scope,
label: text('[data-test-label]'),
diff --git a/ui/tests/pages/components/two-step-button.js b/ui/tests/pages/components/two-step-button.js
index 1c787b9bb..403689e4b 100644
--- a/ui/tests/pages/components/two-step-button.js
+++ b/ui/tests/pages/components/two-step-button.js
@@ -1,6 +1,12 @@
-import { attribute, clickable, hasClass, isPresent, text } from 'ember-cli-page-object';
+import {
+ attribute,
+ clickable,
+ hasClass,
+ isPresent,
+ text,
+} from 'ember-cli-page-object';
-export default scope => ({
+export default (scope) => ({
scope,
isPresent: isPresent(),
diff --git a/ui/tests/pages/exec.js b/ui/tests/pages/exec.js
index a0b59222a..a9b8358a7 100644
--- a/ui/tests/pages/exec.js
+++ b/ui/tests/pages/exec.js
@@ -40,7 +40,9 @@ export default create({
terminal: {
scope: '.xterm-helper-textarea',
- pressEnter: triggerable('keydown', '', { eventProperties: { keyCode: 13 } }),
+ pressEnter: triggerable('keydown', '', {
+ eventProperties: { keyCode: 13 },
+ }),
},
jobDead: {
diff --git a/ui/tests/pages/helpers/codemirror.js b/ui/tests/pages/helpers/codemirror.js
index 8a64b6e5b..0fbfd3033 100644
--- a/ui/tests/pages/helpers/codemirror.js
+++ b/ui/tests/pages/helpers/codemirror.js
@@ -7,7 +7,7 @@ export function codeFillable(selector) {
isDescriptor: true,
get() {
- return function(code) {
+ return function (code) {
const cm = getCodeMirrorInstance(selector);
cm.setValue(code);
return this;
diff --git a/ui/tests/pages/jobs/detail.js b/ui/tests/pages/jobs/detail.js
index e82fc6f83..9c07feaa7 100644
--- a/ui/tests/pages/jobs/detail.js
+++ b/ui/tests/pages/jobs/detail.js
@@ -29,7 +29,10 @@ export default create({
return this.tabs.toArray().findBy('id', id);
},
- recommendations: collection('[data-test-recommendation-accordion]', recommendationAccordion),
+ recommendations: collection(
+ '[data-test-recommendation-accordion]',
+ recommendationAccordion
+ ),
stop: twoStepButton('[data-test-stop]'),
start: twoStepButton('[data-test-start]'),
@@ -82,7 +85,9 @@ export default create({
tooltip: attribute('aria-label'),
},
},
- childrenSummary: jobClientStatusBar('[data-test-job-summary] [data-test-children-status-bar]'),
+ childrenSummary: jobClientStatusBar(
+ '[data-test-job-summary] [data-test-children-status-bar]'
+ ),
allocationsSummary: jobClientStatusBar(
'[data-test-job-summary] [data-test-allocation-status-bar]'
),
diff --git a/ui/tests/pages/jobs/job/allocations.js b/ui/tests/pages/jobs/job/allocations.js
index 8b15cb932..4678f06d0 100644
--- a/ui/tests/pages/jobs/job/allocations.js
+++ b/ui/tests/pages/jobs/job/allocations.js
@@ -40,10 +40,7 @@ export default create({
}),
sortBy(id) {
- return this.sortOptions
- .toArray()
- .findBy('id', id)
- .sort();
+ return this.sortOptions.toArray().findBy('id', id).sort();
},
error: error(),
diff --git a/ui/tests/pages/jobs/job/clients.js b/ui/tests/pages/jobs/job/clients.js
index 83d69fa9e..ba7bad745 100644
--- a/ui/tests/pages/jobs/job/clients.js
+++ b/ui/tests/pages/jobs/job/clients.js
@@ -33,10 +33,7 @@ export default create({
}),
sortBy(id) {
- return this.sortOptions
- .toArray()
- .findBy('id', id)
- .sort();
+ return this.sortOptions.toArray().findBy('id', id).sort();
},
facets: {
diff --git a/ui/tests/pages/jobs/job/evaluations.js b/ui/tests/pages/jobs/job/evaluations.js
index 79200460a..884744f0a 100644
--- a/ui/tests/pages/jobs/job/evaluations.js
+++ b/ui/tests/pages/jobs/job/evaluations.js
@@ -1,4 +1,11 @@
-import { attribute, clickable, create, collection, text, visitable } from 'ember-cli-page-object';
+import {
+ attribute,
+ clickable,
+ create,
+ collection,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import error from 'nomad-ui/tests/pages/components/error';
@@ -15,10 +22,7 @@ export default create({
}),
sortBy(id) {
- return this.sortOptions
- .toArray()
- .findBy('id', id)
- .sort();
+ return this.sortOptions.toArray().findBy('id', id).sort();
},
error: error(),
diff --git a/ui/tests/pages/jobs/job/task-group.js b/ui/tests/pages/jobs/job/task-group.js
index 28bd08dbd..330569c8e 100644
--- a/ui/tests/pages/jobs/job/task-group.js
+++ b/ui/tests/pages/jobs/job/task-group.js
@@ -50,25 +50,36 @@ export default create({
}),
hasScaleEvents: isPresent('[data-test-scale-events]'),
- scaleEvents: collection('[data-test-scale-events] [data-test-accordion-head]', {
- error: isPresent('[data-test-error]'),
- time: text('[data-test-time]'),
- count: text('[data-test-count]'),
- countIcon: { scope: '[data-test-count-icon]' },
- message: text('[data-test-message]'),
+ scaleEvents: collection(
+ '[data-test-scale-events] [data-test-accordion-head]',
+ {
+ error: isPresent('[data-test-error]'),
+ time: text('[data-test-time]'),
+ count: text('[data-test-count]'),
+ countIcon: { scope: '[data-test-count-icon]' },
+ message: text('[data-test-message]'),
- isToggleable: isPresent('[data-test-accordion-toggle]:not(.is-invisible)'),
- toggle: clickable('[data-test-accordion-toggle]'),
- }),
+ isToggleable: isPresent(
+ '[data-test-accordion-toggle]:not(.is-invisible)'
+ ),
+ toggle: clickable('[data-test-accordion-toggle]'),
+ }
+ ),
- scaleEventBodies: collection('[data-test-scale-events] [data-test-accordion-body]', {
- meta: text(),
- }),
+ scaleEventBodies: collection(
+ '[data-test-scale-events] [data-test-accordion-body]',
+ {
+ meta: text(),
+ }
+ ),
hasScalingTimeline: isPresent('[data-test-scaling-timeline]'),
- scalingAnnotations: collection('[data-test-scaling-timeline] [data-test-annotation]', {
- open: clickable('button'),
- }),
+ scalingAnnotations: collection(
+ '[data-test-scaling-timeline] [data-test-annotation]',
+ {
+ open: clickable('button'),
+ }
+ ),
error: error(),
diff --git a/ui/tests/pages/jobs/job/versions.js b/ui/tests/pages/jobs/job/versions.js
index 416406f00..477012f5c 100644
--- a/ui/tests/pages/jobs/job/versions.js
+++ b/ui/tests/pages/jobs/job/versions.js
@@ -1,4 +1,10 @@
-import { attribute, create, collection, text, visitable } from 'ember-cli-page-object';
+import {
+ attribute,
+ create,
+ collection,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import { getter } from 'ember-cli-page-object/macros';
import twoStepButton from 'nomad-ui/tests/pages/components/two-step-button';
@@ -15,7 +21,7 @@ export default create({
revertToButton: twoStepButton('[data-test-revert-to]'),
revertToButtonIsDisabled: attribute('disabled', '[data-test-revert-to]'),
- number: getter(function() {
+ number: getter(function () {
return parseInt(this.text.match(/#(\d+)/)[1]);
}),
}),
diff --git a/ui/tests/pages/layout.js b/ui/tests/pages/layout.js
index b48f2b3af..2fe186795 100644
--- a/ui/tests/pages/layout.js
+++ b/ui/tests/pages/layout.js
@@ -85,7 +85,7 @@ export default create({
}),
breadcrumbFor(id) {
- return this.breadcrumbs.toArray().find(crumb => crumb.id === id);
+ return this.breadcrumbs.toArray().find((crumb) => crumb.id === id);
},
error: {
diff --git a/ui/tests/pages/optimize.js b/ui/tests/pages/optimize.js
index 35fbddc4c..b37efbad7 100644
--- a/ui/tests/pages/optimize.js
+++ b/ui/tests/pages/optimize.js
@@ -30,19 +30,22 @@ export default create({
card: recommendationCard,
- recommendationSummaries: collection('[data-test-recommendation-summary-row]', {
- isActive: hasClass('is-active'),
- isDisabled: hasClass('is-disabled'),
+ recommendationSummaries: collection(
+ '[data-test-recommendation-summary-row]',
+ {
+ isActive: hasClass('is-active'),
+ isDisabled: hasClass('is-disabled'),
- slug: text('[data-test-slug]'),
- namespace: text('[data-test-namespace]'),
- date: text('[data-test-date]'),
- allocationCount: text('[data-test-allocation-count]'),
- cpu: text('[data-test-cpu]'),
- memory: text('[data-test-memory]'),
- aggregateCpu: text('[data-test-aggregate-cpu]'),
- aggregateMemory: text('[data-test-aggregate-memory]'),
- }),
+ slug: text('[data-test-slug]'),
+ namespace: text('[data-test-namespace]'),
+ date: text('[data-test-date]'),
+ allocationCount: text('[data-test-allocation-count]'),
+ cpu: text('[data-test-cpu]'),
+ memory: text('[data-test-memory]'),
+ aggregateCpu: text('[data-test-aggregate-cpu]'),
+ aggregateMemory: text('[data-test-aggregate-memory]'),
+ }
+ ),
empty: {
scope: '[data-test-empty-recommendations]',
diff --git a/ui/tests/pages/servers/detail.js b/ui/tests/pages/servers/detail.js
index 6a9499ead..4b6d41c0c 100644
--- a/ui/tests/pages/servers/detail.js
+++ b/ui/tests/pages/servers/detail.js
@@ -1,4 +1,11 @@
-import { create, collection, clickable, isPresent, text, visitable } from 'ember-cli-page-object';
+import {
+ create,
+ collection,
+ clickable,
+ isPresent,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
export default create({
visit: visitable('/servers/:name'),
diff --git a/ui/tests/pages/servers/list.js b/ui/tests/pages/servers/list.js
index cc884d4e1..2d29cffdd 100644
--- a/ui/tests/pages/servers/list.js
+++ b/ui/tests/pages/servers/list.js
@@ -1,4 +1,10 @@
-import { create, collection, clickable, text, visitable } from 'ember-cli-page-object';
+import {
+ create,
+ collection,
+ clickable,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
export default create({
pageSize: 8,
diff --git a/ui/tests/pages/servers/monitor.js b/ui/tests/pages/servers/monitor.js
index bded4c156..b040e467f 100644
--- a/ui/tests/pages/servers/monitor.js
+++ b/ui/tests/pages/servers/monitor.js
@@ -1,6 +1,15 @@
-import { create, clickable, isPresent, text, visitable } from 'ember-cli-page-object';
+import {
+ create,
+ clickable,
+ isPresent,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import { run } from '@ember/runloop';
-import { selectOpen, selectOpenChoose } from '../../utils/ember-power-select-extensions';
+import {
+ selectOpen,
+ selectOpenChoose,
+} from '../../utils/ember-power-select-extensions';
export default create({
visit: visitable('/servers/:name/monitor'),
diff --git a/ui/tests/pages/storage/plugins/detail.js b/ui/tests/pages/storage/plugins/detail.js
index 160df3400..3a18e9317 100644
--- a/ui/tests/pages/storage/plugins/detail.js
+++ b/ui/tests/pages/storage/plugins/detail.js
@@ -1,4 +1,10 @@
-import { clickable, create, isPresent, text, visitable } from 'ember-cli-page-object';
+import {
+ clickable,
+ create,
+ isPresent,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import allocations from 'nomad-ui/tests/pages/components/allocations';
@@ -12,15 +18,21 @@ export default create({
nodeHealth: text('[data-test-plugin-node-health]'),
provider: text('[data-test-plugin-provider]'),
- controllerAvailabilityIsPresent: isPresent('[data-test-plugin-controller-availability]'),
+ controllerAvailabilityIsPresent: isPresent(
+ '[data-test-plugin-controller-availability]'
+ ),
nodeAvailabilityIsPresent: isPresent('[data-test-plugin-node-availability]'),
...allocations('[data-test-controller-allocation]', 'controllerAllocations'),
...allocations('[data-test-node-allocation]', 'nodeAllocations'),
- goToControllerAllocations: clickable('[data-test-go-to-controller-allocations]'),
+ goToControllerAllocations: clickable(
+ '[data-test-go-to-controller-allocations]'
+ ),
goToNodeAllocations: clickable('[data-test-go-to-node-allocations]'),
- goToControllerAllocationsText: text('[data-test-go-to-controller-allocations]'),
+ goToControllerAllocationsText: text(
+ '[data-test-go-to-controller-allocations]'
+ ),
goToNodeAllocationsText: text('[data-test-go-to-node-allocations]'),
controllerTableIsPresent: isPresent('[data-test-controller-allocations]'),
diff --git a/ui/tests/pages/storage/plugins/plugin/allocations.js b/ui/tests/pages/storage/plugins/plugin/allocations.js
index bd553fbe4..37084aeef 100644
--- a/ui/tests/pages/storage/plugins/plugin/allocations.js
+++ b/ui/tests/pages/storage/plugins/plugin/allocations.js
@@ -1,4 +1,10 @@
-import { clickable, create, isPresent, text, visitable } from 'ember-cli-page-object';
+import {
+ clickable,
+ create,
+ isPresent,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import allocations from 'nomad-ui/tests/pages/components/allocations';
import { multiFacet } from 'nomad-ui/tests/pages/components/facet';
diff --git a/ui/tests/pages/topology.js b/ui/tests/pages/topology.js
index 401115543..c62dfeef0 100644
--- a/ui/tests/pages/topology.js
+++ b/ui/tests/pages/topology.js
@@ -1,4 +1,12 @@
-import { attribute, clickable, collection, create, hasClass, text, visitable } from 'ember-cli-page-object';
+import {
+ attribute,
+ clickable,
+ collection,
+ create,
+ hasClass,
+ text,
+ visitable,
+} from 'ember-cli-page-object';
import TopoViz from 'nomad-ui/tests/pages/components/topo-viz';
import notification from 'nomad-ui/tests/pages/components/notification';
diff --git a/ui/tests/unit/abilities/allocation-test.js b/ui/tests/unit/abilities/allocation-test.js
index 27eb574de..209a00ead 100644
--- a/ui/tests/unit/abilities/allocation-test.js
+++ b/ui/tests/unit/abilities/allocation-test.js
@@ -4,11 +4,11 @@ import { setupTest } from 'ember-qunit';
import Service from '@ember/service';
import setupAbility from 'nomad-ui/tests/helpers/setup-ability';
-module('Unit | Ability | allocation', function(hooks) {
+module('Unit | Ability | allocation', function (hooks) {
setupTest(hooks);
setupAbility('allocation')(hooks);
- test('it permits alloc exec when ACLs are disabled', function(assert) {
+ test('it permits alloc exec when ACLs are disabled', function (assert) {
const mockToken = Service.extend({
aclEnabled: false,
});
@@ -18,7 +18,7 @@ module('Unit | Ability | allocation', function(hooks) {
assert.ok(this.can.can('exec allocation'));
});
- test('it permits alloc exec for management tokens', function(assert) {
+ test('it permits alloc exec for management tokens', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'management' },
@@ -29,7 +29,7 @@ module('Unit | Ability | allocation', function(hooks) {
assert.ok(this.can.can('exec allocation'));
});
- test('it permits alloc exec for client tokens with a policy that has namespace alloc-exec', function(assert) {
+ test('it permits alloc exec for client tokens with a policy that has namespace alloc-exec', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -54,10 +54,12 @@ module('Unit | Ability | allocation', function(hooks) {
this.owner.register('service:system', mockSystem);
this.owner.register('service:token', mockToken);
- assert.ok(this.can.can('exec allocation', null, { namespace: 'aNamespace' }));
+ assert.ok(
+ this.can.can('exec allocation', null, { namespace: 'aNamespace' })
+ );
});
- test('it permits alloc exec for client tokens with a policy that has default namespace alloc-exec and no capabilities for active namespace', function(assert) {
+ test('it permits alloc exec for client tokens with a policy that has default namespace alloc-exec and no capabilities for active namespace', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -86,10 +88,12 @@ module('Unit | Ability | allocation', function(hooks) {
this.owner.register('service:system', mockSystem);
this.owner.register('service:token', mockToken);
- assert.ok(this.can.can('exec allocation', null, { namespace: 'anotherNamespace' }));
+ assert.ok(
+ this.can.can('exec allocation', null, { namespace: 'anotherNamespace' })
+ );
});
- test('it blocks alloc exec for client tokens with a policy that has no alloc-exec capability', function(assert) {
+ test('it blocks alloc exec for client tokens with a policy that has no alloc-exec capability', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -114,10 +118,12 @@ module('Unit | Ability | allocation', function(hooks) {
this.owner.register('service:system', mockSystem);
this.owner.register('service:token', mockToken);
- assert.ok(this.can.cannot('exec allocation', null, { namespace: 'aNamespace' }));
+ assert.ok(
+ this.can.cannot('exec allocation', null, { namespace: 'aNamespace' })
+ );
});
- test('it handles globs in namespace names', function(assert) {
+ test('it handles globs in namespace names', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -162,12 +168,22 @@ module('Unit | Ability | allocation', function(hooks) {
this.owner.register('service:system', mockSystem);
this.owner.register('service:token', mockToken);
- assert.ok(this.can.cannot('exec allocation', null, { namespace: 'production-web' }));
- assert.ok(this.can.can('exec allocation', null, { namespace: 'production-api' }));
- assert.ok(this.can.can('exec allocation', null, { namespace: 'production-other' }));
- assert.ok(this.can.can('exec allocation', null, { namespace: 'something-suffixed' }));
assert.ok(
- this.can.cannot('exec allocation', null, { namespace: 'something-more-suffixed' }),
+ this.can.cannot('exec allocation', null, { namespace: 'production-web' })
+ );
+ assert.ok(
+ this.can.can('exec allocation', null, { namespace: 'production-api' })
+ );
+ assert.ok(
+ this.can.can('exec allocation', null, { namespace: 'production-other' })
+ );
+ assert.ok(
+ this.can.can('exec allocation', null, { namespace: 'something-suffixed' })
+ );
+ assert.ok(
+ this.can.cannot('exec allocation', null, {
+ namespace: 'something-more-suffixed',
+ }),
'expected the namespace with the greatest number of matched characters to be chosen'
);
assert.ok(
diff --git a/ui/tests/unit/abilities/client-test.js b/ui/tests/unit/abilities/client-test.js
index 2a9fe9986..8d2c2a731 100644
--- a/ui/tests/unit/abilities/client-test.js
+++ b/ui/tests/unit/abilities/client-test.js
@@ -4,11 +4,11 @@ import { setupTest } from 'ember-qunit';
import Service from '@ember/service';
import setupAbility from 'nomad-ui/tests/helpers/setup-ability';
-module('Unit | Ability | client', function(hooks) {
+module('Unit | Ability | client', function (hooks) {
setupTest(hooks);
setupAbility('client')(hooks);
- test('it permits client read and write when ACLs are disabled', function(assert) {
+ test('it permits client read and write when ACLs are disabled', function (assert) {
const mockToken = Service.extend({
aclEnabled: false,
});
@@ -18,7 +18,7 @@ module('Unit | Ability | client', function(hooks) {
assert.ok(this.ability.canWrite);
});
- test('it permits client read and write for management tokens', function(assert) {
+ test('it permits client read and write for management tokens', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'management' },
@@ -29,7 +29,7 @@ module('Unit | Ability | client', function(hooks) {
assert.ok(this.ability.canWrite);
});
- test('it permits client read and write for tokens with a policy that has node-write', function(assert) {
+ test('it permits client read and write for tokens with a policy that has node-write', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
@@ -49,7 +49,7 @@ module('Unit | Ability | client', function(hooks) {
assert.ok(this.ability.canWrite);
});
- test('it permits client read and write for tokens with a policy that allows write and another policy that disallows it', function(assert) {
+ test('it permits client read and write for tokens with a policy that allows write and another policy that disallows it', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
@@ -76,7 +76,7 @@ module('Unit | Ability | client', function(hooks) {
assert.ok(this.ability.canWrite);
});
- test('it permits client read and blocks client write for tokens with a policy that does not allow node-write', function(assert) {
+ test('it permits client read and blocks client write for tokens with a policy that does not allow node-write', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
@@ -96,7 +96,7 @@ module('Unit | Ability | client', function(hooks) {
assert.notOk(this.ability.canWrite);
});
- test('it blocks client read and write for tokens without a node policy', function(assert) {
+ test('it blocks client read and write for tokens without a node policy', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'client' },
diff --git a/ui/tests/unit/abilities/job-test.js b/ui/tests/unit/abilities/job-test.js
index 8cd2b0ac1..f1f89233b 100644
--- a/ui/tests/unit/abilities/job-test.js
+++ b/ui/tests/unit/abilities/job-test.js
@@ -4,11 +4,11 @@ import { setupTest } from 'ember-qunit';
import Service from '@ember/service';
import setupAbility from 'nomad-ui/tests/helpers/setup-ability';
-module('Unit | Ability | job', function(hooks) {
+module('Unit | Ability | job', function (hooks) {
setupTest(hooks);
setupAbility('job')(hooks);
- test('it permits job run when ACLs are disabled', function(assert) {
+ test('it permits job run when ACLs are disabled', function (assert) {
const mockToken = Service.extend({
aclEnabled: false,
});
@@ -18,7 +18,7 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.ability.canRun);
});
- test('it permits job run for management tokens', function(assert) {
+ test('it permits job run for management tokens', function (assert) {
const mockToken = Service.extend({
aclEnabled: true,
selfToken: { type: 'management' },
@@ -29,7 +29,7 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.ability.canRun);
});
- test('it permits job run for client tokens with a policy that has namespace submit-job', function(assert) {
+ test('it permits job run for client tokens with a policy that has namespace submit-job', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -57,7 +57,7 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.can.can('run job', null, { namespace: 'aNamespace' }));
});
- test('it permits job run for client tokens with a policy that has default namespace submit-job and no capabilities for active namespace', function(assert) {
+ test('it permits job run for client tokens with a policy that has default namespace submit-job and no capabilities for active namespace', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -89,7 +89,7 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.can.can('run job', null, { namespace: 'anotherNamespace' }));
});
- test('it blocks job run for client tokens with a policy that has no submit-job capability', function(assert) {
+ test('it blocks job run for client tokens with a policy that has no submit-job capability', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -117,7 +117,7 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.can.cannot('run job', null, { namespace: 'aNamespace' }));
});
- test('job scale requires a client token with the submit-job or scale-job capability', function(assert) {
+ test('job scale requires a client token with the submit-job or scale-job capability', function (assert) {
const makePolicies = (namespace, ...capabilities) => [
{
rulesJSON: {
@@ -147,17 +147,26 @@ module('Unit | Ability | job', function(hooks) {
assert.ok(this.can.cannot('scale job', null, { namespace: 'aNamespace' }));
- tokenService.set('selfTokenPolicies', makePolicies('aNamespace', 'scale-job'));
+ tokenService.set(
+ 'selfTokenPolicies',
+ makePolicies('aNamespace', 'scale-job')
+ );
assert.ok(this.can.can('scale job', null, { namespace: 'aNamespace' }));
- tokenService.set('selfTokenPolicies', makePolicies('aNamespace', 'submit-job'));
+ tokenService.set(
+ 'selfTokenPolicies',
+ makePolicies('aNamespace', 'submit-job')
+ );
assert.ok(this.can.can('scale job', null, { namespace: 'aNamespace' }));
- tokenService.set('selfTokenPolicies', makePolicies('bNamespace', 'scale-job'));
+ tokenService.set(
+ 'selfTokenPolicies',
+ makePolicies('bNamespace', 'scale-job')
+ );
assert.ok(this.can.cannot('scale job', null, { namespace: 'aNamespace' }));
});
- test('job dispatch requires a client token with the dispatch-job capability', function(assert) {
+ test('job dispatch requires a client token with the dispatch-job capability', function (assert) {
const makePolicies = (namespace, ...capabilities) => [
{
rulesJSON: {
@@ -185,13 +194,18 @@ module('Unit | Ability | job', function(hooks) {
this.owner.register('service:token', mockToken);
const tokenService = this.owner.lookup('service:token');
- assert.ok(this.can.cannot('dispatch job', null, { namespace: 'aNamespace' }));
+ assert.ok(
+ this.can.cannot('dispatch job', null, { namespace: 'aNamespace' })
+ );
- tokenService.set('selfTokenPolicies', makePolicies('aNamespace', 'dispatch-job'));
+ tokenService.set(
+ 'selfTokenPolicies',
+ makePolicies('aNamespace', 'dispatch-job')
+ );
assert.ok(this.can.can('dispatch job', null, { namespace: 'aNamespace' }));
});
- test('it handles globs in namespace names', function(assert) {
+ test('it handles globs in namespace names', function (assert) {
const mockSystem = Service.extend({
aclEnabled: true,
});
@@ -236,12 +250,18 @@ module('Unit | Ability | job', function(hooks) {
this.owner.register('service:system', mockSystem);
this.owner.register('service:token', mockToken);
- assert.ok(this.can.cannot('run job', null, { namespace: 'production-web' }));
+ assert.ok(
+ this.can.cannot('run job', null, { namespace: 'production-web' })
+ );
assert.ok(this.can.can('run job', null, { namespace: 'production-api' }));
assert.ok(this.can.can('run job', null, { namespace: 'production-other' }));
- assert.ok(this.can.can('run job', null, { namespace: 'something-suffixed' }));
assert.ok(
- this.can.cannot('run job', null, { namespace: 'something-more-suffixed' }),
+ this.can.can('run job', null, { namespace: 'something-suffixed' })
+ );
+ assert.ok(
+ this.can.cannot('run job', null, {
+ namespace: 'something-more-suffixed',
+ }),
'expected the namespace with the greatest number of matched characters to be chosen'
);
assert.ok(
diff --git a/ui/tests/unit/abilities/recommendation-test.js b/ui/tests/unit/abilities/recommendation-test.js
index 3d62fe0d1..4713ffa2f 100644
--- a/ui/tests/unit/abilities/recommendation-test.js
+++ b/ui/tests/unit/abilities/recommendation-test.js
@@ -4,78 +4,84 @@ import { setupTest } from 'ember-qunit';
import Service from '@ember/service';
import setupAbility from 'nomad-ui/tests/helpers/setup-ability';
-module('Unit | Ability | recommendation', function(hooks) {
+module('Unit | Ability | recommendation', function (hooks) {
setupTest(hooks);
setupAbility('recommendation')(hooks);
- module('when the Dynamic Application Sizing feature is present', function(hooks) {
- hooks.beforeEach(function() {
- const mockSystem = Service.extend({
- features: ['Dynamic Application Sizing'],
+ module(
+ 'when the Dynamic Application Sizing feature is present',
+ function (hooks) {
+ hooks.beforeEach(function () {
+ const mockSystem = Service.extend({
+ features: ['Dynamic Application Sizing'],
+ });
+
+ this.owner.register('service:system', mockSystem);
});
- this.owner.register('service:system', mockSystem);
- });
+ test('it permits accepting recommendations when ACLs are disabled', function (assert) {
+ const mockToken = Service.extend({
+ aclEnabled: false,
+ });
- test('it permits accepting recommendations when ACLs are disabled', function(assert) {
- const mockToken = Service.extend({
- aclEnabled: false,
+ this.owner.register('service:token', mockToken);
+
+ assert.ok(this.ability.canAccept);
});
- this.owner.register('service:token', mockToken);
+ test('it permits accepting recommendations for client tokens where any namespace has submit-job capabilities', function (assert) {
+ this.owner.lookup('service:system').set('activeNamespace', {
+ name: 'anotherNamespace',
+ });
- assert.ok(this.ability.canAccept);
- });
-
- test('it permits accepting recommendations for client tokens where any namespace has submit-job capabilities', function(assert) {
- this.owner.lookup('service:system').set('activeNamespace', {
- name: 'anotherNamespace',
- });
-
- const mockToken = Service.extend({
- aclEnabled: true,
- selfToken: { type: 'client' },
- selfTokenPolicies: [
- {
- rulesJSON: {
- Namespaces: [
- {
- Name: 'aNamespace',
- Capabilities: [],
- },
- {
- Name: 'bNamespace',
- Capabilities: ['submit-job'],
- },
- ],
+ const mockToken = Service.extend({
+ aclEnabled: true,
+ selfToken: { type: 'client' },
+ selfTokenPolicies: [
+ {
+ rulesJSON: {
+ Namespaces: [
+ {
+ Name: 'aNamespace',
+ Capabilities: [],
+ },
+ {
+ Name: 'bNamespace',
+ Capabilities: ['submit-job'],
+ },
+ ],
+ },
},
- },
- ],
+ ],
+ });
+
+ this.owner.register('service:token', mockToken);
+
+ assert.ok(this.ability.canAccept);
+ });
+ }
+ );
+
+ module(
+ 'when the Dynamic Application Sizing feature is not present',
+ function (hooks) {
+ hooks.beforeEach(function () {
+ const mockSystem = Service.extend({
+ features: [],
+ });
+
+ this.owner.register('service:system', mockSystem);
});
- this.owner.register('service:token', mockToken);
+ test('it does not permit accepting recommendations regardless of ACL status', function (assert) {
+ const mockToken = Service.extend({
+ aclEnabled: false,
+ });
- assert.ok(this.ability.canAccept);
- });
- });
+ this.owner.register('service:token', mockToken);
- module('when the Dynamic Application Sizing feature is not present', function(hooks) {
- hooks.beforeEach(function() {
- const mockSystem = Service.extend({
- features: [],
+ assert.notOk(this.ability.canAccept);
});
-
- this.owner.register('service:system', mockSystem);
- });
-
- test('it does not permit accepting recommendations regardless of ACL status', function(assert) {
- const mockToken = Service.extend({
- aclEnabled: false,
- });
-
- this.owner.register('service:token', mockToken);
-
- assert.notOk(this.ability.canAccept);
- });
- });
+ }
+ );
});
diff --git a/ui/tests/unit/adapters/allocation-test.js b/ui/tests/unit/adapters/allocation-test.js
index e0e727ec8..31b49943e 100644
--- a/ui/tests/unit/adapters/allocation-test.js
+++ b/ui/tests/unit/adapters/allocation-test.js
@@ -2,10 +2,10 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
-module('Unit | Adapter | Allocation', function(hooks) {
+module('Unit | Adapter | Allocation', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.adapterFor('allocation');
@@ -28,14 +28,17 @@ module('Unit | Adapter | Allocation', function(hooks) {
this.system.get('shouldIncludeRegion');
await this.system.get('defaultRegion');
- const allocation = await this.store.findRecord('allocation', allocationId);
+ const allocation = await this.store.findRecord(
+ 'allocation',
+ allocationId
+ );
this.server.pretender.handledRequests.length = 0;
return allocation;
};
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -46,8 +49,12 @@ module('Unit | Adapter | Allocation', function(hooks) {
task: 'task-name',
region: null,
path: 'some/path',
- ls: `GET /v1/client/fs/ls/alloc-1?path=${encodeURIComponent('some/path')}`,
- stat: `GET /v1/client/fs/stat/alloc-1?path=${encodeURIComponent('some/path')}`,
+ ls: `GET /v1/client/fs/ls/alloc-1?path=${encodeURIComponent(
+ 'some/path'
+ )}`,
+ stat: `GET /v1/client/fs/stat/alloc-1?path=${encodeURIComponent(
+ 'some/path'
+ )}`,
stop: 'POST /v1/allocation/alloc-1/stop',
restart: 'PUT /v1/client/allocation/alloc-1/restart',
},
@@ -57,7 +64,9 @@ module('Unit | Adapter | Allocation', function(hooks) {
task: 'task-name',
region: 'region-2',
path: 'some/path',
- ls: `GET /v1/client/fs/ls/alloc-1?path=${encodeURIComponent('some/path')}®ion=region-2`,
+ ls: `GET /v1/client/fs/ls/alloc-1?path=${encodeURIComponent(
+ 'some/path'
+ )}®ion=region-2`,
stat: `GET /v1/client/fs/stat/alloc-1?path=${encodeURIComponent(
'some/path'
)}®ion=region-2`,
@@ -66,51 +75,63 @@ module('Unit | Adapter | Allocation', function(hooks) {
},
];
- testCases.forEach(testCase => {
- test(`ls makes the correct API call ${testCase.variation}`, async function(assert) {
+ testCases.forEach((testCase) => {
+ test(`ls makes the correct API call ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- const allocation = await this.initialize(testCase.id, { region: testCase.region });
+ const allocation = await this.initialize(testCase.id, {
+ region: testCase.region,
+ });
await this.subject().ls(allocation, testCase.path);
const req = pretender.handledRequests[0];
assert.equal(`${req.method} ${req.url}`, testCase.ls);
});
- test(`stat makes the correct API call ${testCase.variation}`, async function(assert) {
+ test(`stat makes the correct API call ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- const allocation = await this.initialize(testCase.id, { region: testCase.region });
+ const allocation = await this.initialize(testCase.id, {
+ region: testCase.region,
+ });
await this.subject().stat(allocation, testCase.path);
const req = pretender.handledRequests[0];
assert.equal(`${req.method} ${req.url}`, testCase.stat);
});
- test(`stop makes the correct API call ${testCase.variation}`, async function(assert) {
+ test(`stop makes the correct API call ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- const allocation = await this.initialize(testCase.id, { region: testCase.region });
+ const allocation = await this.initialize(testCase.id, {
+ region: testCase.region,
+ });
await this.subject().stop(allocation);
const req = pretender.handledRequests[0];
assert.equal(`${req.method} ${req.url}`, testCase.stop);
});
- test(`restart makes the correct API call ${testCase.variation}`, async function(assert) {
+ test(`restart makes the correct API call ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- const allocation = await this.initialize(testCase.id, { region: testCase.region });
+ const allocation = await this.initialize(testCase.id, {
+ region: testCase.region,
+ });
await this.subject().restart(allocation);
const req = pretender.handledRequests[0];
assert.equal(`${req.method} ${req.url}`, testCase.restart);
});
- test(`restart with optional task name makes the correct API call ${testCase.variation}`, async function(assert) {
+ test(`restart with optional task name makes the correct API call ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- const allocation = await this.initialize(testCase.id, { region: testCase.region });
+ const allocation = await this.initialize(testCase.id, {
+ region: testCase.region,
+ });
await this.subject().restart(allocation, testCase.task);
const req = pretender.handledRequests[0];
assert.equal(`${req.method} ${req.url}`, testCase.restart);
- assert.deepEqual(JSON.parse(req.requestBody), { TaskName: testCase.task });
+ assert.deepEqual(JSON.parse(req.requestBody), {
+ TaskName: testCase.task,
+ });
});
});
});
diff --git a/ui/tests/unit/adapters/deployment-test.js b/ui/tests/unit/adapters/deployment-test.js
index a26a48f91..499a03f62 100644
--- a/ui/tests/unit/adapters/deployment-test.js
+++ b/ui/tests/unit/adapters/deployment-test.js
@@ -2,10 +2,10 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
-module('Unit | Adapter | Deployment', function(hooks) {
+module('Unit | Adapter | Deployment', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
this.system = this.owner.lookup('service:system');
this.subject = () => this.store.adapterFor('deployment');
@@ -22,19 +22,24 @@ module('Unit | Adapter | Deployment', function(hooks) {
this.server.create('node');
const job = this.server.create('job', { createAllocations: false });
- const deploymentRecord = server.schema.deployments.where({ jobId: job.id }).models[0];
+ const deploymentRecord = server.schema.deployments.where({
+ jobId: job.id,
+ }).models[0];
this.system.get('shouldIncludeRegion');
await this.system.get('defaultRegion');
- const deployment = await this.store.findRecord('deployment', deploymentRecord.id);
+ const deployment = await this.store.findRecord(
+ 'deployment',
+ deploymentRecord.id
+ );
this.server.pretender.handledRequests.length = 0;
return deployment;
};
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -42,38 +47,44 @@ module('Unit | Adapter | Deployment', function(hooks) {
{
variation: '',
region: null,
- fail: id => `POST /v1/deployment/fail/${id}`,
- promote: id => `POST /v1/deployment/promote/${id}`,
+ fail: (id) => `POST /v1/deployment/fail/${id}`,
+ promote: (id) => `POST /v1/deployment/promote/${id}`,
},
{
variation: 'with non-default region',
region: 'region-2',
- fail: id => `POST /v1/deployment/fail/${id}?region=region-2`,
- promote: id => `POST /v1/deployment/promote/${id}?region=region-2`,
+ fail: (id) => `POST /v1/deployment/fail/${id}?region=region-2`,
+ promote: (id) => `POST /v1/deployment/promote/${id}?region=region-2`,
},
];
- testCases.forEach(testCase => {
- test(`promote makes the correct API call ${testCase.variation}`, async function(assert) {
+ testCases.forEach((testCase) => {
+ test(`promote makes the correct API call ${testCase.variation}`, async function (assert) {
const deployment = await this.initialize({ region: testCase.region });
await this.subject().promote(deployment);
const request = this.server.pretender.handledRequests[0];
- assert.equal(`${request.method} ${request.url}`, testCase.promote(deployment.id));
+ assert.equal(
+ `${request.method} ${request.url}`,
+ testCase.promote(deployment.id)
+ );
assert.deepEqual(JSON.parse(request.requestBody), {
DeploymentId: deployment.id,
All: true,
});
});
- test(`fail makes the correct API call ${testCase.variation}`, async function(assert) {
+ test(`fail makes the correct API call ${testCase.variation}`, async function (assert) {
const deployment = await this.initialize({ region: testCase.region });
await this.subject().fail(deployment);
const request = this.server.pretender.handledRequests[0];
- assert.equal(`${request.method} ${request.url}`, testCase.fail(deployment.id));
+ assert.equal(
+ `${request.method} ${request.url}`,
+ testCase.fail(deployment.id)
+ );
assert.deepEqual(JSON.parse(request.requestBody), {
DeploymentId: deployment.id,
});
diff --git a/ui/tests/unit/adapters/job-test.js b/ui/tests/unit/adapters/job-test.js
index e6d283bb9..2b696ba19 100644
--- a/ui/tests/unit/adapters/job-test.js
+++ b/ui/tests/unit/adapters/job-test.js
@@ -8,10 +8,10 @@ import { AbortController } from 'fetch';
import { TextEncoderLite } from 'text-encoder-lite';
import base64js from 'base64-js';
-module('Unit | Adapter | Job', function(hooks) {
+module('Unit | Adapter | Job', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.adapterFor('job');
@@ -59,11 +59,11 @@ module('Unit | Adapter | Job', function(hooks) {
};
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('The job endpoint is the only required endpoint for fetching a job', async function(assert) {
+ test('The job endpoint is the only required endpoint for fetching a job', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -81,7 +81,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('When a namespace is set in localStorage but a job in the default namespace is requested, the namespace query param is not present', async function(assert) {
+ test('When a namespace is set in localStorage but a job in the default namespace is requested, the namespace query param is not present', async function (assert) {
await this.initializeUI({ namespace: 'some-namespace' });
const { pretender } = this.server;
@@ -99,7 +99,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('When a namespace is in localStorage and the requested job is in the default namespace, the namespace query param is left out', async function(assert) {
+ test('When a namespace is in localStorage and the requested job is in the default namespace, the namespace query param is left out', async function (assert) {
await this.initializeUI({ namespace: 'red-herring' });
const { pretender } = this.server;
@@ -117,7 +117,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('When the job has a namespace other than default, it is in the URL', async function(assert) {
+ test('When the job has a namespace other than default, it is in the URL', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -135,7 +135,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('When there is no token set in the token service, no X-Nomad-Token header is set', async function(assert) {
+ test('When there is no token set in the token service, no X-Nomad-Token header is set', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -145,12 +145,14 @@ module('Unit | Adapter | Job', function(hooks) {
await settled();
assert.notOk(
- pretender.handledRequests.mapBy('requestHeaders').some(headers => headers['X-Nomad-Token']),
+ pretender.handledRequests
+ .mapBy('requestHeaders')
+ .some((headers) => headers['X-Nomad-Token']),
'No token header present on either job request'
);
});
- test('When a token is set in the token service, then X-Nomad-Token header is set', async function(assert) {
+ test('When a token is set in the token service, then X-Nomad-Token header is set', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -164,12 +166,12 @@ module('Unit | Adapter | Job', function(hooks) {
assert.ok(
pretender.handledRequests
.mapBy('requestHeaders')
- .every(headers => headers['X-Nomad-Token'] === secret),
+ .every((headers) => headers['X-Nomad-Token'] === secret),
'The token header is present on both job requests'
);
});
- test('findAll can be watched', async function(assert) {
+ test('findAll can be watched', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -198,7 +200,7 @@ module('Unit | Adapter | Job', function(hooks) {
await settled();
});
- test('findRecord can be watched', async function(assert) {
+ test('findRecord can be watched', async function (assert) {
await this.initializeUI();
const jobId = JSON.stringify(['job-1', 'default']);
@@ -228,7 +230,7 @@ module('Unit | Adapter | Job', function(hooks) {
await settled();
});
- test('relationships can be reloaded', async function(assert) {
+ test('relationships can be reloaded', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -244,7 +246,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('relationship reloads can be watched', async function(assert) {
+ test('relationship reloads can be watched', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -269,7 +271,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('findAll can be canceled', async function(assert) {
+ test('findAll can be canceled', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -296,7 +298,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.ok(xhr.aborted, 'Request was aborted');
});
- test('findRecord can be canceled', async function(assert) {
+ test('findRecord can be canceled', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -322,7 +324,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.ok(xhr.aborted, 'Request was aborted');
});
- test('relationship reloads can be canceled', async function(assert) {
+ test('relationship reloads can be canceled', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -348,7 +350,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.ok(xhr.aborted, 'Request was aborted');
});
- test('requests can be canceled even if multiple requests for the same URL were made', async function(assert) {
+ test('requests can be canceled even if multiple requests for the same URL were made', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -371,7 +373,11 @@ module('Unit | Adapter | Job', function(hooks) {
const { request: xhr } = pretender.requestReferences[0];
const { request: xhr2 } = pretender.requestReferences[1];
assert.equal(xhr.status, 0, 'Request is still pending');
- assert.equal(pretender.requestReferences.length, 2, 'Two findRecord requests were made');
+ assert.equal(
+ pretender.requestReferences.length,
+ 2,
+ 'Two findRecord requests were made'
+ );
assert.equal(
pretender.requestReferences.mapBy('url').uniq().length,
1,
@@ -389,7 +395,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.notOk(xhr2.aborted, 'Request two was not aborted');
});
- test('dispatch job encodes payload as base64', async function(assert) {
+ test('dispatch job encodes payload as base64', async function (assert) {
const job = await this.initializeWithJob();
job.set('parameterized', true);
@@ -410,7 +416,7 @@ module('Unit | Adapter | Job', function(hooks) {
});
});
- test('when there is no region set, requests are made without the region query param', async function(assert) {
+ test('when there is no region set, requests are made without the region query param', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -430,7 +436,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('when there is a region set, requests are made with the region query param', async function(assert) {
+ test('when there is a region set, requests are made with the region query param', async function (assert) {
const region = 'region-2';
await this.initializeUI({ region });
@@ -452,7 +458,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('when the region is set to the default region, requests are made without the region query param', async function(assert) {
+ test('when the region is set to the default region, requests are made without the region query param', async function (assert) {
await this.initializeUI({ region: 'region-1' });
const { pretender } = this.server;
@@ -472,7 +478,7 @@ module('Unit | Adapter | Job', function(hooks) {
);
});
- test('fetchRawDefinition requests include the activeRegion', async function(assert) {
+ test('fetchRawDefinition requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
@@ -483,7 +489,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'GET');
});
- test('forcePeriodic requests include the activeRegion', async function(assert) {
+ test('forcePeriodic requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
job.set('periodic', true);
@@ -491,11 +497,14 @@ module('Unit | Adapter | Job', function(hooks) {
await this.subject().forcePeriodic(job);
const request = this.server.pretender.handledRequests[0];
- assert.equal(request.url, `/v1/job/${job.plainId}/periodic/force?region=${region}`);
+ assert.equal(
+ request.url,
+ `/v1/job/${job.plainId}/periodic/force?region=${region}`
+ );
assert.equal(request.method, 'POST');
});
- test('stop requests include the activeRegion', async function(assert) {
+ test('stop requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
@@ -506,7 +515,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'DELETE');
});
- test('parse requests include the activeRegion', async function(assert) {
+ test('parse requests include the activeRegion', async function (assert) {
const region = 'region-2';
await this.initializeUI({ region });
@@ -521,7 +530,7 @@ module('Unit | Adapter | Job', function(hooks) {
});
});
- test('plan requests include the activeRegion', async function(assert) {
+ test('plan requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
job.set('_newDefinitionJSON', {});
@@ -533,7 +542,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'POST');
});
- test('run requests include the activeRegion', async function(assert) {
+ test('run requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
job.set('_newDefinitionJSON', {});
@@ -545,7 +554,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'POST');
});
- test('update requests include the activeRegion', async function(assert) {
+ test('update requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
job.set('_newDefinitionJSON', {});
@@ -557,7 +566,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'POST');
});
- test('scale requests include the activeRegion', async function(assert) {
+ test('scale requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
@@ -568,7 +577,7 @@ module('Unit | Adapter | Job', function(hooks) {
assert.equal(request.method, 'POST');
});
- test('dispatch requests include the activeRegion', async function(assert) {
+ test('dispatch requests include the activeRegion', async function (assert) {
const region = 'region-2';
const job = await this.initializeWithJob({ region });
job.set('parameterized', true);
@@ -576,7 +585,10 @@ module('Unit | Adapter | Job', function(hooks) {
await this.subject().dispatch(job, {}, '');
const request = this.server.pretender.handledRequests[0];
- assert.equal(request.url, `/v1/job/${job.plainId}/dispatch?region=${region}`);
+ assert.equal(
+ request.url,
+ `/v1/job/${job.plainId}/dispatch?region=${region}`
+ );
assert.equal(request.method, 'POST');
});
});
diff --git a/ui/tests/unit/adapters/node-test.js b/ui/tests/unit/adapters/node-test.js
index b92c1c0c1..c96ac3147 100644
--- a/ui/tests/unit/adapters/node-test.js
+++ b/ui/tests/unit/adapters/node-test.js
@@ -4,10 +4,10 @@ import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { setupTest } from 'ember-qunit';
import { settled } from '@ember/test-helpers';
-module('Unit | Adapter | Node', function(hooks) {
+module('Unit | Adapter | Node', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.adapterFor('node');
@@ -28,11 +28,11 @@ module('Unit | Adapter | Node', function(hooks) {
this.server.create('allocation', { id: 'node-2-2', nodeId: 'node-2' });
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('findHasMany removes old related models from the store', async function(assert) {
+ test('findHasMany removes old related models from the store', async function (assert) {
// Fetch the model and related allocations
let node = await run(() => this.store.findRecord('node', 'node-1'));
let allocations = await run(() => findHasMany(node, 'allocations'));
@@ -46,7 +46,9 @@ module('Unit | Adapter | Node', function(hooks) {
server.db.allocations.remove('node-1-1');
allocations = await run(() => findHasMany(node, 'allocations'));
- const dbAllocations = this.server.db.allocations.where({ nodeId: node.get('id') });
+ const dbAllocations = this.server.db.allocations.where({
+ nodeId: node.get('id'),
+ });
assert.equal(
allocations.get('length'),
dbAllocations.length,
@@ -59,7 +61,7 @@ module('Unit | Adapter | Node', function(hooks) {
);
});
- test('findHasMany does not remove old unrelated models from the store', async function(assert) {
+ test('findHasMany does not remove old unrelated models from the store', async function (assert) {
// Fetch the first node and related allocations
const node = await run(() => this.store.findRecord('node', 'node-1'));
await run(() => findHasMany(node, 'allocations'));
@@ -70,10 +72,7 @@ module('Unit | Adapter | Node', function(hooks) {
await settled();
assert.deepEqual(
- this.store
- .peekAll('allocation')
- .mapBy('id')
- .sort(),
+ this.store.peekAll('allocation').mapBy('id').sort(),
['node-1-1', 'node-1-2', 'node-2-1', 'node-2-2'],
'All allocations for the first and second node are in the store'
);
@@ -83,10 +82,7 @@ module('Unit | Adapter | Node', function(hooks) {
// Reload the related allocations now that one was removed server-side
await run(() => findHasMany(node, 'allocations'));
assert.deepEqual(
- this.store
- .peekAll('allocation')
- .mapBy('id')
- .sort(),
+ this.store.peekAll('allocation').mapBy('id').sort(),
['node-1-2', 'node-2-1', 'node-2-2'],
'The deleted allocation is removed from the store and the allocations associated with the other node are untouched'
);
@@ -109,10 +105,11 @@ module('Unit | Adapter | Node', function(hooks) {
},
];
- testCases.forEach(testCase => {
- test(`setEligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function(assert) {
+ testCases.forEach((testCase) => {
+ test(`setEligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
await this.subject().setEligible(node);
@@ -125,9 +122,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`setIneligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function(assert) {
+ test(`setIneligible makes the correct POST request to /:node_id/eligibility ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
await this.subject().setIneligible(node);
@@ -140,9 +138,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`drain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function(assert) {
+ test(`drain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
await this.subject().drain(node);
@@ -158,9 +157,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`drain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function(assert) {
+ test(`drain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
@@ -178,9 +178,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`forceDrain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function(assert) {
+ test(`forceDrain makes the correct POST request to /:node_id/drain with appropriate defaults ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
@@ -197,9 +198,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`forceDrain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function(assert) {
+ test(`forceDrain makes the correct POST request to /:node_id/drain with the provided drain spec ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
@@ -217,9 +219,10 @@ module('Unit | Adapter | Node', function(hooks) {
});
});
- test(`cancelDrain makes the correct POST request to /:node_id/drain ${testCase.variation}`, async function(assert) {
+ test(`cancelDrain makes the correct POST request to /:node_id/drain ${testCase.variation}`, async function (assert) {
const { pretender } = this.server;
- if (testCase.region) window.localStorage.nomadActiveRegion = testCase.region;
+ if (testCase.region)
+ window.localStorage.nomadActiveRegion = testCase.region;
const node = await run(() => this.store.findRecord('node', testCase.id));
diff --git a/ui/tests/unit/adapters/volume-test.js b/ui/tests/unit/adapters/volume-test.js
index 683716a4e..8eeace873 100644
--- a/ui/tests/unit/adapters/volume-test.js
+++ b/ui/tests/unit/adapters/volume-test.js
@@ -5,10 +5,10 @@ import { module, test } from 'qunit';
import { startMirage } from 'nomad-ui/initializers/ember-cli-mirage';
import { AbortController } from 'fetch';
-module('Unit | Adapter | Volume', function(hooks) {
+module('Unit | Adapter | Volume', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(async function() {
+ hooks.beforeEach(async function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.adapterFor('volume');
@@ -23,7 +23,10 @@ module('Unit | Adapter | Volume', function(hooks) {
this.server.create('node');
this.server.create('job', { id: 'job-1', namespaceId: 'default' });
this.server.create('csi-plugin', 2);
- this.server.create('csi-volume', { id: 'volume-1', namespaceId: 'some-namespace' });
+ this.server.create('csi-volume', {
+ id: 'volume-1',
+ namespaceId: 'some-namespace',
+ });
this.server.create('region', { id: 'region-1' });
this.server.create('region', { id: 'region-2' });
@@ -43,22 +46,30 @@ module('Unit | Adapter | Volume', function(hooks) {
};
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('The volume endpoint can be queried by type', async function(assert) {
+ test('The volume endpoint can be queried by type', async function (assert) {
const { pretender } = this.server;
await this.initializeUI();
- this.subject().query(this.store, { modelName: 'volume' }, { type: 'csi' }, null, {});
+ this.subject().query(
+ this.store,
+ { modelName: 'volume' },
+ { type: 'csi' },
+ null,
+ {}
+ );
await settled();
- assert.deepEqual(pretender.handledRequests.mapBy('url'), ['/v1/volumes?type=csi']);
+ assert.deepEqual(pretender.handledRequests.mapBy('url'), [
+ '/v1/volumes?type=csi',
+ ]);
});
- test('When the volume has a namespace other than default, it is in the URL', async function(assert) {
+ test('When the volume has a namespace other than default, it is in the URL', async function (assert) {
const { pretender } = this.server;
const volumeName = 'csi/volume-1';
const volumeNamespace = 'some-namespace';
@@ -70,32 +81,46 @@ module('Unit | Adapter | Volume', function(hooks) {
await settled();
assert.deepEqual(pretender.handledRequests.mapBy('url'), [
- `/v1/volume/${encodeURIComponent(volumeName)}?namespace=${volumeNamespace}`,
+ `/v1/volume/${encodeURIComponent(
+ volumeName
+ )}?namespace=${volumeNamespace}`,
]);
});
- test('query can be watched', async function(assert) {
+ test('query can be watched', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
const request = () =>
- this.subject().query(this.store, { modelName: 'volume' }, { type: 'csi' }, null, {
- reload: true,
- adapterOptions: { watch: true },
- });
+ this.subject().query(
+ this.store,
+ { modelName: 'volume' },
+ { type: 'csi' },
+ null,
+ {
+ reload: true,
+ adapterOptions: { watch: true },
+ }
+ );
request();
- assert.equal(pretender.handledRequests[0].url, '/v1/volumes?type=csi&index=1');
+ assert.equal(
+ pretender.handledRequests[0].url,
+ '/v1/volumes?type=csi&index=1'
+ );
await settled();
request();
- assert.equal(pretender.handledRequests[1].url, '/v1/volumes?type=csi&index=2');
+ assert.equal(
+ pretender.handledRequests[1].url,
+ '/v1/volumes?type=csi&index=2'
+ );
await settled();
});
- test('query can be canceled', async function(assert) {
+ test('query can be canceled', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
@@ -122,16 +147,22 @@ module('Unit | Adapter | Volume', function(hooks) {
assert.ok(xhr.aborted, 'Request was aborted');
});
- test('query and findAll have distinct watchList entries', async function(assert) {
+ test('query and findAll have distinct watchList entries', async function (assert) {
await this.initializeUI();
const { pretender } = this.server;
const request = () =>
- this.subject().query(this.store, { modelName: 'volume' }, { type: 'csi' }, null, {
- reload: true,
- adapterOptions: { watch: true },
- });
+ this.subject().query(
+ this.store,
+ { modelName: 'volume' },
+ { type: 'csi' },
+ null,
+ {
+ reload: true,
+ adapterOptions: { watch: true },
+ }
+ );
const findAllRequest = () =>
this.subject().findAll(null, { modelName: 'volume' }, null, {
@@ -140,11 +171,17 @@ module('Unit | Adapter | Volume', function(hooks) {
});
request();
- assert.equal(pretender.handledRequests[0].url, '/v1/volumes?type=csi&index=1');
+ assert.equal(
+ pretender.handledRequests[0].url,
+ '/v1/volumes?type=csi&index=1'
+ );
await settled();
request();
- assert.equal(pretender.handledRequests[1].url, '/v1/volumes?type=csi&index=2');
+ assert.equal(
+ pretender.handledRequests[1].url,
+ '/v1/volumes?type=csi&index=2'
+ );
await settled();
findAllRequest();
diff --git a/ui/tests/unit/components/gauge-chart-test.js b/ui/tests/unit/components/gauge-chart-test.js
index 771da46a1..4ec1d282f 100644
--- a/ui/tests/unit/components/gauge-chart-test.js
+++ b/ui/tests/unit/components/gauge-chart-test.js
@@ -1,14 +1,14 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
-module('Unit | Component | gauge-chart', function(hooks) {
+module('Unit | Component | gauge-chart', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.subject = this.owner.factoryFor('component:gauge-chart');
});
- test('percent is a function of value and total OR complement', function(assert) {
+ test('percent is a function of value and total OR complement', function (assert) {
const chart = this.subject.create();
chart.setProperties({
value: 5,
diff --git a/ui/tests/unit/components/line-chart-test.js b/ui/tests/unit/components/line-chart-test.js
index e39d8230e..dcae81999 100644
--- a/ui/tests/unit/components/line-chart-test.js
+++ b/ui/tests/unit/components/line-chart-test.js
@@ -3,7 +3,7 @@ import { setupTest } from 'ember-qunit';
import d3Format from 'd3-format';
import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
-module('Unit | Component | line-chart', function(hooks) {
+module('Unit | Component | line-chart', function (hooks) {
setupTest(hooks);
setupGlimmerComponentFactory(hooks, 'line-chart');
@@ -15,7 +15,7 @@ module('Unit | Component | line-chart', function(hooks) {
{ foo: 4, bar: 500 },
];
- test('x scale domain is the min and max values in data based on the xProp value', function(assert) {
+ test('x scale domain is the min and max values in data based on the xProp value', function (assert) {
const chart = this.createComponent({
xProp: 'foo',
data,
@@ -36,10 +36,14 @@ module('Unit | Component | line-chart', function(hooks) {
chart.args.data = [...data, { foo: 12, bar: 600 }];
[, xDomainHigh] = chart.xScale.domain();
- assert.equal(xDomainHigh, 12, 'When the data changes, the xScale is recalculated');
+ assert.equal(
+ xDomainHigh,
+ 12,
+ 'When the data changes, the xScale is recalculated'
+ );
});
- test('y scale domain uses the max value in the data based off of yProp, but is always zero-based', function(assert) {
+ test('y scale domain uses the max value in the data based off of yProp, but is always zero-based', function (assert) {
const chart = this.createComponent({
yProp: 'bar',
data,
@@ -56,10 +60,14 @@ module('Unit | Component | line-chart', function(hooks) {
chart.args.data = [...data, { foo: 12, bar: 600 }];
[, yDomainHigh] = chart.yScale.domain();
- assert.equal(yDomainHigh, 600, 'When the data changes, the yScale is recalculated');
+ assert.equal(
+ yDomainHigh,
+ 600,
+ 'When the data changes, the yScale is recalculated'
+ );
});
- test('the number of yTicks is always odd (to always have a mid-line) and is based off the chart height', function(assert) {
+ test('the number of yTicks is always odd (to always have a mid-line) and is based off the chart height', function (assert) {
const chart = this.createComponent({
yProp: 'bar',
data,
@@ -75,7 +83,7 @@ module('Unit | Component | line-chart', function(hooks) {
assert.equal(chart.yTicks.length, 7);
});
- test('the values for yTicks are rounded to whole numbers', function(assert) {
+ test('the values for yTicks are rounded to whole numbers', function (assert) {
const chart = this.createComponent({
yProp: 'bar',
data,
@@ -91,7 +99,7 @@ module('Unit | Component | line-chart', function(hooks) {
assert.deepEqual(chart.yTicks, [0, 83, 167, 250, 333, 417, 500]);
});
- test('the values for yTicks are fractions when the domain is between 0 and 1', function(assert) {
+ test('the values for yTicks are fractions when the domain is between 0 and 1', function (assert) {
const chart = this.createComponent({
yProp: 'bar',
data: [
@@ -107,7 +115,7 @@ module('Unit | Component | line-chart', function(hooks) {
assert.deepEqual(chart.yTicks, [0, 0.25, 0.5]);
});
- test('activeDatumLabel is the xProp value of the activeDatum formatted with xFormat', function(assert) {
+ test('activeDatumLabel is the xProp value of the activeDatum formatted with xFormat', function (assert) {
const chart = this.createComponent({
xProp: 'foo',
yProp: 'bar',
@@ -123,7 +131,7 @@ module('Unit | Component | line-chart', function(hooks) {
);
});
- test('activeDatumValue is the yProp value of the activeDatum formatted with yFormat', function(assert) {
+ test('activeDatumValue is the yProp value of the activeDatum formatted with yFormat', function (assert) {
const chart = this.createComponent({
xProp: 'foo',
yProp: 'bar',
diff --git a/ui/tests/unit/components/scale-events-chart-test.js b/ui/tests/unit/components/scale-events-chart-test.js
index e0b55c952..243f7aa18 100644
--- a/ui/tests/unit/components/scale-events-chart-test.js
+++ b/ui/tests/unit/components/scale-events-chart-test.js
@@ -3,21 +3,21 @@ import { setupTest } from 'ember-qunit';
import sinon from 'sinon';
import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
-module('Unit | Component | scale-events-chart', function(hooks) {
+module('Unit | Component | scale-events-chart', function (hooks) {
setupTest(hooks);
setupGlimmerComponentFactory(hooks, 'scale-events-chart');
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.refTime = new Date();
this.clock = sinon.useFakeTimers(this.refTime);
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.clock.restore();
delete this.refTime;
});
- test('the current date is appended as a datum for the line chart to render', function(assert) {
+ test('the current date is appended as a datum for the line chart to render', function (assert) {
const events = [
{ time: new Date('2020-08-02T04:06:00'), count: 2, hasCount: true },
{ time: new Date('2020-08-01T04:06:00'), count: 2, hasCount: true },
@@ -33,7 +33,7 @@ module('Unit | Component | scale-events-chart', function(hooks) {
assert.equal(+appendedDatum.time, +this.refTime);
});
- test('if the earliest annotation is outside the domain of the events, the earliest annotation time is added as a datum for the line chart to render', function(assert) {
+ test('if the earliest annotation is outside the domain of the events, the earliest annotation time is added as a datum for the line chart to render', function (assert) {
const annotationOutside = [
{ time: new Date('2020-08-01T04:06:00'), hasCount: false, error: true },
{ time: new Date('2020-08-02T04:06:00'), count: 2, hasCount: true },
diff --git a/ui/tests/unit/components/stats-time-series-test.js b/ui/tests/unit/components/stats-time-series-test.js
index 695e327b4..0a308a865 100644
--- a/ui/tests/unit/components/stats-time-series-test.js
+++ b/ui/tests/unit/components/stats-time-series-test.js
@@ -5,14 +5,12 @@ import d3Format from 'd3-format';
import d3TimeFormat from 'd3-time-format';
import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
-module('Unit | Component | stats-time-series', function(hooks) {
+module('Unit | Component | stats-time-series', function (hooks) {
setupTest(hooks);
setupGlimmerComponentFactory(hooks, 'stats-time-series');
const ts = (offset, resolution = 'm') =>
- moment()
- .subtract(offset, resolution)
- .toDate();
+ moment().subtract(offset, resolution).toDate();
const wideData = [
{ timestamp: ts(20), percent: 0.5 },
@@ -47,10 +45,12 @@ module('Unit | Component | stats-time-series', function(hooks) {
{ timestamp: ts(18, 's'), percent: null },
];
- test('xFormat is time-formatted for hours, minutes, and seconds', function(assert) {
+ test('xFormat is time-formatted for hours, minutes, and seconds', function (assert) {
+ assert.expect(11);
+
const chart = this.createComponent({ data: wideData });
- wideData.forEach(datum => {
+ wideData.forEach((datum) => {
assert.equal(
chart.xFormat(datum.timestamp),
d3TimeFormat.timeFormat('%H:%M:%S')(datum.timestamp)
@@ -58,15 +58,20 @@ module('Unit | Component | stats-time-series', function(hooks) {
});
});
- test('yFormat is percent-formatted', function(assert) {
+ test('yFormat is percent-formatted', function (assert) {
+ assert.expect(11);
+
const chart = this.createComponent({ data: wideData });
- wideData.forEach(datum => {
- assert.equal(chart.yFormat(datum.percent), d3Format.format('.1~%')(datum.percent));
+ wideData.forEach((datum) => {
+ assert.equal(
+ chart.yFormat(datum.percent),
+ d3Format.format('.1~%')(datum.percent)
+ );
});
});
- test('x scale domain is at least five minutes', function(assert) {
+ test('x scale domain is at least five minutes', function (assert) {
const chart = this.createComponent({ data: narrowData });
assert.equal(
@@ -78,7 +83,7 @@ module('Unit | Component | stats-time-series', function(hooks) {
);
});
- test('x scale domain is greater than five minutes when the domain of the data is larger than five minutes', function(assert) {
+ test('x scale domain is greater than five minutes when the domain of the data is larger than five minutes', function (assert) {
const chart = this.createComponent({ data: wideData });
assert.equal(
@@ -88,11 +93,14 @@ module('Unit | Component | stats-time-series', function(hooks) {
);
});
- test('y scale domain is typically 0 to 1 (0 to 100%)', function(assert) {
+ test('y scale domain is typically 0 to 1 (0 to 100%)', function (assert) {
const chart = this.createComponent({ data: wideData });
assert.deepEqual(
- [Math.min(...wideData.mapBy('percent')), Math.max(...wideData.mapBy('percent'))],
+ [
+ Math.min(...wideData.mapBy('percent')),
+ Math.max(...wideData.mapBy('percent')),
+ ],
[0.3, 0.9],
'The bounds of the value prop of the dataset is narrower than 0 - 1'
);
@@ -104,7 +112,7 @@ module('Unit | Component | stats-time-series', function(hooks) {
);
});
- test('the extent of the y domain overrides the default 0 to 1 domain when there are values beyond these bounds', function(assert) {
+ test('the extent of the y domain overrides the default 0 to 1 domain when there are values beyond these bounds', function (assert) {
const chart = this.createComponent({ data: unboundedData });
assert.deepEqual(
@@ -130,9 +138,13 @@ module('Unit | Component | stats-time-series', function(hooks) {
);
});
- test('when there are only empty frames in the data array, the default y domain is used', function(assert) {
+ test('when there are only empty frames in the data array, the default y domain is used', function (assert) {
const chart = this.createComponent({ data: nullData });
- assert.deepEqual(chart.yScale(nullData, 0).domain(), [0, 1], 'The bounds are 0 and 1');
+ assert.deepEqual(
+ chart.yScale(nullData, 0).domain(),
+ [0, 1],
+ 'The bounds are 0 and 1'
+ );
});
});
diff --git a/ui/tests/unit/components/tooltip-test.js b/ui/tests/unit/components/tooltip-test.js
index e66f5a4e0..5bdc14892 100644
--- a/ui/tests/unit/components/tooltip-test.js
+++ b/ui/tests/unit/components/tooltip-test.js
@@ -2,12 +2,14 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
-module('Unit | Component | tooltip', function(hooks) {
+module('Unit | Component | tooltip', function (hooks) {
setupTest(hooks);
setupGlimmerComponentFactory(hooks, 'tooltip');
- test('long texts are ellipsised in the middle', function(assert) {
- const tooltip = this.createComponent({ text: 'reeeeeeeeeeeeeeeeeally long text' });
+ test('long texts are ellipsised in the middle', function (assert) {
+ const tooltip = this.createComponent({
+ text: 'reeeeeeeeeeeeeeeeeally long text',
+ });
assert.equal(tooltip.text, 'reeeeeeeeeeeeee...long text');
});
});
diff --git a/ui/tests/unit/components/topo-viz-test.js b/ui/tests/unit/components/topo-viz-test.js
index 3568170ef..b6a2b82e6 100644
--- a/ui/tests/unit/components/topo-viz-test.js
+++ b/ui/tests/unit/components/topo-viz-test.js
@@ -2,11 +2,11 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import setupGlimmerComponentFactory from 'nomad-ui/tests/helpers/glimmer-factory';
-module('Unit | Component | TopoViz', function(hooks) {
+module('Unit | Component | TopoViz', function (hooks) {
setupTest(hooks);
setupGlimmerComponentFactory(hooks, 'topo-viz');
- test('the topology object properly organizes a tree of datacenters > nodes > allocations', async function(assert) {
+ test('the topology object properly organizes a tree of datacenters > nodes > allocations', async function (assert) {
const nodes = [
{ datacenter: 'dc1', id: 'node0', resources: {} },
{ datacenter: 'dc2', id: 'node1', resources: {} },
@@ -32,9 +32,17 @@ module('Unit | Component | TopoViz', function(hooks) {
topoViz.buildTopology();
- assert.deepEqual(topoViz.topology.datacenters.mapBy('name'), ['dc1', 'dc2']);
- assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [nodes[0], nodes[2]]);
- assert.deepEqual(topoViz.topology.datacenters[1].nodes.mapBy('node'), [nodes[1]]);
+ assert.deepEqual(topoViz.topology.datacenters.mapBy('name'), [
+ 'dc1',
+ 'dc2',
+ ]);
+ assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [
+ nodes[0],
+ nodes[2],
+ ]);
+ assert.deepEqual(topoViz.topology.datacenters[1].nodes.mapBy('node'), [
+ nodes[1],
+ ]);
assert.deepEqual(
topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'),
node0Allocs
@@ -49,7 +57,9 @@ module('Unit | Component | TopoViz', function(hooks) {
);
});
- test('the topology object contains an allocation index keyed by jobId+taskGroupName', async function(assert) {
+ test('the topology object contains an allocation index keyed by jobId+taskGroupName', async function (assert) {
+ assert.expect(7);
+
const allocations = [
alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
alloc({ nodeId: 'node0', jobId: 'job0', taskGroupName: 'one' }),
@@ -82,16 +92,18 @@ module('Unit | Component | TopoViz', function(hooks) {
].sort()
);
- Object.keys(topoViz.topology.allocationIndex).forEach(key => {
+ Object.keys(topoViz.topology.allocationIndex).forEach((key) => {
const [jobId, group] = JSON.parse(key);
assert.deepEqual(
topoViz.topology.allocationIndex[key].mapBy('allocation'),
- allocations.filter(alloc => alloc.jobId === jobId && alloc.taskGroupName === group)
+ allocations.filter(
+ (alloc) => alloc.jobId === jobId && alloc.taskGroupName === group
+ )
);
});
});
- test('isSingleColumn is true when there is only one datacenter', async function(assert) {
+ test('isSingleColumn is true when there is only one datacenter', async function (assert) {
const oneDc = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
const twoDc = [...oneDc, { datacenter: 'dc2', id: 'node1', resources: {} }];
@@ -105,7 +117,7 @@ module('Unit | Component | TopoViz', function(hooks) {
assert.notOk(topoViz2.isSingleColumn);
});
- test('isSingleColumn is true when there are multiple datacenters with a high variance in node count', async function(assert) {
+ test('isSingleColumn is true when there are multiple datacenters with a high variance in node count', async function (assert) {
const uniformDcs = [
{ datacenter: 'dc1', id: 'node0', resources: {} },
{ datacenter: 'dc2', id: 'node1', resources: {} },
@@ -118,8 +130,14 @@ module('Unit | Component | TopoViz', function(hooks) {
{ datacenter: 'dc2', id: 'node4', resources: {} },
];
- const twoColumnViz = this.createComponent({ nodes: uniformDcs, allocations: [] });
- const oneColumViz = this.createComponent({ nodes: skewedDcs, allocations: [] });
+ const twoColumnViz = this.createComponent({
+ nodes: uniformDcs,
+ allocations: [],
+ });
+ const oneColumViz = this.createComponent({
+ nodes: skewedDcs,
+ allocations: [],
+ });
twoColumnViz.buildTopology();
oneColumViz.buildTopology();
@@ -128,7 +146,7 @@ module('Unit | Component | TopoViz', function(hooks) {
assert.ok(oneColumViz.isSingleColumn);
});
- test('datacenterIsSingleColumn is only ever false when isSingleColumn is false and the total node count is high', async function(assert) {
+ test('datacenterIsSingleColumn is only ever false when isSingleColumn is false and the total node count is high', async function (assert) {
const manyUniformNodes = Array(25)
.fill(null)
.map((_, index) => ({
@@ -144,8 +162,14 @@ module('Unit | Component | TopoViz', function(hooks) {
resources: {},
}));
- const oneColumnViz = this.createComponent({ nodes: manyUniformNodes, allocations: [] });
- const twoColumnViz = this.createComponent({ nodes: manySkewedNodes, allocations: [] });
+ const oneColumnViz = this.createComponent({
+ nodes: manyUniformNodes,
+ allocations: [],
+ });
+ const twoColumnViz = this.createComponent({
+ nodes: manySkewedNodes,
+ allocations: [],
+ });
oneColumnViz.buildTopology();
twoColumnViz.buildTopology();
@@ -157,8 +181,10 @@ module('Unit | Component | TopoViz', function(hooks) {
assert.ok(twoColumnViz.isSingleColumn);
});
- test('dataForAllocation correctly calculates proportion of node utilization and group key', async function(assert) {
- const nodes = [{ datacenter: 'dc1', id: 'node0', resources: { cpu: 100, memory: 250 } }];
+ test('dataForAllocation correctly calculates proportion of node utilization and group key', async function (assert) {
+ const nodes = [
+ { datacenter: 'dc1', id: 'node0', resources: { cpu: 100, memory: 250 } },
+ ];
const allocations = [
alloc({
nodeId: 'node0',
@@ -171,11 +197,17 @@ module('Unit | Component | TopoViz', function(hooks) {
const topoViz = this.createComponent({ nodes, allocations });
topoViz.buildTopology();
- assert.equal(topoViz.topology.datacenters[0].nodes[0].allocations[0].cpuPercent, 0.5);
- assert.equal(topoViz.topology.datacenters[0].nodes[0].allocations[0].memoryPercent, 0.1);
+ assert.equal(
+ topoViz.topology.datacenters[0].nodes[0].allocations[0].cpuPercent,
+ 0.5
+ );
+ assert.equal(
+ topoViz.topology.datacenters[0].nodes[0].allocations[0].memoryPercent,
+ 0.1
+ );
});
- test('allocations that reference nonexistent nodes are ignored', async function(assert) {
+ test('allocations that reference nonexistent nodes are ignored', async function (assert) {
const nodes = [{ datacenter: 'dc1', id: 'node0', resources: {} }];
const allocations = [
@@ -187,10 +219,13 @@ module('Unit | Component | TopoViz', function(hooks) {
topoViz.buildTopology();
- assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [nodes[0]]);
- assert.deepEqual(topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'), [
- allocations[0],
+ assert.deepEqual(topoViz.topology.datacenters[0].nodes.mapBy('node'), [
+ nodes[0],
]);
+ assert.deepEqual(
+ topoViz.topology.datacenters[0].nodes[0].allocations.mapBy('allocation'),
+ [allocations[0]]
+ );
});
});
diff --git a/ui/tests/unit/mixins/searchable-test.js b/ui/tests/unit/mixins/searchable-test.js
index 5dbc4eaf8..feeb1b66a 100644
--- a/ui/tests/unit/mixins/searchable-test.js
+++ b/ui/tests/unit/mixins/searchable-test.js
@@ -4,15 +4,15 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import Searchable from 'nomad-ui/mixins/searchable';
-module('Unit | Mixin | Searchable', function(hooks) {
+module('Unit | Mixin | Searchable', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
- this.subject = function() {
+ hooks.beforeEach(function () {
+ this.subject = function () {
// eslint-disable-next-line ember/no-new-mixins
const SearchableObject = EmberObject.extend(Searchable, {
source: null,
- searchProps: computed(function() {
+ searchProps: computed(function () {
return ['id', 'name'];
}),
listToSearch: alias('source'),
@@ -23,14 +23,17 @@ module('Unit | Mixin | Searchable', function(hooks) {
};
});
- test('the searchable mixin does nothing when there is no search term', function(assert) {
+ test('the searchable mixin does nothing when there is no search term', function (assert) {
const subject = this.subject();
- subject.set('source', [{ id: '1', name: 'hello' }, { id: '2', name: 'world' }]);
+ subject.set('source', [
+ { id: '1', name: 'hello' },
+ { id: '2', name: 'world' },
+ ]);
assert.deepEqual(subject.get('listSearched'), subject.get('source'));
});
- test('the searchable mixin allows for regex search', function(assert) {
+ test('the searchable mixin allows for regex search', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'hello' },
@@ -41,12 +44,15 @@ module('Unit | Mixin | Searchable', function(hooks) {
subject.set('searchTerm', '.+l+[A-Z]$');
assert.deepEqual(
subject.get('listSearched'),
- [{ id: '1', name: 'hello' }, { id: '2', name: 'world' }],
+ [
+ { id: '1', name: 'hello' },
+ { id: '2', name: 'world' },
+ ],
'hello and world matched for regex'
);
});
- test('the searchable mixin only searches the declared search props', function(assert) {
+ test('the searchable mixin only searches the declared search props', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -57,12 +63,18 @@ module('Unit | Mixin | Searchable', function(hooks) {
subject.set('searchTerm', 'America');
assert.deepEqual(
subject.get('listSearched'),
- [{ id: '1', name: 'United States of America', continent: 'North America' }],
+ [
+ {
+ id: '1',
+ name: 'United States of America',
+ continent: 'North America',
+ },
+ ],
'Only USA matched, since continent is not a search prop'
);
});
- test('the fuzzy search mode is off by default', function(assert) {
+ test('the fuzzy search mode is off by default', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -78,7 +90,7 @@ module('Unit | Mixin | Searchable', function(hooks) {
);
});
- test('the fuzzy search mode can be enabled', function(assert) {
+ test('the fuzzy search mode can be enabled', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -90,17 +102,35 @@ module('Unit | Mixin | Searchable', function(hooks) {
subject.set('searchTerm', 'Ameerica');
assert.deepEqual(
subject.get('listSearched'),
- [{ id: '1', name: 'United States of America', continent: 'North America' }],
+ [
+ {
+ id: '1',
+ name: 'United States of America',
+ continent: 'North America',
+ },
+ ],
'America is matched due to fuzzy matching'
);
});
- test('the fuzzy search can include match results', function(assert) {
+ test('the fuzzy search can include match results', function (assert) {
const subject = this.subject();
subject.set('source', [
- EmberObject.create({ id: '1', name: 'United States of America', continent: 'North America' }),
- EmberObject.create({ id: '2', name: 'Canada', continent: 'North America' }),
- EmberObject.create({ id: '3', name: 'Mexico', continent: 'North America' }),
+ EmberObject.create({
+ id: '1',
+ name: 'United States of America',
+ continent: 'North America',
+ }),
+ EmberObject.create({
+ id: '2',
+ name: 'Canada',
+ continent: 'North America',
+ }),
+ EmberObject.create({
+ id: '3',
+ name: 'Mexico',
+ continent: 'North America',
+ }),
]);
subject.set('fuzzySearchEnabled', true);
@@ -109,7 +139,9 @@ module('Unit | Mixin | Searchable', function(hooks) {
assert.deepEqual(
subject
.get('listSearched')
- .map(object => object.getProperties('id', 'name', 'continent', 'fuzzySearchMatches')),
+ .map((object) =>
+ object.getProperties('id', 'name', 'continent', 'fuzzySearchMatches')
+ ),
[
{
id: '1',
@@ -117,7 +149,13 @@ module('Unit | Mixin | Searchable', function(hooks) {
continent: 'North America',
fuzzySearchMatches: [
{
- indices: [[2, 2], [4, 4], [9, 9], [11, 11], [17, 23]],
+ indices: [
+ [2, 2],
+ [4, 4],
+ [9, 9],
+ [11, 11],
+ [17, 23],
+ ],
value: 'United States of America',
key: 'name',
},
@@ -128,7 +166,7 @@ module('Unit | Mixin | Searchable', function(hooks) {
);
});
- test('the exact match search mode can be disabled', function(assert) {
+ test('the exact match search mode can be disabled', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -154,7 +192,7 @@ module('Unit | Mixin | Searchable', function(hooks) {
);
});
- test('the regex search mode can be disabled', function(assert) {
+ test('the regex search mode can be disabled', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -181,7 +219,7 @@ module('Unit | Mixin | Searchable', function(hooks) {
);
});
- test('each search mode has independent search props', function(assert) {
+ test('each search mode has independent search props', function (assert) {
const subject = this.subject();
subject.set('source', [
{ id: '1', name: 'United States of America', continent: 'North America' },
@@ -204,7 +242,13 @@ module('Unit | Mixin | Searchable', function(hooks) {
subject.set('searchTerm', 'America States');
assert.deepEqual(
subject.get('listSearched'),
- [{ id: '1', name: 'United States of America', continent: 'North America' }],
+ [
+ {
+ id: '1',
+ name: 'United States of America',
+ continent: 'North America',
+ },
+ ],
'Fuzzy match on one country, but not an exact match on continent'
);
@@ -216,38 +260,53 @@ module('Unit | Mixin | Searchable', function(hooks) {
);
});
- test('the resetPagination method is a no-op', function(assert) {
+ test('the resetPagination method is a no-op', function (assert) {
const subject = this.subject();
- assert.strictEqual(subject.get('currentPage'), undefined, 'No currentPage value set');
+ assert.strictEqual(
+ subject.get('currentPage'),
+ undefined,
+ 'No currentPage value set'
+ );
subject.resetPagination();
- assert.strictEqual(subject.get('currentPage'), undefined, 'Still no currentPage value set');
+ assert.strictEqual(
+ subject.get('currentPage'),
+ undefined,
+ 'Still no currentPage value set'
+ );
});
});
-module('Unit | Mixin | Searchable (with pagination)', function(hooks) {
+module('Unit | Mixin | Searchable (with pagination)', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
- this.subject = function() {
+ hooks.beforeEach(function () {
+ this.subject = function () {
// eslint-disable-next-line ember/no-new-mixins
const SearchablePaginatedObject = EmberObject.extend(Searchable, {
source: null,
- searchProps: computed(function() {
+ searchProps: computed(function () {
return ['id', 'name'];
}),
listToSearch: alias('source'),
currentPage: 1,
});
- this.owner.register('test-container:searchable-paginated-object', SearchablePaginatedObject);
+ this.owner.register(
+ 'test-container:searchable-paginated-object',
+ SearchablePaginatedObject
+ );
return this.owner.lookup('test-container:searchable-paginated-object');
};
});
- test('the resetPagination method sets the currentPage to 1', function(assert) {
+ test('the resetPagination method sets the currentPage to 1', function (assert) {
const subject = this.subject();
subject.set('currentPage', 5);
- assert.equal(subject.get('currentPage'), 5, 'Current page is something other than 1');
+ assert.equal(
+ subject.get('currentPage'),
+ 5,
+ 'Current page is something other than 1'
+ );
subject.resetPagination();
assert.equal(subject.get('currentPage'), 1, 'Current page gets reset to 1');
});
diff --git a/ui/tests/unit/models/allocation-test.js b/ui/tests/unit/models/allocation-test.js
index dce5ed10d..a83ea2ca7 100644
--- a/ui/tests/unit/models/allocation-test.js
+++ b/ui/tests/unit/models/allocation-test.js
@@ -2,13 +2,13 @@ import { run } from '@ember/runloop';
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
-module('Unit | Model | allocation', function(hooks) {
+module('Unit | Model | allocation', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
});
- test("When the allocation's job version matches the job's version, the task group comes from the job.", function(assert) {
+ test("When the allocation's job version matches the job's version, the task group comes from the job.", function (assert) {
const job = run(() =>
this.store.createRecord('job', {
name: 'this-job',
@@ -39,7 +39,7 @@ module('Unit | Model | allocation', function(hooks) {
assert.equal(allocation.get('taskGroup.name'), 'from-job');
});
- test("When the allocation's job version does not match the job's version, the task group comes from the alloc.", function(assert) {
+ test("When the allocation's job version does not match the job's version, the task group comes from the alloc.", function (assert) {
const job = run(() =>
this.store.createRecord('job', {
name: 'this-job',
@@ -70,7 +70,7 @@ module('Unit | Model | allocation', function(hooks) {
assert.equal(allocation.get('taskGroup.name'), 'from-allocation');
});
- test("When the allocation's job version does not match the job's version and the allocation has no task group, then task group is null", async function(assert) {
+ test("When the allocation's job version does not match the job's version and the allocation has no task group, then task group is null", async function (assert) {
const job = run(() =>
this.store.createRecord('job', {
name: 'this-job',
diff --git a/ui/tests/unit/models/job-test.js b/ui/tests/unit/models/job-test.js
index d16f46f8f..bff37e302 100644
--- a/ui/tests/unit/models/job-test.js
+++ b/ui/tests/unit/models/job-test.js
@@ -2,10 +2,10 @@ import { run } from '@ember/runloop';
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
-module('Unit | Model | job', function(hooks) {
+module('Unit | Model | job', function (hooks) {
setupTest(hooks);
- test('should expose aggregate allocations derived from task groups', function(assert) {
+ test('should expose aggregate allocations derived from task groups', function (assert) {
const store = this.owner.lookup('service:store');
let summary;
run(() => {
diff --git a/ui/tests/unit/models/task-group-test.js b/ui/tests/unit/models/task-group-test.js
index 7ef246f2f..091bcd745 100644
--- a/ui/tests/unit/models/task-group-test.js
+++ b/ui/tests/unit/models/task-group-test.js
@@ -6,10 +6,10 @@ import { run } from '@ember/runloop';
const sum = (list, key) => list.reduce((sum, item) => sum + get(item, key), 0);
-module('Unit | Model | task-group', function(hooks) {
+module('Unit | Model | task-group', function (hooks) {
setupTest(hooks);
- test("should expose reserved resource stats as aggregates of each task's reserved resources", function(assert) {
+ test("should expose reserved resource stats as aggregates of each task's reserved resources", function (assert) {
const taskGroup = run(() =>
this.owner.lookup('service:store').createRecord('task-group', {
name: 'group-example',
@@ -63,13 +63,17 @@ module('Unit | Model | task-group', function(hooks) {
);
});
- test("should expose mergedMeta as merged with the job's meta", function(assert) {
+ test("should expose mergedMeta as merged with the job's meta", function (assert) {
+ assert.expect(8);
+
const store = this.owner.lookup('service:store');
const jobWithMeta = run(() =>
store.createRecord('job', {
name: 'example-with-meta',
- meta: store.createFragment('structured-attributes', { raw: { a: 'b' } }),
+ meta: store.createFragment('structured-attributes', {
+ raw: { a: 'b' },
+ }),
taskGroups: [
{
name: 'one',
@@ -93,10 +97,7 @@ module('Unit | Model | task-group', function(hooks) {
let expected = [{ a: 'b', c: 'd' }, { a: 'b' }, { a: 'b' }, { a: 'b' }];
expected.forEach((exp, i) => {
assert.deepEqual(
- jobWithMeta
- .get('taskGroups')
- .objectAt(i)
- .get('mergedMeta'),
+ jobWithMeta.get('taskGroups').objectAt(i).get('mergedMeta'),
exp,
'mergedMeta is merged with job meta'
);
@@ -128,10 +129,7 @@ module('Unit | Model | task-group', function(hooks) {
expected = [{ c: 'd' }, {}, {}, {}];
expected.forEach((exp, i) => {
assert.deepEqual(
- jobWithoutMeta
- .get('taskGroups')
- .objectAt(i)
- .get('mergedMeta'),
+ jobWithoutMeta.get('taskGroups').objectAt(i).get('mergedMeta'),
exp,
'mergedMeta is merged with job meta'
);
diff --git a/ui/tests/unit/models/task-test.js b/ui/tests/unit/models/task-test.js
index 43f719198..67a274bf9 100644
--- a/ui/tests/unit/models/task-test.js
+++ b/ui/tests/unit/models/task-test.js
@@ -3,10 +3,12 @@ import { setupTest } from 'ember-qunit';
import { run } from '@ember/runloop';
-module('Unit | Model | task', function(hooks) {
+module('Unit | Model | task', function (hooks) {
setupTest(hooks);
- test("should expose mergedMeta as merged with the job's and task groups's meta", function(assert) {
+ test("should expose mergedMeta as merged with the job's and task groups's meta", function (assert) {
+ assert.expect(8);
+
const job = run(() =>
this.owner.lookup('service:store').createRecord('job', {
name: 'example',
@@ -61,10 +63,7 @@ module('Unit | Model | task', function(hooks) {
expected.forEach((exp, i) => {
assert.deepEqual(
- tg
- .get('tasks')
- .objectAt(i)
- .get('mergedMeta'),
+ tg.get('tasks').objectAt(i).get('mergedMeta'),
exp,
'mergedMeta is merged with task meta'
);
@@ -75,10 +74,7 @@ module('Unit | Model | task', function(hooks) {
expected.forEach((exp, i) => {
assert.deepEqual(
- tg
- .get('tasks')
- .objectAt(i)
- .get('mergedMeta'),
+ tg.get('tasks').objectAt(i).get('mergedMeta'),
exp,
'mergedMeta is merged with job meta'
);
diff --git a/ui/tests/unit/serializers/allocation-test.js b/ui/tests/unit/serializers/allocation-test.js
index 5250d8336..7aa28f72d 100644
--- a/ui/tests/unit/serializers/allocation-test.js
+++ b/ui/tests/unit/serializers/allocation-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import AllocationModel from 'nomad-ui/models/allocation';
-module('Unit | Serializer | Allocation', function(hooks) {
+module('Unit | Serializer | Allocation', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('allocation');
});
@@ -165,7 +165,10 @@ module('Unit | Serializer | Allocation', function(hooks) {
},
},
PreemptedByAllocation: 'preempter-allocation',
- PreemptedAllocations: ['preempted-one-allocation', 'preempted-two-allocation'],
+ PreemptedAllocations: [
+ 'preempted-one-allocation',
+ 'preempted-two-allocation',
+ ],
},
out: {
data: {
@@ -382,9 +385,12 @@ module('Unit | Serializer | Allocation', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(AllocationModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(AllocationModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/application-test.js b/ui/tests/unit/serializers/application-test.js
index 49cacd19b..b1f01389c 100644
--- a/ui/tests/unit/serializers/application-test.js
+++ b/ui/tests/unit/serializers/application-test.js
@@ -10,7 +10,10 @@ class TestSerializer extends ApplicationSerializer {
mapToArray = [
'ArrayableMap',
- { beforeName: 'OriginalNameArrayableMap', afterName: 'RenamedArrayableMap' },
+ {
+ beforeName: 'OriginalNameArrayableMap',
+ afterName: 'RenamedArrayableMap',
+ },
];
separateNanos = ['Time'];
@@ -26,10 +29,10 @@ class TestModel extends Model {
@attr() timeNanos;
}
-module('Unit | Serializer | Application', function(hooks) {
+module('Unit | Serializer | Application', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.owner.register('model:test', TestModel);
this.owner.register('serializer:test', TestSerializer);
@@ -99,9 +102,12 @@ module('Unit | Serializer | Application', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(TestModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(TestModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/deployment-test.js b/ui/tests/unit/serializers/deployment-test.js
index faebc9b66..25afe6ce5 100644
--- a/ui/tests/unit/serializers/deployment-test.js
+++ b/ui/tests/unit/serializers/deployment-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import DeploymentModel from 'nomad-ui/models/deployment';
-module('Unit | Serializer | Deployment', function(hooks) {
+module('Unit | Serializer | Deployment', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('deployment');
});
@@ -119,9 +119,12 @@ module('Unit | Serializer | Deployment', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(DeploymentModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(DeploymentModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/evaluation-test.js b/ui/tests/unit/serializers/evaluation-test.js
index 053828acd..6e17427eb 100644
--- a/ui/tests/unit/serializers/evaluation-test.js
+++ b/ui/tests/unit/serializers/evaluation-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import EvaluationModel from 'nomad-ui/models/evaluation';
-module('Unit | Serializer | Evaluation', function(hooks) {
+module('Unit | Serializer | Evaluation', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('evaluation');
});
@@ -103,9 +103,12 @@ module('Unit | Serializer | Evaluation', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(EvaluationModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(EvaluationModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/job-plan-test.js b/ui/tests/unit/serializers/job-plan-test.js
index 994f811c2..f9e48c86f 100644
--- a/ui/tests/unit/serializers/job-plan-test.js
+++ b/ui/tests/unit/serializers/job-plan-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import JobPlanModel from 'nomad-ui/models/job-plan';
-module('Unit | Serializer | JobPlan', function(hooks) {
+module('Unit | Serializer | JobPlan', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('job-plan');
});
@@ -138,9 +138,12 @@ module('Unit | Serializer | JobPlan', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(JobPlanModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(JobPlanModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/job-summary-test.js b/ui/tests/unit/serializers/job-summary-test.js
index 94ef7e2ac..33d656099 100644
--- a/ui/tests/unit/serializers/job-summary-test.js
+++ b/ui/tests/unit/serializers/job-summary-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import JobSummaryModel from 'nomad-ui/models/job-summary';
-module('Unit | Serializer | JobSummary', function(hooks) {
+module('Unit | Serializer | JobSummary', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('job-summary');
});
@@ -94,9 +94,12 @@ module('Unit | Serializer | JobSummary', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(JobSummaryModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(JobSummaryModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/job-test.js b/ui/tests/unit/serializers/job-test.js
index ab2b393cd..6852da08b 100644
--- a/ui/tests/unit/serializers/job-test.js
+++ b/ui/tests/unit/serializers/job-test.js
@@ -2,14 +2,14 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import JobModel from 'nomad-ui/models/job';
-module('Unit | Serializer | Job', function(hooks) {
+module('Unit | Serializer | Job', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('job');
});
- test('`default` is used as the namespace in the job ID when there is no namespace in the payload', async function(assert) {
+ test('`default` is used as the namespace in the job ID when there is no namespace in the payload', async function (assert) {
const original = {
ID: 'example',
Name: 'example',
@@ -19,7 +19,7 @@ module('Unit | Serializer | Job', function(hooks) {
assert.equal(data.id, JSON.stringify([data.attributes.name, 'default']));
});
- test('The ID of the record is a composite of both the name and the namespace', async function(assert) {
+ test('The ID of the record is a composite of both the name and the namespace', async function (assert) {
const original = {
ID: 'example',
Name: 'example',
@@ -29,7 +29,10 @@ module('Unit | Serializer | Job', function(hooks) {
const { data } = this.subject().normalize(JobModel, original);
assert.equal(
data.id,
- JSON.stringify([data.attributes.name, data.relationships.namespace.data.id])
+ JSON.stringify([
+ data.attributes.name,
+ data.relationships.namespace.data.id,
+ ])
);
});
});
diff --git a/ui/tests/unit/serializers/network-test.js b/ui/tests/unit/serializers/network-test.js
index 8c5d614de..424538554 100644
--- a/ui/tests/unit/serializers/network-test.js
+++ b/ui/tests/unit/serializers/network-test.js
@@ -2,14 +2,14 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import NetworkModel from 'nomad-ui/models/network';
-module('Unit | Serializer | Network', function(hooks) {
+module('Unit | Serializer | Network', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('network');
});
- test('v4 IPs are passed through', async function(assert) {
+ test('v4 IPs are passed through', async function (assert) {
const ip = '10.0.13.12';
const original = {
IP: ip,
@@ -19,7 +19,7 @@ module('Unit | Serializer | Network', function(hooks) {
assert.equal(data.attributes.ip, ip);
});
- test('v6 IPs are wrapped in square brackets', async function(assert) {
+ test('v6 IPs are wrapped in square brackets', async function (assert) {
const ip = '2001:0dac:aba3:0000:0000:8a2e:0370:7334';
const original = {
IP: ip,
diff --git a/ui/tests/unit/serializers/node-test.js b/ui/tests/unit/serializers/node-test.js
index 2df5fb18b..70ad13125 100644
--- a/ui/tests/unit/serializers/node-test.js
+++ b/ui/tests/unit/serializers/node-test.js
@@ -5,21 +5,25 @@ import NodeModel from 'nomad-ui/models/node';
import pushPayloadToStore from '../../utils/push-payload-to-store';
import { settled } from '@ember/test-helpers';
-module('Unit | Serializer | Node', function(hooks) {
+module('Unit | Serializer | Node', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('node');
});
- test('local store is culled to reflect the state of findAll requests', async function(assert) {
+ test('local store is culled to reflect the state of findAll requests', async function (assert) {
const findAllResponse = [
makeNode('1', 'One', '127.0.0.1:4646'),
makeNode('2', 'Two', '127.0.0.2:4646'),
makeNode('3', 'Three', '127.0.0.3:4646'),
];
- const payload = this.subject().normalizeFindAllResponse(this.store, NodeModel, findAllResponse);
+ const payload = this.subject().normalizeFindAllResponse(
+ this.store,
+ NodeModel,
+ findAllResponse
+ );
pushPayloadToStore(this.store, payload, NodeModel.modelName);
assert.equal(
@@ -29,10 +33,7 @@ module('Unit | Serializer | Node', function(hooks) {
);
assert.equal(
- this.store
- .peekAll('node')
- .filterBy('id')
- .get('length'),
+ this.store.peekAll('node').filterBy('id').get('length'),
findAllResponse.length,
'Each original record is now in the store'
);
@@ -61,15 +62,15 @@ module('Unit | Serializer | Node', function(hooks) {
);
assert.equal(
- this.store
- .peekAll('node')
- .filterBy('id')
- .get('length'),
+ this.store.peekAll('node').filterBy('id').get('length'),
newFindAllResponse.length,
'The node length in the store reflects the new response'
);
- assert.notOk(this.store.peekAll('node').findBy('id', '1'), 'Record One is no longer found');
+ assert.notOk(
+ this.store.peekAll('node').findBy('id', '1'),
+ 'Record One is no longer found'
+ );
});
function makeNode(id, name, ip) {
@@ -114,7 +115,10 @@ module('Unit | Serializer | Node', function(hooks) {
healthy: false,
},
],
- hostVolumes: [{ name: 'one', readOnly: true }, { name: 'two', readOnly: false }],
+ hostVolumes: [
+ { name: 'one', readOnly: true },
+ { name: 'two', readOnly: false },
+ ],
},
relationships: {
allocations: {
@@ -203,9 +207,12 @@ module('Unit | Serializer | Node', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(NodeModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(NodeModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/recommendation-summary-test.js b/ui/tests/unit/serializers/recommendation-summary-test.js
index fd7683279..e18677536 100644
--- a/ui/tests/unit/serializers/recommendation-summary-test.js
+++ b/ui/tests/unit/serializers/recommendation-summary-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import RecommendationSummaryModel from 'nomad-ui/models/recommendation-summary';
-module('Unit | Serializer | RecommendationSummary', function(hooks) {
+module('Unit | Serializer | RecommendationSummary', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('recommendation-summary');
});
@@ -202,10 +202,14 @@ module('Unit | Serializer | RecommendationSummary', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
assert.deepEqual(
- this.subject().normalizeArrayResponse(this.store, RecommendationSummaryModel, testCase.in),
+ this.subject().normalizeArrayResponse(
+ this.store,
+ RecommendationSummaryModel,
+ testCase.in
+ ),
testCase.out
);
});
diff --git a/ui/tests/unit/serializers/scale-event-test.js b/ui/tests/unit/serializers/scale-event-test.js
index c6d8c1806..4946d32b9 100644
--- a/ui/tests/unit/serializers/scale-event-test.js
+++ b/ui/tests/unit/serializers/scale-event-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import ScaleEventModel from 'nomad-ui/models/scale-event';
-module('Unit | Serializer | Scale Event', function(hooks) {
+module('Unit | Serializer | Scale Event', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('scale-event');
});
@@ -79,9 +79,12 @@ module('Unit | Serializer | Scale Event', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(ScaleEventModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(ScaleEventModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/serializers/volume-test.js b/ui/tests/unit/serializers/volume-test.js
index 792538fc7..ab2d68b4c 100644
--- a/ui/tests/unit/serializers/volume-test.js
+++ b/ui/tests/unit/serializers/volume-test.js
@@ -2,9 +2,9 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import VolumeModel from 'nomad-ui/models/volume';
-module('Unit | Serializer | Volume', function(hooks) {
+module('Unit | Serializer | Volume', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
this.store = this.owner.lookup('service:store');
this.subject = () => this.store.serializerFor('volume');
});
@@ -16,8 +16,7 @@ module('Unit | Serializer | Volume', function(hooks) {
const normalizationTestCases = [
{
- name:
- '`default` is used as the namespace in the volume ID when there is no namespace in the payload',
+ name: '`default` is used as the namespace in the volume ID when there is no namespace in the payload',
in: {
ID: 'volume-id',
Name: 'volume-id',
@@ -152,8 +151,7 @@ module('Unit | Serializer | Volume', function(hooks) {
},
{
- name:
- 'Allocations are interpreted as embedded records and are properly normalized into included resources in a JSON API shape',
+ name: 'Allocations are interpreted as embedded records and are properly normalized into included resources in a JSON API shape',
in: {
ID: 'volume-id',
Name: 'volume-id',
@@ -358,9 +356,12 @@ module('Unit | Serializer | Volume', function(hooks) {
},
];
- normalizationTestCases.forEach(testCase => {
- test(`normalization: ${testCase.name}`, async function(assert) {
- assert.deepEqual(this.subject().normalize(VolumeModel, testCase.in), testCase.out);
+ normalizationTestCases.forEach((testCase) => {
+ test(`normalization: ${testCase.name}`, async function (assert) {
+ assert.deepEqual(
+ this.subject().normalize(VolumeModel, testCase.in),
+ testCase.out
+ );
});
});
});
diff --git a/ui/tests/unit/services/stats-trackers-registry-test.js b/ui/tests/unit/services/stats-trackers-registry-test.js
index 8a700eab4..b4746dc49 100644
--- a/ui/tests/unit/services/stats-trackers-registry-test.js
+++ b/ui/tests/unit/services/stats-trackers-registry-test.js
@@ -8,16 +8,16 @@ import sinon from 'sinon';
import fetch from 'nomad-ui/utils/fetch';
import NodeStatsTracker from 'nomad-ui/utils/classes/node-stats-tracker';
-module('Unit | Service | Stats Trackers Registry', function(hooks) {
+module('Unit | Service | Stats Trackers Registry', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
- this.subject = function() {
+ hooks.beforeEach(function () {
+ this.subject = function () {
return this.owner.factoryFor('service:stats-trackers-registry').create();
};
});
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
// Inject a mock token service
const authorizedRequestSpy = (this.tokenAuthorizedRequestSpy = sinon.spy());
const mockToken = Service.extend({
@@ -29,7 +29,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
this.owner.register('service:token', mockToken);
this.token = this.owner.lookup('service:token');
- this.server = new Pretender(function() {
+ this.server = new Pretender(function () {
this.get('/v1/client/stats', () => [
200,
{},
@@ -44,7 +44,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
});
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
@@ -56,15 +56,26 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
const mockNode = makeModelMock('node', { id: 'test' });
- test('Creates a tracker when one isn’t found', function(assert) {
+ test('Creates a tracker when one isn’t found', function (assert) {
const registry = this.subject();
const id = 'id';
- assert.equal(registry.get('registryRef').size, 0, 'Nothing in the registry yet');
+ assert.equal(
+ registry.get('registryRef').size,
+ 0,
+ 'Nothing in the registry yet'
+ );
const tracker = registry.getTracker(mockNode.create({ id }));
- assert.ok(tracker instanceof NodeStatsTracker, 'The correct type of tracker is made');
- assert.equal(registry.get('registryRef').size, 1, 'The tracker was added to the registry');
+ assert.ok(
+ tracker instanceof NodeStatsTracker,
+ 'The correct type of tracker is made'
+ );
+ assert.equal(
+ registry.get('registryRef').size,
+ 1,
+ 'The tracker was added to the registry'
+ );
assert.deepEqual(
Array.from(registry.get('registryRef').keys()),
[`node:${id}`],
@@ -72,18 +83,26 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
);
});
- test('Returns an existing tracker when one is found', function(assert) {
+ test('Returns an existing tracker when one is found', function (assert) {
const registry = this.subject();
const node = mockNode.create();
const tracker1 = registry.getTracker(node);
const tracker2 = registry.getTracker(node);
- assert.equal(tracker1, tracker2, 'Returns an existing tracker for the same resource');
- assert.equal(registry.get('registryRef').size, 1, 'Only one tracker in the registry');
+ assert.equal(
+ tracker1,
+ tracker2,
+ 'Returns an existing tracker for the same resource'
+ );
+ assert.equal(
+ registry.get('registryRef').size,
+ 1,
+ 'Only one tracker in the registry'
+ );
});
- test('Registry does not depend on persistent object references', function(assert) {
+ test('Registry does not depend on persistent object references', function (assert) {
const registry = this.subject();
const id = 'some-id';
@@ -98,11 +117,19 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
'And the same className'
);
- assert.equal(registry.getTracker(node1), registry.getTracker(node2), 'Return the same tracker');
- assert.equal(registry.get('registryRef').size, 1, 'Only one tracker in the registry');
+ assert.equal(
+ registry.getTracker(node1),
+ registry.getTracker(node2),
+ 'Return the same tracker'
+ );
+ assert.equal(
+ registry.get('registryRef').size,
+ 1,
+ 'Only one tracker in the registry'
+ );
});
- test('Has a max size', function(assert) {
+ test('Has a max size', function (assert) {
const registry = this.subject();
const ref = registry.get('registryRef');
@@ -111,7 +138,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
assert.ok(ref.limit < Infinity, `A limit (${ref.limit}) is set`);
});
- test('Registry re-attaches deleted resources to cached trackers', function(assert) {
+ test('Registry re-attaches deleted resources to cached trackers', function (assert) {
const registry = this.subject();
const id = 'some-id';
@@ -131,7 +158,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
);
});
- test('Registry re-attaches destroyed resources to cached trackers', async function(assert) {
+ test('Registry re-attaches destroyed resources to cached trackers', async function (assert) {
const registry = this.subject();
const id = 'some-id';
@@ -154,7 +181,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
);
});
- test('Removes least recently used when something needs to be removed', function(assert) {
+ test('Removes least recently used when something needs to be removed', function (assert) {
const registry = this.subject();
const activeNode = mockNode.create({ id: 'active' });
const inactiveNode = mockNode.create({ id: 'inactive' });
@@ -186,7 +213,7 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
);
});
- test('Trackers are created using the token authorizedRequest', function(assert) {
+ test('Trackers are created using the token authorizedRequest', function (assert) {
const registry = this.subject();
const node = mockNode.create();
@@ -194,7 +221,9 @@ module('Unit | Service | Stats Trackers Registry', function(hooks) {
tracker.get('poll').perform();
assert.ok(
- this.tokenAuthorizedRequestSpy.calledWith(`/v1/client/stats?node_id=${node.get('id')}`),
+ this.tokenAuthorizedRequestSpy.calledWith(
+ `/v1/client/stats?node_id=${node.get('id')}`
+ ),
'The token service authorizedRequest function was used'
);
diff --git a/ui/tests/unit/services/token-test.js b/ui/tests/unit/services/token-test.js
index edf1bc266..a88e6f22c 100644
--- a/ui/tests/unit/services/token-test.js
+++ b/ui/tests/unit/services/token-test.js
@@ -3,16 +3,16 @@ import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import Pretender from 'pretender';
-module('Unit | Service | Token', function(hooks) {
+module('Unit | Service | Token', function (hooks) {
setupTest(hooks);
- hooks.beforeEach(function() {
- this.subject = function() {
+ hooks.beforeEach(function () {
+ this.subject = function () {
return this.owner.factoryFor('service:token').create();
};
});
- hooks.beforeEach(function() {
+ hooks.beforeEach(function () {
const mockSystem = Service.extend({
activeRegion: 'region-1',
shouldIncludeRegion: true,
@@ -21,16 +21,16 @@ module('Unit | Service | Token', function(hooks) {
this.owner.register('service:system', mockSystem);
this.system = this.owner.lookup('service:system');
- this.server = new Pretender(function() {
+ this.server = new Pretender(function () {
this.get('/path', () => [200, {}, null]);
});
});
- hooks.afterEach(function() {
+ hooks.afterEach(function () {
this.server.shutdown();
});
- test('authorizedRequest includes the region param when the system service says to', function(assert) {
+ test('authorizedRequest includes the region param when the system service says to', function (assert) {
const token = this.subject();
token.authorizedRequest('/path');
@@ -50,7 +50,7 @@ module('Unit | Service | Token', function(hooks) {
);
});
- test('authorizedRequest does not include the region param when the region param is already in the URL', function(assert) {
+ test('authorizedRequest does not include the region param when the region param is already in the URL', function (assert) {
const token = this.subject();
token.authorizedRequest('/path?query=param®ion=already-here');
@@ -61,7 +61,7 @@ module('Unit | Service | Token', function(hooks) {
);
});
- test('authorizedRawRequest bypasses adding the region param', function(assert) {
+ test('authorizedRawRequest bypasses adding the region param', function (assert) {
const token = this.subject();
token.authorizedRawRequest('/path');
diff --git a/ui/tests/unit/utils/add-to-path-test.js b/ui/tests/unit/utils/add-to-path-test.js
index 6317cfad0..e39822779 100644
--- a/ui/tests/unit/utils/add-to-path-test.js
+++ b/ui/tests/unit/utils/add-to-path-test.js
@@ -19,9 +19,9 @@ const testCases = [
},
];
-module('Unit | Util | addToPath', function() {
- testCases.forEach(testCase => {
- test(testCase.name, function(assert) {
+module('Unit | Util | addToPath', function () {
+ testCases.forEach((testCase) => {
+ test(testCase.name, function (assert) {
assert.equal(
addToPath.apply(null, testCase.in),
testCase.out,
diff --git a/ui/tests/unit/utils/allocation-stats-tracker-test.js b/ui/tests/unit/utils/allocation-stats-tracker-test.js
index 8858c1721..3c319f0ff 100644
--- a/ui/tests/unit/utils/allocation-stats-tracker-test.js
+++ b/ui/tests/unit/utils/allocation-stats-tracker-test.js
@@ -3,17 +3,19 @@ import { assign } from '@ember/polyfills';
import { module, test } from 'qunit';
import sinon from 'sinon';
import Pretender from 'pretender';
-import AllocationStatsTracker, { stats } from 'nomad-ui/utils/classes/allocation-stats-tracker';
+import AllocationStatsTracker, {
+ stats,
+} from 'nomad-ui/utils/classes/allocation-stats-tracker';
import fetch from 'nomad-ui/utils/fetch';
import statsTrackerFrameMissingBehavior from './behaviors/stats-tracker-frame-missing';
import { settled } from '@ember/test-helpers';
-module('Unit | Util | AllocationStatsTracker', function() {
+module('Unit | Util | AllocationStatsTracker', function () {
const refDate = Date.now() * 1000000;
- const makeDate = ts => new Date(ts / 1000000);
+ const makeDate = (ts) => new Date(ts / 1000000);
- const MockAllocation = overrides =>
+ const MockAllocation = (overrides) =>
assign(
{
id: 'some-identifier',
@@ -45,7 +47,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
overrides
);
- const mockFrame = step => ({
+ const mockFrame = (step) => ({
ResourceUsage: {
CpuStats: {
TotalTicks: step + 100,
@@ -92,7 +94,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
Timestamp: refDate + step * 1000,
});
- test('the AllocationStatsTracker constructor expects a fetch definition and an allocation', async function(assert) {
+ test('the AllocationStatsTracker constructor expects a fetch definition and an allocation', async function (assert) {
const tracker = AllocationStatsTracker.create();
assert.throws(
() => {
@@ -103,7 +105,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('the url property is computed based off the allocation id', async function(assert) {
+ test('the url property is computed based off the allocation id', async function (assert) {
const allocation = MockAllocation();
const tracker = AllocationStatsTracker.create({ fetch, allocation });
@@ -114,7 +116,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('reservedCPU and reservedMemory properties come from the allocation', async function(assert) {
+ test('reservedCPU and reservedMemory properties come from the allocation', async function (assert) {
const allocation = MockAllocation();
const tracker = AllocationStatsTracker.create({ fetch, allocation });
@@ -130,7 +132,9 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('the tasks list comes from the allocation', async function(assert) {
+ test('the tasks list comes from the allocation', async function (assert) {
+ assert.expect(7);
+
const allocation = MockAllocation();
const tracker = AllocationStatsTracker.create({ fetch, allocation });
@@ -139,9 +143,13 @@ module('Unit | Util | AllocationStatsTracker', function() {
allocation.taskGroup.tasks.length,
'tasks matches lengths with the allocation task group'
);
- allocation.taskGroup.tasks.forEach(task => {
+ allocation.taskGroup.tasks.forEach((task) => {
const trackerTask = tracker.get('tasks').findBy('task', task.name);
- assert.equal(trackerTask.reservedCPU, task.reservedCPU, `CPU matches for task ${task.name}`);
+ assert.equal(
+ trackerTask.reservedCPU,
+ task.reservedCPU,
+ `CPU matches for task ${task.name}`
+ );
assert.equal(
trackerTask.reservedMemory,
task.reservedMemory,
@@ -150,9 +158,13 @@ module('Unit | Util | AllocationStatsTracker', function() {
});
});
- test('poll results in requesting the url and calling append with the resulting JSON', async function(assert) {
+ test('poll results in requesting the url and calling append with the resulting JSON', async function (assert) {
const allocation = MockAllocation();
- const tracker = AllocationStatsTracker.create({ fetch, allocation, append: sinon.spy() });
+ const tracker = AllocationStatsTracker.create({
+ fetch,
+ allocation,
+ append: sinon.spy(),
+ });
const mockFrame = {
Some: {
data: ['goes', 'here'],
@@ -160,8 +172,12 @@ module('Unit | Util | AllocationStatsTracker', function() {
},
};
- const server = new Pretender(function() {
- this.get('/v1/client/allocation/:id/stats', () => [200, {}, JSON.stringify(mockFrame)]);
+ const server = new Pretender(function () {
+ this.get('/v1/client/allocation/:id/stats', () => [
+ 200,
+ {},
+ JSON.stringify(mockFrame),
+ ]);
});
tracker.get('poll').perform();
@@ -182,7 +198,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
server.shutdown();
});
- test('append appropriately maps a data frame to the tracked stats for cpu and memory for the allocation as well as individual tasks', async function(assert) {
+ test('append appropriately maps a data frame to the tracked stats for cpu and memory for the allocation as well as individual tasks', async function (assert) {
const allocation = MockAllocation();
const tracker = AllocationStatsTracker.create({ fetch, allocation });
@@ -192,9 +208,27 @@ module('Unit | Util | AllocationStatsTracker', function() {
assert.deepEqual(
tracker.get('tasks'),
[
- { task: 'service', reservedCPU: 100, reservedMemory: 256, cpu: [], memory: [] },
- { task: 'sidecar', reservedCPU: 50, reservedMemory: 128, cpu: [], memory: [] },
- { task: 'log-shipper', reservedCPU: 50, reservedMemory: 128, cpu: [], memory: [] },
+ {
+ task: 'service',
+ reservedCPU: 100,
+ reservedMemory: 256,
+ cpu: [],
+ memory: [],
+ },
+ {
+ task: 'sidecar',
+ reservedCPU: 50,
+ reservedMemory: 128,
+ cpu: [],
+ memory: [],
+ },
+ {
+ task: 'log-shipper',
+ reservedCPU: 50,
+ reservedMemory: 128,
+ cpu: [],
+ memory: [],
+ },
],
'tasks represents the tasks for the allocation with no stats yet'
);
@@ -307,8 +341,16 @@ module('Unit | Util | AllocationStatsTracker', function() {
assert.deepEqual(
tracker.get('memory'),
[
- { timestamp: makeDate(refDate + 1000), used: 401 * 1024 * 1024, percent: 401 / 512 },
- { timestamp: makeDate(refDate + 2000), used: 402 * 1024 * 1024, percent: 402 / 512 },
+ {
+ timestamp: makeDate(refDate + 1000),
+ used: 401 * 1024 * 1024,
+ percent: 401 / 512,
+ },
+ {
+ timestamp: makeDate(refDate + 2000),
+ used: 402 * 1024 * 1024,
+ percent: 402 / 512,
+ },
],
'Two frames of memory'
);
@@ -432,10 +474,16 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('each stat list has maxLength equal to bufferSize', async function(assert) {
+ test('each stat list has maxLength equal to bufferSize', async function (assert) {
+ assert.expect(16);
+
const allocation = MockAllocation();
const bufferSize = 10;
- const tracker = AllocationStatsTracker.create({ fetch, allocation, bufferSize });
+ const tracker = AllocationStatsTracker.create({
+ fetch,
+ allocation,
+ bufferSize,
+ });
for (let i = 1; i <= 20; i++) {
tracker.append(mockFrame(i));
@@ -463,7 +511,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
'Old frames are removed in favor of newer ones'
);
- tracker.get('tasks').forEach(task => {
+ tracker.get('tasks').forEach((task) => {
assert.equal(
task.cpu.length,
bufferSize,
@@ -510,12 +558,12 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('the stats computed property macro constructs an AllocationStatsTracker based on an allocationProp and a fetch definition', async function(assert) {
+ test('the stats computed property macro constructs an AllocationStatsTracker based on an allocationProp and a fetch definition', async function (assert) {
const allocation = MockAllocation();
const fetchSpy = sinon.spy();
const SomeClass = EmberObject.extend({
- stats: stats('alloc', function() {
+ stats: stats('alloc', function () {
return () => fetchSpy(this);
}),
});
@@ -537,7 +585,7 @@ module('Unit | Util | AllocationStatsTracker', function() {
);
});
- test('changing the value of the allocationProp constructs a new AllocationStatsTracker', async function(assert) {
+ test('changing the value of the allocationProp constructs a new AllocationStatsTracker', async function (assert) {
const alloc1 = MockAllocation();
const alloc2 = MockAllocation();
const SomeClass = EmberObject.extend({
@@ -553,8 +601,9 @@ module('Unit | Util | AllocationStatsTracker', function() {
someObject.set('alloc', alloc2);
const stats2 = someObject.get('stats');
- assert.notOk(
- stats1 === stats2,
+ assert.notStrictEqual(
+ stats1,
+ stats2,
'Changing the value of alloc results in creating a new AllocationStatsTracker instance'
);
});
diff --git a/ui/tests/unit/utils/behaviors/stats-tracker-frame-missing.js b/ui/tests/unit/utils/behaviors/stats-tracker-frame-missing.js
index 4807c3be2..77d77f673 100644
--- a/ui/tests/unit/utils/behaviors/stats-tracker-frame-missing.js
+++ b/ui/tests/unit/utils/behaviors/stats-tracker-frame-missing.js
@@ -3,7 +3,7 @@ import { test } from 'qunit';
import sinon from 'sinon';
import { settled } from '@ember/test-helpers';
-const MockResponse = json => ({
+const MockResponse = (json) => ({
ok: true,
json() {
return resolve(json);
@@ -17,7 +17,7 @@ export default function statsTrackerFrameMissing({
mockFrame,
compileResources,
}) {
- test('a bad response from a fetch request is handled gracefully', async function(assert) {
+ test('a bad response from a fetch request is handled gracefully', async function (assert) {
const frame = mockFrame(1);
const [compiledCPU, compiledMemory] = compileResources(frame);
@@ -27,27 +27,46 @@ export default function statsTrackerFrameMissing({
};
const resource = ResourceConstructor();
- const tracker = TrackerConstructor.create({ fetch, [resourceName]: resource });
+ const tracker = TrackerConstructor.create({
+ fetch,
+ [resourceName]: resource,
+ });
tracker.get('poll').perform();
await settled();
assert.deepEqual(tracker.get('cpu'), [compiledCPU], 'One frame of cpu');
- assert.deepEqual(tracker.get('memory'), [compiledMemory], 'One frame of memory');
+ assert.deepEqual(
+ tracker.get('memory'),
+ [compiledMemory],
+ 'One frame of memory'
+ );
shouldFail = true;
tracker.get('poll').perform();
await settled();
- assert.deepEqual(tracker.get('cpu'), [compiledCPU], 'Still one frame of cpu');
- assert.deepEqual(tracker.get('memory'), [compiledMemory], 'Still one frame of memory');
+ assert.deepEqual(
+ tracker.get('cpu'),
+ [compiledCPU],
+ 'Still one frame of cpu'
+ );
+ assert.deepEqual(
+ tracker.get('memory'),
+ [compiledMemory],
+ 'Still one frame of memory'
+ );
assert.equal(tracker.get('frameMisses'), 1, 'Frame miss is tracked');
shouldFail = false;
tracker.get('poll').perform();
await settled();
- assert.deepEqual(tracker.get('cpu'), [compiledCPU, compiledCPU], 'Still one frame of cpu');
+ assert.deepEqual(
+ tracker.get('cpu'),
+ [compiledCPU, compiledCPU],
+ 'Still one frame of cpu'
+ );
assert.deepEqual(
tracker.get('memory'),
[compiledMemory, compiledMemory],
@@ -56,7 +75,7 @@ export default function statsTrackerFrameMissing({
assert.equal(tracker.get('frameMisses'), 0, 'Frame misses is reset');
});
- test('enough bad responses from fetch consecutively (as set by maxFrameMisses) results in a pause', async function(assert) {
+ test('enough bad responses from fetch consecutively (as set by maxFrameMisses) results in a pause', async function (assert) {
const fetch = () => {
return resolve({ ok: false });
};
@@ -85,6 +104,9 @@ export default function statsTrackerFrameMissing({
await settled();
assert.equal(tracker.get('frameMisses'), 0, 'Misses reset');
- assert.ok(tracker.pause.called, 'Pause called now that frameMisses == maxFrameMisses');
+ assert.ok(
+ tracker.pause.called,
+ 'Pause called now that frameMisses == maxFrameMisses'
+ );
});
}
diff --git a/ui/tests/unit/utils/encode-test.js b/ui/tests/unit/utils/encode-test.js
index 0fa9fd78a..001fd5feb 100644
--- a/ui/tests/unit/utils/encode-test.js
+++ b/ui/tests/unit/utils/encode-test.js
@@ -1,15 +1,15 @@
import { base64DecodeString, base64EncodeString } from 'nomad-ui/utils/encode';
import { module, test } from 'qunit';
-module('Unit | Utility | encode', function() {
- test('it encodes a null input', function(assert) {
+module('Unit | Utility | encode', function () {
+ test('it encodes a null input', function (assert) {
const encoded = base64EncodeString(null);
const decoded = base64DecodeString(encoded);
assert.equal(decoded, '');
});
- test('it encodes an empty string', function(assert) {
+ test('it encodes an empty string', function (assert) {
const input = '';
const encoded = base64EncodeString(input);
const decoded = base64DecodeString(encoded);
@@ -17,19 +17,19 @@ module('Unit | Utility | encode', function() {
assert.equal(decoded, input);
});
- test('it decodes a null input', function(assert) {
+ test('it decodes a null input', function (assert) {
const decoded = base64DecodeString(null);
assert.equal(decoded, '');
});
- test('it decodes an empty string', function(assert) {
+ test('it decodes an empty string', function (assert) {
const decoded = base64DecodeString('');
assert.equal(decoded, '');
});
- test('it encodes and decodes non-ascii with base64', function(assert) {
+ test('it encodes and decodes non-ascii with base64', function (assert) {
const input = 'hello 🥳';
const encoded = base64EncodeString(input);
const decoded = base64DecodeString(encoded);
diff --git a/ui/tests/unit/utils/escape-task-name-test.js b/ui/tests/unit/utils/escape-task-name-test.js
index 649d2acce..2c8e3d9a9 100644
--- a/ui/tests/unit/utils/escape-task-name-test.js
+++ b/ui/tests/unit/utils/escape-task-name-test.js
@@ -1,8 +1,8 @@
import escapeTaskName from 'nomad-ui/utils/escape-task-name';
import { module, test } from 'qunit';
-module('Unit | Utility | escape-task-name', function() {
- test('it escapes task names for the faux exec CLI', function(assert) {
+module('Unit | Utility | escape-task-name', function () {
+ test('it escapes task names for the faux exec CLI', function (assert) {
assert.equal(escapeTaskName('plain'), 'plain');
assert.equal(escapeTaskName('a space'), 'a\\ space');
assert.equal(escapeTaskName('dollar $ign'), 'dollar\\ \\$ign');
diff --git a/ui/tests/unit/utils/format-duration-test.js b/ui/tests/unit/utils/format-duration-test.js
index 9a3e49230..dd02d0f77 100644
--- a/ui/tests/unit/utils/format-duration-test.js
+++ b/ui/tests/unit/utils/format-duration-test.js
@@ -1,18 +1,19 @@
import { module, test } from 'qunit';
import formatDuration from 'nomad-ui/utils/format-duration';
-module('Unit | Util | formatDuration', function() {
- test('When all units have values, all units are displayed', function(assert) {
- const expectation = '39 years 1 month 13 days 23h 31m 30s 987ms 654µs 400ns';
+module('Unit | Util | formatDuration', function () {
+ test('When all units have values, all units are displayed', function (assert) {
+ const expectation =
+ '39 years 1 month 13 days 23h 31m 30s 987ms 654µs 400ns';
assert.equal(formatDuration(1234567890987654321), expectation, expectation);
});
- test('Any unit without values gets dropped from the display', function(assert) {
+ test('Any unit without values gets dropped from the display', function (assert) {
const expectation = '14 days 6h 56m 890ms 980µs';
assert.equal(formatDuration(1234560890980000), expectation, expectation);
});
- test('The units option allows for units coarser than nanoseconds', function(assert) {
+ test('The units option allows for units coarser than nanoseconds', function (assert) {
const expectation1 = '1s 200ms';
const expectation2 = '20m';
const expectation3 = '1 month 1 day';
@@ -21,15 +22,23 @@ module('Unit | Util | formatDuration', function() {
assert.equal(formatDuration(32, 'd'), expectation3, expectation3);
});
- test('When duration is 0, 0 is shown in terms of the units provided to the function', function(assert) {
+ test('When duration is 0, 0 is shown in terms of the units provided to the function', function (assert) {
assert.equal(formatDuration(0), '0ns', 'formatDuration(0) -> 0ns');
- assert.equal(formatDuration(0, 'year'), '0 years', 'formatDuration(0, "year") -> 0 years');
+ assert.equal(
+ formatDuration(0, 'year'),
+ '0 years',
+ 'formatDuration(0, "year") -> 0 years'
+ );
});
- test('The longForm option expands suffixes to words', function(assert) {
+ test('The longForm option expands suffixes to words', function (assert) {
const expectation1 = '3 seconds 20ms';
const expectation2 = '5 hours 59 minutes';
assert.equal(formatDuration(3020, 'ms', true), expectation1, expectation1);
- assert.equal(formatDuration(60 * 5 + 59, 'm', true), expectation2, expectation2);
+ assert.equal(
+ formatDuration(60 * 5 + 59, 'm', true),
+ expectation2,
+ expectation2
+ );
});
});
diff --git a/ui/tests/unit/utils/generate-exec-url-test.js b/ui/tests/unit/utils/generate-exec-url-test.js
index b2897cc4e..81481e8e3 100644
--- a/ui/tests/unit/utils/generate-exec-url-test.js
+++ b/ui/tests/unit/utils/generate-exec-url-test.js
@@ -4,19 +4,19 @@ import sinon from 'sinon';
const emptyOptions = { queryParams: {} };
-module('Unit | Utility | generate-exec-url', function(hooks) {
- hooks.beforeEach(function() {
+module('Unit | Utility | generate-exec-url', function (hooks) {
+ hooks.beforeEach(function () {
this.urlForSpy = sinon.spy();
this.router = { urlFor: this.urlForSpy, currentRoute: { queryParams: {} } };
});
- test('it generates an exec job URL', function(assert) {
+ test('it generates an exec job URL', function (assert) {
generateExecUrl(this.router, { job: { plainId: 'job-name' } });
assert.ok(this.urlForSpy.calledWith('exec', 'job-name', emptyOptions));
});
- test('it generates an exec job URL with an allocation and task group when there are multiple tasks', function(assert) {
+ test('it generates an exec job URL with an allocation and task group when there are multiple tasks', function (assert) {
generateExecUrl(this.router, {
job: { plainId: 'job-name' },
allocation: {
@@ -26,13 +26,18 @@ module('Unit | Utility | generate-exec-url', function(hooks) {
});
assert.ok(
- this.urlForSpy.calledWith('exec.task-group', 'job-name', 'task-group-name', {
- queryParams: { allocation: 'allocation-short-id' },
- })
+ this.urlForSpy.calledWith(
+ 'exec.task-group',
+ 'job-name',
+ 'task-group-name',
+ {
+ queryParams: { allocation: 'allocation-short-id' },
+ }
+ )
);
});
- test('it generates an exec job URL with an allocation, task group, and task when there is only one task', function(assert) {
+ test('it generates an exec job URL with an allocation, task group, and task when there is only one task', function (assert) {
generateExecUrl(this.router, {
job: { plainId: 'job-name' },
allocation: {
@@ -54,18 +59,23 @@ module('Unit | Utility | generate-exec-url', function(hooks) {
);
});
- test('it generates an exec task group URL', function(assert) {
+ test('it generates an exec task group URL', function (assert) {
generateExecUrl(this.router, {
job: { plainId: 'job-name' },
taskGroup: { name: 'task-group-name' },
});
assert.ok(
- this.urlForSpy.calledWith('exec.task-group', 'job-name', 'task-group-name', emptyOptions)
+ this.urlForSpy.calledWith(
+ 'exec.task-group',
+ 'job-name',
+ 'task-group-name',
+ emptyOptions
+ )
);
});
- test('it generates an exec task URL', function(assert) {
+ test('it generates an exec task URL', function (assert) {
generateExecUrl(this.router, {
allocation: { shortId: 'allocation-short-id' },
job: { plainId: 'job-name' },
@@ -84,7 +94,7 @@ module('Unit | Utility | generate-exec-url', function(hooks) {
);
});
- test('it generates an exec task URL without an allocation', function(assert) {
+ test('it generates an exec task URL without an allocation', function (assert) {
generateExecUrl(this.router, {
job: { plainId: 'job-name' },
taskGroup: { name: 'task-group-name' },
@@ -92,11 +102,16 @@ module('Unit | Utility | generate-exec-url', function(hooks) {
});
assert.ok(
- this.urlForSpy.calledWith('exec.task-group.task', 'job-name', 'task-group-name', 'task-name')
+ this.urlForSpy.calledWith(
+ 'exec.task-group.task',
+ 'job-name',
+ 'task-group-name',
+ 'task-name'
+ )
);
});
- test('it includes job namespace and region when they exist', function(assert) {
+ test('it includes job namespace and region when they exist', function (assert) {
generateExecUrl(this.router, {
job: {
namespace: {
@@ -105,13 +120,25 @@ module('Unit | Utility | generate-exec-url', function(hooks) {
plainId: 'job-name',
region: 'a-region',
},
- allocation: { shortId: 'id', taskGroup: { name: 'task-group-name', tasks: [0, 1] } },
+ allocation: {
+ shortId: 'id',
+ taskGroup: { name: 'task-group-name', tasks: [0, 1] },
+ },
});
assert.ok(
- this.urlForSpy.calledWith('exec.task-group', 'job-name', 'task-group-name', {
- queryParams: { allocation: 'id', namespace: 'a-namespace', region: 'a-region' },
- })
+ this.urlForSpy.calledWith(
+ 'exec.task-group',
+ 'job-name',
+ 'task-group-name',
+ {
+ queryParams: {
+ allocation: 'id',
+ namespace: 'a-namespace',
+ region: 'a-region',
+ },
+ }
+ )
);
});
});
diff --git a/ui/tests/unit/utils/job-client-status-test.js b/ui/tests/unit/utils/job-client-status-test.js
index 70a6532a4..e625a4f57 100644
--- a/ui/tests/unit/utils/job-client-status-test.js
+++ b/ui/tests/unit/utils/job-client-status-test.js
@@ -51,8 +51,8 @@ class AllocationMock {
}
}
-module('Unit | Util | JobClientStatus', function() {
- test('it handles the case where all nodes are running', async function(assert) {
+module('Unit | Util | JobClientStatus', function () {
+ test('it handles the case where all nodes are running', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -84,7 +84,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the degraded case where a node has a failing allocation', async function(assert) {
+ test('it handles the degraded case where a node has a failing allocation', async function (assert) {
const node = new NodeMock('node-2', 'dc1');
const nodes = [node];
const job = {
@@ -120,7 +120,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the case where a node has all lost allocations', async function(assert) {
+ test('it handles the case where a node has all lost allocations', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -156,7 +156,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the case where a node has all failed allocations', async function(assert) {
+ test('it handles the case where a node has all failed allocations', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -192,7 +192,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the degraded case where the expected number of allocations doesnt match the actual number of allocations', async function(assert) {
+ test('it handles the degraded case where the expected number of allocations doesnt match the actual number of allocations', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -228,7 +228,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the not scheduled case where a node has no allocations', async function(assert) {
+ test('it handles the not scheduled case where a node has no allocations', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -260,7 +260,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it handles the queued case where the job is pending', async function(assert) {
+ test('it handles the queued case where the job is pending', async function (assert) {
const node = new NodeMock('node-1', 'dc1');
const nodes = [node];
const job = {
@@ -296,7 +296,7 @@ module('Unit | Util | JobClientStatus', function() {
assert.deepEqual(result, expected);
});
- test('it filters nodes by the datacenter of the job', async function(assert) {
+ test('it filters nodes by the datacenter of the job', async function (assert) {
const node1 = new NodeMock('node-1', 'dc1');
const node2 = new NodeMock('node-2', 'dc2');
const nodes = [node1, node2];
diff --git a/ui/tests/unit/utils/log-test.js b/ui/tests/unit/utils/log-test.js
index bae13b32b..920784aa0 100644
--- a/ui/tests/unit/utils/log-test.js
+++ b/ui/tests/unit/utils/log-test.js
@@ -38,26 +38,31 @@ const MockStreamer = EmberObject.extend({
const Log = _Log.extend({
init() {
this._super();
- const props = this.logStreamer.getProperties('url', 'params', 'logFetch', 'write');
+ const props = this.logStreamer.getProperties(
+ 'url',
+ 'params',
+ 'logFetch',
+ 'write'
+ );
this.set('logStreamer', MockStreamer.create(props));
},
});
-module('Unit | Util | Log', function(hooks) {
- hooks.beforeEach(function() {
+module('Unit | Util | Log', function (hooks) {
+ hooks.beforeEach(function () {
initSpy = sinon.spy();
startSpy = sinon.spy();
stopSpy = sinon.spy();
fetchSpy = sinon.spy();
});
- const makeMocks = output => ({
+ const makeMocks = (output) => ({
url: '/test-url/',
params: {
a: 'param',
another: 'one',
},
- logFetch: function() {
+ logFetch: function () {
fetchSpy(...arguments);
return RSVP.Promise.resolve({
text() {
@@ -67,28 +72,31 @@ module('Unit | Util | Log', function(hooks) {
},
});
- test('logStreamer is created on init', async function(assert) {
+ test('logStreamer is created on init', async function (assert) {
const log = Log.create(makeMocks(''));
assert.ok(log.get('logStreamer'), 'logStreamer property is defined');
assert.ok(initSpy.calledOnce, 'logStreamer init was called');
});
- test('gotoHead builds the correct URL', async function(assert) {
+ test('gotoHead builds the correct URL', async function (assert) {
+ assert.expect(1);
+
const mocks = makeMocks('');
const expectedUrl = `${mocks.url}?a=param&another=one&offset=0&origin=start`;
const log = Log.create(mocks);
run(() => {
log.get('gotoHead').perform();
- assert.ok(fetchSpy.calledWith(expectedUrl), `gotoHead URL was ${expectedUrl}`);
+ assert.ok(
+ fetchSpy.calledWith(expectedUrl),
+ `gotoHead URL was ${expectedUrl}`
+ );
});
});
- test('When gotoHead returns too large of a log, the log is truncated', async function(assert) {
- const longLog = Array(50001)
- .fill('a')
- .join('');
+ test('When gotoHead returns too large of a log, the log is truncated', async function (assert) {
+ const longLog = Array(50001).fill('a').join('');
const encodedLongLog = `{"Offset":0,"Data":"${window.btoa(longLog)}"}`;
const truncationMessage =
'\n\n---------- TRUNCATED: Click "tail" to view the bottom of the log ----------';
@@ -102,10 +110,7 @@ module('Unit | Util | Log', function(hooks) {
await settled();
assert.ok(
- log
- .get('output')
- .toString()
- .endsWith(truncationMessage),
+ log.get('output').toString().endsWith(truncationMessage),
'Truncation message is shown'
);
assert.equal(
@@ -115,26 +120,35 @@ module('Unit | Util | Log', function(hooks) {
);
});
- test('gotoTail builds the correct URL', async function(assert) {
+ test('gotoTail builds the correct URL', async function (assert) {
+ assert.expect(1);
+
const mocks = makeMocks('');
const expectedUrl = `${mocks.url}?a=param&another=one&offset=50000&origin=end`;
const log = Log.create(mocks);
run(() => {
log.get('gotoTail').perform();
- assert.ok(fetchSpy.calledWith(expectedUrl), `gotoTail URL was ${expectedUrl}`);
+ assert.ok(
+ fetchSpy.calledWith(expectedUrl),
+ `gotoTail URL was ${expectedUrl}`
+ );
});
});
- test('startStreaming starts the log streamer', async function(assert) {
+ test('startStreaming starts the log streamer', async function (assert) {
const log = Log.create(makeMocks(''));
log.startStreaming();
assert.ok(startSpy.calledOnce, 'Streaming started');
- assert.equal(log.get('logPointer'), 'tail', 'Streaming points the log to the tail');
+ assert.equal(
+ log.get('logPointer'),
+ 'tail',
+ 'Streaming points the log to the tail'
+ );
});
- test('When the log streamer calls `write`, the output is appended', async function(assert) {
+ test('When the log streamer calls `write`, the output is appended', async function (assert) {
const log = Log.create(makeMocks(''));
const chunk1 = 'Hello';
const chunk2 = ' World';
@@ -150,10 +164,14 @@ module('Unit | Util | Log', function(hooks) {
assert.equal(log.get('output'), chunk1 + chunk2, 'Second chunk written');
log.get('logStreamer').step(chunk3);
- assert.equal(log.get('output'), chunk1 + chunk2 + chunk3, 'Third chunk written');
+ assert.equal(
+ log.get('output'),
+ chunk1 + chunk2 + chunk3,
+ 'Third chunk written'
+ );
});
- test('stop stops the log streamer', async function(assert) {
+ test('stop stops the log streamer', async function (assert) {
const log = Log.create(makeMocks(''));
log.stop();
diff --git a/ui/tests/unit/utils/message-from-adapter-error-test.js b/ui/tests/unit/utils/message-from-adapter-error-test.js
index 7336ee943..2fe795356 100644
--- a/ui/tests/unit/utils/message-from-adapter-error-test.js
+++ b/ui/tests/unit/utils/message-from-adapter-error-test.js
@@ -10,7 +10,10 @@ const testCases = [
},
{
name: 'Generic Error',
- in: [new ServerError([{ detail: 'DB Max Connections' }], 'Server Error'), 'run tests'],
+ in: [
+ new ServerError([{ detail: 'DB Max Connections' }], 'Server Error'),
+ 'run tests',
+ ],
out: 'DB Max Connections',
},
{
@@ -31,9 +34,9 @@ const testCases = [
},
];
-module('Unit | Util | messageFromAdapterError', function() {
- testCases.forEach(testCase => {
- test(testCase.name, function(assert) {
+module('Unit | Util | messageFromAdapterError', function () {
+ testCases.forEach((testCase) => {
+ test(testCase.name, function (assert) {
assert.equal(
messageFromAdapterError.apply(null, testCase.in),
testCase.out,
diff --git a/ui/tests/unit/utils/node-stats-tracker-test.js b/ui/tests/unit/utils/node-stats-tracker-test.js
index 55871280e..1729e14e7 100644
--- a/ui/tests/unit/utils/node-stats-tracker-test.js
+++ b/ui/tests/unit/utils/node-stats-tracker-test.js
@@ -3,17 +3,19 @@ import { assign } from '@ember/polyfills';
import { module, test } from 'qunit';
import sinon from 'sinon';
import Pretender from 'pretender';
-import NodeStatsTracker, { stats } from 'nomad-ui/utils/classes/node-stats-tracker';
+import NodeStatsTracker, {
+ stats,
+} from 'nomad-ui/utils/classes/node-stats-tracker';
import fetch from 'nomad-ui/utils/fetch';
import statsTrackerFrameMissingBehavior from './behaviors/stats-tracker-frame-missing';
import { settled } from '@ember/test-helpers';
-module('Unit | Util | NodeStatsTracker', function() {
+module('Unit | Util | NodeStatsTracker', function () {
const refDate = Date.now() * 1000000;
- const makeDate = ts => new Date(ts / 1000000);
+ const makeDate = (ts) => new Date(ts / 1000000);
- const MockNode = overrides =>
+ const MockNode = (overrides) =>
assign(
{
id: 'some-identifier',
@@ -25,7 +27,7 @@ module('Unit | Util | NodeStatsTracker', function() {
overrides
);
- const mockFrame = step => ({
+ const mockFrame = (step) => ({
CPUTicksConsumed: step + 1000,
Memory: {
Used: (step + 2048) * 1024 * 1024,
@@ -33,7 +35,7 @@ module('Unit | Util | NodeStatsTracker', function() {
Timestamp: refDate + step,
});
- test('the NodeStatsTracker constructor expects a fetch definition and a node', async function(assert) {
+ test('the NodeStatsTracker constructor expects a fetch definition and a node', async function (assert) {
const tracker = NodeStatsTracker.create();
assert.throws(
() => {
@@ -44,7 +46,7 @@ module('Unit | Util | NodeStatsTracker', function() {
);
});
- test('the url property is computed based off the node id', async function(assert) {
+ test('the url property is computed based off the node id', async function (assert) {
const node = MockNode();
const tracker = NodeStatsTracker.create({ fetch, node });
@@ -55,11 +57,15 @@ module('Unit | Util | NodeStatsTracker', function() {
);
});
- test('reservedCPU and reservedMemory properties come from the node', async function(assert) {
+ test('reservedCPU and reservedMemory properties come from the node', async function (assert) {
const node = MockNode();
const tracker = NodeStatsTracker.create({ fetch, node });
- assert.equal(tracker.get('reservedCPU'), node.resources.cpu, 'reservedCPU comes from the node');
+ assert.equal(
+ tracker.get('reservedCPU'),
+ node.resources.cpu,
+ 'reservedCPU comes from the node'
+ );
assert.equal(
tracker.get('reservedMemory'),
node.resources.memory,
@@ -67,9 +73,13 @@ module('Unit | Util | NodeStatsTracker', function() {
);
});
- test('poll results in requesting the url and calling append with the resulting JSON', async function(assert) {
+ test('poll results in requesting the url and calling append with the resulting JSON', async function (assert) {
const node = MockNode();
- const tracker = NodeStatsTracker.create({ fetch, node, append: sinon.spy() });
+ const tracker = NodeStatsTracker.create({
+ fetch,
+ node,
+ append: sinon.spy(),
+ });
const mockFrame = {
Some: {
data: ['goes', 'here'],
@@ -77,7 +87,7 @@ module('Unit | Util | NodeStatsTracker', function() {
},
};
- const server = new Pretender(function() {
+ const server = new Pretender(function () {
this.get('/v1/client/stats', () => [200, {}, JSON.stringify(mockFrame)]);
});
@@ -99,7 +109,7 @@ module('Unit | Util | NodeStatsTracker', function() {
server.shutdown();
});
- test('append appropriately maps a data frame to the tracked stats for cpu and memory for the node', async function(assert) {
+ test('append appropriately maps a data frame to the tracked stats for cpu and memory for the node', async function (assert) {
const node = MockNode();
const tracker = NodeStatsTracker.create({ fetch, node });
@@ -116,7 +126,13 @@ module('Unit | Util | NodeStatsTracker', function() {
assert.deepEqual(
tracker.get('memory'),
- [{ timestamp: makeDate(refDate + 1), used: 2049 * 1024 * 1024, percent: 2049 / 4096 }],
+ [
+ {
+ timestamp: makeDate(refDate + 1),
+ used: 2049 * 1024 * 1024,
+ percent: 2049 / 4096,
+ },
+ ],
'One frame of memory'
);
@@ -134,14 +150,22 @@ module('Unit | Util | NodeStatsTracker', function() {
assert.deepEqual(
tracker.get('memory'),
[
- { timestamp: makeDate(refDate + 1), used: 2049 * 1024 * 1024, percent: 2049 / 4096 },
- { timestamp: makeDate(refDate + 2), used: 2050 * 1024 * 1024, percent: 2050 / 4096 },
+ {
+ timestamp: makeDate(refDate + 1),
+ used: 2049 * 1024 * 1024,
+ percent: 2049 / 4096,
+ },
+ {
+ timestamp: makeDate(refDate + 2),
+ used: 2050 * 1024 * 1024,
+ percent: 2050 / 4096,
+ },
],
'Two frames of memory'
);
});
- test('each stat list has maxLength equal to bufferSize', async function(assert) {
+ test('each stat list has maxLength equal to bufferSize', async function (assert) {
const node = MockNode();
const bufferSize = 10;
const tracker = NodeStatsTracker.create({ fetch, node, bufferSize });
@@ -173,12 +197,12 @@ module('Unit | Util | NodeStatsTracker', function() {
);
});
- test('the stats computed property macro constructs a NodeStatsTracker based on a nodeProp and a fetch definition', async function(assert) {
+ test('the stats computed property macro constructs a NodeStatsTracker based on a nodeProp and a fetch definition', async function (assert) {
const node = MockNode();
const fetchSpy = sinon.spy();
const SomeClass = EmberObject.extend({
- stats: stats('theNode', function() {
+ stats: stats('theNode', function () {
return () => fetchSpy(this);
}),
});
@@ -200,7 +224,7 @@ module('Unit | Util | NodeStatsTracker', function() {
);
});
- test('changing the value of the nodeProp constructs a new NodeStatsTracker', async function(assert) {
+ test('changing the value of the nodeProp constructs a new NodeStatsTracker', async function (assert) {
const node1 = MockNode();
const node2 = MockNode();
const SomeClass = EmberObject.extend({
@@ -216,8 +240,9 @@ module('Unit | Util | NodeStatsTracker', function() {
someObject.set('theNode', node2);
const stats2 = someObject.get('stats');
- assert.notOk(
- stats1 === stats2,
+ assert.notStrictEqual(
+ stats1,
+ stats2,
'Changing the value of the node results in creating a new NodeStatsTracker instance'
);
});
diff --git a/ui/tests/unit/utils/rolling-array-test.js b/ui/tests/unit/utils/rolling-array-test.js
index f3af28cb4..9bf5c290a 100644
--- a/ui/tests/unit/utils/rolling-array-test.js
+++ b/ui/tests/unit/utils/rolling-array-test.js
@@ -2,8 +2,8 @@ import { isArray } from '@ember/array';
import { module, test } from 'qunit';
import RollingArray from 'nomad-ui/utils/classes/rolling-array';
-module('Unit | Util | RollingArray', function() {
- test('has a maxLength property that gets set in the constructor', function(assert) {
+module('Unit | Util | RollingArray', function () {
+ test('has a maxLength property that gets set in the constructor', function (assert) {
const array = RollingArray(10, 'a', 'b', 'c');
assert.equal(array.maxLength, 10, 'maxLength is set in the constructor');
assert.deepEqual(
@@ -13,7 +13,7 @@ module('Unit | Util | RollingArray', function() {
);
});
- test('push works like Array#push', function(assert) {
+ test('push works like Array#push', function (assert) {
const array = RollingArray(10);
const pushReturn = array.push('a');
assert.equal(
@@ -21,7 +21,11 @@ module('Unit | Util | RollingArray', function() {
array.length,
'the return value from push is equal to the return value of Array#push'
);
- assert.equal(array[0], 'a', 'the arguments passed to push are appended to the array');
+ assert.equal(
+ array[0],
+ 'a',
+ 'the arguments passed to push are appended to the array'
+ );
array.push('b', 'c', 'd');
assert.deepEqual(
@@ -31,7 +35,7 @@ module('Unit | Util | RollingArray', function() {
);
});
- test('when pushing past maxLength, items are removed from the head of the array', function(assert) {
+ test('when pushing past maxLength, items are removed from the head of the array', function (assert) {
const array = RollingArray(3);
const pushReturn = array.push(1, 2, 3, 4);
assert.deepEqual(
@@ -46,7 +50,7 @@ module('Unit | Util | RollingArray', function() {
);
});
- test('when splicing past maxLength, items are removed from the head of the array', function(assert) {
+ test('when splicing past maxLength, items are removed from the head of the array', function (assert) {
const array = RollingArray(3, 'a', 'b', 'c');
array.splice(1, 0, 'z');
@@ -71,7 +75,7 @@ module('Unit | Util | RollingArray', function() {
);
});
- test('unshift throws instead of prepending elements', function(assert) {
+ test('unshift throws instead of prepending elements', function (assert) {
const array = RollingArray(5);
assert.throws(
@@ -83,9 +87,9 @@ module('Unit | Util | RollingArray', function() {
);
});
- test('RollingArray is an instance of Array', function(assert) {
+ test('RollingArray is an instance of Array', function (assert) {
const array = RollingArray(5);
- assert.ok(array.constructor === Array, 'The constructor is Array');
+ assert.strictEqual(array.constructor, Array, 'The constructor is Array');
assert.ok(array instanceof Array, 'The instanceof check is true');
assert.ok(isArray(array), 'The ember isArray helper works');
});
diff --git a/ui/tests/unit/utils/stream-frames-test.js b/ui/tests/unit/utils/stream-frames-test.js
index 90bab68c8..c8877e52e 100644
--- a/ui/tests/unit/utils/stream-frames-test.js
+++ b/ui/tests/unit/utils/stream-frames-test.js
@@ -4,9 +4,9 @@ import { TextEncoderLite } from 'text-encoder-lite';
import base64js from 'base64-js';
const Encoder = new TextEncoderLite('utf-8');
-const encode = str => base64js.fromByteArray(Encoder.encode(str));
+const encode = (str) => base64js.fromByteArray(Encoder.encode(str));
-module('Unit | Util | stream-frames', function() {
+module('Unit | Util | stream-frames', function () {
const { btoa } = window;
const decodeTestCases = [
{
@@ -46,8 +46,8 @@ module('Unit | Util | stream-frames', function() {
},
];
- decodeTestCases.forEach(testCase => {
- test(`decode: ${testCase.name}`, function(assert) {
+ decodeTestCases.forEach((testCase) => {
+ test(`decode: ${testCase.name}`, function (assert) {
assert.deepEqual(decode(testCase.in), testCase.out);
});
});
diff --git a/ui/tests/unit/utils/stream-logger-test.js b/ui/tests/unit/utils/stream-logger-test.js
index b0cbb28a2..4bbf0c4e1 100644
--- a/ui/tests/unit/utils/stream-logger-test.js
+++ b/ui/tests/unit/utils/stream-logger-test.js
@@ -3,8 +3,8 @@ import { Promise } from 'rsvp';
import sinon from 'sinon';
import StreamLogger from 'nomad-ui/utils/classes/stream-logger';
-module('Unit | Util | StreamLogger', function() {
- test('when a StreamLogger is stopped before the poll request responds, the request is immediately canceled upon completion', async function(assert) {
+module('Unit | Util | StreamLogger', function () {
+ test('when a StreamLogger is stopped before the poll request responds, the request is immediately canceled upon completion', async function (assert) {
const fetchMock = new FetchMock();
const fetch = fetchMock.request();
@@ -24,7 +24,7 @@ module('Unit | Util | StreamLogger', function() {
assert.equal(fetchMock.reader.cancel.callCount, 1);
});
- test('when the streaming request sends the done flag, the poll task completes', async function(assert) {
+ test('when the streaming request sends the done flag, the poll task completes', async function (assert) {
const fetchMock = new FetchMock();
const fetch = fetchMock.request();
@@ -56,7 +56,7 @@ class FetchMock {
if (this._closeRequest) {
throw new Error('Can only call FetchMock.request once');
}
- return new Promise(resolve => {
+ return new Promise((resolve) => {
this._closeRequest = resolve;
});
}
@@ -65,7 +65,9 @@ class FetchMock {
if (this._closeRequest) {
this._closeRequest(this.response);
} else {
- throw new Error('Must call FetchMock.request() before FetchMock.closeRequest');
+ throw new Error(
+ 'Must call FetchMock.request() before FetchMock.closeRequest'
+ );
}
}
}
@@ -89,7 +91,7 @@ class ReadableStreamMock {
read() {
this.readSpy();
- return new Promise(resolve => {
+ return new Promise((resolve) => {
resolve({ value: new ArrayBuffer(0), done: true });
});
}
diff --git a/ui/tests/unit/utils/units-test.js b/ui/tests/unit/utils/units-test.js
index bb2f06e02..5c8e5b39f 100644
--- a/ui/tests/unit/utils/units-test.js
+++ b/ui/tests/unit/utils/units-test.js
@@ -2,14 +2,14 @@ import { module, test } from 'qunit';
import * as units from 'nomad-ui/utils/units';
function table(fn, cases) {
- cases.forEach(testCase => {
- test(testCase.name || testCase.out, function(assert) {
+ cases.forEach((testCase) => {
+ test(testCase.name || testCase.out, function (assert) {
assert.deepEqual(fn.apply(null, testCase.in), testCase.out);
});
});
}
-module('Unit | Util | units#formatBytes', function() {
+module('Unit | Util | units#formatBytes', function () {
table.call(this, units.formatBytes, [
{ in: [null], out: '0 Bytes', name: 'formats null as 0 bytes' },
{ in: [undefined], out: '0 Bytes', name: 'formats undefined as 0 bytes' },
@@ -18,11 +18,23 @@ module('Unit | Util | units#formatBytes', function() {
{ in: [1023], out: '1,023 Bytes' },
{ in: [1024], out: '1 KiB', name: 'formats 1024 <= x < 1024^2 as KiB' },
{ in: [1024 ** 2 - 1024 * 0.01], out: '1,023.99 KiB' },
- { in: [1024 ** 2], out: '1 MiB', name: 'formats 1024^2 <= x < 1024^3 as MiB' },
+ {
+ in: [1024 ** 2],
+ out: '1 MiB',
+ name: 'formats 1024^2 <= x < 1024^3 as MiB',
+ },
{ in: [1024 ** 2 * 1.016], out: '1.02 MiB' },
- { in: [1024 ** 3], out: '1 GiB', name: 'formats 1024^3 <= x < 1024^4 as GiB' },
+ {
+ in: [1024 ** 3],
+ out: '1 GiB',
+ name: 'formats 1024^3 <= x < 1024^4 as GiB',
+ },
{ in: [1024 ** 3 * 512.5], out: '512.5 GiB' },
- { in: [1024 ** 4], out: '1 TiB', name: 'formats 1024^4 <= x < 1024^5 as TiB' },
+ {
+ in: [1024 ** 4],
+ out: '1 TiB',
+ name: 'formats 1024^4 <= x < 1024^5 as TiB',
+ },
{ in: [1024 ** 4 * 2.1234], out: '2.12 TiB' },
{ in: [1024 ** 5], out: '1 PiB', name: 'formats x > 1024^5 as PiB' },
{ in: [1024 ** 5 * 4000], out: '4,000 PiB' },
@@ -31,11 +43,15 @@ module('Unit | Util | units#formatBytes', function() {
out: '1 TiB',
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1024 ** 2 * -1], out: '-1 MiB', name: 'negative values are still reduced' },
+ {
+ in: [1024 ** 2 * -1],
+ out: '-1 MiB',
+ name: 'negative values are still reduced',
+ },
]);
});
-module('Unit | Util | units#formatScheduledBytes', function() {
+module('Unit | Util | units#formatScheduledBytes', function () {
table.call(this, units.formatScheduledBytes, [
{ in: [null], out: '0 Bytes', name: 'formats null as 0 bytes' },
{ in: [undefined], out: '0 Bytes', name: 'formats undefined as 0 bytes' },
@@ -55,11 +71,15 @@ module('Unit | Util | units#formatScheduledBytes', function() {
out: '2,000 MiB',
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1024 ** 3 * -1], out: '-1,024 MiB', name: 'negative values are still reduced' },
+ {
+ in: [1024 ** 3 * -1],
+ out: '-1,024 MiB',
+ name: 'negative values are still reduced',
+ },
]);
});
-module('Unit | Util | units#formatHertz', function() {
+module('Unit | Util | units#formatHertz', function () {
table.call(this, units.formatHertz, [
{ in: [null], out: '0 Hz', name: 'formats null as 0 Hz' },
{ in: [undefined], out: '0 Hz', name: 'formats undefined as 0 Hz' },
@@ -67,11 +87,23 @@ module('Unit | Util | units#formatHertz', function() {
{ in: [999], out: '999 Hz' },
{ in: [1000], out: '1 KHz', name: 'formats 1000 <= x < 1000^2 as KHz' },
{ in: [1000 ** 2 - 10], out: '999.99 KHz' },
- { in: [1000 ** 2], out: '1 MHz', name: 'formats 1000^2 <= x < 1000^3 as MHz' },
+ {
+ in: [1000 ** 2],
+ out: '1 MHz',
+ name: 'formats 1000^2 <= x < 1000^3 as MHz',
+ },
{ in: [1000 ** 2 * 5.234], out: '5.23 MHz' },
- { in: [1000 ** 3], out: '1 GHz', name: 'formats 1000^3 <= x < 1000^4 as GHz' },
+ {
+ in: [1000 ** 3],
+ out: '1 GHz',
+ name: 'formats 1000^3 <= x < 1000^4 as GHz',
+ },
{ in: [1000 ** 3 * 500.238], out: '500.24 GHz' },
- { in: [1000 ** 4], out: '1 THz', name: 'formats 1000^4 <= x < 1000^5 as THz' },
+ {
+ in: [1000 ** 4],
+ out: '1 THz',
+ name: 'formats 1000^4 <= x < 1000^5 as THz',
+ },
{ in: [1000 ** 4 * 12], out: '12 THz' },
{ in: [1000 ** 5], out: '1 PHz', name: 'formats x > 1000^5 as PHz' },
{ in: [1000 ** 5 * 34567.89], out: '34,567.89 PHz' },
@@ -80,11 +112,15 @@ module('Unit | Util | units#formatHertz', function() {
out: '2 MHz',
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1000 ** 3 * -1], out: '-1 GHz', name: 'negative values are still reduced' },
+ {
+ in: [1000 ** 3 * -1],
+ out: '-1 GHz',
+ name: 'negative values are still reduced',
+ },
]);
});
-module('Unit | Util | units#formatScheduledHertz', function() {
+module('Unit | Util | units#formatScheduledHertz', function () {
table.call(this, units.formatScheduledHertz, [
{ in: [null], out: '0 Hz', name: 'formats null as 0 Hz' },
{ in: [undefined], out: '0 Hz', name: 'formats undefined as 0 Hz' },
@@ -104,13 +140,21 @@ module('Unit | Util | units#formatScheduledHertz', function() {
out: '2,000 MHz',
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1000 ** 3 * -1], out: '-1,000 MHz', name: 'negative values are still reduced' },
+ {
+ in: [1000 ** 3 * -1],
+ out: '-1,000 MHz',
+ name: 'negative values are still reduced',
+ },
]);
});
-module('Unit | Util | units#reduceBytes', function() {
+module('Unit | Util | units#reduceBytes', function () {
table.call(this, units.reduceBytes, [
- { in: [], out: [0, 'Bytes'], name: 'No args behavior results in valid output' },
+ {
+ in: [],
+ out: [0, 'Bytes'],
+ name: 'No args behavior results in valid output',
+ },
{ in: [1024 ** 6], out: [1024, 'PiB'], name: 'Max default unit is PiB' },
{
in: [1024 ** 6 * 1.12345],
@@ -127,13 +171,21 @@ module('Unit | Util | units#reduceBytes', function() {
out: [1024, 'MiB'],
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1024 ** 3 * -1], out: [-1, 'GiB'], name: 'negative values are still reduced' },
+ {
+ in: [1024 ** 3 * -1],
+ out: [-1, 'GiB'],
+ name: 'negative values are still reduced',
+ },
]);
});
-module('Unit | Util | units#reduceHertz', function() {
+module('Unit | Util | units#reduceHertz', function () {
table.call(this, units.reduceHertz, [
- { in: [], out: [0, 'Hz'], name: 'No args behavior results in valid output' },
+ {
+ in: [],
+ out: [0, 'Hz'],
+ name: 'No args behavior results in valid output',
+ },
{ in: [1000 ** 6], out: [1000, 'PHz'], name: 'Max default unit is PHz' },
{
in: [1000 ** 6 * 1.12345],
@@ -150,6 +202,10 @@ module('Unit | Util | units#reduceHertz', function() {
out: [2, 'GHz'],
name: 'accepts a starting unit size as an optional argument',
},
- { in: [1000 ** 3 * -1], out: [-1, 'GHz'], name: 'negative values are still reduced' },
+ {
+ in: [1000 ** 3 * -1],
+ out: [-1, 'GHz'],
+ name: 'negative values are still reduced',
+ },
]);
});
diff --git a/ui/tests/utils/clean-whitespace.js b/ui/tests/utils/clean-whitespace.js
index cc3d5282e..13427811c 100644
--- a/ui/tests/utils/clean-whitespace.js
+++ b/ui/tests/utils/clean-whitespace.js
@@ -1,8 +1,5 @@
// cleans whitespace from a string, for example for cleaning
// textContent in DOM nodes with indentation
export default function cleanWhitespace(string) {
- return string
- .replace(/\n/g, '')
- .replace(/ +/g, ' ')
- .trim();
+ return string.replace(/\n/g, '').replace(/ +/g, ' ').trim();
}
diff --git a/ui/tests/utils/ember-power-select-extensions.js b/ui/tests/utils/ember-power-select-extensions.js
index 245d8ec45..1e63256ac 100644
--- a/ui/tests/utils/ember-power-select-extensions.js
+++ b/ui/tests/utils/ember-power-select-extensions.js
@@ -10,12 +10,17 @@ import { click, settled } from '@ember/test-helpers';
// these two moments. Doing it before opening means hanging on open not on select. Doing it
// after means hanging after the select has occurred (too late).
async function openIfClosedAndGetContentId(trigger) {
- let contentId = trigger.attributes['aria-owns'] && `${trigger.attributes['aria-owns'].value}`;
+ let contentId =
+ trigger.attributes['aria-owns'] &&
+ `${trigger.attributes['aria-owns'].value}`;
let content = contentId ? document.querySelector(`#${contentId}`) : undefined;
// If the dropdown is closed, open it
- if (!content || content.classList.contains('ember-basic-dropdown-content-placeholder')) {
+ if (
+ !content ||
+ content.classList.contains('ember-basic-dropdown-content-placeholder')
+ ) {
await click(trigger);
- await settled();
+
contentId = `${trigger.attributes['aria-owns'].value}`;
}
return contentId;
@@ -30,7 +35,9 @@ export async function selectOpen(cssPathOrTrigger) {
trigger = cssPathOrTrigger.querySelector('.ember-power-select-trigger');
}
} else {
- trigger = document.querySelector(`${cssPathOrTrigger} .ember-power-select-trigger`);
+ trigger = document.querySelector(
+ `${cssPathOrTrigger} .ember-power-select-trigger`
+ );
if (!trigger) {
trigger = document.querySelector(cssPathOrTrigger);
@@ -50,20 +57,28 @@ export async function selectOpen(cssPathOrTrigger) {
return await openIfClosedAndGetContentId(trigger);
}
-export async function selectOpenChoose(contentId, valueOrSelector, optionIndex) {
+export async function selectOpenChoose(
+ contentId,
+ valueOrSelector,
+ optionIndex
+) {
let target;
// Select the option with the given text
- let options = document.querySelectorAll(`#${contentId} .ember-power-select-option`);
+ let options = document.querySelectorAll(
+ `#${contentId} .ember-power-select-option`
+ );
let potentialTargets = [].slice
.apply(options)
- .filter(opt => opt.textContent.indexOf(valueOrSelector) > -1);
+ .filter((opt) => opt.textContent.indexOf(valueOrSelector) > -1);
if (potentialTargets.length === 0) {
- potentialTargets = document.querySelectorAll(`#${contentId} ${valueOrSelector}`);
+ potentialTargets = document.querySelectorAll(
+ `#${contentId} ${valueOrSelector}`
+ );
}
if (potentialTargets.length > 1) {
let filteredTargets = [].slice
.apply(potentialTargets)
- .filter(t => t.textContent.trim() === valueOrSelector);
+ .filter((t) => t.textContent.trim() === valueOrSelector);
if (optionIndex === undefined) {
target = filteredTargets[0] || potentialTargets[0];
} else {
diff --git a/ui/yarn.lock b/ui/yarn.lock
index fefe48c54..576b50462 100644
--- a/ui/yarn.lock
+++ b/ui/yarn.lock
@@ -9,7 +9,7 @@
dependencies:
"@babel/highlight" "^7.10.4"
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11":
+"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
@@ -2603,19 +2603,18 @@
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
-"@eslint/eslintrc@^0.3.0":
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318"
- integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==
+"@eslint/eslintrc@^0.4.3":
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
+ integrity sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==
dependencies:
ajv "^6.12.4"
debug "^4.1.1"
espree "^7.3.0"
- globals "^12.1.0"
+ globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
js-yaml "^3.13.1"
- lodash "^4.17.20"
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
@@ -2840,6 +2839,20 @@
resolved "https://registry.yarnpkg.com/@hashicorp/structure-icons/-/structure-icons-1.9.2.tgz#c75f955b2eec414ecb92f3926c79b4ca01731d3c"
integrity sha512-AffJv0V9npr1EWlM1XrpaKPG9PzddV48OE+jspqy7aRoFZB5++oNnPx4MZQKmFInOljnzNwfktVRkJiQHy7haw==
+"@humanwhocodes/config-array@^0.5.0":
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9"
+ integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.0"
+ debug "^4.1.1"
+ minimatch "^3.0.4"
+
+"@humanwhocodes/object-schema@^1.2.0":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
"@mdx-js/mdx@^1.6.22":
version "1.6.22"
resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba"
@@ -4223,10 +4236,10 @@ ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.2, ajv@^6.12.3, ajv@^6.12.4, ajv
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
-ajv@^7.0.2:
- version "7.0.4"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.4.tgz#827e5f5ae32f5e5c1637db61f253a112229b5e2f"
- integrity sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==
+ajv@^8.0.1:
+ version "8.8.2"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.8.2.tgz#01b4fef2007a28bf75f0b7fc009f62679de4abbb"
+ integrity sha512-x9VuX+R/jcFj1DHo/fCp99esgGDWiHENrKxaCENuCxpoMCmAt/COCGVDwA7kleEpEzJjDnvh3yGoOuLu0Dtllw==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
@@ -7675,6 +7688,14 @@ css-tree@1.0.0-alpha.29:
mdn-data "~1.1.0"
source-map "^0.5.3"
+css-tree@^1.0.0-alpha.39:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
+ integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
+ dependencies:
+ mdn-data "2.0.14"
+ source-map "^0.6.1"
+
css-url-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec"
@@ -9940,20 +9961,29 @@ escodegen@^1.14.1:
optionalDependencies:
source-map "~0.6.1"
+eslint-config-prettier@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a"
+ integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==
+
eslint-plugin-ember-a11y-testing@a11y-tool-sandbox/eslint-plugin-ember-a11y-testing#ca31c9698c7cb105f1c9761d98fcaca7d6874459:
version "0.0.0"
resolved "https://codeload.github.com/a11y-tool-sandbox/eslint-plugin-ember-a11y-testing/tar.gz/ca31c9698c7cb105f1c9761d98fcaca7d6874459"
dependencies:
requireindex "~1.1.0"
-eslint-plugin-ember@^8.9.1:
- version "8.14.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-8.14.0.tgz#fc4c5119b5a1c87604a7bf920ca397783b96b7be"
- integrity sha512-PQhR58omMAZzcJOB8GLWzL6l/vjRZ2Uo1eohxOmgPUyeBkHfZAMlvK+OSeneMLIr4azLQ4GISkklwv6lxb8qnw==
+eslint-plugin-ember@^10.5.8:
+ version "10.5.8"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-ember/-/eslint-plugin-ember-10.5.8.tgz#87e004a5ebed88f94008364554daf57df2c9c718"
+ integrity sha512-d21mJ+F+htgi6HhrjwbOfllJojF4ZWGruW13HkBoGS2SaHqKUyvIH/8j3EjSxlsGFiNfhTEUWkNaUSLJxgbtWg==
dependencies:
"@ember-data/rfc395-data" "^0.0.4"
+ css-tree "^1.0.0-alpha.39"
ember-rfc176-data "^0.3.15"
+ eslint-utils "^3.0.0"
+ estraverse "^5.2.0"
lodash.kebabcase "^4.1.1"
+ requireindex "^1.2.0"
snake-case "^3.0.3"
eslint-plugin-es@^3.0.0:
@@ -9976,6 +10006,21 @@ eslint-plugin-node@^11.1.0:
resolve "^1.10.1"
semver "^6.1.0"
+eslint-plugin-prettier@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz#e9ddb200efb6f3d05ffe83b1665a716af4a387e5"
+ integrity sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==
+ dependencies:
+ prettier-linter-helpers "^1.0.0"
+
+eslint-plugin-qunit@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-qunit/-/eslint-plugin-qunit-6.2.0.tgz#f4efda29da99523e560848d9592c39c0590c308d"
+ integrity sha512-KvPmkIC2MHpfRxs/r8WUeeGkG6y+3qwSi2AZIBtjcM/YG6Z3k0GxW5Hbu3l7X0TDhljVCeBb9Q5puUkHzl83Mw==
+ dependencies:
+ eslint-utils "^3.0.0"
+ requireindex "^1.2.0"
+
eslint-scope@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
@@ -9999,6 +10044,13 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0:
dependencies:
eslint-visitor-keys "^1.1.0"
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
@@ -10009,29 +10061,32 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
-eslint@^7.5.0:
- version "7.19.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.19.0.tgz#6719621b196b5fad72e43387981314e5d0dc3f41"
- integrity sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==
+eslint@^7.32.0:
+ version "7.32.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d"
+ integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==
dependencies:
- "@babel/code-frame" "^7.0.0"
- "@eslint/eslintrc" "^0.3.0"
+ "@babel/code-frame" "7.12.11"
+ "@eslint/eslintrc" "^0.4.3"
+ "@humanwhocodes/config-array" "^0.5.0"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
enquirer "^2.3.5"
+ escape-string-regexp "^4.0.0"
eslint-scope "^5.1.1"
eslint-utils "^2.1.0"
eslint-visitor-keys "^2.0.0"
espree "^7.3.1"
- esquery "^1.2.0"
+ esquery "^1.4.0"
esutils "^2.0.2"
- file-entry-cache "^6.0.0"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
- glob-parent "^5.0.0"
- globals "^12.1.0"
+ glob-parent "^5.1.2"
+ globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
@@ -10039,7 +10094,7 @@ eslint@^7.5.0:
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
- lodash "^4.17.20"
+ lodash.merge "^4.6.2"
minimatch "^3.0.4"
natural-compare "^1.4.0"
optionator "^0.9.1"
@@ -10048,7 +10103,7 @@ eslint@^7.5.0:
semver "^7.2.1"
strip-ansi "^6.0.0"
strip-json-comments "^3.1.0"
- table "^6.0.4"
+ table "^6.0.9"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -10076,10 +10131,10 @@ esprima@~3.0.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9"
integrity sha1-U88kes2ncxPlUcOqLnM0LT+099k=
-esquery@^1.2.0:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57"
- integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==
+esquery@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+ integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
dependencies:
estraverse "^5.1.0"
@@ -10351,6 +10406,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+fast-diff@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
+ integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
+
fast-glob@^2.2.6:
version "2.2.7"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d"
@@ -10475,10 +10535,10 @@ figures@^3.0.0:
dependencies:
escape-string-regexp "^1.0.5"
-file-entry-cache@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a"
- integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
dependencies:
flat-cache "^3.0.4"
@@ -11161,14 +11221,14 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
-glob-parent@^5.0.0, glob-parent@^5.1.0:
+glob-parent@^5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
dependencies:
is-glob "^4.0.1"
-glob-parent@~5.1.0, glob-parent@~5.1.2:
+glob-parent@^5.1.2, glob-parent@~5.1.0, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@@ -11271,12 +11331,12 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
-globals@^12.1.0:
- version "12.4.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
- integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
+globals@^13.6.0, globals@^13.9.0:
+ version "13.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.0.tgz#4d733760304230a0082ed96e21e5c565f898089e"
+ integrity sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==
dependencies:
- type-fest "^0.8.1"
+ type-fest "^0.20.2"
globals@^9.18.0:
version "9.18.0"
@@ -13397,6 +13457,11 @@ lodash.templatesettings@^4.0.0:
dependencies:
lodash._reinterpolate "^3.0.0"
+lodash.truncate@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+ integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
+
lodash.uniq@4.5.0, lodash.uniq@^4.2.0, lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
@@ -13664,6 +13729,11 @@ mdast-util-to-hast@10.0.1:
unist-util-position "^3.0.0"
unist-util-visit "^2.0.0"
+mdn-data@2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
+ integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+
mdn-data@~1.1.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01"
@@ -15233,10 +15303,17 @@ pretender@^3.4.3:
fake-xml-http-request "^2.1.1"
route-recognizer "^0.3.3"
-prettier@^1.4.4:
- version "1.19.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
- integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
+prettier-linter-helpers@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
+ integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
+ dependencies:
+ fast-diff "^1.1.2"
+
+prettier@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
+ integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
prettier@~2.2.1:
version "2.2.1"
@@ -16180,6 +16257,11 @@ require-relative@^0.8.7:
resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de"
integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=
+requireindex@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef"
+ integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==
+
requireindex@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.1.0.tgz#e5404b81557ef75db6e49c5a72004893fe03e162"
@@ -17226,7 +17308,7 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0:
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -17539,15 +17621,16 @@ sync-disk-cache@^2.0.0:
rimraf "^3.0.0"
username-sync "^1.0.2"
-table@^6.0.4:
- version "6.0.7"
- resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34"
- integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==
+table@^6.0.9:
+ version "6.7.5"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.7.5.tgz#f04478c351ef3d8c7904f0e8be90a1b62417d238"
+ integrity sha512-LFNeryOqiQHqCVKzhkymKwt6ozeRhlm8IL1mE8rNUurkir4heF6PzMyRgaTa4tlyPTGGgXuvVOF/OLWiH09Lqw==
dependencies:
- ajv "^7.0.2"
- lodash "^4.17.20"
+ ajv "^8.0.1"
+ lodash.truncate "^4.4.2"
slice-ansi "^4.0.0"
- string-width "^4.2.0"
+ string-width "^4.2.3"
+ strip-ansi "^6.0.1"
tap-parser@^7.0.0:
version "7.0.0"
@@ -18069,6 +18152,11 @@ type-fest@^0.11.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
type-fest@^0.21.3:
version "0.21.3"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"