feat: 🎸 Add mirage data for ascii casts and use fetch (#129)
* feat: 🎸 Add mirage data for ascii casts and use fetch ✅ Closes: ICU-8189
This commit is contained in:
1 parent
06af1a9fc4
commit
1e7268ff54
7 files changed
+272
-23
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import ApplicationAdapter from './application';
|
||||
|
||||
export default class SessionRecordingAdapter extends ApplicationAdapter {
|
||||
/**
|
||||
* Overrides the default `buildURL` such that for custom download methods,
|
||||
* URLs will get the query parameters. All other request types behave as normal.
|
||||
*
|
||||
* @param modelName {string}
|
||||
* @param id {string}
|
||||
* @param snapshot {object}
|
||||
* @param requestType {string}
|
||||
* @param query {object}
|
||||
* @returns {string}
|
||||
*/
|
||||
buildURL(modelName, id, snapshot, requestType, query) {
|
||||
let url = super.buildURL(...arguments);
|
||||
const method = snapshot?.adapterOptions?.method;
|
||||
if (method === 'download') {
|
||||
const queryParams = new URLSearchParams(query).toString();
|
||||
if (queryParams) url = `${url}?${queryParams}`;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the download recording for recordings. Takes in a mime type for the
|
||||
* type or recording to return.
|
||||
* The ID can be the session ID, session recording ID,
|
||||
* connection recording ID, or the channel recording ID.
|
||||
* @param id {string}
|
||||
* @param mimeType {string}
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async getRecordingDownload({ id, mimeType }) {
|
||||
const options = { adapterOptions: { method: 'download' } };
|
||||
const url = this.buildURL('session-recording', id, options, 'findRecord', {
|
||||
mime_type: mimeType,
|
||||
});
|
||||
|
||||
const response = await fetch(url);
|
||||
return response.text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ascii cast recording.
|
||||
* @param id
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
getAsciicast(id) {
|
||||
return this.getRecordingDownload({
|
||||
id,
|
||||
mimeType: 'application/x-asciicast',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -24,4 +24,13 @@ export default class ChannelRecordingModel extends GeneratedChannelRecordingMode
|
||||
get isUnknown() {
|
||||
return !TYPES_CHANNEL_RECORDING.includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the ascii cast recording for this channel.
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
getAsciicast() {
|
||||
const adapter = this.store.adapterFor('session-recording');
|
||||
return adapter.getAsciicast(this.id);
|
||||
}
|
||||
}
|
||||
@@ -27,26 +27,4 @@ export default class SessionRecordingModel extends GeneratedSessionRecordingMode
|
||||
get isUnknown() {
|
||||
return !TYPES_SESSION_RECORDING.includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the recording for either session, connection, or channels.
|
||||
* id can be the session ID, session recording ID, connection recording ID,
|
||||
* or the channel recording ID.
|
||||
* @param {string} id
|
||||
* @param {string} mimeType
|
||||
* @returns {Promise}
|
||||
*/
|
||||
getAsciiCast(id) {
|
||||
const adapter = this.store.adapterFor('application');
|
||||
const options = { adapterOptions: { method: 'download' } };
|
||||
const url = adapter.buildURL(
|
||||
'session-recording',
|
||||
id,
|
||||
options,
|
||||
'findRecord'
|
||||
);
|
||||
return adapter.ajax(url, 'GET', {
|
||||
data: { mimeType: 'application/x-asciicast' },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/adapters/session-recording';
|
||||
@@ -15,6 +15,7 @@ import { pickRandomStatusString } from './factories/session';
|
||||
import initializeMockIPC from './scenarios/ipc';
|
||||
import makeBooleanFilter from './helpers/bexpr-filter';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { asciiCasts } from './data/asciicasts';
|
||||
|
||||
const isTesting = environmentConfig.environment === 'test';
|
||||
|
||||
@@ -688,7 +689,19 @@ function routes() {
|
||||
return sessionRecordings.where({ scopeId });
|
||||
}
|
||||
);
|
||||
this.get('/session-recordings/:id');
|
||||
this.get(
|
||||
'/session-recordings/:idMethod',
|
||||
async ({ sessionRecordings }, { params: { idMethod } }) => {
|
||||
const id = idMethod.split(':')[0];
|
||||
const method = idMethod.split(':')[1];
|
||||
|
||||
if (method === 'download') {
|
||||
return faker.helpers.arrayElement(asciiCasts);
|
||||
} else {
|
||||
return sessionRecordings.find(id);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* Uncomment the following line and the Response import above
|
||||
* Then change the response code to simulate error responses.
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
export const asciiCast1 = `{"version": 2, "width": 124, "height": 36, "timestamp": 1670352594, "env": {"SHELL": "/bin/zsh", "TERM": "xterm-256color"}}
|
||||
[2.138652, "o", "\\u001b[1m\\u001b[7m%\\u001b[27m\\u001b[1m\\u001b[0m \\r \\r\\u001b]2;ember-asciinema-player\\u0007\\u001b]1;..iinema-player\\u0007"]
|
||||
[2.220877, "o", "\\r\\u001b[0m\\u001b[27m\\u001b[24m\\u001b[J\\u001b[33member-asciinema-player\\u001b[00m \\u001b[32mgit\\u001b[00m:\\u001b[36m(main*)\\u001b[00m $ \\u001b[K"]
|
||||
[2.221019, "o", "\\u001b[?1h\\u001b="]
|
||||
[2.221076, "o", "\\u001b[?2004h"]
|
||||
[2.676444, "o", "y"]
|
||||
[2.788653, "o", "\\bya"]
|
||||
[2.868652, "o", "r"]
|
||||
[3.001764, "o", "n"]
|
||||
[3.167636, "o", " "]
|
||||
[3.313668, "o", "t"]
|
||||
[3.460527, "o", "e"]
|
||||
[3.561983, "o", "s"]
|
||||
[3.63678, "o", "t"]
|
||||
[3.853437, "o", "\\u001b[?1l\\u001b>"]
|
||||
[3.853473, "o", "\\u001b[?2004l\\r\\r\\n"]
|
||||
[3.854604, "o", "\\u001b]2;yarn test\\u0007\\u001b]1;yarn\\u0007"]
|
||||
[4.489178, "o", "\\u001b[2K"]
|
||||
[4.48982, "o", "\\u001b[1G\\u001b[1myarn run v1.22.19\\u001b[22m\\r\\n"]
|
||||
[4.555618, "o", "\\u001b[2K"]
|
||||
[4.555649, "o", "\\u001b[1G\\u001b[2m$ npm-run-all lint\\u001b[22m\\r\\n"]
|
||||
[5.345253, "o", "\\u001b[2K"]
|
||||
[5.345509, "o", "\\u001b[1G\\u001b[2m$ npm-run-all --print-name --aggregate-output --continue-on-error --parallel \\"lint:!(fix)\\"\\u001b[22m\\r\\n"]
|
||||
[7.225926, "o", "\\r\\n> ember-asciinema-player@0.0.0 lint:js ember-asciinema-player/package.json\\r\\n> eslint . --cache \\r\\n\\r\\n$ eslint . --cache\\r\\n"]
|
||||
[8.398641, "o", "\\r\\n> ember-asciinema-player@0.0.0 lint:hbs ember-asciinema-player/package.json\\r\\n> ember-template-lint . \\r\\n\\r\\n$ ember-template-lint .\\r\\n\\r\\n"]
|
||||
[8.418537, "o", "\\u001b[2K\\u001b[1G\\u001b[2m$ ember test\\u001b[22m\\r\\n"]
|
||||
[12.256156, "o", "\\u001b[?25l"]
|
||||
[12.256464, "o", "\\u001b[32m⠋\\u001b[39m \\u001b[32mBuilding\\u001b[39m"]
|
||||
[12.2573, "o", "\\u001b[2K"]
|
||||
[12.257386, "o", "\\u001b[1G\\u001b[?25h"]
|
||||
[12.257689, "o", "Environment: test\\r\\n"]
|
||||
[12.257857, "o", "\\u001b[?25l\\u001b[32m⠋\\u001b[39m \\u001b[32mBuilding\\u001b[39m"]
|
||||
[12.539035, "o", "\\u001b[2K"]
|
||||
[12.539144, "o", "\\u001b[1G"]
|
||||
[12.539219, "o", "\\u001b[32m⠙\\u001b[39m \\u001b[32mbuilding... \\u001b[39m"]
|
||||
[12.745202, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[12.745343, "o", "\\u001b[32m⠹\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Babel: @ember/test-helpers > applyPatches]"]
|
||||
[12.825004, "o", "\\u001b[2K"]
|
||||
[12.825031, "o", "\\u001b[1G"]
|
||||
[12.825122, "o", "\\u001b[32m⠸\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Babel: ember-qunit > applyPatches]"]
|
||||
[12.933588, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[12.933624, "o", "\\u001b[32m⠼\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Babel: ember-load-initializers > applyPatches]"]
|
||||
[13.194738, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[13.195009, "o", "\\u001b[32m⠴\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Babel: ember-asciinema-player > applyPatches]"]
|
||||
[13.307878, "o", "\\u001b[2K\\u001b[1G\\u001b[32m⠦\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Package /assets/vendor.js]"]
|
||||
[13.750717, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[13.750755, "o", "\\u001b[32m⠧\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[Concat: Test Support JS]"]
|
||||
[13.869411, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[13.869438, "o", "\\u001b[32m⠇\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[ember-auto-import-webpack]"]
|
||||
[14.655374, "o", "\\u001b[2K\\u001b[1G"]
|
||||
[14.655415, "o", "\\u001b[32m⠏\\u001b[39m \\u001b[32mbuilding... \\u001b[39m[ember-auto-import-webpack]"]
|
||||
[14.73686, "o", "\\u001b[2K\\u001b[1G\\u001b[?25h"]
|
||||
[14.738533, "o", "\\u001b[?25h"]
|
||||
[14.738818, "o", "\\u001b[?25l\\u001b[32m⠋\\u001b[39m cleaning up"]
|
||||
[14.739061, "o", "\\u001b[2K\\u001b[1G\\u001b[?25hcleaning up...\\r\\n"]
|
||||
[14.739197, "o", "\\u001b[?25l\\u001b[32m⠋\\u001b[39m cleaning up"]
|
||||
[14.907985, "o", "\\u001b[2K"]
|
||||
[14.90808, "o", "\\u001b[1G\\u001b[?25h"]
|
||||
[14.908128, "o", "\\u001b[32mBuilt project successfully.\\u001b[39m\\r\\n"]
|
||||
[16.224632, "o", "ok 1 Chrome 108.0 - [2 ms] - ember-qunit: Ember.onerror validation: Ember.onerror is functioning properly\\r\\n"]
|
||||
[16.346568, "o", "\\r\\n1..1\\r\\n# tests 1\\r\\n# pass 1\\r\\n# skip 0\\r\\n# todo 0\\r\\n# fail 0\\r\\n\\r\\n# ok\\r\\n"]
|
||||
[16.403167, "o", "\\u001b[2K"]
|
||||
[16.403388, "o", "\\u001b[1G✨ Done in 11.92s.\\r\\n"]
|
||||
[16.413967, "o", "\\u001b[1m\\u001b[7m%\\u001b[27m\\u001b[1m\\u001b[0m \\r \\r"]
|
||||
[16.414147, "o", "\\u001b]2;ember-asciinema-player\\u0007\\u001b]1;..iinema-player\\u0007"]
|
||||
[16.528341, "o", "\\r\\u001b[0m\\u001b[27m\\u001b[24m\\u001b[J\\u001b[33member-asciinema-player\\u001b[00m \\u001b[32mgit\\u001b[00m:\\u001b[36m(main*)\\u001b[00m $ \\u001b[K"]
|
||||
[16.528501, "o", "\\u001b[?1h\\u001b="]
|
||||
[16.52863, "o", "\\u001b[?2004h"]
|
||||
[19.078794, "o", "\\u001b[?2004l\\r\\r\\n"]`;
|
||||
|
||||
export const asciiCast2 = `{"version": 2, "width": 112, "height": 30, "timestamp": 1672793720, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
|
||||
[0.036928, "o", "\\u001b[?2004h\\u001b[1;32m[\\u001b]0;johan@nixos: ~/src/hashicorp/boundary-enterprise\\u0007johan@nixos:~/src/hashicorp/boundary-enterprise]$\\u001b[0m "]
|
||||
[2.827983, "o", "b"]
|
||||
[2.9386, "o", "o"]
|
||||
[2.97036, "o", "u"]
|
||||
[3.032542, "o", "n"]
|
||||
[3.108687, "o", "d"]
|
||||
[3.246045, "o", "a"]
|
||||
[3.340117, "o", "r"]
|
||||
[3.841216, "o", "y"]
|
||||
[4.314958, "o", " "]
|
||||
[6.052102, "o", "u"]
|
||||
[6.146486, "o", "s"]
|
||||
[6.207341, "o", "e"]
|
||||
[6.273087, "o", "r"]
|
||||
[6.378873, "o", "s"]
|
||||
[6.799687, "o", " "]
|
||||
[7.08347, "o", "l"]
|
||||
[7.159196, "o", "i"]
|
||||
[7.249656, "o", "s"]
|
||||
[7.352251, "o", "t"]
|
||||
[7.450038, "o", " "]
|
||||
[7.688195, "o", "-"]
|
||||
[7.931818, "o", "r"]
|
||||
[8.001542, "o", "e"]
|
||||
[8.387771, "o", "c"]
|
||||
[8.526339, "o", "u"]
|
||||
[8.631438, "o", "r"]
|
||||
[8.81899, "o", "s"]
|
||||
[8.958184, "o", "i"]
|
||||
[9.085688, "o", "v"]
|
||||
[9.134885, "o", "e"]
|
||||
[9.786868, "o", "\\r\\n"]
|
||||
[9.788828, "o", "\\u001b[?2004l\\r"]
|
||||
[10.086691, "o", "\\u001b[0m\\r\\nUser information:\\r\\n ID: u_anon\\r\\n Scope ID: global\\r\\n Version: 1\\r\\n Name: anonymous\\r\\n Description: The anonymous user matches any request, whether authenticated or not\\r\\n Authorized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-accounts\\r\\n set-accounts\\r\\n remove-accounts\\r\\n\\r\\n ID: u_auth\\r\\n Scope ID: global\\r\\n Version: 1\\r\\n Name: authenticated\\r\\n Description: The authenticated user matches any user that has a valid token\\r\\n Authorized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-accounts\\r\\n set-accounts\\r\\n remove-accounts\\r\\n\\r\\n ID: u_recovery\\r\\n Scope ID: global\\r\\n Version: 1\\r\\n Name: recovery\\r\\n Description: The recovery user is used for any request that was performed with the recovery KMS\\r\\n workflow\\r\\n Autho"]
|
||||
[10.086736, "o", "rized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-accounts\\r\\n set-accounts\\r\\n remove-accounts\\r\\n\\r\\n ID: u_1234567890\\r\\n Scope ID: global\\r\\n Version: 3\\r\\n Name: admin\\r\\n Description: Initial admin user within the \\"global\\" scope\\r\\n Primary Account ID: acctpw_1234567890\\r\\n Login Name: admin\\r\\n Authorized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-accounts\\r\\n set-accounts\\r\\n remove-accounts\\r\\n\\r\\n ID: u_0987654321\\r\\n Scope ID: global\\r\\n Version: 3\\r\\n Name: user\\r\\n Description: Initial unprivileged user\\r\\n Primary Account ID: acctpw_0987654321\\r\\n Login Name: user\\r\\n Authorized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-accounts\\r\\n set-accounts\\r\\n remove-accounts\\u001b[0m\\r\\n"]
|
||||
[10.106453, "o", "\\u001b[?2004h\\u001b[1;32m[\\u001b]0;johan@nixos: ~/src/hashicorp/boundary-enterprise\\u0007johan@nixos:~/src/hashicorp/boundary-enterprise]$\\u001b[0m "]
|
||||
[12.501496, "o", "b"]
|
||||
[12.703134, "o", "o"]
|
||||
[12.752198, "o", "u"]
|
||||
[12.775329, "o", "n"]
|
||||
[12.905261, "o", "d"]
|
||||
[13.002373, "o", "a"]
|
||||
[13.100111, "o", "r"]
|
||||
[13.354779, "o", "y"]
|
||||
[13.699827, "o", " "]
|
||||
[13.998849, "o", "t"]
|
||||
[14.139192, "o", "a"]
|
||||
[14.19663, "o", "r"]
|
||||
[14.392075, "o", "g"]
|
||||
[14.489938, "o", "e"]
|
||||
[14.579533, "o", "t"]
|
||||
[14.674628, "o", "s"]
|
||||
[14.830951, "o", " "]
|
||||
[15.015311, "o", "l"]
|
||||
[15.077147, "o", "i"]
|
||||
[15.262221, "o", "s"]
|
||||
[15.355571, "o", "t"]
|
||||
[15.456597, "o", " "]
|
||||
[15.91612, "o", "-"]
|
||||
[16.264491, "o", "r"]
|
||||
[16.351595, "o", "e"]
|
||||
[16.798456, "o", "c"]
|
||||
[16.891689, "o", "u"]
|
||||
[16.997975, "o", "r"]
|
||||
[17.176378, "o", "s"]
|
||||
[17.290104, "o", "i"]
|
||||
[17.434691, "o", "v"]
|
||||
[17.482502, "o", "e"]
|
||||
[18.393541, "o", "\\r\\n"]
|
||||
[18.39558, "o", "\\u001b[?2004l\\r"]
|
||||
[18.673452, "o", "\\u001b[0m\\r\\nTarget information:\\r\\n ID: ttcp_1234567890\\r\\n Scope ID: p_1234567890\\r\\n Version: 2\\r\\n Type: tcp\\r\\n Name: Generated target\\r\\n Description: Provides an initial target in Boundary\\r\\n Authorized Actions:\\r\\n no-op\\r\\n read\\r\\n update\\r\\n delete\\r\\n add-host-sources\\r\\n set-host-sources\\r\\n remove-host-sources\\r\\n add-credential-sources\\r\\n set-credential-sources\\r\\n remove-credential-sources\\r\\n authorize-session\\u001b[0m\\r\\n"]
|
||||
[18.692528, "o", "\\u001b[?2004h\\u001b[1;32m[\\u001b]0;johan@nixos: ~/src/hashicorp/boundary-enterprise\\u0007johan@nixos:~/src/hashicorp/boundary-enterprise]$\\u001b[0m "]
|
||||
[20.083966, "o", "e"]
|
||||
[20.37301, "o", "x"]
|
||||
[20.51445, "o", "i"]
|
||||
[20.612885, "o", "t"]
|
||||
[21.303896, "o", "\\r\\n"]
|
||||
[21.307902, "o", "\\u001b[?2004l\\rexit\\r\\n"]`;
|
||||
|
||||
export const asciiCasts = [asciiCast1, asciiCast2];
|
||||
@@ -0,0 +1,42 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Adapter | session recording', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it generates correct URLs for downloading asciicast', function (assert) {
|
||||
assert.expect(1);
|
||||
const mockSnapshot = {
|
||||
adapterOptions: {
|
||||
method: 'download',
|
||||
},
|
||||
};
|
||||
const queryObject = {
|
||||
mime_type: 'mimeType',
|
||||
};
|
||||
const adapter = this.owner.lookup('adapter:session-recording');
|
||||
const createRecordURL = adapter.buildURL(
|
||||
'session-recording',
|
||||
'sr_id',
|
||||
mockSnapshot,
|
||||
'findRecord',
|
||||
queryObject
|
||||
);
|
||||
assert.strictEqual(
|
||||
createRecordURL,
|
||||
'/v1/session-recordings/sr_id:download?mime_type=mimeType'
|
||||
);
|
||||
});
|
||||
|
||||
test('it generates correct URLs for retrieving session-recordings', function (assert) {
|
||||
assert.expect(1);
|
||||
const adapter = this.owner.lookup('adapter:session-recording');
|
||||
const createRecordURL = adapter.buildURL(
|
||||
'session-recording',
|
||||
'sr_id',
|
||||
{},
|
||||
'findRecord'
|
||||
);
|
||||
assert.strictEqual(createRecordURL, '/v1/session-recordings/sr_id');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user