mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
fix: strip timezone information from a date in dau response (#11962)
* fix: strip timezone information from a date in dau response Timezone information is lost, so do not forward it to the client. * fix: timezone offset should be flipped * Make tests deterministic
This commit is contained in:
4
coderd/apidoc/docs.go
generated
4
coderd/apidoc/docs.go
generated
@ -8877,8 +8877,8 @@ const docTemplate = `{
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"date": {
|
"date": {
|
||||||
"type": "string",
|
"description": "Date is a string formatted as 2024-01-31.\nTimezone and time information is not included.",
|
||||||
"format": "date-time"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
4
coderd/apidoc/swagger.json
generated
4
coderd/apidoc/swagger.json
generated
@ -7913,8 +7913,8 @@
|
|||||||
"type": "integer"
|
"type": "integer"
|
||||||
},
|
},
|
||||||
"date": {
|
"date": {
|
||||||
"type": "string",
|
"description": "Date is a string formatted as 2024-01-31.\nTimezone and time information is not included.",
|
||||||
"format": "date-time"
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -39,6 +39,9 @@ import (
|
|||||||
func TestDeploymentInsights(t *testing.T) {
|
func TestDeploymentInsights(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
clientTz, err := time.LoadLocation("America/Chicago")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
client := coderdtest.New(t, &coderdtest.Options{
|
client := coderdtest.New(t, &coderdtest.Options{
|
||||||
IncludeProvisionerDaemon: true,
|
IncludeProvisionerDaemon: true,
|
||||||
AgentStatsRefreshInterval: time.Millisecond * 100,
|
AgentStatsRefreshInterval: time.Millisecond * 100,
|
||||||
@ -64,7 +67,7 @@ func TestDeploymentInsights(t *testing.T) {
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
daus, err := client.DeploymentDAUs(context.Background(), codersdk.TimezoneOffsetHour(time.UTC))
|
daus, err := client.DeploymentDAUs(context.Background(), codersdk.TimezoneOffsetHour(clientTz))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{})
|
res, err := client.Workspaces(ctx, codersdk.WorkspaceFilter{})
|
||||||
@ -84,22 +87,23 @@ func TestDeploymentInsights(t *testing.T) {
|
|||||||
_ = sshConn.Close()
|
_ = sshConn.Close()
|
||||||
|
|
||||||
wantDAUs := &codersdk.DAUsResponse{
|
wantDAUs := &codersdk.DAUsResponse{
|
||||||
|
TZHourOffset: codersdk.TimezoneOffsetHour(clientTz),
|
||||||
Entries: []codersdk.DAUEntry{
|
Entries: []codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: time.Now().UTC().Truncate(time.Hour * 24),
|
Date: time.Now().In(clientTz).Format("2006-01-02"),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
require.Eventuallyf(t, func() bool {
|
require.Eventuallyf(t, func() bool {
|
||||||
daus, err = client.DeploymentDAUs(ctx, codersdk.TimezoneOffsetHour(time.UTC))
|
daus, err = client.DeploymentDAUs(ctx, codersdk.TimezoneOffsetHour(clientTz))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return len(daus.Entries) > 0
|
return len(daus.Entries) > 0
|
||||||
},
|
},
|
||||||
testutil.WaitShort, testutil.IntervalFast,
|
testutil.WaitShort, testutil.IntervalFast,
|
||||||
"deployment daus never loaded",
|
"deployment daus never loaded",
|
||||||
)
|
)
|
||||||
gotDAUs, err := client.DeploymentDAUs(ctx, codersdk.TimezoneOffsetHour(time.UTC))
|
gotDAUs, err := client.DeploymentDAUs(ctx, codersdk.TimezoneOffsetHour(clientTz))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, gotDAUs, wantDAUs)
|
require.Equal(t, gotDAUs, wantDAUs)
|
||||||
|
|
||||||
|
@ -22,6 +22,10 @@ import (
|
|||||||
"github.com/coder/retry"
|
"github.com/coder/retry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func OnlyDate(t time.Time) string {
|
||||||
|
return t.Format("2006-01-02")
|
||||||
|
}
|
||||||
|
|
||||||
// deploymentTimezoneOffsets are the timezones that are cached and supported.
|
// deploymentTimezoneOffsets are the timezones that are cached and supported.
|
||||||
// Any non-listed timezone offsets will need to use the closest supported one.
|
// Any non-listed timezone offsets will need to use the closest supported one.
|
||||||
var deploymentTimezoneOffsets = []int{
|
var deploymentTimezoneOffsets = []int{
|
||||||
@ -166,7 +170,9 @@ func convertDAUResponse[T dauRow](rows []T, tzOffset int) codersdk.DAUsResponse
|
|||||||
var resp codersdk.DAUsResponse
|
var resp codersdk.DAUsResponse
|
||||||
for _, date := range fillEmptyDays(dates) {
|
for _, date := range fillEmptyDays(dates) {
|
||||||
resp.Entries = append(resp.Entries, codersdk.DAUEntry{
|
resp.Entries = append(resp.Entries, codersdk.DAUEntry{
|
||||||
Date: date,
|
// This date is truncated to 00:00:00 of the given day, so only
|
||||||
|
// return date information.
|
||||||
|
Date: OnlyDate(date),
|
||||||
Amount: len(respMap[date]),
|
Amount: len(respMap[date]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -67,19 +67,19 @@ func TestCache_TemplateUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
tplWant: want{[]codersdk.DAUEntry{
|
tplWant: want{[]codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 27),
|
Date: metricscache.OnlyDate(date(2022, 8, 27)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 28),
|
Date: metricscache.OnlyDate(date(2022, 8, 28)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 29),
|
Date: metricscache.OnlyDate(date(2022, 8, 29)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 30),
|
Date: metricscache.OnlyDate(date(2022, 8, 30)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
}, 1},
|
}, 1},
|
||||||
@ -95,15 +95,15 @@ func TestCache_TemplateUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
tplWant: want{[]codersdk.DAUEntry{
|
tplWant: want{[]codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 27),
|
Date: metricscache.OnlyDate(date(2022, 8, 27)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 28),
|
Date: metricscache.OnlyDate(date(2022, 8, 28)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 8, 29),
|
Date: metricscache.OnlyDate(date(2022, 8, 29)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
}, 1},
|
}, 1},
|
||||||
@ -121,31 +121,31 @@ func TestCache_TemplateUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
tplWant: want{[]codersdk.DAUEntry{
|
tplWant: want{[]codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 1),
|
Date: metricscache.OnlyDate(date(2022, 1, 1)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 2),
|
Date: metricscache.OnlyDate(date(2022, 1, 2)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 3),
|
Date: metricscache.OnlyDate(date(2022, 1, 3)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 4),
|
Date: metricscache.OnlyDate(date(2022, 1, 4)),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 5),
|
Date: metricscache.OnlyDate(date(2022, 1, 5)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 6),
|
Date: metricscache.OnlyDate(date(2022, 1, 6)),
|
||||||
Amount: 0,
|
Amount: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 7),
|
Date: metricscache.OnlyDate(date(2022, 1, 7)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
}, 2},
|
}, 2},
|
||||||
@ -164,17 +164,17 @@ func TestCache_TemplateUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
tplWant: want{[]codersdk.DAUEntry{
|
tplWant: want{[]codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 2),
|
Date: metricscache.OnlyDate(date(2022, 1, 2)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
}, 2},
|
}, 2},
|
||||||
dauWant: []codersdk.DAUEntry{
|
dauWant: []codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 1),
|
Date: metricscache.OnlyDate(date(2022, 1, 1)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 2),
|
Date: metricscache.OnlyDate(date(2022, 1, 2)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -192,13 +192,13 @@ func TestCache_TemplateUsers(t *testing.T) {
|
|||||||
},
|
},
|
||||||
dauWant: []codersdk.DAUEntry{
|
dauWant: []codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 1),
|
Date: metricscache.OnlyDate(date(2022, 1, 1)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tplWant: want{[]codersdk.DAUEntry{
|
tplWant: want{[]codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: date(2022, 1, 2),
|
Date: metricscache.OnlyDate(date(2022, 1, 2)),
|
||||||
Amount: 2,
|
Amount: 2,
|
||||||
},
|
},
|
||||||
}, 2},
|
}, 2},
|
||||||
|
@ -1405,7 +1405,7 @@ func TestTemplateMetrics(t *testing.T) {
|
|||||||
wantDAUs := &codersdk.DAUsResponse{
|
wantDAUs := &codersdk.DAUsResponse{
|
||||||
Entries: []codersdk.DAUEntry{
|
Entries: []codersdk.DAUEntry{
|
||||||
{
|
{
|
||||||
Date: time.Now().UTC().Truncate(time.Hour * 24),
|
Date: time.Now().UTC().Truncate(time.Hour * 24).Format("2006-01-02"),
|
||||||
Amount: 1,
|
Amount: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -2168,8 +2168,10 @@ type DAUsResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DAUEntry struct {
|
type DAUEntry struct {
|
||||||
Date time.Time `json:"date" format:"date-time"`
|
// Date is a string formatted as 2024-01-31.
|
||||||
Amount int `json:"amount"`
|
// Timezone and time information is not included.
|
||||||
|
Date string `json:"date"`
|
||||||
|
Amount int `json:"amount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DAURequest struct {
|
type DAURequest struct {
|
||||||
@ -2184,14 +2186,22 @@ func (d DAURequest) asRequestOption() RequestOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TimezoneOffsetHour(loc *time.Location) int {
|
// TimezoneOffsetHourWithTime is implemented to match the javascript 'getTimezoneOffset()' function.
|
||||||
|
// This is the amount of time between this date evaluated in UTC and evaluated in the 'loc'
|
||||||
|
// The trivial case of times being on the same day is:
|
||||||
|
// 'time.Now().UTC().Hour() - time.Now().In(loc).Hour()'
|
||||||
|
func TimezoneOffsetHourWithTime(now time.Time, loc *time.Location) int {
|
||||||
if loc == nil {
|
if loc == nil {
|
||||||
// Default to UTC time to be consistent across all callers.
|
// Default to UTC time to be consistent across all callers.
|
||||||
loc = time.UTC
|
loc = time.UTC
|
||||||
}
|
}
|
||||||
_, offsetSec := time.Now().In(loc).Zone()
|
_, offsetSec := now.In(loc).Zone()
|
||||||
// Convert to hours
|
// Convert to hours and flip the sign
|
||||||
return offsetSec / 60 / 60
|
return -1 * offsetSec / 60 / 60
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimezoneOffsetHour(loc *time.Location) int {
|
||||||
|
return TimezoneOffsetHourWithTime(time.Now(), loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) DeploymentDAUsLocalTZ(ctx context.Context) (*DAUsResponse, error) {
|
func (c *Client) DeploymentDAUsLocalTZ(ctx context.Context) (*DAUsResponse, error) {
|
||||||
|
@ -205,6 +205,7 @@ func TestTimezoneOffsets(t *testing.T) {
|
|||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Name string
|
Name string
|
||||||
|
Now time.Time
|
||||||
Loc *time.Location
|
Loc *time.Location
|
||||||
ExpectedOffset int
|
ExpectedOffset int
|
||||||
}{
|
}{
|
||||||
@ -213,29 +214,52 @@ func TestTimezoneOffsets(t *testing.T) {
|
|||||||
Loc: time.UTC,
|
Loc: time.UTC,
|
||||||
ExpectedOffset: 0,
|
ExpectedOffset: 0,
|
||||||
},
|
},
|
||||||
// The following test cases are broken re: daylight savings
|
|
||||||
//{
|
{
|
||||||
// Name: "Eastern",
|
Name: "Eastern",
|
||||||
// Loc: must(time.LoadLocation("America/New_York")),
|
Now: time.Date(2021, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||||
// ExpectedOffset: -4,
|
Loc: must(time.LoadLocation("America/New_York")),
|
||||||
// },
|
ExpectedOffset: 5,
|
||||||
//{
|
},
|
||||||
// Name: "Central",
|
{
|
||||||
// Loc: must(time.LoadLocation("America/Chicago")),
|
// Daylight savings is on the 14th of March to Nov 7 in 2021
|
||||||
// ExpectedOffset: -5,
|
Name: "EasternDaylightSavings",
|
||||||
// },
|
Now: time.Date(2021, 3, 16, 0, 0, 0, 0, time.UTC),
|
||||||
//{
|
Loc: must(time.LoadLocation("America/New_York")),
|
||||||
// Name: "Ireland",
|
ExpectedOffset: 4,
|
||||||
// Loc: must(time.LoadLocation("Europe/Dublin")),
|
},
|
||||||
// ExpectedOffset: 1,
|
{
|
||||||
// },
|
Name: "Central",
|
||||||
|
Now: time.Date(2021, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
Loc: must(time.LoadLocation("America/Chicago")),
|
||||||
|
ExpectedOffset: 6,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "CentralDaylightSavings",
|
||||||
|
Now: time.Date(2021, 3, 16, 0, 0, 0, 0, time.UTC),
|
||||||
|
Loc: must(time.LoadLocation("America/Chicago")),
|
||||||
|
ExpectedOffset: 5,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Ireland",
|
||||||
|
Now: time.Date(2021, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||||
|
Loc: must(time.LoadLocation("Europe/Dublin")),
|
||||||
|
ExpectedOffset: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "IrelandDaylightSavings",
|
||||||
|
Now: time.Date(2021, 4, 3, 0, 0, 0, 0, time.UTC),
|
||||||
|
Loc: must(time.LoadLocation("Europe/Dublin")),
|
||||||
|
ExpectedOffset: -1,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "HalfHourTz",
|
Name: "HalfHourTz",
|
||||||
|
Now: time.Date(2024, 1, 20, 6, 0, 0, 0, must(time.LoadLocation("Asia/Yangon"))),
|
||||||
// This timezone is +6:30, but the function rounds to the nearest hour.
|
// This timezone is +6:30, but the function rounds to the nearest hour.
|
||||||
// This is intentional because our DAUs endpoint only covers 1-hour offsets.
|
// This is intentional because our DAUs endpoint only covers 1-hour offsets.
|
||||||
// If the user is in a non-hour timezone, they get the closest hour bucket.
|
// If the user is in a non-hour timezone, they get the closest hour bucket.
|
||||||
Loc: must(time.LoadLocation("Asia/Yangon")),
|
Loc: must(time.LoadLocation("Asia/Yangon")),
|
||||||
ExpectedOffset: 6,
|
ExpectedOffset: -6,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +268,7 @@ func TestTimezoneOffsets(t *testing.T) {
|
|||||||
t.Run(c.Name, func(t *testing.T) {
|
t.Run(c.Name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
offset := codersdk.TimezoneOffsetHour(c.Loc)
|
offset := codersdk.TimezoneOffsetHourWithTime(c.Now, c.Loc)
|
||||||
require.Equal(t, c.ExpectedOffset, offset)
|
require.Equal(t, c.ExpectedOffset, offset)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
2
docs/api/insights.md
generated
2
docs/api/insights.md
generated
@ -22,7 +22,7 @@ curl -X GET http://coder-server:8080/api/v2/insights/daus \
|
|||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"amount": 0,
|
"amount": 0,
|
||||||
"date": "2019-08-24T14:15:22Z"
|
"date": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tz_hour_offset": 0
|
"tz_hour_offset": 0
|
||||||
|
12
docs/api/schemas.md
generated
12
docs/api/schemas.md
generated
@ -1931,16 +1931,16 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"amount": 0,
|
"amount": 0,
|
||||||
"date": "2019-08-24T14:15:22Z"
|
"date": "string"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Properties
|
### Properties
|
||||||
|
|
||||||
| Name | Type | Required | Restrictions | Description |
|
| Name | Type | Required | Restrictions | Description |
|
||||||
| -------- | ------- | -------- | ------------ | ----------- |
|
| -------- | ------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
|
||||||
| `amount` | integer | false | | |
|
| `amount` | integer | false | | |
|
||||||
| `date` | string | false | | |
|
| `date` | string | false | | Date is a string formatted as 2024-01-31. Timezone and time information is not included. |
|
||||||
|
|
||||||
## codersdk.DAUsResponse
|
## codersdk.DAUsResponse
|
||||||
|
|
||||||
@ -1949,7 +1949,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
|
|||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"amount": 0,
|
"amount": 0,
|
||||||
"date": "2019-08-24T14:15:22Z"
|
"date": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tz_hour_offset": 0
|
"tz_hour_offset": 0
|
||||||
|
2
docs/api/templates.md
generated
2
docs/api/templates.md
generated
@ -842,7 +842,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/daus \
|
|||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"amount": 0,
|
"amount": 0,
|
||||||
"date": "2019-08-24T14:15:22Z"
|
"date": "string"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"tz_hour_offset": 0
|
"tz_hour_offset": 0
|
||||||
|
@ -21,17 +21,17 @@ export const MockOrganization: TypesGen.Organization = {
|
|||||||
export const MockTemplateDAUResponse: TypesGen.DAUsResponse = {
|
export const MockTemplateDAUResponse: TypesGen.DAUsResponse = {
|
||||||
tz_hour_offset: 0,
|
tz_hour_offset: 0,
|
||||||
entries: [
|
entries: [
|
||||||
{ date: "2022-08-27T00:00:00Z", amount: 1 },
|
{ date: "2022-08-27", amount: 1 },
|
||||||
{ date: "2022-08-29T00:00:00Z", amount: 2 },
|
{ date: "2022-08-29", amount: 2 },
|
||||||
{ date: "2022-08-30T00:00:00Z", amount: 1 },
|
{ date: "2022-08-30", amount: 1 },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
export const MockDeploymentDAUResponse: TypesGen.DAUsResponse = {
|
export const MockDeploymentDAUResponse: TypesGen.DAUsResponse = {
|
||||||
tz_hour_offset: 0,
|
tz_hour_offset: 0,
|
||||||
entries: [
|
entries: [
|
||||||
{ date: "2022-08-27T00:00:00Z", amount: 10 },
|
{ date: "2022-08-27", amount: 10 },
|
||||||
{ date: "2022-08-29T00:00:00Z", amount: 22 },
|
{ date: "2022-08-29", amount: 22 },
|
||||||
{ date: "2022-08-30T00:00:00Z", amount: 14 },
|
{ date: "2022-08-30", amount: 14 },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
export const MockSessionToken: TypesGen.LoginWithPasswordResponse = {
|
export const MockSessionToken: TypesGen.LoginWithPasswordResponse = {
|
||||||
|
Reference in New Issue
Block a user