-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #276 from jrhender/miniflare-jest-env
Initial test around stampy.ts
- Loading branch information
Showing
11 changed files
with
118,436 additions
and
42 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
117,380 changes: 117,380 additions & 0 deletions
117,380
app/mocks/coda-responses/cached-coda-responses.json
Large diffs are not rendered by default.
Oops, something went wrong.
128 changes: 128 additions & 0 deletions
128
app/mocks/coda-responses/refresh-coda-data-for-tests.ts
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,128 @@ | ||
/** | ||
* This is a script to refresh the mock return data for tests. | ||
*/ | ||
|
||
import * as fs from 'fs' | ||
import _ from 'lodash' | ||
import * as path from 'path' | ||
import * as toml from 'toml' | ||
import { | ||
ALL_ANSWERS_TABLE, | ||
BANNERS_TABLE, | ||
QUESTION_DETAILS_TABLE, | ||
TAGS_TABLE, | ||
makeCodaRequest, | ||
} from '../../server-utils/coda-urls' | ||
|
||
async function main(): Promise<void> { | ||
const codaRequestsToCache: CodaRequestParams[] = [ | ||
{ | ||
table: QUESTION_DETAILS_TABLE, | ||
queryColumn: 'UI ID', | ||
queryValue: '0', | ||
}, | ||
{ | ||
table: ALL_ANSWERS_TABLE, | ||
}, | ||
{ | ||
table: TAGS_TABLE, | ||
queryColumn: 'Internal?', | ||
queryValue: 'false', | ||
}, | ||
{ | ||
table: BANNERS_TABLE, | ||
}, | ||
] | ||
|
||
const cacheResults: CachedCodaQueries = await Promise.all( | ||
codaRequestsToCache.map(async (codaParams) => { | ||
const cachedRequests = await getCodaData(codaParams) | ||
return {codaParams, cachedRequests} | ||
}) | ||
) | ||
const writeData = JSON.stringify(cacheResults, null, 2) | ||
const filename = `cached-coda-responses.json` | ||
await writeFile(writeData, filename) | ||
} | ||
|
||
export type CachedCodaQueries = Array<CachedCodaQuery> | ||
type CachedCodaQuery = { | ||
codaParams: CodaRequestParams | ||
cachedRequests: CachedRequest[] | ||
} | ||
type CodaRequestParams = { | ||
table: string | ||
queryColumn?: string | ||
queryValue?: string | ||
} | ||
type CachedRequest = { | ||
url: string | ||
httpMethod: string | ||
responseData: any | ||
} | ||
|
||
const getCodaData = async (codaRequestParams: CodaRequestParams) => { | ||
const codaUrl = makeCodaRequest(codaRequestParams) | ||
console.log(`Fetching ${codaUrl}`) | ||
const cachedRequests: CachedRequest[] = [] | ||
await paginatedGet(codaUrl, cachedRequests) | ||
return cachedRequests | ||
} | ||
|
||
const paginatedGet = async (url: string, responses: any[]) => { | ||
const responseData = await getData(url) | ||
const data = {url, httpMethod: 'GET', responseData} | ||
responses.push(data) | ||
|
||
if (responseData.nextPageLink) { | ||
await paginatedGet(responseData.nextPageLink, responses) | ||
} | ||
return | ||
} | ||
|
||
const readCodaToken = (): string => { | ||
const tokenFromEnv = process.env.CODA_TOKEN | ||
if (tokenFromEnv) { | ||
console.log('found Coda token from environment') | ||
return tokenFromEnv | ||
} | ||
const wranglerToml = fs.readFileSync('wrangler.toml', 'utf8') | ||
const config = toml.parse(wranglerToml) | ||
const tokenFromToml: string = config.vars.CODA_TOKEN | ||
if (tokenFromToml) { | ||
console.log('found Coda token from wrangler config') | ||
return tokenFromToml | ||
} | ||
|
||
throw Error('unable to get a Coda token') | ||
} | ||
|
||
const getDataWithAuthz = async (url: string, authzToken: string) => { | ||
const options = { | ||
headers: { | ||
Authorization: `Bearer ${authzToken}`, | ||
}, | ||
} | ||
const response = await fetch(url, options) | ||
return await response.json() | ||
} | ||
|
||
const getData = _.partialRight(getDataWithAuthz, readCodaToken()) | ||
|
||
const writeFile = (data: string, filename: string): Promise<void> => { | ||
const filePath = path.join(__dirname, filename) | ||
|
||
return new Promise((resolve, reject) => { | ||
fs.writeFile(filePath, data, (err) => { | ||
if (err) { | ||
console.error('An error occurred:', err) | ||
reject(err) | ||
} else { | ||
console.log('File has been written successfully.') | ||
resolve() | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
main() |
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,36 @@ | ||
/** | ||
* This file contains the URLs for the Coda API. | ||
* It is a separate file in part so usage doesn't require CF worker env vars. | ||
*/ | ||
|
||
// Use table ide, rather than names, in case of renames | ||
export const QUESTION_DETAILS_TABLE = 'grid-sync-1059-File' // Answers | ||
export const INITIAL_QUESTIONS_TABLE = 'table-yWog6qRzV4' // Initial questions | ||
export const ON_SITE_TABLE = 'table-aOTSHIz_mN' // On-site answers | ||
export const ALL_ANSWERS_TABLE = 'table-YvPEyAXl8a' // All answers | ||
export const INCOMING_QUESTIONS_TABLE = 'grid-S_6SYj6Tjm' // Incoming questions | ||
export const TAGS_TABLE = 'grid-4uOTjz1Rkz' | ||
export const WRITES_TABLE = 'table-eEhx2YPsBE' | ||
export const GLOSSARY_TABLE = 'grid-_pSzs23jmw' | ||
export const BANNERS_TABLE = 'grid-3WgZ9_NkvO' | ||
|
||
type CodaRequest = { | ||
table: string | ||
queryColumn?: string | ||
queryValue?: string | ||
limit?: number | ||
} | ||
export const makeCodaRequest = ({table, queryColumn, queryValue, limit}: CodaRequest): string => { | ||
let params = `useColumnNames=true&sortBy=natural&valueFormat=rich${ | ||
queryColumn && queryValue ? `&query=${quote(queryColumn)}:${quote(queryValue)}` : '' | ||
}` | ||
if (limit) { | ||
params = `${params}&limit=${limit}` | ||
} | ||
return `https://coda.io/apis/v1/docs/${CODA_DOC_ID}/tables/${enc(table)}/rows?${params}` | ||
} | ||
|
||
export const CODA_DOC_ID = 'fau7sl2hmG' | ||
|
||
const enc = encodeURIComponent | ||
const quote = (x: string) => encodeURIComponent(`"${x.replace(/"/g, '\\"')}"`) |
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,54 @@ | ||
import {loadQuestionDetail} from '~/server-utils/stampy' | ||
import cachedCodaQueriesJson from '~/mocks/coda-responses/cached-coda-responses.json' | ||
import {QUESTION_DETAILS_TABLE} from './coda-urls' | ||
import {CachedCodaQueries} from '~/mocks/coda-responses/refresh-coda-data-for-tests' | ||
import _ from 'lodash' | ||
|
||
export const questions: Array<string> = ['0'] | ||
const cachedQueries = cachedCodaQueriesJson as CachedCodaQueries | ||
|
||
describe('loadQuestionDetail', () => { | ||
it.each<string>(questions)('can load question %i', async (questionId) => { | ||
const fetchMock = getMiniflareFetchMock() | ||
fetchMock.disableNetConnect() | ||
const mockCodaRequest = _.partial(mockCodaRequestUsingMiniflareFetchMock, fetchMock) | ||
const allCachedRequests = cachedQueries.flatMap((codaQuery) => codaQuery.cachedRequests) | ||
for (const cachedRequest of allCachedRequests) { | ||
mockCodaRequest(cachedRequest.url, cachedRequest.responseData) | ||
} | ||
|
||
const cachedQuery = cachedQueries.find((cachedQuery) => | ||
_.isEqual(cachedQuery.codaParams, { | ||
table: QUESTION_DETAILS_TABLE, | ||
queryColumn: 'UI ID', | ||
queryValue: questionId, | ||
}) | ||
) | ||
if (!cachedQuery) { | ||
throw new Error(`Cached response not found for question ${questionId}`) | ||
} | ||
|
||
const questionDetail = await loadQuestionDetail('NEVER_RELOAD', questionId) | ||
|
||
const cachedQuestionData = cachedQuery.cachedRequests[0].responseData | ||
const firstItem = cachedQuestionData.items[0] | ||
expect(questionDetail.data.status).toBe(firstItem.values.Status.name) | ||
const linkUrl = new URL(firstItem.values.Link.url) | ||
expect(questionDetail.data.answerEditLink).toBe(linkUrl.origin + linkUrl.pathname) | ||
}) | ||
}) | ||
|
||
const mockCodaRequestUsingMiniflareFetchMock = async ( | ||
fetchMock: ReturnType<typeof getMiniflareFetchMock>, | ||
urlString: string, | ||
responseData: any | ||
) => { | ||
const url = new URL(urlString) | ||
const origin = fetchMock.get(`${url.origin}`) | ||
origin | ||
.intercept({ | ||
method: 'GET', | ||
path: url.href.replace(url.origin, ''), | ||
}) | ||
.reply(200, responseData) | ||
} |
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 |
---|---|---|
@@ -1,5 +1,8 @@ | ||
/** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
testEnvironment: 'miniflare', | ||
moduleNameMapper: { | ||
'^~/(.*)$': '<rootDir>/app/$1', | ||
}, | ||
} |
Oops, something went wrong.