-
Notifications
You must be signed in to change notification settings - Fork 167
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a default expiration time setting (#364)
* Add a default expiration time setting * Move settings.go * work in progress * Temp * work in progress * work in progress * More progress * work in progress * work in progress * work in progress * work in progress * Sync access to settings * work in progress * Parse file lifetime more rigorously * Fix SQL indentation * work in progress * Add e2e tests * Tweak UI * Remove unnecessary comments * Refactor constructors for file lifetime
- Loading branch information
Showing
24 changed files
with
856 additions
and
33 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { test, expect } from "@playwright/test"; | ||
import { login } from "./helpers/login.js"; | ||
|
||
test("default file expiration is 30 days", async ({ page }) => { | ||
await login(page); | ||
|
||
await page.locator("data-test-id=system-dropdown").hover(); | ||
await page.locator("a[href='/settings']").click(); | ||
await expect(page).toHaveURL("/settings"); | ||
|
||
await expect(page.locator("#default-expiration")).toHaveValue("30"); | ||
await expect(page.locator("#time-unit")).toHaveValue("days"); | ||
|
||
await page.locator("data-test-id=upload-btn").click(); | ||
await expect(page).toHaveURL("/"); | ||
|
||
await expect(page.locator("#expiration-select option[selected]")).toHaveText( | ||
"30 days" | ||
); | ||
}); | ||
|
||
test("changes default file expiration to 5 days", async ({ page }) => { | ||
await login(page); | ||
|
||
await page.locator("data-test-id=system-dropdown").hover(); | ||
await page.locator("a[href='/settings']").click(); | ||
await expect(page).toHaveURL("/settings"); | ||
|
||
await page.locator("#default-expiration").fill("5"); | ||
await page.locator("#settings-form button[type='submit']").click(); | ||
|
||
await page.locator("data-test-id=upload-btn").click(); | ||
await expect(page).toHaveURL("/"); | ||
|
||
await expect(page.locator("#expiration-select option[selected]")).toHaveText( | ||
"5 days" | ||
); | ||
}); | ||
|
||
test("changes default file expiration to 1 year", async ({ page }) => { | ||
await login(page); | ||
|
||
await page.locator("data-test-id=system-dropdown").hover(); | ||
await page.locator("a[href='/settings']").click(); | ||
await expect(page).toHaveURL("/settings"); | ||
|
||
await page.locator("#default-expiration").fill("1"); | ||
await page.locator("#time-unit").selectOption("years"); | ||
await page.locator("#settings-form button[type='submit']").click(); | ||
|
||
await page.locator("data-test-id=upload-btn").click(); | ||
await expect(page).toHaveURL("/"); | ||
|
||
await expect(page.locator("#expiration-select option[selected]")).toHaveText( | ||
"1 year" | ||
); | ||
|
||
// Because 1 year is one of the built-in defaults, we shouldn't see any | ||
// additional items in the options list. | ||
const expirationOptions = await page | ||
.locator("#expiration-select option") | ||
.allInnerTexts(); | ||
expect(expirationOptions[0]).toEqual("1 day"); | ||
expect(expirationOptions[1]).toEqual("7 days"); | ||
expect(expirationOptions[2]).toEqual("30 days"); | ||
expect(expirationOptions[3]).toEqual("1 year"); | ||
expect(expirationOptions[4]).toEqual("Never"); | ||
expect(expirationOptions[5]).toEqual("Custom"); | ||
}); | ||
|
||
test("changes default file expiration to 10 years", async ({ page }) => { | ||
await login(page); | ||
|
||
await page.locator("data-test-id=system-dropdown").hover(); | ||
await page.locator("a[href='/settings']").click(); | ||
await expect(page).toHaveURL("/settings"); | ||
|
||
// Change default expiration to 10 years. | ||
await page.locator("#default-expiration").fill("10"); | ||
await page.locator("#time-unit").selectOption("years"); | ||
await page.locator("#settings-form button[type='submit']").click(); | ||
|
||
await page.locator("data-test-id=upload-btn").click(); | ||
await expect(page).toHaveURL("/"); | ||
|
||
await expect(page.locator("#expiration-select option[selected]")).toHaveText( | ||
"10 years" | ||
); | ||
}); |
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,29 @@ | ||
package parse | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/mtlynch/picoshare/v2/picoshare" | ||
) | ||
|
||
const minFileLifetimeInDays = 1 | ||
const maxFileLifetimeInYears = 10 | ||
|
||
// This is imprecise, but it's okay because file lifetimes are not exact | ||
// measures of time. | ||
const daysPerYear = 365 | ||
|
||
var ( | ||
ErrFileLifetimeTooShort = fmt.Errorf("file lifetime must be at least %d days", minFileLifetimeInDays) | ||
ErrFileLifetimeTooLong = fmt.Errorf("file lifetime must be at most %d years", maxFileLifetimeInYears) | ||
) | ||
|
||
func FileLifetime(lifetimeInDays uint16) (picoshare.FileLifetime, error) { | ||
if lifetimeInDays < minFileLifetimeInDays { | ||
return picoshare.FileLifetime{}, ErrFileLifetimeTooShort | ||
} | ||
if lifetimeInDays > (maxFileLifetimeInYears * daysPerYear) { | ||
return picoshare.FileLifetime{}, ErrFileLifetimeTooLong | ||
} | ||
return picoshare.NewFileLifetimeInDays(lifetimeInDays), nil | ||
} |
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,58 @@ | ||
package parse_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/mtlynch/picoshare/v2/handlers/parse" | ||
"github.com/mtlynch/picoshare/v2/picoshare" | ||
) | ||
|
||
func TestFileLifetime(t *testing.T) { | ||
for _, tt := range []struct { | ||
description string | ||
input uint16 | ||
output picoshare.FileLifetime | ||
err error | ||
}{ | ||
{ | ||
description: "valid lifetime", | ||
input: 7, | ||
output: picoshare.NewFileLifetimeInDays(7), | ||
err: nil, | ||
}, | ||
{ | ||
description: "accepts the minimum valid lifetime", | ||
input: 1, | ||
output: picoshare.NewFileLifetimeInDays(1), | ||
err: nil, | ||
}, | ||
{ | ||
description: "accepts the maximum valid lifetime", | ||
input: 365 * 10, | ||
output: picoshare.NewFileLifetimeInYears(10), | ||
err: nil, | ||
}, | ||
{ | ||
description: "rejects too short a lifetime", | ||
input: 0, | ||
output: picoshare.FileLifetime{}, | ||
err: parse.ErrFileLifetimeTooShort, | ||
}, | ||
{ | ||
description: "rejects too long a lifetime", | ||
input: 3651, | ||
output: picoshare.FileLifetime{}, | ||
err: parse.ErrFileLifetimeTooLong, | ||
}, | ||
} { | ||
t.Run(tt.description, func(t *testing.T) { | ||
lt, err := parse.FileLifetime(tt.input) | ||
if got, want := err, tt.err; got != want { | ||
t.Fatalf("err=%v, want=%v", got, want) | ||
} | ||
if got, want := lt, tt.output; got != want { | ||
t.Errorf("lifetime=%s, want=%s", got.FriendlyName(), want.FriendlyName()) | ||
} | ||
}) | ||
} | ||
} |
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
Oops, something went wrong.