Skip to content

Commit 7577774

Browse files
committed
test(otp): cover FindOneTimeToken and add a seed helper
Pin the exact-hash path: no pkce_ match, the type filter applies, and either of two types is found. seedToken replaces the truncate, create user, insert row boilerplate in the hash lookup tests.
1 parent 5c364c8 commit 7577774

1 file changed

Lines changed: 40 additions & 13 deletions

File tree

‎internal/models/one_time_token_test.go‎

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ func (ts *OneTimeTokenTestSuite) createUser() *User {
4848
return u
4949
}
5050

51+
// seedToken starts from an empty table and returns the user who owns the row.
52+
func (ts *OneTimeTokenTestSuite) seedToken(hash string, tokenType OneTimeTokenType) *User {
53+
TruncateAll(ts.db)
54+
u := ts.createUser()
55+
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), hash, tokenType, time.Minute))
56+
return u
57+
}
58+
5159
func (ts *OneTimeTokenTestSuite) TestCreateOneTimeToken() {
5260
cases := map[string]time.Duration{
5361
"future window": 15 * time.Minute,
@@ -98,11 +106,37 @@ func (ts *OneTimeTokenTestSuite) TestCreateOneTimeTokenResendReplacesWindow() {
98106
"resend must move expires_at forward, first=%s second=%s", first.ExpiresAt, second.ExpiresAt)
99107
}
100108

109+
func (ts *OneTimeTokenTestSuite) TestFindOneTimeToken() {
110+
ts.Run("matches the exact hash only, not the pkce_ prefixed form", func() {
111+
ts.seedToken("pkce_hash", ConfirmationToken)
112+
113+
ott, err := FindOneTimeToken(ts.db, "hash", ConfirmationToken)
114+
require.True(ts.T(), IsNotFoundError(err), "expected not found error, got %v", err)
115+
require.Nil(ts.T(), ott)
116+
})
117+
118+
ts.Run("does not return a row of another token type", func() {
119+
ts.seedToken("hash", RecoveryToken)
120+
121+
ott, err := FindOneTimeToken(ts.db, "hash", ConfirmationToken)
122+
require.True(ts.T(), IsNotFoundError(err), "expected not found error, got %v", err)
123+
require.Nil(ts.T(), ott)
124+
})
125+
126+
ts.Run("matches either of two token types", func() {
127+
u := ts.seedToken("hash", RecoveryToken)
128+
129+
// The row has the second type, so this also checks the argument order.
130+
ott, err := FindOneTimeToken(ts.db, "hash", ConfirmationToken, RecoveryToken)
131+
require.NoError(ts.T(), err)
132+
require.Equal(ts.T(), RecoveryToken, ott.TokenType)
133+
require.Equal(ts.T(), u.ID, ott.UserID)
134+
})
135+
}
136+
101137
func (ts *OneTimeTokenTestSuite) TestFindOneTimeTokenWithPKCEFallback() {
102138
ts.Run("exact hash match", func() {
103-
TruncateAll(ts.db)
104-
u := ts.createUser()
105-
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), "hash", ConfirmationToken, time.Minute))
139+
u := ts.seedToken("hash", ConfirmationToken)
106140

107141
ott, err := FindOneTimeTokenWithPKCEFallback(ts.db, "hash", ConfirmationToken)
108142
require.NoError(ts.T(), err)
@@ -111,9 +145,7 @@ func (ts *OneTimeTokenTestSuite) TestFindOneTimeTokenWithPKCEFallback() {
111145
})
112146

113147
ts.Run("falls back to pkce_ prefixed hash", func() {
114-
TruncateAll(ts.db)
115-
u := ts.createUser()
116-
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), "pkce_hash", ConfirmationToken, time.Minute))
148+
u := ts.seedToken("pkce_hash", ConfirmationToken)
117149

118150
ott, err := FindOneTimeTokenWithPKCEFallback(ts.db, "hash", ConfirmationToken)
119151
require.NoError(ts.T(), err)
@@ -122,12 +154,9 @@ func (ts *OneTimeTokenTestSuite) TestFindOneTimeTokenWithPKCEFallback() {
122154
})
123155

124156
ts.Run("prefers exact match over pkce_ prefixed hash", func() {
125-
TruncateAll(ts.db)
126-
u := ts.createUser()
127-
128157
// (user_id, token_type) is unique, so the two candidates have to be
129158
// different types. Both types are passed so both are eligible.
130-
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), "hash", ConfirmationToken, time.Minute))
159+
u := ts.seedToken("hash", ConfirmationToken)
131160
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), "pkce_hash", RecoveryToken, time.Minute))
132161

133162
ott, err := FindOneTimeTokenWithPKCEFallback(ts.db, "hash", ConfirmationToken, RecoveryToken)
@@ -146,9 +175,7 @@ func (ts *OneTimeTokenTestSuite) TestFindOneTimeTokenWithPKCEFallback() {
146175
})
147176

148177
ts.Run("token type filter applies to the pkce_ fallback", func() {
149-
TruncateAll(ts.db)
150-
u := ts.createUser()
151-
require.NoError(ts.T(), CreateOneTimeToken(ts.db, u.ID, u.GetEmail(), "pkce_hash", RecoveryToken, time.Minute))
178+
ts.seedToken("pkce_hash", RecoveryToken)
152179

153180
ott, err := FindOneTimeTokenWithPKCEFallback(ts.db, "hash", ConfirmationToken)
154181
require.True(ts.T(), IsNotFoundError(err), "expected not found error, got %v", err)

0 commit comments

Comments
 (0)