chore: add e2e test for refresh tokens cooldown period - skip e2e (#2860)
* chore: add e2e test for refresh tokens cooldown period * chore: fix refreshing session in e2e * chore: fix session refresh cooldown test * chore: fix e2e test * Add dropped response simulation test --------- Co-authored-by: moughxyz <mo@standardnotes.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { LoggerInterface, joinPaths, sleep } from '@standardnotes/utils'
|
||||
import { Environment } from '@standardnotes/models'
|
||||
import { LegacySession, Session, SessionToken } from '@standardnotes/domain-core'
|
||||
import { LegacySession, Result, Session, SessionToken } from '@standardnotes/domain-core'
|
||||
import {
|
||||
HttpStatusCode,
|
||||
HttpRequestParams,
|
||||
@@ -23,10 +23,11 @@ import { HttpRequestOptions } from './HttpRequestOptions'
|
||||
export class HttpService implements HttpServiceInterface {
|
||||
private session?: Session | LegacySession
|
||||
private __latencySimulatorMs?: number
|
||||
private __simulateNextSessionRefreshResponseDrop = false
|
||||
private declare host: string
|
||||
loggingEnabled = false
|
||||
|
||||
private inProgressRefreshSessionPromise?: Promise<boolean>
|
||||
private inProgressRefreshSessionPromise?: Promise<Result<HttpResponse<SessionRefreshResponseBody>>>
|
||||
private updateMetaCallback!: (meta: HttpResponseMeta) => void
|
||||
private refreshSessionCallback!: (session: Session) => void
|
||||
|
||||
@@ -173,12 +174,19 @@ export class HttpService implements HttpServiceInterface {
|
||||
if (this.inProgressRefreshSessionPromise) {
|
||||
await this.inProgressRefreshSessionPromise
|
||||
} else {
|
||||
this.inProgressRefreshSessionPromise = this.refreshSession()
|
||||
const isSessionRefreshed = await this.inProgressRefreshSessionPromise
|
||||
this.inProgressRefreshSessionPromise = undefined
|
||||
const hasSessionTokenRenewedInBetweenOurRequest = httpRequest.authentication !== this.getSessionAccessToken()
|
||||
if (!hasSessionTokenRenewedInBetweenOurRequest) {
|
||||
this.inProgressRefreshSessionPromise = this.refreshSession()
|
||||
const isSessionRefreshedResultOrError = await this.inProgressRefreshSessionPromise
|
||||
let isSessionRefreshed = false
|
||||
if (!isSessionRefreshedResultOrError.isFailed()) {
|
||||
isSessionRefreshed = !isErrorResponse(isSessionRefreshedResultOrError.getValue())
|
||||
}
|
||||
this.inProgressRefreshSessionPromise = undefined
|
||||
|
||||
if (!isSessionRefreshed) {
|
||||
return response
|
||||
if (!isSessionRefreshed) {
|
||||
return response
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,13 +198,13 @@ export class HttpService implements HttpServiceInterface {
|
||||
return response
|
||||
}
|
||||
|
||||
async refreshSession(): Promise<boolean> {
|
||||
async refreshSession(): Promise<Result<HttpResponse<SessionRefreshResponseBody>>> {
|
||||
if (!this.session) {
|
||||
return false
|
||||
return Result.fail('No session to refresh')
|
||||
}
|
||||
|
||||
if (this.session instanceof LegacySession) {
|
||||
return false
|
||||
return Result.fail('Cannot refresh legacy session')
|
||||
}
|
||||
|
||||
const response = await this.post<SessionRefreshResponseBody>(Paths.v1.refreshSession, {
|
||||
@@ -204,8 +212,13 @@ export class HttpService implements HttpServiceInterface {
|
||||
refresh_token: this.session.refreshToken.value,
|
||||
})
|
||||
|
||||
if (this.__simulateNextSessionRefreshResponseDrop) {
|
||||
this.__simulateNextSessionRefreshResponseDrop = false
|
||||
return Result.fail('Simulating a dropped response')
|
||||
}
|
||||
|
||||
if (isErrorResponse(response)) {
|
||||
return false
|
||||
return Result.ok(response)
|
||||
}
|
||||
|
||||
if (response.meta) {
|
||||
@@ -217,7 +230,7 @@ export class HttpService implements HttpServiceInterface {
|
||||
response.data.session.access_expiration,
|
||||
)
|
||||
if (accessTokenOrError.isFailed()) {
|
||||
return false
|
||||
return Result.fail(accessTokenOrError.getError())
|
||||
}
|
||||
|
||||
const accessToken = accessTokenOrError.getValue()
|
||||
@@ -227,21 +240,21 @@ export class HttpService implements HttpServiceInterface {
|
||||
response.data.session.refresh_expiration,
|
||||
)
|
||||
if (refreshTokenOrError.isFailed()) {
|
||||
return false
|
||||
return Result.fail(refreshTokenOrError.getError())
|
||||
}
|
||||
|
||||
const refreshToken = refreshTokenOrError.getValue()
|
||||
|
||||
const sessionOrError = Session.create(accessToken, refreshToken, response.data.session.readonly_access)
|
||||
if (sessionOrError.isFailed()) {
|
||||
return false
|
||||
return Result.fail(sessionOrError.getError())
|
||||
}
|
||||
|
||||
this.setSession(sessionOrError.getValue())
|
||||
|
||||
this.refreshSessionCallback(this.session)
|
||||
|
||||
return true
|
||||
return Result.ok(response)
|
||||
}
|
||||
|
||||
private params(inParams: Record<string | number | symbol, unknown>): HttpRequestParams {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { LegacySession, Session } from '@standardnotes/domain-core'
|
||||
import { LegacySession, Result, Session } from '@standardnotes/domain-core'
|
||||
import { HttpRequest, HttpRequestParams, HttpResponse, HttpResponseMeta } from '@standardnotes/responses'
|
||||
|
||||
import { HttpRequestOptions } from './HttpRequestOptions'
|
||||
import { SessionRefreshResponseBody } from '../Response'
|
||||
|
||||
export interface HttpServiceInterface {
|
||||
setHost(host: string): void
|
||||
@@ -16,7 +17,7 @@ export interface HttpServiceInterface {
|
||||
runHttp<T>(httpRequest: HttpRequest): Promise<HttpResponse<T>>
|
||||
|
||||
setSession(session: Session | LegacySession): void
|
||||
refreshSession(): Promise<boolean>
|
||||
refreshSession(): Promise<Result<HttpResponse<SessionRefreshResponseBody>>>
|
||||
setCallbacks(
|
||||
updateMetaCallback: (meta: HttpResponseMeta) => void,
|
||||
refreshSessionCallback: (session: Session) => void,
|
||||
|
||||
Reference in New Issue
Block a user