52a62f2b8d
UI to accompany the new ACLs APIs
482 lines
17 KiB
JavaScript
482 lines
17 KiB
JavaScript
/* eslint no-console: "off" */
|
|
import Inflector from 'ember-inflector';
|
|
import yadda from './helpers/yadda';
|
|
import { currentURL, click, triggerKeyEvent, fillIn, find } from '@ember/test-helpers';
|
|
import getDictionary from '@hashicorp/ember-cli-api-double/dictionary';
|
|
import pages from 'consul-ui/tests/pages';
|
|
import api from 'consul-ui/tests/helpers/api';
|
|
// const dont = `( don't| shouldn't| can't)?`;
|
|
const pluralize = function(str) {
|
|
return Inflector.inflector.pluralize(str);
|
|
};
|
|
const create = function(number, name, value) {
|
|
// don't return a promise here as
|
|
// I don't need it to wait
|
|
api.server.createList(name, number, value);
|
|
};
|
|
const lastRequest = function(method) {
|
|
return api.server.history
|
|
.slice(0)
|
|
.reverse()
|
|
.find(function(item) {
|
|
return item.method === method;
|
|
});
|
|
};
|
|
const fillInElement = function(page, name, value) {
|
|
const cm = document.querySelector(`textarea[name="${name}"] + .CodeMirror`);
|
|
if (cm) {
|
|
cm.CodeMirror.setValue(value);
|
|
return page;
|
|
} else {
|
|
return page.fillIn(name, value);
|
|
}
|
|
};
|
|
var currentPage;
|
|
export default function(assert) {
|
|
return (
|
|
yadda.localisation.English.library(
|
|
getDictionary(function(model, cb) {
|
|
switch (model) {
|
|
case 'datacenter':
|
|
case 'datacenters':
|
|
case 'dcs':
|
|
model = 'dc';
|
|
break;
|
|
case 'services':
|
|
model = 'service';
|
|
break;
|
|
case 'nodes':
|
|
model = 'node';
|
|
break;
|
|
case 'kvs':
|
|
model = 'kv';
|
|
break;
|
|
case 'acls':
|
|
model = 'acl';
|
|
break;
|
|
case 'sessions':
|
|
model = 'session';
|
|
break;
|
|
case 'intentions':
|
|
model = 'intention';
|
|
break;
|
|
}
|
|
cb(null, model);
|
|
}, yadda)
|
|
)
|
|
// doubles
|
|
.given(['$number $model model[s]?', '$number $model models'], function(number, model) {
|
|
return create(number, model);
|
|
})
|
|
.given(['$number $model model[s]? with the value "$value"'], function(number, model, value) {
|
|
return create(number, model, value);
|
|
})
|
|
.given(
|
|
['$number $model model[s]? from yaml\n$yaml', '$number $model model[s]? from json\n$json'],
|
|
function(number, model, data) {
|
|
return create(number, model, data);
|
|
}
|
|
)
|
|
// TODO: Abstract this away from HTTP
|
|
.given(['the url "$url" responds with a $status status'], function(url, status) {
|
|
return api.server.respondWithStatus(url.split('?')[0], parseInt(status));
|
|
})
|
|
// interactions
|
|
.when('I visit the $name page', function(name) {
|
|
currentPage = pages[name];
|
|
return currentPage.visit();
|
|
})
|
|
.when('I visit the $name page for the "$id" $model', function(name, id, model) {
|
|
currentPage = pages[name];
|
|
return currentPage.visit({
|
|
[model]: id,
|
|
});
|
|
})
|
|
.when(
|
|
['I visit the $name page for yaml\n$yaml', 'I visit the $name page for json\n$json'],
|
|
function(name, data) {
|
|
currentPage = pages[name];
|
|
// TODO: Consider putting an assertion here for testing the current url
|
|
// do I absolutely definitely need that all the time?
|
|
return pages[name].visit(data);
|
|
}
|
|
)
|
|
.when('I click "$selector"', function(selector) {
|
|
return click(selector);
|
|
})
|
|
// TODO: Probably nicer to think of better vocab than having the 'without " rule'
|
|
.when('I click (?!")$property(?!")', function(property) {
|
|
try {
|
|
return currentPage[property]();
|
|
} catch (e) {
|
|
console.error(e);
|
|
throw new Error(`The '${property}' property on the page object doesn't exist`);
|
|
}
|
|
})
|
|
.when('I click $prop on the $component', function(prop, component) {
|
|
// Collection
|
|
var obj;
|
|
if (typeof currentPage[component].objectAt === 'function') {
|
|
obj = currentPage[component].objectAt(0);
|
|
} else {
|
|
obj = currentPage[component];
|
|
}
|
|
const func = obj[prop].bind(obj);
|
|
try {
|
|
return func();
|
|
} catch (e) {
|
|
throw new Error(
|
|
`The '${prop}' property on the '${component}' page object doesn't exist.\n${e.message}`
|
|
);
|
|
}
|
|
})
|
|
.when('I submit', function(selector) {
|
|
return currentPage.submit();
|
|
})
|
|
.then('I fill in "$name" with "$value"', function(name, value) {
|
|
return currentPage.fillIn(name, value);
|
|
})
|
|
.then(['I fill in with yaml\n$yaml', 'I fill in with json\n$json'], function(data) {
|
|
return Object.keys(data).reduce(function(prev, item, i, arr) {
|
|
return fillInElement(prev, item, data[item]);
|
|
}, currentPage);
|
|
})
|
|
.then(
|
|
['I fill in the $form form with yaml\n$yaml', 'I fill in the $form with json\n$json'],
|
|
function(form, data) {
|
|
return Object.keys(data).reduce(function(prev, item, i, arr) {
|
|
const name = `${form}[${item}]`;
|
|
return fillInElement(prev, name, data[item]);
|
|
}, currentPage);
|
|
}
|
|
)
|
|
.then(['I type "$text" into "$selector"'], function(text, selector) {
|
|
return fillIn(selector, text);
|
|
})
|
|
.then(['I type with yaml\n$yaml'], function(data) {
|
|
const keys = Object.keys(data);
|
|
return keys
|
|
.reduce(function(prev, item, i, arr) {
|
|
return prev.fillIn(item, data[item]);
|
|
}, currentPage)
|
|
.then(function() {
|
|
return Promise.all(
|
|
keys.map(function(item) {
|
|
return triggerKeyEvent(`[name="${item}"]`, 'keyup', 83); // TODO: This is 's', be more generic
|
|
})
|
|
);
|
|
});
|
|
})
|
|
// debugging helpers
|
|
.then('print the current url', function(url) {
|
|
console.log(currentURL());
|
|
return Promise.resolve();
|
|
})
|
|
.then('log the "$text"', function(text) {
|
|
console.log(text);
|
|
return Promise.resolve();
|
|
})
|
|
.then('pause for $milliseconds', function(milliseconds) {
|
|
return new Promise(function(resolve) {
|
|
setTimeout(resolve, milliseconds);
|
|
});
|
|
})
|
|
// assertions
|
|
.then('a $method request is made to "$url" with the body from yaml\n$yaml', function(
|
|
method,
|
|
url,
|
|
data
|
|
) {
|
|
const request = api.server.history[api.server.history.length - 2];
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
const body = JSON.parse(request.requestBody);
|
|
Object.keys(data).forEach(function(key, i, arr) {
|
|
assert.deepEqual(
|
|
body[key],
|
|
data[key],
|
|
`Expected the payload to contain ${key} equaling ${data[key]}, ${key} was ${body[key]}`
|
|
);
|
|
});
|
|
})
|
|
// TODO: This one can replace the above one, it covers more use cases
|
|
// also DRY it out a bit
|
|
.then('a $method request is made to "$url" from yaml\n$yaml', function(method, url, yaml) {
|
|
const request = api.server.history[api.server.history.length - 2];
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
let data = yaml.body || {};
|
|
const body = JSON.parse(request.requestBody);
|
|
Object.keys(data).forEach(function(key, i, arr) {
|
|
assert.equal(
|
|
body[key],
|
|
data[key],
|
|
`Expected the payload to contain ${key} to equal ${body[key]}, ${key} was ${data[key]}`
|
|
);
|
|
});
|
|
data = yaml.headers || {};
|
|
const headers = request.requestHeaders;
|
|
Object.keys(data).forEach(function(key, i, arr) {
|
|
assert.equal(
|
|
headers[key],
|
|
data[key],
|
|
`Expected the payload to contain ${key} to equal ${headers[key]}, ${key} was ${
|
|
data[key]
|
|
}`
|
|
);
|
|
});
|
|
})
|
|
.then('a $method request is made to "$url" with the body "$body"', function(
|
|
method,
|
|
url,
|
|
data
|
|
) {
|
|
const request = api.server.history[api.server.history.length - 2];
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
const body = request.requestBody;
|
|
assert.equal(body, data, `Expected the request body to be ${data}, was ${body}`);
|
|
})
|
|
.then('a $method request is made to "$url" with no body', function(method, url) {
|
|
const request = api.server.history[api.server.history.length - 2];
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
const body = request.requestBody;
|
|
assert.equal(body, null, `Expected the request body to be null, was ${body}`);
|
|
})
|
|
|
|
.then('a $method request is made to "$url"', function(method, url) {
|
|
const request = api.server.history[api.server.history.length - 2];
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
})
|
|
.then('the last $method request was made to "$url"', function(method, url) {
|
|
const request = lastRequest(method);
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
})
|
|
.then('the last $method request was made to "$url" with the body from yaml\n$yaml', function(
|
|
method,
|
|
url,
|
|
data
|
|
) {
|
|
const request = lastRequest(method);
|
|
assert.ok(request, `Expected a ${method} request`);
|
|
assert.equal(
|
|
request.method,
|
|
method,
|
|
`Expected the request method to be ${method}, was ${request.method}`
|
|
);
|
|
assert.equal(request.url, url, `Expected the request url to be ${url}, was ${request.url}`);
|
|
const body = JSON.parse(request.requestBody);
|
|
Object.keys(data).forEach(function(key, i, arr) {
|
|
assert.deepEqual(
|
|
body[key],
|
|
data[key],
|
|
`Expected the payload to contain ${key} equaling ${data[key]}, ${key} was ${body[key]}`
|
|
);
|
|
});
|
|
})
|
|
.then('the last $method requests were like yaml\n$yaml', function(method, data) {
|
|
const requests = api.server.history.reverse().filter(function(item) {
|
|
return item.method === method;
|
|
});
|
|
data.reverse().forEach(function(item, i, arr) {
|
|
assert.equal(
|
|
requests[i].url,
|
|
item,
|
|
`Expected the request url to be ${item}, was ${requests[i].url}`
|
|
);
|
|
});
|
|
})
|
|
.then('the url should be $url', function(url) {
|
|
// TODO: nice! $url should be wrapped in ""
|
|
if (url === "''") {
|
|
url = '';
|
|
}
|
|
const current = currentURL() || '';
|
|
assert.equal(current, url, `Expected the url to be ${url} was ${current}`);
|
|
})
|
|
.then(['I see $num $model', 'I see $num $model model', 'I see $num $model models'], function(
|
|
num,
|
|
model
|
|
) {
|
|
const len = currentPage[pluralize(model)].filter(function(item) {
|
|
return item.isVisible;
|
|
}).length;
|
|
|
|
assert.equal(len, num, `Expected ${num} ${pluralize(model)}, saw ${len}`);
|
|
})
|
|
// TODO: I${ dont } see
|
|
.then([`I see $num $model model[s]? with the $property "$value"`], function(
|
|
// negate,
|
|
num,
|
|
model,
|
|
property,
|
|
value
|
|
) {
|
|
const len = currentPage[pluralize(model)].filter(function(item) {
|
|
return item.isVisible && item[property] == value;
|
|
}).length;
|
|
assert.equal(
|
|
len,
|
|
num,
|
|
`Expected ${num} ${pluralize(model)} with ${property} set to "${value}", saw ${len}`
|
|
);
|
|
})
|
|
// TODO: Make this accept a 'contains' word so you can search for text containing also
|
|
.then('I have settings like yaml\n$yaml', function(data) {
|
|
// TODO: Inject this
|
|
const settings = window.localStorage;
|
|
Object.keys(data).forEach(function(prop) {
|
|
const actual = settings.getItem(prop);
|
|
const expected = data[prop];
|
|
assert.strictEqual(actual, expected, `Expected settings to be ${expected} was ${actual}`);
|
|
});
|
|
})
|
|
.then('I see $property on the $component like yaml\n$yaml', function(
|
|
property,
|
|
component,
|
|
yaml
|
|
) {
|
|
const _component = currentPage[component];
|
|
const iterator = new Array(_component.length).fill(true);
|
|
// this will catch if we get aren't managing to select a component
|
|
assert.ok(iterator.length > 0);
|
|
iterator.forEach(function(item, i, arr) {
|
|
const actual =
|
|
typeof _component.objectAt(i)[property] === 'undefined'
|
|
? null
|
|
: _component.objectAt(i)[property];
|
|
|
|
// anything coming from the DOM is going to be text/strings
|
|
// if the yaml has numbers, cast them to strings
|
|
// TODO: This would get problematic for deeper objects
|
|
// will have to look to do this recursively
|
|
const expected = typeof yaml[i] === 'number' ? yaml[i].toString() : yaml[i];
|
|
|
|
assert.deepEqual(
|
|
actual,
|
|
expected,
|
|
`Expected to see ${property} on ${component}[${i}] as ${JSON.stringify(
|
|
expected
|
|
)}, was ${JSON.stringify(actual)}`
|
|
);
|
|
});
|
|
})
|
|
.then(['I see $property on the $component'], function(property, component) {
|
|
// TODO: Time to work on repetition
|
|
// Collection
|
|
var obj;
|
|
if (typeof currentPage[component].objectAt === 'function') {
|
|
obj = currentPage[component].objectAt(0);
|
|
} else {
|
|
obj = currentPage[component];
|
|
}
|
|
let _component;
|
|
if (typeof obj === 'function') {
|
|
const func = obj[property].bind(obj);
|
|
try {
|
|
_component = func();
|
|
} catch (e) {
|
|
console.error(e);
|
|
throw new Error(
|
|
`The '${property}' property on the '${component}' page object doesn't exist`
|
|
);
|
|
}
|
|
} else {
|
|
_component = obj;
|
|
}
|
|
assert.ok(_component[property], `Expected to see ${property} on ${component}`);
|
|
})
|
|
.then(["I don't see $property on the $component"], function(property, component) {
|
|
// Collection
|
|
var obj;
|
|
if (typeof currentPage[component].objectAt === 'function') {
|
|
obj = currentPage[component].objectAt(0);
|
|
} else {
|
|
obj = currentPage[component];
|
|
}
|
|
const func = obj[property].bind(obj);
|
|
assert.throws(
|
|
function() {
|
|
func();
|
|
},
|
|
function(e) {
|
|
return e.toString().indexOf('Element not found') !== -1;
|
|
},
|
|
`Expected to not see ${property} on ${component}`
|
|
);
|
|
})
|
|
.then(["I don't see $property"], function(property) {
|
|
assert.throws(
|
|
function() {
|
|
currentPage[property]();
|
|
},
|
|
function(e) {
|
|
return e.toString().indexOf('Element not found') !== -1;
|
|
},
|
|
`Expected to not see ${property}`
|
|
);
|
|
})
|
|
.then(['I see $property'], function(property) {
|
|
assert.ok(currentPage[property], `Expected to see ${property}`);
|
|
})
|
|
.then(['I see $property like "$value"'], function(property, value) {
|
|
assert.equal(
|
|
currentPage[property],
|
|
value,
|
|
`Expected to see ${property}, was ${currentPage[property]}`
|
|
);
|
|
})
|
|
.then(['I see the text "$text" in "$selector"'], function(text, selector) {
|
|
assert.ok(
|
|
find(selector).textContent.indexOf(text) !== -1,
|
|
`Expected to see "${text}" in "${selector}"`
|
|
);
|
|
})
|
|
// TODO: Think of better language
|
|
// TODO: These should be mergeable
|
|
.then(['"$selector" has the "$class" class'], function(selector, cls) {
|
|
// because `find` doesn't work, guessing its sandboxed to ember's container
|
|
assert.ok(
|
|
document.querySelector(selector).classList.contains(cls),
|
|
`Expected [class] to contain ${cls} on ${selector}`
|
|
);
|
|
})
|
|
.then(['"$selector" doesn\'t have the "$class" class'], function(selector, cls) {
|
|
assert.ok(
|
|
!document.querySelector(selector).classList.contains(cls),
|
|
`Expected [class] not to contain ${cls} on ${selector}`
|
|
);
|
|
})
|
|
.then('ok', function() {
|
|
assert.ok(true);
|
|
})
|
|
);
|
|
}
|