Bun tests #24
20 changed files with 1518 additions and 415 deletions
128
.config/vite-utils/fixup-bun-test.ts
Normal file
128
.config/vite-utils/fixup-bun-test.ts
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
const bunTest = require('bun:test')
|
||||||
|
const console = require('console') // https://github.com/oven-sh/bun/issues/6044
|
||||||
|
const chaiExpect = require('chai').expect
|
||||||
|
const bunExpect = bunTest.expect
|
||||||
|
|
||||||
|
class BunTestUnsupportedError extends Error {
|
||||||
|
constructor(readonly feature) {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _wrapBunExpect(args, bun, invert = false) {
|
||||||
|
let chai = chaiExpect(...args)
|
||||||
|
if (invert) chai = chai.not
|
||||||
|
|
||||||
|
return new Proxy(bun, {
|
||||||
|
get: (target, prop, receiver) => {
|
||||||
|
if (prop === 'eq') return (...args) => chai.eq(...args)
|
||||||
|
if (prop === 'eql') return (...args) => chai.eql(...args)
|
||||||
|
if (prop === 'throws') return (...args) => chai.throws(...args)
|
||||||
|
if (prop === 'is') return chai.is
|
||||||
|
if (prop === 'to') return chai.to
|
||||||
|
if (prop === 'false') return chai.false
|
||||||
|
if (prop === 'true') return chai.true
|
||||||
|
if (prop === 'deep') return chai.deep
|
||||||
|
|
||||||
|
if (prop === 'toMatchInlineSnapshot') {
|
||||||
|
return (expected, options) => {
|
||||||
|
let snapshot
|
||||||
|
if (typeof args[0] === 'string') {
|
||||||
|
const snapshot = '"' + args[0] + '"'
|
||||||
|
return chaiExpect(snapshot).eql(expected.trim())
|
||||||
|
} else {
|
||||||
|
const obj = eval('(' + expected + ')') // idc lol
|
||||||
|
return chaiExpect(args[0]).eql(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop === 'not') {
|
||||||
|
const not = bun.not
|
||||||
|
return _wrapBunExpect(args, not, !invert)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop === 'rejects') {
|
||||||
|
if (typeof args[0] === 'function') {
|
||||||
|
const newArgs = [args[0](), ...args.slice(1)]
|
||||||
|
return _wrapBunExpect(newArgs, bunExpect(...newArgs), invert).rejects
|
||||||
|
}
|
||||||
|
|
||||||
|
return bun.rejects
|
||||||
|
}
|
||||||
|
if (prop === 'resolves') {
|
||||||
|
return bun.resolves
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop === 'toHaveBeenCalledOnce' || prop === 'toHaveBeenCalledTimes' || prop === 'toMatchSnapshot') {
|
||||||
|
throw new BunTestUnsupportedError(prop)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reflect.get(target, prop, receiver).bind(bun)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function expect(...args) {
|
||||||
|
return _wrapBunExpect(args, bunExpect(...args))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect.any = bunExpect.any
|
||||||
|
|
||||||
|
const stubbedGlobal = new Map()
|
||||||
|
function stubGlobal(name, value) {
|
||||||
|
stubbedGlobal.set(name, globalThis[name])
|
||||||
|
globalThis[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
function unstubAllGlobals() {
|
||||||
|
for (const [name, value] of stubbedGlobal) {
|
||||||
|
globalThis[name] = value
|
||||||
|
}
|
||||||
|
stubbedGlobal.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
const _wrapRunner = (name, fn) => {
|
||||||
|
const handleError = (err) => {
|
||||||
|
if (err instanceof BunTestUnsupportedError) {
|
||||||
|
console.warn(`skipping "${name}" - ${err.feature} is currently not supported in bun:test`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
return (...args) => {
|
||||||
|
try {
|
||||||
|
const res = fn(...args)
|
||||||
|
if (res instanceof Promise) {
|
||||||
|
return res.catch(handleError)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
} catch (e) {
|
||||||
|
return handleError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const it = (name, fn) => bunTest.it(name, _wrapRunner(name, fn))
|
||||||
|
it.only = (name, fn) => bunTest.it.only(name, _wrapRunner(name, fn))
|
||||||
|
it.skip = (name, fn) => bunTest.it.skip(name, _wrapRunner(name, fn))
|
||||||
|
it.each = (table) => (name, fn) => bunTest.it.each(table)(name, _wrapRunner(name, fn))
|
||||||
|
|
||||||
|
export { it }
|
||||||
|
|
||||||
|
export const vi = {
|
||||||
|
...bunTest.jest,
|
||||||
|
...bunTest.vi,
|
||||||
|
mocked: (fn) => fn,
|
||||||
|
stubGlobal,
|
||||||
|
unstubAllGlobals,
|
||||||
|
...['setSystemTime', 'advanceTimersByTimeAsync', 'advanceTimersByTime', 'waitFor', 'doMock'].reduce(
|
||||||
|
(acc, name) => ({
|
||||||
|
...acc,
|
||||||
|
[name]: () => {
|
||||||
|
throw new BunTestUnsupportedError(name)
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
),
|
||||||
|
}
|
26
.config/vite-utils/fixup-cjs.ts
Normal file
26
.config/vite-utils/fixup-cjs.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Plugin } from 'vite'
|
||||||
|
import * as cjsLexer from 'cjs-module-lexer'
|
||||||
|
import esbuild from 'esbuild'
|
||||||
|
|
||||||
|
await cjsLexer.init()
|
||||||
|
|
||||||
|
export function fixupCjs(): Plugin {
|
||||||
|
return {
|
||||||
|
name: 'fixup-cjs',
|
||||||
|
async transform(code, id) {
|
||||||
|
if (!id.match(/\/packages\/tl\/.*\.js$/)) return code
|
||||||
|
|
||||||
|
const lexed = cjsLexer.parse(code)
|
||||||
|
const r = await esbuild.transform(code, { format: 'esm' })
|
||||||
|
code = r.code.replace(/export default require_stdin\(\);/, '')
|
||||||
|
|
||||||
|
code += 'const __exp = require_stdin()\n'
|
||||||
|
|
||||||
|
for (const exp of lexed.exports) {
|
||||||
|
code += `export const ${exp} = __exp.${exp}\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
return code
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
21
.config/vite-utils/test-setup-plugin.ts
Normal file
21
.config/vite-utils/test-setup-plugin.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { Plugin } from 'vite'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
|
const setupFile = fileURLToPath(new URL('./test-setup.mts', import.meta.url))
|
||||||
|
|
||||||
|
export function testSetup(params?: { additionalCode?: string }): Plugin {
|
||||||
|
const { additionalCode = '' } = params || {}
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'test-setup',
|
||||||
|
async transform(code, id) {
|
||||||
|
if (!id.match(/\.test\.m?[tj]s/)) return
|
||||||
|
|
||||||
|
return {
|
||||||
|
code: `import '${setupFile}'\n` + additionalCode + code,
|
||||||
|
map: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
apply: 'build',
|
||||||
|
}
|
||||||
|
}
|
9
.config/vite-utils/test-setup.mts
Normal file
9
.config/vite-utils/test-setup.mts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { setPlatform } from '../../packages/core/src/platform.js'
|
||||||
|
|
||||||
|
// @ts-expect-error no .env here
|
||||||
|
const TEST_ENV = import.meta.env.TEST_ENV
|
||||||
|
if (TEST_ENV === 'browser') {
|
||||||
|
setPlatform(new (await import('../../packages/web/src/platform.js')).WebPlatform())
|
||||||
|
} else {
|
||||||
|
setPlatform(new (await import('../../packages/node/src/platform.js')).NodePlatform())
|
||||||
|
}
|
|
@ -1,11 +1,9 @@
|
||||||
/// <reference types="vitest" />
|
/// <reference types="vitest" />
|
||||||
import { defineConfig, mergeConfig } from 'vite'
|
import { defineConfig, mergeConfig } from 'vite'
|
||||||
import * as cjsLexer from 'cjs-module-lexer'
|
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||||
import esbuild from 'esbuild'
|
|
||||||
|
|
||||||
import baseConfig from './vite.mjs'
|
import baseConfig from './vite.mjs'
|
||||||
|
import { fixupCjs } from './vite-utils/fixup-cjs'
|
||||||
await cjsLexer.init()
|
|
||||||
|
|
||||||
export default mergeConfig(baseConfig, defineConfig({
|
export default mergeConfig(baseConfig, defineConfig({
|
||||||
test: {
|
test: {
|
||||||
|
@ -19,6 +17,8 @@ export default mergeConfig(baseConfig, defineConfig({
|
||||||
toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'Date']
|
toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'Date']
|
||||||
},
|
},
|
||||||
retry: process.env.CI ? 3 : 0,
|
retry: process.env.CI ? 3 : 0,
|
||||||
|
isolate: false,
|
||||||
|
fileParallelism: false, // leads to ERR_INSUFFICIENT_RESOURCES
|
||||||
// for whatever reason using exclude-s makes the vite never start the browser, so we use skip-s instead.
|
// for whatever reason using exclude-s makes the vite never start the browser, so we use skip-s instead.
|
||||||
// exclude: [
|
// exclude: [
|
||||||
// './packages/crypto-node/**',
|
// './packages/crypto-node/**',
|
||||||
|
@ -26,24 +26,15 @@ export default mergeConfig(baseConfig, defineConfig({
|
||||||
// ],
|
// ],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
{
|
fixupCjs(),
|
||||||
name: 'fixup-cjs',
|
nodePolyfills({
|
||||||
async transform(code, id) {
|
include: ['stream', 'path', 'zlib', 'util'],
|
||||||
if (!id.match(/\/packages\/tl\/.*\.js$/)) return code
|
globals: {
|
||||||
|
Buffer: false,
|
||||||
const lexed = cjsLexer.parse(code)
|
global: false,
|
||||||
const r = await esbuild.transform(code, { format: 'esm' })
|
process: false,
|
||||||
code = r.code.replace(/export default require_stdin\(\);/, '')
|
},
|
||||||
|
})
|
||||||
code += 'const __exp = require_stdin()\n'
|
|
||||||
|
|
||||||
for (const exp of lexed.exports) {
|
|
||||||
code += `export const ${exp} = __exp.${exp}\n`
|
|
||||||
}
|
|
||||||
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
],
|
||||||
define: {
|
define: {
|
||||||
'import.meta.env.TEST_ENV': '"browser"'
|
'import.meta.env.TEST_ENV': '"browser"'
|
||||||
|
|
|
@ -1,10 +1,126 @@
|
||||||
/// <reference types="vitest" />
|
import { defineConfig } from 'vite'
|
||||||
import { defineConfig, mergeConfig } from 'vite'
|
import { globSync } from 'glob'
|
||||||
|
import { resolve, join } from 'path'
|
||||||
|
import * as fs from 'fs'
|
||||||
|
import { fixupCjs } from './vite-utils/fixup-cjs'
|
||||||
|
import { testSetup } from './vite-utils/test-setup-plugin'
|
||||||
|
|
||||||
import baseConfig from './vite.mjs'
|
const SKIP_PACKAGES = ['create-bot', 'crypto-node']
|
||||||
|
|
||||||
export default mergeConfig(baseConfig, defineConfig({
|
// https://github.com/oven-sh/bun/issues/4145 prevents us from using vitest directly
|
||||||
define: {
|
// so we have to use bun's native test runner
|
||||||
'import.meta.env.TEST_ENV': '"bun"'
|
const FIXUP_TEST = resolve(__dirname, 'vite-utils/fixup-bun-test.ts')
|
||||||
|
|
||||||
|
|
||||||
|
// bun:test doesn't support certain features of vitest, so we'll skip them for now
|
||||||
|
// https://github.com/oven-sh/bun/issues/1825
|
||||||
|
const SKIP_TESTS = [
|
||||||
|
// uses timers
|
||||||
|
'core/src/network/config-manager.test.ts',
|
||||||
|
// incompatible spies
|
||||||
|
'core/src/utils/crypto/mtproto.test.ts',
|
||||||
|
// snapshot format
|
||||||
|
'tl-utils/src/codegen/errors.test.ts'
|
||||||
|
].map(path => resolve(__dirname, '../packages', path))
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
entry: (() => {
|
||||||
|
const files: string[] = []
|
||||||
|
|
||||||
|
const packages = resolve(__dirname, '../packages')
|
||||||
|
|
||||||
|
for (const dir of fs.readdirSync(packages)) {
|
||||||
|
if (dir.startsWith('.') || SKIP_PACKAGES.includes(dir)) continue
|
||||||
|
if (!fs.statSync(resolve(packages, dir)).isDirectory()) continue
|
||||||
|
|
||||||
|
const fullDir = resolve(packages, dir)
|
||||||
|
|
||||||
|
for (const file of globSync(join(fullDir, '**/*.test.ts'))) {
|
||||||
|
if (SKIP_TESTS.includes(file)) continue
|
||||||
|
files.push(file)
|
||||||
}
|
}
|
||||||
}))
|
}
|
||||||
|
|
||||||
|
return files
|
||||||
|
})(),
|
||||||
|
formats: ['es'],
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
'zlib',
|
||||||
|
'vitest',
|
||||||
|
'stream',
|
||||||
|
'net',
|
||||||
|
'crypto',
|
||||||
|
'module',
|
||||||
|
'fs',
|
||||||
|
'fs/promises',
|
||||||
|
'events',
|
||||||
|
'path',
|
||||||
|
'util',
|
||||||
|
'os',
|
||||||
|
'bun:test',
|
||||||
|
],
|
||||||
|
output: {
|
||||||
|
chunkFileNames: 'chunk-[hash].js',
|
||||||
|
entryFileNames: '[name]-[hash].test.js',
|
||||||
|
minifyInternalExports: false,
|
||||||
|
},
|
||||||
|
treeshake: false,
|
||||||
|
},
|
||||||
|
commonjsOptions: {
|
||||||
|
ignoreDynamicRequires: true,
|
||||||
|
},
|
||||||
|
outDir: 'dist/tests',
|
||||||
|
emptyOutDir: true,
|
||||||
|
target: 'esnext',
|
||||||
|
minify: false,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fixupCjs(),
|
||||||
|
{
|
||||||
|
name: 'fix-vitest',
|
||||||
|
transform(code) {
|
||||||
|
if (!code.includes('vitest')) return code
|
||||||
|
code = code.replace(/^import {(.+?)} from ['"]vitest['"]/gms, (_, names) => {
|
||||||
|
const namesParsed = names.split(',').map((name) => name.trim())
|
||||||
|
|
||||||
|
const namesFromFixup: string[] = []
|
||||||
|
const newNames = namesParsed
|
||||||
|
.map((name) => {
|
||||||
|
if (['expect', 'vi', 'it'].includes(name)) {
|
||||||
|
namesFromFixup.push(name)
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
|
||||||
|
let code = `import {${newNames.join(', ')}} from 'bun:test'`
|
||||||
|
|
||||||
|
if (namesFromFixup.length) {
|
||||||
|
code += `\nimport { ${namesFromFixup.join(', ')} } from '${FIXUP_TEST}'`
|
||||||
|
}
|
||||||
|
return code
|
||||||
|
})
|
||||||
|
return code
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'fix-wasm-load',
|
||||||
|
async transform(code, id) {
|
||||||
|
if (code.includes('@mtcute/wasm/mtcute.wasm')) {
|
||||||
|
return code.replace('@mtcute/wasm/mtcute.wasm', resolve(__dirname, '../packages/wasm/mtcute.wasm'))
|
||||||
|
}
|
||||||
|
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
},
|
||||||
|
testSetup(),
|
||||||
|
],
|
||||||
|
define: {
|
||||||
|
'import.meta.env.TEST_ENV': '"bun"',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
|
@ -11,8 +11,16 @@ export default defineConfig({
|
||||||
'packages/**/*.test-d.ts',
|
'packages/**/*.test-d.ts',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
coverage: {
|
||||||
|
include: [
|
||||||
|
'packages/**/*.ts',
|
||||||
|
],
|
||||||
|
exclude: [
|
||||||
|
'packages/**/index.ts',
|
||||||
|
]
|
||||||
|
},
|
||||||
setupFiles: [
|
setupFiles: [
|
||||||
'./.config/vitest.setup.mts'
|
'./.config/vite-utils/test-setup.mts'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
define: {
|
define: {
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { setPlatform } from '../packages/core/src/platform.js'
|
|
||||||
|
|
||||||
// @ts-expect-error no .env here
|
|
||||||
const TEST_ENV = import.meta.env.TEST_ENV
|
|
||||||
if (TEST_ENV === 'browser') {
|
|
||||||
setPlatform(new (await import('../packages/web/src/platform.js')).WebPlatform())
|
|
||||||
} else {
|
|
||||||
setPlatform(new (await import('../packages/node/src/platform.js')).NodePlatform())
|
|
||||||
}
|
|
6
.github/workflows/test.yaml
vendored
6
.github/workflows/test.yaml
vendored
|
@ -43,14 +43,18 @@ jobs:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
with:
|
with:
|
||||||
files: ./coverage/coverage-final.json
|
files: ./coverage/coverage-final.json
|
||||||
|
|
||||||
test-bun:
|
test-bun:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: lint
|
needs: lint
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: ./.github/actions/init
|
||||||
- uses: ./.github/actions/init-bun
|
- uses: ./.github/actions/init-bun
|
||||||
|
- name: 'Build tests'
|
||||||
|
run: pnpm exec vite build -c .config/vite.bun.mts
|
||||||
- name: 'Run tests'
|
- name: 'Run tests'
|
||||||
run: bun run test:ci
|
run: cd dist/tests && bun test
|
||||||
|
|
||||||
test-web:
|
test-web:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
16
package.json
16
package.json
|
@ -36,13 +36,13 @@
|
||||||
"@commitlint/cli": "17.6.5",
|
"@commitlint/cli": "17.6.5",
|
||||||
"@commitlint/config-conventional": "17.6.5",
|
"@commitlint/config-conventional": "17.6.5",
|
||||||
"@types/node": "20.10.0",
|
"@types/node": "20.10.0",
|
||||||
"@types/node-forge": "1.3.2",
|
|
||||||
"@types/ws": "8.5.4",
|
"@types/ws": "8.5.4",
|
||||||
"@typescript-eslint/eslint-plugin": "6.4.0",
|
"@typescript-eslint/eslint-plugin": "6.4.0",
|
||||||
"@typescript-eslint/parser": "6.4.0",
|
"@typescript-eslint/parser": "6.4.0",
|
||||||
"@vitest/browser": "0.34.6",
|
"@vitest/browser": "1.4.0",
|
||||||
"@vitest/coverage-v8": "0.34.6",
|
"@vitest/coverage-v8": "1.4.0",
|
||||||
"@vitest/ui": "0.34.6",
|
"@vitest/ui": "1.4.0",
|
||||||
|
"chai": "^5.1.0",
|
||||||
"cjs-module-lexer": "1.2.3",
|
"cjs-module-lexer": "1.2.3",
|
||||||
"dotenv-flow": "3.2.0",
|
"dotenv-flow": "3.2.0",
|
||||||
"dpdm": "3.14.0",
|
"dpdm": "3.14.0",
|
||||||
|
@ -56,8 +56,7 @@
|
||||||
"glob": "10.2.6",
|
"glob": "10.2.6",
|
||||||
"husky": "8.0.3",
|
"husky": "8.0.3",
|
||||||
"lint-staged": "13.2.2",
|
"lint-staged": "13.2.2",
|
||||||
"node-forge": "1.3.1",
|
"playwright": "^1.42.1",
|
||||||
"playwright": "^1.40.1",
|
|
||||||
"prettier": "3.0.3",
|
"prettier": "3.0.3",
|
||||||
"rimraf": "5.0.1",
|
"rimraf": "5.0.1",
|
||||||
"semver": "7.5.1",
|
"semver": "7.5.1",
|
||||||
|
@ -65,8 +64,9 @@
|
||||||
"tsconfig-paths": "4.2.0",
|
"tsconfig-paths": "4.2.0",
|
||||||
"typedoc": "0.25.3",
|
"typedoc": "0.25.3",
|
||||||
"typescript": "5.1.6",
|
"typescript": "5.1.6",
|
||||||
"vite": "5.0.3",
|
"vite": "5.1.6",
|
||||||
"vitest": "0.34.6"
|
"vite-plugin-node-polyfills": "0.21.0",
|
||||||
|
"vitest": "1.4.0"
|
||||||
},
|
},
|
||||||
"prettier": "./.config/prettier.cjs",
|
"prettier": "./.config/prettier.cjs",
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
|
|
@ -15,15 +15,11 @@ describe('isProbablyPlainText', () => {
|
||||||
it('should return true for buffers only containing printable ascii', () => {
|
it('should return true for buffers only containing printable ascii', () => {
|
||||||
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text'))).to.be.true
|
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text'))).to.be.true
|
||||||
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\nwith unix new lines'))).to.be.true
|
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\nwith unix new lines'))).to.be.true
|
||||||
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\r\nwith windows new lines'))).to.be
|
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\r\nwith windows new lines'))).to.be.true
|
||||||
|
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\n\twith unix new lines and tabs'))).to.be
|
||||||
.true
|
.true
|
||||||
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\n\twith unix new lines and tabs')))
|
expect(isProbablyPlainText(p.utf8Encode('hello this is some ascii text\r\n\twith windows new lines and tabs')))
|
||||||
.to.be.true
|
.to.be.true
|
||||||
expect(
|
|
||||||
isProbablyPlainText(
|
|
||||||
p.utf8Encode('hello this is some ascii text\r\n\twith windows new lines and tabs'),
|
|
||||||
),
|
|
||||||
).to.be.true
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return false for buffers containing some binary data', () => {
|
it('should return false for buffers containing some binary data', () => {
|
||||||
|
@ -55,7 +51,7 @@ describe('svgPathToFile', () => {
|
||||||
const path = 'M 0 0 L 100 0 L 100 100 L 0 100 L 0 0 Z'
|
const path = 'M 0 0 L 100 0 L 100 100 L 0 100 L 0 0 Z'
|
||||||
|
|
||||||
expect(p.utf8Decode(svgPathToFile(path))).toMatchInlineSnapshot(
|
expect(p.utf8Decode(svgPathToFile(path))).toMatchInlineSnapshot(
|
||||||
'"<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?><svg version=\\"1.1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlns:xlink=\\"http://www.w3.org/1999/xlink\\"viewBox=\\"0 0 512 512\\" xml:space=\\"preserve\\"><path d=\\"M 0 0 L 100 0 L 100 100 L 0 100 L 0 0 Z\\"/></svg>"',
|
'"<?xml version="1.0" encoding="utf-8"?><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"viewBox="0 0 512 512" xml:space="preserve"><path d="M 0 0 L 100 0 L 100 100 L 0 100 L 0 0 Z"/></svg>"',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { TransportState } from '@mtcute/core'
|
||||||
import { getPlatform } from '@mtcute/core/platform.js'
|
import { getPlatform } from '@mtcute/core/platform.js'
|
||||||
import { defaultProductionDc, LogManager } from '@mtcute/core/utils.js'
|
import { defaultProductionDc, LogManager } from '@mtcute/core/utils.js'
|
||||||
|
|
||||||
if (import.meta.env.TEST_ENV === 'node' || import.meta.env.TEST_ENV === 'bun') {
|
if (import.meta.env.TEST_ENV === 'node') {
|
||||||
vi.doMock('net', () => ({
|
vi.doMock('net', () => ({
|
||||||
connect: vi.fn().mockImplementation((port: number, ip: string, cb: () => void) => {
|
connect: vi.fn().mockImplementation((port: number, ip: string, cb: () => void) => {
|
||||||
cb()
|
cb()
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {
|
||||||
testRefMessagesRepository,
|
testRefMessagesRepository,
|
||||||
} from '@mtcute/test'
|
} from '@mtcute/test'
|
||||||
|
|
||||||
import { SqliteStorage } from '../src/index.js'
|
if (import.meta.env.TEST_ENV === 'node') {
|
||||||
|
const { SqliteStorage } = await import('../src/index.js')
|
||||||
|
|
||||||
if (import.meta.env.TEST_ENV === 'node' || import.meta.env.TEST_ENV === 'bun') {
|
|
||||||
describe('SqliteStorage', () => {
|
describe('SqliteStorage', () => {
|
||||||
const storage = new SqliteStorage(':memory:')
|
const storage = new SqliteStorage(':memory:')
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "pnpm run -w build-package test"
|
"build": "pnpm run -w build-package test"
|
||||||
},
|
},
|
||||||
|
@ -21,7 +22,7 @@
|
||||||
"@mtcute/node": "workspace:^",
|
"@mtcute/node": "workspace:^",
|
||||||
"@mtcute/web": "workspace:^",
|
"@mtcute/web": "workspace:^",
|
||||||
"@mtcute/tl": "workspace:*",
|
"@mtcute/tl": "workspace:*",
|
||||||
"vitest": "^0.34.6"
|
"vitest": "1.4.0"
|
||||||
},
|
},
|
||||||
"peerDependenciesMeta": {
|
"peerDependenciesMeta": {
|
||||||
"@mtcute/node": {
|
"@mtcute/node": {
|
||||||
|
|
|
@ -2,10 +2,7 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vite
|
||||||
import { gzipSync, inflateSync } from 'zlib'
|
import { gzipSync, inflateSync } from 'zlib'
|
||||||
|
|
||||||
import { getPlatform } from '@mtcute/core/platform.js'
|
import { getPlatform } from '@mtcute/core/platform.js'
|
||||||
import {
|
import { dataViewFromBuffer, ICryptoProvider } from '@mtcute/core/utils.js'
|
||||||
dataViewFromBuffer,
|
|
||||||
ICryptoProvider,
|
|
||||||
} from '@mtcute/core/utils.js'
|
|
||||||
|
|
||||||
import { defaultCryptoProvider } from './platform.js'
|
import { defaultCryptoProvider } from './platform.js'
|
||||||
|
|
||||||
|
@ -42,9 +39,14 @@ export function withFakeRandom(provider: ICryptoProvider, source = DEFAULT_ENTRO
|
||||||
offset += buf.length
|
offset += buf.length
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.randomFill = getRandomValues
|
return new Proxy<ICryptoProvider>(provider, {
|
||||||
|
get(target, prop, receiver) {
|
||||||
|
if (prop === 'randomFill') return getRandomValues
|
||||||
|
|
||||||
return provider
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
||||||
|
return Reflect.get(target, prop, receiver)
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useFakeMathRandom(source = DEFAULT_ENTROPY): void {
|
export function useFakeMathRandom(source = DEFAULT_ENTROPY): void {
|
||||||
|
@ -176,14 +178,10 @@ export function testCryptoProvider(c: ICryptoProvider): void {
|
||||||
p.hexDecode('6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353'),
|
p.hexDecode('6D656E746174696F6E206F6620494745206D6F646520666F72204F70656E5353'),
|
||||||
)
|
)
|
||||||
expect(
|
expect(
|
||||||
p.hexEncode(
|
p.hexEncode(aes.encrypt(p.hexDecode('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b'))),
|
||||||
aes.encrypt(p.hexDecode('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')),
|
|
||||||
),
|
|
||||||
).to.eq('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')
|
).to.eq('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')
|
||||||
expect(
|
expect(
|
||||||
p.hexEncode(
|
p.hexEncode(aes.decrypt(p.hexDecode('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69'))),
|
||||||
aes.decrypt(p.hexDecode('792ea8ae577b1a66cb3bd92679b8030ca54ee631976bd3a04547fdcb4639fa69')),
|
|
||||||
),
|
|
||||||
).to.eq('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')
|
).to.eq('99706487a1cde613bc6de0b6f24b1c7aa448c8b9c3403e3467a8cad89340f53b')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ export class RpcError extends Error {
|
||||||
static fromTl(obj: object): RpcError;
|
static fromTl(obj: object): RpcError;
|
||||||
}
|
}
|
||||||
",
|
",
|
||||||
"const _descriptionsMap = JSON.parse('{\\"FLOOD_WAIT_%d\\":\\"Wait %d seconds\\"}')
|
"const _descriptionsMap = JSON.parse('{"FLOOD_WAIT_%d":"Wait %d seconds"}')
|
||||||
class RpcError extends Error {
|
class RpcError extends Error {
|
||||||
constructor(code, text, description) {
|
constructor(code, text, description) {
|
||||||
super(description || 'Unknown RPC error: [' + code + ':' + text + ']');
|
super(description || 'Unknown RPC error: [' + code + ':' + text + ']');
|
||||||
|
@ -50,7 +50,7 @@ RpcError.fromTl = function (obj) {
|
||||||
|
|
||||||
var err = new RpcError(obj.errorCode, obj.errorMessage);
|
var err = new RpcError(obj.errorCode, obj.errorMessage);
|
||||||
var match, param;
|
var match, param;
|
||||||
if ((match=err.text.match(/^FLOOD_WAIT_(\\\\d+)$/))!=null){ err.text = 'FLOOD_WAIT_%d'; param = err.duration = parseInt(match[1]) }
|
if ((match=err.text.match(/^FLOOD_WAIT_(\\d+)$/))!=null){ err.text = 'FLOOD_WAIT_%d'; param = err.duration = parseInt(match[1]) }
|
||||||
|
|
||||||
else return err
|
else return err
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ type TlObject =
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with methods 2`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with methods 2`] = `
|
||||||
"ns.isAnyTest = _isAny('Test');
|
"ns.isAnyTest = _isAny('Test');
|
||||||
_types = JSON.parse('{\\"test\\":\\"Test\\"}');"
|
_types = JSON.parse('{"test":"Test"}');"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with multi-unions 1`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with multi-unions 1`] = `
|
||||||
|
@ -210,7 +210,7 @@ type TlObject =
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with multi-unions 2`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with multi-unions 2`] = `
|
||||||
"ns.isAnyTest = _isAny('Test');
|
"ns.isAnyTest = _isAny('Test');
|
||||||
_types = JSON.parse('{\\"test\\":\\"Test\\",\\"test2\\":\\"Test\\"}');"
|
_types = JSON.parse('{"test":"Test","test2":"Test"}');"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with namespaces 1`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes schemas with namespaces 1`] = `
|
||||||
|
@ -270,7 +270,7 @@ ns.test = {};
|
||||||
(function(ns){
|
(function(ns){
|
||||||
ns.isAnyTest = _isAny('test.Test');
|
ns.isAnyTest = _isAny('test.Test');
|
||||||
})(ns.test);
|
})(ns.test);
|
||||||
_types = JSON.parse('{\\"test\\":\\"Test\\",\\"test2\\":\\"Test\\",\\"test.test\\":\\"test.Test\\",\\"test.test2\\":\\"test.Test\\"}');"
|
_types = JSON.parse('{"test":"Test","test2":"Test","test.test":"test.Test","test.test2":"test.Test"}');"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes simple schemas 1`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes simple schemas 1`] = `
|
||||||
|
@ -288,5 +288,5 @@ type TlObject =
|
||||||
|
|
||||||
exports[`generateTypescriptDefinitionsForTlSchema > writes simple schemas 2`] = `
|
exports[`generateTypescriptDefinitionsForTlSchema > writes simple schemas 2`] = `
|
||||||
"ns.isAnyTest = _isAny('Test');
|
"ns.isAnyTest = _isAny('Test');
|
||||||
_types = JSON.parse('{\\"test\\":\\"Test\\"}');"
|
_types = JSON.parse('{"test":"Test"}');"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { initSync } from '../src/index.js'
|
||||||
export async function initWasm() {
|
export async function initWasm() {
|
||||||
const url = new URL('../mtcute.wasm', import.meta.url)
|
const url = new URL('../mtcute.wasm', import.meta.url)
|
||||||
|
|
||||||
if (import.meta.env.TEST_ENV === 'node' || import.meta.env.TEST_ENV === 'bun') {
|
if (import.meta.env.TEST_ENV === 'node') {
|
||||||
const fs = await import('fs/promises')
|
const fs = await import('fs/promises')
|
||||||
const blob = await fs.readFile(url)
|
const blob = await fs.readFile(url)
|
||||||
initSync(blob)
|
initSync(blob)
|
||||||
|
|
1484
pnpm-lock.yaml
1484
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@ import { fileURLToPath } from 'url'
|
||||||
import { getPackageJsons } from './utils.mjs'
|
import { getPackageJsons } from './utils.mjs'
|
||||||
|
|
||||||
export async function validateDepsVersions() {
|
export async function validateDepsVersions() {
|
||||||
const packageJsons = await getPackageJsons()
|
const packageJsons = await getPackageJsons(true)
|
||||||
|
|
||||||
const versions = {}
|
const versions = {}
|
||||||
const errors = []
|
const errors = []
|
||||||
|
|
Loading…
Reference in a new issue