File size: 4,979 Bytes
3d61b8f
 
701a199
8bcc42c
3d61b8f
 
 
 
 
8bcc42c
3d61b8f
 
 
 
 
8bcc42c
3d61b8f
 
 
 
701a199
8bcc42c
3d61b8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701a199
8bcc42c
 
3d61b8f
 
 
8bcc42c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
701a199
5a58109
 
701a199
8bcc42c
 
3d61b8f
8bcc42c
3d61b8f
 
 
 
 
 
 
 
 
 
 
 
8bcc42c
3d61b8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5a58109
8bcc42c
5a58109
3d61b8f
 
5a58109
 
 
 
 
3d61b8f
 
 
 
5a58109
3d61b8f
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import {
  __resetCustomerMemoryForTests,
  getCustomerMemoryScope,
  getPotsEstimatorCarryover,
  getRapidRouterDraftCarryover,
  getSmartProfile,
  listResumeWorkCards,
  mergeSmartProfile,
  setCustomerMemoryScope,
  setPotsEstimatorCarryover,
  setRapidRouterDraftCarryover,
  upsertResumeWorkCard,
} from "./customerMemory";

const LEGACY_CUSTOMER_MEMORY_KEY = "masters_toolkit_customer_memory_v1";
const store = new Map<string, string>();

beforeEach(() => {
  store.clear();
  __resetCustomerMemoryForTests();
  setCustomerMemoryScope("anonymous");
  Object.defineProperty(window, "localStorage", {
    configurable: true,
    value: {
      getItem: (key: string) => (store.has(key) ? String(store.get(key)) : null),
      setItem: (key: string, value: string) => {
        store.set(key, String(value));
      },
      removeItem: (key: string) => {
        store.delete(key);
      },
      clear: () => {
        store.clear();
      },
    },
  });
});

afterEach(() => {
  __resetCustomerMemoryForTests();
  setCustomerMemoryScope("anonymous");
  store.clear();
});

describe("customerMemory", () => {
  it("isolates stored customer data by scoped user identity", () => {
    store.set(
      LEGACY_CUSTOMER_MEMORY_KEY,
      JSON.stringify({
        profile: { companyName: "Legacy Shared Customer" },
      })
    );

    setCustomerMemoryScope(" James@Verizon.com ");
    expect(getCustomerMemoryScope()).toBe("james@verizon.com");
    expect(getSmartProfile()).toBeNull();
    mergeSmartProfile({ companyName: "John Q", email: "johnq@example.com" });
    setRapidRouterDraftCarryover({ customerName: "John Q", qty: 2 }, "James draft");
    upsertResumeWorkCard({
      id: "rapid_router:last_order_draft",
      title: "Repeat last Rapid Router order draft",
      source: "rapid_router",
      actionCommand: "navigate:rapid_router_draft",
    });

    setCustomerMemoryScope("timmy@verizon.com");
    expect(getSmartProfile()).toBeNull();
    expect(getRapidRouterDraftCarryover()).toBeNull();
    expect(listResumeWorkCards()).toEqual([]);

    mergeSmartProfile({ companyName: "Different Customer" });
    expect(getSmartProfile()?.companyName).toBe("Different Customer");

    setCustomerMemoryScope("james@verizon.com");
    expect(getSmartProfile()?.companyName).toBe("John Q");
    expect(getRapidRouterDraftCarryover()?.summary).toBe("James draft");
    expect(listResumeWorkCards()[0]?.id).toBe("rapid_router:last_order_draft");
    const persisted = JSON.parse(store.get("masters_toolkit_customer_memory_v2:james@verizon.com") || "{}");
    expect(persisted.profile?.companyName).toBe("John Q");
    expect(persisted.carryover?.rapidRouterDraft?.summary).toBe("James draft");
    expect(Array.isArray(persisted.cards)).toBe(true);
  });

  it("merges and returns smart profile fields", () => {
    setCustomerMemoryScope("owner@example.com");
    mergeSmartProfile({ companyName: "Acme", city: "Miami", state: "fl", zip: "33127-1000" });
    mergeSmartProfile({ contactName: "Pat", email: "pat@example.com" });
    const profile = getSmartProfile();
    expect(profile?.companyName).toBe("Acme");
    expect(profile?.city).toBe("Miami");
    expect(profile?.state).toBe("FL");
    expect(profile?.zip).toBe("33127");
    expect(profile?.contactName).toBe("Pat");
    expect(profile?.email).toBe("pat@example.com");
  });

  it("stores and sorts resume cards by recency", () => {
    setCustomerMemoryScope("owner@example.com");
    upsertResumeWorkCard({
      id: "older",
      title: "Older card",
      source: "knowledgebase",
      actionCommand: "router_helper:open",
      updatedAt: "2026-03-01T00:00:00.000Z",
    });
    upsertResumeWorkCard({
      id: "newer",
      title: "Newer card",
      source: "rapid_router",
      actionCommand: "navigate:rapid_router_draft",
      updatedAt: "2026-03-02T00:00:00.000Z",
    });
    const cards = listResumeWorkCards();
    expect(cards[0]?.id).toBe("newer");
    expect(cards[1]?.id).toBe("older");
  });

  it("persists customer carryover and profile data across a reload", () => {
    setCustomerMemoryScope("owner@example.com");
    mergeSmartProfile({ companyName: "Acme", city: "Miami" });
    setPotsEstimatorCarryover({ companyName: "Acme", totalLines: 12 }, "Acme carryover");
    setRapidRouterDraftCarryover({ customerName: "Acme", qty: 3 }, "Acme order");

    __resetCustomerMemoryForTests();

    expect(getSmartProfile()?.companyName).toBe("Acme");
    expect(getSmartProfile()?.city).toBe("Miami");
    expect(getPotsEstimatorCarryover()?.summary).toBe("Acme carryover");
    expect(getRapidRouterDraftCarryover()?.summary).toBe("Acme order");
    expect((getPotsEstimatorCarryover()?.payload || {}).companyName).toBe("Acme");
    expect((getRapidRouterDraftCarryover()?.payload || {}).qty).toBe(3);
    expect(store.get("masters_toolkit_customer_memory_v2:owner@example.com")).toContain("Acme");
  });
});