mirror of
https://github.com/kemko/nomad.git
synced 2026-01-06 10:25:42 +03:00
Test coverage for task-file component
This commit is contained in:
@@ -4,6 +4,7 @@ import { computed } from '@ember/object';
|
||||
export default Component.extend({
|
||||
tagName: 'figure',
|
||||
classNames: 'image-file',
|
||||
'data-test-image-file': true,
|
||||
|
||||
src: null,
|
||||
alt: null,
|
||||
|
||||
@@ -29,7 +29,7 @@ export default Component.extend({
|
||||
|
||||
mode: 'head',
|
||||
|
||||
fileComponent: computed('stat', function() {
|
||||
fileComponent: computed('stat.ContentType', function() {
|
||||
const contentType = this.stat.ContentType || '';
|
||||
|
||||
if (contentType.startsWith('image/')) {
|
||||
@@ -41,7 +41,7 @@ export default Component.extend({
|
||||
}
|
||||
}),
|
||||
|
||||
isLarge: computed('stat', function() {
|
||||
isLarge: computed('stat.Size', function() {
|
||||
return this.stat.Size > 50000;
|
||||
}),
|
||||
|
||||
@@ -107,7 +107,6 @@ export default Component.extend({
|
||||
this.set('noConnection', true);
|
||||
} else {
|
||||
this.send('failoverToServer');
|
||||
this.stream.perform();
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<p>The files for this task are inaccessible. Check the condition of the client the allocation is on.</p>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="boxed-section-head">
|
||||
<div data-test-header class="boxed-section-head">
|
||||
{{yield}}
|
||||
<span class="pull-right">
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
{{else if (eq fileComponent "image")}}
|
||||
{{image-file src=catUrl alt=stat.Name size=stat.Size}}
|
||||
{{else}}
|
||||
<div class="empty-message is-hollow">
|
||||
<div data-test-unsupported-type class="empty-message is-hollow">
|
||||
<h3 class="empty-message-headline">Unsupported File Type</h3>
|
||||
<p class="empty-message-body message">The Nomad UI could not render this file, but you can still call view the file directly.</p>
|
||||
<p class="empty-message-body">
|
||||
|
||||
226
ui/tests/integration/task-file-test.js
Normal file
226
ui/tests/integration/task-file-test.js
Normal file
@@ -0,0 +1,226 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupRenderingTest } from 'ember-qunit';
|
||||
import { render, settled } from '@ember/test-helpers';
|
||||
import { find } from 'ember-native-dom-helpers';
|
||||
import hbs from 'htmlbars-inline-precompile';
|
||||
import Pretender from 'pretender';
|
||||
import { logEncode } from '../../mirage/data/logs';
|
||||
|
||||
const { assign } = Object;
|
||||
const HOST = '1.1.1.1:1111';
|
||||
|
||||
module('Integration | Component | task file', function(hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function() {
|
||||
this.server = new Pretender(function() {
|
||||
this.get('/v1/regions', () => [200, {}, JSON.stringify(['default'])]);
|
||||
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']);
|
||||
});
|
||||
});
|
||||
|
||||
hooks.afterEach(function() {
|
||||
this.server.shutdown();
|
||||
});
|
||||
|
||||
const commonTemplate = hbs`
|
||||
{{task-file allocation=allocation task=task file=file stat=stat}}
|
||||
`;
|
||||
|
||||
const fileStat = (type, size = 0) => ({
|
||||
stat: {
|
||||
Size: size,
|
||||
ContentType: type,
|
||||
},
|
||||
});
|
||||
const makeProps = (props = {}) =>
|
||||
assign(
|
||||
{},
|
||||
{
|
||||
allocation: {
|
||||
id: 'alloc-1',
|
||||
node: {
|
||||
httpAddr: HOST,
|
||||
},
|
||||
},
|
||||
task: {
|
||||
name: 'task-name',
|
||||
},
|
||||
file: 'path/to/file',
|
||||
stat: {
|
||||
Size: 12345,
|
||||
ContentType: 'text/plain',
|
||||
},
|
||||
},
|
||||
props
|
||||
);
|
||||
|
||||
test('When a file is text-based, the file mode is streaming', async function(assert) {
|
||||
const props = makeProps(fileStat('text/plain', 500));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.ok(
|
||||
find('[data-test-file-box] [data-test-log-cli]'),
|
||||
'The streaming file component was rendered'
|
||||
);
|
||||
assert.notOk(
|
||||
find('[data-test-file-box] [data-test-image-file]'),
|
||||
'The image file component was not rendered'
|
||||
);
|
||||
});
|
||||
|
||||
test('When a file is an image, the file mode is image', async function(assert) {
|
||||
const props = makeProps(fileStat('image/png', 1234));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.ok(
|
||||
find('[data-test-file-box] [data-test-image-file]'),
|
||||
'The image file component was rendered'
|
||||
);
|
||||
assert.notOk(
|
||||
find('[data-test-file-box] [data-test-log-cli]'),
|
||||
'The streaming file component was not rendered'
|
||||
);
|
||||
});
|
||||
|
||||
test('When the file is neither text-based or an image, the unsupported file type empty state is shown', async function(assert) {
|
||||
const props = makeProps(fileStat('wat/ohno', 1234));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.notOk(
|
||||
find('[data-test-file-box] [data-test-image-file]'),
|
||||
'The image file component was not rendered'
|
||||
);
|
||||
assert.notOk(
|
||||
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');
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.ok(
|
||||
find('[data-test-unsupported-type] [data-test-log-action="raw"]'),
|
||||
'Unsupported file type message includes a link to the raw file'
|
||||
);
|
||||
|
||||
assert.notOk(
|
||||
find('[data-test-header] [data-test-log-action="raw"]'),
|
||||
'Raw link is no longer in the header'
|
||||
);
|
||||
});
|
||||
|
||||
test('The view raw button goes to the correct API url', async function(assert) {
|
||||
const props = makeProps(fileStat('image/png', 1234));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
const rawLink = find('[data-test-log-action="raw"]');
|
||||
assert.equal(
|
||||
rawLink.getAttribute('href'),
|
||||
`/v1/client/fs/cat/${props.allocation.id}?path=${props.task.name}/${props.file}`,
|
||||
'Raw link href is correct'
|
||||
);
|
||||
|
||||
assert.equal(rawLink.getAttribute('target'), '_blank', 'Raw link opens in a new tab');
|
||||
assert.equal(
|
||||
rawLink.getAttribute('rel'),
|
||||
'noopener noreferrer',
|
||||
'Raw link rel correctly bars openers and referrers'
|
||||
);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.notOk(find('[data-test-log-action="head"]'), 'No head button');
|
||||
assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button');
|
||||
|
||||
this.set('stat.Size', 100000);
|
||||
|
||||
await settled();
|
||||
|
||||
assert.ok(find('[data-test-log-action="head"]'), 'Head button is shown');
|
||||
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) {
|
||||
const props = makeProps(fileStat('image/svg', 5000));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
assert.notOk(find('[data-test-log-action="head"]'), 'No head button');
|
||||
assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button');
|
||||
|
||||
this.set('stat.Size', 100000);
|
||||
|
||||
await settled();
|
||||
|
||||
assert.notOk(find('[data-test-log-action="head"]'), 'Still no head button');
|
||||
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) {
|
||||
const props = makeProps(fileStat('image/svg', 5000));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(hbs`
|
||||
{{#task-file allocation=allocation task=task file=file stat=stat}}
|
||||
<div data-test-yield-spy>Yielded content</div>
|
||||
{{/task-file}}
|
||||
`);
|
||||
|
||||
assert.ok(
|
||||
find('[data-test-header] [data-test-yield-spy]'),
|
||||
'Yielded content shows up in the header'
|
||||
);
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
const classes = Array.from(find('[data-test-file-box]').classList);
|
||||
assert.ok(classes.includes('is-dark'), 'Body is dark');
|
||||
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) {
|
||||
const props = makeProps(fileStat('image/jpeg', 5000));
|
||||
this.setProperties(props);
|
||||
|
||||
await render(commonTemplate);
|
||||
|
||||
let classes = Array.from(find('[data-test-file-box]').classList);
|
||||
assert.notOk(classes.includes('is-dark'), 'Body is not dark');
|
||||
assert.notOk(classes.includes('is-full-bleed'), 'Body is not full-bleed');
|
||||
|
||||
this.set('stat.ContentType', 'something/unknown');
|
||||
|
||||
await settled();
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user