placementt-core 1.400.1013 → 1.400.1015
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/lib/productResolver.d.ts +8 -10
- package/lib/productResolver.js +28 -4
- package/lib/productResolver.js.map +1 -1
- package/lib/typeDefinitions.d.ts +7 -5
- package/package.json +1 -1
- package/src/productResolver.ts +35 -13
- package/src/typeDefinitions.ts +9 -5
- package/src/productResolver.test.ts +0 -156
package/lib/productResolver.d.ts
CHANGED
|
@@ -9,17 +9,12 @@ import { InstituteData } from "./typeDefinitions";
|
|
|
9
9
|
* Three of those are also sub-flags that only apply when `employerEvents` (or the
|
|
10
10
|
* careersHub package) is switched on.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
* the
|
|
14
|
-
*
|
|
15
|
-
* skills on their dashboard that staff could not see on their profile. Wex was
|
|
16
|
-
* opt-in for staff (`workExperience &&`) and opt-out for students (`!== false`).
|
|
17
|
-
*
|
|
18
|
-
* This is the single answer. Nav, home, student surfaces and the backend all read
|
|
19
|
-
* it, so they cannot disagree about what a customer bought. Dependency-free.
|
|
12
|
+
* `parents` has no flag at all — a school has a parent database when there are
|
|
13
|
+
* parents in it — so this is a hook: the count is a query, and the answer arrives
|
|
14
|
+
* a tick after the flags do.
|
|
20
15
|
*/
|
|
21
16
|
/** The product a surface can gate on. */
|
|
22
|
-
export type ProductKey = "wex" | "network" | "events" | "skills" | "activities" | "destinations" | "alumni";
|
|
17
|
+
export type ProductKey = "wex" | "network" | "parents" | "events" | "skills" | "activities" | "destinations" | "alumni";
|
|
23
18
|
export type ResolvedProducts = Record<ProductKey, boolean> & {
|
|
24
19
|
/** Package shape, so callers stop testing `package ===` themselves. */
|
|
25
20
|
isTrust: boolean;
|
|
@@ -41,12 +36,15 @@ export type ProductResolverInput = Partial<Pick<InstituteData, "package" | "work
|
|
|
41
36
|
*
|
|
42
37
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
43
38
|
* @param {object} [options] extra context.
|
|
39
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
40
|
+
* none on its own oId, so pass its schools'.
|
|
44
41
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
45
42
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
46
43
|
* existing destinations rule.
|
|
47
44
|
* @return {ResolvedProducts} what this institute has.
|
|
48
45
|
*/
|
|
49
|
-
export declare function
|
|
46
|
+
export declare function useProductResolver(institute?: ProductResolverInput, options?: {
|
|
47
|
+
oIds?: string[];
|
|
50
48
|
trustSchools?: ProductResolverInput[];
|
|
51
49
|
}): ResolvedProducts;
|
|
52
50
|
/** Human labels, for checklists, settings and the trust product strip. */
|
package/lib/productResolver.js
CHANGED
|
@@ -1,21 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.PRODUCT_LABELS = void 0;
|
|
4
|
-
exports.
|
|
5
|
-
const
|
|
7
|
+
exports.useProductResolver = useProductResolver;
|
|
8
|
+
const react_1 = require("react");
|
|
9
|
+
const firestore_1 = require("firebase/firestore");
|
|
10
|
+
const firebaseQuery_1 = __importDefault(require("./firebase/firebaseQuery"));
|
|
11
|
+
const PRODUCT_ORDER = ["wex", "destinations", "events", "skills", "activities", "network", "parents", "alumni"];
|
|
6
12
|
/** Opt-out flag: undefined means on, only an explicit `false` switches it off. */
|
|
7
13
|
const on = (flag) => flag !== false;
|
|
14
|
+
const firebaseQuery = new firebaseQuery_1.default();
|
|
8
15
|
/**
|
|
9
16
|
* Resolve an institute's products.
|
|
10
17
|
*
|
|
11
18
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
12
19
|
* @param {object} [options] extra context.
|
|
20
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
21
|
+
* none on its own oId, so pass its schools'.
|
|
13
22
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
14
23
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
15
24
|
* existing destinations rule.
|
|
16
25
|
* @return {ResolvedProducts} what this institute has.
|
|
17
26
|
*/
|
|
18
|
-
function
|
|
27
|
+
function useProductResolver(institute, options) {
|
|
28
|
+
const [parentCount, setParentCount] = (0, react_1.useState)(0);
|
|
29
|
+
const oIds = options?.oIds || [];
|
|
30
|
+
const scope = oIds.join(",");
|
|
31
|
+
(0, react_1.useEffect)(() => {
|
|
32
|
+
if (!oIds.length) {
|
|
33
|
+
setParentCount(0);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
Promise.all(oIds.map((o) => firebaseQuery.getCount(["parents"], [(0, firestore_1.where)("oId", "==", o)])))
|
|
37
|
+
.then((counts) => setParentCount(counts.reduce((t, c) => t + c, 0)))
|
|
38
|
+
.catch(() => setParentCount(0));
|
|
39
|
+
}, [scope]);
|
|
19
40
|
const i = institute || {};
|
|
20
41
|
const pkg = i.package;
|
|
21
42
|
const isTrust = pkg === "institutes-two";
|
|
@@ -39,10 +60,12 @@ function resolveProduct(institute, options) {
|
|
|
39
60
|
// Opt-out and ungated: every institute gets the employer network unless it is
|
|
40
61
|
// explicitly switched off. Matches Institutes.tsx and the staff home today.
|
|
41
62
|
const network = on(i.network);
|
|
63
|
+
// No flag: the database exists if anyone is in it.
|
|
64
|
+
const parents = parentCount > 0;
|
|
42
65
|
const hubIds = Object.entries(i.careersHubLinks || {})
|
|
43
66
|
.filter(([, link]) => link?.status === "approved")
|
|
44
67
|
.map(([oId]) => oId);
|
|
45
|
-
const products = { wex, network, events, skills, activities, destinations, alumni };
|
|
68
|
+
const products = { wex, network, parents, events, skills, activities, destinations, alumni };
|
|
46
69
|
return {
|
|
47
70
|
...products,
|
|
48
71
|
isTrust,
|
|
@@ -61,6 +84,7 @@ exports.PRODUCT_LABELS = {
|
|
|
61
84
|
skills: "Skills",
|
|
62
85
|
activities: "Activities",
|
|
63
86
|
network: "Employer network",
|
|
87
|
+
parents: "Parent database",
|
|
64
88
|
alumni: "Alumni",
|
|
65
89
|
};
|
|
66
90
|
//# sourceMappingURL=productResolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"productResolver.js","sourceRoot":"","sources":["../src/productResolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"productResolver.js","sourceRoot":"","sources":["../src/productResolver.ts"],"names":[],"mappings":"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"}
|
package/lib/typeDefinitions.d.ts
CHANGED
|
@@ -875,6 +875,11 @@ export type RiskAssessmentFieldDef = {
|
|
|
875
875
|
type: "string" | "dropdown";
|
|
876
876
|
options?: string[];
|
|
877
877
|
};
|
|
878
|
+
export type RiskAssessmentOptions = {
|
|
879
|
+
template?: boolean;
|
|
880
|
+
columns?: boolean;
|
|
881
|
+
form?: boolean;
|
|
882
|
+
};
|
|
878
883
|
export type EmployerField = {
|
|
879
884
|
name: string;
|
|
880
885
|
label?: string;
|
|
@@ -1062,11 +1067,7 @@ export type InstituteData = {
|
|
|
1062
1067
|
riskAssessmentTemplate?: Timestamp;
|
|
1063
1068
|
riskAssessmentColumns?: RiskAssessmentFieldDef[];
|
|
1064
1069
|
riskAssessmentFormId?: string;
|
|
1065
|
-
riskAssessmentEnabled?:
|
|
1066
|
-
template?: boolean;
|
|
1067
|
-
columns?: boolean;
|
|
1068
|
-
form?: boolean;
|
|
1069
|
-
};
|
|
1070
|
+
riskAssessmentEnabled?: RiskAssessmentOptions;
|
|
1070
1071
|
privacyPolicy: Timestamp;
|
|
1071
1072
|
demo?: boolean;
|
|
1072
1073
|
emailTemplates?: {
|
|
@@ -1436,6 +1437,7 @@ export type PlacementReviewDetails = {
|
|
|
1436
1437
|
trackAttendance?: boolean;
|
|
1437
1438
|
daysEachWeek?: ("Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | "Sun")[];
|
|
1438
1439
|
riskAssessmentColumns?: RiskAssessmentFieldDef[];
|
|
1440
|
+
riskAssessmentEnabled?: RiskAssessmentOptions;
|
|
1439
1441
|
employerFields?: EmployerField[];
|
|
1440
1442
|
};
|
|
1441
1443
|
export type ProviderMatch = {
|
package/package.json
CHANGED
package/src/productResolver.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {useEffect, useState} from "react";
|
|
2
|
+
import {where} from "firebase/firestore";
|
|
3
|
+
import FirebaseQuery from "./firebase/firebaseQuery";
|
|
1
4
|
import {InstituteData} from "./typeDefinitions";
|
|
2
5
|
|
|
3
6
|
/**
|
|
@@ -10,19 +13,14 @@ import {InstituteData} from "./typeDefinitions";
|
|
|
10
13
|
* Three of those are also sub-flags that only apply when `employerEvents` (or the
|
|
11
14
|
* careersHub package) is switched on.
|
|
12
15
|
*
|
|
13
|
-
*
|
|
14
|
-
* the
|
|
15
|
-
*
|
|
16
|
-
* skills on their dashboard that staff could not see on their profile. Wex was
|
|
17
|
-
* opt-in for staff (`workExperience &&`) and opt-out for students (`!== false`).
|
|
18
|
-
*
|
|
19
|
-
* This is the single answer. Nav, home, student surfaces and the backend all read
|
|
20
|
-
* it, so they cannot disagree about what a customer bought. Dependency-free.
|
|
16
|
+
* `parents` has no flag at all — a school has a parent database when there are
|
|
17
|
+
* parents in it — so this is a hook: the count is a query, and the answer arrives
|
|
18
|
+
* a tick after the flags do.
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
21
|
/** The product a surface can gate on. */
|
|
24
22
|
export type ProductKey =
|
|
25
|
-
"wex"|"network"|"events"|"skills"|"activities"|"destinations"|"alumni";
|
|
23
|
+
"wex"|"network"|"parents"|"events"|"skills"|"activities"|"destinations"|"alumni";
|
|
26
24
|
|
|
27
25
|
export type ResolvedProducts = Record<ProductKey, boolean> & {
|
|
28
26
|
/** Package shape, so callers stop testing `package ===` themselves. */
|
|
@@ -46,25 +44,45 @@ export type ProductResolverInput = Partial<Pick<InstituteData,
|
|
|
46
44
|
"alumniManagement"|"careersHubLinks">>;
|
|
47
45
|
|
|
48
46
|
const PRODUCT_ORDER: ProductKey[] =
|
|
49
|
-
["wex", "destinations", "events", "skills", "activities", "network", "alumni"];
|
|
47
|
+
["wex", "destinations", "events", "skills", "activities", "network", "parents", "alumni"];
|
|
50
48
|
|
|
51
49
|
/** Opt-out flag: undefined means on, only an explicit `false` switches it off. */
|
|
52
50
|
const on = (flag?: boolean) => flag !== false;
|
|
53
51
|
|
|
52
|
+
const firebaseQuery = new FirebaseQuery();
|
|
53
|
+
|
|
54
54
|
/**
|
|
55
55
|
* Resolve an institute's products.
|
|
56
56
|
*
|
|
57
57
|
* @param {ProductResolverInput} [institute] the institute, or a partial of it.
|
|
58
58
|
* @param {object} [options] extra context.
|
|
59
|
+
* @param {string[]} [options.oIds] whose parent database to count. A trust holds
|
|
60
|
+
* none on its own oId, so pass its schools'.
|
|
59
61
|
* @param {ProductResolverInput[]} [options.trustSchools] schools beneath a trust.
|
|
60
62
|
* A trust shows a product when any of its schools has it, matching the nav's
|
|
61
63
|
* existing destinations rule.
|
|
62
64
|
* @return {ResolvedProducts} what this institute has.
|
|
63
65
|
*/
|
|
64
|
-
export function
|
|
66
|
+
export function useProductResolver(
|
|
65
67
|
institute?: ProductResolverInput,
|
|
66
|
-
options?: {trustSchools?: ProductResolverInput[]},
|
|
68
|
+
options?: {oIds?: string[], trustSchools?: ProductResolverInput[]},
|
|
67
69
|
): ResolvedProducts {
|
|
70
|
+
const [parentCount, setParentCount] = useState(0);
|
|
71
|
+
|
|
72
|
+
const oIds = options?.oIds || [];
|
|
73
|
+
const scope = oIds.join(",");
|
|
74
|
+
|
|
75
|
+
useEffect(() => {
|
|
76
|
+
if (!oIds.length) {
|
|
77
|
+
setParentCount(0);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
Promise.all(oIds.map((o) =>
|
|
81
|
+
firebaseQuery.getCount(["parents"], [where("oId", "==", o)])))
|
|
82
|
+
.then((counts) => setParentCount(counts.reduce((t, c) => t + c, 0)))
|
|
83
|
+
.catch(() => setParentCount(0));
|
|
84
|
+
}, [scope]);
|
|
85
|
+
|
|
68
86
|
const i = institute || {};
|
|
69
87
|
const pkg = i.package;
|
|
70
88
|
|
|
@@ -115,12 +133,15 @@ export function resolveProduct(
|
|
|
115
133
|
// explicitly switched off. Matches Institutes.tsx and the staff home today.
|
|
116
134
|
const network = on(i.network);
|
|
117
135
|
|
|
136
|
+
// No flag: the database exists if anyone is in it.
|
|
137
|
+
const parents = parentCount > 0;
|
|
138
|
+
|
|
118
139
|
const hubIds = Object.entries(i.careersHubLinks || {})
|
|
119
140
|
.filter(([, link]) => link?.status === "approved")
|
|
120
141
|
.map(([oId]) => oId);
|
|
121
142
|
|
|
122
143
|
const products: Record<ProductKey, boolean> =
|
|
123
|
-
{wex, network, events, skills, activities, destinations, alumni};
|
|
144
|
+
{wex, network, parents, events, skills, activities, destinations, alumni};
|
|
124
145
|
|
|
125
146
|
return {
|
|
126
147
|
...products,
|
|
@@ -141,5 +162,6 @@ export const PRODUCT_LABELS: Record<ProductKey, string> = {
|
|
|
141
162
|
skills: "Skills",
|
|
142
163
|
activities: "Activities",
|
|
143
164
|
network: "Employer network",
|
|
165
|
+
parents: "Parent database",
|
|
144
166
|
alumni: "Alumni",
|
|
145
167
|
};
|
package/src/typeDefinitions.ts
CHANGED
|
@@ -897,6 +897,13 @@ export type RiskAssessmentFieldDef = {
|
|
|
897
897
|
options?: string[]
|
|
898
898
|
}
|
|
899
899
|
|
|
900
|
+
// Which routes an institute lets employers use to submit a risk assessment.
|
|
901
|
+
export type RiskAssessmentOptions = {
|
|
902
|
+
template?: boolean,
|
|
903
|
+
columns?: boolean,
|
|
904
|
+
form?: boolean,
|
|
905
|
+
}
|
|
906
|
+
|
|
900
907
|
export type EmployerField = {
|
|
901
908
|
name: string,
|
|
902
909
|
label?: string,
|
|
@@ -1082,11 +1089,7 @@ export type InstituteData = {
|
|
|
1082
1089
|
riskAssessmentTemplate?: Timestamp,
|
|
1083
1090
|
riskAssessmentColumns?: RiskAssessmentFieldDef[],
|
|
1084
1091
|
riskAssessmentFormId?: string,
|
|
1085
|
-
riskAssessmentEnabled?:
|
|
1086
|
-
template?: boolean,
|
|
1087
|
-
columns?: boolean,
|
|
1088
|
-
form?: boolean,
|
|
1089
|
-
},
|
|
1092
|
+
riskAssessmentEnabled?: RiskAssessmentOptions,
|
|
1090
1093
|
privacyPolicy: Timestamp,
|
|
1091
1094
|
demo?: boolean,
|
|
1092
1095
|
emailTemplates?: {
|
|
@@ -1432,6 +1435,7 @@ export type PlacementReviewDetails = {
|
|
|
1432
1435
|
trackAttendance?: boolean,
|
|
1433
1436
|
daysEachWeek?: ("Mon"|"Tue"|"Wed"|"Thu"|"Fri"|"Sat"|"Sun")[],
|
|
1434
1437
|
riskAssessmentColumns?: RiskAssessmentFieldDef[],
|
|
1438
|
+
riskAssessmentEnabled?: RiskAssessmentOptions,
|
|
1435
1439
|
employerFields?: EmployerField[],
|
|
1436
1440
|
}
|
|
1437
1441
|
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import {resolveProduct} from "./productResolver";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The defaults are the point of these tests. Four flags are opt-out, so a refactor
|
|
5
|
-
* that "tidies" `!== false` into a truthy check would silently switch four products
|
|
6
|
-
* off for every institute that has never touched the toggle — which is most of them.
|
|
7
|
-
*/
|
|
8
|
-
describe("resolveProduct", () => {
|
|
9
|
-
describe("opt-out defaults", () => {
|
|
10
|
-
it("gives a bare institute the employer network", () => {
|
|
11
|
-
expect(resolveProduct({package: "institutes-one"}).network).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("switches the network off only on an explicit false", () => {
|
|
15
|
-
expect(resolveProduct({network: false}).network).toBe(false);
|
|
16
|
-
expect(resolveProduct({network: undefined}).network).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("turns on events, skills and activities when employerEvents is set and the sub-flags are undefined", () => {
|
|
20
|
-
const p = resolveProduct({package: "institutes-one", employerEvents: true});
|
|
21
|
-
expect(p.events).toBe(true);
|
|
22
|
-
expect(p.skills).toBe(true);
|
|
23
|
-
expect(p.activities).toBe(true);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it("lets each sub-flag be switched off independently", () => {
|
|
27
|
-
const p = resolveProduct({
|
|
28
|
-
package: "institutes-one",
|
|
29
|
-
employerEvents: true,
|
|
30
|
-
careersEvents: false,
|
|
31
|
-
trackExtracurriculars: false,
|
|
32
|
-
});
|
|
33
|
-
expect(p.events).toBe(false);
|
|
34
|
-
expect(p.activities).toBe(false);
|
|
35
|
-
expect(p.skills).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
describe("sub-flags need their parent", () => {
|
|
40
|
-
it("does not give skills or activities to a school without employerEvents", () => {
|
|
41
|
-
const p = resolveProduct({package: "institutes-one", workExperience: true});
|
|
42
|
-
expect(p.skills).toBe(false);
|
|
43
|
-
expect(p.activities).toBe(false);
|
|
44
|
-
expect(p.events).toBe(false);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("does not resurrect them from an explicit true on the sub-flag alone", () => {
|
|
48
|
-
const p = resolveProduct({
|
|
49
|
-
package: "institutes-one",
|
|
50
|
-
skillsAssessmentsProduct: true,
|
|
51
|
-
trackExtracurriculars: true,
|
|
52
|
-
});
|
|
53
|
-
expect(p.skills).toBe(false);
|
|
54
|
-
expect(p.activities).toBe(false);
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe("opt-in products", () => {
|
|
59
|
-
it("leaves wex, destinations and alumni off by default", () => {
|
|
60
|
-
const p = resolveProduct({package: "institutes-one"});
|
|
61
|
-
expect(p.wex).toBe(false);
|
|
62
|
-
expect(p.destinations).toBe(false);
|
|
63
|
-
expect(p.alumni).toBe(false);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("turns them on when explicitly true", () => {
|
|
67
|
-
const p = resolveProduct({
|
|
68
|
-
package: "institutes-one",
|
|
69
|
-
workExperience: true,
|
|
70
|
-
destinationTracking: true,
|
|
71
|
-
alumniManagement: true,
|
|
72
|
-
});
|
|
73
|
-
expect(p.wex).toBe(true);
|
|
74
|
-
expect(p.destinations).toBe(true);
|
|
75
|
-
expect(p.alumni).toBe(true);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
describe("packages", () => {
|
|
80
|
-
it("gives a careersHub events without employerEvents, but no wex or skills", () => {
|
|
81
|
-
const p = resolveProduct({package: "careersHub"});
|
|
82
|
-
expect(p.events).toBe(true);
|
|
83
|
-
expect(p.isHub).toBe(true);
|
|
84
|
-
expect(p.wex).toBe(false);
|
|
85
|
-
expect(p.skills).toBe(false);
|
|
86
|
-
expect(p.activities).toBe(false);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("does not give a careersHub school its own wex even with the flag set", () => {
|
|
90
|
-
const p = resolveProduct({package: "careersSchool", workExperience: true});
|
|
91
|
-
expect(p.wex).toBe(false);
|
|
92
|
-
expect(p.isHubSchool).toBe(true);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it("rolls a trust's products up from its schools", () => {
|
|
96
|
-
const p = resolveProduct({package: "institutes-two"}, {
|
|
97
|
-
trustSchools: [
|
|
98
|
-
{destinationTracking: true},
|
|
99
|
-
{employerEvents: true, careersEvents: false},
|
|
100
|
-
],
|
|
101
|
-
});
|
|
102
|
-
expect(p.isTrust).toBe(true);
|
|
103
|
-
expect(p.destinations).toBe(true);
|
|
104
|
-
expect(p.skills).toBe(true); // sub-flag undefined at the school
|
|
105
|
-
expect(p.events).toBe(false); // explicitly off at the only events school
|
|
106
|
-
expect(p.wex).toBe(false);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("does not roll schools up for a non-trust", () => {
|
|
110
|
-
const p = resolveProduct({package: "institutes-one"}, {
|
|
111
|
-
trustSchools: [{destinationTracking: true}],
|
|
112
|
-
});
|
|
113
|
-
expect(p.destinations).toBe(false);
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe("hub links", () => {
|
|
118
|
-
it("counts only approved links", () => {
|
|
119
|
-
const p = resolveProduct({
|
|
120
|
-
careersHubLinks: {
|
|
121
|
-
hubA: {exists: true, invited: "2026-01-01", status: "approved"},
|
|
122
|
-
hubB: {exists: true, invited: "2026-01-01", status: "invited"},
|
|
123
|
-
hubC: {exists: true, invited: "2026-01-01", status: "declined"},
|
|
124
|
-
},
|
|
125
|
-
});
|
|
126
|
-
expect(p.hubLinked).toBe(true);
|
|
127
|
-
expect(p.hubIds).toEqual(["hubA"]);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it("is not hub-linked with no links", () => {
|
|
131
|
-
expect(resolveProduct({}).hubLinked).toBe(false);
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe("enabled", () => {
|
|
136
|
-
it("lists products in display order and drives the layout mode", () => {
|
|
137
|
-
const skillsOnly = resolveProduct({
|
|
138
|
-
package: "institutes-one",
|
|
139
|
-
employerEvents: true,
|
|
140
|
-
careersEvents: false,
|
|
141
|
-
network: false,
|
|
142
|
-
});
|
|
143
|
-
expect(skillsOnly.enabled).toEqual(["skills", "activities"]);
|
|
144
|
-
|
|
145
|
-
const fullStack = resolveProduct({
|
|
146
|
-
package: "institutes-one",
|
|
147
|
-
workExperience: true,
|
|
148
|
-
employerEvents: true,
|
|
149
|
-
destinationTracking: true,
|
|
150
|
-
alumniManagement: true,
|
|
151
|
-
});
|
|
152
|
-
expect(fullStack.enabled).toEqual(
|
|
153
|
-
["wex", "destinations", "events", "skills", "activities", "network", "alumni"]);
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
});
|