Skip to content

Commit

Permalink
chore: tests rename -d
Browse files Browse the repository at this point in the history
  • Loading branch information
arpowers committed Mar 20, 2024
1 parent 850dce4 commit af05902
Show file tree
Hide file tree
Showing 41 changed files with 232 additions and 71 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ jobs:
- name: SPOT tests
run: npm exec -- vitest run @fiction/core/plugin-user/test/userUpdate.ci.test.ts -u

- name: DEV unit tests
run: npm exec -- vitest run wip -u --reporter=hanging-process --reporter=verbose

- name: STABLE unit tests
run: npm exec -- vitest run ci -u

Expand Down
8 changes: 0 additions & 8 deletions @fiction/core/envVars.ts

This file was deleted.

2 changes: 1 addition & 1 deletion @fiction/core/plugin-app/test/renderHtml.ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('serverRenderHtml', () => {
const html = await fictionRender.serverRenderHtml(params)

// Assert the results
expect(html.replace(testUtils.fictionApp.port.toString(), 'PORT')).toMatchInlineSnapshot(`"<!DOCTYPE html><html bar="foo"><head><headtags></headtags><preloadlinks></preloadlinks><link href="http://localhost:PORT" rel="canonical"><meta name="generator" content="FictionJS 6.0.4"></head><body foo="bar"><bodytagsopen></bodytagsopen><div id="app"><htmlbody></htmlbody></div><bodytags></bodytags><!--{"renderedPathname":"/","isProd":true}--></body></html>"`)
expect(html.replace(testUtils.fictionApp.port.toString(), 'PORT')).toMatchInlineSnapshot(`"<!DOCTYPE html><html bar="foo"><head><headtags></headtags><preloadlinks></preloadlinks><link href="http://localhost:PORT" rel="canonical"><meta name="generator" content="FictionJS 6.0.9"></head><body foo="bar"><bodytagsopen></bodytagsopen><div id="app"><htmlbody></htmlbody></div><bodytags></bodytags><!--{"renderedPathname":"/","isProd":true}--></body></html>"`)
expect(html).toContain('<headtags></headtags>'.toLowerCase())
expect(html).toContain('<htmlBody></htmlBody>'.toLowerCase())
expect(html).toContain('foo="bar"')
Expand Down
5 changes: 3 additions & 2 deletions @fiction/core/plugin-app/test/rendering.ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ describe('rendering tests', () => {
if (!testUtils)
return

const ohost = 'whatever.com'
// Mock the Request object
const headers = {
'host': 'example.com:3000',
'User-Agent': 'Mozilla/5.0',
'X-Original-Host': 'whatever.com',
'X-Original-Host': ohost,
'Custom-Header': 'value123',
}
const mockRequest = {
Expand Down Expand Up @@ -63,7 +64,7 @@ describe('rendering tests', () => {

expect(requestVars?.ALL_HEADERS).toContain('host: example.com:3000')
expect(requestVars?.ALL_HEADERS).toContain('User-Agent: Mozilla/5.0')
expect(requestVars?.ALL_HEADERS).toContain('X-Original-Host: whateverq.com')
expect(requestVars?.ALL_HEADERS).toContain(`X-Original-Host: ${ohost}`)
expect(requestVars?.ALL_HEADERS).toContain('Custom-Header: value123')
})
})
1 change: 0 additions & 1 deletion @fiction/core/plugin-env/test/.fiction/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface CompiledServiceConfig {
| 'GOOGLE_CLIENT_ID'
| 'GOOGLE_CLIENT_SECRET'
| 'IS_TEST'
| 'NGROK_AUTH_TOKEN'
| 'NODE_ENV'
| 'POSTGRES_URL'
| 'RUNTIME_COMMIT'
Expand Down
13 changes: 3 additions & 10 deletions @fiction/core/plugin-user/test/user.browser.ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,14 @@ describe('user tests', async () => {

expect(spy).toHaveBeenCalled()

// due to timeouts
delete user.geo

expect(snap(user, { maskedKeys: ['cityName', 'timezone', 'ipOrganization', 'latitude', 'longitude', 'regionName'] })).toMatchInlineSnapshot(`
{
"createdAt": "[dateTime:]",
"email": "[email:********+**********@*****.***]",
"fullName": "[name:****]",
"geo": {
"cityName": "**MASKED**",
"countryCode": "[hash:**]",
"ip": "",
"ipOrganization": "**MASKED**",
"latitude": "**MASKED**",
"longitude": "**MASKED**",
"regionName": "**MASKED**",
"timezone": "**MASKED**",
},
"lastSeenAt": "[dateTime:]",
"orgs": "[object Object]",
"role": "subscriber",
Expand Down
6 changes: 3 additions & 3 deletions @fiction/core/utils-analytics/geo.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { UserGeolocation } from '../types'
import { getNetworkIp, isLocalhostIp } from '../utils'
import { fetchWithTimeout, getNetworkIp, isLocalhostIp } from '../utils'
import { log } from '../plugin-log'

export interface GeoData {
Expand Down Expand Up @@ -35,7 +35,7 @@ interface ipApiResponse {

export async function getGeoFree(ip?: string): Promise<GeoData | undefined> {
try {
const fetched = await fetch(`http://ip-api.com/json/${ip}`, {
const fetched = await fetchWithTimeout(`http://ip-api.com/json/${ip}`, {
method: 'GET',
headers: { 'access-control-allow-origin': '*' },
})
Expand Down Expand Up @@ -113,7 +113,7 @@ export async function getGeo(ip?: string): Promise<GeoData | undefined> {
ip = await getNetworkIp()

try {
const fetched = await fetch(
const fetched = await fetchWithTimeout(
`https://api.db-ip.com/v2/c41c91295b5abead5e3db1dd9d237e282629f4c8/${ip}`,
{
method: 'GET',
Expand Down
139 changes: 139 additions & 0 deletions @fiction/core/utils-analytics/test/geo.ci.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it, vi } from 'vitest'
import { getGeo, getGeoFree, setUserGeolocation } from '../geo'
import { fetchWithTimeout, isLocalhostIp } from '../../utils'

// Mock the utilities used in the geo functions
vi.mock('../../utils', () => ({
fetchWithTimeout: vi.fn(),
isLocalhostIp: vi.fn(),
}))

describe('geo functions', () => {
describe('getGeoFree', () => {
it('should fetch free geo data successfully', async () => {
const mockIp = '123.123.123.123'
const mockApiResponse = {
query: mockIp,
country: 'United States',
countryCode: 'US',
city: 'San Francisco',
lat: 37.7749,
lon: -122.4194,
timezone: 'America/Los_Angeles',
regionName: 'California',
isp: 'ISP Name',
org: 'Organization Name',
}

vi.mocked(fetchWithTimeout).mockResolvedValueOnce({
json: () => Promise.resolve(mockApiResponse),
} as Response)

const expectedGeoData = {
ip: mockIp,
countryCode: 'US',
cityName: 'San Francisco',
latitude: 37.7749,
longitude: -122.4194,
timezone: 'America/Los_Angeles',
regionName: 'California',
ipOrganization: 'Organization Name',
}

const result = await getGeoFree(mockIp)

expect(result).toEqual(expectedGeoData)
expect(fetchWithTimeout).toHaveBeenCalledWith(`http://ip-api.com/json/${mockIp}`, expect.any(Object))
})
})

describe('getGeo', () => {
it('should fetch detailed geo data successfully', async () => {
const mockIp = '123.123.123.123'
const mockApiResponse = {
ipAddress: mockIp,
countryCode: 'US',
stateProv: 'California',
city: 'San Francisco',
latitude: 37.7749,
longitude: -122.4194,
timeZone: 'America/Los_Angeles',
isCrawler: false,
isProxy: false,
threatLevel: 'low',
org: 'ISP Name',
}

vi.mocked(fetchWithTimeout).mockResolvedValueOnce({
json: () => Promise.resolve(mockApiResponse),
} as Response)

const expectedGeoData = {
ip: mockIp,
countryCode: 'US',
cityName: 'San Francisco',
latitude: 37.7749,
longitude: -122.4194,
timezone: 'America/Los_Angeles',
regionName: 'California',
ipIsCrawler: false,
ipIsProxy: false,
ipThreatLevel: 'low',
ipOrganization: 'ISP Name',
}

const result = await getGeo(mockIp)

expect(result).toEqual(expectedGeoData)
expect(fetchWithTimeout).toHaveBeenCalled()
})


})

describe('setUserGeolocation', () => {
it('should fetch user geolocation data successfully', async () => {
const mockApiResponse = {
ip: '123.123.123.123',
country_code: 'US',
country_name: 'United States',
region_code: 'CA',
region_name: 'California',
city: 'San Francisco',
zip_code: '94016',
time_zone: 'America/Los_Angeles',
latitude: 37.7749,
longitude: -122.4194,
}

globalThis.fetch = vi.fn().mockResolvedValueOnce({
json: () => Promise.resolve(mockApiResponse),
})

const expectedGeoData = {
ip: '123.123.123.123',
countryCode: 'US',
countryName: 'United States',
regionCode: 'CA',
regionName: 'California',
city: 'San Francisco',
zip: '94016',
timeZone: 'America/Los_Angeles',
latitude: 37.7749,
longitude: -122.4194,
metroCode: undefined,
name: 'San Francisco, United States',
}

const result = await setUserGeolocation()

expect(result).toEqual(expectedGeoData)
expect(globalThis.fetch).toHaveBeenCalledWith('https://freegeoip.app/json/')
})


})
})
23 changes: 10 additions & 13 deletions @fiction/core/utils/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
/**
* Advanced fetch function that adds a timeout and format option to native fetch
*/
export async function fetchAdvanced<T = unknown>(resource: string, options?: { timeout?: number, format?: 'json' | 'text' }): Promise<T> {
const { timeout = 8000, format = 'json' } = options ?? {}
export async function fetchWithTimeout(url: string, options?: RequestInit & { timeout?: number }): Promise<Response> {
const { timeout = 5000, ...fetchOptions } = options || {}

const controller = new AbortController()
const id = setTimeout(() => controller.abort(), timeout)

const response = await window.fetch(resource, {
...options,
signal: controller.signal,
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => {
reject(new Error(`Request timed out after ${timeout} ms`))
}, timeout)
})

const out = (await response[format]()) as T

clearTimeout(id)

return out
return Promise.race([
fetch(url, fetchOptions),
timeoutPromise,
])
}
70 changes: 46 additions & 24 deletions @fiction/core/utils/test/fetch.ci.test.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,49 @@
/**
* @vitest-environment happy-dom
*/
import { describe, expect, it } from 'vitest'
import { fetchAdvanced } from '@fiction/core/utils/fetch'

describe('fetch', () => {
it('has window and fetch', () => {
expect(typeof window).toMatchInlineSnapshot('"object"')
expect(typeof window.fetch).toMatchInlineSnapshot('"function"')
expect(typeof fetch).toMatchInlineSnapshot('"function"')
import type { MockInstance } from 'vitest'
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
import { fetchWithTimeout } from '@fiction/core/utils/fetch'

describe('fetchWithTimeout', () => {
let fetchMock: MockInstance
beforeEach(() => {
fetchMock = vi.spyOn(globalThis, 'fetch')
})

afterEach(() => {
vi.restoreAllMocks()
})

it('should complete the fetch operation successfully before the timeout', async () => {
const mockResponse = new Response(JSON.stringify({ key: 'value' }), {
status: 200,
headers: { 'Content-Type': 'application/json' },
})

fetchMock.mockResolvedValueOnce(mockResponse)

const response = await fetchWithTimeout('https://jsonplaceholder.typicode.com/posts/1', { timeout: 3000 })
const data = await response.json()

expect(data).toEqual({ key: 'value' })
expect(fetchMock).toHaveBeenCalledTimes(1)
})
it('fetch advanced with timeout', async () => {
const result = await fetchAdvanced<Record<string, any>>(
'https://jsonplaceholder.typicode.com/todos/1',
)

expect(result).toMatchInlineSnapshot(`
{
"completed": false,
"id": 1,
"title": "delectus aut autem",
"userId": 1,
}
`)

it('should abort the fetch operation after the timeout', async () => {
// Mock a fetch implementation that will not resolve or reject within the test timeout,
// simulating a long-running request that will be aborted.
fetchMock.mockImplementationOnce(() => new Promise(() => {}))

const fetchPromise = fetchWithTimeout('https://jsonplaceholder.typicode.com/posts/1', { timeout: 1000 })

await expect(fetchPromise).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: Request timed out after 1000 ms]`)

expect(fetchMock).toHaveBeenCalledTimes(1)
})

it('should handle network or other fetch related errors gracefully', async () => {
const errorMessage = 'Network error'
fetchMock.mockRejectedValueOnce(new Error(errorMessage))

await expect(fetchWithTimeout('https://jsonplaceholder.typicode.com/posts/1')).rejects.toThrow(errorMessage)
expect(fetchMock).toHaveBeenCalledTimes(1)
})
})
4 changes: 2 additions & 2 deletions @fiction/core/utils/test/fonts.ci.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe('getThemeFontConfig', () => {
expect(result).toMatchInlineSnapshot(`
{
"body": "'Source Serif 4', Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif",
"getFontsUrl": [Function],
"fontsUrl": "https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&family=Source+Serif+4:ital,wght@0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap",
"input": "'DM Mono', 'Roboto', Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif",
"mono": "'DM Mono', 'Nimbus Mono PS', 'Courier New', monospace",
"sans": "'Roboto', Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif",
Expand Down Expand Up @@ -96,7 +96,7 @@ describe('getThemeFontConfig', () => {
expect(result).toMatchInlineSnapshot(`
{
"body": "'Custom Serif', Charter, 'Bitstream Charter', 'Sitka Text', Cambria, serif",
"getFontsUrl": [Function],
"fontsUrl": "https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap",
"input": "'Roboto', Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif",
"mono": "'Custom Mono', 'DM Mono', 'Nimbus Mono PS', 'Courier New', monospace",
"sans": "'Roboto', Inter, Roboto, 'Helvetica Neue', 'Arial Nova', 'Nimbus Sans', Arial, sans-serif",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ describe('siteRendering Tests', async () => {
await testUtils.init()

subDomain = shortId()
const hostname = `${subDomain}.fiction.com`

const common = {
fictionSites: testUtils.fictionSites,
siteRouter: testUtils.fictionRouterSites,
parentRouter: testUtils.fictionRouter,
siteMode: 'standard',
} as const

Expand Down Expand Up @@ -53,7 +53,7 @@ describe('siteRendering Tests', async () => {

const mountEl = document.createElement('div')
const { init: _, initialized: __, close: ___, ...service } = testUtils
const entry = await testUtils.fictionAppSites.mountApp({ mountEl, service, runVars: { SUBDOMAIN: subDomain } })
const entry = await testUtils.fictionAppSites.mountApp({ mountEl, service, runVars: { HOSTNAME: hostname } })

await waitFor(300)

Expand Down
Loading

0 comments on commit af05902

Please sign in to comment.