57 lines
3.1 KiB
JavaScript
57 lines
3.1 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
import { createRequire } from 'node:module';
|
|
import { test } from 'node:test';
|
|
import React from 'react';
|
|
import { act, create } from 'react-test-renderer';
|
|
import ts from 'typescript';
|
|
import * as chatModel from '../src/lib/chat.ts';
|
|
|
|
globalThis.IS_REACT_ACT_ENVIRONMENT = true;
|
|
const require = createRequire(import.meta.url);
|
|
function harness() {
|
|
let resolvePicker;
|
|
const picker = new Promise(resolve => { resolvePicker = resolve; });
|
|
const drafts = [];
|
|
const chat = { detail: { name: 'Test', canSend: true }, messages: [], members: [], reactions: {}, loading: false };
|
|
const output = ts.transpileModule(readFileSync(new URL('../components/chat-conversation.tsx', import.meta.url), 'utf8'), {
|
|
compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX, target: ts.ScriptTarget.ES2022 },
|
|
}).outputText;
|
|
const exports = {};
|
|
new Function('require', 'exports', output)(name => {
|
|
if (name === 'react-native') return { ...Object.fromEntries(['ActivityIndicator', 'FlatList', 'Modal', 'Pressable', 'ScrollView', 'Text', 'TextInput', 'View'].map(key => [key, key])), StyleSheet: { create: value => value } };
|
|
if (name === '@expo/vector-icons') return { Ionicons: 'Icon' };
|
|
if (name === 'expo-image') return { Image: 'Image' };
|
|
if (name === 'expo-image-picker') return { launchImageLibraryAsync: () => picker };
|
|
if (name === '@/hooks/use-chat-conversation') return { useChatConversation: () => chat };
|
|
if (name === '@/src/lib/chat-api') return { chatApi: {} };
|
|
if (name === '@/src/lib/chat-image') return { prepareMobileChatImage: async () => ({ name: 'Bild.jpg', dataUrl: 'data:image/jpeg;base64,YQ==' }) };
|
|
if (name === '@/src/lib/chat') return chatModel;
|
|
return require(name);
|
|
}, exports);
|
|
const props = { token: 't', room: { key: 'test', name: 'Test' }, enabled: true,
|
|
draft: { text: 'Bild dazu', image: null, clientId: 'draft' }, onDraft: draft => drafts.push(draft) };
|
|
let root;
|
|
return {
|
|
drafts,
|
|
async render(enabled) { await act(async () => { const element = React.createElement(exports.ChatConversation, { ...props, enabled }); if (root) root.update(element); else root = create(element); }); },
|
|
async pick() { await act(async () => root.root.findByProps({ accessibilityLabel: 'Bild anhängen' }).props.onPress()); },
|
|
async finish() { await act(async () => resolvePicker({ canceled: false, assets: [{ uri: 'file:///test.jpg' }] })); },
|
|
async dispose() { await act(async () => root.unmount()); },
|
|
};
|
|
}
|
|
test('System-Fotoauswahl darf die App vorübergehend in den Hintergrund versetzen', async () => {
|
|
const h = harness();
|
|
try {
|
|
await h.render(true); await h.pick(); await h.render(false); await h.finish();
|
|
assert.equal(h.drafts.length, 1);
|
|
assert.equal(h.drafts[0].text, 'Bild dazu');
|
|
assert.equal(h.drafts[0].image.name, 'Bild.jpg');
|
|
} finally { await h.dispose(); }
|
|
});
|
|
test('Eine verspätete Fotoauswahl verändert nach Raumwechsel keinen anderen Entwurf', async () => {
|
|
const h = harness();
|
|
await h.render(true); await h.pick(); await h.dispose(); await h.finish();
|
|
assert.equal(h.drafts.length, 0);
|
|
});
|