@sasjs/cli 6.14.0 → 6.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/commands/build/internal/mockSite/assets/sw.js +742 -173
- package/build/commands/build/internal/mockSite/mockSite.d.ts +10 -0
- package/build/commands/build/internal/mockSite/mockSite.js +208 -32
- package/build/commands/build/internal/mockSite/spec/mockSite.spec.js +102 -6
- package/build/commands/build/internal/mockSite/spec/sw.spec.js +661 -34
- package/package.json +2 -1
|
@@ -68,6 +68,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
68
68
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
69
69
|
var path_1 = __importDefault(require("path"));
|
|
70
70
|
var api_1 = require("@sasjs/api");
|
|
71
|
+
var os_1 = __importDefault(require("os"));
|
|
72
|
+
var yazl_1 = __importDefault(require("yazl"));
|
|
73
|
+
var mockSite_1 = require("../mockSite");
|
|
71
74
|
/**
|
|
72
75
|
* The other half of the parity claim: the service worker is what turns an
|
|
73
76
|
* /SASjsApi/ request into a response, so its framing (webout body, the _debug
|
|
@@ -86,6 +89,19 @@ var drivePath = function (relative) {
|
|
|
86
89
|
var apiBrowserBuild = function () {
|
|
87
90
|
return path_1.default.join(path_1.default.dirname(require.resolve('@sasjs/api')), '..', '..', 'build', 'browser.js');
|
|
88
91
|
};
|
|
92
|
+
/**
|
|
93
|
+
* The lint bundle the site ships, built once for the suite from the installed
|
|
94
|
+
* packages - the same call `sasjs build` makes, so the worker under test answers
|
|
95
|
+
* the code routes with the code the site carries.
|
|
96
|
+
*/
|
|
97
|
+
var lintBundlePath;
|
|
98
|
+
var lintBundle = function () {
|
|
99
|
+
if (!lintBundlePath) {
|
|
100
|
+
lintBundlePath = path_1.default.join(os_1.default.tmpdir(), "sasjs-lint-".concat(process.pid, ".js"));
|
|
101
|
+
(0, mockSite_1.buildLintBundle)(lintBundlePath);
|
|
102
|
+
}
|
|
103
|
+
return lintBundlePath;
|
|
104
|
+
};
|
|
89
105
|
var loadWorker = function () {
|
|
90
106
|
jest.resetModules();
|
|
91
107
|
var handlers = {};
|
|
@@ -107,6 +123,13 @@ var loadWorker = function () {
|
|
|
107
123
|
return;
|
|
108
124
|
if (path.includes('api-browser'))
|
|
109
125
|
return require(apiBrowserBuild());
|
|
126
|
+
if (path.includes('lint-browser')) {
|
|
127
|
+
// the bundle assigns globalThis.SASjsCode, and this harness keeps the
|
|
128
|
+
// worker's `self` apart from the module global
|
|
129
|
+
require(lintBundle());
|
|
130
|
+
self.SASjsCode = global.SASjsCode;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
110
133
|
require('../assets/runtime-core.js');
|
|
111
134
|
// The corpus needs the same drive with its writes refused, without building
|
|
112
135
|
// a second site. The flag is flipped after the case has seeded, because a
|
|
@@ -132,10 +155,20 @@ var loadWorker = function () {
|
|
|
132
155
|
};
|
|
133
156
|
};
|
|
134
157
|
require('../assets/sw.js');
|
|
135
|
-
global.fetch = jest.fn(function (
|
|
158
|
+
global.fetch = jest.fn(function (input) { return __awaiter(void 0, void 0, void 0, function () {
|
|
159
|
+
var target;
|
|
136
160
|
var _a;
|
|
137
161
|
return __generator(this, function (_b) {
|
|
138
|
-
|
|
162
|
+
target = typeof input === 'string' ? input : (input && input.url) || String(input);
|
|
163
|
+
// a navigation back to the site root: the static host's copy of the page
|
|
164
|
+
if (new URL(target, origin).pathname === '/')
|
|
165
|
+
return [2 /*return*/, new Response('<html><body>static page</body></html>', {
|
|
166
|
+
status: 200,
|
|
167
|
+
headers: { 'content-type': 'text/html' }
|
|
168
|
+
})];
|
|
169
|
+
if (target.includes('index.html'))
|
|
170
|
+
return [2 /*return*/, new Response('<!doctype html><html><head><title>App</title></head><body>home</body></html>', { status: 200, headers: { 'content-type': 'text/html' } })];
|
|
171
|
+
return [2 /*return*/, target.includes('vfs-seed')
|
|
139
172
|
? jsonResponse({
|
|
140
173
|
files: (_a = {},
|
|
141
174
|
_a[drivePath('services/public/getdata.js')] = '_webout = "seeded";',
|
|
@@ -190,6 +223,24 @@ var jsonResponse = function (body) { return ({
|
|
|
190
223
|
return [2 /*return*/, body];
|
|
191
224
|
}); }); }
|
|
192
225
|
}); };
|
|
226
|
+
/** A zip archive of text members, written the way a deploy upload ships one.
|
|
227
|
+
* The first member is stored rather than deflated, so both methods the reader
|
|
228
|
+
* accepts are exercised by the one case. */
|
|
229
|
+
var zipOf = function (files) {
|
|
230
|
+
return new Promise(function (resolve, reject) {
|
|
231
|
+
var zip = new yazl_1.default.ZipFile();
|
|
232
|
+
Object.keys(files).forEach(function (name, index) {
|
|
233
|
+
return zip.addBuffer(Buffer.from(files[name]), name, {
|
|
234
|
+
compress: index !== 0
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
zip.end();
|
|
238
|
+
var chunks = [];
|
|
239
|
+
zip.outputStream.on('data', function (chunk) { return chunks.push(chunk); });
|
|
240
|
+
zip.outputStream.on('end', function () { return resolve(Buffer.concat(chunks)); });
|
|
241
|
+
zip.outputStream.on('error', reject);
|
|
242
|
+
});
|
|
243
|
+
};
|
|
193
244
|
var runRequest = function (body) { return ({
|
|
194
245
|
method: 'POST',
|
|
195
246
|
headers: { 'content-type': 'application/json' },
|
|
@@ -551,31 +602,543 @@ describe('service worker host', function () {
|
|
|
551
602
|
}
|
|
552
603
|
});
|
|
553
604
|
}); });
|
|
554
|
-
it('answers the session
|
|
555
|
-
var dispatch, session, _a, unknown,
|
|
556
|
-
return __generator(this, function (
|
|
557
|
-
switch (
|
|
605
|
+
it('answers the session route with the caller, and names a route it does not have', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
606
|
+
var dispatch, session, _a, refused, _b, unknown, _c;
|
|
607
|
+
return __generator(this, function (_d) {
|
|
608
|
+
switch (_d.label) {
|
|
558
609
|
case 0:
|
|
559
610
|
dispatch = seeded().dispatch;
|
|
560
611
|
return [4 /*yield*/, dispatch('/SASjsApi/session')];
|
|
561
612
|
case 1:
|
|
562
|
-
session =
|
|
613
|
+
session = _d.sent();
|
|
563
614
|
_a = expect;
|
|
564
615
|
return [4 /*yield*/, session.json()];
|
|
565
616
|
case 2:
|
|
566
|
-
_a.apply(void 0, [
|
|
567
|
-
|
|
617
|
+
_a.apply(void 0, [_d.sent()]).toEqual({
|
|
618
|
+
uid: 'user-admin',
|
|
619
|
+
username: 'sasjsadmin',
|
|
620
|
+
displayName: 'Demo Admin',
|
|
621
|
+
isAdmin: true,
|
|
622
|
+
needsToUpdatePassword: false
|
|
623
|
+
});
|
|
624
|
+
return [4 /*yield*/, dispatch('/SASjsApi/session', {
|
|
625
|
+
headers: { authorization: 'Bearer not-a-token' }
|
|
626
|
+
})];
|
|
568
627
|
case 3:
|
|
569
|
-
|
|
570
|
-
expect(
|
|
628
|
+
refused = _d.sent();
|
|
629
|
+
expect(refused.status).toBe(401);
|
|
571
630
|
_b = expect;
|
|
572
|
-
return [4 /*yield*/,
|
|
631
|
+
return [4 /*yield*/, refused.json()];
|
|
573
632
|
case 4:
|
|
574
|
-
_b.apply(void 0, [(
|
|
633
|
+
_b.apply(void 0, [(_d.sent()).message]).toBe('Unauthorized');
|
|
634
|
+
return [4 /*yield*/, dispatch('/SASjsApi/unknown/route')];
|
|
635
|
+
case 5:
|
|
636
|
+
unknown = _d.sent();
|
|
637
|
+
expect(unknown.status).toBe(404);
|
|
638
|
+
_c = expect;
|
|
639
|
+
return [4 /*yield*/, unknown.json()];
|
|
640
|
+
case 6:
|
|
641
|
+
_c.apply(void 0, [(_d.sent()).message]).toContain('Not part of the API');
|
|
575
642
|
return [2 /*return*/];
|
|
576
643
|
}
|
|
577
644
|
});
|
|
578
645
|
}); });
|
|
646
|
+
describe('the API surface the package carries', function () {
|
|
647
|
+
it('answers the sign-in flow, and the record routes as that caller', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
648
|
+
var worker, signedIn, _a, refused, _b, authorized, code, exchanged, pair, users, _c;
|
|
649
|
+
return __generator(this, function (_d) {
|
|
650
|
+
switch (_d.label) {
|
|
651
|
+
case 0:
|
|
652
|
+
worker = seeded();
|
|
653
|
+
return [4 /*yield*/, worker.dispatch('/SASLogon/login', runRequest({ username: 'sasjsadmin', password: 'Orion123' }))];
|
|
654
|
+
case 1:
|
|
655
|
+
signedIn = _d.sent();
|
|
656
|
+
expect(signedIn.status).toBe(200);
|
|
657
|
+
_a = expect;
|
|
658
|
+
return [4 /*yield*/, signedIn.json()];
|
|
659
|
+
case 2:
|
|
660
|
+
_a.apply(void 0, [(_d.sent()).user.username]).toBe('sasjsadmin');
|
|
661
|
+
return [4 /*yield*/, worker.dispatch('/SASLogon/login', runRequest({ username: 'sasjsadmin', password: 'nope' }))];
|
|
662
|
+
case 3:
|
|
663
|
+
refused = _d.sent();
|
|
664
|
+
expect(refused.status).toBe(401);
|
|
665
|
+
_b = expect;
|
|
666
|
+
return [4 /*yield*/, refused.json()];
|
|
667
|
+
case 4:
|
|
668
|
+
_b.apply(void 0, [(_d.sent()).message]).toBe('Invalid Password.');
|
|
669
|
+
return [4 /*yield*/, worker.dispatch('/SASLogon/authorize', runRequest({ clientId: 'web_app' }))];
|
|
670
|
+
case 5:
|
|
671
|
+
authorized = _d.sent();
|
|
672
|
+
return [4 /*yield*/, authorized.json()];
|
|
673
|
+
case 6:
|
|
674
|
+
code = (_d.sent()).code;
|
|
675
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/auth/token', runRequest({ clientId: 'web_app', code: code }))];
|
|
676
|
+
case 7:
|
|
677
|
+
exchanged = _d.sent();
|
|
678
|
+
return [4 /*yield*/, exchanged.json()];
|
|
679
|
+
case 8:
|
|
680
|
+
pair = _d.sent();
|
|
681
|
+
expect(pair.accessToken).toBeTruthy();
|
|
682
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/user', {
|
|
683
|
+
headers: { authorization: "Bearer ".concat(pair.accessToken) }
|
|
684
|
+
})];
|
|
685
|
+
case 9:
|
|
686
|
+
users = _d.sent();
|
|
687
|
+
_c = expect;
|
|
688
|
+
return [4 /*yield*/, users.json()];
|
|
689
|
+
case 10:
|
|
690
|
+
_c.apply(void 0, [(_d.sent()).map(function (user) { return user.username; }).sort()]).toEqual(['sasjsadmin', 'sasjsuser']);
|
|
691
|
+
return [2 /*return*/];
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}); });
|
|
695
|
+
it('answers the administration records the fixture seeds', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
696
|
+
var dispatch, groups, _a, permissions, _b, clients, _c, mine, _d, _e, _f;
|
|
697
|
+
return __generator(this, function (_g) {
|
|
698
|
+
switch (_g.label) {
|
|
699
|
+
case 0:
|
|
700
|
+
dispatch = seeded().dispatch;
|
|
701
|
+
return [4 /*yield*/, dispatch('/SASjsApi/group')];
|
|
702
|
+
case 1:
|
|
703
|
+
groups = _g.sent();
|
|
704
|
+
_a = expect;
|
|
705
|
+
return [4 /*yield*/, groups.json()];
|
|
706
|
+
case 2:
|
|
707
|
+
_a.apply(void 0, [(_g.sent()).map(function (group) { return group.name; }).sort()]).toEqual(['Admins', 'DCGroup']);
|
|
708
|
+
return [4 /*yield*/, dispatch('/SASjsApi/permission')];
|
|
709
|
+
case 3:
|
|
710
|
+
permissions = _g.sent();
|
|
711
|
+
_b = expect;
|
|
712
|
+
return [4 /*yield*/, permissions.json()];
|
|
713
|
+
case 4:
|
|
714
|
+
_b.apply(void 0, [(_g.sent()).length]).toBe(3);
|
|
715
|
+
return [4 /*yield*/, dispatch('/SASjsApi/client')];
|
|
716
|
+
case 5:
|
|
717
|
+
clients = _g.sent();
|
|
718
|
+
_c = expect;
|
|
719
|
+
return [4 /*yield*/, clients.json()];
|
|
720
|
+
case 6:
|
|
721
|
+
_c.apply(void 0, [(_g.sent()).map(function (client) { return client.clientId; }).sort()]).toEqual(['sasjs', 'web_app']);
|
|
722
|
+
return [4 /*yield*/, dispatch('/SASjsApi/info/myAuthorizedRoutes')];
|
|
723
|
+
case 7:
|
|
724
|
+
mine = _g.sent();
|
|
725
|
+
_d = expect;
|
|
726
|
+
_f = (_e = Object).keys;
|
|
727
|
+
return [4 /*yield*/, mine.json()];
|
|
728
|
+
case 8:
|
|
729
|
+
_d.apply(void 0, [_f.apply(_e, [_g.sent()]).length]).toBeGreaterThan(0);
|
|
730
|
+
return [2 /*return*/];
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
}); });
|
|
734
|
+
it('answers the Admin reports from the worker activity log', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
735
|
+
var dispatch, empty, _a, afterFirst, _b, listed, lines, infoLines, diagnostics, report, logs, _c, tail, tailBody, wrongName, missing;
|
|
736
|
+
return __generator(this, function (_d) {
|
|
737
|
+
switch (_d.label) {
|
|
738
|
+
case 0:
|
|
739
|
+
dispatch = seeded().dispatch;
|
|
740
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/diagnostics')];
|
|
741
|
+
case 1:
|
|
742
|
+
empty = _d.sent();
|
|
743
|
+
_a = expect;
|
|
744
|
+
return [4 /*yield*/, empty.json()];
|
|
745
|
+
case 2:
|
|
746
|
+
_a.apply(void 0, [(_d.sent()).logs]).toEqual({
|
|
747
|
+
folder: 'worker memory',
|
|
748
|
+
fileCount: 0,
|
|
749
|
+
totalBytes: 0,
|
|
750
|
+
newestFile: null,
|
|
751
|
+
newestModified: null
|
|
752
|
+
});
|
|
753
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs')];
|
|
754
|
+
case 3:
|
|
755
|
+
afterFirst = _d.sent();
|
|
756
|
+
_b = expect;
|
|
757
|
+
return [4 /*yield*/, afterFirst.json()];
|
|
758
|
+
case 4:
|
|
759
|
+
_b.apply(void 0, [(_d.sent()).files.length]).toBe(1);
|
|
760
|
+
// the file's mtime is the last write, not the moment a report was read:
|
|
761
|
+
// /info was the request immediately before this listing
|
|
762
|
+
return [4 /*yield*/, dispatch('/SASjsApi/info')];
|
|
763
|
+
case 5:
|
|
764
|
+
// the file's mtime is the last write, not the moment a report was read:
|
|
765
|
+
// /info was the request immediately before this listing
|
|
766
|
+
_d.sent();
|
|
767
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs')];
|
|
768
|
+
case 6: return [4 /*yield*/, (_d.sent()).json()];
|
|
769
|
+
case 7:
|
|
770
|
+
listed = (_d.sent())
|
|
771
|
+
.files[0];
|
|
772
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs/app.log?lines=20')];
|
|
773
|
+
case 8: return [4 /*yield*/, (_d.sent()).json()];
|
|
774
|
+
case 9:
|
|
775
|
+
lines = (_d.sent()).content.split('\n');
|
|
776
|
+
infoLines = lines.filter(function (line) {
|
|
777
|
+
return line.includes('GET /SASjsApi/info 200');
|
|
778
|
+
});
|
|
779
|
+
expect(infoLines.length).toBe(1);
|
|
780
|
+
expect(infoLines[0].startsWith(listed.modified)).toBe(true);
|
|
781
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/diagnostics')];
|
|
782
|
+
case 10:
|
|
783
|
+
diagnostics = _d.sent();
|
|
784
|
+
expect(diagnostics.status).toBe(200);
|
|
785
|
+
return [4 /*yield*/, diagnostics.json()];
|
|
786
|
+
case 11:
|
|
787
|
+
report = _d.sent();
|
|
788
|
+
expect(report.server.mode).toBe('browser');
|
|
789
|
+
expect(report.filesystem).toBeNull();
|
|
790
|
+
expect(report.logs.fileCount).toBe(1);
|
|
791
|
+
expect(typeof report.memory.heapTotalBytes).toBe('number');
|
|
792
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs')];
|
|
793
|
+
case 12:
|
|
794
|
+
logs = _d.sent();
|
|
795
|
+
_c = expect;
|
|
796
|
+
return [4 /*yield*/, logs.json()];
|
|
797
|
+
case 13:
|
|
798
|
+
_c.apply(void 0, [(_d.sent()).files.map(function (file) { return file.name; })]).toEqual([
|
|
799
|
+
'app.log'
|
|
800
|
+
]);
|
|
801
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs/app.log?lines=5')];
|
|
802
|
+
case 14:
|
|
803
|
+
tail = _d.sent();
|
|
804
|
+
return [4 /*yield*/, tail.json()];
|
|
805
|
+
case 15:
|
|
806
|
+
tailBody = _d.sent();
|
|
807
|
+
expect(tail.status).toBe(200);
|
|
808
|
+
expect(tailBody.content).toContain('GET /SASjsApi/info 200');
|
|
809
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs/secret.txt')];
|
|
810
|
+
case 16:
|
|
811
|
+
wrongName = _d.sent();
|
|
812
|
+
expect(wrongName.status).toBe(400);
|
|
813
|
+
return [4 /*yield*/, dispatch('/SASjsApi/admin/logs/other.log')];
|
|
814
|
+
case 17:
|
|
815
|
+
missing = _d.sent();
|
|
816
|
+
expect(missing.status).toBe(404);
|
|
817
|
+
return [2 /*return*/];
|
|
818
|
+
}
|
|
819
|
+
});
|
|
820
|
+
}); });
|
|
821
|
+
it('imports the fixture directory, and unpublishes the site itself', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
822
|
+
var dispatch, synced, _a, unpublished, _b, other;
|
|
823
|
+
return __generator(this, function (_c) {
|
|
824
|
+
switch (_c.label) {
|
|
825
|
+
case 0:
|
|
826
|
+
dispatch = seeded().dispatch;
|
|
827
|
+
return [4 /*yield*/, dispatch('/SASjsApi/authConfig/synchroniseWithLDAP', { method: 'POST' })];
|
|
828
|
+
case 1:
|
|
829
|
+
synced = _c.sent();
|
|
830
|
+
expect(synced.status).toBe(200);
|
|
831
|
+
_a = expect;
|
|
832
|
+
return [4 /*yield*/, synced.json()];
|
|
833
|
+
case 2:
|
|
834
|
+
_a.apply(void 0, [_c.sent()]).toEqual({ userCount: 0, groupCount: 0 });
|
|
835
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy', {
|
|
836
|
+
method: 'DELETE',
|
|
837
|
+
headers: { 'content-type': 'application/json' },
|
|
838
|
+
body: JSON.stringify({
|
|
839
|
+
streamServiceName: 'Test',
|
|
840
|
+
appLoc: appLoc
|
|
841
|
+
})
|
|
842
|
+
})];
|
|
843
|
+
case 3:
|
|
844
|
+
unpublished = _c.sent();
|
|
845
|
+
expect(unpublished.status).toBe(200);
|
|
846
|
+
_b = expect;
|
|
847
|
+
return [4 /*yield*/, unpublished.json()];
|
|
848
|
+
case 4:
|
|
849
|
+
_b.apply(void 0, [_c.sent()]).toEqual({ status: 'success' });
|
|
850
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy', {
|
|
851
|
+
method: 'DELETE',
|
|
852
|
+
headers: { 'content-type': 'application/json' },
|
|
853
|
+
body: JSON.stringify({
|
|
854
|
+
streamServiceName: 'Other',
|
|
855
|
+
appLoc: '/Public/app/other'
|
|
856
|
+
})
|
|
857
|
+
})];
|
|
858
|
+
case 5:
|
|
859
|
+
other = _c.sent();
|
|
860
|
+
expect(other.status).toBe(404);
|
|
861
|
+
return [2 /*return*/];
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
}); });
|
|
865
|
+
it('lints and formats a buffer with the bundled linter', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
866
|
+
var dispatch, linted, diagnostics, formatted, _a;
|
|
867
|
+
return __generator(this, function (_b) {
|
|
868
|
+
switch (_b.label) {
|
|
869
|
+
case 0:
|
|
870
|
+
dispatch = seeded().dispatch;
|
|
871
|
+
return [4 /*yield*/, dispatch('/SASjsApi/code/lint', runRequest({ code: 'data a;\nrun;\n' }))];
|
|
872
|
+
case 1:
|
|
873
|
+
linted = _b.sent();
|
|
874
|
+
expect(linted.status).toBe(200);
|
|
875
|
+
return [4 /*yield*/, linted.json()];
|
|
876
|
+
case 2:
|
|
877
|
+
diagnostics = _b.sent();
|
|
878
|
+
expect(Array.isArray(diagnostics)).toBe(true);
|
|
879
|
+
expect(diagnostics.length).toBeGreaterThan(0);
|
|
880
|
+
expect(diagnostics[0].message).toContain('Doxygen');
|
|
881
|
+
return [4 /*yield*/, dispatch('/SASjsApi/code/format', runRequest({ code: 'data a;set b;run;' }))];
|
|
882
|
+
case 3:
|
|
883
|
+
formatted = _b.sent();
|
|
884
|
+
expect(formatted.status).toBe(200);
|
|
885
|
+
_a = expect;
|
|
886
|
+
return [4 /*yield*/, formatted.text()];
|
|
887
|
+
case 4:
|
|
888
|
+
_a.apply(void 0, [_b.sent()]).toContain('@brief');
|
|
889
|
+
return [2 /*return*/];
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
}); });
|
|
893
|
+
it('serves the build page at the home route, and falls back when it fails', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
894
|
+
var worker, response, _a, runtime, original, fallback, body;
|
|
895
|
+
return __generator(this, function (_b) {
|
|
896
|
+
switch (_b.label) {
|
|
897
|
+
case 0:
|
|
898
|
+
worker = seeded();
|
|
899
|
+
return [4 /*yield*/, worker.dispatch('/')];
|
|
900
|
+
case 1:
|
|
901
|
+
response = _b.sent();
|
|
902
|
+
expect(response.status).toBe(200);
|
|
903
|
+
expect(response.headers.get('content-type')).toContain('text/html');
|
|
904
|
+
_a = expect;
|
|
905
|
+
return [4 /*yield*/, response.text()];
|
|
906
|
+
case 2:
|
|
907
|
+
_a.apply(void 0, [_b.sent()]).toContain('<body>home</body>');
|
|
908
|
+
runtime = worker.self.SASjsMockRuntime;
|
|
909
|
+
original = runtime.ensureReady;
|
|
910
|
+
runtime.ensureReady = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
911
|
+
return __generator(this, function (_a) {
|
|
912
|
+
throw new Error('home route exploded');
|
|
913
|
+
});
|
|
914
|
+
}); };
|
|
915
|
+
_b.label = 3;
|
|
916
|
+
case 3:
|
|
917
|
+
_b.trys.push([3, , 6, 7]);
|
|
918
|
+
return [4 /*yield*/, worker.dispatch('/')];
|
|
919
|
+
case 4:
|
|
920
|
+
fallback = _b.sent();
|
|
921
|
+
expect(fallback.status).toBe(200);
|
|
922
|
+
return [4 /*yield*/, fallback.text()];
|
|
923
|
+
case 5:
|
|
924
|
+
body = _b.sent();
|
|
925
|
+
expect(body).toContain('static page');
|
|
926
|
+
expect(body).not.toContain('home route exploded');
|
|
927
|
+
return [3 /*break*/, 7];
|
|
928
|
+
case 6:
|
|
929
|
+
runtime.ensureReady = original;
|
|
930
|
+
return [7 /*endfinally*/];
|
|
931
|
+
case 7: return [2 /*return*/];
|
|
932
|
+
}
|
|
933
|
+
});
|
|
934
|
+
}); });
|
|
935
|
+
it('matches a path whatever its casing, as the API does', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
936
|
+
var dispatch, response, _a;
|
|
937
|
+
return __generator(this, function (_b) {
|
|
938
|
+
switch (_b.label) {
|
|
939
|
+
case 0:
|
|
940
|
+
dispatch = seeded().dispatch;
|
|
941
|
+
return [4 /*yield*/, dispatch('/sasjsapi/INFO')];
|
|
942
|
+
case 1:
|
|
943
|
+
response = _b.sent();
|
|
944
|
+
expect(response.status).toBe(200);
|
|
945
|
+
_a = expect;
|
|
946
|
+
return [4 /*yield*/, response.json()];
|
|
947
|
+
case 2:
|
|
948
|
+
_a.apply(void 0, [(_b.sent()).mode]).toBe('desktop');
|
|
949
|
+
return [2 /*return*/];
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
}); });
|
|
953
|
+
it('starts a session, then reads its state, log and output', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
954
|
+
var dispatch, program, triggered, sessionId, state, _a, output, _b, log, missing;
|
|
955
|
+
return __generator(this, function (_c) {
|
|
956
|
+
switch (_c.label) {
|
|
957
|
+
case 0:
|
|
958
|
+
dispatch = seeded().dispatch;
|
|
959
|
+
program = encodeURIComponent("".concat(appLoc, "/services/public/getdata"));
|
|
960
|
+
return [4 /*yield*/, dispatch('/SASjsApi/stp/trigger?_program=' + program, runRequest({ params: {} }))];
|
|
961
|
+
case 1:
|
|
962
|
+
triggered = _c.sent();
|
|
963
|
+
expect(triggered.status).toBe(200);
|
|
964
|
+
return [4 /*yield*/, triggered.json()];
|
|
965
|
+
case 2:
|
|
966
|
+
sessionId = (_c.sent()).sessionId;
|
|
967
|
+
expect(sessionId).toBeTruthy();
|
|
968
|
+
return [4 /*yield*/, dispatch("/SASjsApi/session/".concat(sessionId, "/state"))];
|
|
969
|
+
case 3:
|
|
970
|
+
state = _c.sent();
|
|
971
|
+
_a = expect;
|
|
972
|
+
return [4 /*yield*/, state.json()];
|
|
973
|
+
case 4:
|
|
974
|
+
_a.apply(void 0, [_c.sent()]).toEqual({ state: 'completed' });
|
|
975
|
+
return [4 /*yield*/, dispatch("/SASjsApi/session/".concat(sessionId, "/output"))];
|
|
976
|
+
case 5:
|
|
977
|
+
output = _c.sent();
|
|
978
|
+
expect(output.status).toBe(200);
|
|
979
|
+
_b = expect;
|
|
980
|
+
return [4 /*yield*/, output.text()];
|
|
981
|
+
case 6:
|
|
982
|
+
_b.apply(void 0, [_c.sent()]).toBe('seeded');
|
|
983
|
+
return [4 /*yield*/, dispatch("/SASjsApi/session/".concat(sessionId, "/log"))];
|
|
984
|
+
case 7:
|
|
985
|
+
log = _c.sent();
|
|
986
|
+
expect(log.status).toBe(200);
|
|
987
|
+
return [4 /*yield*/, dispatch('/SASjsApi/session/not-a-session/state')];
|
|
988
|
+
case 8:
|
|
989
|
+
missing = _c.sent();
|
|
990
|
+
expect(missing.status).toBe(404);
|
|
991
|
+
return [2 /*return*/];
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
}); });
|
|
995
|
+
it('refuses a deploy upload with no archive, and one that is not a zip', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
996
|
+
var dispatch, empty, _a, form, notZip, _b;
|
|
997
|
+
return __generator(this, function (_c) {
|
|
998
|
+
switch (_c.label) {
|
|
999
|
+
case 0:
|
|
1000
|
+
dispatch = seeded().dispatch;
|
|
1001
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy/upload', {
|
|
1002
|
+
method: 'POST',
|
|
1003
|
+
body: new FormData()
|
|
1004
|
+
})];
|
|
1005
|
+
case 1:
|
|
1006
|
+
empty = _c.sent();
|
|
1007
|
+
expect(empty.status).toBe(400);
|
|
1008
|
+
_a = expect;
|
|
1009
|
+
return [4 /*yield*/, empty.text()];
|
|
1010
|
+
case 2:
|
|
1011
|
+
_a.apply(void 0, [_c.sent()]).toBe('"file" is not present.');
|
|
1012
|
+
form = new FormData();
|
|
1013
|
+
form.set('file', new Blob([new Uint8Array([1, 2, 3])]), 'not-a-zip.zip');
|
|
1014
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy/upload', {
|
|
1015
|
+
method: 'POST',
|
|
1016
|
+
body: form
|
|
1017
|
+
})];
|
|
1018
|
+
case 3:
|
|
1019
|
+
notZip = _c.sent();
|
|
1020
|
+
expect(notZip.status).toBe(400);
|
|
1021
|
+
_b = expect;
|
|
1022
|
+
return [4 /*yield*/, notZip.text()];
|
|
1023
|
+
case 4:
|
|
1024
|
+
_b.apply(void 0, [_c.sent()]).toBe('The archive is not a zip file.');
|
|
1025
|
+
return [2 /*return*/];
|
|
1026
|
+
}
|
|
1027
|
+
});
|
|
1028
|
+
}); });
|
|
1029
|
+
it('takes a token from the query when a link cannot carry a header', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1030
|
+
var worker, authorized, code, exchanged, pair, users, _a;
|
|
1031
|
+
return __generator(this, function (_b) {
|
|
1032
|
+
switch (_b.label) {
|
|
1033
|
+
case 0:
|
|
1034
|
+
worker = seeded();
|
|
1035
|
+
return [4 /*yield*/, worker.dispatch('/SASLogon/authorize', runRequest({ clientId: 'web_app' }))];
|
|
1036
|
+
case 1:
|
|
1037
|
+
authorized = _b.sent();
|
|
1038
|
+
return [4 /*yield*/, authorized.json()];
|
|
1039
|
+
case 2:
|
|
1040
|
+
code = (_b.sent()).code;
|
|
1041
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/auth/token', runRequest({ clientId: 'web_app', code: code }))];
|
|
1042
|
+
case 3:
|
|
1043
|
+
exchanged = _b.sent();
|
|
1044
|
+
return [4 /*yield*/, exchanged.json()];
|
|
1045
|
+
case 4:
|
|
1046
|
+
pair = _b.sent();
|
|
1047
|
+
return [4 /*yield*/, worker.dispatch("/SASjsApi/user?access_token=".concat(encodeURIComponent(pair.accessToken)))];
|
|
1048
|
+
case 5:
|
|
1049
|
+
users = _b.sent();
|
|
1050
|
+
expect(users.status).toBe(200);
|
|
1051
|
+
_a = expect;
|
|
1052
|
+
return [4 /*yield*/, users.json()];
|
|
1053
|
+
case 6:
|
|
1054
|
+
_a.apply(void 0, [(_b.sent()).length]).toBe(2);
|
|
1055
|
+
return [2 /*return*/];
|
|
1056
|
+
}
|
|
1057
|
+
});
|
|
1058
|
+
}); });
|
|
1059
|
+
it('names a table the page did not name, and takes an archive under any field', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1060
|
+
var worker, unnamed, _a, form, _b, _c, _d, _e, _f, upload;
|
|
1061
|
+
var _g;
|
|
1062
|
+
return __generator(this, function (_h) {
|
|
1063
|
+
switch (_h.label) {
|
|
1064
|
+
case 0:
|
|
1065
|
+
worker = seeded();
|
|
1066
|
+
worker.runtime.load((_g = {},
|
|
1067
|
+
_g[drivePath('services/public/echo.js')] = '_webout = _WEBIN_NAME1 + "|" + _WEBIN_FILEREF1;',
|
|
1068
|
+
_g));
|
|
1069
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/stp/execute?_program=' +
|
|
1070
|
+
encodeURIComponent("".concat(appLoc, "/services/public/echo")), runRequest({ params: {}, tables: [{ csv: 'A,B\r\n1,2' }] }))];
|
|
1071
|
+
case 1:
|
|
1072
|
+
unnamed = _h.sent();
|
|
1073
|
+
_a = expect;
|
|
1074
|
+
return [4 /*yield*/, unnamed.text()];
|
|
1075
|
+
case 2:
|
|
1076
|
+
_a.apply(void 0, [_h.sent()]).toBe('table1|A,B\r\n1,2');
|
|
1077
|
+
form = new FormData();
|
|
1078
|
+
form.set('appLoc', appLoc);
|
|
1079
|
+
_c = (_b = form).set;
|
|
1080
|
+
_d = ['archive'];
|
|
1081
|
+
_e = Blob.bind;
|
|
1082
|
+
_f = Uint8Array.bind;
|
|
1083
|
+
return [4 /*yield*/, zipOf({ 'x.txt': 'x' })];
|
|
1084
|
+
case 3:
|
|
1085
|
+
_c.apply(_b, _d.concat([new (_e.apply(Blob, [void 0, [new (_f.apply(Uint8Array, [void 0, _h.sent()]))()]]))(),
|
|
1086
|
+
'deploy.zip']));
|
|
1087
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/drive/deploy/upload', {
|
|
1088
|
+
method: 'POST',
|
|
1089
|
+
body: form
|
|
1090
|
+
})];
|
|
1091
|
+
case 4:
|
|
1092
|
+
upload = _h.sent();
|
|
1093
|
+
expect(upload.status).toBe(200);
|
|
1094
|
+
return [2 /*return*/];
|
|
1095
|
+
}
|
|
1096
|
+
});
|
|
1097
|
+
}); });
|
|
1098
|
+
it('expands an uploaded archive into the drive', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1099
|
+
var dispatch, archive, form, response, tree, listing, _a, _b, file, _c;
|
|
1100
|
+
return __generator(this, function (_d) {
|
|
1101
|
+
switch (_d.label) {
|
|
1102
|
+
case 0:
|
|
1103
|
+
dispatch = seeded().dispatch;
|
|
1104
|
+
return [4 /*yield*/, zipOf({
|
|
1105
|
+
'services/public/run.js': '_webout = "deployed";',
|
|
1106
|
+
'docs/readme.txt': 'hello'
|
|
1107
|
+
})];
|
|
1108
|
+
case 1:
|
|
1109
|
+
archive = _d.sent();
|
|
1110
|
+
form = new FormData();
|
|
1111
|
+
form.set('appLoc', appLoc);
|
|
1112
|
+
form.set('file', new Blob([new Uint8Array(archive)]), 'deploy.zip');
|
|
1113
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy/upload', {
|
|
1114
|
+
method: 'POST',
|
|
1115
|
+
body: form
|
|
1116
|
+
})];
|
|
1117
|
+
case 2:
|
|
1118
|
+
response = _d.sent();
|
|
1119
|
+
expect(response.status).toBe(200);
|
|
1120
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/filetree?_folderPath=' + encodeURIComponent(appLoc))];
|
|
1121
|
+
case 3:
|
|
1122
|
+
tree = _d.sent();
|
|
1123
|
+
_b = (_a = JSON).stringify;
|
|
1124
|
+
return [4 /*yield*/, tree.json()];
|
|
1125
|
+
case 4:
|
|
1126
|
+
listing = _b.apply(_a, [_d.sent()]);
|
|
1127
|
+
expect(listing).toContain('run.js');
|
|
1128
|
+
expect(listing).toContain('readme.txt');
|
|
1129
|
+
return [4 /*yield*/, dispatch('/SASjsApi/drive/file?_filePath=' +
|
|
1130
|
+
encodeURIComponent("".concat(appLoc, "/docs/readme.txt")))];
|
|
1131
|
+
case 5:
|
|
1132
|
+
file = _d.sent();
|
|
1133
|
+
_c = expect;
|
|
1134
|
+
return [4 /*yield*/, file.text()];
|
|
1135
|
+
case 6:
|
|
1136
|
+
_c.apply(void 0, [_d.sent()]).toBe('hello');
|
|
1137
|
+
return [2 /*return*/];
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
}); });
|
|
1141
|
+
});
|
|
579
1142
|
it('answers 404 for a drive file the drive does not hold', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
580
1143
|
var dispatch, response, _a;
|
|
581
1144
|
return __generator(this, function (_b) {
|
|
@@ -686,12 +1249,12 @@ describe('service worker host', function () {
|
|
|
686
1249
|
_a = expect;
|
|
687
1250
|
return [4 /*yield*/, response.json()];
|
|
688
1251
|
case 2:
|
|
689
|
-
_a.apply(void 0, [_b.sent()]).toEqual({ message: '_program is required' });
|
|
1252
|
+
_a.apply(void 0, [_b.sent()]).toEqual({ message: '"_program" is required' });
|
|
690
1253
|
return [2 /*return*/];
|
|
691
1254
|
}
|
|
692
1255
|
});
|
|
693
1256
|
}); });
|
|
694
|
-
it('answers
|
|
1257
|
+
it('answers the documented failure envelope when the service throws', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
695
1258
|
var _a, runtime, dispatch, response, body;
|
|
696
1259
|
var _b;
|
|
697
1260
|
return __generator(this, function (_c) {
|
|
@@ -705,11 +1268,17 @@ describe('service worker host', function () {
|
|
|
705
1268
|
encodeURIComponent("".concat(appLoc, "/services/public/broken")))];
|
|
706
1269
|
case 1:
|
|
707
1270
|
response = _c.sent();
|
|
708
|
-
return [4 /*yield*/, response.json()
|
|
1271
|
+
return [4 /*yield*/, response.json()
|
|
1272
|
+
// the package's decision, and the server's: a run that failed is a 400
|
|
1273
|
+
// carrying the failure envelope, not a 500 that blames the transport
|
|
1274
|
+
];
|
|
709
1275
|
case 2:
|
|
710
1276
|
body = _c.sent();
|
|
711
|
-
|
|
1277
|
+
// the package's decision, and the server's: a run that failed is a 400
|
|
1278
|
+
// carrying the failure envelope, not a 500 that blames the transport
|
|
1279
|
+
expect(response.status).toBe(400);
|
|
712
1280
|
expect(body.status).toBe('failure');
|
|
1281
|
+
expect(body.message).toBe('Job execution failed.');
|
|
713
1282
|
expect(body.error).toContain('boom');
|
|
714
1283
|
return [2 /*return*/];
|
|
715
1284
|
}
|
|
@@ -721,13 +1290,58 @@ describe('service worker host', function () {
|
|
|
721
1290
|
switch (_b.label) {
|
|
722
1291
|
case 0:
|
|
723
1292
|
dispatch = seeded().dispatch;
|
|
724
|
-
return [4 /*yield*/, dispatch('/SASjsApi/code/execute', runRequest({ code: '_webout = "inline";', params: {} }))
|
|
1293
|
+
return [4 /*yield*/, dispatch('/SASjsApi/code/execute', runRequest({ code: '_webout = "inline";', runTime: 'js', params: {} }))
|
|
1294
|
+
// a code route's documented body is the webout framed with the log, so the
|
|
1295
|
+
// run's output is the first section rather than the whole body
|
|
1296
|
+
];
|
|
725
1297
|
case 1:
|
|
726
1298
|
response = _b.sent();
|
|
1299
|
+
// a code route's documented body is the webout framed with the log, so the
|
|
1300
|
+
// run's output is the first section rather than the whole body
|
|
1301
|
+
_a = expect;
|
|
1302
|
+
return [4 /*yield*/, response.text()];
|
|
1303
|
+
case 2:
|
|
1304
|
+
// a code route's documented body is the webout framed with the log, so the
|
|
1305
|
+
// run's output is the first section rather than the whole body
|
|
1306
|
+
_a.apply(void 0, [(_b.sent()).split(LOGS_SEPARATOR)[0].trim()]).toBe('inline');
|
|
1307
|
+
return [2 /*return*/];
|
|
1308
|
+
}
|
|
1309
|
+
});
|
|
1310
|
+
}); });
|
|
1311
|
+
it('reads the table envelope the page bridge posts for an XHR', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1312
|
+
var worker, response, _a;
|
|
1313
|
+
var _b;
|
|
1314
|
+
return __generator(this, function (_c) {
|
|
1315
|
+
switch (_c.label) {
|
|
1316
|
+
case 0:
|
|
1317
|
+
worker = seeded();
|
|
1318
|
+
worker.runtime.load((_b = {},
|
|
1319
|
+
_b[drivePath('services/public/echo.js')] = '_webout = _WEBIN_NAME1 + "|" + _WEBIN_FILEREF1;',
|
|
1320
|
+
_b));
|
|
1321
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/stp/execute?_program=' +
|
|
1322
|
+
encodeURIComponent("".concat(appLoc, "/services/public/echo")), runRequest({
|
|
1323
|
+
params: {},
|
|
1324
|
+
tables: [
|
|
1325
|
+
{
|
|
1326
|
+
name: 'SASControlTable',
|
|
1327
|
+
filename: 'SASControlTable.csv',
|
|
1328
|
+
csv: 'A,B\r\n1,2'
|
|
1329
|
+
}
|
|
1330
|
+
]
|
|
1331
|
+
}))
|
|
1332
|
+
// the bridge hands the worker `{params, tables}`; a stored program sees the
|
|
1333
|
+
// tables as its _WEBIN variables, not as one `tables` session variable
|
|
1334
|
+
];
|
|
1335
|
+
case 1:
|
|
1336
|
+
response = _c.sent();
|
|
1337
|
+
// the bridge hands the worker `{params, tables}`; a stored program sees the
|
|
1338
|
+
// tables as its _WEBIN variables, not as one `tables` session variable
|
|
727
1339
|
_a = expect;
|
|
728
1340
|
return [4 /*yield*/, response.text()];
|
|
729
1341
|
case 2:
|
|
730
|
-
|
|
1342
|
+
// the bridge hands the worker `{params, tables}`; a stored program sees the
|
|
1343
|
+
// tables as its _WEBIN variables, not as one `tables` session variable
|
|
1344
|
+
_a.apply(void 0, [_c.sent()]).toBe('SASControlTable|A,B\r\n1,2');
|
|
731
1345
|
return [2 /*return*/];
|
|
732
1346
|
}
|
|
733
1347
|
});
|
|
@@ -1505,42 +2119,55 @@ describe('service worker host', function () {
|
|
|
1505
2119
|
}); };
|
|
1506
2120
|
var _loop_1 = function (testCase) {
|
|
1507
2121
|
it(testCase.id, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1508
|
-
var worker, _a, requestPath, init, response,
|
|
1509
|
-
return __generator(this, function (
|
|
1510
|
-
switch (
|
|
2122
|
+
var worker, _a, requestPath, init, response, body, want, _b, _c, _d;
|
|
2123
|
+
return __generator(this, function (_e) {
|
|
2124
|
+
switch (_e.label) {
|
|
1511
2125
|
case 0:
|
|
1512
2126
|
worker = loadWorker();
|
|
1513
2127
|
return [4 /*yield*/, seedDrive(worker.runtime, testCase)];
|
|
1514
2128
|
case 1:
|
|
1515
|
-
|
|
2129
|
+
_e.sent();
|
|
1516
2130
|
worker.refuseWrites(Boolean(testCase.unwritable));
|
|
1517
2131
|
_a = httpFor(testCase), requestPath = _a.path, init = _a.init;
|
|
1518
2132
|
return [4 /*yield*/, worker.dispatch(requestPath, init)];
|
|
1519
2133
|
case 2:
|
|
1520
|
-
response =
|
|
2134
|
+
response = _e.sent();
|
|
1521
2135
|
expect(response.status).toBe(testCase.expect.status);
|
|
1522
2136
|
if (!(testCase.expect.error !== undefined)) return [3 /*break*/, 4];
|
|
1523
|
-
|
|
1524
|
-
|
|
2137
|
+
return [4 /*yield*/, response.text()
|
|
2138
|
+
// the routes that answer an envelope - the two deploy routes - send
|
|
2139
|
+
// `{status, message}`; the rest send the message itself as text, which
|
|
2140
|
+
// is what the server's `res.status(code).send(err.message)` does
|
|
2141
|
+
];
|
|
1525
2142
|
case 3:
|
|
1526
|
-
|
|
1527
|
-
|
|
2143
|
+
body = _e.sent();
|
|
2144
|
+
// the routes that answer an envelope - the two deploy routes - send
|
|
2145
|
+
// `{status, message}`; the rest send the message itself as text, which
|
|
2146
|
+
// is what the server's `res.status(code).send(err.message)` does
|
|
2147
|
+
if ((response.headers.get('content-type') || '').includes('application/json'))
|
|
2148
|
+
expect(JSON.parse(body)).toEqual({
|
|
2149
|
+
status: 'failure',
|
|
2150
|
+
message: testCase.expect.error
|
|
2151
|
+
});
|
|
2152
|
+
else
|
|
2153
|
+
expect(body).toBe(testCase.expect.error);
|
|
2154
|
+
return [3 /*break*/, 8];
|
|
1528
2155
|
case 4:
|
|
1529
2156
|
want = testCase.expect.contents;
|
|
1530
2157
|
if (!(typeof want === 'string')) return [3 /*break*/, 6];
|
|
1531
|
-
|
|
2158
|
+
_b = expect;
|
|
1532
2159
|
return [4 /*yield*/, response.text()];
|
|
1533
2160
|
case 5:
|
|
1534
|
-
|
|
2161
|
+
_b.apply(void 0, [_e.sent()]).toBe(want);
|
|
1535
2162
|
return [3 /*break*/, 8];
|
|
1536
2163
|
case 6:
|
|
1537
2164
|
if (!(want !== undefined)) return [3 /*break*/, 8];
|
|
1538
|
-
|
|
1539
|
-
|
|
2165
|
+
_c = expect;
|
|
2166
|
+
_d = Uint8Array.bind;
|
|
1540
2167
|
return [4 /*yield*/, response.arrayBuffer()];
|
|
1541
2168
|
case 7:
|
|
1542
|
-
|
|
1543
|
-
|
|
2169
|
+
_c.apply(void 0, [new (_d.apply(Uint8Array, [void 0, _e.sent()]))()]).toEqual(want);
|
|
2170
|
+
_e.label = 8;
|
|
1544
2171
|
case 8: return [2 /*return*/];
|
|
1545
2172
|
}
|
|
1546
2173
|
});
|