-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: Unify generator store slices creation #39
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './loadProfile' | ||
export * from './rules' | ||
export * from './testData' | ||
export * from './testOptions' |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { ProxyData } from '@/types' | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
|
||
interface State { | ||
requests: ProxyData[] | ||
recordingPath: string | ||
allowList: string[] | ||
filteredRequests: ProxyData[] | ||
showAllowListDialog: boolean | ||
} | ||
|
||
interface Actions { | ||
setRecording: (recording: ProxyData[], path: string) => void | ||
resetRecording: () => void | ||
setAllowList: (value: string[]) => void | ||
setFilteredRequests: (requests: ProxyData[]) => void | ||
setShowAllowListDialog: (value: boolean) => void | ||
} | ||
|
||
export type RecordingSliceStore = State & Actions | ||
|
||
export const createRecordingSlice: ImmerStateCreator<RecordingSliceStore> = ( | ||
set | ||
) => ({ | ||
requests: [], | ||
recordingPath: '', | ||
allowList: [], | ||
filteredRequests: [], | ||
Comment on lines
+27
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might be a little complicated 🤔 When saving the State to the file we do no care about There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We may need to write some adapter functions that will turn the state into a file: it's not just that the state has some runtime properties (like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there will be 2 separate types of state: State for app use and GeneratorFile type, which won't include internal props like selectedRunId. And 2 functions to convert between them. As for filteredRequests - agree that it should be a memoized selector 👍 |
||
showAllowListDialog: false, | ||
|
||
setRecording: (requests: ProxyData[], path: string) => | ||
set((state) => { | ||
state.requests = requests | ||
state.allowList = [] | ||
state.filteredRequests = [] | ||
state.recordingPath = path | ||
state.showAllowListDialog = true | ||
}), | ||
resetRecording: () => | ||
set((state) => { | ||
state.requests = [] | ||
state.allowList = [] | ||
state.filteredRequests = [] | ||
state.recordingPath = '' | ||
}), | ||
setAllowList: (value) => | ||
set((state) => { | ||
state.allowList = value | ||
}), | ||
setFilteredRequests: (requests) => | ||
set((state) => { | ||
state.filteredRequests = requests | ||
}), | ||
setShowAllowListDialog: (value) => | ||
set((state) => { | ||
state.showAllowListDialog = value | ||
}), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,23 @@ | ||
import { TestRule } from '@/types/rules' | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
import { rules } from '../fixtures' | ||
import { RulesState } from '../types' | ||
|
||
export const createRulesSlice: ImmerStateCreator<RulesState> = (set) => ({ | ||
interface State { | ||
rules: TestRule[] | ||
selectedRuleId: string | null | ||
} | ||
|
||
interface Actions { | ||
createRule: (type: TestRule['type']) => void | ||
updateRule: (rule: TestRule) => void | ||
cloneRule: (id: string) => void | ||
deleteRule: (id: string) => void | ||
selectRule: (id: string) => void | ||
} | ||
|
||
export type RulesSliceStore = State & Actions | ||
Comment on lines
+5
to
+18
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like having internal There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we might have to discuss the requirements more before deciding 🤔 |
||
|
||
export const createRulesSlice: ImmerStateCreator<RulesSliceStore> = (set) => ({ | ||
rules, | ||
selectedRuleId: null, | ||
createRule: (type: TestRule['type']) => | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
import { Variable } from '@/types' | ||
|
||
interface State { | ||
variables: Variable[] | ||
} | ||
|
||
interface Actions { | ||
setVariables: (variables: Variable[]) => void | ||
} | ||
|
||
export type TestDataStore = State & Actions | ||
|
||
export const createTestDataSlice: ImmerStateCreator<TestDataStore> = (set) => ({ | ||
variables: [], | ||
|
||
setVariables: (variables: Variable[]) => | ||
set((state) => { | ||
state.variables = variables | ||
}), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
import { LoadProfileStore, createLoadProfileSlice } from './loadProfile' | ||
import { ThinkTimeStore, createThinkTimeSlice } from './thinkTime' | ||
|
||
export type TestOptionsStore = LoadProfileStore & ThinkTimeStore | ||
|
||
export const createTestOptionsSlice: ImmerStateCreator< | ||
LoadProfileStore & ThinkTimeStore | ||
> = (...args) => ({ | ||
...createLoadProfileSlice(...args), | ||
...createThinkTimeSlice(...args), | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { ExecutorType } from '@/constants/generator' | ||
import { | ||
RampingStage, | ||
RampingVUsOptions, | ||
SharedIterationsOptions, | ||
} from '@/types/testOptions' | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
|
||
interface SharedIterationsState | ||
extends Omit<SharedIterationsOptions, 'executor'> { | ||
setVus: (value: SharedIterationsOptions['vus']) => void | ||
setIterations: (value: SharedIterationsOptions['iterations']) => void | ||
setMaxDuration: (value: SharedIterationsOptions['maxDuration']) => void | ||
} | ||
|
||
interface CommonState { | ||
executor: ExecutorType | ||
gracefulStop: string | undefined | ||
startTime: string | undefined | ||
} | ||
|
||
interface CommonActions { | ||
setExecutor: (value: ExecutorType) => void | ||
setGracefulStop: (value: string | undefined) => void | ||
setStartTime: (value: string | undefined) => void | ||
} | ||
|
||
type CommonStore = CommonState & CommonActions | ||
|
||
const createCommonSlice: ImmerStateCreator<CommonStore> = (set) => ({ | ||
executor: ExecutorType.RampingVUs, | ||
gracefulStop: undefined, | ||
startTime: undefined, | ||
|
||
setExecutor: (value) => | ||
set((state) => { | ||
state.executor = value | ||
}), | ||
setGracefulStop: (value) => | ||
set((state) => { | ||
state.gracefulStop = value | ||
}), | ||
setStartTime: (value) => | ||
set((state) => { | ||
state.startTime = value | ||
}), | ||
}) | ||
|
||
interface RampingActions { | ||
addStage: () => void | ||
removeStage: (index: number) => void | ||
updateStage: (index: number, value: RampingStage) => void | ||
setGracefulRampDown: (value: RampingVUsOptions['gracefulRampDown']) => void | ||
setStartVUs: (value: RampingVUsOptions['startVUs']) => void | ||
} | ||
|
||
type RampingStore = Omit<RampingVUsOptions, 'executor'> & RampingActions | ||
|
||
const createRampingSlice: ImmerStateCreator<RampingStore> = (set) => ({ | ||
gracefulRampDown: undefined, | ||
stages: [], | ||
startVUs: undefined, | ||
|
||
setGracefulRampDown: (value) => | ||
set((state) => { | ||
state.gracefulRampDown = value | ||
}), | ||
addStage: () => | ||
set((state) => { | ||
state.stages.push(createStage()) | ||
}), | ||
removeStage: (index) => | ||
set((state) => { | ||
state.stages.splice(index, 1) | ||
}), | ||
updateStage: (index, value) => | ||
set((state) => { | ||
state.stages[index] = value | ||
}), | ||
setStartVUs: (value) => | ||
set((state) => { | ||
state.startVUs = value | ||
}), | ||
}) | ||
|
||
interface SharedIterationsActions { | ||
setIterations: (value: number | undefined) => void | ||
setMaxDuration: (value: string | undefined) => void | ||
setVus: (value: number | undefined) => void | ||
} | ||
|
||
type SharedIterationsStore = Omit<SharedIterationsState, 'executor'> & | ||
SharedIterationsActions | ||
|
||
const createSharedIterationsSlice: ImmerStateCreator<SharedIterationsStore> = ( | ||
set | ||
) => ({ | ||
iterations: undefined, | ||
maxDuration: undefined, | ||
vus: undefined, | ||
|
||
setIterations: (value) => | ||
set((state) => { | ||
state.iterations = value | ||
}), | ||
setMaxDuration: (value) => | ||
set((state) => { | ||
state.maxDuration = value | ||
}), | ||
setVus: (value) => | ||
set((state) => { | ||
state.vus = value | ||
}), | ||
}) | ||
|
||
export type LoadProfileStore = CommonStore & | ||
RampingStore & | ||
SharedIterationsStore | ||
|
||
export const createLoadProfileSlice: ImmerStateCreator<LoadProfileStore> = ( | ||
...args | ||
) => ({ | ||
...createCommonSlice(...args), | ||
...createRampingSlice(...args), | ||
...createSharedIterationsSlice(...args), | ||
}) | ||
|
||
function createStage() { | ||
return { | ||
target: '', | ||
duration: '', | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { ImmerStateCreator } from '@/utils/typescript' | ||
import { SleepType, Timing } from '@/types/testOptions' | ||
import { createFixedTiming } from '@/utils/thinkTime' | ||
|
||
interface State { | ||
sleepType: SleepType | ||
timing: Timing | ||
} | ||
|
||
interface Actions { | ||
setSleepType: (value: SleepType) => void | ||
setTiming: (timing: Timing) => void | ||
} | ||
|
||
export type ThinkTimeStore = State & Actions | ||
|
||
export const createThinkTimeSlice: ImmerStateCreator<ThinkTimeStore> = ( | ||
set | ||
) => ({ | ||
sleepType: 'groups', | ||
timing: createFixedTiming(), | ||
|
||
setSleepType: (value: SleepType) => | ||
set((state) => { | ||
state.sleepType = value | ||
}), | ||
|
||
setTiming: (timing: Timing) => | ||
set((state) => { | ||
state.timing = timing | ||
}), | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any specific reason for dropping the prefix to the name ?
As it will be used outside it might make sense to keep it 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not exported, so the prefix is dropped for readability