@sasjs/cli 6.25.0 → 6.26.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.
@@ -1,4 +1,15 @@
1
1
  "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
2
13
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
14
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
15
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -62,6 +73,15 @@ var __read = (this && this.__read) || function (o, n) {
62
73
  }
63
74
  return ar;
64
75
  };
76
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
77
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
78
+ if (ar || !(i in from)) {
79
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
80
+ ar[i] = from[i];
81
+ }
82
+ }
83
+ return to.concat(ar || Array.prototype.slice.call(from));
84
+ };
65
85
  var __importDefault = (this && this.__importDefault) || function (mod) {
66
86
  return (mod && mod.__esModule) ? mod : { "default": mod };
67
87
  };
@@ -163,7 +183,7 @@ var loadWorker = function (base) {
163
183
  };
164
184
  require('../assets/sw.js');
165
185
  global.fetch = jest.fn(function (input) { return __awaiter(void 0, void 0, void 0, function () {
166
- var target, fixture;
186
+ var target, fixture, fixture;
167
187
  var _a;
168
188
  return __generator(this, function (_b) {
169
189
  target = typeof input === 'string' ? input : (input && input.url) || String(input);
@@ -175,6 +195,12 @@ var loadWorker = function (base) {
175
195
  })];
176
196
  if (target.includes('index.html'))
177
197
  return [2 /*return*/, new Response('<!doctype html><html><head><title>App</title></head><body>home</body></html>', { status: 200, headers: { 'content-type': 'text/html' } })];
198
+ if (target.includes('identity.json')) {
199
+ fixture = global.__sasjsIdentity;
200
+ if (fixture === 'missing')
201
+ return [2 /*return*/, new Response('', { status: 404 })];
202
+ return [2 /*return*/, jsonResponse(fixture || api_1.DEFAULT_IDENTITY)];
203
+ }
178
204
  if (target.includes('sas-transcript')) {
179
205
  fixture = global.__sasTranscript;
180
206
  return [2 /*return*/, fixture ? jsonResponse(fixture) : new Response('', { status: 404 })];
@@ -262,6 +288,8 @@ describe('service worker host', function () {
262
288
  delete global.self;
263
289
  delete global.importScripts;
264
290
  delete global.fetch;
291
+ delete global.__sasjsIdentity;
292
+ delete global.__mockHostClients;
265
293
  });
266
294
  var seeded = function () {
267
295
  var _a;
@@ -928,44 +956,40 @@ describe('service worker host', function () {
928
956
  });
929
957
  }); });
930
958
  it('imports the fixture directory, and unpublishes the site itself', function () { return __awaiter(void 0, void 0, void 0, function () {
931
- var dispatch, synced, _a, unpublished, _b, other;
932
- return __generator(this, function (_c) {
933
- switch (_c.label) {
959
+ var dispatch, synced, _a, siteAppId, unpublished, removed, other;
960
+ return __generator(this, function (_b) {
961
+ switch (_b.label) {
934
962
  case 0:
935
963
  dispatch = seeded().dispatch;
936
964
  return [4 /*yield*/, dispatch('/SASjsApi/authConfig/synchroniseWithLDAP', { method: 'POST' })];
937
965
  case 1:
938
- synced = _c.sent();
966
+ synced = _b.sent();
939
967
  expect(synced.status).toBe(200);
940
968
  _a = expect;
941
969
  return [4 /*yield*/, synced.json()];
942
970
  case 2:
943
- _a.apply(void 0, [_c.sent()]).toEqual({ userCount: 0, groupCount: 0 });
971
+ _a.apply(void 0, [_b.sent()]).toEqual({ userCount: 0, groupCount: 0 });
972
+ siteAppId = '6f1c1c1e-6a1e-4c4a-9d1a-1b2c3d4e5f60';
944
973
  return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy', {
945
974
  method: 'DELETE',
946
975
  headers: { 'content-type': 'application/json' },
947
- body: JSON.stringify({
948
- streamServiceName: 'Test',
949
- appLoc: appLoc
950
- })
976
+ body: JSON.stringify({ id: siteAppId })
951
977
  })];
952
978
  case 3:
953
- unpublished = _c.sent();
979
+ unpublished = _b.sent();
954
980
  expect(unpublished.status).toBe(200);
955
- _b = expect;
956
981
  return [4 /*yield*/, unpublished.json()];
957
982
  case 4:
958
- _b.apply(void 0, [_c.sent()]).toEqual({ status: 'success' });
983
+ removed = _b.sent();
984
+ expect(removed.status).toBe('success');
985
+ expect(removed.app.id).toBe(siteAppId);
959
986
  return [4 /*yield*/, dispatch('/SASjsApi/drive/deploy', {
960
987
  method: 'DELETE',
961
988
  headers: { 'content-type': 'application/json' },
962
- body: JSON.stringify({
963
- streamServiceName: 'Other',
964
- appLoc: '/Public/app/other'
965
- })
989
+ body: JSON.stringify({ id: '00000000-0000-4000-8000-000000000000' })
966
990
  })];
967
991
  case 5:
968
- other = _c.sent();
992
+ other = _b.sent();
969
993
  expect(other.status).toBe(404);
970
994
  return [2 /*return*/];
971
995
  }
@@ -2663,4 +2687,484 @@ describe('service worker host', function () {
2663
2687
  finally { if (e_4) throw e_4.error; }
2664
2688
  }
2665
2689
  });
2690
+ /**
2691
+ * The identity and record corpora, over the worker's HTTP surface.
2692
+ *
2693
+ * The same cases @sasjs/api runs against its own services, and the server runs
2694
+ * against a live sasjs/server. A failure here is this host's transport, the
2695
+ * fixture it booted, or a route it does not answer - never the decisions, which
2696
+ * are the package's.
2697
+ */
2698
+ describe('identity and record conformance', function () {
2699
+ var e_8, _a;
2700
+ /**
2701
+ * Boots the worker from a fixture, the way the page does: the case's own
2702
+ * identity, and `subject: null` for no implicit caller, so a case that
2703
+ * expects the answer an anonymous request gets is not silently answered as
2704
+ * the fixture's administrator.
2705
+ */
2706
+ var boot = function (worker_1, identity_1) {
2707
+ var args_1 = [];
2708
+ for (var _i = 2; _i < arguments.length; _i++) {
2709
+ args_1[_i - 2] = arguments[_i];
2710
+ }
2711
+ return __awaiter(void 0, __spreadArray([worker_1, identity_1], __read(args_1), false), void 0, function (worker, identity, subject) {
2712
+ var pending;
2713
+ if (subject === void 0) { subject = null; }
2714
+ return __generator(this, function (_a) {
2715
+ switch (_a.label) {
2716
+ case 0:
2717
+ pending = worker.message({
2718
+ type: 'sasjs-seed',
2719
+ identity: identity,
2720
+ subject: subject
2721
+ }).pending;
2722
+ return [4 /*yield*/, pending];
2723
+ case 1:
2724
+ _a.sent();
2725
+ return [2 /*return*/];
2726
+ }
2727
+ });
2728
+ });
2729
+ };
2730
+ /** The request a case describes, as HTTP: path parameters filled, token sent. */
2731
+ var httpForCase = function (testCase) {
2732
+ var e_9, _a;
2733
+ var _b = __read(testCase.route.split(' '), 2), method = _b[0], routePath = _b[1];
2734
+ var filled = routePath.replace(/\{(\w+)\}/g, function (_match, name) {
2735
+ return encodeURIComponent(String((testCase.request.params || {})[name]));
2736
+ });
2737
+ var query = new URLSearchParams();
2738
+ try {
2739
+ for (var _c = __values(Object.entries(testCase.request.query || {})), _d = _c.next(); !_d.done; _d = _c.next()) {
2740
+ var _e = __read(_d.value, 2), key = _e[0], value = _e[1];
2741
+ if (value !== undefined)
2742
+ query.set(key, String(value));
2743
+ }
2744
+ }
2745
+ catch (e_9_1) { e_9 = { error: e_9_1 }; }
2746
+ finally {
2747
+ try {
2748
+ if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
2749
+ }
2750
+ finally { if (e_9) throw e_9.error; }
2751
+ }
2752
+ var suffix = query.toString() ? "?".concat(query) : '';
2753
+ var headers = {};
2754
+ var init = { method: method, headers: headers };
2755
+ if (testCase.request.token)
2756
+ headers.authorization = 'Bearer ' + testCase.request.token;
2757
+ if (testCase.request.body !== undefined) {
2758
+ init.body = JSON.stringify(testCase.request.body);
2759
+ headers['content-type'] = 'application/json';
2760
+ }
2761
+ return { path: filled + suffix, init: init };
2762
+ };
2763
+ /** The assertions the package's own corpus makes, against an HTTP answer. */
2764
+ var expectAnswer = function (testCase, response) { return __awaiter(void 0, void 0, void 0, function () {
2765
+ var want, contentType, isJson, sent, _a, _b, expected, error, _c, body, _d, required, _e, optional, present_1, allowed_1;
2766
+ return __generator(this, function (_f) {
2767
+ switch (_f.label) {
2768
+ case 0:
2769
+ expect({ case: testCase.id, status: response.status }).toEqual({
2770
+ case: testCase.id,
2771
+ status: testCase.expect.status
2772
+ });
2773
+ want = testCase.expect;
2774
+ contentType = response.headers.get('content-type') || '';
2775
+ isJson = contentType.includes('application/json');
2776
+ if (!(want.contents !== undefined)) return [3 /*break*/, 5];
2777
+ if (!(want.encoding === 'text')) return [3 /*break*/, 2];
2778
+ return [4 /*yield*/, response.text()];
2779
+ case 1:
2780
+ _a = _f.sent();
2781
+ return [3 /*break*/, 4];
2782
+ case 2:
2783
+ _b = Uint8Array.bind;
2784
+ return [4 /*yield*/, response.arrayBuffer()];
2785
+ case 3:
2786
+ _a = new (_b.apply(Uint8Array, [void 0, _f.sent()]))();
2787
+ _f.label = 4;
2788
+ case 4:
2789
+ sent = _a;
2790
+ expected = typeof want.contents === 'string'
2791
+ ? want.encoding === 'text'
2792
+ ? want.contents
2793
+ : new TextEncoder().encode(want.contents)
2794
+ : want.contents;
2795
+ expect(sent).toEqual(expected);
2796
+ return [2 /*return*/];
2797
+ case 5:
2798
+ if (!(want.error !== undefined)) return [3 /*break*/, 10];
2799
+ if (!isJson) return [3 /*break*/, 7];
2800
+ return [4 /*yield*/, response.json()];
2801
+ case 6:
2802
+ _c = (_f.sent()).message;
2803
+ return [3 /*break*/, 9];
2804
+ case 7: return [4 /*yield*/, response.text()];
2805
+ case 8:
2806
+ _c = _f.sent();
2807
+ _f.label = 9;
2808
+ case 9:
2809
+ error = _c;
2810
+ expect({ case: testCase.id, error: error }).toEqual({
2811
+ case: testCase.id,
2812
+ error: want.error
2813
+ });
2814
+ return [2 /*return*/];
2815
+ case 10:
2816
+ if (want.body === undefined &&
2817
+ want.partial === undefined &&
2818
+ want.keys === undefined &&
2819
+ want.shape === undefined)
2820
+ return [2 /*return*/];
2821
+ return [4 /*yield*/, response.json()];
2822
+ case 11:
2823
+ body = _f.sent();
2824
+ if (want.body !== undefined)
2825
+ expect(body).toEqual(want.body);
2826
+ if (want.partial !== undefined)
2827
+ expect(body).toMatchObject(want.partial);
2828
+ if (want.keys !== undefined)
2829
+ expect(Object.keys(body).sort()).toEqual(want.keys.slice().sort());
2830
+ if (want.shape !== undefined) {
2831
+ _d = want.shape, required = _d.required, _e = _d.optional, optional = _e === void 0 ? [] : _e;
2832
+ present_1 = Object.keys(body);
2833
+ allowed_1 = __spreadArray(__spreadArray([], __read(required), false), __read(optional), false);
2834
+ expect({
2835
+ case: testCase.id,
2836
+ missing: required.filter(function (key) { return !present_1.includes(key); }),
2837
+ unexpected: present_1.filter(function (key) { return !allowed_1.includes(key); })
2838
+ }).toEqual({ case: testCase.id, missing: [], unexpected: [] });
2839
+ }
2840
+ return [2 /*return*/];
2841
+ }
2842
+ });
2843
+ }); };
2844
+ var _loop_2 = function (testCase) {
2845
+ it("".concat(testCase.id, ": ").concat(testCase.description), function () { return __awaiter(void 0, void 0, void 0, function () {
2846
+ var worker, _a, requestPath, init, _b, _c;
2847
+ return __generator(this, function (_d) {
2848
+ switch (_d.label) {
2849
+ case 0:
2850
+ worker = loadWorker();
2851
+ return [4 /*yield*/, boot(worker, testCase.identity || api_1.DEFAULT_IDENTITY)];
2852
+ case 1:
2853
+ _d.sent();
2854
+ _a = httpForCase(testCase), requestPath = _a.path, init = _a.init;
2855
+ _b = expectAnswer;
2856
+ _c = [testCase];
2857
+ return [4 /*yield*/, worker.dispatch(requestPath, init)];
2858
+ case 2: return [4 /*yield*/, _b.apply(void 0, _c.concat([_d.sent()]))];
2859
+ case 3:
2860
+ _d.sent();
2861
+ return [2 /*return*/];
2862
+ }
2863
+ });
2864
+ }); });
2865
+ };
2866
+ try {
2867
+ for (var _b = __values(__spreadArray(__spreadArray([], __read(api_1.IDENTITY_CORPUS), false), __read(api_1.RECORD_CORPUS), false)), _c = _b.next(); !_c.done; _c = _b.next()) {
2868
+ var testCase = _c.value;
2869
+ _loop_2(testCase);
2870
+ }
2871
+ }
2872
+ catch (e_8_1) { e_8 = { error: e_8_1 }; }
2873
+ finally {
2874
+ try {
2875
+ if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
2876
+ }
2877
+ finally { if (e_8) throw e_8.error; }
2878
+ }
2879
+ it('answers as the fixture administrator when no subject was chosen', function () { return __awaiter(void 0, void 0, void 0, function () {
2880
+ var worker, response, rules;
2881
+ return __generator(this, function (_a) {
2882
+ switch (_a.label) {
2883
+ case 0:
2884
+ worker = loadWorker();
2885
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/permission')];
2886
+ case 1:
2887
+ response = _a.sent();
2888
+ return [4 /*yield*/, response.json()];
2889
+ case 2:
2890
+ rules = _a.sent();
2891
+ expect(response.status).toBe(200);
2892
+ expect(rules.length).toBe(3);
2893
+ expect(rules.map(function (rule) { return rule.uid; })).toEqual([
2894
+ 'rule-routes',
2895
+ 'rule-execute',
2896
+ 'rule-code'
2897
+ ]);
2898
+ return [2 /*return*/];
2899
+ }
2900
+ });
2901
+ }); });
2902
+ it('signs in as another account, changing the permission answer and the token subject', function () { return __awaiter(void 0, void 0, void 0, function () {
2903
+ var worker, _a, replies, pending, ack, routes, _b, session, _c;
2904
+ return __generator(this, function (_d) {
2905
+ switch (_d.label) {
2906
+ case 0:
2907
+ worker = loadWorker();
2908
+ _a = worker.message({
2909
+ type: 'sasjs-as',
2910
+ username: 'sasjsuser'
2911
+ }), replies = _a.replies, pending = _a.pending;
2912
+ return [4 /*yield*/, pending];
2913
+ case 1:
2914
+ _d.sent();
2915
+ ack = replies[0];
2916
+ expect(ack.username).toBe('sasjsuser');
2917
+ expect(ack.accessToken).toBeTruthy();
2918
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/info/myAuthorizedRoutes')];
2919
+ case 2:
2920
+ routes = _d.sent();
2921
+ _b = expect;
2922
+ return [4 /*yield*/, routes.json()];
2923
+ case 3:
2924
+ _b.apply(void 0, [(_d.sent()).paths]).toEqual([
2925
+ '/AppStream',
2926
+ '/SASjsApi/stp/execute',
2927
+ '/SASjsApi/drive/file'
2928
+ ]);
2929
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/session', {
2930
+ headers: { authorization: 'Bearer ' + ack.accessToken }
2931
+ })];
2932
+ case 4:
2933
+ session = _d.sent();
2934
+ expect(session.status).toBe(200);
2935
+ _c = expect;
2936
+ return [4 /*yield*/, session.json()];
2937
+ case 5:
2938
+ _c.apply(void 0, [(_d.sent()).username]).toBe('sasjsuser');
2939
+ return [2 /*return*/];
2940
+ }
2941
+ });
2942
+ }); });
2943
+ it('returns to the administrator with no account named, or with "admin"', function () { return __awaiter(void 0, void 0, void 0, function () {
2944
+ var worker, back, routes, _a;
2945
+ return __generator(this, function (_b) {
2946
+ switch (_b.label) {
2947
+ case 0:
2948
+ worker = loadWorker();
2949
+ return [4 /*yield*/, worker.message({ type: 'sasjs-as', username: 'sasjsuser' }).pending];
2950
+ case 1:
2951
+ _b.sent();
2952
+ back = worker.message({ type: 'sasjs-as', username: 'admin' });
2953
+ return [4 /*yield*/, back.pending];
2954
+ case 2:
2955
+ _b.sent();
2956
+ expect(back.replies[0].username).toBe('sasjsadmin');
2957
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/info/myAuthorizedRoutes')
2958
+ // a route only the administrator's rules reach: the restricted account's
2959
+ // list is the three entries the corpus pins
2960
+ ];
2961
+ case 3:
2962
+ routes = _b.sent();
2963
+ // a route only the administrator's rules reach: the restricted account's
2964
+ // list is the three entries the corpus pins
2965
+ _a = expect;
2966
+ return [4 /*yield*/, routes.json()];
2967
+ case 4:
2968
+ // a route only the administrator's rules reach: the restricted account's
2969
+ // list is the three entries the corpus pins
2970
+ _a.apply(void 0, [(_b.sent()).paths]).toContain('/SASjsApi/code/execute');
2971
+ return [2 /*return*/];
2972
+ }
2973
+ });
2974
+ }); });
2975
+ it('refuses an unknown account by name, naming the accounts the fixture holds', function () { return __awaiter(void 0, void 0, void 0, function () {
2976
+ var worker, _a, replies, pending;
2977
+ return __generator(this, function (_b) {
2978
+ switch (_b.label) {
2979
+ case 0:
2980
+ worker = loadWorker();
2981
+ _a = worker.message({
2982
+ type: 'sasjs-as',
2983
+ username: 'nobody'
2984
+ }), replies = _a.replies, pending = _a.pending;
2985
+ return [4 /*yield*/, pending];
2986
+ case 1:
2987
+ _b.sent();
2988
+ expect(replies[0].error).toContain('no account named "nobody"');
2989
+ expect(replies[0].error).toContain('sasjsadmin');
2990
+ expect(replies[0].accessToken).toBeUndefined();
2991
+ return [2 /*return*/];
2992
+ }
2993
+ });
2994
+ }); });
2995
+ it('refuses a persisted fixture in a format this build does not read, by name', function () { return __awaiter(void 0, void 0, void 0, function () {
2996
+ var worker, _a, replies, pending;
2997
+ return __generator(this, function (_b) {
2998
+ switch (_b.label) {
2999
+ case 0:
3000
+ worker = loadWorker();
3001
+ _a = worker.message({
3002
+ type: 'sasjs-seed',
3003
+ identity: __assign(__assign({}, api_1.DEFAULT_IDENTITY), { format: 0 }),
3004
+ subject: null
3005
+ }), replies = _a.replies, pending = _a.pending;
3006
+ return [4 /*yield*/, pending];
3007
+ case 1:
3008
+ _b.sent();
3009
+ expect(replies[0].error).toContain('states format 0');
3010
+ expect(replies[0].error).toContain('Rebuild the site');
3011
+ // the page drops the stored row ONLY for this kind: a host-side failure
3012
+ // must not take the visitor's accounts with it
3013
+ expect(replies[0].errorKind).toBe('identity');
3014
+ return [2 /*return*/];
3015
+ }
3016
+ });
3017
+ }); });
3018
+ it('refuses a shipped fixture it cannot read, naming the file', function () { return __awaiter(void 0, void 0, void 0, function () {
3019
+ var worker, response, body;
3020
+ return __generator(this, function (_a) {
3021
+ switch (_a.label) {
3022
+ case 0:
3023
+ ;
3024
+ global.__sasjsIdentity = __assign(__assign({}, api_1.DEFAULT_IDENTITY), { format: 7 });
3025
+ worker = loadWorker();
3026
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/permission')];
3027
+ case 1:
3028
+ response = _a.sent();
3029
+ return [4 /*yield*/, response.json()];
3030
+ case 2:
3031
+ body = _a.sent();
3032
+ expect(response.status).toBe(500);
3033
+ expect(body.message).toContain('host/identity.json cannot be used');
3034
+ expect(body.message).toContain('states format 7');
3035
+ return [2 /*return*/];
3036
+ }
3037
+ });
3038
+ }); });
3039
+ it('replies with the error when a reset cannot read the shipped fixture', function () { return __awaiter(void 0, void 0, void 0, function () {
3040
+ var worker, _a, replies, pending;
3041
+ return __generator(this, function (_b) {
3042
+ switch (_b.label) {
3043
+ case 0:
3044
+ // the page waits for this ack: silence is read as success, and a reset is
3045
+ // the way out of a site whose fixture broke
3046
+ ;
3047
+ global.__sasjsIdentity = __assign(__assign({}, api_1.DEFAULT_IDENTITY), { format: 4 });
3048
+ worker = loadWorker();
3049
+ // a request first, so the failure is the cached one the site already has
3050
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/permission')];
3051
+ case 1:
3052
+ // a request first, so the failure is the cached one the site already has
3053
+ _b.sent();
3054
+ _a = worker.message({ type: 'sasjs-reset' }), replies = _a.replies, pending = _a.pending;
3055
+ return [4 /*yield*/, pending];
3056
+ case 2:
3057
+ _b.sent();
3058
+ expect(replies[0].type).toBe('sasjs-reset-ack');
3059
+ expect(replies[0].error).toContain('host/identity.json cannot be used');
3060
+ expect(replies[0].boot).toBeUndefined();
3061
+ return [2 /*return*/];
3062
+ }
3063
+ });
3064
+ }); });
3065
+ it('falls back to the packaged fixture when the site ships no identity file', function () { return __awaiter(void 0, void 0, void 0, function () {
3066
+ var worker, response, rules;
3067
+ return __generator(this, function (_a) {
3068
+ switch (_a.label) {
3069
+ case 0:
3070
+ ;
3071
+ global.__sasjsIdentity = 'missing';
3072
+ worker = loadWorker();
3073
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/permission')];
3074
+ case 1:
3075
+ response = _a.sent();
3076
+ return [4 /*yield*/, response.json()];
3077
+ case 2:
3078
+ rules = _a.sent();
3079
+ expect(response.status).toBe(200);
3080
+ expect(rules.length).toBe(3);
3081
+ return [2 /*return*/];
3082
+ }
3083
+ });
3084
+ }); });
3085
+ it('reports an account created through the routes, so the page can store it', function () { return __awaiter(void 0, void 0, void 0, function () {
3086
+ var worker, sent, response, persisted;
3087
+ return __generator(this, function (_a) {
3088
+ switch (_a.label) {
3089
+ case 0:
3090
+ worker = loadWorker();
3091
+ sent = [];
3092
+ global.__mockHostClients = [
3093
+ { postMessage: function (message) { return sent.push(message); } }
3094
+ ];
3095
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/user', {
3096
+ method: 'POST',
3097
+ headers: { 'content-type': 'application/json' },
3098
+ body: JSON.stringify({
3099
+ username: 'newuser',
3100
+ displayName: 'New User',
3101
+ password: 'newpass',
3102
+ isAdmin: false,
3103
+ isActive: true
3104
+ })
3105
+ })];
3106
+ case 1:
3107
+ response = _a.sent();
3108
+ expect(response.status).toBe(200);
3109
+ persisted = sent.find(function (message) { return message.type === 'sasjs-persist' && message.identity; });
3110
+ expect(persisted.identity.users.map(function (user) { return user.username; })).toContain('newuser');
3111
+ delete global.__mockHostClients;
3112
+ return [2 /*return*/];
3113
+ }
3114
+ });
3115
+ }); });
3116
+ it('restores the shipped fixture on reset', function () { return __awaiter(void 0, void 0, void 0, function () {
3117
+ var worker, users, _a, routes, _b;
3118
+ return __generator(this, function (_c) {
3119
+ switch (_c.label) {
3120
+ case 0:
3121
+ worker = loadWorker();
3122
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/user', {
3123
+ method: 'POST',
3124
+ headers: { 'content-type': 'application/json' },
3125
+ body: JSON.stringify({
3126
+ username: 'newuser',
3127
+ displayName: 'New User',
3128
+ password: 'newpass',
3129
+ isAdmin: false,
3130
+ isActive: true
3131
+ })
3132
+ })];
3133
+ case 1:
3134
+ _c.sent();
3135
+ return [4 /*yield*/, worker.message({ type: 'sasjs-as', username: 'sasjsuser' }).pending];
3136
+ case 2:
3137
+ _c.sent();
3138
+ return [4 /*yield*/, worker.message({ type: 'sasjs-reset' }).pending];
3139
+ case 3:
3140
+ _c.sent();
3141
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/user')];
3142
+ case 4:
3143
+ users = _c.sent();
3144
+ _a = expect;
3145
+ return [4 /*yield*/, users.json()];
3146
+ case 5:
3147
+ _a.apply(void 0, [(_c.sent()).map(function (user) { return user.username; })]).toEqual([
3148
+ 'sasjsadmin',
3149
+ 'sasjsuser'
3150
+ ]);
3151
+ return [4 /*yield*/, worker.dispatch('/SASjsApi/info/myAuthorizedRoutes')
3152
+ // a route only the administrator's rules reach: the restricted account's
3153
+ // list is the three entries the corpus pins
3154
+ ];
3155
+ case 6:
3156
+ routes = _c.sent();
3157
+ // a route only the administrator's rules reach: the restricted account's
3158
+ // list is the three entries the corpus pins
3159
+ _b = expect;
3160
+ return [4 /*yield*/, routes.json()];
3161
+ case 7:
3162
+ // a route only the administrator's rules reach: the restricted account's
3163
+ // list is the three entries the corpus pins
3164
+ _b.apply(void 0, [(_c.sent()).paths]).toContain('/SASjsApi/code/execute');
3165
+ return [2 /*return*/];
3166
+ }
3167
+ });
3168
+ }); });
3169
+ });
2666
3170
  });
package/package.json CHANGED
@@ -70,10 +70,10 @@
70
70
  "registry": "https://registry.npmjs.org"
71
71
  },
72
72
  "dependencies": {
73
- "@sasjs/adapter": "5.1.3",
74
- "@sasjs/api": "0.24.0",
75
- "@sasjs/core": "6.1.1",
76
- "@sasjs/lint": "^5.1.0",
73
+ "@sasjs/adapter": "5.2.6",
74
+ "@sasjs/api": "0.27.0",
75
+ "@sasjs/core": "7.1.12",
76
+ "@sasjs/lint": "5.1.1",
77
77
  "@sasjs/utils": "4.11.0",
78
78
  "axios": "1.20.0",
79
79
  "chalk": "4.1.2",
@@ -125,5 +125,5 @@
125
125
  "ws": "8.21.0",
126
126
  "nanoid": "3.3.18"
127
127
  },
128
- "version": "6.25.0"
128
+ "version": "6.26.0"
129
129
  }