fix(mobile): prepare v1.0.7 OTA release

This commit is contained in:
jjbrunton committed 2026-08-30 20:41:08 +01:00
1 parent 2664791233
commit db5980c9bd
16 files changed
+221 -61

No files matched your search

@@ -0,0 +1,46 @@
const configPath = require.resolve("../../app.config");
type UpdateConfig = {
updates: {
codeSigningCertificate?: string;
codeSigningMetadata?: Record<string, string>;
};
};
function resolveConfig(environment: Record<string, string>): UpdateConfig {
const previous = {
DISABLE_CODE_SIGNING: process.env.DISABLE_CODE_SIGNING,
RELEASE_CHANNEL: process.env.RELEASE_CHANNEL,
};
Object.assign(process.env, environment);
jest.resetModules();
try {
// eslint-disable-next-line @typescript-eslint/no-require-imports
return (require(configPath) as () => UpdateConfig)();
} finally {
for (const [key, value] of Object.entries(previous)) {
if (value === undefined) {
delete process.env[key];
} else {
process.env[key] = value;
}
}
}
}
describe("Expo OTA configuration", () => {
it("rejects disabling code signing for a production build", () => {
expect(() =>
resolveConfig({ RELEASE_CHANNEL: "production", DISABLE_CODE_SIGNING: "1" }),
).toThrow("RELEASE_CHANNEL=production does not permit DISABLE_CODE_SIGNING");
});
it("keeps local development code-signing opt-out available", () => {
const config = resolveConfig({ RELEASE_CHANNEL: "development", DISABLE_CODE_SIGNING: "1" });
expect(config.updates.codeSigningCertificate).toBeUndefined();
expect(config.updates.codeSigningMetadata).toBeUndefined();
});
});
@@ -112,6 +112,7 @@ describe("authStore", () => {
});
it("clears user-scoped stores and hosted auth when the API rejects the session", async () => {
useAuthStore.setState({ sealedCount: 3 } as any);
(authClient.auth.getSession as jest.Mock).mockResolvedValueOnce({
data: { session: { user: { id: "me" } } },
});
@@ -122,6 +123,7 @@ describe("authStore", () => {
expect(useAuthStore.getState()).toMatchObject({
user: null,
sealedCount: 0,
isAuthenticated: false,
isAnonymous: false,
isLoading: false,
@@ -132,4 +134,28 @@ describe("authStore", () => {
expect(useSubscriptionStore.getState().subscription).toMatchObject({ isProUser: false });
expect(authClient.auth.signOut).toHaveBeenCalled();
});
it("clears sealed answers during an explicit sign-out", async () => {
useAuthStore.setState({ user: profile, sealedCount: 3, isAuthenticated: true } as any);
await useAuthStore.getState().signOut();
expect(useAuthStore.getState()).toMatchObject({
user: null,
sealedCount: 0,
isAuthenticated: false,
});
});
it("clears sealed answers when the auth listener clears the user", () => {
useAuthStore.setState({ user: profile, sealedCount: 3, isAuthenticated: true } as any);
useAuthStore.getState().setUser(null);
expect(useAuthStore.getState()).toMatchObject({
user: null,
sealedCount: 0,
isAuthenticated: false,
});
});
});
+3 -3
View File
@@ -88,7 +88,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
} catch (error) {
if (error instanceof ApiError && error.status === 401) {
console.log("[Auth] Session rejected by API, signing out");
set({ user: null, couple: null, partner: null, isAuthenticated: false, isAnonymous: false, isLoading: false });
set({ user: null, couple: null, partner: null, sealedCount: 0, isAuthenticated: false, isAnonymous: false, isLoading: false });
const { useMatchStore, usePacksStore, useMessageStore, useSubscriptionStore, useNotificationPreferencesStore, useStreakStore, useResponsesStore, useQuizStore } = getOtherStores();
useMatchStore.getState().clearMatches();
usePacksStore.getState().clearPacks();
@@ -137,6 +137,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
user: null,
couple: null,
partner: null,
sealedCount: 0,
isAuthenticated: false,
isAnonymous: false,
isLoading: false,
@@ -171,7 +172,7 @@ export const useAuthStore = create<AuthState>((set, get) => ({
...(user === null && { isAnonymous: false }),
isLoading: false,
// Clear couple/partner when user is null (signed out)
...(user === null && { couple: null, partner: null })
...(user === null && { couple: null, partner: null, sealedCount: 0 })
});
// Clear other stores when user signs out
if (user === null) {
@@ -211,4 +212,3 @@ export const useAuthStore = create<AuthState>((set, get) => ({
void syncTimezone(userId);
},
}));