@terreno/api 0.0.10 → 0.0.11-beta.1
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/CLAUDE.md +107 -0
- package/bunfig.toml +3 -2
- package/dist/api.d.ts +3 -14
- package/dist/api.js +44 -68
- package/dist/api.test.js +2051 -166
- package/dist/permissions.d.ts +1 -1
- package/dist/permissions.js +17 -25
- package/dist/utils.test.js +169 -7
- package/package.json +3 -2
- package/src/api.test.ts +1736 -142
- package/src/api.ts +19 -61
- package/src/permissions.ts +4 -14
- package/src/utils.test.ts +189 -9
package/dist/api.test.js
CHANGED
|
@@ -90,7 +90,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
90
90
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91
91
|
var bun_test_1 = require("bun:test");
|
|
92
92
|
var Sentry = __importStar(require("@sentry/node"));
|
|
93
|
-
var sortBy_1 = __importDefault(require("lodash/sortBy"));
|
|
94
93
|
var qs_1 = __importDefault(require("qs"));
|
|
95
94
|
var supertest_1 = __importDefault(require("supertest"));
|
|
96
95
|
var api_1 = require("./api");
|
|
@@ -99,6 +98,7 @@ var errors_1 = require("./errors");
|
|
|
99
98
|
var expressServer_1 = require("./expressServer");
|
|
100
99
|
var permissions_1 = require("./permissions");
|
|
101
100
|
var tests_1 = require("./tests");
|
|
101
|
+
var transformers_1 = require("./transformers");
|
|
102
102
|
(0, bun_test_1.describe)("@terreno/api", function () {
|
|
103
103
|
var server;
|
|
104
104
|
var app;
|
|
@@ -1879,262 +1879,2147 @@ var tests_1 = require("./tests");
|
|
|
1879
1879
|
});
|
|
1880
1880
|
}); });
|
|
1881
1881
|
});
|
|
1882
|
-
(0, bun_test_1.describe)("
|
|
1883
|
-
var
|
|
1884
|
-
var
|
|
1885
|
-
var
|
|
1882
|
+
(0, bun_test_1.describe)("error handling", function () {
|
|
1883
|
+
var admin;
|
|
1884
|
+
var agent;
|
|
1885
|
+
var spinach;
|
|
1886
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1887
|
+
var _a;
|
|
1888
|
+
return __generator(this, function (_b) {
|
|
1889
|
+
switch (_b.label) {
|
|
1890
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
1891
|
+
case 1:
|
|
1892
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
1893
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
1894
|
+
calories: 1,
|
|
1895
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
1896
|
+
hidden: false,
|
|
1897
|
+
name: "Spinach",
|
|
1898
|
+
ownerId: admin._id,
|
|
1899
|
+
source: {
|
|
1900
|
+
name: "Brand",
|
|
1901
|
+
},
|
|
1902
|
+
})];
|
|
1903
|
+
case 2:
|
|
1904
|
+
spinach = _b.sent();
|
|
1905
|
+
app = (0, tests_1.getBaseServer)();
|
|
1906
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
1907
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
1908
|
+
return [2 /*return*/];
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
}); });
|
|
1912
|
+
(0, bun_test_1.it)("PUT returns 500 not supported", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1913
|
+
var res;
|
|
1914
|
+
return __generator(this, function (_a) {
|
|
1915
|
+
switch (_a.label) {
|
|
1916
|
+
case 0:
|
|
1917
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
1918
|
+
allowAnonymous: true,
|
|
1919
|
+
permissions: {
|
|
1920
|
+
create: [permissions_1.Permissions.IsAny],
|
|
1921
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
1922
|
+
list: [permissions_1.Permissions.IsAny],
|
|
1923
|
+
read: [permissions_1.Permissions.IsAny],
|
|
1924
|
+
update: [permissions_1.Permissions.IsAny],
|
|
1925
|
+
},
|
|
1926
|
+
}));
|
|
1927
|
+
server = (0, supertest_1.default)(app);
|
|
1928
|
+
return [4 /*yield*/, server.put("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(500)];
|
|
1929
|
+
case 1:
|
|
1930
|
+
res = _a.sent();
|
|
1931
|
+
(0, bun_test_1.expect)(res.body.title).toBe("PUT is not supported.");
|
|
1932
|
+
return [2 /*return*/];
|
|
1933
|
+
}
|
|
1934
|
+
});
|
|
1935
|
+
}); });
|
|
1936
|
+
(0, bun_test_1.it)("preCreate returning undefined throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1937
|
+
var res;
|
|
1938
|
+
return __generator(this, function (_a) {
|
|
1939
|
+
switch (_a.label) {
|
|
1940
|
+
case 0:
|
|
1941
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
1942
|
+
allowAnonymous: true,
|
|
1943
|
+
permissions: {
|
|
1944
|
+
create: [permissions_1.Permissions.IsAny],
|
|
1945
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
1946
|
+
list: [permissions_1.Permissions.IsAny],
|
|
1947
|
+
read: [permissions_1.Permissions.IsAny],
|
|
1948
|
+
update: [permissions_1.Permissions.IsAny],
|
|
1949
|
+
},
|
|
1950
|
+
preCreate: function () { return undefined; },
|
|
1951
|
+
}));
|
|
1952
|
+
server = (0, supertest_1.default)(app);
|
|
1953
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(403)];
|
|
1954
|
+
case 1:
|
|
1955
|
+
res = _a.sent();
|
|
1956
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Create not allowed");
|
|
1957
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("A body must be returned from preCreate");
|
|
1958
|
+
return [2 /*return*/];
|
|
1959
|
+
}
|
|
1960
|
+
});
|
|
1961
|
+
}); });
|
|
1962
|
+
(0, bun_test_1.it)("preUpdate returning undefined throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1963
|
+
var res;
|
|
1964
|
+
return __generator(this, function (_a) {
|
|
1965
|
+
switch (_a.label) {
|
|
1966
|
+
case 0:
|
|
1967
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
1968
|
+
allowAnonymous: true,
|
|
1969
|
+
permissions: {
|
|
1970
|
+
create: [permissions_1.Permissions.IsAny],
|
|
1971
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
1972
|
+
list: [permissions_1.Permissions.IsAny],
|
|
1973
|
+
read: [permissions_1.Permissions.IsAny],
|
|
1974
|
+
update: [permissions_1.Permissions.IsAny],
|
|
1975
|
+
},
|
|
1976
|
+
preUpdate: function () { return undefined; },
|
|
1977
|
+
}));
|
|
1978
|
+
server = (0, supertest_1.default)(app);
|
|
1979
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(403)];
|
|
1980
|
+
case 1:
|
|
1981
|
+
res = _a.sent();
|
|
1982
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
1983
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("A body must be returned from preUpdate");
|
|
1984
|
+
return [2 /*return*/];
|
|
1985
|
+
}
|
|
1986
|
+
});
|
|
1987
|
+
}); });
|
|
1988
|
+
(0, bun_test_1.it)("preDelete returning undefined throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1989
|
+
var res;
|
|
1990
|
+
return __generator(this, function (_a) {
|
|
1991
|
+
switch (_a.label) {
|
|
1992
|
+
case 0:
|
|
1993
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
1994
|
+
allowAnonymous: true,
|
|
1995
|
+
permissions: {
|
|
1996
|
+
create: [permissions_1.Permissions.IsAny],
|
|
1997
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
1998
|
+
list: [permissions_1.Permissions.IsAny],
|
|
1999
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2000
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2001
|
+
},
|
|
2002
|
+
preDelete: function () { return undefined; },
|
|
2003
|
+
}));
|
|
2004
|
+
server = (0, supertest_1.default)(app);
|
|
2005
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2006
|
+
case 1:
|
|
2007
|
+
agent = _a.sent();
|
|
2008
|
+
return [4 /*yield*/, agent.delete("/food/".concat(spinach._id)).expect(403)];
|
|
2009
|
+
case 2:
|
|
2010
|
+
res = _a.sent();
|
|
2011
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Delete not allowed");
|
|
2012
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("A body must be returned from preDelete");
|
|
2013
|
+
return [2 /*return*/];
|
|
2014
|
+
}
|
|
2015
|
+
});
|
|
2016
|
+
}); });
|
|
2017
|
+
(0, bun_test_1.it)("postCreate hook error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2018
|
+
var res;
|
|
2019
|
+
return __generator(this, function (_a) {
|
|
2020
|
+
switch (_a.label) {
|
|
2021
|
+
case 0:
|
|
2022
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2023
|
+
allowAnonymous: true,
|
|
2024
|
+
permissions: {
|
|
2025
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2026
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2027
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2028
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2029
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2030
|
+
},
|
|
2031
|
+
postCreate: function () {
|
|
2032
|
+
throw new Error("postCreate failed");
|
|
2033
|
+
},
|
|
2034
|
+
}));
|
|
2035
|
+
server = (0, supertest_1.default)(app);
|
|
2036
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(400)];
|
|
2037
|
+
case 1:
|
|
2038
|
+
res = _a.sent();
|
|
2039
|
+
(0, bun_test_1.expect)(res.body.title).toContain("postCreate hook error");
|
|
2040
|
+
return [2 /*return*/];
|
|
2041
|
+
}
|
|
2042
|
+
});
|
|
2043
|
+
}); });
|
|
2044
|
+
(0, bun_test_1.it)("postUpdate hook error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2045
|
+
var res;
|
|
2046
|
+
return __generator(this, function (_a) {
|
|
2047
|
+
switch (_a.label) {
|
|
2048
|
+
case 0:
|
|
2049
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2050
|
+
allowAnonymous: true,
|
|
2051
|
+
permissions: {
|
|
2052
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2053
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2054
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2055
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2056
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2057
|
+
},
|
|
2058
|
+
postUpdate: function () {
|
|
2059
|
+
throw new Error("postUpdate failed");
|
|
2060
|
+
},
|
|
2061
|
+
}));
|
|
2062
|
+
server = (0, supertest_1.default)(app);
|
|
2063
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(400)];
|
|
2064
|
+
case 1:
|
|
2065
|
+
res = _a.sent();
|
|
2066
|
+
(0, bun_test_1.expect)(res.body.title).toContain("postUpdate hook error");
|
|
2067
|
+
return [2 /*return*/];
|
|
2068
|
+
}
|
|
2069
|
+
});
|
|
2070
|
+
}); });
|
|
2071
|
+
(0, bun_test_1.it)("postDelete hook error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2072
|
+
var res;
|
|
2073
|
+
return __generator(this, function (_a) {
|
|
2074
|
+
switch (_a.label) {
|
|
2075
|
+
case 0:
|
|
2076
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2077
|
+
allowAnonymous: true,
|
|
2078
|
+
permissions: {
|
|
2079
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2080
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2081
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2082
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2083
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2084
|
+
},
|
|
2085
|
+
postDelete: function () {
|
|
2086
|
+
throw new Error("postDelete failed");
|
|
2087
|
+
},
|
|
2088
|
+
}));
|
|
2089
|
+
server = (0, supertest_1.default)(app);
|
|
2090
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2091
|
+
case 1:
|
|
2092
|
+
agent = _a.sent();
|
|
2093
|
+
return [4 /*yield*/, agent.delete("/food/".concat(spinach._id)).expect(400)];
|
|
2094
|
+
case 2:
|
|
2095
|
+
res = _a.sent();
|
|
2096
|
+
(0, bun_test_1.expect)(res.body.title).toContain("postDelete hook error");
|
|
2097
|
+
return [2 /*return*/];
|
|
2098
|
+
}
|
|
2099
|
+
});
|
|
2100
|
+
}); });
|
|
2101
|
+
(0, bun_test_1.it)("responseHandler error in read is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2102
|
+
var res;
|
|
2103
|
+
return __generator(this, function (_a) {
|
|
2104
|
+
switch (_a.label) {
|
|
2105
|
+
case 0:
|
|
2106
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2107
|
+
allowAnonymous: true,
|
|
2108
|
+
permissions: {
|
|
2109
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2110
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2111
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2112
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2113
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2114
|
+
},
|
|
2115
|
+
responseHandler: function (_data, method) {
|
|
2116
|
+
if (method === "read") {
|
|
2117
|
+
throw new Error("responseHandler read failed");
|
|
2118
|
+
}
|
|
2119
|
+
return {};
|
|
2120
|
+
},
|
|
2121
|
+
}));
|
|
2122
|
+
server = (0, supertest_1.default)(app);
|
|
2123
|
+
return [4 /*yield*/, server.get("/food/".concat(spinach._id)).expect(500)];
|
|
2124
|
+
case 1:
|
|
2125
|
+
res = _a.sent();
|
|
2126
|
+
(0, bun_test_1.expect)(res.body.title).toContain("responseHandler error");
|
|
2127
|
+
return [2 /*return*/];
|
|
2128
|
+
}
|
|
2129
|
+
});
|
|
2130
|
+
}); });
|
|
2131
|
+
(0, bun_test_1.it)("responseHandler error in create is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2132
|
+
var res;
|
|
2133
|
+
return __generator(this, function (_a) {
|
|
2134
|
+
switch (_a.label) {
|
|
2135
|
+
case 0:
|
|
2136
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2137
|
+
allowAnonymous: true,
|
|
2138
|
+
permissions: {
|
|
2139
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2140
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2141
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2142
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2143
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2144
|
+
},
|
|
2145
|
+
responseHandler: function (_data, method) {
|
|
2146
|
+
if (method === "create") {
|
|
2147
|
+
throw new Error("responseHandler create failed");
|
|
2148
|
+
}
|
|
2149
|
+
return {};
|
|
2150
|
+
},
|
|
2151
|
+
}));
|
|
2152
|
+
server = (0, supertest_1.default)(app);
|
|
2153
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(500)];
|
|
2154
|
+
case 1:
|
|
2155
|
+
res = _a.sent();
|
|
2156
|
+
(0, bun_test_1.expect)(res.body.title).toContain("responseHandler error");
|
|
2157
|
+
return [2 /*return*/];
|
|
2158
|
+
}
|
|
2159
|
+
});
|
|
2160
|
+
}); });
|
|
2161
|
+
(0, bun_test_1.it)("responseHandler error in update is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2162
|
+
var res;
|
|
2163
|
+
return __generator(this, function (_a) {
|
|
2164
|
+
switch (_a.label) {
|
|
2165
|
+
case 0:
|
|
2166
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2167
|
+
allowAnonymous: true,
|
|
2168
|
+
permissions: {
|
|
2169
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2170
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2171
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2172
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2173
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2174
|
+
},
|
|
2175
|
+
responseHandler: function (_data, method) {
|
|
2176
|
+
if (method === "update") {
|
|
2177
|
+
throw new Error("responseHandler update failed");
|
|
2178
|
+
}
|
|
2179
|
+
return {};
|
|
2180
|
+
},
|
|
2181
|
+
}));
|
|
2182
|
+
server = (0, supertest_1.default)(app);
|
|
2183
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(500)];
|
|
2184
|
+
case 1:
|
|
2185
|
+
res = _a.sent();
|
|
2186
|
+
(0, bun_test_1.expect)(res.body.title).toContain("responseHandler error");
|
|
2187
|
+
return [2 /*return*/];
|
|
2188
|
+
}
|
|
2189
|
+
});
|
|
2190
|
+
}); });
|
|
2191
|
+
(0, bun_test_1.it)("responseHandler error in list is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2192
|
+
var res;
|
|
2193
|
+
return __generator(this, function (_a) {
|
|
2194
|
+
switch (_a.label) {
|
|
2195
|
+
case 0:
|
|
2196
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2197
|
+
allowAnonymous: true,
|
|
2198
|
+
permissions: {
|
|
2199
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2200
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2201
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2202
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2203
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2204
|
+
},
|
|
2205
|
+
responseHandler: function (_data, method) {
|
|
2206
|
+
if (method === "list") {
|
|
2207
|
+
throw new Error("responseHandler list failed");
|
|
2208
|
+
}
|
|
2209
|
+
return {};
|
|
2210
|
+
},
|
|
2211
|
+
}));
|
|
2212
|
+
server = (0, supertest_1.default)(app);
|
|
2213
|
+
return [4 /*yield*/, server.get("/food").expect(500)];
|
|
2214
|
+
case 1:
|
|
2215
|
+
res = _a.sent();
|
|
2216
|
+
(0, bun_test_1.expect)(res.body.title).toContain("responseHandler error");
|
|
2217
|
+
return [2 /*return*/];
|
|
2218
|
+
}
|
|
2219
|
+
});
|
|
2220
|
+
}); });
|
|
2221
|
+
(0, bun_test_1.it)("list with non-array responseHandler returns data directly", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2222
|
+
var res;
|
|
2223
|
+
return __generator(this, function (_a) {
|
|
2224
|
+
switch (_a.label) {
|
|
2225
|
+
case 0:
|
|
2226
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2227
|
+
allowAnonymous: true,
|
|
2228
|
+
permissions: {
|
|
2229
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2230
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2231
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2232
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2233
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2234
|
+
},
|
|
2235
|
+
responseHandler: function (_data, method) {
|
|
2236
|
+
if (method === "list") {
|
|
2237
|
+
return { custom: "response" };
|
|
2238
|
+
}
|
|
2239
|
+
return {};
|
|
2240
|
+
},
|
|
2241
|
+
}));
|
|
2242
|
+
server = (0, supertest_1.default)(app);
|
|
2243
|
+
return [4 /*yield*/, server.get("/food").expect(200)];
|
|
2244
|
+
case 1:
|
|
2245
|
+
res = _a.sent();
|
|
2246
|
+
(0, bun_test_1.expect)(res.body.data).toEqual({ custom: "response" });
|
|
2247
|
+
(0, bun_test_1.expect)(res.body.more).toBeUndefined();
|
|
2248
|
+
(0, bun_test_1.expect)(res.body.total).toBeUndefined();
|
|
2249
|
+
return [2 /*return*/];
|
|
2250
|
+
}
|
|
2251
|
+
});
|
|
2252
|
+
}); });
|
|
2253
|
+
(0, bun_test_1.it)("list with query sort param", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2254
|
+
var res;
|
|
2255
|
+
return __generator(this, function (_a) {
|
|
2256
|
+
switch (_a.label) {
|
|
2257
|
+
case 0: return [4 /*yield*/, tests_1.FoodModel.create({
|
|
2258
|
+
calories: 200,
|
|
2259
|
+
created: new Date("2021-12-04T00:00:20.000Z"),
|
|
2260
|
+
hidden: false,
|
|
2261
|
+
name: "Apple",
|
|
2262
|
+
ownerId: admin._id,
|
|
2263
|
+
})];
|
|
2264
|
+
case 1:
|
|
2265
|
+
_a.sent();
|
|
2266
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2267
|
+
allowAnonymous: true,
|
|
2268
|
+
permissions: {
|
|
2269
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2270
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2271
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2272
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2273
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2274
|
+
},
|
|
2275
|
+
queryFields: ["name"],
|
|
2276
|
+
}));
|
|
2277
|
+
server = (0, supertest_1.default)(app);
|
|
2278
|
+
return [4 /*yield*/, server.get("/food?sort=name").expect(200)];
|
|
2279
|
+
case 2:
|
|
2280
|
+
res = _a.sent();
|
|
2281
|
+
(0, bun_test_1.expect)(res.body.data[0].name).toBe("Apple");
|
|
2282
|
+
(0, bun_test_1.expect)(res.body.data[1].name).toBe("Spinach");
|
|
2283
|
+
return [4 /*yield*/, server.get("/food?sort=-name").expect(200)];
|
|
2284
|
+
case 3:
|
|
2285
|
+
// Sort by name descending
|
|
2286
|
+
res = _a.sent();
|
|
2287
|
+
(0, bun_test_1.expect)(res.body.data[0].name).toBe("Spinach");
|
|
2288
|
+
(0, bun_test_1.expect)(res.body.data[1].name).toBe("Apple");
|
|
2289
|
+
return [2 /*return*/];
|
|
2290
|
+
}
|
|
2291
|
+
});
|
|
2292
|
+
}); });
|
|
2293
|
+
(0, bun_test_1.it)("queryFilter error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2294
|
+
var res;
|
|
2295
|
+
return __generator(this, function (_a) {
|
|
2296
|
+
switch (_a.label) {
|
|
2297
|
+
case 0:
|
|
2298
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2299
|
+
allowAnonymous: true,
|
|
2300
|
+
permissions: {
|
|
2301
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2302
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2303
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2304
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2305
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2306
|
+
},
|
|
2307
|
+
queryFilter: function () {
|
|
2308
|
+
throw new Error("queryFilter failed");
|
|
2309
|
+
},
|
|
2310
|
+
}));
|
|
2311
|
+
server = (0, supertest_1.default)(app);
|
|
2312
|
+
return [4 /*yield*/, server.get("/food").expect(400)];
|
|
2313
|
+
case 1:
|
|
2314
|
+
res = _a.sent();
|
|
2315
|
+
(0, bun_test_1.expect)(res.body.title).toContain("Query filter error");
|
|
2316
|
+
return [2 /*return*/];
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
}); });
|
|
2320
|
+
(0, bun_test_1.it)("custom endpoints take priority", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2321
|
+
var res;
|
|
2322
|
+
return __generator(this, function (_a) {
|
|
2323
|
+
switch (_a.label) {
|
|
2324
|
+
case 0:
|
|
2325
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2326
|
+
allowAnonymous: true,
|
|
2327
|
+
endpoints: function (router) {
|
|
2328
|
+
router.get("/custom", function (_req, res) {
|
|
2329
|
+
res.json({ custom: true });
|
|
2330
|
+
});
|
|
2331
|
+
},
|
|
2332
|
+
permissions: {
|
|
2333
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2334
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2335
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2336
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2337
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2338
|
+
},
|
|
2339
|
+
}));
|
|
2340
|
+
server = (0, supertest_1.default)(app);
|
|
2341
|
+
return [4 /*yield*/, server.get("/food/custom").expect(200)];
|
|
2342
|
+
case 1:
|
|
2343
|
+
res = _a.sent();
|
|
2344
|
+
(0, bun_test_1.expect)(res.body.custom).toBe(true);
|
|
2345
|
+
return [2 /*return*/];
|
|
2346
|
+
}
|
|
2347
|
+
});
|
|
2348
|
+
}); });
|
|
2349
|
+
(0, bun_test_1.it)("disallowed query param returns 400", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2350
|
+
var res;
|
|
2351
|
+
return __generator(this, function (_a) {
|
|
2352
|
+
switch (_a.label) {
|
|
2353
|
+
case 0:
|
|
2354
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2355
|
+
allowAnonymous: true,
|
|
2356
|
+
permissions: {
|
|
2357
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2358
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2359
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2360
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2361
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2362
|
+
},
|
|
2363
|
+
queryFields: ["name"],
|
|
2364
|
+
}));
|
|
2365
|
+
server = (0, supertest_1.default)(app);
|
|
2366
|
+
return [4 /*yield*/, server.get("/food?calories=100").expect(400)];
|
|
2367
|
+
case 1:
|
|
2368
|
+
res = _a.sent();
|
|
2369
|
+
(0, bun_test_1.expect)(res.body.title).toContain("calories is not allowed as a query param");
|
|
2370
|
+
return [2 /*return*/];
|
|
2371
|
+
}
|
|
2372
|
+
});
|
|
2373
|
+
}); });
|
|
2374
|
+
(0, bun_test_1.it)("queryFilter returning null returns empty array", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2375
|
+
var res;
|
|
2376
|
+
return __generator(this, function (_a) {
|
|
2377
|
+
switch (_a.label) {
|
|
2378
|
+
case 0:
|
|
2379
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2380
|
+
allowAnonymous: true,
|
|
2381
|
+
permissions: {
|
|
2382
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2383
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2384
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2385
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2386
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2387
|
+
},
|
|
2388
|
+
queryFilter: function () { return null; },
|
|
2389
|
+
}));
|
|
2390
|
+
server = (0, supertest_1.default)(app);
|
|
2391
|
+
return [4 /*yield*/, server.get("/food").expect(200)];
|
|
2392
|
+
case 1:
|
|
2393
|
+
res = _a.sent();
|
|
2394
|
+
(0, bun_test_1.expect)(res.body.data).toEqual([]);
|
|
2395
|
+
return [2 /*return*/];
|
|
2396
|
+
}
|
|
2397
|
+
});
|
|
2398
|
+
}); });
|
|
2399
|
+
(0, bun_test_1.it)("preUpdate returning null throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2400
|
+
var res;
|
|
2401
|
+
return __generator(this, function (_a) {
|
|
2402
|
+
switch (_a.label) {
|
|
2403
|
+
case 0:
|
|
2404
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2405
|
+
allowAnonymous: true,
|
|
2406
|
+
permissions: {
|
|
2407
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2408
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2409
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2410
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2411
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2412
|
+
},
|
|
2413
|
+
preUpdate: function () { return null; },
|
|
2414
|
+
}));
|
|
2415
|
+
server = (0, supertest_1.default)(app);
|
|
2416
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(403)];
|
|
2417
|
+
case 1:
|
|
2418
|
+
res = _a.sent();
|
|
2419
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
2420
|
+
return [2 /*return*/];
|
|
2421
|
+
}
|
|
2422
|
+
});
|
|
2423
|
+
}); });
|
|
2424
|
+
(0, bun_test_1.it)("preDelete returning null throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2425
|
+
var res;
|
|
2426
|
+
return __generator(this, function (_a) {
|
|
2427
|
+
switch (_a.label) {
|
|
2428
|
+
case 0:
|
|
2429
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2430
|
+
allowAnonymous: true,
|
|
2431
|
+
permissions: {
|
|
2432
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2433
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2434
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2435
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2436
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2437
|
+
},
|
|
2438
|
+
preDelete: function () { return null; },
|
|
2439
|
+
}));
|
|
2440
|
+
server = (0, supertest_1.default)(app);
|
|
2441
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2442
|
+
case 1:
|
|
2443
|
+
agent = _a.sent();
|
|
2444
|
+
return [4 /*yield*/, agent.delete("/food/".concat(spinach._id)).expect(403)];
|
|
2445
|
+
case 2:
|
|
2446
|
+
res = _a.sent();
|
|
2447
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Delete not allowed");
|
|
2448
|
+
return [2 /*return*/];
|
|
2449
|
+
}
|
|
2450
|
+
});
|
|
2451
|
+
}); });
|
|
2452
|
+
(0, bun_test_1.it)("preCreate returning null throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2453
|
+
var res;
|
|
2454
|
+
return __generator(this, function (_a) {
|
|
2455
|
+
switch (_a.label) {
|
|
2456
|
+
case 0:
|
|
2457
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2458
|
+
allowAnonymous: true,
|
|
2459
|
+
permissions: {
|
|
2460
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2461
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2462
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2463
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2464
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2465
|
+
},
|
|
2466
|
+
preCreate: function () { return null; },
|
|
2467
|
+
}));
|
|
2468
|
+
server = (0, supertest_1.default)(app);
|
|
2469
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(403)];
|
|
2470
|
+
case 1:
|
|
2471
|
+
res = _a.sent();
|
|
2472
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Create not allowed");
|
|
2473
|
+
return [2 /*return*/];
|
|
2474
|
+
}
|
|
2475
|
+
});
|
|
2476
|
+
}); });
|
|
2477
|
+
(0, bun_test_1.it)("preCreate error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2478
|
+
var res;
|
|
2479
|
+
return __generator(this, function (_a) {
|
|
2480
|
+
switch (_a.label) {
|
|
2481
|
+
case 0:
|
|
2482
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2483
|
+
allowAnonymous: true,
|
|
2484
|
+
permissions: {
|
|
2485
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2486
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2487
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2488
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2489
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2490
|
+
},
|
|
2491
|
+
preCreate: function () {
|
|
2492
|
+
throw new Error("preCreate failed");
|
|
2493
|
+
},
|
|
2494
|
+
}));
|
|
2495
|
+
server = (0, supertest_1.default)(app);
|
|
2496
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(400)];
|
|
2497
|
+
case 1:
|
|
2498
|
+
res = _a.sent();
|
|
2499
|
+
(0, bun_test_1.expect)(res.body.title).toContain("preCreate hook error");
|
|
2500
|
+
return [2 /*return*/];
|
|
2501
|
+
}
|
|
2502
|
+
});
|
|
2503
|
+
}); });
|
|
2504
|
+
(0, bun_test_1.it)("preUpdate error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2505
|
+
var res;
|
|
2506
|
+
return __generator(this, function (_a) {
|
|
2507
|
+
switch (_a.label) {
|
|
2508
|
+
case 0:
|
|
2509
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2510
|
+
allowAnonymous: true,
|
|
2511
|
+
permissions: {
|
|
2512
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2513
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2514
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2515
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2516
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2517
|
+
},
|
|
2518
|
+
preUpdate: function () {
|
|
2519
|
+
throw new Error("preUpdate failed");
|
|
2520
|
+
},
|
|
2521
|
+
}));
|
|
2522
|
+
server = (0, supertest_1.default)(app);
|
|
2523
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ name: "Kale" }).expect(400)];
|
|
2524
|
+
case 1:
|
|
2525
|
+
res = _a.sent();
|
|
2526
|
+
(0, bun_test_1.expect)(res.body.title).toContain("preUpdate hook error");
|
|
2527
|
+
return [2 /*return*/];
|
|
2528
|
+
}
|
|
2529
|
+
});
|
|
2530
|
+
}); });
|
|
2531
|
+
(0, bun_test_1.it)("invalid array operation type returns 400", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2532
|
+
return __generator(this, function (_a) {
|
|
2533
|
+
return [2 /*return*/];
|
|
2534
|
+
});
|
|
2535
|
+
}); });
|
|
2536
|
+
});
|
|
2537
|
+
(0, bun_test_1.describe)("array operation errors", function () {
|
|
2538
|
+
var admin;
|
|
2539
|
+
var apple;
|
|
2540
|
+
var agent;
|
|
2541
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2542
|
+
var _a;
|
|
2543
|
+
return __generator(this, function (_b) {
|
|
2544
|
+
switch (_b.label) {
|
|
2545
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
2546
|
+
case 1:
|
|
2547
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
2548
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
2549
|
+
calories: 100,
|
|
2550
|
+
categories: [
|
|
2551
|
+
{ name: "Fruit", show: true },
|
|
2552
|
+
{ name: "Popular", show: false },
|
|
2553
|
+
],
|
|
2554
|
+
created: new Date("2021-12-03T00:00:30.000Z"),
|
|
2555
|
+
hidden: false,
|
|
2556
|
+
name: "Apple",
|
|
2557
|
+
ownerId: admin._id,
|
|
2558
|
+
tags: ["healthy", "cheap"],
|
|
2559
|
+
})];
|
|
2560
|
+
case 2:
|
|
2561
|
+
apple = _b.sent();
|
|
2562
|
+
app = (0, tests_1.getBaseServer)();
|
|
2563
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
2564
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
2565
|
+
return [2 /*return*/];
|
|
2566
|
+
}
|
|
2567
|
+
});
|
|
2568
|
+
}); });
|
|
2569
|
+
(0, bun_test_1.it)("array operation preUpdate returning undefined throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2570
|
+
var res;
|
|
2571
|
+
return __generator(this, function (_a) {
|
|
2572
|
+
switch (_a.label) {
|
|
2573
|
+
case 0:
|
|
2574
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2575
|
+
allowAnonymous: true,
|
|
2576
|
+
permissions: {
|
|
2577
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2578
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2579
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2580
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2581
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2582
|
+
},
|
|
2583
|
+
preUpdate: function () { return undefined; },
|
|
2584
|
+
}));
|
|
2585
|
+
server = (0, supertest_1.default)(app);
|
|
2586
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2587
|
+
case 1:
|
|
2588
|
+
agent = _a.sent();
|
|
2589
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(403)];
|
|
2590
|
+
case 2:
|
|
2591
|
+
res = _a.sent();
|
|
2592
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
2593
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("A body must be returned from preUpdate");
|
|
2594
|
+
return [2 /*return*/];
|
|
2595
|
+
}
|
|
2596
|
+
});
|
|
2597
|
+
}); });
|
|
2598
|
+
(0, bun_test_1.it)("array operation preUpdate returning null throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2599
|
+
var res;
|
|
2600
|
+
return __generator(this, function (_a) {
|
|
2601
|
+
switch (_a.label) {
|
|
2602
|
+
case 0:
|
|
2603
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2604
|
+
allowAnonymous: true,
|
|
2605
|
+
permissions: {
|
|
2606
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2607
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2608
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2609
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2610
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2611
|
+
},
|
|
2612
|
+
preUpdate: function () { return null; },
|
|
2613
|
+
}));
|
|
2614
|
+
server = (0, supertest_1.default)(app);
|
|
2615
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2616
|
+
case 1:
|
|
2617
|
+
agent = _a.sent();
|
|
2618
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(403)];
|
|
2619
|
+
case 2:
|
|
2620
|
+
res = _a.sent();
|
|
2621
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
2622
|
+
return [2 /*return*/];
|
|
2623
|
+
}
|
|
2624
|
+
});
|
|
2625
|
+
}); });
|
|
2626
|
+
(0, bun_test_1.it)("array operation preUpdate error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2627
|
+
var res;
|
|
2628
|
+
return __generator(this, function (_a) {
|
|
2629
|
+
switch (_a.label) {
|
|
2630
|
+
case 0:
|
|
2631
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2632
|
+
allowAnonymous: true,
|
|
2633
|
+
permissions: {
|
|
2634
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2635
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2636
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2637
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2638
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2639
|
+
},
|
|
2640
|
+
preUpdate: function () {
|
|
2641
|
+
throw new Error("preUpdate array failed");
|
|
2642
|
+
},
|
|
2643
|
+
}));
|
|
2644
|
+
server = (0, supertest_1.default)(app);
|
|
2645
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2646
|
+
case 1:
|
|
2647
|
+
agent = _a.sent();
|
|
2648
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(400)];
|
|
2649
|
+
case 2:
|
|
2650
|
+
res = _a.sent();
|
|
2651
|
+
(0, bun_test_1.expect)(res.body.title).toContain("preUpdate hook error");
|
|
2652
|
+
return [2 /*return*/];
|
|
2653
|
+
}
|
|
2654
|
+
});
|
|
2655
|
+
}); });
|
|
2656
|
+
(0, bun_test_1.it)("array operation postUpdate error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2657
|
+
var res;
|
|
2658
|
+
return __generator(this, function (_a) {
|
|
2659
|
+
switch (_a.label) {
|
|
2660
|
+
case 0:
|
|
2661
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2662
|
+
allowAnonymous: true,
|
|
2663
|
+
permissions: {
|
|
2664
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2665
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2666
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2667
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2668
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2669
|
+
},
|
|
2670
|
+
postUpdate: function () {
|
|
2671
|
+
throw new Error("postUpdate array failed");
|
|
2672
|
+
},
|
|
2673
|
+
}));
|
|
2674
|
+
server = (0, supertest_1.default)(app);
|
|
2675
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2676
|
+
case 1:
|
|
2677
|
+
agent = _a.sent();
|
|
2678
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(400)];
|
|
2679
|
+
case 2:
|
|
2680
|
+
res = _a.sent();
|
|
2681
|
+
(0, bun_test_1.expect)(res.body.title).toContain("PATCH Post Update error");
|
|
2682
|
+
return [2 /*return*/];
|
|
2683
|
+
}
|
|
2684
|
+
});
|
|
2685
|
+
}); });
|
|
2686
|
+
(0, bun_test_1.it)("array operation denied without update permission", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2687
|
+
var res;
|
|
2688
|
+
return __generator(this, function (_a) {
|
|
2689
|
+
switch (_a.label) {
|
|
2690
|
+
case 0:
|
|
2691
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2692
|
+
allowAnonymous: true,
|
|
2693
|
+
permissions: {
|
|
2694
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2695
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2696
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2697
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2698
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2699
|
+
},
|
|
2700
|
+
}));
|
|
2701
|
+
server = (0, supertest_1.default)(app);
|
|
2702
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2703
|
+
case 1:
|
|
2704
|
+
agent = _a.sent();
|
|
2705
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(405)];
|
|
2706
|
+
case 2:
|
|
2707
|
+
res = _a.sent();
|
|
2708
|
+
(0, bun_test_1.expect)(res.body.title).toContain("Access to PATCH");
|
|
2709
|
+
return [2 /*return*/];
|
|
2710
|
+
}
|
|
2711
|
+
});
|
|
2712
|
+
}); });
|
|
2713
|
+
(0, bun_test_1.it)("array operation on non-existent document returns 404", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2714
|
+
var fakeId, res;
|
|
2715
|
+
return __generator(this, function (_a) {
|
|
2716
|
+
switch (_a.label) {
|
|
2717
|
+
case 0:
|
|
2718
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2719
|
+
allowAnonymous: true,
|
|
2720
|
+
permissions: {
|
|
2721
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2722
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2723
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2724
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2725
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2726
|
+
},
|
|
2727
|
+
}));
|
|
2728
|
+
server = (0, supertest_1.default)(app);
|
|
2729
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2730
|
+
case 1:
|
|
2731
|
+
agent = _a.sent();
|
|
2732
|
+
fakeId = "000000000000000000000000";
|
|
2733
|
+
return [4 /*yield*/, agent.post("/food/".concat(fakeId, "/tags")).send({ tags: "organic" }).expect(404)];
|
|
2734
|
+
case 2:
|
|
2735
|
+
res = _a.sent();
|
|
2736
|
+
(0, bun_test_1.expect)(res.body.title).toContain("Could not find document to PATCH");
|
|
2737
|
+
return [2 /*return*/];
|
|
2738
|
+
}
|
|
2739
|
+
});
|
|
2740
|
+
}); });
|
|
2741
|
+
(0, bun_test_1.it)("array operation denied when user cannot update specific doc", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2742
|
+
var res;
|
|
2743
|
+
return __generator(this, function (_a) {
|
|
2744
|
+
switch (_a.label) {
|
|
2745
|
+
case 0:
|
|
2746
|
+
// Create food owned by admin, then try to update as notAdmin
|
|
2747
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2748
|
+
allowAnonymous: true,
|
|
2749
|
+
permissions: {
|
|
2750
|
+
create: [permissions_1.Permissions.IsAuthenticated],
|
|
2751
|
+
delete: [permissions_1.Permissions.IsAuthenticated],
|
|
2752
|
+
list: [permissions_1.Permissions.IsAuthenticated],
|
|
2753
|
+
read: [permissions_1.Permissions.IsAuthenticated],
|
|
2754
|
+
update: [permissions_1.Permissions.IsOwner],
|
|
2755
|
+
},
|
|
2756
|
+
}));
|
|
2757
|
+
server = (0, supertest_1.default)(app);
|
|
2758
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2759
|
+
case 1:
|
|
2760
|
+
// Login as notAdmin and try to update admin's food (apple)
|
|
2761
|
+
agent = _a.sent();
|
|
2762
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(403)];
|
|
2763
|
+
case 2:
|
|
2764
|
+
res = _a.sent();
|
|
2765
|
+
(0, bun_test_1.expect)(res.body.title).toContain("Patch not allowed");
|
|
2766
|
+
return [2 /*return*/];
|
|
2767
|
+
}
|
|
2768
|
+
});
|
|
2769
|
+
}); });
|
|
2770
|
+
(0, bun_test_1.it)("array operation transform error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2771
|
+
var res;
|
|
2772
|
+
return __generator(this, function (_a) {
|
|
2773
|
+
switch (_a.label) {
|
|
2774
|
+
case 0:
|
|
2775
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2776
|
+
allowAnonymous: true,
|
|
2777
|
+
permissions: {
|
|
2778
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
2779
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
2780
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
2781
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
2782
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
2783
|
+
},
|
|
2784
|
+
transformer: (0, transformers_1.AdminOwnerTransformer)({
|
|
2785
|
+
adminWriteFields: ["name"],
|
|
2786
|
+
}),
|
|
2787
|
+
}));
|
|
2788
|
+
server = (0, supertest_1.default)(app);
|
|
2789
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
2790
|
+
case 1:
|
|
2791
|
+
agent = _a.sent();
|
|
2792
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(403)];
|
|
2793
|
+
case 2:
|
|
2794
|
+
res = _a.sent();
|
|
2795
|
+
(0, bun_test_1.expect)(res.body.title).toContain("cannot write fields");
|
|
2796
|
+
return [2 /*return*/];
|
|
2797
|
+
}
|
|
2798
|
+
});
|
|
2799
|
+
}); });
|
|
2800
|
+
});
|
|
2801
|
+
(0, bun_test_1.describe)("transformer errors", function () {
|
|
2802
|
+
var admin;
|
|
2803
|
+
var spinach;
|
|
2804
|
+
var agent;
|
|
2805
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2806
|
+
var _a;
|
|
2807
|
+
return __generator(this, function (_b) {
|
|
2808
|
+
switch (_b.label) {
|
|
2809
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
2810
|
+
case 1:
|
|
2811
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
2812
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
2813
|
+
calories: 1,
|
|
2814
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
2815
|
+
hidden: false,
|
|
2816
|
+
name: "Spinach",
|
|
2817
|
+
ownerId: admin._id,
|
|
2818
|
+
source: {
|
|
2819
|
+
name: "Brand",
|
|
2820
|
+
},
|
|
2821
|
+
})];
|
|
2822
|
+
case 2:
|
|
2823
|
+
spinach = _b.sent();
|
|
2824
|
+
app = (0, tests_1.getBaseServer)();
|
|
2825
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
2826
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
2827
|
+
return [2 /*return*/];
|
|
2828
|
+
}
|
|
2829
|
+
});
|
|
2830
|
+
}); });
|
|
2831
|
+
(0, bun_test_1.it)("transform error in create is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2832
|
+
var res;
|
|
2833
|
+
return __generator(this, function (_a) {
|
|
2834
|
+
switch (_a.label) {
|
|
2835
|
+
case 0:
|
|
2836
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2837
|
+
allowAnonymous: true,
|
|
2838
|
+
permissions: {
|
|
2839
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2840
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2841
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2842
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2843
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2844
|
+
},
|
|
2845
|
+
transformer: (0, transformers_1.AdminOwnerTransformer)({
|
|
2846
|
+
// Only allow 'name' to be written, so 'calories' will throw
|
|
2847
|
+
anonWriteFields: ["name"],
|
|
2848
|
+
}),
|
|
2849
|
+
}));
|
|
2850
|
+
server = (0, supertest_1.default)(app);
|
|
2851
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(400)];
|
|
2852
|
+
case 1:
|
|
2853
|
+
res = _a.sent();
|
|
2854
|
+
(0, bun_test_1.expect)(res.body.title).toContain("cannot write fields");
|
|
2855
|
+
return [2 /*return*/];
|
|
2856
|
+
}
|
|
2857
|
+
});
|
|
2858
|
+
}); });
|
|
2859
|
+
(0, bun_test_1.it)("transform error in patch is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2860
|
+
var res;
|
|
2861
|
+
return __generator(this, function (_a) {
|
|
2862
|
+
switch (_a.label) {
|
|
2863
|
+
case 0:
|
|
2864
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2865
|
+
allowAnonymous: true,
|
|
2866
|
+
permissions: {
|
|
2867
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2868
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2869
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2870
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2871
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2872
|
+
},
|
|
2873
|
+
transformer: (0, transformers_1.AdminOwnerTransformer)({
|
|
2874
|
+
// Only allow 'name' to be written, so 'calories' will throw
|
|
2875
|
+
anonWriteFields: ["name"],
|
|
2876
|
+
}),
|
|
2877
|
+
}));
|
|
2878
|
+
server = (0, supertest_1.default)(app);
|
|
2879
|
+
return [4 /*yield*/, server.patch("/food/".concat(spinach._id)).send({ calories: 100 }).expect(403)];
|
|
2880
|
+
case 1:
|
|
2881
|
+
res = _a.sent();
|
|
2882
|
+
(0, bun_test_1.expect)(res.body.title).toContain("cannot write fields");
|
|
2883
|
+
return [2 /*return*/];
|
|
2884
|
+
}
|
|
2885
|
+
});
|
|
2886
|
+
}); });
|
|
2887
|
+
(0, bun_test_1.it)("model.create validation error is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2888
|
+
var RequiredModel, res;
|
|
2889
|
+
return __generator(this, function (_a) {
|
|
2890
|
+
switch (_a.label) {
|
|
2891
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./tests")); })];
|
|
2892
|
+
case 1:
|
|
2893
|
+
RequiredModel = (_a.sent()).RequiredModel;
|
|
2894
|
+
app.use("/required", (0, api_1.modelRouter)(RequiredModel, {
|
|
2895
|
+
allowAnonymous: true,
|
|
2896
|
+
permissions: {
|
|
2897
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2898
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2899
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2900
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2901
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2902
|
+
},
|
|
2903
|
+
}));
|
|
2904
|
+
server = (0, supertest_1.default)(app);
|
|
2905
|
+
return [4 /*yield*/, server.post("/required").send({ about: "test" }).expect(400)];
|
|
2906
|
+
case 2:
|
|
2907
|
+
res = _a.sent();
|
|
2908
|
+
(0, bun_test_1.expect)(res.body.title).toContain("Required");
|
|
2909
|
+
return [2 /*return*/];
|
|
2910
|
+
}
|
|
2911
|
+
});
|
|
2912
|
+
}); });
|
|
2913
|
+
(0, bun_test_1.it)("preDelete hook throwing APIError is re-thrown", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2914
|
+
var res;
|
|
2915
|
+
return __generator(this, function (_a) {
|
|
2916
|
+
switch (_a.label) {
|
|
2917
|
+
case 0:
|
|
2918
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2919
|
+
allowAnonymous: true,
|
|
2920
|
+
permissions: {
|
|
2921
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2922
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2923
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2924
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2925
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2926
|
+
},
|
|
2927
|
+
preDelete: function () {
|
|
2928
|
+
throw new errors_1.APIError({
|
|
2929
|
+
disableExternalErrorTracking: true,
|
|
2930
|
+
status: 400,
|
|
2931
|
+
title: "Custom preDelete APIError",
|
|
2932
|
+
});
|
|
2933
|
+
},
|
|
2934
|
+
}));
|
|
2935
|
+
server = (0, supertest_1.default)(app);
|
|
2936
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
2937
|
+
case 1:
|
|
2938
|
+
agent = _a.sent();
|
|
2939
|
+
return [4 /*yield*/, agent.delete("/food/".concat(spinach._id)).expect(400)];
|
|
2940
|
+
case 2:
|
|
2941
|
+
res = _a.sent();
|
|
2942
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Custom preDelete APIError");
|
|
2943
|
+
(0, bun_test_1.expect)(res.body.disableExternalErrorTracking).toBe(true);
|
|
2944
|
+
return [2 /*return*/];
|
|
2945
|
+
}
|
|
2946
|
+
});
|
|
2947
|
+
}); });
|
|
2948
|
+
});
|
|
2949
|
+
(0, bun_test_1.describe)("special query params", function () {
|
|
2950
|
+
var admin;
|
|
2951
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2952
|
+
var _a;
|
|
2953
|
+
return __generator(this, function (_b) {
|
|
2954
|
+
switch (_b.label) {
|
|
2955
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
2956
|
+
case 1:
|
|
2957
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
2958
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
2959
|
+
calories: 1,
|
|
2960
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
2961
|
+
hidden: false,
|
|
2962
|
+
name: "Spinach",
|
|
2963
|
+
ownerId: admin._id,
|
|
2964
|
+
})];
|
|
2965
|
+
case 2:
|
|
2966
|
+
_b.sent();
|
|
2967
|
+
app = (0, tests_1.getBaseServer)();
|
|
2968
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
2969
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
2970
|
+
return [2 /*return*/];
|
|
2971
|
+
}
|
|
2972
|
+
});
|
|
2973
|
+
}); });
|
|
2974
|
+
(0, bun_test_1.it)("period query param is stripped from query", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2975
|
+
var res;
|
|
2976
|
+
return __generator(this, function (_a) {
|
|
2977
|
+
switch (_a.label) {
|
|
2978
|
+
case 0:
|
|
2979
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
2980
|
+
allowAnonymous: true,
|
|
2981
|
+
permissions: {
|
|
2982
|
+
create: [permissions_1.Permissions.IsAny],
|
|
2983
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
2984
|
+
list: [permissions_1.Permissions.IsAny],
|
|
2985
|
+
read: [permissions_1.Permissions.IsAny],
|
|
2986
|
+
update: [permissions_1.Permissions.IsAny],
|
|
2987
|
+
},
|
|
2988
|
+
queryFields: ["name", "period"],
|
|
2989
|
+
queryFilter: function (_user, query) {
|
|
2990
|
+
// Simulate a queryFilter that accepts and processes period
|
|
2991
|
+
if (query === null || query === void 0 ? void 0 : query.period) {
|
|
2992
|
+
// Period is processed but shouldn't be passed to mongo
|
|
2993
|
+
return query;
|
|
2994
|
+
}
|
|
2995
|
+
return query !== null && query !== void 0 ? query : {};
|
|
2996
|
+
},
|
|
2997
|
+
}));
|
|
2998
|
+
server = (0, supertest_1.default)(app);
|
|
2999
|
+
return [4 /*yield*/, server.get("/food?period=weekly").expect(200)];
|
|
3000
|
+
case 1:
|
|
3001
|
+
res = _a.sent();
|
|
3002
|
+
(0, bun_test_1.expect)(res.body.data).toBeDefined();
|
|
3003
|
+
return [2 /*return*/];
|
|
3004
|
+
}
|
|
3005
|
+
});
|
|
3006
|
+
}); });
|
|
3007
|
+
(0, bun_test_1.it)("query with false value", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3008
|
+
var res;
|
|
3009
|
+
return __generator(this, function (_a) {
|
|
3010
|
+
switch (_a.label) {
|
|
3011
|
+
case 0:
|
|
3012
|
+
// Create a food that is hidden
|
|
3013
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
3014
|
+
calories: 50,
|
|
3015
|
+
created: new Date("2021-12-04T00:00:20.000Z"),
|
|
3016
|
+
hidden: true,
|
|
3017
|
+
name: "HiddenFood",
|
|
3018
|
+
ownerId: admin._id,
|
|
3019
|
+
})];
|
|
3020
|
+
case 1:
|
|
3021
|
+
// Create a food that is hidden
|
|
3022
|
+
_a.sent();
|
|
3023
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3024
|
+
allowAnonymous: true,
|
|
3025
|
+
permissions: {
|
|
3026
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3027
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3028
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3029
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3030
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3031
|
+
},
|
|
3032
|
+
queryFields: ["name", "hidden"],
|
|
3033
|
+
}));
|
|
3034
|
+
server = (0, supertest_1.default)(app);
|
|
3035
|
+
return [4 /*yield*/, server.get("/food?hidden=false").expect(200)];
|
|
3036
|
+
case 2:
|
|
3037
|
+
res = _a.sent();
|
|
3038
|
+
(0, bun_test_1.expect)(res.body.data.every(function (f) { return f.hidden === false; })).toBe(true);
|
|
3039
|
+
return [2 /*return*/];
|
|
3040
|
+
}
|
|
3041
|
+
});
|
|
3042
|
+
}); });
|
|
3043
|
+
(0, bun_test_1.it)("$search query triggers special handling code path", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3044
|
+
var res;
|
|
3045
|
+
return __generator(this, function (_a) {
|
|
3046
|
+
switch (_a.label) {
|
|
3047
|
+
case 0:
|
|
3048
|
+
// The $search code path just accesses the collection but doesn't do anything with it
|
|
3049
|
+
// This test verifies the code path is exercised
|
|
3050
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3051
|
+
allowAnonymous: true,
|
|
3052
|
+
permissions: {
|
|
3053
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3054
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3055
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3056
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3057
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3058
|
+
},
|
|
3059
|
+
// Need to include $search in queryFields for it to pass validation
|
|
3060
|
+
queryFields: ["name", "$search"],
|
|
3061
|
+
}));
|
|
3062
|
+
server = (0, supertest_1.default)(app);
|
|
3063
|
+
return [4 /*yield*/, server.get("/food?$search=test")];
|
|
3064
|
+
case 1:
|
|
3065
|
+
res = _a.sent();
|
|
3066
|
+
// May return 500 because $search is passed to Mongo which doesn't support it without Atlas
|
|
3067
|
+
// The important thing is we've exercised the code path
|
|
3068
|
+
(0, bun_test_1.expect)(res.status === 200 || res.status === 500).toBe(true);
|
|
3069
|
+
return [2 /*return*/];
|
|
3070
|
+
}
|
|
3071
|
+
});
|
|
3072
|
+
}); });
|
|
3073
|
+
(0, bun_test_1.it)("$autocomplete query triggers special handling code path", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3074
|
+
var res;
|
|
3075
|
+
return __generator(this, function (_a) {
|
|
3076
|
+
switch (_a.label) {
|
|
3077
|
+
case 0:
|
|
3078
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3079
|
+
allowAnonymous: true,
|
|
3080
|
+
permissions: {
|
|
3081
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3082
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3083
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3084
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3085
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3086
|
+
},
|
|
3087
|
+
queryFields: ["name", "$autocomplete"],
|
|
3088
|
+
}));
|
|
3089
|
+
server = (0, supertest_1.default)(app);
|
|
3090
|
+
return [4 /*yield*/, server.get("/food?$autocomplete=test")];
|
|
3091
|
+
case 1:
|
|
3092
|
+
res = _a.sent();
|
|
3093
|
+
(0, bun_test_1.expect)(res.status === 200 || res.status === 500).toBe(true);
|
|
3094
|
+
return [2 /*return*/];
|
|
3095
|
+
}
|
|
3096
|
+
});
|
|
3097
|
+
}); });
|
|
3098
|
+
});
|
|
3099
|
+
(0, bun_test_1.describe)("addPopulateToQuery", function () {
|
|
3100
|
+
(0, bun_test_1.it)("returns query unchanged with no populate paths", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3101
|
+
var query, result;
|
|
3102
|
+
return __generator(this, function (_a) {
|
|
3103
|
+
switch (_a.label) {
|
|
3104
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3105
|
+
case 1:
|
|
3106
|
+
_a.sent();
|
|
3107
|
+
query = tests_1.FoodModel.find({});
|
|
3108
|
+
result = (0, api_1.addPopulateToQuery)(query, undefined);
|
|
3109
|
+
(0, bun_test_1.expect)(result).toBe(query);
|
|
3110
|
+
return [2 /*return*/];
|
|
3111
|
+
}
|
|
3112
|
+
});
|
|
3113
|
+
}); });
|
|
3114
|
+
(0, bun_test_1.it)("returns query unchanged with empty populate paths", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3115
|
+
var query, result;
|
|
3116
|
+
return __generator(this, function (_a) {
|
|
3117
|
+
switch (_a.label) {
|
|
3118
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3119
|
+
case 1:
|
|
3120
|
+
_a.sent();
|
|
3121
|
+
query = tests_1.FoodModel.find({});
|
|
3122
|
+
result = (0, api_1.addPopulateToQuery)(query, []);
|
|
3123
|
+
(0, bun_test_1.expect)(result).toBe(query);
|
|
3124
|
+
return [2 /*return*/];
|
|
3125
|
+
}
|
|
3126
|
+
});
|
|
3127
|
+
}); });
|
|
3128
|
+
(0, bun_test_1.it)("applies multiple populate paths", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3129
|
+
var query, result;
|
|
3130
|
+
return __generator(this, function (_a) {
|
|
3131
|
+
switch (_a.label) {
|
|
3132
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3133
|
+
case 1:
|
|
3134
|
+
_a.sent();
|
|
3135
|
+
query = tests_1.FoodModel.find({});
|
|
3136
|
+
result = (0, api_1.addPopulateToQuery)(query, [
|
|
3137
|
+
{ fields: ["email"], path: "ownerId" },
|
|
3138
|
+
{ fields: ["name"], path: "eatenBy" },
|
|
3139
|
+
]);
|
|
3140
|
+
// The result should be a query with populate applied
|
|
3141
|
+
(0, bun_test_1.expect)(result).toBeDefined();
|
|
3142
|
+
return [2 /*return*/];
|
|
3143
|
+
}
|
|
3144
|
+
});
|
|
3145
|
+
}); });
|
|
3146
|
+
});
|
|
3147
|
+
(0, bun_test_1.describe)("soft delete with isDeleted plugin", function () {
|
|
3148
|
+
var admin;
|
|
3149
|
+
var agent;
|
|
3150
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3151
|
+
var _a;
|
|
3152
|
+
return __generator(this, function (_b) {
|
|
3153
|
+
switch (_b.label) {
|
|
3154
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3155
|
+
case 1:
|
|
3156
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
3157
|
+
app = (0, tests_1.getBaseServer)();
|
|
3158
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
3159
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
3160
|
+
return [2 /*return*/];
|
|
3161
|
+
}
|
|
3162
|
+
});
|
|
3163
|
+
}); });
|
|
3164
|
+
(0, bun_test_1.it)("soft deletes user with deleted field", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3165
|
+
var res, deletedUser;
|
|
3166
|
+
return __generator(this, function (_a) {
|
|
3167
|
+
switch (_a.label) {
|
|
3168
|
+
case 0:
|
|
3169
|
+
// UserModel has the isDisabledPlugin which adds a 'disabled' field,
|
|
3170
|
+
// but we need to test the 'deleted' field check.
|
|
3171
|
+
// Let's use a model that has the deleted field.
|
|
3172
|
+
app.use("/users", (0, api_1.modelRouter)(tests_1.UserModel, {
|
|
3173
|
+
allowAnonymous: true,
|
|
3174
|
+
permissions: {
|
|
3175
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3176
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3177
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3178
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3179
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3180
|
+
},
|
|
3181
|
+
}));
|
|
3182
|
+
server = (0, supertest_1.default)(app);
|
|
3183
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
3184
|
+
case 1:
|
|
3185
|
+
agent = _a.sent();
|
|
3186
|
+
return [4 /*yield*/, agent.delete("/users/".concat(admin._id)).expect(204)];
|
|
3187
|
+
case 2:
|
|
3188
|
+
res = _a.sent();
|
|
3189
|
+
(0, bun_test_1.expect)(res.body).toEqual({});
|
|
3190
|
+
return [4 /*yield*/, tests_1.UserModel.findById(admin._id)];
|
|
3191
|
+
case 3:
|
|
3192
|
+
deletedUser = _a.sent();
|
|
3193
|
+
(0, bun_test_1.expect)(deletedUser).toBeNull();
|
|
3194
|
+
return [2 /*return*/];
|
|
3195
|
+
}
|
|
3196
|
+
});
|
|
3197
|
+
}); });
|
|
3198
|
+
});
|
|
3199
|
+
(0, bun_test_1.describe)("populate in create", function () {
|
|
3200
|
+
var admin;
|
|
3201
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3202
|
+
var _a;
|
|
3203
|
+
return __generator(this, function (_b) {
|
|
3204
|
+
switch (_b.label) {
|
|
3205
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3206
|
+
case 1:
|
|
3207
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
3208
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
3209
|
+
calories: 1,
|
|
3210
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
3211
|
+
hidden: false,
|
|
3212
|
+
name: "Spinach",
|
|
3213
|
+
ownerId: admin._id,
|
|
3214
|
+
})];
|
|
3215
|
+
case 2:
|
|
3216
|
+
_b.sent();
|
|
3217
|
+
app = (0, tests_1.getBaseServer)();
|
|
3218
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
3219
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
3220
|
+
return [2 /*return*/];
|
|
3221
|
+
}
|
|
3222
|
+
});
|
|
3223
|
+
}); });
|
|
3224
|
+
(0, bun_test_1.it)("handles populate with valid path in create", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3225
|
+
var res;
|
|
3226
|
+
return __generator(this, function (_a) {
|
|
3227
|
+
switch (_a.label) {
|
|
3228
|
+
case 0:
|
|
3229
|
+
// Test that valid populate works in create flow
|
|
3230
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3231
|
+
allowAnonymous: true,
|
|
3232
|
+
permissions: {
|
|
3233
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3234
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3235
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3236
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3237
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3238
|
+
},
|
|
3239
|
+
populatePaths: [{ fields: ["email"], path: "ownerId" }],
|
|
3240
|
+
}));
|
|
3241
|
+
server = (0, supertest_1.default)(app);
|
|
3242
|
+
return [4 /*yield*/, server
|
|
3243
|
+
.post("/food")
|
|
3244
|
+
.send({ calories: 15, name: "Broccoli", ownerId: admin._id })
|
|
3245
|
+
.expect(201)];
|
|
3246
|
+
case 1:
|
|
3247
|
+
res = _a.sent();
|
|
3248
|
+
(0, bun_test_1.expect)(res.body.data.name).toBe("Broccoli");
|
|
3249
|
+
// Verify populate worked - ownerId should be an object with email
|
|
3250
|
+
(0, bun_test_1.expect)(res.body.data.ownerId.email).toBe(admin.email);
|
|
3251
|
+
return [2 /*return*/];
|
|
3252
|
+
}
|
|
3253
|
+
});
|
|
3254
|
+
}); });
|
|
3255
|
+
});
|
|
3256
|
+
(0, bun_test_1.describe)("save error handling", function () {
|
|
3257
|
+
var admin;
|
|
3258
|
+
var spinach;
|
|
3259
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3260
|
+
var _a;
|
|
3261
|
+
return __generator(this, function (_b) {
|
|
3262
|
+
switch (_b.label) {
|
|
3263
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3264
|
+
case 1:
|
|
3265
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
3266
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
3267
|
+
calories: 1,
|
|
3268
|
+
created: new Date("2021-12-03T00:00:20.000Z"),
|
|
3269
|
+
hidden: false,
|
|
3270
|
+
name: "Spinach",
|
|
3271
|
+
ownerId: admin._id,
|
|
3272
|
+
source: {
|
|
3273
|
+
name: "Brand",
|
|
3274
|
+
},
|
|
3275
|
+
})];
|
|
3276
|
+
case 2:
|
|
3277
|
+
spinach = _b.sent();
|
|
3278
|
+
app = (0, tests_1.getBaseServer)();
|
|
3279
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
3280
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
3281
|
+
return [2 /*return*/];
|
|
3282
|
+
}
|
|
3283
|
+
});
|
|
3284
|
+
}); });
|
|
3285
|
+
(0, bun_test_1.it)("handles patch save error with validation failure", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3286
|
+
var res;
|
|
3287
|
+
return __generator(this, function (_a) {
|
|
3288
|
+
switch (_a.label) {
|
|
3289
|
+
case 0:
|
|
3290
|
+
// The FoodModel has strict: "throw" which will cause validation errors for unknown fields
|
|
3291
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3292
|
+
allowAnonymous: true,
|
|
3293
|
+
permissions: {
|
|
3294
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3295
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3296
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3297
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3298
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3299
|
+
},
|
|
3300
|
+
}));
|
|
3301
|
+
server = (0, supertest_1.default)(app);
|
|
3302
|
+
return [4 /*yield*/, server
|
|
3303
|
+
.patch("/food/".concat(spinach._id))
|
|
3304
|
+
.send({ invalidField: "value" })
|
|
3305
|
+
.expect(400)];
|
|
3306
|
+
case 1:
|
|
3307
|
+
res = _a.sent();
|
|
3308
|
+
(0, bun_test_1.expect)(res.body.title).toContain("preUpdate hook save error");
|
|
3309
|
+
return [2 /*return*/];
|
|
3310
|
+
}
|
|
3311
|
+
});
|
|
3312
|
+
}); });
|
|
3313
|
+
});
|
|
3314
|
+
(0, bun_test_1.describe)("body undefined after transform without preCreate", function () {
|
|
3315
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3316
|
+
return __generator(this, function (_a) {
|
|
3317
|
+
switch (_a.label) {
|
|
3318
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3319
|
+
case 1:
|
|
3320
|
+
_a.sent();
|
|
3321
|
+
app = (0, tests_1.getBaseServer)();
|
|
3322
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
3323
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
3324
|
+
return [2 /*return*/];
|
|
3325
|
+
}
|
|
3326
|
+
});
|
|
3327
|
+
}); });
|
|
3328
|
+
(0, bun_test_1.it)("handles undefined body after transform when no preCreate", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3329
|
+
var res;
|
|
3330
|
+
return __generator(this, function (_a) {
|
|
3331
|
+
switch (_a.label) {
|
|
3332
|
+
case 0:
|
|
3333
|
+
// Create a transformer that returns undefined
|
|
3334
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3335
|
+
allowAnonymous: true,
|
|
3336
|
+
permissions: {
|
|
3337
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3338
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3339
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3340
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3341
|
+
update: [permissions_1.Permissions.IsAny],
|
|
3342
|
+
},
|
|
3343
|
+
transformer: {
|
|
3344
|
+
transform: function () { return undefined; },
|
|
3345
|
+
},
|
|
3346
|
+
}));
|
|
3347
|
+
server = (0, supertest_1.default)(app);
|
|
3348
|
+
return [4 /*yield*/, server.post("/food").send({ calories: 15, name: "Broccoli" }).expect(400)];
|
|
3349
|
+
case 1:
|
|
3350
|
+
res = _a.sent();
|
|
3351
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Invalid request body");
|
|
3352
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("Body is undefined");
|
|
3353
|
+
return [2 /*return*/];
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
}); });
|
|
3357
|
+
});
|
|
3358
|
+
(0, bun_test_1.describe)("soft delete with deleted field", function () {
|
|
3359
|
+
var _admin;
|
|
1886
3360
|
var agent;
|
|
1887
3361
|
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1888
|
-
var _a
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
switch (_c.label) {
|
|
3362
|
+
var _a;
|
|
3363
|
+
return __generator(this, function (_b) {
|
|
3364
|
+
switch (_b.label) {
|
|
1892
3365
|
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
1893
3366
|
case 1:
|
|
1894
|
-
|
|
1895
|
-
return [4 /*yield*/, Promise.all([
|
|
1896
|
-
tests_1.StaffUserModel.create({
|
|
1897
|
-
department: "Accounting",
|
|
1898
|
-
email: "staff@example.com",
|
|
1899
|
-
}),
|
|
1900
|
-
tests_1.SuperUserModel.create({
|
|
1901
|
-
email: "superuser@example.com",
|
|
1902
|
-
superTitle: "Super Man",
|
|
1903
|
-
}),
|
|
1904
|
-
])];
|
|
1905
|
-
case 2:
|
|
1906
|
-
_a = __read.apply(void 0, [_c.sent(), 2]), staffUserId = _a[0], superUserId = _a[1];
|
|
1907
|
-
return [4 /*yield*/, tests_1.UserModel.findById(staffUserId)];
|
|
1908
|
-
case 3:
|
|
1909
|
-
staffUser = (_c.sent());
|
|
1910
|
-
return [4 /*yield*/, tests_1.UserModel.findById(superUserId)];
|
|
1911
|
-
case 4:
|
|
1912
|
-
superUser = (_c.sent());
|
|
3367
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), _admin = _a[0];
|
|
1913
3368
|
app = (0, tests_1.getBaseServer)();
|
|
1914
3369
|
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
1915
3370
|
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
1916
|
-
|
|
3371
|
+
return [2 /*return*/];
|
|
3372
|
+
}
|
|
3373
|
+
});
|
|
3374
|
+
}); });
|
|
3375
|
+
(0, bun_test_1.it)("soft deletes document with deleted field using isDeletedPlugin", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3376
|
+
var mongoose, softDeleteSchema, SoftDeleteModel, testDoc, softDeleted;
|
|
3377
|
+
return __generator(this, function (_a) {
|
|
3378
|
+
switch (_a.label) {
|
|
3379
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("mongoose")); })];
|
|
3380
|
+
case 1:
|
|
3381
|
+
mongoose = _a.sent();
|
|
3382
|
+
softDeleteSchema = new mongoose.Schema({
|
|
3383
|
+
deleted: { default: false, type: Boolean },
|
|
3384
|
+
name: String,
|
|
3385
|
+
});
|
|
3386
|
+
try {
|
|
3387
|
+
SoftDeleteModel = mongoose.model("SoftDeleteTest");
|
|
3388
|
+
}
|
|
3389
|
+
catch (_b) {
|
|
3390
|
+
SoftDeleteModel = mongoose.model("SoftDeleteTest", softDeleteSchema);
|
|
3391
|
+
}
|
|
3392
|
+
// Clean up any existing documents
|
|
3393
|
+
return [4 /*yield*/, SoftDeleteModel.deleteMany({})];
|
|
3394
|
+
case 2:
|
|
3395
|
+
// Clean up any existing documents
|
|
3396
|
+
_a.sent();
|
|
3397
|
+
return [4 /*yield*/, SoftDeleteModel.create({ name: "TestItem" })];
|
|
3398
|
+
case 3:
|
|
3399
|
+
testDoc = _a.sent();
|
|
3400
|
+
app.use("/softdelete", (0, api_1.modelRouter)(SoftDeleteModel, {
|
|
1917
3401
|
allowAnonymous: true,
|
|
1918
|
-
discriminatorKey: "__t",
|
|
1919
3402
|
permissions: {
|
|
1920
|
-
create: [permissions_1.Permissions.
|
|
1921
|
-
delete: [permissions_1.Permissions.
|
|
1922
|
-
list: [permissions_1.Permissions.
|
|
1923
|
-
read: [permissions_1.Permissions.
|
|
1924
|
-
update: [permissions_1.Permissions.
|
|
3403
|
+
create: [permissions_1.Permissions.IsAny],
|
|
3404
|
+
delete: [permissions_1.Permissions.IsAny],
|
|
3405
|
+
list: [permissions_1.Permissions.IsAny],
|
|
3406
|
+
read: [permissions_1.Permissions.IsAny],
|
|
3407
|
+
update: [permissions_1.Permissions.IsAny],
|
|
1925
3408
|
},
|
|
1926
3409
|
}));
|
|
1927
3410
|
server = (0, supertest_1.default)(app);
|
|
1928
3411
|
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
|
|
3412
|
+
case 4:
|
|
3413
|
+
agent = _a.sent();
|
|
3414
|
+
// Delete should soft delete (set deleted: true) instead of hard delete
|
|
3415
|
+
return [4 /*yield*/, agent.delete("/softdelete/".concat(testDoc._id)).expect(204)];
|
|
1929
3416
|
case 5:
|
|
1930
|
-
|
|
3417
|
+
// Delete should soft delete (set deleted: true) instead of hard delete
|
|
3418
|
+
_a.sent();
|
|
3419
|
+
return [4 /*yield*/, SoftDeleteModel.findById(testDoc._id)];
|
|
3420
|
+
case 6:
|
|
3421
|
+
softDeleted = _a.sent();
|
|
3422
|
+
(0, bun_test_1.expect)(softDeleted).not.toBeNull();
|
|
3423
|
+
(0, bun_test_1.expect)(softDeleted === null || softDeleted === void 0 ? void 0 : softDeleted.deleted).toBe(true);
|
|
3424
|
+
// Clean up
|
|
3425
|
+
return [4 /*yield*/, SoftDeleteModel.deleteMany({})];
|
|
3426
|
+
case 7:
|
|
3427
|
+
// Clean up
|
|
3428
|
+
_a.sent();
|
|
3429
|
+
return [2 /*return*/];
|
|
3430
|
+
}
|
|
3431
|
+
});
|
|
3432
|
+
}); });
|
|
3433
|
+
});
|
|
3434
|
+
(0, bun_test_1.describe)("array operation with undefined preUpdate return", function () {
|
|
3435
|
+
var admin;
|
|
3436
|
+
var apple;
|
|
3437
|
+
var agent;
|
|
3438
|
+
(0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3439
|
+
var _a;
|
|
3440
|
+
return __generator(this, function (_b) {
|
|
3441
|
+
switch (_b.label) {
|
|
3442
|
+
case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
|
|
3443
|
+
case 1:
|
|
3444
|
+
_a = __read.apply(void 0, [_b.sent(), 1]), admin = _a[0];
|
|
3445
|
+
return [4 /*yield*/, tests_1.FoodModel.create({
|
|
3446
|
+
calories: 100,
|
|
3447
|
+
categories: [
|
|
3448
|
+
{ name: "Fruit", show: true },
|
|
3449
|
+
{ name: "Popular", show: false },
|
|
3450
|
+
],
|
|
3451
|
+
created: new Date("2021-12-03T00:00:30.000Z"),
|
|
3452
|
+
hidden: false,
|
|
3453
|
+
name: "Apple",
|
|
3454
|
+
ownerId: admin._id,
|
|
3455
|
+
tags: ["healthy", "cheap"],
|
|
3456
|
+
})];
|
|
3457
|
+
case 2:
|
|
3458
|
+
apple = _b.sent();
|
|
3459
|
+
app = (0, tests_1.getBaseServer)();
|
|
3460
|
+
(0, auth_1.setupAuth)(app, tests_1.UserModel);
|
|
3461
|
+
(0, auth_1.addAuthRoutes)(app, tests_1.UserModel);
|
|
1931
3462
|
return [2 /*return*/];
|
|
1932
3463
|
}
|
|
1933
3464
|
});
|
|
1934
3465
|
}); });
|
|
1935
|
-
(0, bun_test_1.it)("
|
|
1936
|
-
var res
|
|
3466
|
+
(0, bun_test_1.it)("array operation preUpdate returning undefined for array POST throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3467
|
+
var res;
|
|
1937
3468
|
return __generator(this, function (_a) {
|
|
1938
3469
|
switch (_a.label) {
|
|
1939
|
-
case 0:
|
|
3470
|
+
case 0:
|
|
3471
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3472
|
+
allowAnonymous: true,
|
|
3473
|
+
permissions: {
|
|
3474
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
3475
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
3476
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
3477
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
3478
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
3479
|
+
},
|
|
3480
|
+
preUpdate: function () { return undefined; },
|
|
3481
|
+
}));
|
|
3482
|
+
server = (0, supertest_1.default)(app);
|
|
3483
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
1940
3484
|
case 1:
|
|
3485
|
+
agent = _a.sent();
|
|
3486
|
+
return [4 /*yield*/, agent.post("/food/".concat(apple._id, "/tags")).send({ tags: "organic" }).expect(403)];
|
|
3487
|
+
case 2:
|
|
1941
3488
|
res = _a.sent();
|
|
1942
|
-
(0, bun_test_1.expect)(res.body.
|
|
1943
|
-
|
|
1944
|
-
(0, bun_test_1.expect)(data[0].email).toBe("admin+other@example.com");
|
|
1945
|
-
(0, bun_test_1.expect)(data[0].department).toBeUndefined();
|
|
1946
|
-
(0, bun_test_1.expect)(data[0].supertitle).toBeUndefined();
|
|
1947
|
-
(0, bun_test_1.expect)(data[0].__t).toBeUndefined();
|
|
1948
|
-
(0, bun_test_1.expect)(data[1].email).toBe("admin@example.com");
|
|
1949
|
-
(0, bun_test_1.expect)(data[1].department).toBeUndefined();
|
|
1950
|
-
(0, bun_test_1.expect)(data[1].supertitle).toBeUndefined();
|
|
1951
|
-
(0, bun_test_1.expect)(data[1].__t).toBeUndefined();
|
|
1952
|
-
(0, bun_test_1.expect)(data[2].email).toBe("notAdmin@example.com");
|
|
1953
|
-
(0, bun_test_1.expect)(data[2].department).toBeUndefined();
|
|
1954
|
-
(0, bun_test_1.expect)(data[2].supertitle).toBeUndefined();
|
|
1955
|
-
(0, bun_test_1.expect)(data[2].__t).toBeUndefined();
|
|
1956
|
-
(0, bun_test_1.expect)(data[3].email).toBe("staff@example.com");
|
|
1957
|
-
(0, bun_test_1.expect)(data[3].department).toBe("Accounting");
|
|
1958
|
-
(0, bun_test_1.expect)(data[3].supertitle).toBeUndefined();
|
|
1959
|
-
(0, bun_test_1.expect)(data[3].__t).toBe("Staff");
|
|
1960
|
-
(0, bun_test_1.expect)(data[4].email).toBe("superuser@example.com");
|
|
1961
|
-
(0, bun_test_1.expect)(data[4].department).toBeUndefined();
|
|
1962
|
-
(0, bun_test_1.expect)(data[4].superTitle).toBe("Super Man");
|
|
1963
|
-
(0, bun_test_1.expect)(data[4].__t).toBe("SuperUser");
|
|
3489
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
3490
|
+
(0, bun_test_1.expect)(res.body.detail).toBe("A body must be returned from preUpdate");
|
|
1964
3491
|
return [2 /*return*/];
|
|
1965
3492
|
}
|
|
1966
3493
|
});
|
|
1967
3494
|
}); });
|
|
1968
|
-
(0, bun_test_1.it)("
|
|
3495
|
+
(0, bun_test_1.it)("array operation preUpdate returning null for array PATCH throws error", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1969
3496
|
var res;
|
|
1970
3497
|
return __generator(this, function (_a) {
|
|
1971
3498
|
switch (_a.label) {
|
|
1972
|
-
case 0:
|
|
3499
|
+
case 0:
|
|
3500
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3501
|
+
allowAnonymous: true,
|
|
3502
|
+
permissions: {
|
|
3503
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
3504
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
3505
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
3506
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
3507
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
3508
|
+
},
|
|
3509
|
+
preUpdate: function () { return null; },
|
|
3510
|
+
}));
|
|
3511
|
+
server = (0, supertest_1.default)(app);
|
|
3512
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
1973
3513
|
case 1:
|
|
3514
|
+
agent = _a.sent();
|
|
3515
|
+
return [4 /*yield*/, agent
|
|
3516
|
+
.patch("/food/".concat(apple._id, "/tags/healthy"))
|
|
3517
|
+
.send({ tags: "unhealthy" })
|
|
3518
|
+
.expect(403)];
|
|
3519
|
+
case 2:
|
|
1974
3520
|
res = _a.sent();
|
|
1975
|
-
(0, bun_test_1.expect)(res.body.
|
|
1976
|
-
(0, bun_test_1.expect)(res.body.data.department).toBeUndefined();
|
|
1977
|
-
(0, bun_test_1.expect)(res.body.data.superTitle).toBe("Super Man");
|
|
3521
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Update not allowed");
|
|
1978
3522
|
return [2 /*return*/];
|
|
1979
3523
|
}
|
|
1980
3524
|
});
|
|
1981
3525
|
}); });
|
|
1982
|
-
(0, bun_test_1.it)("
|
|
1983
|
-
var res
|
|
3526
|
+
(0, bun_test_1.it)("array operation preUpdate error for array DELETE is handled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3527
|
+
var res;
|
|
1984
3528
|
return __generator(this, function (_a) {
|
|
1985
3529
|
switch (_a.label) {
|
|
1986
|
-
case 0:
|
|
1987
|
-
|
|
1988
|
-
|
|
3530
|
+
case 0:
|
|
3531
|
+
app.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
|
|
3532
|
+
allowAnonymous: true,
|
|
3533
|
+
permissions: {
|
|
3534
|
+
create: [permissions_1.Permissions.IsAdmin],
|
|
3535
|
+
delete: [permissions_1.Permissions.IsAdmin],
|
|
3536
|
+
list: [permissions_1.Permissions.IsAdmin],
|
|
3537
|
+
read: [permissions_1.Permissions.IsAdmin],
|
|
3538
|
+
update: [permissions_1.Permissions.IsAdmin],
|
|
3539
|
+
},
|
|
3540
|
+
preUpdate: function () {
|
|
3541
|
+
throw new Error("preUpdate error during delete");
|
|
3542
|
+
},
|
|
3543
|
+
}));
|
|
3544
|
+
server = (0, supertest_1.default)(app);
|
|
3545
|
+
return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
|
|
1989
3546
|
case 1:
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
return [4 /*yield*/, agent
|
|
1993
|
-
.patch("/users/".concat(superUser._id))
|
|
1994
|
-
.send({ __t: "SuperUser", superTitle: "Batman" })
|
|
1995
|
-
.expect(200)];
|
|
3547
|
+
agent = _a.sent();
|
|
3548
|
+
return [4 /*yield*/, agent.delete("/food/".concat(apple._id, "/tags/healthy")).expect(400)];
|
|
1996
3549
|
case 2:
|
|
1997
3550
|
res = _a.sent();
|
|
1998
|
-
(0, bun_test_1.expect)(res.body.
|
|
1999
|
-
(0, bun_test_1.expect)(res.body.data.department).toBeUndefined();
|
|
2000
|
-
(0, bun_test_1.expect)(res.body.data.superTitle).toBe("Batman");
|
|
2001
|
-
return [4 /*yield*/, tests_1.SuperUserModel.findById(superUser._id)];
|
|
2002
|
-
case 3:
|
|
2003
|
-
user = _a.sent();
|
|
2004
|
-
(0, bun_test_1.expect)(user === null || user === void 0 ? void 0 : user.superTitle).toBe("Batman");
|
|
3551
|
+
(0, bun_test_1.expect)(res.body.title).toContain("preUpdate hook error");
|
|
2005
3552
|
return [2 /*return*/];
|
|
2006
3553
|
}
|
|
2007
3554
|
});
|
|
2008
3555
|
}); });
|
|
2009
|
-
|
|
2010
|
-
|
|
3556
|
+
});
|
|
3557
|
+
});
|
|
3558
|
+
(0, bun_test_1.describe)("errors module", function () {
|
|
3559
|
+
(0, bun_test_1.describe)("APIError", function () {
|
|
3560
|
+
(0, bun_test_1.it)("sets default status to 500 when not provided", function () {
|
|
3561
|
+
var error = new errors_1.APIError({ title: "Test error" });
|
|
3562
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
3563
|
+
});
|
|
3564
|
+
(0, bun_test_1.it)("sets status to 500 for invalid status codes below 400", function () {
|
|
3565
|
+
var error = new errors_1.APIError({ status: 200, title: "Test error" });
|
|
3566
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
3567
|
+
});
|
|
3568
|
+
(0, bun_test_1.it)("sets status to 500 for invalid status codes above 599", function () {
|
|
3569
|
+
var error = new errors_1.APIError({ status: 600, title: "Test error" });
|
|
3570
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
3571
|
+
});
|
|
3572
|
+
(0, bun_test_1.it)("includes error stack in message when error is provided", function () {
|
|
3573
|
+
var originalError = new Error("Original error");
|
|
3574
|
+
var apiError = new errors_1.APIError({
|
|
3575
|
+
error: originalError,
|
|
3576
|
+
title: "Wrapped error",
|
|
3577
|
+
});
|
|
3578
|
+
(0, bun_test_1.expect)(apiError.message).toContain("Wrapped error");
|
|
3579
|
+
(0, bun_test_1.expect)(originalError.stack).toBeDefined();
|
|
3580
|
+
(0, bun_test_1.expect)(apiError.message).toContain(originalError.stack);
|
|
3581
|
+
});
|
|
3582
|
+
(0, bun_test_1.it)("includes detail in message when provided", function () {
|
|
3583
|
+
var error = new errors_1.APIError({
|
|
3584
|
+
detail: "More details here",
|
|
3585
|
+
title: "Test error",
|
|
3586
|
+
});
|
|
3587
|
+
(0, bun_test_1.expect)(error.message).toContain("Test error");
|
|
3588
|
+
(0, bun_test_1.expect)(error.message).toContain("More details here");
|
|
3589
|
+
});
|
|
3590
|
+
(0, bun_test_1.it)("sets fields in meta when provided", function () {
|
|
3591
|
+
var _a;
|
|
3592
|
+
var error = new errors_1.APIError({
|
|
3593
|
+
fields: { email: "Invalid email format" },
|
|
3594
|
+
title: "Validation error",
|
|
3595
|
+
});
|
|
3596
|
+
(0, bun_test_1.expect)((_a = error.meta) === null || _a === void 0 ? void 0 : _a.fields).toEqual({ email: "Invalid email format" });
|
|
3597
|
+
});
|
|
3598
|
+
});
|
|
3599
|
+
(0, bun_test_1.describe)("errorsPlugin", function () {
|
|
3600
|
+
(0, bun_test_1.it)("adds apiErrors field to schema", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3601
|
+
var mongoose, errorsPlugin, testSchema;
|
|
2011
3602
|
return __generator(this, function (_a) {
|
|
2012
3603
|
switch (_a.label) {
|
|
2013
|
-
case 0: return [4 /*yield*/,
|
|
2014
|
-
.patch("/users/".concat(notAdmin._id))
|
|
2015
|
-
.send({ email: "newemail@example.com", superTitle: "The Boss" })
|
|
2016
|
-
.expect(200)];
|
|
3604
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("mongoose")); })];
|
|
2017
3605
|
case 1:
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
(0, bun_test_1.expect)(res.body.data.superTitle).toBeUndefined();
|
|
2021
|
-
return [4 /*yield*/, tests_1.SuperUserModel.findById(notAdmin._id)];
|
|
3606
|
+
mongoose = _a.sent();
|
|
3607
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./errors")); })];
|
|
2022
3608
|
case 2:
|
|
2023
|
-
|
|
2024
|
-
|
|
3609
|
+
errorsPlugin = (_a.sent()).errorsPlugin;
|
|
3610
|
+
testSchema = new mongoose.Schema({ name: String });
|
|
3611
|
+
errorsPlugin(testSchema);
|
|
3612
|
+
(0, bun_test_1.expect)(testSchema.path("apiErrors")).toBeDefined();
|
|
2025
3613
|
return [2 /*return*/];
|
|
2026
3614
|
}
|
|
2027
3615
|
});
|
|
2028
3616
|
}); });
|
|
2029
|
-
|
|
3617
|
+
});
|
|
3618
|
+
(0, bun_test_1.describe)("isAPIError", function () {
|
|
3619
|
+
(0, bun_test_1.it)("returns true for APIError instances", function () {
|
|
3620
|
+
var isAPIError = require("./errors").isAPIError;
|
|
3621
|
+
var error = new errors_1.APIError({ title: "Test" });
|
|
3622
|
+
(0, bun_test_1.expect)(isAPIError(error)).toBe(true);
|
|
3623
|
+
});
|
|
3624
|
+
(0, bun_test_1.it)("returns false for regular Error instances", function () {
|
|
3625
|
+
var isAPIError = require("./errors").isAPIError;
|
|
3626
|
+
var error = new Error("Test");
|
|
3627
|
+
(0, bun_test_1.expect)(isAPIError(error)).toBe(false);
|
|
3628
|
+
});
|
|
3629
|
+
});
|
|
3630
|
+
(0, bun_test_1.describe)("getDisableExternalErrorTracking", function () {
|
|
3631
|
+
(0, bun_test_1.it)("returns undefined for non-objects", function () {
|
|
3632
|
+
var getDisableExternalErrorTracking = require("./errors").getDisableExternalErrorTracking;
|
|
3633
|
+
(0, bun_test_1.expect)(getDisableExternalErrorTracking(null)).toBeUndefined();
|
|
3634
|
+
(0, bun_test_1.expect)(getDisableExternalErrorTracking("string")).toBeUndefined();
|
|
3635
|
+
});
|
|
3636
|
+
(0, bun_test_1.it)("returns value from APIError", function () {
|
|
3637
|
+
var getDisableExternalErrorTracking = require("./errors").getDisableExternalErrorTracking;
|
|
3638
|
+
var error = new errors_1.APIError({ disableExternalErrorTracking: true, title: "Test" });
|
|
3639
|
+
(0, bun_test_1.expect)(getDisableExternalErrorTracking(error)).toBe(true);
|
|
3640
|
+
});
|
|
3641
|
+
(0, bun_test_1.it)("returns value from plain object with property", function () {
|
|
3642
|
+
var getDisableExternalErrorTracking = require("./errors").getDisableExternalErrorTracking;
|
|
3643
|
+
var obj = { disableExternalErrorTracking: true };
|
|
3644
|
+
(0, bun_test_1.expect)(getDisableExternalErrorTracking(obj)).toBe(true);
|
|
3645
|
+
});
|
|
3646
|
+
});
|
|
3647
|
+
(0, bun_test_1.describe)("getAPIErrorBody", function () {
|
|
3648
|
+
(0, bun_test_1.it)("includes all non-undefined fields", function () {
|
|
3649
|
+
var getAPIErrorBody = require("./errors").getAPIErrorBody;
|
|
3650
|
+
var error = new errors_1.APIError({
|
|
3651
|
+
code: "TEST_CODE",
|
|
3652
|
+
detail: "Test detail",
|
|
3653
|
+
id: "error-123",
|
|
3654
|
+
links: { about: "http://example.com" },
|
|
3655
|
+
meta: { extra: "data" },
|
|
3656
|
+
source: { parameter: "id" },
|
|
3657
|
+
status: 400,
|
|
3658
|
+
title: "Test error",
|
|
3659
|
+
});
|
|
3660
|
+
var body = getAPIErrorBody(error);
|
|
3661
|
+
(0, bun_test_1.expect)(body.title).toBe("Test error");
|
|
3662
|
+
(0, bun_test_1.expect)(body.status).toBe(400);
|
|
3663
|
+
(0, bun_test_1.expect)(body.code).toBe("TEST_CODE");
|
|
3664
|
+
(0, bun_test_1.expect)(body.detail).toBe("Test detail");
|
|
3665
|
+
(0, bun_test_1.expect)(body.id).toBe("error-123");
|
|
3666
|
+
(0, bun_test_1.expect)(body.links).toEqual({ about: "http://example.com" });
|
|
3667
|
+
(0, bun_test_1.expect)(body.source).toEqual({ parameter: "id" });
|
|
3668
|
+
(0, bun_test_1.expect)(body.meta).toEqual({ extra: "data" });
|
|
3669
|
+
});
|
|
3670
|
+
});
|
|
3671
|
+
(0, bun_test_1.describe)("apiUnauthorizedMiddleware", function () {
|
|
3672
|
+
(0, bun_test_1.it)("returns 401 for Unauthorized errors", function () {
|
|
3673
|
+
var apiUnauthorizedMiddleware = require("./errors").apiUnauthorizedMiddleware;
|
|
3674
|
+
var err = new Error("Unauthorized");
|
|
3675
|
+
var res = {
|
|
3676
|
+
json: function (data) {
|
|
3677
|
+
this.body = data;
|
|
3678
|
+
return this;
|
|
3679
|
+
},
|
|
3680
|
+
send: function () {
|
|
3681
|
+
return this;
|
|
3682
|
+
},
|
|
3683
|
+
status: function (code) {
|
|
3684
|
+
this.statusCode = code;
|
|
3685
|
+
return this;
|
|
3686
|
+
},
|
|
3687
|
+
};
|
|
3688
|
+
var next = function () { };
|
|
3689
|
+
apiUnauthorizedMiddleware(err, {}, res, next);
|
|
3690
|
+
(0, bun_test_1.expect)(res.statusCode).toBe(401);
|
|
3691
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Unauthorized");
|
|
3692
|
+
});
|
|
3693
|
+
(0, bun_test_1.it)("calls next for non-Unauthorized errors", function () {
|
|
3694
|
+
var apiUnauthorizedMiddleware = require("./errors").apiUnauthorizedMiddleware;
|
|
3695
|
+
var err = new Error("Some other error");
|
|
3696
|
+
var nextCalled = false;
|
|
3697
|
+
var next = function () {
|
|
3698
|
+
nextCalled = true;
|
|
3699
|
+
};
|
|
3700
|
+
apiUnauthorizedMiddleware(err, {}, {}, next);
|
|
3701
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
3702
|
+
});
|
|
3703
|
+
});
|
|
3704
|
+
});
|
|
3705
|
+
(0, bun_test_1.describe)("permissions module", function () {
|
|
3706
|
+
(0, bun_test_1.describe)("OwnerQueryFilter", function () {
|
|
3707
|
+
(0, bun_test_1.it)("returns ownerId filter when user is provided", function () {
|
|
3708
|
+
var OwnerQueryFilter = require("./permissions").OwnerQueryFilter;
|
|
3709
|
+
var user = { id: "user-123" };
|
|
3710
|
+
var filter = OwnerQueryFilter(user);
|
|
3711
|
+
(0, bun_test_1.expect)(filter).toEqual({ ownerId: "user-123" });
|
|
3712
|
+
});
|
|
3713
|
+
(0, bun_test_1.it)("returns null when user is undefined", function () {
|
|
3714
|
+
var OwnerQueryFilter = require("./permissions").OwnerQueryFilter;
|
|
3715
|
+
var filter = OwnerQueryFilter(undefined);
|
|
3716
|
+
(0, bun_test_1.expect)(filter).toBeNull();
|
|
3717
|
+
});
|
|
3718
|
+
});
|
|
3719
|
+
(0, bun_test_1.describe)("Permissions.IsAuthenticatedOrReadOnly", function () {
|
|
3720
|
+
(0, bun_test_1.it)("returns true for authenticated non-anonymous users", function () {
|
|
3721
|
+
var Permissions = require("./permissions").Permissions;
|
|
3722
|
+
var user = { id: "user-123", isAnonymous: false };
|
|
3723
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("create", user)).toBe(true);
|
|
3724
|
+
});
|
|
3725
|
+
(0, bun_test_1.it)("returns true for read methods when user is anonymous", function () {
|
|
3726
|
+
var Permissions = require("./permissions").Permissions;
|
|
3727
|
+
var user = { id: "user-123", isAnonymous: true };
|
|
3728
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("list", user)).toBe(true);
|
|
3729
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("read", user)).toBe(true);
|
|
3730
|
+
});
|
|
3731
|
+
(0, bun_test_1.it)("returns false for write methods when user is anonymous", function () {
|
|
3732
|
+
var Permissions = require("./permissions").Permissions;
|
|
3733
|
+
var user = { id: "user-123", isAnonymous: true };
|
|
3734
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("create", user)).toBe(false);
|
|
3735
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("update", user)).toBe(false);
|
|
3736
|
+
(0, bun_test_1.expect)(Permissions.IsAuthenticatedOrReadOnly("delete", user)).toBe(false);
|
|
3737
|
+
});
|
|
3738
|
+
});
|
|
3739
|
+
(0, bun_test_1.describe)("Permissions.IsOwnerOrReadOnly", function () {
|
|
3740
|
+
(0, bun_test_1.it)("returns true when no object is provided", function () {
|
|
3741
|
+
var Permissions = require("./permissions").Permissions;
|
|
3742
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("update", { id: "user-123" }, undefined)).toBe(true);
|
|
3743
|
+
});
|
|
3744
|
+
(0, bun_test_1.it)("returns true for admin users", function () {
|
|
3745
|
+
var Permissions = require("./permissions").Permissions;
|
|
3746
|
+
var user = { admin: true, id: "admin-123" };
|
|
3747
|
+
var obj = { ownerId: "other-user" };
|
|
3748
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("update", user, obj)).toBe(true);
|
|
3749
|
+
});
|
|
3750
|
+
(0, bun_test_1.it)("returns true when user is owner", function () {
|
|
3751
|
+
var Permissions = require("./permissions").Permissions;
|
|
3752
|
+
var user = { id: "user-123" };
|
|
3753
|
+
var obj = { ownerId: "user-123" };
|
|
3754
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("update", user, obj)).toBe(true);
|
|
3755
|
+
});
|
|
3756
|
+
(0, bun_test_1.it)("returns true for read methods when not owner", function () {
|
|
3757
|
+
var Permissions = require("./permissions").Permissions;
|
|
3758
|
+
var user = { id: "user-123" };
|
|
3759
|
+
var obj = { ownerId: "other-user" };
|
|
3760
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("list", user, obj)).toBe(true);
|
|
3761
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("read", user, obj)).toBe(true);
|
|
3762
|
+
});
|
|
3763
|
+
(0, bun_test_1.it)("returns false for write methods when not owner", function () {
|
|
3764
|
+
var Permissions = require("./permissions").Permissions;
|
|
3765
|
+
var user = { id: "user-123" };
|
|
3766
|
+
var obj = { ownerId: "other-user" };
|
|
3767
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("update", user, obj)).toBe(false);
|
|
3768
|
+
(0, bun_test_1.expect)(Permissions.IsOwnerOrReadOnly("delete", user, obj)).toBe(false);
|
|
3769
|
+
});
|
|
3770
|
+
});
|
|
3771
|
+
});
|
|
3772
|
+
(0, bun_test_1.describe)("utils module", function () {
|
|
3773
|
+
(0, bun_test_1.describe)("isValidObjectId", function () {
|
|
3774
|
+
(0, bun_test_1.it)("returns true for valid ObjectId strings", function () {
|
|
3775
|
+
var isValidObjectId = require("./utils").isValidObjectId;
|
|
3776
|
+
(0, bun_test_1.expect)(isValidObjectId("507f1f77bcf86cd799439011")).toBe(true);
|
|
3777
|
+
});
|
|
3778
|
+
(0, bun_test_1.it)("returns false for invalid ObjectId strings", function () {
|
|
3779
|
+
var isValidObjectId = require("./utils").isValidObjectId;
|
|
3780
|
+
(0, bun_test_1.expect)(isValidObjectId("invalid-id")).toBe(false);
|
|
3781
|
+
(0, bun_test_1.expect)(isValidObjectId("12345")).toBe(false);
|
|
3782
|
+
(0, bun_test_1.expect)(isValidObjectId("")).toBe(false);
|
|
3783
|
+
});
|
|
3784
|
+
(0, bun_test_1.it)("returns false for 12-character strings that are not valid ObjectIds", function () {
|
|
3785
|
+
var isValidObjectId = require("./utils").isValidObjectId;
|
|
3786
|
+
// mongoose's native isValid returns true for any 12-char string
|
|
3787
|
+
// but our implementation should return false since toString won't match
|
|
3788
|
+
(0, bun_test_1.expect)(isValidObjectId("123456789012")).toBe(false);
|
|
3789
|
+
});
|
|
3790
|
+
});
|
|
3791
|
+
(0, bun_test_1.describe)("timeout", function () {
|
|
3792
|
+
(0, bun_test_1.it)("resolves after specified time", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3793
|
+
var timeout, start, elapsed;
|
|
2030
3794
|
return __generator(this, function (_a) {
|
|
2031
3795
|
switch (_a.label) {
|
|
2032
|
-
case 0:
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
3796
|
+
case 0:
|
|
3797
|
+
timeout = require("./utils").timeout;
|
|
3798
|
+
start = Date.now();
|
|
3799
|
+
return [4 /*yield*/, timeout(50)];
|
|
2036
3800
|
case 1:
|
|
2037
3801
|
_a.sent();
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
3802
|
+
elapsed = Date.now() - start;
|
|
3803
|
+
(0, bun_test_1.expect)(elapsed).toBeGreaterThanOrEqual(40);
|
|
3804
|
+
return [2 /*return*/];
|
|
3805
|
+
}
|
|
3806
|
+
});
|
|
3807
|
+
}); });
|
|
3808
|
+
});
|
|
3809
|
+
// Note: Comprehensive checkModelsStrict tests are in utils.test.ts with mocked mongoose
|
|
3810
|
+
});
|
|
3811
|
+
(0, bun_test_1.describe)("populate module", function () {
|
|
3812
|
+
(0, bun_test_1.describe)("unpopulate", function () {
|
|
3813
|
+
(0, bun_test_1.it)("throws error when path is empty", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3814
|
+
var unpopulate, doc;
|
|
3815
|
+
return __generator(this, function (_a) {
|
|
3816
|
+
switch (_a.label) {
|
|
3817
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3818
|
+
case 1:
|
|
3819
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3820
|
+
doc = { name: "test" };
|
|
3821
|
+
(0, bun_test_1.expect)(function () { return unpopulate(doc, ""); }).toThrow("path is required");
|
|
3822
|
+
return [2 /*return*/];
|
|
3823
|
+
}
|
|
3824
|
+
});
|
|
3825
|
+
}); });
|
|
3826
|
+
(0, bun_test_1.it)("unpopulates single populated field", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3827
|
+
var unpopulate, doc, result;
|
|
3828
|
+
return __generator(this, function (_a) {
|
|
3829
|
+
switch (_a.label) {
|
|
3830
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3831
|
+
case 1:
|
|
3832
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3833
|
+
doc = {
|
|
3834
|
+
name: "test",
|
|
3835
|
+
ownerId: { _id: "owner-123", email: "owner@test.com" },
|
|
3836
|
+
};
|
|
3837
|
+
result = unpopulate(doc, "ownerId");
|
|
3838
|
+
(0, bun_test_1.expect)(result.ownerId).toBe("owner-123");
|
|
3839
|
+
return [2 /*return*/];
|
|
3840
|
+
}
|
|
3841
|
+
});
|
|
3842
|
+
}); });
|
|
3843
|
+
(0, bun_test_1.it)("unpopulates array of populated fields", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3844
|
+
var unpopulate, doc, result;
|
|
3845
|
+
return __generator(this, function (_a) {
|
|
3846
|
+
switch (_a.label) {
|
|
3847
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3848
|
+
case 1:
|
|
3849
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3850
|
+
doc = {
|
|
3851
|
+
items: [{ _id: "item-1", name: "Item 1" }, { _id: "item-2", name: "Item 2" }, "item-3"],
|
|
3852
|
+
name: "test",
|
|
3853
|
+
};
|
|
3854
|
+
result = unpopulate(doc, "items");
|
|
3855
|
+
(0, bun_test_1.expect)(result.items).toEqual(["item-1", "item-2", "item-3"]);
|
|
3856
|
+
return [2 /*return*/];
|
|
3857
|
+
}
|
|
3858
|
+
});
|
|
3859
|
+
}); });
|
|
3860
|
+
(0, bun_test_1.it)("handles nested paths", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3861
|
+
var unpopulate, doc, result;
|
|
3862
|
+
return __generator(this, function (_a) {
|
|
3863
|
+
switch (_a.label) {
|
|
3864
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3865
|
+
case 1:
|
|
3866
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3867
|
+
doc = {
|
|
3868
|
+
name: "test",
|
|
3869
|
+
nested: {
|
|
3870
|
+
items: [
|
|
3871
|
+
{ _id: "item-1", name: "Item 1" },
|
|
3872
|
+
{ _id: "item-2", name: "Item 2" },
|
|
3873
|
+
],
|
|
3874
|
+
},
|
|
3875
|
+
};
|
|
3876
|
+
result = unpopulate(doc, "nested.items");
|
|
3877
|
+
(0, bun_test_1.expect)(result.nested.items).toEqual(["item-1", "item-2"]);
|
|
3878
|
+
return [2 /*return*/];
|
|
3879
|
+
}
|
|
3880
|
+
});
|
|
3881
|
+
}); });
|
|
3882
|
+
(0, bun_test_1.it)("returns original doc when path does not exist", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3883
|
+
var unpopulate, doc, result;
|
|
3884
|
+
return __generator(this, function (_a) {
|
|
3885
|
+
switch (_a.label) {
|
|
3886
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3887
|
+
case 1:
|
|
3888
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3889
|
+
doc = { name: "test" };
|
|
3890
|
+
result = unpopulate(doc, "nonexistent");
|
|
3891
|
+
(0, bun_test_1.expect)(result).toEqual(doc);
|
|
3892
|
+
return [2 /*return*/];
|
|
3893
|
+
}
|
|
3894
|
+
});
|
|
3895
|
+
}); });
|
|
3896
|
+
(0, bun_test_1.it)("handles nested array paths", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3897
|
+
var unpopulate, doc, result;
|
|
3898
|
+
return __generator(this, function (_a) {
|
|
3899
|
+
switch (_a.label) {
|
|
3900
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./populate")); })];
|
|
3901
|
+
case 1:
|
|
3902
|
+
unpopulate = (_a.sent()).unpopulate;
|
|
3903
|
+
doc = {
|
|
3904
|
+
containers: [
|
|
3905
|
+
{ items: [{ _id: "item-1" }, { _id: "item-2" }] },
|
|
3906
|
+
{ items: [{ _id: "item-3" }, { _id: "item-4" }] },
|
|
3907
|
+
],
|
|
3908
|
+
name: "test",
|
|
3909
|
+
};
|
|
3910
|
+
result = unpopulate(doc, "containers.items");
|
|
3911
|
+
(0, bun_test_1.expect)(result.containers[0].items).toEqual(["item-1", "item-2"]);
|
|
3912
|
+
(0, bun_test_1.expect)(result.containers[1].items).toEqual(["item-3", "item-4"]);
|
|
3913
|
+
return [2 /*return*/];
|
|
3914
|
+
}
|
|
3915
|
+
});
|
|
3916
|
+
}); });
|
|
3917
|
+
});
|
|
3918
|
+
});
|
|
3919
|
+
(0, bun_test_1.describe)("auth module edge cases", function () {
|
|
3920
|
+
(0, bun_test_1.describe)("generateTokens", function () {
|
|
3921
|
+
(0, bun_test_1.it)("returns null tokens when user is missing", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3922
|
+
var generateTokens, result;
|
|
3923
|
+
return __generator(this, function (_a) {
|
|
3924
|
+
switch (_a.label) {
|
|
3925
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./auth")); })];
|
|
3926
|
+
case 1:
|
|
3927
|
+
generateTokens = (_a.sent()).generateTokens;
|
|
3928
|
+
return [4 /*yield*/, generateTokens(null)];
|
|
2042
3929
|
case 2:
|
|
2043
|
-
_a.sent();
|
|
3930
|
+
result = _a.sent();
|
|
3931
|
+
(0, bun_test_1.expect)(result.token).toBeNull();
|
|
3932
|
+
(0, bun_test_1.expect)(result.refreshToken).toBeNull();
|
|
2044
3933
|
return [2 /*return*/];
|
|
2045
3934
|
}
|
|
2046
3935
|
});
|
|
2047
3936
|
}); });
|
|
2048
|
-
(0, bun_test_1.it)("
|
|
2049
|
-
var
|
|
3937
|
+
(0, bun_test_1.it)("returns null tokens when user has no _id", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3938
|
+
var generateTokens, result;
|
|
2050
3939
|
return __generator(this, function (_a) {
|
|
2051
3940
|
switch (_a.label) {
|
|
2052
|
-
case 0: return [4 /*yield*/,
|
|
2053
|
-
.patch("/users/".concat(superUser._id))
|
|
2054
|
-
.send({ __t: "SuperUser", department: "Journalism" })
|
|
2055
|
-
.expect(200)];
|
|
3941
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./auth")); })];
|
|
2056
3942
|
case 1:
|
|
2057
|
-
|
|
2058
|
-
(
|
|
2059
|
-
return [4 /*yield*/, tests_1.SuperUserModel.findById(superUser._id)];
|
|
3943
|
+
generateTokens = (_a.sent()).generateTokens;
|
|
3944
|
+
return [4 /*yield*/, generateTokens({ email: "test@test.com" })];
|
|
2060
3945
|
case 2:
|
|
2061
|
-
|
|
2062
|
-
(0, bun_test_1.expect)(
|
|
3946
|
+
result = _a.sent();
|
|
3947
|
+
(0, bun_test_1.expect)(result.token).toBeNull();
|
|
3948
|
+
(0, bun_test_1.expect)(result.refreshToken).toBeNull();
|
|
2063
3949
|
return [2 /*return*/];
|
|
2064
3950
|
}
|
|
2065
3951
|
});
|
|
2066
3952
|
}); });
|
|
2067
|
-
(0, bun_test_1.it)("
|
|
2068
|
-
var
|
|
3953
|
+
(0, bun_test_1.it)("includes custom payload from generateJWTPayload option", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3954
|
+
var generateTokens, jwt, user, result, decoded;
|
|
2069
3955
|
return __generator(this, function (_a) {
|
|
2070
3956
|
switch (_a.label) {
|
|
2071
|
-
case 0: return [4 /*yield*/,
|
|
2072
|
-
.post("/users")
|
|
2073
|
-
.send({
|
|
2074
|
-
__t: "SuperUser",
|
|
2075
|
-
department: "R&D",
|
|
2076
|
-
email: "brucewayne@example.com",
|
|
2077
|
-
superTitle: "Batman",
|
|
2078
|
-
})
|
|
2079
|
-
.expect(201)];
|
|
3957
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./auth")); })];
|
|
2080
3958
|
case 1:
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
// Because we pass __t, this should create a SuperUser which has no department, so this is
|
|
2084
|
-
// dropped.
|
|
2085
|
-
(0, bun_test_1.expect)(res.body.data.department).toBeUndefined();
|
|
2086
|
-
(0, bun_test_1.expect)(res.body.data.superTitle).toBe("Batman");
|
|
2087
|
-
return [4 /*yield*/, tests_1.SuperUserModel.findById(res.body.data._id)];
|
|
3959
|
+
generateTokens = (_a.sent()).generateTokens;
|
|
3960
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("jsonwebtoken")); })];
|
|
2088
3961
|
case 2:
|
|
2089
|
-
|
|
2090
|
-
|
|
3962
|
+
jwt = _a.sent();
|
|
3963
|
+
user = { _id: "user-123" };
|
|
3964
|
+
return [4 /*yield*/, generateTokens(user, {
|
|
3965
|
+
generateJWTPayload: function (u) { return ({ customField: "customValue", userId: u._id }); },
|
|
3966
|
+
})];
|
|
3967
|
+
case 3:
|
|
3968
|
+
result = _a.sent();
|
|
3969
|
+
(0, bun_test_1.expect)(result.token).toBeDefined();
|
|
3970
|
+
decoded = jwt.decode(result.token);
|
|
3971
|
+
(0, bun_test_1.expect)(decoded.customField).toBe("customValue");
|
|
3972
|
+
(0, bun_test_1.expect)(decoded.id).toBe("user-123");
|
|
2091
3973
|
return [2 /*return*/];
|
|
2092
3974
|
}
|
|
2093
3975
|
});
|
|
2094
3976
|
}); });
|
|
2095
|
-
(0, bun_test_1.it)("
|
|
2096
|
-
var user;
|
|
3977
|
+
(0, bun_test_1.it)("uses custom token expiration from generateTokenExpiration option", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3978
|
+
var generateTokens, jwt, user, result, decoded, expectedExp;
|
|
2097
3979
|
return __generator(this, function (_a) {
|
|
2098
3980
|
switch (_a.label) {
|
|
2099
|
-
case 0:
|
|
2100
|
-
// Fails without __t.
|
|
2101
|
-
return [4 /*yield*/, agent.delete("/users/".concat(superUser._id)).expect(404)];
|
|
3981
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./auth")); })];
|
|
2102
3982
|
case 1:
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
return [4 /*yield*/, agent
|
|
2106
|
-
.delete("/users/".concat(superUser._id))
|
|
2107
|
-
.send({
|
|
2108
|
-
__t: "SuperUser",
|
|
2109
|
-
})
|
|
2110
|
-
.expect(204)];
|
|
3983
|
+
generateTokens = (_a.sent()).generateTokens;
|
|
3984
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("jsonwebtoken")); })];
|
|
2111
3985
|
case 2:
|
|
2112
|
-
_a.sent();
|
|
2113
|
-
|
|
3986
|
+
jwt = _a.sent();
|
|
3987
|
+
user = { _id: "user-123" };
|
|
3988
|
+
return [4 /*yield*/, generateTokens(user, {
|
|
3989
|
+
generateTokenExpiration: function () { return "1h"; },
|
|
3990
|
+
})];
|
|
2114
3991
|
case 3:
|
|
2115
|
-
|
|
2116
|
-
(0, bun_test_1.expect)(
|
|
3992
|
+
result = _a.sent();
|
|
3993
|
+
(0, bun_test_1.expect)(result.token).toBeDefined();
|
|
3994
|
+
decoded = jwt.decode(result.token);
|
|
3995
|
+
expectedExp = Math.floor(Date.now() / 1000) + 3600;
|
|
3996
|
+
(0, bun_test_1.expect)(decoded.exp).toBeGreaterThan(expectedExp - 5);
|
|
3997
|
+
(0, bun_test_1.expect)(decoded.exp).toBeLessThan(expectedExp + 5);
|
|
2117
3998
|
return [2 /*return*/];
|
|
2118
3999
|
}
|
|
2119
4000
|
});
|
|
2120
4001
|
}); });
|
|
2121
|
-
(0, bun_test_1.it)("
|
|
2122
|
-
var user;
|
|
4002
|
+
(0, bun_test_1.it)("uses custom refresh token expiration from generateRefreshTokenExpiration option", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
4003
|
+
var generateTokens, jwt, user, result, decoded, expectedExp;
|
|
2123
4004
|
return __generator(this, function (_a) {
|
|
2124
4005
|
switch (_a.label) {
|
|
2125
|
-
case 0:
|
|
2126
|
-
// Fails for base user with __t
|
|
2127
|
-
return [4 /*yield*/, agent.delete("/users/".concat(notAdmin._id)).send({ __t: "SuperUser" }).expect(404)];
|
|
4006
|
+
case 0: return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("./auth")); })];
|
|
2128
4007
|
case 1:
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
return [4 /*yield*/, agent.delete("/users/".concat(notAdmin._id)).expect(204)];
|
|
4008
|
+
generateTokens = (_a.sent()).generateTokens;
|
|
4009
|
+
return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("jsonwebtoken")); })];
|
|
2132
4010
|
case 2:
|
|
2133
|
-
_a.sent();
|
|
2134
|
-
|
|
4011
|
+
jwt = _a.sent();
|
|
4012
|
+
user = { _id: "user-123" };
|
|
4013
|
+
return [4 /*yield*/, generateTokens(user, {
|
|
4014
|
+
generateRefreshTokenExpiration: function () { return "7d"; },
|
|
4015
|
+
})];
|
|
2135
4016
|
case 3:
|
|
2136
|
-
|
|
2137
|
-
(0, bun_test_1.expect)(
|
|
4017
|
+
result = _a.sent();
|
|
4018
|
+
(0, bun_test_1.expect)(result.refreshToken).toBeDefined();
|
|
4019
|
+
decoded = jwt.decode(result.refreshToken);
|
|
4020
|
+
expectedExp = Math.floor(Date.now() / 1000) + 7 * 24 * 3600;
|
|
4021
|
+
(0, bun_test_1.expect)(decoded.exp).toBeGreaterThan(expectedExp - 10);
|
|
4022
|
+
(0, bun_test_1.expect)(decoded.exp).toBeLessThan(expectedExp + 10);
|
|
2138
4023
|
return [2 /*return*/];
|
|
2139
4024
|
}
|
|
2140
4025
|
});
|