github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/tests/integration/components/fs/file-test.js (about) 1 import { module, test } from 'qunit'; 2 import { setupRenderingTest } from 'ember-qunit'; 3 import { find, click, render, settled } from '@ember/test-helpers'; 4 import hbs from 'htmlbars-inline-precompile'; 5 import Pretender from 'pretender'; 6 import { logEncode } from '../../../../mirage/data/logs'; 7 import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit'; 8 9 const { assign } = Object; 10 const HOST = '1.1.1.1:1111'; 11 12 module('Integration | Component | fs/file', function(hooks) { 13 setupRenderingTest(hooks); 14 15 hooks.beforeEach(function() { 16 this.server = new Pretender(function() { 17 this.get('/v1/agent/members', () => [ 18 200, 19 {}, 20 JSON.stringify({ ServerRegion: 'default', Members: [] }), 21 ]); 22 this.get('/v1/regions', () => [200, {}, JSON.stringify(['default', 'region-2'])]); 23 this.get('/v1/client/fs/stream/:alloc_id', () => [200, {}, logEncode(['Hello World'], 0)]); 24 this.get('/v1/client/fs/cat/:alloc_id', () => [200, {}, 'Hello World']); 25 this.get('/v1/client/fs/readat/:alloc_id', () => [200, {}, 'Hello World']); 26 }); 27 this.system = this.owner.lookup('service:system'); 28 }); 29 30 hooks.afterEach(function() { 31 this.server.shutdown(); 32 window.localStorage.clear(); 33 }); 34 35 const commonTemplate = hbs` 36 <Fs::File @allocation={{allocation}} @taskState={{taskState}} @file={{file}} @stat={{stat}} /> 37 `; 38 39 const fileStat = (type, size = 0) => ({ 40 stat: { 41 Size: size, 42 ContentType: type, 43 }, 44 }); 45 const makeProps = (props = {}) => 46 assign( 47 {}, 48 { 49 allocation: { 50 id: 'alloc-1', 51 node: { 52 httpAddr: HOST, 53 }, 54 }, 55 taskState: { 56 name: 'task-name', 57 }, 58 file: 'path/to/file', 59 stat: { 60 Size: 12345, 61 ContentType: 'text/plain', 62 }, 63 }, 64 props 65 ); 66 67 test('When a file is text-based, the file mode is streaming', async function(assert) { 68 const props = makeProps(fileStat('text/plain', 500)); 69 this.setProperties(props); 70 71 await render(commonTemplate); 72 73 assert.ok( 74 find('[data-test-file-box] [data-test-log-cli]'), 75 'The streaming file component was rendered' 76 ); 77 assert.notOk( 78 find('[data-test-file-box] [data-test-image-file]'), 79 'The image file component was not rendered' 80 ); 81 82 await componentA11yAudit(this.element, assert); 83 }); 84 85 test('When a file is an image, the file mode is image', async function(assert) { 86 const props = makeProps(fileStat('image/png', 1234)); 87 this.setProperties(props); 88 89 await render(commonTemplate); 90 91 assert.ok( 92 find('[data-test-file-box] [data-test-image-file]'), 93 'The image file component was rendered' 94 ); 95 assert.notOk( 96 find('[data-test-file-box] [data-test-log-cli]'), 97 'The streaming file component was not rendered' 98 ); 99 100 await componentA11yAudit(this.element, assert); 101 }); 102 103 test('When the file is neither text-based or an image, the unsupported file type empty state is shown', async function(assert) { 104 const props = makeProps(fileStat('wat/ohno', 1234)); 105 this.setProperties(props); 106 107 await render(commonTemplate); 108 109 assert.notOk( 110 find('[data-test-file-box] [data-test-image-file]'), 111 'The image file component was not rendered' 112 ); 113 assert.notOk( 114 find('[data-test-file-box] [data-test-log-cli]'), 115 'The streaming file component was not rendered' 116 ); 117 assert.ok(find('[data-test-unsupported-type]'), 'Unsupported file type message is shown'); 118 await componentA11yAudit(this.element, assert); 119 }); 120 121 test('The unsupported file type empty state includes a link to the raw file', async function(assert) { 122 const props = makeProps(fileStat('wat/ohno', 1234)); 123 this.setProperties(props); 124 125 await render(commonTemplate); 126 127 assert.ok( 128 find('[data-test-unsupported-type] [data-test-log-action="raw"]'), 129 'Unsupported file type message includes a link to the raw file' 130 ); 131 132 assert.notOk( 133 find('[data-test-header] [data-test-log-action="raw"]'), 134 'Raw link is no longer in the header' 135 ); 136 }); 137 138 test('The view raw button goes to the correct API url', async function(assert) { 139 const props = makeProps(fileStat('image/png', 1234)); 140 this.setProperties(props); 141 142 await render(commonTemplate); 143 click('[data-test-log-action="raw"]'); 144 await settled(); 145 assert.ok( 146 this.server.handledRequests.find( 147 ({ url: url }) => 148 url === 149 `/v1/client/fs/cat/${props.allocation.id}?path=${encodeURIComponent( 150 `${props.taskState.name}/${props.file}` 151 )}` 152 ), 153 'Request to file is made' 154 ); 155 }); 156 157 test('The view raw button respects the active region', async function(assert) { 158 const region = 'region-2'; 159 window.localStorage.nomadActiveRegion = region; 160 161 const props = makeProps(fileStat('image/png', 1234)); 162 this.setProperties(props); 163 164 await this.system.get('regions'); 165 await render(commonTemplate); 166 167 click('[data-test-log-action="raw"]'); 168 await settled(); 169 assert.ok( 170 this.server.handledRequests.find( 171 ({ url: url }) => 172 url === 173 `/v1/client/fs/cat/${props.allocation.id}?path=${encodeURIComponent( 174 `${props.taskState.name}/${props.file}` 175 )}®ion=${region}` 176 ), 177 'Request to file is made with region' 178 ); 179 }); 180 181 test('The head and tail buttons are not shown when the file is small', async function(assert) { 182 const props = makeProps(fileStat('application/json', 5000)); 183 this.setProperties(props); 184 185 await render(commonTemplate); 186 187 assert.notOk(find('[data-test-log-action="head"]'), 'No head button'); 188 assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button'); 189 190 this.set('stat.Size', 100000); 191 192 await settled(); 193 194 assert.ok(find('[data-test-log-action="head"]'), 'Head button is shown'); 195 assert.ok(find('[data-test-log-action="tail"]'), 'Tail button is shown'); 196 }); 197 198 test('The head and tail buttons are not shown for an image file', async function(assert) { 199 const props = makeProps(fileStat('image/svg', 5000)); 200 this.setProperties(props); 201 202 await render(commonTemplate); 203 204 assert.notOk(find('[data-test-log-action="head"]'), 'No head button'); 205 assert.notOk(find('[data-test-log-action="tail"]'), 'No tail button'); 206 207 this.set('stat.Size', 100000); 208 209 await settled(); 210 211 assert.notOk(find('[data-test-log-action="head"]'), 'Still no head button'); 212 assert.notOk(find('[data-test-log-action="tail"]'), 'Still no tail button'); 213 }); 214 215 test('Yielded content goes in the top-left header area', async function(assert) { 216 const props = makeProps(fileStat('image/svg', 5000)); 217 this.setProperties(props); 218 219 await render(hbs` 220 <Fs::File @allocation={{allocation}} @taskState={{taskState}} @file={{file}} @stat={{stat}}> 221 <div data-test-yield-spy>Yielded content</div> 222 </Fs::File> 223 `); 224 225 assert.ok( 226 find('[data-test-header] [data-test-yield-spy]'), 227 'Yielded content shows up in the header' 228 ); 229 230 await componentA11yAudit(this.element, assert); 231 }); 232 233 test('The body is full-bleed and dark when the file is streaming', async function(assert) { 234 const props = makeProps(fileStat('application/json', 5000)); 235 this.setProperties(props); 236 237 await render(commonTemplate); 238 239 const classes = Array.from(find('[data-test-file-box]').classList); 240 assert.ok(classes.includes('is-dark'), 'Body is dark'); 241 assert.ok(classes.includes('is-full-bleed'), 'Body is full-bleed'); 242 }); 243 244 test('The body has padding and a light background when the file is not streaming', async function(assert) { 245 const props = makeProps(fileStat('image/jpeg', 5000)); 246 this.setProperties(props); 247 248 await render(commonTemplate); 249 250 let classes = Array.from(find('[data-test-file-box]').classList); 251 assert.notOk(classes.includes('is-dark'), 'Body is not dark'); 252 assert.notOk(classes.includes('is-full-bleed'), 'Body is not full-bleed'); 253 254 this.set('stat.ContentType', 'something/unknown'); 255 256 await settled(); 257 258 classes = Array.from(find('[data-test-file-box]').classList); 259 assert.notOk(classes.includes('is-dark'), 'Body is still not dark'); 260 assert.notOk(classes.includes('is-full-bleed'), 'Body is still not full-bleed'); 261 }); 262 });