mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
feat(app): gate a collapsing guild header behind an experiment (#2779)
This commit is contained in:
1 parent
550e6b05a1
commit
d0c6146429
29 files changed
+1449
-115
No files matched your search
@@ -0,0 +1,95 @@
|
||||
// @vitest-environment happy-dom
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {
|
||||
type ExperimentAssignmentsResponse,
|
||||
INERT_EXPERIMENT_ASSIGNMENTS_RESPONSE,
|
||||
} from '@fluxer/schema/src/domains/experiment/ExperimentSchemas';
|
||||
import {
|
||||
type GuildHeaderCollapseAssignmentResponse,
|
||||
INERT_GUILD_HEADER_COLLAPSE_ASSIGNMENT,
|
||||
} from '@fluxer/schema/src/domains/experiment/GuildHeaderCollapseSchemas';
|
||||
import {runInAction} from 'mobx';
|
||||
import {afterEach, describe, expect, it, vi} from 'vitest';
|
||||
|
||||
vi.mock('@app/features/platform/utils/AppLogger', () => ({
|
||||
Logger: class {
|
||||
debug = vi.fn();
|
||||
info = vi.fn();
|
||||
warn = vi.fn();
|
||||
error = vi.fn();
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@app/features/platform/transport/RestTransport', () => ({
|
||||
http: {get: vi.fn(), post: vi.fn()},
|
||||
}));
|
||||
|
||||
const {ExperimentAssignments} = await import('@app/features/experiment/state/ExperimentAssignments');
|
||||
const {GuildHeaderCollapseRollout} = await import('@app/features/app/state/GuildHeaderCollapseRollout');
|
||||
|
||||
const TARGETED_ASSIGNMENT: GuildHeaderCollapseAssignmentResponse = {
|
||||
enabled: true,
|
||||
config_version: 3,
|
||||
user_targeted: true,
|
||||
source: 'canary',
|
||||
};
|
||||
|
||||
function publish(assignment: GuildHeaderCollapseAssignmentResponse | undefined): void {
|
||||
const response: ExperimentAssignmentsResponse = {
|
||||
poll_interval_seconds: 300,
|
||||
poll_jitter_percent: 15,
|
||||
assignments: assignment === undefined ? {} : {guild_header_collapse: assignment},
|
||||
};
|
||||
runInAction(() => {
|
||||
ExperimentAssignments.response = response;
|
||||
});
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
runInAction(() => {
|
||||
ExperimentAssignments.response = INERT_EXPERIMENT_ASSIGNMENTS_RESPONSE;
|
||||
});
|
||||
});
|
||||
|
||||
describe('GuildHeaderCollapseRollout', () => {
|
||||
it('reads the inert assignment before any response has landed', () => {
|
||||
expect(GuildHeaderCollapseRollout.assignment).toEqual(INERT_GUILD_HEADER_COLLAPSE_ASSIGNMENT);
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(false);
|
||||
});
|
||||
|
||||
it('treats a missing experiment key as off', () => {
|
||||
publish(undefined);
|
||||
|
||||
expect(GuildHeaderCollapseRollout.assignment).toEqual(INERT_GUILD_HEADER_COLLAPSE_ASSIGNMENT);
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(false);
|
||||
});
|
||||
|
||||
it('collapses on scroll for a targeted account', () => {
|
||||
publish(TARGETED_ASSIGNMENT);
|
||||
|
||||
expect(GuildHeaderCollapseRollout.assignment).toEqual(TARGETED_ASSIGNMENT);
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(true);
|
||||
});
|
||||
|
||||
it('keeps the old header for an account outside the rollout', () => {
|
||||
publish({...TARGETED_ASSIGNMENT, user_targeted: false, source: null});
|
||||
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps the old header while the rollout is disabled instance-wide', () => {
|
||||
publish({...TARGETED_ASSIGNMENT, enabled: false});
|
||||
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(false);
|
||||
});
|
||||
|
||||
it('follows a later poll that turns the rollout off', () => {
|
||||
publish(TARGETED_ASSIGNMENT);
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(true);
|
||||
|
||||
publish({...TARGETED_ASSIGNMENT, enabled: false, user_targeted: false, source: null});
|
||||
|
||||
expect(GuildHeaderCollapseRollout.collapsesOnScroll).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import ExperimentAssignments from '@app/features/experiment/state/ExperimentAssignments';
|
||||
import {readGuildHeaderCollapseAssignment} from '@fluxer/schema/src/domains/experiment/ExperimentSchemas';
|
||||
import {
|
||||
type GuildHeaderCollapseAssignmentResponse,
|
||||
isGuildHeaderCollapseTargeted,
|
||||
} from '@fluxer/schema/src/domains/experiment/GuildHeaderCollapseSchemas';
|
||||
|
||||
class GuildHeaderCollapseRolloutSelector {
|
||||
get assignment(): GuildHeaderCollapseAssignmentResponse {
|
||||
return readGuildHeaderCollapseAssignment(ExperimentAssignments.response);
|
||||
}
|
||||
|
||||
get collapsesOnScroll(): boolean {
|
||||
return isGuildHeaderCollapseTargeted(this.assignment);
|
||||
}
|
||||
}
|
||||
|
||||
export const GuildHeaderCollapseRollout = new GuildHeaderCollapseRolloutSelector();
|
||||
|
||||
export default GuildHeaderCollapseRollout;
|
||||
Reference in new issue
Block a user