Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/program-boilerplate/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist
dist
*.tsbuildinfo
8 changes: 8 additions & 0 deletions packages/program-boilerplate/.oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"ignorePatterns": [],
"printWidth": 80,
"sortImports": {
"newlinesBetween": false
}
}
16 changes: 16 additions & 0 deletions packages/program-boilerplate/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["typescript", "unicorn", "oxc"],
"categories": {
"correctness": "error",
"suspicious": "error"
},
"options": {
"typeAware": true,
"typeCheck": true
},
"rules": {},
"env": {
"builtin": true
}
}
30 changes: 19 additions & 11 deletions packages/program-boilerplate/__tests__/jsonata.test.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,45 @@
import * as assert from "node:assert";
import { describe, test } from "node:test";
import jsonata from "jsonata";
import { safeJsonata, timeboxExpression } from "../src/jsonata";
import { safeJsonata, timeboxExpression } from "../src/jsonata.ts";

// oxlint-disable typescript/no-floating-promises

describe("#timeboxExpression", () => {
const infExpr = jsonata("( $inf := function(){$inf()}; $inf())");

test("infinite loops throw error", () => {
test("infinite loops throw error", { timeout: 7000 }, () => {
timeboxExpression(infExpr);

let error: any;
expect(() => {
assert.throws(() => {
try {
infExpr.evaluate(undefined);
} catch (e) {
error = e;
throw e;
}
}).toThrow();
expect(error!.code === "U1001" || error!.code === "U1002").toBe(true);
}, 7000);
});

assert.strictEqual(
error!.code === "U1001" || error!.code === "U1002",
true,
);
});
});

describe("#safeJsonata", () => {
const infExpr = "( $inf := function(){$inf()}; $inf())";

const expr = "( event.key = 'purchase' ? 111 )";
const input = { event: { key: "purchase" } };
test("infinite loops do not throw, but still exit", () => {
expect(() => {
test("infinite loops do not throw, but still exit", { timeout: 7000 }, () => {
assert.doesNotThrow(() => {
safeJsonata(infExpr, undefined);
}).not.toThrow();
}, 7000);
});
});

test("jsonata is evaluated as normal", () => {
expect(safeJsonata(expr, input)).toBe(111);
assert.strictEqual(safeJsonata(expr, input), 111);
});
});
19 changes: 8 additions & 11 deletions packages/program-boilerplate/__tests__/logger.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { getLogger, setLogLevel } from "../src/logger";
import * as assert from "node:assert";
import { describe, test } from "node:test";
import { getLogger } from "../src/logger.ts";

// oxlint-disable typescript/no-floating-promises

const logger = getLogger("notice");
describe("#getLogger", () => {
test("first call initializes the logger at the given level", () => {
expect(logger);
expect(logger.level).toBe("notice");
assert.ok(logger);
assert.strictEqual(logger.level, "notice");
});

test("logger is only initialized once", () => {
expect(getLogger("warn")).toBe(logger);
});
});

describe("#setLogLevel", () => {
test("sets the log level of an initialized logger", () => {
setLogLevel("crit");
expect(logger.level).toBe("crit");
assert.strictEqual(getLogger("warn"), logger);
});
});
76 changes: 40 additions & 36 deletions packages/program-boilerplate/__tests__/transaction.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { RewardData } from "@saasquatch/schema/types/ProgramTransaction";
import * as assert from "node:assert";
import { beforeEach, describe, test } from "node:test";
import type { RewardData } from "@saasquatch/schema/types/ProgramTransaction/index.d.ts";
import {
nonRewardEmailQueryForNonReferralPrograms,
nonRewardEmailQueryForReferralPrograms,
rewardEmailQuery,
rewardEmailQueryForNonReferralPrograms,
} from "../src/queries";
import Transaction from "../src/transaction";
import { Referral } from "../src/types/saasquatch";
} from "../src/queries.ts";
import Transaction from "../src/transaction.ts";
import type { Referral } from "../src/types/saasquatch.ts";

// oxlint-disable typescript/no-floating-promises

describe("Transaction class", () => {
const messageType: "PROGRAM_TRIGGER" = "PROGRAM_TRIGGER";
const messageType = "PROGRAM_TRIGGER" as const;
const testContext = {
body: {
messageType,
Expand Down Expand Up @@ -106,7 +110,7 @@ describe("Transaction class", () => {
describe("#fireProgramEvalAnalytics", () => {
test("evalAnalytic is pushed to analytics", () => {
transaction.fireProgramEvalAnalytics(testUser, "ACQUISITION");
expect(transaction.analytics).toStrictEqual([
assert.deepStrictEqual(transaction.analytics, [
{
eventType: "PROGRAM_EVALUATED",
data: {
Expand All @@ -130,10 +134,10 @@ describe("Transaction class", () => {
"testAnalyticsKey",
"testDedupKey",
now,
false
false,
);

expect(transaction.analytics).toStrictEqual([
assert.deepStrictEqual(transaction.analytics, [
{
eventType: "PROGRAM_GOAL",
data: {
Expand All @@ -156,7 +160,7 @@ describe("Transaction class", () => {
const rewardKey = "testRewardKey123";
test("createReward mutation is pushed to mutations", () => {
const { rewardId } = transaction.generateSimpleReward(rewardKey);
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "CREATE_REWARD",
data: {
Expand Down Expand Up @@ -192,7 +196,7 @@ describe("Transaction class", () => {
unit: "CAD",
},
});
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "CREATE_REWARD",
data: {
Expand Down Expand Up @@ -223,7 +227,7 @@ describe("Transaction class", () => {
const emailKey = "testEmailKey2344";
test("sendEmail mutation is pushed to mutations (with reward)", () => {
transaction.generateSimpleEmail({ emailKey, user: testUser, rewardId });
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "SEND_EMAIL",
data: {
Expand All @@ -247,7 +251,7 @@ describe("Transaction class", () => {

test("sendEmail mutation is pushed to mutations (without reward)", () => {
transaction.generateSimpleEmail({ emailKey, user: testUser });
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "SEND_EMAIL",
data: {
Expand Down Expand Up @@ -280,7 +284,7 @@ describe("Transaction class", () => {
referralId,
rewardId,
});
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "SEND_EMAIL",
data: {
Expand Down Expand Up @@ -312,7 +316,7 @@ describe("Transaction class", () => {
user: testUser,
referralId,
});
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "SEND_EMAIL",
data: {
Expand Down Expand Up @@ -348,23 +352,23 @@ describe("Transaction class", () => {
user: testUser,
});

expect(transaction.mutations.length).toBe(2);
assert.deepStrictEqual(transaction.mutations.length, 2);

const [rewardMutation, emailMutation] = transaction.mutations;
expect(rewardMutation.type).toBe("CREATE_REWARD");

// oxlint-disable-next-line typescript/no-unsafe-type-assertion
const mut = rewardMutation.data as RewardData;

expect(mut.user).toStrictEqual({
assert.deepStrictEqual(rewardMutation.type, "CREATE_REWARD");
assert.deepStrictEqual(mut.user, {
id: "referrerID",
accountId: "referrerACCOUNTID",
});
expect(mut.key).toBe(rewardKey);
expect(mut.user).toStrictEqual({
assert.deepStrictEqual(mut.key, rewardKey);
assert.deepStrictEqual(mut.user, {
id: "referrerID",
accountId: "referrerACCOUNTID",
});
expect(emailMutation).toStrictEqual({
assert.deepStrictEqual(emailMutation, {
type: "SEND_EMAIL",
data: {
user: {
Expand Down Expand Up @@ -406,36 +410,36 @@ describe("Transaction class", () => {
},
});

expect(transaction.mutations.length).toBe(2);
assert.deepStrictEqual(transaction.mutations.length, 2);

const [rewardMutation, emailMutation] = transaction.mutations;
expect(rewardMutation.type).toBe("CREATE_REWARD");

// oxlint-disable-next-line typescript/no-unsafe-type-assertion
const mut = rewardMutation.data as RewardData;

expect(mut.user).toStrictEqual({
assert.deepStrictEqual(rewardMutation.type, "CREATE_REWARD");
assert.deepStrictEqual(mut.user, {
id: "referrerID",
accountId: "referrerACCOUNTID",
});
expect(mut.key).toBe(rewardKey);
expect(mut.referralId).toBe(referralId);
expect(mut.status).toBe(undefined);
expect(mut.rewardSource).toBe(undefined);
expect(mut.userEvent).toBe(undefined);
expect(mut.overrideProperties).toStrictEqual({
assert.deepStrictEqual(mut.key, rewardKey);
assert.deepStrictEqual(mut.referralId, referralId);
assert.deepStrictEqual(mut.status, undefined);
assert.deepStrictEqual(mut.rewardSource, undefined);
assert.deepStrictEqual(mut.userEvent, undefined);
assert.deepStrictEqual(mut.overrideProperties, {
dateExpires: ts,
});
expect(mut.dynamicProperties).toStrictEqual({
assert.deepStrictEqual(mut.dynamicProperties, {
type: "CREDIT",
assignedCredit: 2000,
unit: "CAD",
});
expect(mut.user).toStrictEqual({
assert.deepStrictEqual(mut.user, {
id: "referrerID",
accountId: "referrerACCOUNTID",
});

expect(emailMutation).toStrictEqual({
assert.deepStrictEqual(emailMutation, {
type: "SEND_EMAIL",
data: {
user: {
Expand Down Expand Up @@ -498,7 +502,7 @@ describe("Transaction class", () => {
];

transaction.generateRefunds();
expect(transaction.mutations).toStrictEqual([
assert.deepStrictEqual(transaction.mutations, [
{
type: "MODERATE_GRAPH_NODES",
data: {
Expand Down Expand Up @@ -573,7 +577,7 @@ describe("Transaction class", () => {
},
];

expect(transaction.toJson()).toStrictEqual({
assert.deepStrictEqual(transaction.toJson(), {
mutations: [
{
type: "MODERATE_GRAPH_NODES",
Expand Down
Loading