diff --git a/api/__tests__/click-event.test.ts b/api/__tests__/click-event.test.ts index 926537a..24be051 100644 --- a/api/__tests__/click-event.test.ts +++ b/api/__tests__/click-event.test.ts @@ -1,4 +1,4 @@ -import { afterAll, beforeAll, describe, expect, test } from '@jest/globals'; +import { afterAll, beforeAll, describe, expect, test, afterEach } from '@jest/globals'; import request, { Test } from "supertest"; import { api } from "@/netlify/functions/api"; import { Project } from '@/src/utils/types'; @@ -6,6 +6,7 @@ import { deleteProjectById } from '@/src/actions/project'; import { Server, IncomingMessage, ServerResponse } from 'http'; import TestAgent from 'supertest/lib/agent'; import { MongoMemoryServer } from 'mongodb-memory-server'; +import { deleteClickEvents, getClickEvents } from '@/src/actions/click-event'; let testProject: Project | null = null; let server: Server; @@ -39,12 +40,21 @@ describe("/api/events/click-event", () => { userId: "exampleUserId" }; + afterEach(async () => { + // Clean up click events + await deleteClickEvents(); + }) + test("Create new click event with valid client token", async () => { const response = await agent .post("/api/events/click-event") .set("clienttoken", testProject?.clientApiKey as string) .send(clickEventProperties); expect(response.status).toBe(200); + + const events = await getClickEvents(); + expect(events.length).toEqual(1); + }); test("Create new click event without valid client token", async () => { @@ -53,6 +63,10 @@ describe("/api/events/click-event", () => { .set("clienttoken", "invalid client token") .send(clickEventProperties); expect(response.status).toBe(403); + + + const events = await getClickEvents(); + expect(events.length).toEqual(0); }); }); }); diff --git a/api/src/actions/click-event.ts b/api/src/actions/click-event.ts index 7e99bd9..732aec3 100644 --- a/api/src/actions/click-event.ts +++ b/api/src/actions/click-event.ts @@ -1,11 +1,11 @@ -import { ClickEvent } from "@/src/utils/types"; +import { ClickEvent, EventCategories, EventSubcategories } from "@/src/utils/types"; import { dbConnect } from "@/src/utils/db-connect"; import { ClickEventModel } from "@/src/models/click-event"; import ProjectModel from "@/src/models/project"; export const createClickEvent = async (event: Partial) => { await dbConnect(); - const createdEvent = await ClickEventModel.create(event); + const createdEvent = await ClickEventModel.create({ ...event, category: EventCategories.INTERACTION, subcategory: EventSubcategories.CLICK }); return createdEvent; } diff --git a/api/src/actions/custom-event.ts b/api/src/actions/custom-event.ts index 6ea7266..e0b1a8a 100644 --- a/api/src/actions/custom-event.ts +++ b/api/src/actions/custom-event.ts @@ -1,4 +1,4 @@ -import { CustomEventType } from "@/src/utils/types"; +import { CustomEventType, EventCategories } from "@/src/utils/types"; import { dbConnect } from "@/src/utils/db-connect"; import CustomEventTypeModel from "@/src/models/custom-event-type"; import CustomEvent from "@/src/models/custom-event"; @@ -17,7 +17,13 @@ export const createCustomEvent = async (projectId: string, eventTypeId: string, && Object.keys(typeProperties).every(k => properties.hasOwnProperty(k))) { return null; } - const createdEvent = await CustomEvent.create({ projectId, eventTypeId, properties }); + const createdEvent = await CustomEvent.create({ + projectId, + eventTypeId, + properties, + category: eventType.category, + subcategory: eventType.subcategory + }); return createdEvent; } //one function to get eventTypeId, then this paginated method diff --git a/api/src/actions/input-event.ts b/api/src/actions/input-event.ts index 8a2afc6..12cd1e0 100644 --- a/api/src/actions/input-event.ts +++ b/api/src/actions/input-event.ts @@ -1,11 +1,11 @@ -import { InputEvent } from "@/src/utils/types"; +import { EventCategories, EventSubcategories, InputEvent } from "@/src/utils/types"; import { dbConnect } from "@/src/utils/db-connect"; import { InputEventModel } from "@/src/models/input-event"; import ProjectModel from "@/src/models/project"; export const createInputEvent = async (event: Partial) => { await dbConnect(); - const createdEvent = await InputEventModel.create(event); + const createdEvent = await InputEventModel.create({ ...event, category: EventCategories.INTERACTION, subcategory: EventSubcategories.INPUT }); return createdEvent; } diff --git a/api/src/actions/visit-event.ts b/api/src/actions/visit-event.ts index 8c70e6d..27994f0 100644 --- a/api/src/actions/visit-event.ts +++ b/api/src/actions/visit-event.ts @@ -1,11 +1,11 @@ -import { VisitEvent } from "@/src/utils/types"; +import { EventCategories, EventSubcategories, VisitEvent } from "@/src/utils/types"; import { dbConnect } from "@/src/utils/db-connect"; import { VisitEventModel } from "@/src/models/visit-event"; import Project from "@/src/models/project"; export const createVisitEvent = async (event: Partial) => { await dbConnect(); - const createdEvent = await VisitEventModel.create(event); + const createdEvent = await VisitEventModel.create({ ...event, category: EventCategories.ACTIVITY, subcategory: EventSubcategories.VISIT }); return createdEvent; } @@ -15,6 +15,7 @@ export const getVisitEvents = async (date?: Date) => { const events = await VisitEventModel.find({ createdAt: { $gte: fromDate } }) return events } + export const paginatedGetVisitEvents = async (afterDate: Date, afterID: string, limit: number, projectName: String) => { await dbConnect(); const project = await Project.findOne({ projectName: projectName }) diff --git a/api/src/controllers/events/click-event.ts b/api/src/controllers/events/click-event.ts index 75e1d09..133d9d8 100644 --- a/api/src/controllers/events/click-event.ts +++ b/api/src/controllers/events/click-event.ts @@ -22,8 +22,6 @@ const clickEventRoute = APIWrapper({ } const event: Partial = { projectId: project._id, - category: EventCategories.INTERACTION, - subcategory: EventSubcategories.CLICK, eventProperties: { objectId, userId diff --git a/api/src/models/custom-event.ts b/api/src/models/custom-event.ts index f9e1d1e..0716bba 100644 --- a/api/src/models/custom-event.ts +++ b/api/src/models/custom-event.ts @@ -1,22 +1,13 @@ -import mongoose, { Schema } from "mongoose"; -import { CustomEvent } from "@/src/utils/types"; -import ProjectModel from "@/src/models/project"; +import mongoose, { CallbackError, Schema } from "mongoose"; +import { BaseEvent, CustomEvent, EventCategories } from "@/src/utils/types"; import CustomEventTypeModel from "@/src/models/custom-event-type"; -export const CustomEventSchema = new mongoose.Schema({ - subcategory: { - type: String, - required: true, - }, + +const CustomEventSchema = new Schema({ properties: { type: Schema.Types.Mixed, required: true }, - projectId: { - type: Schema.Types.ObjectId, - required: true, - ref: ProjectModel.modelName - }, eventTypeId: { type: Schema.Types.ObjectId, required: true, @@ -24,6 +15,13 @@ export const CustomEventSchema = new mongoose.Schema({ } }, { timestamps: true }); +CustomEventSchema.pre("save", async function (this: Document & CustomEvent, next: (err?: CallbackError) => void) { + if (!this.category) { + this.category = EventCategories.CUSTOM; + } + next(); +}); + const CustomEventModel = (mongoose.models.CustomEvent as mongoose.Model) || mongoose.model("CustomEvent", CustomEventSchema); diff --git a/api/src/utils/types.ts b/api/src/utils/types.ts index a5fd577..626cb5a 100644 --- a/api/src/utils/types.ts +++ b/api/src/utils/types.ts @@ -54,11 +54,9 @@ export interface CustomEventType { projectId: string | Types.ObjectId; } -export interface CustomEvent { +export interface CustomEvent extends BaseEvent { _id: string | Types.ObjectId; - projectId: string | Types.ObjectId; eventTypeId: string | Types.ObjectId; - subcategory: string; properties: string[] | Types.Array; } @@ -98,6 +96,7 @@ export interface InternalResponseData { export enum EventCategories { INTERACTION = "Interaction", ACTIVITY = "Activity", + CUSTOM = "Custom" } export enum EventSubcategories {