Skip to content

Commit 8cda9e9

Browse files
new test and sign in test fixes
1 parent c09dd67 commit 8cda9e9

File tree

2 files changed

+239
-1
lines changed

2 files changed

+239
-1
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import Sinon from 'sinon';
2+
import { expect } from 'chai';
3+
import { configureStore } from './atlas-ai-store';
4+
import type { PreferencesAccess } from 'compass-preferences-model';
5+
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
6+
import {
7+
atlasAiServiceOptedIn,
8+
attemptId,
9+
AttemptStateMap,
10+
cancelOptIn,
11+
closeOptInModal,
12+
optIn,
13+
optIntoGenAIWithModalPrompt,
14+
} from './atlas-optin-reducer';
15+
16+
describe('atlasOptInReducer', function () {
17+
const sandbox = Sinon.createSandbox();
18+
let mockPreferences: PreferencesAccess;
19+
20+
beforeEach(async function () {
21+
mockPreferences = await createSandboxFromDefaultPreferences();
22+
});
23+
24+
afterEach(function () {
25+
sandbox.reset();
26+
});
27+
28+
describe('optIn', function () {
29+
it('should check authenticated state and set state to success if already authenticated', async function () {
30+
const mockAtlasService = {
31+
optIn: sandbox.stub().resolves({ sub: '1234' }),
32+
};
33+
const store = configureStore({
34+
atlasAuthService: mockAtlasService as any,
35+
atlasAiService: mockAtlasService as any,
36+
preferences: mockPreferences,
37+
});
38+
39+
expect(store.getState()).to.have.nested.property('state', 'initial');
40+
void store.dispatch(atlasAiServiceOptedIn());
41+
await store.dispatch(optIn());
42+
expect(mockAtlasService.optIn).not.to.have.been.called;
43+
expect(store.getState()).to.have.nested.property('state', 'success');
44+
});
45+
46+
it('should start opt in, and set state to success', async function () {
47+
const mockAtlasService = {
48+
optIn: sandbox.stub().resolves({ sub: '1234' }),
49+
};
50+
const store = configureStore({
51+
atlasAuthService: mockAtlasService as any,
52+
atlasAiService: mockAtlasService as any,
53+
preferences: mockPreferences,
54+
});
55+
56+
expect(store.getState()).to.have.nested.property('state', 'initial');
57+
void store.dispatch(optIntoGenAIWithModalPrompt()).catch(() => {});
58+
await store.dispatch(optIn());
59+
expect(mockAtlasService.optIn).to.have.been.calledOnce;
60+
expect(store.getState()).to.have.nested.property('state', 'success');
61+
});
62+
63+
it('should fail opt in if opt in failed', async function () {
64+
const mockAtlasService = {
65+
optIn: sandbox.stub().rejects(new Error('Pineapples!')),
66+
};
67+
const store = configureStore({
68+
atlasAuthService: mockAtlasService as any,
69+
atlasAiService: mockAtlasService as any,
70+
preferences: mockPreferences,
71+
});
72+
73+
void store.dispatch(optIntoGenAIWithModalPrompt()).catch(() => {});
74+
const optInPromise = store.dispatch(optIn());
75+
// Avoid unhandled rejections.
76+
AttemptStateMap.get(attemptId)?.promise.catch(() => {});
77+
await optInPromise;
78+
expect(mockAtlasService.optIn).to.have.been.calledOnce;
79+
expect(store.getState()).to.have.nested.property('state', 'error');
80+
});
81+
});
82+
83+
describe('cancelOptIn', function () {
84+
it('should do nothing if no opt in is in progress', function () {
85+
const store = configureStore({
86+
atlasAuthService: {} as any,
87+
atlasAiService: {} as any,
88+
preferences: mockPreferences,
89+
});
90+
expect(store.getState()).to.have.nested.property('state', 'initial');
91+
store.dispatch(cancelOptIn());
92+
expect(store.getState()).to.have.nested.property('state', 'initial');
93+
});
94+
95+
it('should cancel opt in if opt in is in progress', async function () {
96+
const mockAtlasService = {
97+
optIn: sandbox
98+
.stub()
99+
.callsFake(({ signal }: { signal: AbortSignal }) => {
100+
return new Promise((resolve, reject) => {
101+
signal.addEventListener('abort', () => {
102+
reject(signal.reason);
103+
});
104+
});
105+
}),
106+
};
107+
const store = configureStore({
108+
atlasAuthService: mockAtlasService as any,
109+
atlasAiService: mockAtlasService as any,
110+
preferences: mockPreferences,
111+
});
112+
113+
void store.dispatch(optIntoGenAIWithModalPrompt()).catch(() => {});
114+
115+
await Promise.all([
116+
store.dispatch(optIn()),
117+
store.dispatch(cancelOptIn()),
118+
]);
119+
expect(store.getState()).to.have.nested.property('state', 'canceled');
120+
});
121+
});
122+
123+
describe('optIntoAtlasWithModalPrompt', function () {
124+
it('should resolve when user finishes opt in with prompt flow', async function () {
125+
const mockAtlasService = {
126+
optIn: sandbox.stub().resolves({ sub: '1234' }),
127+
};
128+
const store = configureStore({
129+
atlasAuthService: mockAtlasService as any,
130+
atlasAiService: mockAtlasService as any,
131+
preferences: mockPreferences,
132+
});
133+
134+
const optInPromise = store.dispatch(optIntoGenAIWithModalPrompt());
135+
await store.dispatch(optIn());
136+
await optInPromise;
137+
138+
expect(store.getState()).to.have.property('state', 'success');
139+
});
140+
141+
it('should reject if opt in flow fails', async function () {
142+
const mockAtlasService = {
143+
optIn: sandbox.stub().rejects(new Error('Whoops!')),
144+
};
145+
const store = configureStore({
146+
atlasAuthService: mockAtlasService as any,
147+
atlasAiService: mockAtlasService as any,
148+
preferences: mockPreferences,
149+
});
150+
151+
const optInPromise = store.dispatch(optIntoGenAIWithModalPrompt());
152+
await store.dispatch(optIn());
153+
154+
try {
155+
await optInPromise;
156+
throw new Error('Expected optInPromise to throw');
157+
} catch (err) {
158+
expect(err).to.have.property('message', 'Whoops!');
159+
}
160+
161+
expect(store.getState()).to.have.property('state', 'error');
162+
});
163+
164+
it('should reject if user dismissed the modal', async function () {
165+
const mockAtlasService = {
166+
optIn: sandbox.stub().resolves({ sub: '1234' }),
167+
};
168+
const store = configureStore({
169+
atlasAuthService: mockAtlasService as any,
170+
atlasAiService: mockAtlasService as any,
171+
preferences: mockPreferences,
172+
});
173+
174+
const optInPromise = store.dispatch(optIntoGenAIWithModalPrompt());
175+
store.dispatch(closeOptInModal(new Error('This operation was aborted')));
176+
177+
try {
178+
await optInPromise;
179+
throw new Error('Expected optInPromise to throw');
180+
} catch (err) {
181+
expect(err).to.have.property('message', 'This operation was aborted');
182+
}
183+
184+
expect(store.getState()).to.have.property('state', 'canceled');
185+
});
186+
187+
it('should reject if provided signal was aborted', async function () {
188+
const mockAtlasService = {
189+
optIn: sandbox.stub().resolves({ sub: '1234' }),
190+
};
191+
const store = configureStore({
192+
atlasAuthService: mockAtlasService as any,
193+
atlasAiService: mockAtlasService as any,
194+
preferences: mockPreferences,
195+
});
196+
197+
const c = new AbortController();
198+
const optInPromise = store.dispatch(
199+
optIntoGenAIWithModalPrompt({ signal: c.signal })
200+
);
201+
c.abort(new Error('Aborted from outside'));
202+
203+
try {
204+
await optInPromise;
205+
throw new Error('Expected optInPromise to throw');
206+
} catch (err) {
207+
expect(err).to.have.property('message', 'Aborted from outside');
208+
}
209+
210+
expect(store.getState()).to.have.property('state', 'canceled');
211+
});
212+
});
213+
});

packages/compass-generative-ai/src/store/atlas-signin-reducer.spec.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@ import {
1010
closeSignInModal,
1111
atlasServiceSignedIn,
1212
} from './atlas-signin-reducer';
13-
import { configureStore } from './atlas-signin-store';
13+
import { configureStore } from './atlas-ai-store';
14+
import type { PreferencesAccess } from 'compass-preferences-model';
15+
import { createSandboxFromDefaultPreferences } from 'compass-preferences-model';
1416

1517
describe('atlasSignInReducer', function () {
1618
const sandbox = Sinon.createSandbox();
19+
let mockPreferences: PreferencesAccess;
20+
21+
beforeEach(async function () {
22+
mockPreferences = await createSandboxFromDefaultPreferences();
23+
});
1724

1825
afterEach(function () {
1926
sandbox.reset();
@@ -26,6 +33,8 @@ describe('atlasSignInReducer', function () {
2633
};
2734
const store = configureStore({
2835
atlasAuthService: mockAtlasService as any,
36+
atlasAiService: mockAtlasService as any,
37+
preferences: mockPreferences,
2938
});
3039

3140
expect(store.getState()).to.have.nested.property('state', 'initial');
@@ -41,6 +50,8 @@ describe('atlasSignInReducer', function () {
4150
};
4251
const store = configureStore({
4352
atlasAuthService: mockAtlasService as any,
53+
atlasAiService: mockAtlasService as any,
54+
preferences: mockPreferences,
4455
});
4556

4657
expect(store.getState()).to.have.nested.property('state', 'initial');
@@ -56,6 +67,8 @@ describe('atlasSignInReducer', function () {
5667
};
5768
const store = configureStore({
5869
atlasAuthService: mockAtlasService as any,
70+
atlasAiService: mockAtlasService as any,
71+
preferences: mockPreferences,
5972
});
6073

6174
void store.dispatch(signIntoAtlasWithModalPrompt()).catch(() => {});
@@ -72,6 +85,8 @@ describe('atlasSignInReducer', function () {
7285
it('should do nothing if no sign in is in progress', function () {
7386
const store = configureStore({
7487
atlasAuthService: {} as any,
88+
atlasAiService: {} as any,
89+
preferences: mockPreferences,
7590
});
7691
expect(store.getState()).to.have.nested.property('state', 'initial');
7792
store.dispatch(cancelSignIn());
@@ -92,6 +107,8 @@ describe('atlasSignInReducer', function () {
92107
};
93108
const store = configureStore({
94109
atlasAuthService: mockAtlasService as any,
110+
atlasAiService: mockAtlasService as any,
111+
preferences: mockPreferences,
95112
});
96113

97114
void store.dispatch(signIntoAtlasWithModalPrompt()).catch(() => {});
@@ -111,6 +128,8 @@ describe('atlasSignInReducer', function () {
111128
};
112129
const store = configureStore({
113130
atlasAuthService: mockAtlasService as any,
131+
atlasAiService: mockAtlasService as any,
132+
preferences: mockPreferences,
114133
});
115134

116135
const signInPromise = store.dispatch(signIntoAtlasWithModalPrompt());
@@ -126,6 +145,8 @@ describe('atlasSignInReducer', function () {
126145
};
127146
const store = configureStore({
128147
atlasAuthService: mockAtlasService as any,
148+
atlasAiService: mockAtlasService as any,
149+
preferences: mockPreferences,
129150
});
130151

131152
const signInPromise = store.dispatch(signIntoAtlasWithModalPrompt());
@@ -147,6 +168,8 @@ describe('atlasSignInReducer', function () {
147168
};
148169
const store = configureStore({
149170
atlasAuthService: mockAtlasService as any,
171+
atlasAiService: mockAtlasService as any,
172+
preferences: mockPreferences,
150173
});
151174

152175
const signInPromise = store.dispatch(signIntoAtlasWithModalPrompt());
@@ -168,6 +191,8 @@ describe('atlasSignInReducer', function () {
168191
};
169192
const store = configureStore({
170193
atlasAuthService: mockAtlasService as any,
194+
atlasAiService: mockAtlasService as any,
195+
preferences: mockPreferences,
171196
});
172197

173198
const c = new AbortController();

0 commit comments

Comments
 (0)