mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-09-24 21:40:48 +02:00
feat(tests): add api e2e tests (#3617)
* feat(tests): add api e2e tests * lockfile * mobile * try linux fix [skip ci] * ios fix * fix test on windows * improve cache * fix pnpm audit [skip ci]
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { expect } from '@wdio/globals'
|
||||
import { tauri, describePlugin, isMobile } from '../helpers/index.js'
|
||||
|
||||
// The example registers the plugin with a `Webview` target, so records logged
|
||||
// from the page (and from Rust) are forwarded back to `attachLogger`.
|
||||
//
|
||||
// The plugin's default format differs per platform: `[date][time][target][level]
|
||||
// message` on desktop, and just `[target] message` on mobile, where the platform
|
||||
// logger (logcat / os_log) already stamps the time and level.
|
||||
|
||||
interface Record {
|
||||
level: number
|
||||
message: string
|
||||
}
|
||||
|
||||
type Level = 'error' | 'warn' | 'info' | 'debug' | 'trace'
|
||||
|
||||
/** Logs `message` at `level` and resolves with the records `attachLogger` saw. */
|
||||
function logAndCollect(level: Level, message: string) {
|
||||
return tauri(
|
||||
(api, level, message) =>
|
||||
new Promise<Record[]>((resolve, reject) => {
|
||||
const records: Record[] = []
|
||||
api.log
|
||||
.attachLogger((record) => {
|
||||
if (record.message.includes(message)) {
|
||||
records.push(record)
|
||||
}
|
||||
})
|
||||
.then(async (detach) => {
|
||||
// eslint-disable-next-line security/detect-object-injection
|
||||
await api.log[level](message)
|
||||
setTimeout(() => {
|
||||
detach()
|
||||
resolve(records)
|
||||
}, 1000)
|
||||
})
|
||||
.catch(reject)
|
||||
}),
|
||||
level,
|
||||
message
|
||||
)
|
||||
}
|
||||
|
||||
describePlugin('log', () => {
|
||||
it('attachLogger receives records logged from the webview', async () => {
|
||||
const records = await logAndCollect('info', 'info record from e2e')
|
||||
expect(records).toHaveLength(1)
|
||||
expect(records[0].level).toBe(3) // LogLevel.Info
|
||||
expect(records[0].message).toMatch(
|
||||
isMobile
|
||||
? /\[webview[^\]]*\] info record from e2e$/
|
||||
: /\[webview[^\]]*\]\[INFO\] info record from e2e$/
|
||||
)
|
||||
})
|
||||
|
||||
it('records carry the level they were logged at', async () => {
|
||||
const error = await logAndCollect('error', 'error record from e2e')
|
||||
const warn = await logAndCollect('warn', 'warn record from e2e')
|
||||
expect(error[0].level).toBe(5) // LogLevel.Error
|
||||
expect(warn[0].level).toBe(4) // LogLevel.Warn
|
||||
if (!isMobile) {
|
||||
// the level is only part of the formatted message on desktop
|
||||
expect(error[0].message).toContain('[ERROR]')
|
||||
expect(warn[0].message).toContain('[WARN]')
|
||||
}
|
||||
})
|
||||
|
||||
it('records below the configured level are dropped', async () => {
|
||||
// the example sets the level filter to Info
|
||||
const debug = await logAndCollect('debug', 'debug record from e2e')
|
||||
const trace = await logAndCollect('trace', 'trace record from e2e')
|
||||
expect(debug).toHaveLength(0)
|
||||
expect(trace).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('log options are accepted', async () => {
|
||||
const records = await tauri(
|
||||
(api, needle) =>
|
||||
new Promise<Record[]>((resolve, reject) => {
|
||||
const records: Record[] = []
|
||||
api.log
|
||||
.attachLogger((record) => {
|
||||
if (record.message.includes(needle)) records.push(record)
|
||||
})
|
||||
.then(async (detach) => {
|
||||
await api.log.info(needle, {
|
||||
file: 'e2e.spec.ts',
|
||||
line: 42,
|
||||
keyValues: { suite: 'plugins-e2e' }
|
||||
})
|
||||
setTimeout(() => {
|
||||
detach()
|
||||
resolve(records)
|
||||
}, 1000)
|
||||
})
|
||||
.catch(reject)
|
||||
}),
|
||||
'record with options from e2e'
|
||||
)
|
||||
expect(records).toHaveLength(1)
|
||||
expect(records[0].level).toBe(3)
|
||||
})
|
||||
|
||||
it('detaching the logger stops delivery', async () => {
|
||||
const count = await tauri(
|
||||
(api, needle) =>
|
||||
new Promise<number>((resolve, reject) => {
|
||||
let count = 0
|
||||
api.log
|
||||
.attachLogger((record) => {
|
||||
if (record.message.includes(needle)) count++
|
||||
})
|
||||
.then(async (detach) => {
|
||||
await api.log.info(needle)
|
||||
await new Promise((r) => setTimeout(r, 500))
|
||||
detach()
|
||||
await api.log.info(needle)
|
||||
await new Promise((r) => setTimeout(r, 1000))
|
||||
resolve(count)
|
||||
})
|
||||
.catch(reject)
|
||||
}),
|
||||
'detached record from e2e'
|
||||
)
|
||||
expect(count).toBe(1)
|
||||
})
|
||||
|
||||
it('attachConsole forwards records to the console', async () => {
|
||||
const forwarded = await tauri(
|
||||
(api, needle) =>
|
||||
new Promise<string[]>((resolve, reject) => {
|
||||
const seen: string[] = []
|
||||
// Info records are forwarded to `console.info`
|
||||
const original = console.info
|
||||
console.info = (...args: unknown[]) => {
|
||||
const text = args.map(String).join(' ')
|
||||
if (text.includes(needle)) seen.push(text)
|
||||
original.apply(console, args)
|
||||
}
|
||||
api.log
|
||||
.attachConsole()
|
||||
.then(async (detach) => {
|
||||
await api.log.info(needle)
|
||||
setTimeout(() => {
|
||||
detach()
|
||||
console.info = original
|
||||
resolve(seen)
|
||||
}, 1000)
|
||||
})
|
||||
.catch(reject)
|
||||
}),
|
||||
'console record from e2e'
|
||||
)
|
||||
expect(forwarded.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('records logged from Rust are forwarded to the webview too', async () => {
|
||||
// the example's `log_operation` command logs its arguments at Info
|
||||
const message = await tauri(
|
||||
(api, needle) =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
api.log
|
||||
.attachLogger((record) => {
|
||||
if (record.message.includes(needle)) resolve(record.message)
|
||||
})
|
||||
.then(() =>
|
||||
api.core.invoke('log_operation', {
|
||||
event: 'tauri-click',
|
||||
payload: needle
|
||||
})
|
||||
)
|
||||
.catch(reject)
|
||||
setTimeout(() => reject(new Error('record not received')), 5000)
|
||||
}),
|
||||
'rust log from e2e'
|
||||
)
|
||||
expect(message).toContain(
|
||||
isMobile ? '[api_lib::cmd] tauri-click' : '[INFO] tauri-click'
|
||||
)
|
||||
expect(message).toContain('rust log from e2e')
|
||||
expect(message).not.toContain('[webview')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user