-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Chore: introduce Fishery as object factory and yarn dev:msw (#1023)
* feat: define types for CheckAlert * feat: add AlertsPerCheck and AlertCard components in Check form * feat: add schema for new alert fields * feat: add useCheckAlert hook and datasource methods to fetch and update alerts * feat: fetch alerts when creating/updating checks and format payload for api * feat: fetch alerts when editing a check, and format response for form * chore: mock API response (only for testing purposes) * fix: filter alerts according to the supported checktypes * fix: make current tests pass - adjust schema validation to make it optional - add test handlers for new alerts requests * fix: remove mocked response for testing with dev API * fix: set correct alert id to payload - Also, invalidate cache for fetching fresh check alerts * fix: remove alert mocks as the API is available in dev * test: add tests for creating a check with alerts per check * fix: remove percentiles dropdown - Instead of grouping by alert type, I'm displaying all alerts as separate ones - Grouping by type didn't allow to specify threshold for different percentiles * refactor: introduce new CheckAlert types: Base, Draft and Published * test: add mocks back temporarily - since the alerts API is no longer in dev, I'm adding the mocks back to be able to test it - This should be improved by #850 * refactor: avoid passing unneeded props to AlertsPerCheck - Also, adding loading and error states * fix: remove emtpy response from listAlertsforCheck * refactor: move predefined alerts to external file - Add specific predefined alerts according to the check type in a single constants file - Display threshold units * fix: tests * fix: rebase conflicts * refactor: display new alerts in list format * chore: remove unneeded AlertCard component * fix: tests * feat: add AlertsPerCheck and AlertCard components in Check form * refactor: avoid passing unneeded props to AlertsPerCheck - Also, adding loading and error states * chore: introduce fishery and faker * feat: define Fishery factories for creating objects - Addresses all check types, probes and alerts * chore: create fixtures by consuming the object factories * fix: filter by probe on data transferred panels for browser checks * feat: introduce yarn dev:msw to start the app mocking the api using msw handlers * fix: move worker setup under useEffect * fix: conflicts after rebase * fix: humanize alert labels * fix: tests * feat: add feature flag - To enable the feature, set sm-alerts-per-check=true * fix: address review comments - move worker initialization to module.ts - use sequence for Fishery ids - simplify probes and checks mocks creation * fix: remove unneeded properties from check fixtures * fix: remove type assertion * fix: review comments * fix: add comment on query key * fix: change layout * feat: add default values for check alerts * fix: address review comments * fix: setting submitting form state when alerts request fails * fix: allow to delete input values * fix: target definition for http checks * fix: set default value when generating form values * fix: tests * chore: remove checkAlert id concept (#1041) The API is removing the id property for check alerts as they can be identified just by the name * fix: remove check alert id from factory * fix: center header and tweak description text * chore: remove mocked data as API is available in dev * fix: move serviceWorker setup to external file and load async
- Loading branch information
Showing
15 changed files
with
507 additions
and
412 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { setupWorker } from 'msw'; | ||
import { handlers } from 'test/handlers'; | ||
|
||
setupWorker(...handlers).start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
import { faker } from '@faker-js/faker'; | ||
import { Factory } from 'fishery'; | ||
|
||
import { | ||
AlertSensitivity, | ||
Check, | ||
CheckAlertPublished, | ||
CheckAlertType, | ||
CheckType, | ||
DnsProtocol, | ||
DnsRecordType, | ||
DnsResponseCodes, | ||
HTTPCompressionAlgo, | ||
HttpMethod, | ||
HttpVersion, | ||
IpVersion, | ||
Probe, | ||
} from 'types'; | ||
|
||
const baseCheckModel = ({ sequence }: { sequence: number }) => ({ | ||
id: sequence, | ||
job: faker.lorem.word(), | ||
target: faker.internet.domainName(), | ||
frequency: faker.number.int({ min: 1, max: 60 * 1000 }), | ||
timeout: faker.number.int({ min: 30, max: 60 * 1000 }), | ||
enabled: true, | ||
alertSensitivity: faker.helpers.arrayElement(Object.values(AlertSensitivity)), | ||
basicMetricsOnly: faker.datatype.boolean(), | ||
labels: [{ name: faker.animal.petName(), value: faker.color.human() }], | ||
probes: [], | ||
modified: Math.floor(faker.date.recent().getTime() / 1000), | ||
created: Math.floor(faker.date.past().getTime() / 1000), | ||
}); | ||
|
||
const baseProbeModel = ({ sequence }: { sequence: number }) => ({ | ||
id: sequence, | ||
name: faker.lorem.word(), | ||
public: faker.datatype.boolean(), | ||
latitude: faker.location.latitude(), | ||
longitude: faker.location.longitude(), | ||
region: faker.helpers.arrayElement(['EMEA', 'AMER', 'APAC']), | ||
labels: [{ name: faker.animal.petName(), value: faker.color.human() }], | ||
online: true, | ||
onlineChange: Math.floor(faker.date.past().getTime() / 1000), | ||
version: faker.system.semver(), | ||
deprecated: false, | ||
modified: Math.floor(faker.date.recent().getTime() / 1000), | ||
created: Math.floor(faker.date.past().getTime() / 1000), | ||
capabilities: { | ||
disableScriptedChecks: false, | ||
disableBrowserChecks: false, | ||
}, | ||
}); | ||
|
||
const tlsConfig = () => ({ | ||
caCert: faker.helpers.maybe(() => faker.string.uuid()), | ||
clientCert: faker.helpers.maybe(() => faker.string.uuid()), | ||
clientKey: faker.helpers.maybe(() => faker.string.uuid()), | ||
insecureSkipVerify: faker.helpers.maybe(() => faker.datatype.boolean()), | ||
serverName: faker.helpers.maybe(() => faker.lorem.word()), | ||
}); | ||
|
||
type CheckTransientParams = { | ||
type: CheckType; | ||
}; | ||
|
||
export const db = { | ||
check: Factory.define<Check, CheckTransientParams>(({ transientParams, sequence }) => { | ||
const { type } = transientParams; | ||
|
||
switch (type) { | ||
case CheckType.HTTP: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
target: faker.internet.url(), | ||
settings: { | ||
http: { | ||
method: faker.helpers.arrayElement(Object.values(HttpMethod)), | ||
headers: faker.helpers.maybe(() => []), | ||
body: faker.helpers.maybe(() => faker.lorem.text()), | ||
ipVersion: faker.helpers.arrayElement(Object.values(IpVersion)), | ||
noFollowRedirects: faker.datatype.boolean(), | ||
tlsConfig: faker.helpers.maybe(() => tlsConfig()), | ||
compression: faker.helpers.maybe(() => faker.helpers.arrayElement(Object.values(HTTPCompressionAlgo))), | ||
proxyURL: faker.helpers.maybe(() => faker.internet.url()), | ||
proxyConnectHeaders: faker.helpers.maybe(() => []), | ||
bearerToken: faker.helpers.maybe(() => faker.lorem.word()), | ||
basicAuth: faker.helpers.maybe(() => ({ | ||
username: faker.internet.username(), | ||
password: faker.internet.password(), | ||
})), | ||
failIfSSL: faker.helpers.maybe(() => faker.datatype.boolean()), | ||
failIfNotSSL: faker.helpers.maybe(() => faker.datatype.boolean()), | ||
validStatusCodes: faker.helpers.maybe(() => []), | ||
validHTTPVersions: faker.helpers.maybe(() => faker.helpers.arrayElements(Object.values(HttpVersion))), | ||
failIfBodyMatchesRegexp: faker.helpers.maybe(() => []), | ||
failIfBodyNotMatchesRegexp: faker.helpers.maybe(() => []), | ||
failIfHeaderMatchesRegexp: faker.helpers.maybe(() => []), | ||
failIfHeaderNotMatchesRegexp: faker.helpers.maybe(() => []), | ||
cacheBustingQueryParamName: faker.helpers.maybe(() => faker.lorem.word()), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.PING: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
ping: { | ||
ipVersion: faker.helpers.arrayElement(Object.values(IpVersion)), | ||
dontFragment: faker.datatype.boolean(), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.DNS: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
dns: { | ||
recordType: faker.helpers.arrayElement(Object.values(DnsRecordType)), | ||
server: faker.internet.domainName(), | ||
ipVersion: faker.helpers.arrayElement(Object.values(IpVersion)), | ||
protocol: faker.helpers.arrayElement(Object.values(DnsProtocol)), | ||
port: faker.number.int({ min: 1, max: 65535 }), | ||
validRCodes: faker.helpers.maybe(() => faker.helpers.arrayElements(Object.values(DnsResponseCodes))), | ||
validateAnswerRRS: faker.helpers.maybe(() => ({ | ||
failIfMatchesRegexp: [], | ||
failIfNotMatchesRegexp: [], | ||
})), | ||
validateAuthorityRRS: faker.helpers.maybe(() => ({ | ||
failIfMatchesRegexp: [], | ||
failIfNotMatchesRegexp: [], | ||
})), | ||
validateAdditionalRRS: faker.helpers.maybe(() => ({ | ||
failIfMatchesRegexp: [], | ||
failIfNotMatchesRegexp: [], | ||
})), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.TCP: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
tcp: { | ||
ipVersion: faker.helpers.arrayElement(Object.values(IpVersion)), | ||
tls: faker.helpers.maybe(() => faker.datatype.boolean()), | ||
tlsConfig: faker.helpers.maybe(() => tlsConfig()), | ||
queryResponse: faker.helpers.maybe(() => []), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.Traceroute: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
traceroute: { | ||
maxHops: faker.number.int({ min: 1, max: 10 }), | ||
maxUnknownHops: faker.number.int({ min: 1, max: 10 }), | ||
ptrLookup: faker.datatype.boolean(), | ||
hopTimeout: faker.number.int({ min: 1, max: 120 }), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.MULTI_HTTP: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
multihttp: { | ||
entries: [ | ||
{ | ||
variables: faker.helpers.maybe(() => []), | ||
request: { | ||
method: faker.helpers.arrayElement(Object.values(HttpMethod)), | ||
url: faker.internet.url(), | ||
body: faker.helpers.maybe(() => ({ | ||
contentType: faker.helpers.arrayElement([ | ||
'application/json', | ||
'application/xml', | ||
'application/x-www-form-urlencoded', | ||
]), | ||
contentEncoding: faker.helpers.maybe(() => faker.helpers.arrayElement(['gzip', 'deflate'])), | ||
payload: faker.lorem.sentence(), | ||
})), | ||
headers: faker.helpers.maybe(() => []), | ||
queryFields: faker.helpers.maybe(() => []), | ||
postData: faker.helpers.maybe(() => ({ | ||
mimeType: 'text/plain', | ||
text: '', | ||
})), | ||
}, | ||
checks: faker.helpers.maybe(() => []), | ||
}, | ||
], | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.Scripted: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
scripted: { | ||
script: faker.lorem.text(), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.Browser: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
browser: { | ||
script: faker.lorem.text(), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
case CheckType.GRPC: { | ||
return { | ||
...baseCheckModel({ sequence }), | ||
settings: { | ||
grpc: { | ||
ipVersion: faker.helpers.arrayElement(Object.values(IpVersion)), | ||
service: faker.helpers.maybe(() => faker.lorem.word()), | ||
tls: faker.helpers.maybe(() => faker.datatype.boolean()), | ||
tlsConfig: faker.helpers.maybe(() => tlsConfig()), | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
default: { | ||
throw new Error(`Unsupported check type: ${type}`); | ||
} | ||
} | ||
}), | ||
|
||
probe: Factory.define<Probe>(({ sequence }) => ({ | ||
...baseProbeModel({ sequence }), | ||
public: false, | ||
})), | ||
|
||
alert: Factory.define<CheckAlertPublished>(() => ({ | ||
name: faker.helpers.arrayElement(Object.values(CheckAlertType)), | ||
threshold: faker.number.int({ min: 50, max: 500 }), | ||
created: Math.floor(faker.date.past().getTime() / 1000), | ||
modified: Math.floor(faker.date.recent().getTime() / 1000), | ||
})), | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,13 @@ | ||
import { db } from 'test/db'; | ||
|
||
import { CheckAlertType } from 'types'; | ||
import { CheckAlertsResponse } from 'datasource/responses.types'; | ||
|
||
export const BASIC_CHECK_ALERTS: CheckAlertsResponse = { | ||
alerts: [ | ||
{ | ||
name: CheckAlertType['HTTPRequestDurationTooHighP90'], | ||
threshold: 350, | ||
created: 1724854935, | ||
modified: 1724854935, | ||
}, | ||
{ | ||
name: CheckAlertType['HTTPRequestDurationTooHighP95'], | ||
threshold: 100, | ||
created: 1724854935, | ||
modified: 1724854935, | ||
}, | ||
{ | ||
name: CheckAlertType['HTTPTargetCertificateCloseToExpiring'], | ||
threshold: 90, | ||
created: 1724854935, | ||
modified: 1724854935, | ||
}, | ||
{ | ||
name: CheckAlertType['ProbeFailedExecutionsTooHigh'], | ||
threshold: 20, | ||
created: 1724854935, | ||
modified: 1724854935, | ||
}, | ||
], | ||
CheckAlertType.HTTPRequestDurationTooHighP90, | ||
CheckAlertType.HTTPRequestDurationTooHighP95, | ||
CheckAlertType.HTTPTargetCertificateCloseToExpiring, | ||
CheckAlertType.ProbeFailedExecutionsTooHigh, | ||
].map((name) => db.alert.build({ name })), | ||
}; |
Oops, something went wrong.