diff --git a/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.test.tsx b/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.test.tsx
index ea9db1729c..aac659ace7 100644
--- a/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.test.tsx
+++ b/packages/app/src/cli/services/app-logs/logs-command/ui/components/Logs.test.tsx
@@ -45,117 +45,6 @@ const NETWORK_ACCESS_HTTP_RESPONSE = {
},
}
-const USE_POLL_APP_LOGS_RETURN_VALUE = {
- appLogOutputs: [
- {
- appLog: new FunctionRunLog({
- export: 'run',
- input: INPUT,
- inputBytes: INPUT_BYTES,
- output: OUTPUT,
- outputBytes: OUTPUT_BYTES,
- logs: LOGS,
- functionId: FUNCTION_ID,
- fuelConsumed: FUEL_CONSUMED,
- errorMessage: 'errorMessage',
- errorType: 'errorType',
- inputQueryVariablesMetafieldValue: '{"key":"value"}',
- inputQueryVariablesMetafieldNamespace: 'inputQueryVariablesMetafieldNamespace',
- inputQueryVariablesMetafieldKey: 'inputQueryVariablesMetafieldKey',
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: `export "run" executed in 0.5124M instructions`,
- storeName: 'my-store',
- status: STATUS === 'success' ? 'Success' : 'Failure',
- source: SOURCE,
- },
- },
- {
- appLog: new NetworkAccessResponseFromCacheLog({
- cacheEntryEpochMs: 1683904621000,
- cacheTtlMs: 300000,
- httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
- httpResponse: NETWORK_ACCESS_HTTP_RESPONSE,
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: 'network access response from cache',
- storeName: 'my-store',
- status: 'Success',
- source: SOURCE,
- },
- },
- {
- appLog: new NetworkAccessRequestExecutedLog({
- attempt: 1,
- connectTimeMs: 40,
- writeReadTimeMs: 40,
- httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
- httpResponse: NETWORK_ACCESS_HTTP_RESPONSE,
- error: null,
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: 'network access request executed in 80 ms',
- status: 'Success',
- storeName: 'my-store',
- source: SOURCE,
- },
- },
- {
- appLog: new NetworkAccessRequestExecutedLog({
- attempt: 1,
- connectTimeMs: null,
- writeReadTimeMs: null,
- httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
- httpResponse: null,
- error: 'Timeout Error',
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: 'network access request executed',
- storeName: 'my-store',
- status: 'Failure',
- source: SOURCE,
- },
- },
- {
- appLog: new NetworkAccessRequestExecutionInBackgroundLog({
- reason: BackgroundExecutionReason.NoCachedResponse,
- httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: 'network access request executing in background',
- storeName: 'my-store',
- status: 'Success',
- source: SOURCE,
- },
- },
- {
- appLog: new NetworkAccessRequestExecutionInBackgroundLog({
- reason: BackgroundExecutionReason.CacheAboutToExpire,
- httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
- }),
- prefix: {
- functionId: FUNCTION_ID,
- logTimestamp: TIME,
- description: 'network access request executing in background',
- storeName: 'my-store',
- status: 'Success',
- source: SOURCE,
- },
- },
- ],
- errors: [],
-}
-
const USE_POLL_APP_LOGS_ERRORS_RETURN_VALUE = {
errors: ['Test Error'],
appLogOutputs: [],
@@ -167,129 +56,471 @@ STORE_NAME_BY_ID.set('1', 'my-store')
const EMPTY_FILTERS = {status: undefined, sources: undefined}
describe('Logs', () => {
- test('renders prefix and applogs', async () => {
- // Given
- const mockedUsePollAppLogs = vi.fn().mockReturnValue(USE_POLL_APP_LOGS_RETURN_VALUE)
- vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
- // When
- const renderInstance = render(
- ,
- )
+ describe('App Logs', () => {
+ test('renders FunctionRunLog correctly with metafield data', async () => {
+ const appLogOutput = {
+ appLog: new FunctionRunLog({
+ export: 'run',
+ input: INPUT,
+ inputBytes: INPUT_BYTES,
+ output: OUTPUT,
+ outputBytes: OUTPUT_BYTES,
+ logs: LOGS,
+ functionId: FUNCTION_ID,
+ fuelConsumed: FUEL_CONSUMED,
+ errorMessage: 'errorMessage',
+ errorType: 'errorType',
+ inputQueryVariablesMetafieldValue: '{"key":"value"}',
+ inputQueryVariablesMetafieldNamespace: 'inputQueryVariablesMetafieldNamespace',
+ inputQueryVariablesMetafieldKey: 'inputQueryVariablesMetafieldKey',
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: `export "run" executed in 0.5124M instructions`,
+ storeName: 'my-store',
+ status: STATUS === 'success' ? 'Success' : 'Failure',
+ source: SOURCE,
+ },
+ }
- // Then
- const lastFrame = renderInstance.lastFrame()
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [appLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
- expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
- "2024-06-18 16:02:04.868 my-store my-function Success export \\"run\\" executed in 0.5124M instructions
- test logs
+ const renderInstance = render(
+ ,
+ )
- Input Query Variables:
+ const lastFrame = renderInstance.lastFrame()
- Namespace: inputQueryVariablesMetafieldNamespace
- Key: inputQueryVariablesMetafieldKey
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success export \\"run\\" executed in 0.5124M instructions
+ test logs
- {
- \\"key\\": \\"value\\"
- }
+ Input Query Variables:
- Input (10 bytes):
+ Namespace: inputQueryVariablesMetafieldNamespace
+ Key: inputQueryVariablesMetafieldKey
- {
- \\"test\\": \\"input\\"
- }
+ {
+ \\"key\\": \\"value\\"
+ }
- Output (10 bytes):
+ Input (10 bytes):
- {
- \\"test\\": \\"output\\"
- }
- 2024-06-18 16:02:04.868 my-store my-function Success network access response from cache
- Cache write time: 2023-05-12T15:17:01.000Z
- Cache TTL: 300 s
- HTTP request:
- {
- \\"url\\": \\"https://api.example.com/hello\\",
- \\"method\\": \\"GET\\",
- \\"headers\\": {},
- \\"body\\": null,
- \\"policy\\": {
- \\"read_timeout_ms\\": 500
- }
- }
- HTTP response:
- {
- \\"status\\": 200,
- \\"body\\": \\"Success\\",
- \\"headers\\": {
- \\"header1\\": \\"value1\\"
- }
- }
- 2024-06-18 16:02:04.868 my-store my-function Success network access request executed in 80 ms
- Attempt: 1
- Connect time: 40 ms
- Write read time: 40 ms
- HTTP request:
- {
- \\"url\\": \\"https://api.example.com/hello\\",
- \\"method\\": \\"GET\\",
- \\"headers\\": {},
- \\"body\\": null,
- \\"policy\\": {
- \\"read_timeout_ms\\": 500
- }
- }
- HTTP response:
- {
- \\"status\\": 200,
- \\"body\\": \\"Success\\",
- \\"headers\\": {
- \\"header1\\": \\"value1\\"
- }
- }
- 2024-06-18 16:02:04.868 my-store my-function Failure network access request executed
- Attempt: 1
- HTTP request:
- {
- \\"url\\": \\"https://api.example.com/hello\\",
- \\"method\\": \\"GET\\",
- \\"headers\\": {},
- \\"body\\": null,
- \\"policy\\": {
- \\"read_timeout_ms\\": 500
+ {
+ \\"test\\": \\"input\\"
+ }
+
+ Output (10 bytes):
+
+ {
+ \\"test\\": \\"output\\"
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ test('renders FunctionRunLog correctly with nil metafield value', async () => {
+ const appLogOutput = {
+ appLog: new FunctionRunLog({
+ export: 'run',
+ input: INPUT,
+ inputBytes: INPUT_BYTES,
+ output: OUTPUT,
+ outputBytes: OUTPUT_BYTES,
+ logs: LOGS,
+ functionId: FUNCTION_ID,
+ fuelConsumed: FUEL_CONSUMED,
+ errorMessage: 'errorMessage',
+ errorType: 'errorType',
+ inputQueryVariablesMetafieldValue: null,
+ inputQueryVariablesMetafieldNamespace: 'inputQueryVariablesMetafieldNamespace',
+ inputQueryVariablesMetafieldKey: 'inputQueryVariablesMetafieldKey',
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: `export "run" executed in 0.5124M instructions`,
+ storeName: 'my-store',
+ status: STATUS === 'success' ? 'Success' : 'Failure',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [appLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success export \\"run\\" executed in 0.5124M instructions
+ test logs
+
+ Input Query Variables:
+
+ Namespace: inputQueryVariablesMetafieldNamespace
+ Key: inputQueryVariablesMetafieldKey
+
+ No metafield data found!
+
+ Input (10 bytes):
+
+ {
+ \\"test\\": \\"input\\"
+ }
+
+ Output (10 bytes):
+
+ {
+ \\"test\\": \\"output\\"
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ test('redners FunctionRunLog without iqv when key and namespace are null', async () => {
+ const appLogOutput = {
+ appLog: new FunctionRunLog({
+ export: 'run',
+ input: INPUT,
+ inputBytes: INPUT_BYTES,
+ output: OUTPUT,
+ outputBytes: OUTPUT_BYTES,
+ logs: LOGS,
+ functionId: FUNCTION_ID,
+ fuelConsumed: FUEL_CONSUMED,
+ errorMessage: 'errorMessage',
+ errorType: 'errorType',
+ inputQueryVariablesMetafieldValue: null,
+ inputQueryVariablesMetafieldNamespace: null,
+ inputQueryVariablesMetafieldKey: null,
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: `export "run" executed in 0.5124M instructions`,
+ storeName: 'my-store',
+ status: STATUS === 'success' ? 'Success' : 'Failure',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [appLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success export \\"run\\" executed in 0.5124M instructions
+ test logs
+
+ Input (10 bytes):
+
+ {
+ \\"test\\": \\"input\\"
+ }
+
+ Output (10 bytes):
+
+ {
+ \\"test\\": \\"output\\"
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+ })
+
+ describe('Webhooks', () => {
+ test('renders NetworkAccessResponseFromCacheLog correctly', async () => {
+ const webhookLogOutput = {
+ appLog: new NetworkAccessResponseFromCacheLog({
+ cacheEntryEpochMs: 1683904621000,
+ cacheTtlMs: 300000,
+ httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
+ httpResponse: NETWORK_ACCESS_HTTP_RESPONSE,
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: 'network access response from cache',
+ storeName: 'my-store',
+ status: 'Success',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [webhookLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success network access response from cache
+ Cache write time: 2023-05-12T15:17:01.000Z
+ Cache TTL: 300 s
+ HTTP request:
+ {
+ \\"url\\": \\"https://api.example.com/hello\\",
+ \\"method\\": \\"GET\\",
+ \\"headers\\": {},
+ \\"body\\": null,
+ \\"policy\\": {
+ \\"read_timeout_ms\\": 500
+ }
}
- }
- Error: Timeout Error
- 2024-06-18 16:02:04.868 my-store my-function Success network access request executing in background
- Reason: No cached response available
- HTTP request:
- {
- \\"url\\": \\"https://api.example.com/hello\\",
- \\"method\\": \\"GET\\",
- \\"headers\\": {},
- \\"body\\": null,
- \\"policy\\": {
- \\"read_timeout_ms\\": 500
+ HTTP response:
+ {
+ \\"status\\": 200,
+ \\"body\\": \\"Success\\",
+ \\"headers\\": {
+ \\"header1\\": \\"value1\\"
+ }
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ test('renders NetworkAccessRequestExecutedLog correctly with success', async () => {
+ const webhookLogOutput = {
+ appLog: new NetworkAccessRequestExecutedLog({
+ attempt: 1,
+ connectTimeMs: 40,
+ writeReadTimeMs: 40,
+ httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
+ httpResponse: NETWORK_ACCESS_HTTP_RESPONSE,
+ error: null,
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: 'network access request executed in 80 ms',
+ status: 'Success',
+ storeName: 'my-store',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [webhookLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success network access request executed in 80 ms
+ Attempt: 1
+ Connect time: 40 ms
+ Write read time: 40 ms
+ HTTP request:
+ {
+ \\"url\\": \\"https://api.example.com/hello\\",
+ \\"method\\": \\"GET\\",
+ \\"headers\\": {},
+ \\"body\\": null,
+ \\"policy\\": {
+ \\"read_timeout_ms\\": 500
+ }
}
- }
- 2024-06-18 16:02:04.868 my-store my-function Success network access request executing in background
- Reason: Cache is about to expire
- HTTP request:
- {
- \\"url\\": \\"https://api.example.com/hello\\",
- \\"method\\": \\"GET\\",
- \\"headers\\": {},
- \\"body\\": null,
- \\"policy\\": {
- \\"read_timeout_ms\\": 500
+ HTTP response:
+ {
+ \\"status\\": 200,
+ \\"body\\": \\"Success\\",
+ \\"headers\\": {
+ \\"header1\\": \\"value1\\"
+ }
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ test('renders NetworkAccessRequestExecutedLog correctly with failure', async () => {
+ const webhookLogOutput = {
+ appLog: new NetworkAccessRequestExecutedLog({
+ attempt: 1,
+ connectTimeMs: null,
+ writeReadTimeMs: null,
+ httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
+ httpResponse: null,
+ error: 'Timeout Error',
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: 'network access request executed',
+ storeName: 'my-store',
+ status: 'Failure',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [webhookLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Failure network access request executed
+ Attempt: 1
+ HTTP request:
+ {
+ \\"url\\": \\"https://api.example.com/hello\\",
+ \\"method\\": \\"GET\\",
+ \\"headers\\": {},
+ \\"body\\": null,
+ \\"policy\\": {
+ \\"read_timeout_ms\\": 500
+ }
}
- }"
- `)
+ Error: Timeout Error"
+ `)
- renderInstance.unmount()
+ renderInstance.unmount()
+ })
+
+ test('renders NetworkAccessRequestExecutionInBackgroundLog correctly with NoCachedResponse', async () => {
+ const webhookLogOutput = {
+ appLog: new NetworkAccessRequestExecutionInBackgroundLog({
+ reason: BackgroundExecutionReason.NoCachedResponse,
+ httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: 'network access request executing in background',
+ storeName: 'my-store',
+ status: 'Success',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [webhookLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success network access request executing in background
+ Reason: No cached response available
+ HTTP request:
+ {
+ \\"url\\": \\"https://api.example.com/hello\\",
+ \\"method\\": \\"GET\\",
+ \\"headers\\": {},
+ \\"body\\": null,
+ \\"policy\\": {
+ \\"read_timeout_ms\\": 500
+ }
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ test('renders NetworkAccessRequestExecutionInBackgroundLog correctly with CacheAboutToExpire', async () => {
+ const webhookLogOutput = {
+ appLog: new NetworkAccessRequestExecutionInBackgroundLog({
+ reason: BackgroundExecutionReason.CacheAboutToExpire,
+ httpRequest: NETWORK_ACCESS_HTTP_REQUEST,
+ }),
+ prefix: {
+ functionId: FUNCTION_ID,
+ logTimestamp: TIME,
+ description: 'network access request executing in background',
+ storeName: 'my-store',
+ status: 'Success',
+ source: SOURCE,
+ },
+ }
+
+ const mockedUsePollAppLogs = vi.fn().mockReturnValue({appLogOutputs: [webhookLogOutput], errors: []})
+ vi.mocked(usePollAppLogs).mockImplementation(mockedUsePollAppLogs)
+
+ const renderInstance = render(
+ ,
+ )
+
+ const lastFrame = renderInstance.lastFrame()
+
+ expect(unstyled(lastFrame!)).toMatchInlineSnapshot(`
+ "2024-06-18 16:02:04.868 my-store my-function Success network access request executing in background
+ Reason: Cache is about to expire
+ HTTP request:
+ {
+ \\"url\\": \\"https://api.example.com/hello\\",
+ \\"method\\": \\"GET\\",
+ \\"headers\\": {},
+ \\"body\\": null,
+ \\"policy\\": {
+ \\"read_timeout_ms\\": 500
+ }
+ }"
+ `)
+
+ renderInstance.unmount()
+ })
+
+ // Add more tests for other webhook log types (NetworkAccessRequestExecutedLog, NetworkAccessRequestExecutionInBackgroundLog)
})
test('handles errors', async () => {